diff --git a/.github/workflows/pull-request.yml b/.github/workflows/pull-request.yml index 46dd0299f..fe177bf35 100644 --- a/.github/workflows/pull-request.yml +++ b/.github/workflows/pull-request.yml @@ -6,6 +6,10 @@ name: Arduino-Pico CI on: pull_request: +env: + TRAVIS_BUILD_DIR: ${{ github.workspace }} + TRAVIS_TAG: ${{ github.ref }} + jobs: @@ -20,7 +24,7 @@ jobs: - name: Run codespell uses: codespell-project/actions-codespell@master with: - skip: ./ArduinoCore-API,./libraries/ESP8266SdFat,./libraries/Adafruit_TinyUSB_Arduino,./libraries/LittleFS/lib,./libraries/Ethernet,./tools/pyserial,./pico-sdk,./.github,./docs/i2s.rst,./cores/rp2040/api,./libraries/FreeRTOS,./tools/libbearssl/bearssl,./include,./libraries/WiFi/examples/BearSSL_Server,./ota/uzlib + skip: ./ArduinoCore-API,./libraries/ESP8266SdFat,./libraries/Adafruit_TinyUSB_Arduino,./libraries/LittleFS/lib,./libraries/Ethernet,./tools/pyserial,./pico-sdk,./.github,./docs/i2s.rst,./cores/rp2040/api,./libraries/FreeRTOS,./tools/libbearssl/bearssl,./include,./libraries/WiFi/examples/BearSSL_Server,./ota/uzlib,./libraries/http-parser/lib,./libraries/WebServer/examples/HelloServerBearSSL/HelloServerBearSSL.ino,./libraries/HTTPUpdateServer/examples/SecureBearSSLUpdater/SecureBearSSLUpdater.ino,./.git ignore_words_list: ser,dout # Consistent style @@ -46,10 +50,6 @@ jobs: ./tests/restyle.sh # If anything changed, GIT should return an error and fail the test git diff --exit-code -# - name: Check Arduino API copy is clean -# run: | -# git submodule update --init ./ArduinoCore-API -# diff -r ./cores/rp2040/api ./ArduinoCore-API/api # Build all examples on linux (core and Arduino IDE) build-linux: @@ -57,26 +57,24 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - chunk: [0, 1, 2, 3] + chunk: [0, 1, 2, 3, 4, 5] steps: - uses: actions/checkout@v3 with: submodules: true - - uses: actions/setup-python@v2 + - uses: actions/setup-python@v4 with: python-version: '3.x' - name: Cache Linux toolchain id: cache-linux - uses: actions/cache@v2 + uses: actions/cache@v3 with: path: ./tools/dist key: ${{ runner.os }}-${{ hashFiles('package/package_pico_index.template.json', 'tests/common.sh') }} - name: Build Sketches env: - TRAVIS_BUILD_DIR: ${{ github.workspace }} - TRAVIS_TAG: ${{ github.ref }} BUILD_PARITY: custom - mod: 4 + mod: 6 rem: ${{ matrix.chunk }} run: | cd pico-sdk @@ -92,19 +90,17 @@ jobs: - uses: actions/checkout@v3 with: submodules: true - - uses: actions/setup-python@v2 + - uses: actions/setup-python@v4 with: python-version: '3.x' - name: Cache Linux toolchain id: cache-linux - uses: actions/cache@v2 + uses: actions/cache@v3 with: path: ./tools/dist key: ${{ runner.os }}-${{ hashFiles('package/package_pico_index.template.json', 'tests/common.sh') }} - name: Build Sketches env: - TRAVIS_BUILD_DIR: ${{ github.workspace }} - TRAVIS_TAG: ${{ github.ref }} BUILD_PARITY: custom run: | cd pico-sdk @@ -120,19 +116,17 @@ jobs: - uses: actions/checkout@v3 with: submodules: true - - uses: actions/setup-python@v2 + - uses: actions/setup-python@v4 with: python-version: '3.x' - name: Cache Windows toolchain id: cache-windows - uses: actions/cache@v2 + uses: actions/cache@v3 with: path: ./tools/dist key: ${{ runner.os }}-${{ hashFiles('package/package_pico_index.template.json', 'tests/common.sh') }} - name: Build Sketch env: - TRAVIS_BUILD_DIR: ${{ github.workspace }} - TRAVIS_TAG: ${{ github.ref }} WINDOWS: 1 BUILD_PARITY: custom mod: 500 @@ -150,24 +144,22 @@ jobs: # Single build under macOS to ensure the Mac toolchain is good. build-mac: name: Mac - runs-on: macOS-latest + runs-on: macOS-12 steps: - uses: actions/checkout@v3 with: submodules: true - - uses: actions/setup-python@v2 + - uses: actions/setup-python@v4 with: python-version: '3.x' - name: Cache Mac toolchain id: cache-mac - uses: actions/cache@v2 + uses: actions/cache@v3 with: path: ./tools/dist key: ${{ runner.os }}-${{ hashFiles('package/package_pico_index.template.json', 'tests/common.sh') }} - name: Build Sketch env: - TRAVIS_BUILD_DIR: ${{ github.workspace }} - TRAVIS_TAG: ${{ github.ref }} MACOSX: 1 BUILD_PARITY: custom mod: 500 @@ -194,19 +186,21 @@ jobs: git submodule update --init cd ../.. - name: Cache pip - uses: actions/cache@v2 + uses: actions/cache@v3 with: path: ~/.cache/pip key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }} restore-keys: | ${{ runner.os }}-pip- - name: Cache PlatformIO - uses: actions/cache@v2 + uses: actions/cache@v3 with: path: ~/.platformio key: ${{ runner.os }}-${{ hashFiles('**/lockfiles') }} - name: Set up Python - uses: actions/setup-python@v2 + uses: actions/setup-python@v4 + with: + python-version: '3.x' - name: Install PlatformIO run: | python -m pip install --upgrade pip @@ -223,3 +217,5 @@ jobs: run: pio ci --board=rpipicow -O "platform_packages=framework-arduinopico@symlink:///home/runner/work/arduino-pico/arduino-pico" libraries/WiFi/examples/ScanNetworks/ScanNetworks.ino - name: Build Signed OTA Example run: pio ci --board=rpipicow -O "platform_packages=framework-arduinopico@symlink:///home/runner/work/arduino-pico/arduino-pico" libraries/ArduinoOTA/examples/SignedOTA/SignedOTA.ino + - name: Build Bluetooth Example + run: pio ci --board=rpipicow -O "platform_packages=framework-arduinopico@symlink:///home/runner/work/arduino-pico/arduino-pico" -O "build_flags=-DPIO_FRAMEWORK_ARDUINO_ENABLE_BLUETOOTH" libraries/MouseBLE/examples/BLECircle/BLECircle.ino diff --git a/.github/workflows/release-to-publish.yml b/.github/workflows/release-to-publish.yml index 68115f605..a5d342ce7 100644 --- a/.github/workflows/release-to-publish.yml +++ b/.github/workflows/release-to-publish.yml @@ -9,22 +9,22 @@ jobs: name: Update master JSON file runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 with: submodules: true - name: Cache pip - uses: actions/cache@v2 + uses: actions/cache@v3 with: path: ~/.cache/pip key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }} restore-keys: | ${{ runner.os }}-pip- - name: Cache PlatformIO - uses: actions/cache@v2 + uses: actions/cache@v3 with: path: ~/.platformio key: ${{ runner.os }}-${{ hashFiles('**/lockfiles') }} - - uses: actions/setup-python@v2 + - uses: actions/setup-python@v4 with: python-version: '3.x' - name: Install PlatformIO diff --git a/.github/workflows/tag-to-draft-release.yml b/.github/workflows/tag-to-draft-release.yml index a04cd6344..6e337e555 100644 --- a/.github/workflows/tag-to-draft-release.yml +++ b/.github/workflows/tag-to-draft-release.yml @@ -15,11 +15,11 @@ jobs: name: Package runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 with: submodules: true fetch-depth: 0 - - uses: actions/setup-python@v2 + - uses: actions/setup-python@v4 with: python-version: '3.x' - name: Build package JSON diff --git a/.gitignore b/.gitignore index bc0a2616e..99add2f70 100644 --- a/.gitignore +++ b/.gitignore @@ -3,4 +3,5 @@ system tools/dist docs/_build ota/build -tools/libpico/build \ No newline at end of file +tools/libpico/build +platform.local.txt diff --git a/.gitmodules b/.gitmodules index f739fa814..a13d196ac 100644 --- a/.gitmodules +++ b/.gitmodules @@ -3,7 +3,7 @@ url = https://github.com/earlephilhower/ArduinoCore-API.git [submodule "pico-sdk"] path = pico-sdk - url = https://github.com/earlephilhower/pico-sdk.git + url = https://github.com/raspberrypi/pico-sdk.git [submodule "system/pyserial"] path = tools/pyserial url = https://github.com/pyserial/pyserial.git @@ -14,14 +14,14 @@ path = libraries/ESP8266SdFat url = https://github.com/earlephilhower/ESP8266SdFat.git [submodule "libraries/Keyboard"] - path = libraries/Keyboard - url = https://github.com/earlephilhower/Keyboard + path = libraries/HID_Keyboard + url = https://github.com/earlephilhower/Keyboard.git [submodule "libraries/Mouse"] - path = libraries/Mouse - url = https://github.com/earlephilhower/Mouse + path = libraries/HID_Mouse + url = https://github.com/earlephilhower/Mouse.git [submodule "libraries/Joystick"] - path = libraries/Joystick - url = https://github.com/benjaminaigner/Joystick + path = libraries/HID_Joystick + url = https://github.com/earlephilhower/Joystick.git [submodule "libraries/Adafruit_TinyUSB_Arduino"] path = libraries/Adafruit_TinyUSB_Arduino url = https://github.com/adafruit/Adafruit_TinyUSB_Arduino.git @@ -41,3 +41,6 @@ [submodule "libraries/WizFi360_arduino_library"] path = libraries/WizFi360_arduino_library url = https://github.com/Wiznet/WizFi360_arduino_library.git +[submodule "libraries/http_parser/lib/http-parser"] + path = libraries/http-parser/lib/http-parser + url = https://github.com/nodejs/http-parser.git diff --git a/README.md b/README.md index 3c47f1ee1..9e46988b2 100644 --- a/README.md +++ b/README.md @@ -9,10 +9,15 @@ This is a port of the RP2040 (Raspberry Pi Pico processor) to the Arduino ecosys # Documentation See https://arduino-pico.readthedocs.io/en/latest/ along with the examples for more detailed usage information. +# Contributing +Read the [Contributing Guide](https://github.com/earlephilhower/arduino-pico/blob/master/docs/contrib.rst) for more information on submitting pull requests and porting libraries or sketches to this core. + # Supported Boards * Raspberry Pi Pico * Raspberry Pi Pico W +* 0xCB Helios * Adafruit Feather RP2040 +* Adafruit Feather RP2040 SCORPIO * Adafruit ItsyBitsy RP2040 * Adafruit KB2040 * Adafruit Macropad RP2040 @@ -20,11 +25,14 @@ See https://arduino-pico.readthedocs.io/en/latest/ along with the examples for m * Adafruit STEMMA Friend RP2040 * Adafruit Trinkey RP2040 QT * Arduino Nano RP2040 Connect +* BridgeTek IDM2040-7A * Cytron Maker Pi RP2040 * Cytron Maker Nano RP2040 +* DatanoiseTV PicoADK+ * DeRuiLab FlyBoard2040 Core * DFRobot Beetle RP2040 * ElectronicCats Hunter Cat NFC +* ExtremeElectronics RC2040 * Invector Labs Challenger RP2040 WiFi * Invector Labs Challenger RP2040 WiFi/BLE * Invector Labs Challenger NB RP2040 WiFi @@ -32,13 +40,26 @@ See https://arduino-pico.readthedocs.io/en/latest/ along with the examples for m * Invector Labs Challenger RP2040 LoRa * Invector Labs Challenger RP2040 SubGHz * Invector Labs Challenger RP2040 SD/RTC +* Invector Labs Challenger RP2040 UWB * Invector Labs RPICO32 +* Melopero Cookie RP2040 * Melopero Shake RP2040 +* Neko Systems BL2040 Mini +* nullbits Bit-C PRO +* Pimoroni PGA2040 +* Seeed Indicator RP2040 * Seeed XIAO RP2040 * Solder Party RP2040 Stamp * SparkFun ProMicro RP2040 * SparkFun Thing Plus RP2040 * uPesy RP2040 DevKit +* VCC-GND YD-RP2040 +* Viyalab Mizu RP2040 +* Waveshare RP2040 Zero +* Waveshare RP2040 One +* Waveshare RP2040 Plus +* Waveshare RP2040 LCD 0.96 +* Waveshare RP2040 LCD 1.28 * WIZnet W5100S-EVB-Pico * WIZnet W5500-EVB-Pico * WIZnet W6100-EVB-Pico @@ -46,13 +67,33 @@ See https://arduino-pico.readthedocs.io/en/latest/ along with the examples for m * Generic (configurable flash, I/O pins) # Installing via Arduino Boards Manager -**Windows Users**: Please do not use the Windows Store version of the actual Arduino application +## Windows-specific Notes +Please do not use the Windows Store version of the actual Arduino application because it has issues detecting attached Pico boards. Use the "Windows ZIP" or plain "Windows" executable (EXE) download direct from https://arduino.cc. and allow it to install any device drivers it suggests. Otherwise the Pico board may not be detected. Also, if trying out the 2.0 beta Arduino please install the release 1.8 version beforehand to ensure needed device drivers are present. (See #20 for more details.) +## Linux-specific Notes +Installing Arduino using flatpak (often used by "App Stores" in various Linux +distributions) will mean it has restricted access to the host. This might cause uploads to fail +with error messages such as the following: + +``` +Scanning for RP2040 devices +... +No drive to deploy. +``` + +If you encounter this, you will need to either install Arduino in a different manner, or override +the flatpak sandboxing feature using the following command, then restarting Arduino. + +``` +flatpak override --user --filesystem=host:ro cc.arduino.IDE2 +``` + +## Installation Open up the Arduino IDE and go to File->Preferences. In the dialog that pops up, enter the following URL in the "Additional Boards Manager URLs" field: @@ -70,6 +111,12 @@ Type "pico" in the search box and select "Add": ![image](https://user-images.githubusercontent.com/11875/111917223-12063680-8a3c-11eb-8884-4f32b8f0feb1.png) # Installing via GIT + +**Windows Users:** Before installing via `git` on Windows, please read and follow the directions in +[this link](https://arduino-pico.readthedocs.io/en/latest/platformio.html#important-steps-for-windows-users-before-installing). +If Win32 long paths are not enabled, and `git` not configured to use them then there +may be errors when attempting to clone the submodules. + To install via GIT (for latest and greatest versions): ```` mkdir -p ~/Arduino/hardware/pico @@ -146,14 +193,20 @@ The installed tools include a version of OpenOCD (in the pqt-openocd directory) # Features * Adafruit TinyUSB Arduino (USB mouse, keyboard, flash drive, generic HID, CDC Serial, MIDI, WebUSB, others) -* Generic Arduino USB Serial, Keyboard, and Mouse emulation +* Bluetooth on the PicoW (Classic and BLE) with Keyboard, Mouse, Joystick, and Virtual Serial +* Generic Arduino USB Serial, Keyboard, Joystick, and Mouse emulation * WiFi (Pico W) +* HTTP client and server (WebServer) +* SSL/TLS/HTTPS * Over-the-Air (OTA) upgrades * Filesystems (LittleFS and SD/SDFS) * Multicore support (setup1() and loop1()) * FreeRTOS SMP support * Overclocking and underclocking from the menus * digitalWrite/Read, shiftIn/Out, tone, analogWrite(PWM)/Read, temperature +* Analog stereo audio in using DMA and the built-in ADC +* Analog stereo audio out using PWM hardware +* USB drive mode for data loggers (SingleFileDrive) * Peripherals: SPI master, Wire(I2C) master/slave, dual UART, emulated EEPROM, I2S audio input, I2S audio output, Servo * printf (i.e. debug) output over USB serial @@ -171,6 +224,10 @@ Here are some links to coverage and additional tutorials for using `arduino-pico * Pre-release Adafruit QT Py RP2040 - https://www.youtube.com/watch?v=sfC1msqXX0I * Adafruit Feather RP2040 running LCD + TMP117 - https://www.youtube.com/watch?v=fKDeqZiIwHg * Demonstration of Servos and I2C in Korean - https://cafe.naver.com/arduinoshield/1201 +* Home Assistant Pico W integration starter project using Arduino - https://github.com/daniloc/PicoW_HomeAssistant_Starter +* Tutorials for the Raspberry Pi Pico / uPesy RP2040 DevKit board + - English version: https://www.upesy.com/blogs/tutorials/best-tutorials-for-rpi-pi-pico-with-arduino-code + - French version: https://www.upesy.fr/blogs/tutorials/best-tutorials-for-rpi-pi-pico-with-arduino-code # Contributing If you want to contribute or have bugfixes, drop me a note at or open an issue/PR here. @@ -188,7 +245,10 @@ If you want to contribute or have bugfixes, drop me a note at -#include "hardware/gpio.h" // Required for the port*Register macros +#include // Required for the port*Register macros #include "debug_internal.h" #include // CMSIS @@ -68,30 +68,48 @@ void noInterrupts(); #define portOutputRegister(port) ((volatile uint32_t*) sio_hw->gpio_out) #define portInputRegister(port) ((volatile uint32_t*) sio_hw->gpio_in) #define portModeRegister(port) ((volatile uint32_t*) sio_hw->gpio_oe) +#define digitalWriteFast(pin, val) (val ? sio_hw->gpio_set = (1 << pin) : sio_hw->gpio_clr = (1 << pin)) +#define digitalReadFast(pin) ((1 << pin) & sio_hw->gpio_in) +#define sei() interrupts() +#define cli() noInterrupts() // ADC RP2040-specific calls void analogReadResolution(int bits); -float analogReadTemp(); // Returns core temp in Centigrade +#ifdef __cplusplus +float analogReadTemp(float vref = 3.3); // Returns core temp in Centigrade +#endif // PWM RP2040-specific calls void analogWriteFreq(uint32_t freq); void analogWriteRange(uint32_t range); void analogWriteResolution(int res); -// FreeRTOS potential calls -extern bool __isFreeRTOS; - #ifdef __cplusplus } // extern "C" #endif +// FreeRTOS potential calls +extern bool __isFreeRTOS; + // Ancient AVR defines #define HAVE_HWSERIAL0 #define HAVE_HWSERIAL1 #define HAVE_HWSERIAL2 +// PSTR/etc. +#ifndef FPSTR +#define FPSTR (const char *) +#endif + +#ifndef PGM_VOID_P +#define PGM_VOID_P void * +#endif + #ifdef __cplusplus +// emptyString is an ESP-ism, a constant string with "" +extern const String emptyString; + #ifdef USE_TINYUSB // Needed for declaring Serial #include "Adafruit_USBD_CDC.h" diff --git a/cores/rp2040/Bootsel.cpp b/cores/rp2040/Bootsel.cpp index e008faeba..7d50657ce 100644 --- a/cores/rp2040/Bootsel.cpp +++ b/cores/rp2040/Bootsel.cpp @@ -4,11 +4,11 @@ SPDX-License-Identifier: BSD-3-Clause */ #include -#include "pico/stdlib.h" -#include "hardware/gpio.h" -#include "hardware/sync.h" -#include "hardware/structs/ioqspi.h" -#include "hardware/structs/sio.h" +#include +#include +#include +#include +#include // This example blinks the Pico LED when the BOOTSEL button is pressed. // diff --git a/cores/rp2040/CoreMutex.cpp b/cores/rp2040/CoreMutex.cpp new file mode 100644 index 000000000..2331b10fc --- /dev/null +++ b/cores/rp2040/CoreMutex.cpp @@ -0,0 +1,68 @@ +/* + CoreMutex for the Raspberry Pi Pico RP2040 + + Implements a deadlock-safe multicore mutex for sharing things like the + USB or UARTs. + + Copyright (c) 2021 Earle F. Philhower, III + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include "Arduino.h" +#include "CoreMutex.h" + +CoreMutex::CoreMutex(mutex_t *mutex, uint8_t option) { + _mutex = mutex; + _acquired = false; + _option = option; + if (__isFreeRTOS) { + auto m = __get_freertos_mutex_for_ptr(mutex); + if (_option & FromISR) { + __freertos_mutex_take_from_isr(m); + } else { + if (!__freertos_mutex_try_take(m)) { + return; + } + } + } else { + uint32_t owner; + if (!mutex_try_enter(_mutex, &owner)) { + if (owner == get_core_num()) { // Deadlock! + if (_option & DebugEnable) { + DEBUGCORE("CoreMutex - Deadlock detected!\n"); + } + return; + } + mutex_enter_blocking(_mutex); + } + } + _acquired = true; +} + +CoreMutex::~CoreMutex() { + if (_acquired) { + if (__isFreeRTOS) { + auto m = __get_freertos_mutex_for_ptr(_mutex); + if (_option & FromISR) { + __freertos_mutex_give_from_isr(m); + } else { + __freertos_mutex_give(m); + } + } else { + mutex_exit(_mutex); + } + } +} diff --git a/cores/rp2040/CoreMutex.h b/cores/rp2040/CoreMutex.h index f504a9122..1f4426643 100644 --- a/cores/rp2040/CoreMutex.h +++ b/cores/rp2040/CoreMutex.h @@ -23,29 +23,18 @@ #pragma once -#include "pico/mutex.h" +#include +#include "_freertos.h" + +enum { + DebugEnable = 1, + FromISR = 1 << 1, +}; class CoreMutex { public: - CoreMutex(mutex_t *mutex) { - uint32_t owner; - _mutex = mutex; - _acquired = false; - if (!mutex_try_enter(_mutex, &owner)) { - if (owner == get_core_num()) { // Deadlock! - DEBUGCORE("CoreMutex - Deadlock detected!\n"); - return; - } - mutex_enter_blocking(_mutex); - } - _acquired = true; - } - - ~CoreMutex() { - if (_acquired) { - mutex_exit(_mutex); - } - } + CoreMutex(mutex_t *mutex, uint8_t option = DebugEnable); + ~CoreMutex(); operator bool() { return _acquired; @@ -54,4 +43,5 @@ class CoreMutex { private: mutex_t *_mutex; bool _acquired; + uint8_t _option; }; diff --git a/cores/rp2040/FS.cpp b/cores/rp2040/FS.cpp index 0f352efec..8a25e2255 100644 --- a/cores/rp2040/FS.cpp +++ b/cores/rp2040/FS.cpp @@ -192,13 +192,12 @@ File File::openNextFile() { String File::readString() { String ret; ret.reserve(size() - position()); - char temp[256 + 1]; - int countRead = readBytes(temp, sizeof(temp) - 1); - while (countRead > 0) { - temp[countRead] = 0; - ret += temp; - countRead = readBytes(temp, sizeof(temp) - 1); - } + uint8_t temp[256]; + int countRead; + do { + countRead = read(temp, sizeof(temp)); + ret.concat(temp, countRead); + } while (countRead > 0); return ret; } diff --git a/cores/rp2040/FS.h b/cores/rp2040/FS.h index b0703c0de..0ea617aaa 100644 --- a/cores/rp2040/FS.h +++ b/cores/rp2040/FS.h @@ -50,7 +50,9 @@ enum SeekMode { class File : public Stream { public: - File(FileImplPtr p = FileImplPtr(), FS *baseFS = nullptr) : _p(p), _fakeDir(nullptr), _baseFS(baseFS) { } + File(FileImplPtr p = FileImplPtr(), FS *baseFS = nullptr) : _p(p), _fakeDir(nullptr), _baseFS(baseFS) { + _startMillis = millis(); /* workaround -O3 spurious warning #768 */ + } // Print methods: size_t write(uint8_t) override; @@ -238,7 +240,7 @@ class FS { } time_t (*_timeCallback)(void) = nullptr; static time_t _defaultTimeCB(void) { - return time(NULL); + return time(nullptr); } }; diff --git a/cores/rp2040/PolledTimeout.h b/cores/rp2040/PolledTimeout.h index 32494d872..3551437d8 100644 --- a/cores/rp2040/PolledTimeout.h +++ b/cores/rp2040/PolledTimeout.h @@ -129,10 +129,10 @@ struct TimeUnit { } }; -using TimeMillis = TimeUnit< TimeSourceMillis, 1000 >; -using TimeFastMillis = TimeUnit< TimeSourceCycles, 1000 >; -using TimeFastMicros = TimeUnit< TimeSourceCycles, 1000000 >; -using TimeFastNanos = TimeUnit< TimeSourceCycles, 1000000000 >; +using TimeMillis = TimeUnit < TimeSourceMillis, 1'000 >; +using TimeFastMillis = TimeUnit < TimeSourceCycles, 1'000 >; +using TimeFastMicros = TimeUnit < TimeSourceCycles, 1'000'000 >; +using TimeFastNanos = TimeUnit < TimeSourceCycles, 1'000'000'000 >; } //TimePolicy diff --git a/cores/rp2040/RP2040Support.cpp b/cores/rp2040/RP2040Support.cpp new file mode 100644 index 000000000..ffb4d975a --- /dev/null +++ b/cores/rp2040/RP2040Support.cpp @@ -0,0 +1,33 @@ +/* + RP2040 utility class + + Copyright (c) 2021 Earle F. Philhower, III + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include +#include + +extern "C" void boot_double_tap_check(); + +// The following check will never actually execute, but it will cause the boot reset +// checker to be linked in as part of the constructors. + +void RP2040::enableDoubleResetBootloader() { + if (psm_hw->done == 0) { + boot_double_tap_check(); + } +} diff --git a/cores/rp2040/RP2040Support.h b/cores/rp2040/RP2040Support.h index 465830cd8..639f8a55d 100644 --- a/cores/rp2040/RP2040Support.h +++ b/cores/rp2040/RP2040Support.h @@ -27,24 +27,15 @@ #include #include #include +#include #include #include "CoreMutex.h" #include "ccount.pio.h" #include -extern "C" volatile bool __otherCoreIdled; - -// Halt the FreeRTOS PendSV task switching magic -extern "C" int __holdUpPendSV; +#include "_freertos.h" -// FreeRTOS weak functions, to be overridden when we really are running FreeRTOS -extern "C" { - extern void vTaskSuspendAll() __attribute__((weak)); - extern int32_t xTaskResumeAll() __attribute__((weak)); - typedef struct tskTaskControlBlock * TaskHandle_t; - extern void vTaskPreemptionDisable(TaskHandle_t p) __attribute__((weak)); - extern void vTaskPreemptionEnable(TaskHandle_t p) __attribute__((weak)); -} +extern "C" volatile bool __otherCoreIdled; class _MFIFO { public: @@ -100,15 +91,14 @@ class _MFIFO { if (!_multicore) { return; } - __holdUpPendSV = 1; if (__isFreeRTOS) { - vTaskPreemptionDisable(nullptr); - vTaskSuspendAll(); + __freertos_idle_other_core(); + } else { + mutex_enter_blocking(&_idleMutex); + __otherCoreIdled = false; + multicore_fifo_push_blocking(_GOTOSLEEP); + while (!__otherCoreIdled) { /* noop */ } } - mutex_enter_blocking(&_idleMutex); - __otherCoreIdled = false; - multicore_fifo_push_blocking(_GOTOSLEEP); - while (!__otherCoreIdled) { /* noop */ } } void resumeOtherCore() { @@ -118,10 +108,8 @@ class _MFIFO { mutex_exit(&_idleMutex); __otherCoreIdled = false; if (__isFreeRTOS) { - xTaskResumeAll(); - vTaskPreemptionEnable(nullptr); + __freertos_resume_other_core(); } - __holdUpPendSV = 0; // Other core will exit busy-loop and return to operation // once __otherCoreIdled == false. @@ -248,7 +236,7 @@ class RP2040 { // Convert from microseconds to PIO clock cycles static int usToPIOCycles(int us) { // Parenthesis needed to guarantee order of operations to avoid 32bit overflow - return (us * (clock_get_hz(clk_sys) / 1000000)); + return (us * (clock_get_hz(clk_sys) / 1'000'000)); } // Get current clock frequency @@ -256,6 +244,11 @@ class RP2040 { return clock_get_hz(clk_sys); } + // Get current CPU core number + static int cpuid() { + return sio_hw->cpuid; + } + // Get CPU cycle count. Needs to do magic to extens 24b HW to something longer volatile uint64_t _epoch = 0; inline uint32_t getCycleCount() { @@ -314,15 +307,28 @@ class RP2040 { } void reboot() { - watchdog_reboot(0, 0, 100); + watchdog_reboot(0, 0, 10); + while (1) { + continue; + } } inline void restart() { reboot(); } + static void enableDoubleResetBootloader(); + + void wdt_begin(uint32_t delay_ms) { + watchdog_enable(delay_ms, 1); + } + + void wdt_reset() { + watchdog_update(); + } + const char *getChipID() { - static char id[PICO_UNIQUE_BOARD_ID_SIZE_BYTES + 1] = { 0 }; + static char id[2 * PICO_UNIQUE_BOARD_ID_SIZE_BYTES + 1] = { 0 }; if (!id[0]) { pico_get_unique_board_id_string(id, sizeof(id)); } @@ -333,28 +339,20 @@ class RP2040 { _MFIFO fifo; - // TODO - Not so great HW random generator. 32-bits wide. Cryptographers somewhere are crying uint32_t hwrand32() { - // Try and whiten the HW ROSC bit - uint32_t r = 0; - for (int k = 0; k < 32; k++) { - unsigned long int b; - do { - b = rosc_hw->randombit & 1; - if (b != (rosc_hw->randombit & 1)) { - break; - } - } while (true); - r <<= 1; - r |= b; - } - // Stir using the cycle count LSBs. In any WiFi use case this will be a random # since the connection time is not cycle-accurate - uint64_t rr = (((uint64_t)~r) << 32LL) | r; - rr >>= rp2040.getCycleCount() & 32LL; + return get_rand_32(); + } - return (uint32_t)rr; + bool isPicoW() { +#if !defined(ARDUINO_RASPBERRY_PI_PICO_W) + return false; +#else + extern bool __isPicoW; + return __isPicoW; +#endif } + private: static void _SystickHandler() { rp2040._epoch += 1LL << 24; diff --git a/cores/rp2040/RP2040USB.cpp b/cores/rp2040/RP2040USB.cpp index e94e8b136..d2ebb2a01 100644 --- a/cores/rp2040/RP2040USB.cpp +++ b/cores/rp2040/RP2040USB.cpp @@ -25,14 +25,18 @@ #include "CoreMutex.h" #include "RP2040USB.h" -#include "tusb.h" -#include "class/hid/hid_device.h" -#include "class/audio/audio.h" -#include "class/midi/midi.h" -#include "pico/time.h" -#include "hardware/irq.h" -#include "pico/mutex.h" -#include "pico/unique_id.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "sdkoverride/tusb_absmouse.h" +#include // Big, global USB mutex, shared with all USB devices to make sure we don't // have multiple cores updating the TUSB state in parallel @@ -42,12 +46,11 @@ mutex_t __usb_mutex; #define USB_TASK_INTERVAL 1000 static int __usb_task_irq; -// USB VID/PID (note that PID can change depending on the add'l interfaces) +#ifndef USBD_VID #define USBD_VID (0x2E8A) // Raspberry Pi +#endif -#ifdef SERIALUSB_PID -#define USBD_PID (SERIALUSB_PID) -#else +#ifndef USBD_PID #define USBD_PID (0x000a) // Raspberry Pi Pico SDK CDC #endif @@ -67,11 +70,17 @@ static int __usb_task_irq; #define USBD_STR_PRODUCT (0x02) #define USBD_STR_SERIAL (0x03) #define USBD_STR_CDC (0x04) - +#define USBD_STR_RPI_RESET (0x05) #define EPNUM_HID 0x83 -#define EPNUM_MIDI 0x01 +#define USBD_MSC_EPOUT 0x03 +#define USBD_MSC_EPIN 0x84 +#define USBD_MSC_EPSIZE 64 + +#define TUD_RPI_RESET_DESCRIPTOR(_itfnum, _stridx) \ + /* Interface */\ + 9, TUSB_DESC_INTERFACE, _itfnum, 0, 0, TUSB_CLASS_VENDOR_SPECIFIC, RESET_INTERFACE_SUBCLASS, RESET_INTERFACE_PROTOCOL, _stridx, const uint8_t *tud_descriptor_device_cb(void) { @@ -91,7 +100,7 @@ const uint8_t *tud_descriptor_device_cb(void) { .iSerialNumber = USBD_STR_SERIAL, .bNumConfigurations = 1 }; - if (__USBInstallSerial && !__USBInstallKeyboard && !__USBInstallMouse && !__USBInstallJoystick && !__USBInstallMIDI) { + if (__USBInstallSerial && !__USBInstallKeyboard && !__USBInstallMouse && !__USBInstallAbsoluteMouse && !__USBInstallJoystick && !__USBInstallMassStorage) { // Can use as-is, this is the default USB case return (const uint8_t *)&usbd_desc_device; } @@ -99,14 +108,14 @@ const uint8_t *tud_descriptor_device_cb(void) { if (__USBInstallKeyboard) { usbd_desc_device.idProduct |= 0x8000; } - if (__USBInstallMouse) { + if (__USBInstallMouse || __USBInstallAbsoluteMouse) { usbd_desc_device.idProduct |= 0x4000; } if (__USBInstallJoystick) { usbd_desc_device.idProduct |= 0x0100; } - if (__USBInstallMIDI) { - usbd_desc_device.idProduct |= 0x2000; + if (__USBInstallMassStorage) { + usbd_desc_device.idProduct ^= 0x2000; } // Set the device class to 0 to indicate multiple device classes usbd_desc_device.bDeviceClass = 0; @@ -120,15 +129,15 @@ int __USBGetKeyboardReportID() { } int __USBGetMouseReportID() { - return __USBInstallKeyboard ? 2 : 1; + return __USBInstallKeyboard ? 3 : 1; } int __USBGetJoystickReportID() { int i = 1; if (__USBInstallKeyboard) { - i++; + i += 2; } - if (__USBInstallMouse) { + if (__USBInstallMouse || __USBInstallAbsoluteMouse) { i++; } return i; @@ -147,8 +156,9 @@ static uint8_t *GetDescHIDReport(int *len) { void __SetupDescHIDReport() { //allocate memory for the HID report descriptors. We don't use them, but need the size here. uint8_t desc_hid_report_mouse[] = { TUD_HID_REPORT_DESC_MOUSE(HID_REPORT_ID(1)) }; + uint8_t desc_hid_report_absmouse[] = { TUD_HID_REPORT_DESC_ABSMOUSE(HID_REPORT_ID(1)) }; uint8_t desc_hid_report_joystick[] = { TUD_HID_REPORT_DESC_GAMEPAD(HID_REPORT_ID(1)) }; - uint8_t desc_hid_report_keyboard[] = { TUD_HID_REPORT_DESC_KEYBOARD(HID_REPORT_ID(1)) }; + uint8_t desc_hid_report_keyboard[] = { TUD_HID_REPORT_DESC_KEYBOARD(HID_REPORT_ID(1)), TUD_HID_REPORT_DESC_CONSUMER(HID_REPORT_ID(2)) }; int size = 0; //accumulate the size of all used HID report descriptors @@ -157,6 +167,8 @@ void __SetupDescHIDReport() { } if (__USBInstallMouse) { size += sizeof(desc_hid_report_mouse); + } else if (__USBInstallAbsoluteMouse) { + size += sizeof(desc_hid_report_absmouse); } if (__USBInstallJoystick) { size += sizeof(desc_hid_report_joystick); @@ -185,11 +197,19 @@ void __SetupDescHIDReport() { if (__USBInstallMouse) { //determine if we need an offset (USB keyboard is installed) if (__USBInstallKeyboard) { - uint8_t desc_local[] = { TUD_HID_REPORT_DESC_MOUSE(HID_REPORT_ID(2)) }; + uint8_t desc_local[] = { TUD_HID_REPORT_DESC_MOUSE(HID_REPORT_ID(3)) }; memcpy(__hid_report + sizeof(desc_hid_report_keyboard), desc_local, sizeof(desc_local)); } else { memcpy(__hid_report, desc_hid_report_mouse, sizeof(desc_hid_report_mouse)); } + } else if (__USBInstallAbsoluteMouse) { + //determine if we need an offset (USB keyboard is installed) + if (__USBInstallKeyboard) { + uint8_t desc_local[] = { TUD_HID_REPORT_DESC_ABSMOUSE(HID_REPORT_ID(3)) }; + memcpy(__hid_report + sizeof(desc_hid_report_keyboard), desc_local, sizeof(desc_local)); + } else { + memcpy(__hid_report, desc_hid_report_absmouse, sizeof(desc_hid_report_absmouse)); + } } //3.) joystick descriptor. 2 additional checks are necessary for mouse and/or keyboard @@ -197,12 +217,15 @@ void __SetupDescHIDReport() { uint8_t reportid = 1; int offset = 0; if (__USBInstallKeyboard) { - reportid++; + reportid += 2; offset += sizeof(desc_hid_report_keyboard); } if (__USBInstallMouse) { reportid++; offset += sizeof(desc_hid_report_mouse); + } else if (__USBInstallAbsoluteMouse) { + reportid++; + offset += sizeof(desc_hid_report_absmouse); } uint8_t desc_local[] = { TUD_HID_REPORT_DESC_GAMEPAD(HID_REPORT_ID(reportid)) }; memcpy(__hid_report + offset, desc_local, sizeof(desc_local)); @@ -226,9 +249,9 @@ const uint8_t *tud_descriptor_configuration_cb(uint8_t index) { void __SetupUSBDescriptor() { if (!usbd_desc_cfg) { - bool hasHID = __USBInstallKeyboard || __USBInstallMouse || __USBInstallJoystick; + bool hasHID = __USBInstallKeyboard || __USBInstallMouse || __USBInstallAbsoluteMouse || __USBInstallJoystick; - uint8_t interface_count = (__USBInstallSerial ? 2 : 0) + (hasHID ? 1 : 0) + (__USBInstallMIDI ? 2 : 0); + uint8_t interface_count = (__USBInstallSerial ? 2 : 0) + (hasHID ? 1 : 0) + (__USBInstallMassStorage ? 1 : 0); uint8_t cdc_desc[TUD_CDC_DESC_LEN] = { // Interface number, string index, protocol, report descriptor len, EP In & Out address, size & polling interval @@ -243,13 +266,20 @@ void __SetupUSBDescriptor() { TUD_HID_DESCRIPTOR(hid_itf, 0, HID_ITF_PROTOCOL_NONE, hid_report_len, EPNUM_HID, CFG_TUD_HID_EP_BUFSIZE, 10) }; - uint8_t midi_itf = hid_itf + (hasHID ? 1 : 0); - uint8_t midi_desc[TUD_MIDI_DESC_LEN] = { - // Interface number, string index, EP Out & EP In address, EP size - TUD_MIDI_DESCRIPTOR(midi_itf, 0, EPNUM_MIDI, 0x80 | EPNUM_MIDI, 64) + uint8_t msd_itf = interface_count - 1; + uint8_t msd_desc[TUD_MSC_DESC_LEN] = { + TUD_MSC_DESCRIPTOR(msd_itf, 0, USBD_MSC_EPOUT, USBD_MSC_EPIN, USBD_MSC_EPSIZE) }; - int usbd_desc_len = TUD_CONFIG_DESC_LEN + (__USBInstallSerial ? sizeof(cdc_desc) : 0) + (hasHID ? sizeof(hid_desc) : 0) + (__USBInstallMIDI ? sizeof(midi_desc) : 0); + int usbd_desc_len = TUD_CONFIG_DESC_LEN + (__USBInstallSerial ? sizeof(cdc_desc) : 0) + (hasHID ? sizeof(hid_desc) : 0) + (__USBInstallMassStorage ? sizeof(msd_desc) : 0); + +#ifdef ENABLE_PICOTOOL_USB + uint8_t picotool_itf = interface_count++; + uint8_t picotool_desc[] = { + TUD_RPI_RESET_DESCRIPTOR(picotool_itf, USBD_STR_RPI_RESET) + }; + usbd_desc_len += sizeof(picotool_desc); +#endif uint8_t tud_cfg_desc[TUD_CONFIG_DESC_LEN] = { // Config number, interface count, string index, total length, attribute, power in mA @@ -271,26 +301,34 @@ void __SetupUSBDescriptor() { memcpy(ptr, hid_desc, sizeof(hid_desc)); ptr += sizeof(hid_desc); } - if (__USBInstallMIDI) { - memcpy(ptr, midi_desc, sizeof(midi_desc)); + if (__USBInstallMassStorage) { + memcpy(ptr, msd_desc, sizeof(msd_desc)); + ptr += sizeof(msd_desc); } +#ifdef ENABLE_PICOTOOL_USB + memcpy(ptr, picotool_desc, sizeof(picotool_desc)); + ptr += sizeof(picotool_desc); +#endif } } } const uint16_t *tud_descriptor_string_cb(uint8_t index, uint16_t langid) { (void) langid; -#define DESC_STR_MAX (20) +#define DESC_STR_MAX (32) static uint16_t desc_str[DESC_STR_MAX]; static char idString[PICO_UNIQUE_BOARD_ID_SIZE_BYTES * 2 + 1]; static const char *const usbd_desc_str[] = { [USBD_STR_0] = "", - [USBD_STR_MANUF] = "Raspberry Pi", - [USBD_STR_PRODUCT] = "PicoArduino", + [USBD_STR_MANUF] = USB_MANUFACTURER, + [USBD_STR_PRODUCT] = USB_PRODUCT, [USBD_STR_SERIAL] = idString, [USBD_STR_CDC] = "Board CDC", +#ifdef ENABLE_PICOTOOL_USB + [USBD_STR_RPI_RESET] = "Reset", +#endif }; if (!idString[0]) { @@ -303,7 +341,7 @@ const uint16_t *tud_descriptor_string_cb(uint8_t index, uint16_t langid) { len = 1; } else { if (index >= sizeof(usbd_desc_str) / sizeof(usbd_desc_str[0])) { - return NULL; + return nullptr; } const char *str = usbd_desc_str[index]; for (len = 0; len < DESC_STR_MAX - 1 && str[len]; ++len) { @@ -322,7 +360,7 @@ static void usb_irq() { // if the mutex is already owned, then we are in user code // in this file which will do a tud_task itself, so we'll just do nothing // until the next tick; we won't starve - if (mutex_try_enter(&__usb_mutex, NULL)) { + if (mutex_try_enter(&__usb_mutex, nullptr)) { tud_task(); mutex_exit(&__usb_mutex); } @@ -352,13 +390,14 @@ void __USBStart() { irq_set_exclusive_handler(__usb_task_irq, usb_irq); irq_set_enabled(__usb_task_irq, true); - add_alarm_in_us(USB_TASK_INTERVAL, timer_task, NULL, true); + add_alarm_in_us(USB_TASK_INTERVAL, timer_task, nullptr, true); } // Invoked when received GET_REPORT control request // Application must fill buffer report's content and return its length. // Return zero will cause the stack to STALL request +extern "C" uint16_t tud_hid_get_report_cb(uint8_t instance, uint8_t report_id, hid_report_type_t report_type, uint8_t* buffer, uint16_t reqlen) __attribute__((weak)); extern "C" uint16_t tud_hid_get_report_cb(uint8_t instance, uint8_t report_id, hid_report_type_t report_type, uint8_t* buffer, uint16_t reqlen) { // TODO not implemented (void) instance; @@ -372,6 +411,7 @@ extern "C" uint16_t tud_hid_get_report_cb(uint8_t instance, uint8_t report_id, h // Invoked when received SET_REPORT control request or // received data on OUT endpoint ( Report ID = 0, Type = 0 ) +extern "C" void tud_hid_set_report_cb(uint8_t instance, uint8_t report_id, hid_report_type_t report_type, uint8_t const* buffer, uint16_t bufsize) __attribute__((weak)); extern "C" void tud_hid_set_report_cb(uint8_t instance, uint8_t report_id, hid_report_type_t report_type, uint8_t const* buffer, uint16_t bufsize) { // TODO set LED based on CAPLOCK, NUMLOCK etc... (void) instance; @@ -381,4 +421,188 @@ extern "C" void tud_hid_set_report_cb(uint8_t instance, uint8_t report_id, hid_r (void) bufsize; } +extern "C" int32_t tud_msc_read10_cb(uint8_t lun, uint32_t lba, uint32_t offset, void* buffer, uint32_t bufsize) __attribute__((weak)); +extern "C" int32_t tud_msc_read10_cb(uint8_t lun, uint32_t lba, uint32_t offset, void* buffer, uint32_t bufsize) { + (void) lun; + (void) lba; + (void) offset; + (void) buffer; + (void) bufsize; + return -1; +} + +extern "C" bool tud_msc_test_unit_ready_cb(uint8_t lun) __attribute__((weak)); +extern "C" bool tud_msc_test_unit_ready_cb(uint8_t lun) { + (void) lun; + return false; +} + +extern "C" int32_t tud_msc_write10_cb(uint8_t lun, uint32_t lba, uint32_t offset, uint8_t* buffer, uint32_t bufsize) __attribute__((weak)); +extern "C" int32_t tud_msc_write10_cb(uint8_t lun, uint32_t lba, uint32_t offset, uint8_t* buffer, uint32_t bufsize) { + (void) lun; + (void) lba; + (void) offset; + (void) buffer; + (void) bufsize; + return -1; +} + +extern "C" int32_t tud_msc_scsi_cb(uint8_t lun, uint8_t const scsi_cmd[16], void* buffer, uint16_t bufsize) __attribute__((weak)); +extern "C" int32_t tud_msc_scsi_cb(uint8_t lun, uint8_t const scsi_cmd[16], void* buffer, uint16_t bufsize) { + (void) lun; + (void) scsi_cmd; + (void) buffer; + (void) bufsize; + return 0; +} + +extern "C" void tud_msc_capacity_cb(uint8_t lun, uint32_t* block_count, uint16_t* block_size) __attribute__((weak)); +extern "C" void tud_msc_capacity_cb(uint8_t lun, uint32_t* block_count, uint16_t* block_size) { + (void) lun; + *block_count = 0; + *block_size = 0; +} + +extern "C" void tud_msc_inquiry_cb(uint8_t lun, uint8_t vendor_id[8], uint8_t product_id[16], uint8_t product_rev[4]) __attribute__((weak)); +extern "C" void tud_msc_inquiry_cb(uint8_t lun, uint8_t vendor_id[8], uint8_t product_id[16], uint8_t product_rev[4]) { + (void) lun; + vendor_id[0] = 0; + product_id[0] = 0; + product_rev[0] = 0; +} + + + +#ifdef ENABLE_PICOTOOL_USB + +static uint8_t _picotool_itf_num; + +static void resetd_init() { +} + +static void resetd_reset(uint8_t rhport) { + (void) rhport; + _picotool_itf_num = 0; +} + +static uint16_t resetd_open(uint8_t rhport, + tusb_desc_interface_t const *itf_desc, uint16_t max_len) { + (void) rhport; + TU_VERIFY(TUSB_CLASS_VENDOR_SPECIFIC == itf_desc->bInterfaceClass && + RESET_INTERFACE_SUBCLASS == itf_desc->bInterfaceSubClass && + RESET_INTERFACE_PROTOCOL == itf_desc->bInterfaceProtocol, 0); + + uint16_t const drv_len = sizeof(tusb_desc_interface_t); + TU_VERIFY(max_len >= drv_len, 0); + + _picotool_itf_num = itf_desc->bInterfaceNumber; + return drv_len; +} + +// Support for parameterized reset via vendor interface control request +static bool resetd_control_xfer_cb(uint8_t rhport, uint8_t stage, + tusb_control_request_t const *request) { + (void) rhport; + // nothing to do with DATA & ACK stage + if (stage != CONTROL_STAGE_SETUP) { + return true; + } + + if (request->wIndex == _picotool_itf_num) { + if (request->bRequest == RESET_REQUEST_BOOTSEL) { + reset_usb_boot(0, (request->wValue & 0x7f)); + // does not return, otherwise we'd return true + } + + if (request->bRequest == RESET_REQUEST_FLASH) { + watchdog_reboot(0, 0, 100); + return true; + } + + } + return false; +} + +static bool resetd_xfer_cb(uint8_t rhport, uint8_t ep_addr, + xfer_result_t result, uint32_t xferred_bytes) { + (void) rhport; + (void) ep_addr; + (void) result; + (void) xferred_bytes; + return true; +} + +static usbd_class_driver_t const _resetd_driver = { +#if CFG_TUSB_DEBUG >= 2 + .name = "RESET", +#endif + .init = resetd_init, + .reset = resetd_reset, + .open = resetd_open, + .control_xfer_cb = resetd_control_xfer_cb, + .xfer_cb = resetd_xfer_cb, + .sof = NULL +}; + +// Implement callback to add our custom driver +usbd_class_driver_t const *usbd_app_driver_get_cb(uint8_t *driver_count) { + *driver_count = 1; + return &_resetd_driver; +} + +#elif defined NO_USB + +// will ensure backward compatibility with existing code when using pico-debug + +#warning "NO_USB selected. No output to Serial will occur!" + +#include + +void SerialUSB::begin(unsigned long baud) { +} + +void SerialUSB::end() { + +} + +int SerialUSB::peek() { + return 0; +} + +int SerialUSB::read() { + return -1; +} + +int SerialUSB::available() { + return 0; +} + +int SerialUSB::availableForWrite() { + return 0; +} + +void SerialUSB::flush() { + +} + +size_t SerialUSB::write(uint8_t c) { + (void) c; + return 0; +} + +size_t SerialUSB::write(const uint8_t *buf, size_t length) { + (void) buf; + (void) length; + return 0; +} + +SerialUSB::operator bool() { + return false; +} + +SerialUSB Serial; + +#endif + + #endif diff --git a/cores/rp2040/RP2040USB.h b/cores/rp2040/RP2040USB.h index 57ee4b97e..ba219be34 100644 --- a/cores/rp2040/RP2040USB.h +++ b/cores/rp2040/RP2040USB.h @@ -19,14 +19,20 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "pico/mutex.h" +#include // Weak function definitions for each type of endpoint extern void __USBInstallSerial() __attribute__((weak)); + extern void __USBInstallKeyboard() __attribute__((weak)); + extern void __USBInstallJoystick() __attribute__((weak)); + +// One or the other allowed, not both extern void __USBInstallMouse() __attribute__((weak)); -extern void __USBInstallMIDI() __attribute__((weak)); +extern void __USBInstallAbsoluteMouse() __attribute__((weak)); + +extern void __USBInstallMassStorage() __attribute__((weak)); // Big, global USB mutex, shared with all USB devices to make sure we don't // have multiple cores updating the TUSB state in parallel diff --git a/cores/rp2040/RP2040Version.h b/cores/rp2040/RP2040Version.h index 611fe445e..fad22cd4a 100644 --- a/cores/rp2040/RP2040Version.h +++ b/cores/rp2040/RP2040Version.h @@ -1,5 +1,5 @@ #pragma once -#define ARDUINO_PICO_MAJOR 2 -#define ARDUINO_PICO_MINOR 4 +#define ARDUINO_PICO_MAJOR 3 +#define ARDUINO_PICO_MINOR 2 #define ARDUINO_PICO_REVISION 0 -#define ARDUINO_PICO_VERSION_STR "2.4.0" +#define ARDUINO_PICO_VERSION_STR "3.2.0" diff --git a/cores/rp2040/SerialPIO.cpp b/cores/rp2040/SerialPIO.cpp index ac15ca26a..68579891d 100644 --- a/cores/rp2040/SerialPIO.cpp +++ b/cores/rp2040/SerialPIO.cpp @@ -230,7 +230,7 @@ void SerialPIO::begin(unsigned long baud, uint16_t config) { pio_sm_clear_fifos(_rxPIO, _rxSM); // Remove any existing data // Put phase divider into OSR w/o using add'l program memory - pio_sm_put_blocking(_rxPIO, _rxSM, clock_get_hz(clk_sys) / (_baud * 2) - 5 /* insns in PIO halfbit loop */); + pio_sm_put_blocking(_rxPIO, _rxSM, clock_get_hz(clk_sys) / (_baud * 2) - 7 /* insns in PIO halfbit loop */); pio_sm_exec(_rxPIO, _rxSM, pio_encode_pull(false, false)); // Join the TX FIFO to the RX one now that we don't need it @@ -259,9 +259,11 @@ void SerialPIO::end() { } if (_tx != NOPIN) { pio_sm_set_enabled(_txPIO, _txSM, false); + pio_sm_unclaim(_txPIO, _txSM); } if (_rx != NOPIN) { pio_sm_set_enabled(_rxPIO, _rxSM, false); + pio_sm_unclaim(_rxPIO, _rxSM); _pioSP[pio_get_index(_rxPIO)][_rxSM] = nullptr; // If no more active, disable the IRQ auto pioNum = pio_get_index(_rxPIO); @@ -370,3 +372,8 @@ size_t SerialPIO::write(uint8_t c) { SerialPIO::operator bool() { return _running; } + +#ifdef ARDUINO_NANO_RP2040_CONNECT +// NINA updates +SerialPIO Serial3(SERIAL3_TX, SERIAL3_RX); +#endif diff --git a/cores/rp2040/SerialPIO.h b/cores/rp2040/SerialPIO.h index 70c27c4bd..171ceddbb 100644 --- a/cores/rp2040/SerialPIO.h +++ b/cores/rp2040/SerialPIO.h @@ -80,3 +80,8 @@ class SerialPIO : public HardwareSerial { uint32_t _reader; uint8_t *_queue; }; + +#ifdef ARDUINO_NANO_RP2040_CONNECT +// NINA updates +extern SerialPIO Serial3; +#endif diff --git a/cores/rp2040/SerialUART.cpp b/cores/rp2040/SerialUART.cpp index 662427d72..6faadbcac 100644 --- a/cores/rp2040/SerialUART.cpp +++ b/cores/rp2040/SerialUART.cpp @@ -69,7 +69,7 @@ bool SerialUART::setRTS(pin_size_t pin) { constexpr uint32_t valid[2] = { __bitset({3, 15, 19}) /* UART0 */, __bitset({7, 11, 23, 27}) /* UART1 */ }; - if ((!_running) && ((1 << pin) & valid[uart_get_index(_uart)])) { + if ((!_running) && ((pin == UART_PIN_NOT_DEFINED) || ((1 << pin) & valid[uart_get_index(_uart)]))) { _rts = pin; return true; } @@ -86,7 +86,7 @@ bool SerialUART::setCTS(pin_size_t pin) { constexpr uint32_t valid[2] = { __bitset({2, 14, 18}) /* UART0 */, __bitset({6, 10, 22, 26}) /* UART1 */ }; - if ((!_running) && ((1 << pin) & valid[uart_get_index(_uart)])) { + if ((!_running) && ((pin == UART_PIN_NOT_DEFINED) || ((1 << pin) & valid[uart_get_index(_uart)]))) { _cts = pin; return true; } @@ -134,6 +134,20 @@ void SerialUART::begin(unsigned long baud, uint16_t config) { _overflow = false; _queue = new uint8_t[_fifoSize]; _baud = baud; + + _fcnTx = gpio_get_function(_tx); + _fcnRx = gpio_get_function(_rx); + gpio_set_function(_tx, GPIO_FUNC_UART); + gpio_set_function(_rx, GPIO_FUNC_UART); + if (_rts != UART_PIN_NOT_DEFINED) { + _fcnRts = gpio_get_function(_rts); + gpio_set_function(_rts, GPIO_FUNC_UART); + } + if (_cts != UART_PIN_NOT_DEFINED) { + _fcnCts = gpio_get_function(_cts); + gpio_set_function(_cts, GPIO_FUNC_UART); + } + uart_init(_uart, baud); int bits, stop; uart_parity_t parity; @@ -171,14 +185,6 @@ void SerialUART::begin(unsigned long baud, uint16_t config) { break; } uart_set_format(_uart, bits, stop, parity); - gpio_set_function(_tx, GPIO_FUNC_UART); - gpio_set_function(_rx, GPIO_FUNC_UART); - if (_rts != UART_PIN_NOT_DEFINED) { - gpio_set_function(_rts, GPIO_FUNC_UART); - } - if (_cts != UART_PIN_NOT_DEFINED) { - gpio_set_function(_cts, GPIO_FUNC_UART); - } uart_set_hw_flow(_uart, _rts != UART_PIN_NOT_DEFINED, _cts != UART_PIN_NOT_DEFINED); _writer = 0; _reader = 0; @@ -196,6 +202,7 @@ void SerialUART::begin(unsigned long baud, uint16_t config) { } else { // Polling mode has no IRQs used } + _break = false; _running = true; } @@ -211,6 +218,7 @@ void SerialUART::end() { irq_set_enabled(UART1_IRQ, false); } } + // Paranoia - ensure nobody else is using anything here at the same time mutex_enter_blocking(&_mutex); mutex_enter_blocking(&_fifoMutex); @@ -219,6 +227,16 @@ void SerialUART::end() { // Reset the mutexes once all is off/cleaned up mutex_exit(&_fifoMutex); mutex_exit(&_mutex); + + // Restore pin functions + gpio_set_function(_tx, _fcnTx); + gpio_set_function(_rx, _fcnRx); + if (_rts != UART_PIN_NOT_DEFINED) { + gpio_set_function(_rts, _fcnRts); + } + if (_cts != UART_PIN_NOT_DEFINED) { + gpio_set_function(_cts, _fcnCts); + } } void SerialUART::_pumpFIFO() { @@ -273,13 +291,22 @@ int SerialUART::read() { } bool SerialUART::overflow() { - CoreMutex m(&_mutex); - if (!_running || !m) { + if (!_running) { return false; } - bool hold = _overflow; + + if (_polling) { + _handleIRQ(false); + } else { + _pumpFIFO(); + } + + mutex_enter_blocking(&_fifoMutex); + bool ovf = _overflow; _overflow = false; - return hold; + mutex_exit(&_fifoMutex); + + return ovf; } int SerialUART::available() { @@ -350,6 +377,25 @@ SerialUART::operator bool() { return _running; } +bool SerialUART::getBreakReceived() { + if (!_running) { + return false; + } + + if (_polling) { + _handleIRQ(false); + } else { + _pumpFIFO(); + } + + mutex_enter_blocking(&_fifoMutex); + bool break_received = _break; + _break = false; + mutex_exit(&_fifoMutex); + + return break_received; +} + void arduino::serialEvent1Run(void) { if (serialEvent1 && Serial1.available()) { serialEvent1(); @@ -375,7 +421,16 @@ void __not_in_flash_func(SerialUART::_handleIRQ)(bool inIRQ) { // ICR is write-to-clear uart_get_hw(_uart)->icr = UART_UARTICR_RTIC_BITS | UART_UARTICR_RXIC_BITS; while (uart_is_readable(_uart)) { - auto val = uart_getc(_uart); + uint32_t raw = uart_get_hw(_uart)->dr; + if (raw & 0x400) { + // break! + _break = true; + continue; + } else if (raw & 0x300) { + // Framing, Parity Error. Ignore this bad char + continue; + } + uint8_t val = raw & 0xff; auto next_writer = _writer + 1; if (next_writer == _fifoSize) { next_writer = 0; diff --git a/cores/rp2040/SerialUART.h b/cores/rp2040/SerialUART.h index 564c01534..76cb0546a 100644 --- a/cores/rp2040/SerialUART.h +++ b/cores/rp2040/SerialUART.h @@ -63,18 +63,29 @@ class SerialUART : public HardwareSerial { bool overflow(); operator bool() override; + // ESP8266 compat + void setDebugOutput(bool unused) { + (void) unused; + } + // Not to be called by users, only from the IRQ handler. In public so that the C-language IQR callback can access it void _handleIRQ(bool inIRQ = true); + // Allows the user to sleep until a break is received (self-clears the flag + // on read) + bool getBreakReceived(); + private: bool _running = false; uart_inst_t *_uart; pin_size_t _tx, _rx; pin_size_t _rts, _cts; + enum gpio_function _fcnTx, _fcnRx, _fcnRts, _fcnCts; int _baud; mutex_t _mutex; bool _polling = false; bool _overflow; + bool _break; // Lockless, IRQ-handled circular queue uint32_t _writer; diff --git a/cores/rp2040/SerialUSB.cpp b/cores/rp2040/SerialUSB.cpp index 8974d17fb..c82a8a751 100644 --- a/cores/rp2040/SerialUSB.cpp +++ b/cores/rp2040/SerialUSB.cpp @@ -25,14 +25,15 @@ #include #include "CoreMutex.h" -#include "tusb.h" -#include "pico/time.h" -#include "pico/binary_info.h" -#include "pico/bootrom.h" -#include "hardware/irq.h" -#include "pico/mutex.h" -#include "hardware/watchdog.h" -#include "pico/unique_id.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include #ifndef DISABLE_USB_SERIAL // Ensure we are installed in the USB chain @@ -64,52 +65,57 @@ void SerialUSB::end() { } int SerialUSB::peek() { - CoreMutex m(&__usb_mutex); + CoreMutex m(&__usb_mutex, false); if (!_running || !m) { return 0; } uint8_t c; + tud_task(); return tud_cdc_peek(&c) ? (int) c : -1; } int SerialUSB::read() { - CoreMutex m(&__usb_mutex); + CoreMutex m(&__usb_mutex, false); if (!_running || !m) { return -1; } - if (tud_cdc_connected() && tud_cdc_available()) { + tud_task(); + if (tud_cdc_available()) { return tud_cdc_read_char(); } return -1; } int SerialUSB::available() { - CoreMutex m(&__usb_mutex); + CoreMutex m(&__usb_mutex, false); if (!_running || !m) { return 0; } + tud_task(); return tud_cdc_available(); } int SerialUSB::availableForWrite() { - CoreMutex m(&__usb_mutex); + CoreMutex m(&__usb_mutex, false); if (!_running || !m) { return 0; } + tud_task(); return tud_cdc_write_available(); } void SerialUSB::flush() { - CoreMutex m(&__usb_mutex); + CoreMutex m(&__usb_mutex, false); if (!_running || !m) { return; } tud_cdc_write_flush(); + tud_task(); } size_t SerialUSB::write(uint8_t c) { @@ -117,7 +123,7 @@ size_t SerialUSB::write(uint8_t c) { } size_t SerialUSB::write(const uint8_t *buf, size_t length) { - CoreMutex m(&__usb_mutex); + CoreMutex m(&__usb_mutex, false); if (!_running || !m) { return 0; } @@ -142,7 +148,7 @@ size_t SerialUSB::write(const uint8_t *buf, size_t length) { tud_task(); tud_cdc_write_flush(); if (!tud_cdc_connected() || - (!tud_cdc_write_available() && time_us_64() > last_avail_time + 1000000 /* 1 second */)) { + (!tud_cdc_write_available() && time_us_64() > last_avail_time + 1'000'000 /* 1 second */)) { break; } } @@ -151,11 +157,12 @@ size_t SerialUSB::write(const uint8_t *buf, size_t length) { // reset our timeout last_avail_time = 0; } + tud_task(); return written; } SerialUSB::operator bool() { - CoreMutex m(&__usb_mutex); + CoreMutex m(&__usb_mutex, false); if (!_running || !m) { return false; } @@ -168,8 +175,20 @@ SerialUSB::operator bool() { static bool _dtr = false; static bool _rts = false; static int _bps = 115200; +static bool _rebooting = false; static void CheckSerialReset() { - if ((_bps == 1200) && (!_dtr)) { + if (!_rebooting && (_bps == 1200) && (!_dtr)) { + if (__isFreeRTOS) { + __freertos_idle_other_core(); + } + _rebooting = true; + // Disable NVIC IRQ, so that we don't get bothered anymore + irq_set_enabled(USBCTRL_IRQ, false); + // Reset the whole USB hardware block + reset_block(RESETS_RESET_USBCTRL_BITS); + unreset_block(RESETS_RESET_USBCTRL_BITS); + // Delay a bit, so the PC can figure out that we have disconnected. + sleep_ms(3); reset_usb_boot(0, 0); while (1); // WDT will fire here } diff --git a/cores/rp2040/SerialUSB.h b/cores/rp2040/SerialUSB.h index f4be03313..0e0b6bff0 100644 --- a/cores/rp2040/SerialUSB.h +++ b/cores/rp2040/SerialUSB.h @@ -44,6 +44,11 @@ class SerialUSB : public HardwareSerial { using Print::write; operator bool() override; + // ESP8266 compat + void setDebugOutput(bool unused) { + (void) unused; + } + private: bool _running = false; }; diff --git a/libraries/WiFi/src/StackThunk.cpp b/cores/rp2040/StackThunk.cpp similarity index 66% rename from libraries/WiFi/src/StackThunk.cpp rename to cores/rp2040/StackThunk.cpp index a0c5adf55..062ad7e94 100644 --- a/libraries/WiFi/src/StackThunk.cpp +++ b/cores/rp2040/StackThunk.cpp @@ -1,3 +1,22 @@ +/* + StackThunk - Implements a simple 2nd stack for BSSL and others + Copyright (c) 2022 Earle F. Philhower, III. All rights reserved. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + #include #include #include @@ -5,9 +24,9 @@ extern "C" { - uint32_t *stack_thunk_ptr = NULL; - uint32_t *stack_thunk_top = NULL; - uint32_t *stack_thunk_save = NULL; /* Saved A1 while in BearSSL */ + uint32_t *stack_thunk_ptr = nullptr; + uint32_t *stack_thunk_top = nullptr; + uint32_t *stack_thunk_save = nullptr; /* Saved A1 while in BearSSL */ uint32_t stack_thunk_refcnt = 0; /* Largest stack usage seen in the wild at 6120 */ @@ -28,7 +47,7 @@ extern "C" { abort(); } stack_thunk_top = stack_thunk_ptr + _stackSize - 1; - stack_thunk_save = NULL; + stack_thunk_save = nullptr; stack_thunk_repaint(); } } @@ -42,9 +61,9 @@ extern "C" { stack_thunk_refcnt--; if (!stack_thunk_refcnt) { free(stack_thunk_ptr); - stack_thunk_ptr = NULL; - stack_thunk_top = NULL; - stack_thunk_save = NULL; + stack_thunk_ptr = nullptr; + stack_thunk_top = nullptr; + stack_thunk_save = nullptr; } } diff --git a/libraries/WiFi/src/StackThunk.h b/cores/rp2040/StackThunk.h similarity index 63% rename from libraries/WiFi/src/StackThunk.h rename to cores/rp2040/StackThunk.h index 52862a94f..c1bb1c540 100644 --- a/libraries/WiFi/src/StackThunk.h +++ b/cores/rp2040/StackThunk.h @@ -1,3 +1,22 @@ +/* + StackThunk - Implements a simple 2nd stack for BSSL and others + Copyright (c) 2022 Earle F. Philhower, III. All rights reserved. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + #pragma once #include diff --git a/cores/rp2040/Tone.cpp b/cores/rp2040/Tone.cpp index 2fde82545..a6355892b 100644 --- a/cores/rp2040/Tone.cpp +++ b/cores/rp2040/Tone.cpp @@ -28,6 +28,7 @@ typedef struct { pin_size_t pin; PIO pio; int sm; + int off; alarm_id_t alarm; } Tone; @@ -38,10 +39,18 @@ auto_init_mutex(_toneMutex); static PIOProgram _tone2Pgm(&tone2_program); static std::map _toneMap; +static inline bool pio_sm_get_enabled(PIO pio, uint sm) { + check_pio_param(pio); + check_sm_param(sm); + return (pio->ctrl & ~(1u << sm)) & (1 << sm); +} + int64_t _stopTonePIO(alarm_id_t id, void *user_data) { (void) id; Tone *tone = (Tone *)user_data; tone->alarm = 0; + digitalWrite(tone->pin, LOW); + pinMode(tone->pin, OUTPUT); pio_sm_set_enabled(tone->pio, tone->sm, false); return 0; } @@ -62,7 +71,7 @@ void tone(uint8_t pin, unsigned int frequency, unsigned long duration) { return; // Weird deadlock case } - int us = 1000000 / frequency / 2; + int us = 1'000'000 / frequency / 2; if (us < 5) { us = 5; } @@ -72,14 +81,12 @@ void tone(uint8_t pin, unsigned int frequency, unsigned long duration) { newTone = new Tone(); newTone->pin = pin; pinMode(pin, OUTPUT); - int off; - if (!_tone2Pgm.prepare(&newTone->pio, &newTone->sm, &off)) { + if (!_tone2Pgm.prepare(&newTone->pio, &newTone->sm, &newTone->off)) { DEBUGCORE("ERROR: tone unable to start, out of PIO resources\n"); // ERROR, no free slots delete newTone; return; } - tone2_program_init(newTone->pio, newTone->sm, off, pin); newTone->alarm = 0; } else { newTone = entry->second; @@ -88,6 +95,9 @@ void tone(uint8_t pin, unsigned int frequency, unsigned long duration) { newTone->alarm = 0; } } + if (!pio_sm_get_enabled(newTone->pio, newTone->sm)) { + tone2_program_init(newTone->pio, newTone->sm, newTone->off, pin); + } pio_sm_clear_fifos(newTone->pio, newTone->sm); // Remove any old updates that haven't yet taken effect pio_sm_put_blocking(newTone->pio, newTone->sm, RP2040::usToPIOCycles(us)); pio_sm_set_enabled(newTone->pio, newTone->sm, true); @@ -99,7 +109,7 @@ void tone(uint8_t pin, unsigned int frequency, unsigned long duration) { if (ret > 0) { newTone->alarm = ret; } else { - DEBUGCORE("ERROR: Unable to allocate timer for tone(%d, %d, %d)\n", + DEBUGCORE("ERROR: Unable to allocate timer for tone(%d, %d, %lu)\n", pin, frequency, duration); } } diff --git a/cores/rp2040/WMath.cpp b/cores/rp2040/WMath.cpp index ca9366595..43cd301a9 100644 --- a/cores/rp2040/WMath.cpp +++ b/cores/rp2040/WMath.cpp @@ -16,8 +16,8 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "stdlib.h" -#include "stdint.h" +#include +#include void randomSeed(uint32_t dwSeed) { if (dwSeed != 0) { diff --git a/cores/rp2040/WString.h b/cores/rp2040/WString.h new file mode 100644 index 000000000..663db3068 --- /dev/null +++ b/cores/rp2040/WString.h @@ -0,0 +1 @@ +#include "api/String.h" diff --git a/cores/rp2040/_freertos.cpp b/cores/rp2040/_freertos.cpp new file mode 100644 index 000000000..221f56dab --- /dev/null +++ b/cores/rp2040/_freertos.cpp @@ -0,0 +1,104 @@ +/* + _freertos.cpp - Internal core definitions for FreeRTOS + + Copyright (c) 2022 Earle F. Philhower, III + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include "_freertos.h" +#include +#include +#include "Arduino.h" + +typedef struct { + mutex_t *src; + SemaphoreHandle_t dst; +} FMMap; + +static FMMap *_map = nullptr; +SemaphoreHandle_t __get_freertos_mutex_for_ptr(mutex_t *m, bool recursive) { + if (!_map) { + _map = (FMMap *)calloc(sizeof(FMMap), 16); + } + // Pre-existing map + for (int i = 0; i < 16; i++) { + if (m == _map[i].src) { + return _map[i].dst; + } + } + + for (int i = 0; i < 16; i++) { + if (_map[i].src == nullptr) { + // Make a new mutex + SemaphoreHandle_t fm; + if (recursive) { + fm = _freertos_recursive_mutex_create(); + } else { + fm = __freertos_mutex_create(); + } + if (fm == nullptr) { + return nullptr; + } + + _map[i].src = m; + _map[i].dst = fm; + return fm; + } + } + return nullptr; // Need to make space for more mutex maps! +} + + +// The HW Random code needs a precise sleep_until() in order to assure it +// grabs the ROSC bit when it wants. Unfortunately, under FreeRTOS the +// sleep_until() becomes imprecise and the "did I get the bit when I wanted" +// check in the pico_rand code always fails and you get an infinite loop. + +// This block wraps the 2 get_rand calls to set a flag to convert +// sleep_until() (which can do a task swap and cause bad timing) into a +// busy wait. + +extern "C" { + static bool __inRand = false; + + extern uint64_t __real_get_rand_64(); + uint64_t __wrap_get_rand_64() { + if (__isFreeRTOS) { + rp2040.idleOtherCore(); + __inRand = true; + auto r = __real_get_rand_64(); + __inRand = false; + rp2040.resumeOtherCore(); + return r; + } else { + return __real_get_rand_64(); + } + } + + uint32_t __wrap_get_rand_32() { + return (uint32_t) __wrap_get_rand_64(); + } + + extern void __real_sleep_until(absolute_time_t t); + void __wrap_sleep_until(absolute_time_t t) { + if (__inRand) { + busy_wait_until(t); + } else { + __real_sleep_until(t); + } + } + +} diff --git a/cores/rp2040/_freertos.h b/cores/rp2040/_freertos.h new file mode 100644 index 000000000..04db74ca7 --- /dev/null +++ b/cores/rp2040/_freertos.h @@ -0,0 +1,56 @@ +/* + _freertos.h - Internal core definitions for FreeRTOS + + Copyright (c) 2022 Earle F. Philhower, III + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#pragma once +#include + +// Cannot include refs to FreeRTOS's actual semaphore calls because they +// are implemented as macros, so we have a wrapper in our variant hook +// to handle it. + +extern bool __isFreeRTOS; + +// FreeRTOS has been set up +extern volatile bool __freeRTOSinitted; + +extern "C" { +#ifndef INC_FREERTOS_H + struct QueueDefinition; /* Using old naming convention so as not to break kernel aware debuggers. */ + typedef struct QueueDefinition * QueueHandle_t; + typedef QueueHandle_t SemaphoreHandle_t; +#endif + + extern SemaphoreHandle_t __freertos_mutex_create() __attribute__((weak)); + extern SemaphoreHandle_t _freertos_recursive_mutex_create() __attribute__((weak)); + + extern void __freertos_mutex_take(SemaphoreHandle_t mtx) __attribute__((weak)); + extern void __freertos_mutex_take_from_isr(SemaphoreHandle_t mtx) __attribute__((weak)); + extern int __freertos_mutex_try_take(SemaphoreHandle_t mtx) __attribute__((weak)); + extern void __freertos_mutex_give(SemaphoreHandle_t mtx) __attribute__((weak)); + extern void __freertos_mutex_give_from_isr(SemaphoreHandle_t mtx) __attribute__((weak)); + + extern void __freertos_recursive_mutex_take(SemaphoreHandle_t mtx) __attribute__((weak)); + extern int __freertos_recursive_mutex_try_take(SemaphoreHandle_t mtx) __attribute__((weak)); + extern void __freertos_recursive_mutex_give(SemaphoreHandle_t mtx) __attribute__((weak)); + + extern void __freertos_idle_other_core() __attribute__((weak)); + extern void __freertos_resume_other_core() __attribute__((weak)); +} +extern SemaphoreHandle_t __get_freertos_mutex_for_ptr(mutex_t *m, bool recursive = false); diff --git a/cores/rp2040/_needsbt.h b/cores/rp2040/_needsbt.h new file mode 100644 index 000000000..14c1b73b1 --- /dev/null +++ b/cores/rp2040/_needsbt.h @@ -0,0 +1,7 @@ +// Simple helper header to ensure pico libs support ?BT + +#ifndef ENABLE_CLASSIC +#define ENABLE_CLASSIC 0 +#endif + +static_assert(ENABLE_CLASSIC, "This library needs Bluetooth enabled. Use the 'Tools->IP/Bluetooth Stack' menu in the IDE to enable it."); diff --git a/cores/rp2040/api/ArduinoAPI.h b/cores/rp2040/api/ArduinoAPI.h index 699df1dd4..da5278836 100644 --- a/cores/rp2040/api/ArduinoAPI.h +++ b/cores/rp2040/api/ArduinoAPI.h @@ -1,57 +1,2 @@ -/* - Arduino API main include - Copyright (c) 2016 Arduino LLC. All right reserved. - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -*/ - -#ifndef ARDUINO_API_H -#define ARDUINO_API_H - -// version 1.2.0 -#define ARDUINO_API_VERSION 10200 - -#include "Binary.h" - -#ifdef __cplusplus -#include "Interrupts.h" -#include "IPAddress.h" -#include "Print.h" -#include "Printable.h" -#include "PluggableUSB.h" -#include "Server.h" -#include "String.h" -#include "Stream.h" -#include "Udp.h" -#include "USBAPI.h" -#include "WCharacter.h" -#endif - -/* Standard C library includes */ -#include -#include -#include -#include -#include - -// Misc Arduino core functions -#include "Common.h" - -#ifdef __cplusplus -// Compatibility layer for older code -#include "Compat.h" -#endif - -#endif +#pragma once +#include "../../../ArduinoCore-API/api/ArduinoAPI.h" diff --git a/cores/rp2040/api/Binary.h b/cores/rp2040/api/Binary.h index 947542e38..1c1c91dc7 100644 --- a/cores/rp2040/api/Binary.h +++ b/cores/rp2040/api/Binary.h @@ -1,552 +1,2 @@ -/* - binary.h - Definitions for binary constants - Deprecated -- use 0b binary literals instead - Copyright (c) 2006 David A. Mellis. All right reserved. - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -*/ - -#ifndef Binary_h -#define Binary_h - -/* If supported, 0b binary literals are preferable to these constants. - * In that case, warn the user about these being deprecated (if possible). */ -#if __cplusplus >= 201402L - /* C++14 introduces binary literals; C++11 introduces [[deprecated()]] */ - #define DEPRECATED(x) [[deprecated("use " #x " instead")]] -#elif __GNUC__ >= 6 - /* GCC 4.3 supports binary literals; GCC 6 supports __deprecated__ on enums*/ - #define DEPRECATED(x) __attribute__ ((__deprecated__ ("use " #x " instead"))) -#else - /* binary literals not supported, or "deprecated" warning not displayable */ - #define DEPRECATED(x) -#endif - -enum { - B0 DEPRECATED(0b0 ) = 0, - B00 DEPRECATED(0b00 ) = 0, - B000 DEPRECATED(0b000 ) = 0, - B0000 DEPRECATED(0b0000 ) = 0, - B00000 DEPRECATED(0b00000 ) = 0, - B000000 DEPRECATED(0b000000 ) = 0, - B0000000 DEPRECATED(0b0000000 ) = 0, - B00000000 DEPRECATED(0b00000000) = 0, - B1 DEPRECATED(0b1 ) = 1, - B01 DEPRECATED(0b01 ) = 1, - B001 DEPRECATED(0b001 ) = 1, - B0001 DEPRECATED(0b0001 ) = 1, - B00001 DEPRECATED(0b00001 ) = 1, - B000001 DEPRECATED(0b000001 ) = 1, - B0000001 DEPRECATED(0b0000001 ) = 1, - B00000001 DEPRECATED(0b00000001) = 1, - B10 DEPRECATED(0b10 ) = 2, - B010 DEPRECATED(0b010 ) = 2, - B0010 DEPRECATED(0b0010 ) = 2, - B00010 DEPRECATED(0b00010 ) = 2, - B000010 DEPRECATED(0b000010 ) = 2, - B0000010 DEPRECATED(0b0000010 ) = 2, - B00000010 DEPRECATED(0b00000010) = 2, - B11 DEPRECATED(0b11 ) = 3, - B011 DEPRECATED(0b011 ) = 3, - B0011 DEPRECATED(0b0011 ) = 3, - B00011 DEPRECATED(0b00011 ) = 3, - B000011 DEPRECATED(0b000011 ) = 3, - B0000011 DEPRECATED(0b0000011 ) = 3, - B00000011 DEPRECATED(0b00000011) = 3, - B100 DEPRECATED(0b100 ) = 4, - B0100 DEPRECATED(0b0100 ) = 4, - B00100 DEPRECATED(0b00100 ) = 4, - B000100 DEPRECATED(0b000100 ) = 4, - B0000100 DEPRECATED(0b0000100 ) = 4, - B00000100 DEPRECATED(0b00000100) = 4, - B101 DEPRECATED(0b101 ) = 5, - B0101 DEPRECATED(0b0101 ) = 5, - B00101 DEPRECATED(0b00101 ) = 5, - B000101 DEPRECATED(0b000101 ) = 5, - B0000101 DEPRECATED(0b0000101 ) = 5, - B00000101 DEPRECATED(0b00000101) = 5, - B110 DEPRECATED(0b110 ) = 6, - B0110 DEPRECATED(0b0110 ) = 6, - B00110 DEPRECATED(0b00110 ) = 6, - B000110 DEPRECATED(0b000110 ) = 6, - B0000110 DEPRECATED(0b0000110 ) = 6, - B00000110 DEPRECATED(0b00000110) = 6, - B111 DEPRECATED(0b111 ) = 7, - B0111 DEPRECATED(0b0111 ) = 7, - B00111 DEPRECATED(0b00111 ) = 7, - B000111 DEPRECATED(0b000111 ) = 7, - B0000111 DEPRECATED(0b0000111 ) = 7, - B00000111 DEPRECATED(0b00000111) = 7, - B1000 DEPRECATED(0b1000 ) = 8, - B01000 DEPRECATED(0b01000 ) = 8, - B001000 DEPRECATED(0b001000 ) = 8, - B0001000 DEPRECATED(0b0001000 ) = 8, - B00001000 DEPRECATED(0b00001000) = 8, - B1001 DEPRECATED(0b1001 ) = 9, - B01001 DEPRECATED(0b01001 ) = 9, - B001001 DEPRECATED(0b001001 ) = 9, - B0001001 DEPRECATED(0b0001001 ) = 9, - B00001001 DEPRECATED(0b00001001) = 9, - B1010 DEPRECATED(0b1010 ) = 10, - B01010 DEPRECATED(0b01010 ) = 10, - B001010 DEPRECATED(0b001010 ) = 10, - B0001010 DEPRECATED(0b0001010 ) = 10, - B00001010 DEPRECATED(0b00001010) = 10, - B1011 DEPRECATED(0b1011 ) = 11, - B01011 DEPRECATED(0b01011 ) = 11, - B001011 DEPRECATED(0b001011 ) = 11, - B0001011 DEPRECATED(0b0001011 ) = 11, - B00001011 DEPRECATED(0b00001011) = 11, - B1100 DEPRECATED(0b1100 ) = 12, - B01100 DEPRECATED(0b01100 ) = 12, - B001100 DEPRECATED(0b001100 ) = 12, - B0001100 DEPRECATED(0b0001100 ) = 12, - B00001100 DEPRECATED(0b00001100) = 12, - B1101 DEPRECATED(0b1101 ) = 13, - B01101 DEPRECATED(0b01101 ) = 13, - B001101 DEPRECATED(0b001101 ) = 13, - B0001101 DEPRECATED(0b0001101 ) = 13, - B00001101 DEPRECATED(0b00001101) = 13, - B1110 DEPRECATED(0b1110 ) = 14, - B01110 DEPRECATED(0b01110 ) = 14, - B001110 DEPRECATED(0b001110 ) = 14, - B0001110 DEPRECATED(0b0001110 ) = 14, - B00001110 DEPRECATED(0b00001110) = 14, - B1111 DEPRECATED(0b1111 ) = 15, - B01111 DEPRECATED(0b01111 ) = 15, - B001111 DEPRECATED(0b001111 ) = 15, - B0001111 DEPRECATED(0b0001111 ) = 15, - B00001111 DEPRECATED(0b00001111) = 15, - B10000 DEPRECATED(0b10000 ) = 16, - B010000 DEPRECATED(0b010000 ) = 16, - B0010000 DEPRECATED(0b0010000 ) = 16, - B00010000 DEPRECATED(0b00010000) = 16, - B10001 DEPRECATED(0b10001 ) = 17, - B010001 DEPRECATED(0b010001 ) = 17, - B0010001 DEPRECATED(0b0010001 ) = 17, - B00010001 DEPRECATED(0b00010001) = 17, - B10010 DEPRECATED(0b10010 ) = 18, - B010010 DEPRECATED(0b010010 ) = 18, - B0010010 DEPRECATED(0b0010010 ) = 18, - B00010010 DEPRECATED(0b00010010) = 18, - B10011 DEPRECATED(0b10011 ) = 19, - B010011 DEPRECATED(0b010011 ) = 19, - B0010011 DEPRECATED(0b0010011 ) = 19, - B00010011 DEPRECATED(0b00010011) = 19, - B10100 DEPRECATED(0b10100 ) = 20, - B010100 DEPRECATED(0b010100 ) = 20, - B0010100 DEPRECATED(0b0010100 ) = 20, - B00010100 DEPRECATED(0b00010100) = 20, - B10101 DEPRECATED(0b10101 ) = 21, - B010101 DEPRECATED(0b010101 ) = 21, - B0010101 DEPRECATED(0b0010101 ) = 21, - B00010101 DEPRECATED(0b00010101) = 21, - B10110 DEPRECATED(0b10110 ) = 22, - B010110 DEPRECATED(0b010110 ) = 22, - B0010110 DEPRECATED(0b0010110 ) = 22, - B00010110 DEPRECATED(0b00010110) = 22, - B10111 DEPRECATED(0b10111 ) = 23, - B010111 DEPRECATED(0b010111 ) = 23, - B0010111 DEPRECATED(0b0010111 ) = 23, - B00010111 DEPRECATED(0b00010111) = 23, - B11000 DEPRECATED(0b11000 ) = 24, - B011000 DEPRECATED(0b011000 ) = 24, - B0011000 DEPRECATED(0b0011000 ) = 24, - B00011000 DEPRECATED(0b00011000) = 24, - B11001 DEPRECATED(0b11001 ) = 25, - B011001 DEPRECATED(0b011001 ) = 25, - B0011001 DEPRECATED(0b0011001 ) = 25, - B00011001 DEPRECATED(0b00011001) = 25, - B11010 DEPRECATED(0b11010 ) = 26, - B011010 DEPRECATED(0b011010 ) = 26, - B0011010 DEPRECATED(0b0011010 ) = 26, - B00011010 DEPRECATED(0b00011010) = 26, - B11011 DEPRECATED(0b11011 ) = 27, - B011011 DEPRECATED(0b011011 ) = 27, - B0011011 DEPRECATED(0b0011011 ) = 27, - B00011011 DEPRECATED(0b00011011) = 27, - B11100 DEPRECATED(0b11100 ) = 28, - B011100 DEPRECATED(0b011100 ) = 28, - B0011100 DEPRECATED(0b0011100 ) = 28, - B00011100 DEPRECATED(0b00011100) = 28, - B11101 DEPRECATED(0b11101 ) = 29, - B011101 DEPRECATED(0b011101 ) = 29, - B0011101 DEPRECATED(0b0011101 ) = 29, - B00011101 DEPRECATED(0b00011101) = 29, - B11110 DEPRECATED(0b11110 ) = 30, - B011110 DEPRECATED(0b011110 ) = 30, - B0011110 DEPRECATED(0b0011110 ) = 30, - B00011110 DEPRECATED(0b00011110) = 30, - B11111 DEPRECATED(0b11111 ) = 31, - B011111 DEPRECATED(0b011111 ) = 31, - B0011111 DEPRECATED(0b0011111 ) = 31, - B00011111 DEPRECATED(0b00011111) = 31, - B100000 DEPRECATED(0b100000 ) = 32, - B0100000 DEPRECATED(0b0100000 ) = 32, - B00100000 DEPRECATED(0b00100000) = 32, - B100001 DEPRECATED(0b100001 ) = 33, - B0100001 DEPRECATED(0b0100001 ) = 33, - B00100001 DEPRECATED(0b00100001) = 33, - B100010 DEPRECATED(0b100010 ) = 34, - B0100010 DEPRECATED(0b0100010 ) = 34, - B00100010 DEPRECATED(0b00100010) = 34, - B100011 DEPRECATED(0b100011 ) = 35, - B0100011 DEPRECATED(0b0100011 ) = 35, - B00100011 DEPRECATED(0b00100011) = 35, - B100100 DEPRECATED(0b100100 ) = 36, - B0100100 DEPRECATED(0b0100100 ) = 36, - B00100100 DEPRECATED(0b00100100) = 36, - B100101 DEPRECATED(0b100101 ) = 37, - B0100101 DEPRECATED(0b0100101 ) = 37, - B00100101 DEPRECATED(0b00100101) = 37, - B100110 DEPRECATED(0b100110 ) = 38, - B0100110 DEPRECATED(0b0100110 ) = 38, - B00100110 DEPRECATED(0b00100110) = 38, - B100111 DEPRECATED(0b100111 ) = 39, - B0100111 DEPRECATED(0b0100111 ) = 39, - B00100111 DEPRECATED(0b00100111) = 39, - B101000 DEPRECATED(0b101000 ) = 40, - B0101000 DEPRECATED(0b0101000 ) = 40, - B00101000 DEPRECATED(0b00101000) = 40, - B101001 DEPRECATED(0b101001 ) = 41, - B0101001 DEPRECATED(0b0101001 ) = 41, - B00101001 DEPRECATED(0b00101001) = 41, - B101010 DEPRECATED(0b101010 ) = 42, - B0101010 DEPRECATED(0b0101010 ) = 42, - B00101010 DEPRECATED(0b00101010) = 42, - B101011 DEPRECATED(0b101011 ) = 43, - B0101011 DEPRECATED(0b0101011 ) = 43, - B00101011 DEPRECATED(0b00101011) = 43, - B101100 DEPRECATED(0b101100 ) = 44, - B0101100 DEPRECATED(0b0101100 ) = 44, - B00101100 DEPRECATED(0b00101100) = 44, - B101101 DEPRECATED(0b101101 ) = 45, - B0101101 DEPRECATED(0b0101101 ) = 45, - B00101101 DEPRECATED(0b00101101) = 45, - B101110 DEPRECATED(0b101110 ) = 46, - B0101110 DEPRECATED(0b0101110 ) = 46, - B00101110 DEPRECATED(0b00101110) = 46, - B101111 DEPRECATED(0b101111 ) = 47, - B0101111 DEPRECATED(0b0101111 ) = 47, - B00101111 DEPRECATED(0b00101111) = 47, - B110000 DEPRECATED(0b110000 ) = 48, - B0110000 DEPRECATED(0b0110000 ) = 48, - B00110000 DEPRECATED(0b00110000) = 48, - B110001 DEPRECATED(0b110001 ) = 49, - B0110001 DEPRECATED(0b0110001 ) = 49, - B00110001 DEPRECATED(0b00110001) = 49, - B110010 DEPRECATED(0b110010 ) = 50, - B0110010 DEPRECATED(0b0110010 ) = 50, - B00110010 DEPRECATED(0b00110010) = 50, - B110011 DEPRECATED(0b110011 ) = 51, - B0110011 DEPRECATED(0b0110011 ) = 51, - B00110011 DEPRECATED(0b00110011) = 51, - B110100 DEPRECATED(0b110100 ) = 52, - B0110100 DEPRECATED(0b0110100 ) = 52, - B00110100 DEPRECATED(0b00110100) = 52, - B110101 DEPRECATED(0b110101 ) = 53, - B0110101 DEPRECATED(0b0110101 ) = 53, - B00110101 DEPRECATED(0b00110101) = 53, - B110110 DEPRECATED(0b110110 ) = 54, - B0110110 DEPRECATED(0b0110110 ) = 54, - B00110110 DEPRECATED(0b00110110) = 54, - B110111 DEPRECATED(0b110111 ) = 55, - B0110111 DEPRECATED(0b0110111 ) = 55, - B00110111 DEPRECATED(0b00110111) = 55, - B111000 DEPRECATED(0b111000 ) = 56, - B0111000 DEPRECATED(0b0111000 ) = 56, - B00111000 DEPRECATED(0b00111000) = 56, - B111001 DEPRECATED(0b111001 ) = 57, - B0111001 DEPRECATED(0b0111001 ) = 57, - B00111001 DEPRECATED(0b00111001) = 57, - B111010 DEPRECATED(0b111010 ) = 58, - B0111010 DEPRECATED(0b0111010 ) = 58, - B00111010 DEPRECATED(0b00111010) = 58, - B111011 DEPRECATED(0b111011 ) = 59, - B0111011 DEPRECATED(0b0111011 ) = 59, - B00111011 DEPRECATED(0b00111011) = 59, - B111100 DEPRECATED(0b111100 ) = 60, - B0111100 DEPRECATED(0b0111100 ) = 60, - B00111100 DEPRECATED(0b00111100) = 60, - B111101 DEPRECATED(0b111101 ) = 61, - B0111101 DEPRECATED(0b0111101 ) = 61, - B00111101 DEPRECATED(0b00111101) = 61, - B111110 DEPRECATED(0b111110 ) = 62, - B0111110 DEPRECATED(0b0111110 ) = 62, - B00111110 DEPRECATED(0b00111110) = 62, - B111111 DEPRECATED(0b111111 ) = 63, - B0111111 DEPRECATED(0b0111111 ) = 63, - B00111111 DEPRECATED(0b00111111) = 63, - B1000000 DEPRECATED(0b1000000 ) = 64, - B01000000 DEPRECATED(0b01000000) = 64, - B1000001 DEPRECATED(0b1000001 ) = 65, - B01000001 DEPRECATED(0b01000001) = 65, - B1000010 DEPRECATED(0b1000010 ) = 66, - B01000010 DEPRECATED(0b01000010) = 66, - B1000011 DEPRECATED(0b1000011 ) = 67, - B01000011 DEPRECATED(0b01000011) = 67, - B1000100 DEPRECATED(0b1000100 ) = 68, - B01000100 DEPRECATED(0b01000100) = 68, - B1000101 DEPRECATED(0b1000101 ) = 69, - B01000101 DEPRECATED(0b01000101) = 69, - B1000110 DEPRECATED(0b1000110 ) = 70, - B01000110 DEPRECATED(0b01000110) = 70, - B1000111 DEPRECATED(0b1000111 ) = 71, - B01000111 DEPRECATED(0b01000111) = 71, - B1001000 DEPRECATED(0b1001000 ) = 72, - B01001000 DEPRECATED(0b01001000) = 72, - B1001001 DEPRECATED(0b1001001 ) = 73, - B01001001 DEPRECATED(0b01001001) = 73, - B1001010 DEPRECATED(0b1001010 ) = 74, - B01001010 DEPRECATED(0b01001010) = 74, - B1001011 DEPRECATED(0b1001011 ) = 75, - B01001011 DEPRECATED(0b01001011) = 75, - B1001100 DEPRECATED(0b1001100 ) = 76, - B01001100 DEPRECATED(0b01001100) = 76, - B1001101 DEPRECATED(0b1001101 ) = 77, - B01001101 DEPRECATED(0b01001101) = 77, - B1001110 DEPRECATED(0b1001110 ) = 78, - B01001110 DEPRECATED(0b01001110) = 78, - B1001111 DEPRECATED(0b1001111 ) = 79, - B01001111 DEPRECATED(0b01001111) = 79, - B1010000 DEPRECATED(0b1010000 ) = 80, - B01010000 DEPRECATED(0b01010000) = 80, - B1010001 DEPRECATED(0b1010001 ) = 81, - B01010001 DEPRECATED(0b01010001) = 81, - B1010010 DEPRECATED(0b1010010 ) = 82, - B01010010 DEPRECATED(0b01010010) = 82, - B1010011 DEPRECATED(0b1010011 ) = 83, - B01010011 DEPRECATED(0b01010011) = 83, - B1010100 DEPRECATED(0b1010100 ) = 84, - B01010100 DEPRECATED(0b01010100) = 84, - B1010101 DEPRECATED(0b1010101 ) = 85, - B01010101 DEPRECATED(0b01010101) = 85, - B1010110 DEPRECATED(0b1010110 ) = 86, - B01010110 DEPRECATED(0b01010110) = 86, - B1010111 DEPRECATED(0b1010111 ) = 87, - B01010111 DEPRECATED(0b01010111) = 87, - B1011000 DEPRECATED(0b1011000 ) = 88, - B01011000 DEPRECATED(0b01011000) = 88, - B1011001 DEPRECATED(0b1011001 ) = 89, - B01011001 DEPRECATED(0b01011001) = 89, - B1011010 DEPRECATED(0b1011010 ) = 90, - B01011010 DEPRECATED(0b01011010) = 90, - B1011011 DEPRECATED(0b1011011 ) = 91, - B01011011 DEPRECATED(0b01011011) = 91, - B1011100 DEPRECATED(0b1011100 ) = 92, - B01011100 DEPRECATED(0b01011100) = 92, - B1011101 DEPRECATED(0b1011101 ) = 93, - B01011101 DEPRECATED(0b01011101) = 93, - B1011110 DEPRECATED(0b1011110 ) = 94, - B01011110 DEPRECATED(0b01011110) = 94, - B1011111 DEPRECATED(0b1011111 ) = 95, - B01011111 DEPRECATED(0b01011111) = 95, - B1100000 DEPRECATED(0b1100000 ) = 96, - B01100000 DEPRECATED(0b01100000) = 96, - B1100001 DEPRECATED(0b1100001 ) = 97, - B01100001 DEPRECATED(0b01100001) = 97, - B1100010 DEPRECATED(0b1100010 ) = 98, - B01100010 DEPRECATED(0b01100010) = 98, - B1100011 DEPRECATED(0b1100011 ) = 99, - B01100011 DEPRECATED(0b01100011) = 99, - B1100100 DEPRECATED(0b1100100 ) = 100, - B01100100 DEPRECATED(0b01100100) = 100, - B1100101 DEPRECATED(0b1100101 ) = 101, - B01100101 DEPRECATED(0b01100101) = 101, - B1100110 DEPRECATED(0b1100110 ) = 102, - B01100110 DEPRECATED(0b01100110) = 102, - B1100111 DEPRECATED(0b1100111 ) = 103, - B01100111 DEPRECATED(0b01100111) = 103, - B1101000 DEPRECATED(0b1101000 ) = 104, - B01101000 DEPRECATED(0b01101000) = 104, - B1101001 DEPRECATED(0b1101001 ) = 105, - B01101001 DEPRECATED(0b01101001) = 105, - B1101010 DEPRECATED(0b1101010 ) = 106, - B01101010 DEPRECATED(0b01101010) = 106, - B1101011 DEPRECATED(0b1101011 ) = 107, - B01101011 DEPRECATED(0b01101011) = 107, - B1101100 DEPRECATED(0b1101100 ) = 108, - B01101100 DEPRECATED(0b01101100) = 108, - B1101101 DEPRECATED(0b1101101 ) = 109, - B01101101 DEPRECATED(0b01101101) = 109, - B1101110 DEPRECATED(0b1101110 ) = 110, - B01101110 DEPRECATED(0b01101110) = 110, - B1101111 DEPRECATED(0b1101111 ) = 111, - B01101111 DEPRECATED(0b01101111) = 111, - B1110000 DEPRECATED(0b1110000 ) = 112, - B01110000 DEPRECATED(0b01110000) = 112, - B1110001 DEPRECATED(0b1110001 ) = 113, - B01110001 DEPRECATED(0b01110001) = 113, - B1110010 DEPRECATED(0b1110010 ) = 114, - B01110010 DEPRECATED(0b01110010) = 114, - B1110011 DEPRECATED(0b1110011 ) = 115, - B01110011 DEPRECATED(0b01110011) = 115, - B1110100 DEPRECATED(0b1110100 ) = 116, - B01110100 DEPRECATED(0b01110100) = 116, - B1110101 DEPRECATED(0b1110101 ) = 117, - B01110101 DEPRECATED(0b01110101) = 117, - B1110110 DEPRECATED(0b1110110 ) = 118, - B01110110 DEPRECATED(0b01110110) = 118, - B1110111 DEPRECATED(0b1110111 ) = 119, - B01110111 DEPRECATED(0b01110111) = 119, - B1111000 DEPRECATED(0b1111000 ) = 120, - B01111000 DEPRECATED(0b01111000) = 120, - B1111001 DEPRECATED(0b1111001 ) = 121, - B01111001 DEPRECATED(0b01111001) = 121, - B1111010 DEPRECATED(0b1111010 ) = 122, - B01111010 DEPRECATED(0b01111010) = 122, - B1111011 DEPRECATED(0b1111011 ) = 123, - B01111011 DEPRECATED(0b01111011) = 123, - B1111100 DEPRECATED(0b1111100 ) = 124, - B01111100 DEPRECATED(0b01111100) = 124, - B1111101 DEPRECATED(0b1111101 ) = 125, - B01111101 DEPRECATED(0b01111101) = 125, - B1111110 DEPRECATED(0b1111110 ) = 126, - B01111110 DEPRECATED(0b01111110) = 126, - B1111111 DEPRECATED(0b1111111 ) = 127, - B01111111 DEPRECATED(0b01111111) = 127, - B10000000 DEPRECATED(0b10000000) = 128, - B10000001 DEPRECATED(0b10000001) = 129, - B10000010 DEPRECATED(0b10000010) = 130, - B10000011 DEPRECATED(0b10000011) = 131, - B10000100 DEPRECATED(0b10000100) = 132, - B10000101 DEPRECATED(0b10000101) = 133, - B10000110 DEPRECATED(0b10000110) = 134, - B10000111 DEPRECATED(0b10000111) = 135, - B10001000 DEPRECATED(0b10001000) = 136, - B10001001 DEPRECATED(0b10001001) = 137, - B10001010 DEPRECATED(0b10001010) = 138, - B10001011 DEPRECATED(0b10001011) = 139, - B10001100 DEPRECATED(0b10001100) = 140, - B10001101 DEPRECATED(0b10001101) = 141, - B10001110 DEPRECATED(0b10001110) = 142, - B10001111 DEPRECATED(0b10001111) = 143, - B10010000 DEPRECATED(0b10010000) = 144, - B10010001 DEPRECATED(0b10010001) = 145, - B10010010 DEPRECATED(0b10010010) = 146, - B10010011 DEPRECATED(0b10010011) = 147, - B10010100 DEPRECATED(0b10010100) = 148, - B10010101 DEPRECATED(0b10010101) = 149, - B10010110 DEPRECATED(0b10010110) = 150, - B10010111 DEPRECATED(0b10010111) = 151, - B10011000 DEPRECATED(0b10011000) = 152, - B10011001 DEPRECATED(0b10011001) = 153, - B10011010 DEPRECATED(0b10011010) = 154, - B10011011 DEPRECATED(0b10011011) = 155, - B10011100 DEPRECATED(0b10011100) = 156, - B10011101 DEPRECATED(0b10011101) = 157, - B10011110 DEPRECATED(0b10011110) = 158, - B10011111 DEPRECATED(0b10011111) = 159, - B10100000 DEPRECATED(0b10100000) = 160, - B10100001 DEPRECATED(0b10100001) = 161, - B10100010 DEPRECATED(0b10100010) = 162, - B10100011 DEPRECATED(0b10100011) = 163, - B10100100 DEPRECATED(0b10100100) = 164, - B10100101 DEPRECATED(0b10100101) = 165, - B10100110 DEPRECATED(0b10100110) = 166, - B10100111 DEPRECATED(0b10100111) = 167, - B10101000 DEPRECATED(0b10101000) = 168, - B10101001 DEPRECATED(0b10101001) = 169, - B10101010 DEPRECATED(0b10101010) = 170, - B10101011 DEPRECATED(0b10101011) = 171, - B10101100 DEPRECATED(0b10101100) = 172, - B10101101 DEPRECATED(0b10101101) = 173, - B10101110 DEPRECATED(0b10101110) = 174, - B10101111 DEPRECATED(0b10101111) = 175, - B10110000 DEPRECATED(0b10110000) = 176, - B10110001 DEPRECATED(0b10110001) = 177, - B10110010 DEPRECATED(0b10110010) = 178, - B10110011 DEPRECATED(0b10110011) = 179, - B10110100 DEPRECATED(0b10110100) = 180, - B10110101 DEPRECATED(0b10110101) = 181, - B10110110 DEPRECATED(0b10110110) = 182, - B10110111 DEPRECATED(0b10110111) = 183, - B10111000 DEPRECATED(0b10111000) = 184, - B10111001 DEPRECATED(0b10111001) = 185, - B10111010 DEPRECATED(0b10111010) = 186, - B10111011 DEPRECATED(0b10111011) = 187, - B10111100 DEPRECATED(0b10111100) = 188, - B10111101 DEPRECATED(0b10111101) = 189, - B10111110 DEPRECATED(0b10111110) = 190, - B10111111 DEPRECATED(0b10111111) = 191, - B11000000 DEPRECATED(0b11000000) = 192, - B11000001 DEPRECATED(0b11000001) = 193, - B11000010 DEPRECATED(0b11000010) = 194, - B11000011 DEPRECATED(0b11000011) = 195, - B11000100 DEPRECATED(0b11000100) = 196, - B11000101 DEPRECATED(0b11000101) = 197, - B11000110 DEPRECATED(0b11000110) = 198, - B11000111 DEPRECATED(0b11000111) = 199, - B11001000 DEPRECATED(0b11001000) = 200, - B11001001 DEPRECATED(0b11001001) = 201, - B11001010 DEPRECATED(0b11001010) = 202, - B11001011 DEPRECATED(0b11001011) = 203, - B11001100 DEPRECATED(0b11001100) = 204, - B11001101 DEPRECATED(0b11001101) = 205, - B11001110 DEPRECATED(0b11001110) = 206, - B11001111 DEPRECATED(0b11001111) = 207, - B11010000 DEPRECATED(0b11010000) = 208, - B11010001 DEPRECATED(0b11010001) = 209, - B11010010 DEPRECATED(0b11010010) = 210, - B11010011 DEPRECATED(0b11010011) = 211, - B11010100 DEPRECATED(0b11010100) = 212, - B11010101 DEPRECATED(0b11010101) = 213, - B11010110 DEPRECATED(0b11010110) = 214, - B11010111 DEPRECATED(0b11010111) = 215, - B11011000 DEPRECATED(0b11011000) = 216, - B11011001 DEPRECATED(0b11011001) = 217, - B11011010 DEPRECATED(0b11011010) = 218, - B11011011 DEPRECATED(0b11011011) = 219, - B11011100 DEPRECATED(0b11011100) = 220, - B11011101 DEPRECATED(0b11011101) = 221, - B11011110 DEPRECATED(0b11011110) = 222, - B11011111 DEPRECATED(0b11011111) = 223, - B11100000 DEPRECATED(0b11100000) = 224, - B11100001 DEPRECATED(0b11100001) = 225, - B11100010 DEPRECATED(0b11100010) = 226, - B11100011 DEPRECATED(0b11100011) = 227, - B11100100 DEPRECATED(0b11100100) = 228, - B11100101 DEPRECATED(0b11100101) = 229, - B11100110 DEPRECATED(0b11100110) = 230, - B11100111 DEPRECATED(0b11100111) = 231, - B11101000 DEPRECATED(0b11101000) = 232, - B11101001 DEPRECATED(0b11101001) = 233, - B11101010 DEPRECATED(0b11101010) = 234, - B11101011 DEPRECATED(0b11101011) = 235, - B11101100 DEPRECATED(0b11101100) = 236, - B11101101 DEPRECATED(0b11101101) = 237, - B11101110 DEPRECATED(0b11101110) = 238, - B11101111 DEPRECATED(0b11101111) = 239, - B11110000 DEPRECATED(0b11110000) = 240, - B11110001 DEPRECATED(0b11110001) = 241, - B11110010 DEPRECATED(0b11110010) = 242, - B11110011 DEPRECATED(0b11110011) = 243, - B11110100 DEPRECATED(0b11110100) = 244, - B11110101 DEPRECATED(0b11110101) = 245, - B11110110 DEPRECATED(0b11110110) = 246, - B11110111 DEPRECATED(0b11110111) = 247, - B11111000 DEPRECATED(0b11111000) = 248, - B11111001 DEPRECATED(0b11111001) = 249, - B11111010 DEPRECATED(0b11111010) = 250, - B11111011 DEPRECATED(0b11111011) = 251, - B11111100 DEPRECATED(0b11111100) = 252, - B11111101 DEPRECATED(0b11111101) = 253, - B11111110 DEPRECATED(0b11111110) = 254, - B11111111 DEPRECATED(0b11111111) = 255 -}; - -#undef DEPRECATED - -#endif +#pragma once +#include "../../../ArduinoCore-API/api/Binary.h" diff --git a/cores/rp2040/api/Client.h b/cores/rp2040/api/Client.h index 5a1d99fe9..5f48487f8 100644 --- a/cores/rp2040/api/Client.h +++ b/cores/rp2040/api/Client.h @@ -1,46 +1,2 @@ -/* - Client.h - Base class that provides Client - Copyright (c) 2011 Adrian McEwen. All right reserved. - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -*/ - #pragma once - -#include "Stream.h" -#include "IPAddress.h" - -namespace arduino { - -class Client : public Stream { - -public: - virtual int connect(IPAddress ip, uint16_t port) =0; - virtual int connect(const char *host, uint16_t port) =0; - virtual size_t write(uint8_t) =0; - virtual size_t write(const uint8_t *buf, size_t size) =0; - virtual int available() = 0; - virtual int read() = 0; - virtual int read(uint8_t *buf, size_t size) = 0; - virtual int peek() = 0; - virtual void flush() = 0; - virtual void stop() = 0; - virtual uint8_t connected() = 0; - virtual operator bool() = 0; -protected: - uint8_t* rawIPAddress(IPAddress& addr) { return addr.raw_address(); }; -}; - -} \ No newline at end of file +#include "../../../ArduinoCore-API/api/Client.h" diff --git a/cores/rp2040/api/Common.cpp b/cores/rp2040/api/Common.cpp index d1f822c90..167da33a9 100644 --- a/cores/rp2040/api/Common.cpp +++ b/cores/rp2040/api/Common.cpp @@ -1,10 +1 @@ -#include "Common.h" - -/* C++ prototypes */ -long map(long x, long in_min, long in_max, long out_min, long out_max) -{ - return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min; -} - -uint16_t makeWord(uint16_t w) { return w; } -uint16_t makeWord(uint8_t h, uint8_t l) { return (h << 8) | l; } \ No newline at end of file +#include "../../../ArduinoCore-API/api/Common.cpp" diff --git a/cores/rp2040/api/Common.h b/cores/rp2040/api/Common.h index 3210b3a86..7d570fed3 100644 --- a/cores/rp2040/api/Common.h +++ b/cores/rp2040/api/Common.h @@ -1,173 +1,2 @@ #pragma once -#include - -#ifdef __cplusplus -extern "C"{ -#endif - -void yield(void); - -typedef enum { - LOW = 0, - HIGH = 1, - CHANGE = 2, - FALLING = 3, - RISING = 4, -} PinStatus; - -typedef enum { - INPUT = 0x0, - OUTPUT = 0x1, - INPUT_PULLUP = 0x2, - INPUT_PULLDOWN = 0x3, - OUTPUT_2MA = 0x4, - OUTPUT_4MA = 0x5, - OUTPUT_8MA = 0x6, - OUTPUT_12MA = 0x7, -} PinMode; - -typedef enum { - LSBFIRST = 0, - MSBFIRST = 1, -} BitOrder; - -#define PI 3.1415926535897932384626433832795 -#define HALF_PI 1.5707963267948966192313216916398 -#define TWO_PI 6.283185307179586476925286766559 -#define DEG_TO_RAD 0.017453292519943295769236907684886 -#define RAD_TO_DEG 57.295779513082320876798154814105 -#define EULER 2.718281828459045235360287471352 - -#define SERIAL 0x0 -#define DISPLAY 0x1 - -#ifndef constrain -#define constrain(amt,low,high) ((amt)<(low)?(low):((amt)>(high)?(high):(amt))) -#endif - -#ifndef radians -#define radians(deg) ((deg)*DEG_TO_RAD) -#endif - -#ifndef degrees -#define degrees(rad) ((rad)*RAD_TO_DEG) -#endif - -#ifndef sq -#define sq(x) ((x)*(x)) -#endif - -typedef void (*voidFuncPtr)(void); -typedef void (*voidFuncPtrParam)(void*); - -// interrupts() / noInterrupts() must be defined by the core - -#define lowByte(w) ((uint8_t) ((w) & 0xff)) -#define highByte(w) ((uint8_t) ((w) >> 8)) - -#define bitRead(value, bit) (((value) >> (bit)) & 0x01) -#define bitSet(value, bit) ((value) |= (1UL << (bit))) -#define bitClear(value, bit) ((value) &= ~(1UL << (bit))) -#define bitToggle(value, bit) ((value) ^= (1UL << (bit))) -#define bitWrite(value, bit, bitvalue) (bitvalue ? bitSet(value, bit) : bitClear(value, bit)) - -#ifndef bit -#define bit(b) (1UL << (b)) -#endif - -/* TODO: request for removal */ -typedef bool boolean; -typedef uint8_t byte; -typedef uint16_t word; - -void init(void); -void initVariant(void); - -#ifndef HOST -int atexit(void (*func)()) __attribute__((weak)); -#endif -int main() __attribute__((weak)); - -#ifdef EXTENDED_PIN_MODE -// Platforms who wnat to declare more than 256 pins need to define EXTENDED_PIN_MODE globally -typedef uint32_t pin_size_t; -#else -typedef uint8_t pin_size_t; -#endif - -void pinMode(pin_size_t pinNumber, PinMode pinMode); -void digitalWrite(pin_size_t pinNumber, PinStatus status); -PinStatus digitalRead(pin_size_t pinNumber); -int analogRead(pin_size_t pinNumber); -void analogReference(uint8_t mode); -void analogWrite(pin_size_t pinNumber, int value); - -unsigned long millis(void); -unsigned long micros(void); -void delay(unsigned long); -void delayMicroseconds(unsigned int us); -unsigned long pulseIn(pin_size_t pin, uint8_t state, unsigned long timeout); -unsigned long pulseInLong(pin_size_t pin, uint8_t state, unsigned long timeout); - -void shiftOut(pin_size_t dataPin, pin_size_t clockPin, BitOrder bitOrder, uint8_t val); -uint8_t shiftIn(pin_size_t dataPin, pin_size_t clockPin, BitOrder bitOrder); - -void attachInterrupt(pin_size_t interruptNumber, voidFuncPtr callback, PinStatus mode); -void attachInterruptParam(pin_size_t interruptNumber, voidFuncPtrParam callback, PinStatus mode, void* param); -void detachInterrupt(pin_size_t interruptNumber); - -void setup(void); -void loop(void); - -#ifdef __cplusplus -} // extern "C" -#endif - -#ifdef __cplusplus - template - auto min(const T& a, const L& b) -> decltype((b < a) ? b : a) - { - return (b < a) ? b : a; - } - - template - auto max(const T& a, const L& b) -> decltype((b < a) ? b : a) - { - return (a < b) ? b : a; - } -#else -#ifndef min -#define min(a,b) \ - ({ __typeof__ (a) _a = (a); \ - __typeof__ (b) _b = (b); \ - _a < _b ? _a : _b; }) -#endif -#ifndef max -#define max(a,b) \ - ({ __typeof__ (a) _a = (a); \ - __typeof__ (b) _b = (b); \ - _a > _b ? _a : _b; }) -#endif -#endif - -#ifdef __cplusplus - -/* C++ prototypes */ -uint16_t makeWord(uint16_t w); -uint16_t makeWord(byte h, byte l); - -#define word(...) makeWord(__VA_ARGS__) - -unsigned long pulseIn(uint8_t pin, uint8_t state, unsigned long timeout = 1000000L); -unsigned long pulseInLong(uint8_t pin, uint8_t state, unsigned long timeout = 1000000L); - -void tone(uint8_t _pin, unsigned int frequency, unsigned long duration = 0); -void noTone(uint8_t _pin); - -// WMath prototypes -long random(long); -long random(long, long); -void randomSeed(unsigned long); -long map(long, long, long, long, long); - -#endif // __cplusplus +#include "../../../ArduinoCore-API/api/Common.h" diff --git a/cores/rp2040/api/Compat.h b/cores/rp2040/api/Compat.h index 725ccd668..7e2725705 100644 --- a/cores/rp2040/api/Compat.h +++ b/cores/rp2040/api/Compat.h @@ -1,16 +1,2 @@ -#ifndef __COMPAT_H__ -#define __COMPAT_H__ - -namespace arduino { - -inline void pinMode(pin_size_t pinNumber, int mode) { - pinMode(pinNumber, (PinMode)mode); -}; - -inline void digitalWrite(pin_size_t pinNumber, int status) { - digitalWrite(pinNumber, (PinStatus)status); -}; - -} - -#endif \ No newline at end of file +#pragma once +#include "../../../ArduinoCore-API/api/Compat.h" diff --git a/cores/rp2040/api/HardwareI2C.h b/cores/rp2040/api/HardwareI2C.h index 4a8e5f981..15a207876 100644 --- a/cores/rp2040/api/HardwareI2C.h +++ b/cores/rp2040/api/HardwareI2C.h @@ -1,47 +1,2 @@ -/* - Copyright (c) 2016 Arduino LLC. All right reserved. - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - See the GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -*/ - #pragma once - -#include -#include "Stream.h" - -namespace arduino { - -class HardwareI2C : public Stream -{ - public: - virtual void begin() = 0; - virtual void begin(uint8_t address) = 0; - virtual void end() = 0; - - virtual void setClock(uint32_t freq) = 0; - - virtual void beginTransmission(uint8_t address) = 0; - virtual uint8_t endTransmission(bool stopBit) = 0; - virtual uint8_t endTransmission(void) = 0; - - virtual size_t requestFrom(uint8_t address, size_t len, bool stopBit) = 0; - virtual size_t requestFrom(uint8_t address, size_t len) = 0; - - virtual void onReceive(void(*)(int)) = 0; - virtual void onRequest(void(*)(void)) = 0; -}; - -} - +#include "../../../ArduinoCore-API/api/HardwareI2C.h" diff --git a/cores/rp2040/api/HardwareSPI.h b/cores/rp2040/api/HardwareSPI.h index d66094697..67577c92f 100644 --- a/cores/rp2040/api/HardwareSPI.h +++ b/cores/rp2040/api/HardwareSPI.h @@ -1,130 +1,2 @@ -/* - Copyright (c) 2018 Arduino LLC. All right reserved. - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - See the GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -*/ - #pragma once - -#include "Common.h" -#include -#include "Stream.h" - -#define SPI_HAS_TRANSACTION - -namespace arduino { - -typedef enum { - SPI_MODE0 = 0, - SPI_MODE1 = 1, - SPI_MODE2 = 2, - SPI_MODE3 = 3, -} SPIMode; - - -class SPISettings { - public: - SPISettings(uint32_t clock, BitOrder bitOrder, SPIMode dataMode) { - if (__builtin_constant_p(clock)) { - init_AlwaysInline(clock, bitOrder, dataMode); - } else { - init_MightInline(clock, bitOrder, dataMode); - } - } - - SPISettings(uint32_t clock, BitOrder bitOrder, int dataMode) { - if (__builtin_constant_p(clock)) { - init_AlwaysInline(clock, bitOrder, (SPIMode)dataMode); - } else { - init_MightInline(clock, bitOrder, (SPIMode)dataMode); - } - } - - // Default speed set to 4MHz, SPI mode set to MODE 0 and Bit order set to MSB first. - SPISettings() { init_AlwaysInline(4000000, MSBFIRST, SPI_MODE0); } - - bool operator==(const SPISettings& rhs) const - { - if ((this->clockFreq == rhs.clockFreq) && - (this->bitOrder == rhs.bitOrder) && - (this->dataMode == rhs.dataMode)) { - return true; - } - return false; - } - - bool operator!=(const SPISettings& rhs) const - { - return !(*this == rhs); - } - - uint32_t getClockFreq() const { - return clockFreq; - } - SPIMode getDataMode() const { - return dataMode; - } - BitOrder getBitOrder() const { - return (bitOrder); - } - - private: - void init_MightInline(uint32_t clock, BitOrder bitOrder, SPIMode dataMode) { - init_AlwaysInline(clock, bitOrder, dataMode); - } - - // Core developer MUST use an helper function in beginTransaction() to use this data - void init_AlwaysInline(uint32_t clock, BitOrder bitOrder, SPIMode dataMode) __attribute__((__always_inline__)) { - this->clockFreq = clock; - this->dataMode = dataMode; - this->bitOrder = bitOrder; - } - - uint32_t clockFreq; - SPIMode dataMode; - BitOrder bitOrder; - - friend class HardwareSPI; -}; - -const SPISettings DEFAULT_SPI_SETTINGS = SPISettings(); - -class HardwareSPI -{ - public: - virtual ~HardwareSPI() { } - - virtual uint8_t transfer(uint8_t data) = 0; - virtual uint16_t transfer16(uint16_t data) = 0; - virtual void transfer(void *buf, size_t count) = 0; - - // Transaction Functions - virtual void usingInterrupt(int interruptNumber) = 0; - virtual void notUsingInterrupt(int interruptNumber) = 0; - virtual void beginTransaction(SPISettings settings) = 0; - virtual void endTransaction(void) = 0; - - // SPI Configuration methods - virtual void attachInterrupt() = 0; - virtual void detachInterrupt() = 0; - - virtual void begin() = 0; - virtual void end() = 0; -}; - -// Alias SPIClass to HardwareSPI since it's already the defacto standard for SPI classe name -typedef HardwareSPI SPIClass; - -} +#include "../../../ArduinoCore-API/api/HardwareSPI.h" diff --git a/cores/rp2040/api/HardwareSerial.h b/cores/rp2040/api/HardwareSerial.h index e8f0657ae..3eaaf973f 100644 --- a/cores/rp2040/api/HardwareSerial.h +++ b/cores/rp2040/api/HardwareSerial.h @@ -1,105 +1,2 @@ -/* - Copyright (c) 2016 Arduino LLC. All right reserved. - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - See the GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -*/ - #pragma once - -#include -#include "Stream.h" - -namespace arduino { - -// XXX: Those constants should be defined as const int / enums? -// XXX: shall we use namespaces too? -#define SERIAL_PARITY_EVEN (0x1ul) -#define SERIAL_PARITY_ODD (0x2ul) -#define SERIAL_PARITY_NONE (0x3ul) -#define SERIAL_PARITY_MARK (0x4ul) -#define SERIAL_PARITY_SPACE (0x5ul) -#define SERIAL_PARITY_MASK (0xFul) - -#define SERIAL_STOP_BIT_1 (0x10ul) -#define SERIAL_STOP_BIT_1_5 (0x20ul) -#define SERIAL_STOP_BIT_2 (0x30ul) -#define SERIAL_STOP_BIT_MASK (0xF0ul) - -#define SERIAL_DATA_5 (0x100ul) -#define SERIAL_DATA_6 (0x200ul) -#define SERIAL_DATA_7 (0x300ul) -#define SERIAL_DATA_8 (0x400ul) -#define SERIAL_DATA_MASK (0xF00ul) - -#define SERIAL_5N1 (SERIAL_STOP_BIT_1 | SERIAL_PARITY_NONE | SERIAL_DATA_5) -#define SERIAL_6N1 (SERIAL_STOP_BIT_1 | SERIAL_PARITY_NONE | SERIAL_DATA_6) -#define SERIAL_7N1 (SERIAL_STOP_BIT_1 | SERIAL_PARITY_NONE | SERIAL_DATA_7) -#define SERIAL_8N1 (SERIAL_STOP_BIT_1 | SERIAL_PARITY_NONE | SERIAL_DATA_8) -#define SERIAL_5N2 (SERIAL_STOP_BIT_2 | SERIAL_PARITY_NONE | SERIAL_DATA_5) -#define SERIAL_6N2 (SERIAL_STOP_BIT_2 | SERIAL_PARITY_NONE | SERIAL_DATA_6) -#define SERIAL_7N2 (SERIAL_STOP_BIT_2 | SERIAL_PARITY_NONE | SERIAL_DATA_7) -#define SERIAL_8N2 (SERIAL_STOP_BIT_2 | SERIAL_PARITY_NONE | SERIAL_DATA_8) -#define SERIAL_5E1 (SERIAL_STOP_BIT_1 | SERIAL_PARITY_EVEN | SERIAL_DATA_5) -#define SERIAL_6E1 (SERIAL_STOP_BIT_1 | SERIAL_PARITY_EVEN | SERIAL_DATA_6) -#define SERIAL_7E1 (SERIAL_STOP_BIT_1 | SERIAL_PARITY_EVEN | SERIAL_DATA_7) -#define SERIAL_8E1 (SERIAL_STOP_BIT_1 | SERIAL_PARITY_EVEN | SERIAL_DATA_8) -#define SERIAL_5E2 (SERIAL_STOP_BIT_2 | SERIAL_PARITY_EVEN | SERIAL_DATA_5) -#define SERIAL_6E2 (SERIAL_STOP_BIT_2 | SERIAL_PARITY_EVEN | SERIAL_DATA_6) -#define SERIAL_7E2 (SERIAL_STOP_BIT_2 | SERIAL_PARITY_EVEN | SERIAL_DATA_7) -#define SERIAL_8E2 (SERIAL_STOP_BIT_2 | SERIAL_PARITY_EVEN | SERIAL_DATA_8) -#define SERIAL_5O1 (SERIAL_STOP_BIT_1 | SERIAL_PARITY_ODD | SERIAL_DATA_5) -#define SERIAL_6O1 (SERIAL_STOP_BIT_1 | SERIAL_PARITY_ODD | SERIAL_DATA_6) -#define SERIAL_7O1 (SERIAL_STOP_BIT_1 | SERIAL_PARITY_ODD | SERIAL_DATA_7) -#define SERIAL_8O1 (SERIAL_STOP_BIT_1 | SERIAL_PARITY_ODD | SERIAL_DATA_8) -#define SERIAL_5O2 (SERIAL_STOP_BIT_2 | SERIAL_PARITY_ODD | SERIAL_DATA_5) -#define SERIAL_6O2 (SERIAL_STOP_BIT_2 | SERIAL_PARITY_ODD | SERIAL_DATA_6) -#define SERIAL_7O2 (SERIAL_STOP_BIT_2 | SERIAL_PARITY_ODD | SERIAL_DATA_7) -#define SERIAL_8O2 (SERIAL_STOP_BIT_2 | SERIAL_PARITY_ODD | SERIAL_DATA_8) -#define SERIAL_5M1 (SERIAL_STOP_BIT_1 | SERIAL_PARITY_MARK | SERIAL_DATA_5) -#define SERIAL_6M1 (SERIAL_STOP_BIT_1 | SERIAL_PARITY_MARK | SERIAL_DATA_6) -#define SERIAL_7M1 (SERIAL_STOP_BIT_1 | SERIAL_PARITY_MARK | SERIAL_DATA_7) -#define SERIAL_8M1 (SERIAL_STOP_BIT_1 | SERIAL_PARITY_MARK | SERIAL_DATA_8) -#define SERIAL_5M2 (SERIAL_STOP_BIT_2 | SERIAL_PARITY_MARK | SERIAL_DATA_5) -#define SERIAL_6M2 (SERIAL_STOP_BIT_2 | SERIAL_PARITY_MARK | SERIAL_DATA_6) -#define SERIAL_7M2 (SERIAL_STOP_BIT_2 | SERIAL_PARITY_MARK | SERIAL_DATA_7) -#define SERIAL_8M2 (SERIAL_STOP_BIT_2 | SERIAL_PARITY_MARK | SERIAL_DATA_8) -#define SERIAL_5S1 (SERIAL_STOP_BIT_1 | SERIAL_PARITY_SPACE | SERIAL_DATA_5) -#define SERIAL_6S1 (SERIAL_STOP_BIT_1 | SERIAL_PARITY_SPACE | SERIAL_DATA_6) -#define SERIAL_7S1 (SERIAL_STOP_BIT_1 | SERIAL_PARITY_SPACE | SERIAL_DATA_7) -#define SERIAL_8S1 (SERIAL_STOP_BIT_1 | SERIAL_PARITY_SPACE | SERIAL_DATA_8) -#define SERIAL_5S2 (SERIAL_STOP_BIT_2 | SERIAL_PARITY_SPACE | SERIAL_DATA_5) -#define SERIAL_6S2 (SERIAL_STOP_BIT_2 | SERIAL_PARITY_SPACE | SERIAL_DATA_6) -#define SERIAL_7S2 (SERIAL_STOP_BIT_2 | SERIAL_PARITY_SPACE | SERIAL_DATA_7) -#define SERIAL_8S2 (SERIAL_STOP_BIT_2 | SERIAL_PARITY_SPACE | SERIAL_DATA_8) - -class HardwareSerial : public Stream -{ - public: - virtual void begin(unsigned long) = 0; - virtual void begin(unsigned long baudrate, uint16_t config) = 0; - virtual void end() = 0; - virtual int available(void) = 0; - virtual int peek(void) = 0; - virtual int read(void) = 0; - virtual void flush(void) = 0; - virtual size_t write(uint8_t) = 0; - using Print::write; // pull in write(str) and write(buf, size) from Print - virtual operator bool() = 0; -}; - -// XXX: Are we keeping the serialEvent API? -extern void serialEventRun(void) __attribute__((weak)); - -} \ No newline at end of file +#include "../../../ArduinoCore-API/api/HardwareSerial.h" diff --git a/cores/rp2040/api/IPAddress.cpp b/cores/rp2040/api/IPAddress.cpp index 404b65623..5326ee618 100644 --- a/cores/rp2040/api/IPAddress.cpp +++ b/cores/rp2040/api/IPAddress.cpp @@ -1,248 +1 @@ -/* - IPAddress.cpp - Base class that provides IPAddress - Copyright (c) 2011 Adrian McEwen. All right reserved. - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include -#include -#include - -IPAddress::IPAddress(const IPAddress& from) -{ - ip_addr_copy(_ip, from._ip); -} - -IPAddress::IPAddress() { - _ip = *IP_ANY_TYPE; // lwIP's v4-or-v6 generic address -} - -bool IPAddress::isSet () const { - return !ip_addr_isany(&_ip) && ((*this) != IPADDR_NONE); -} - -IPAddress::IPAddress(uint8_t first_octet, uint8_t second_octet, uint8_t third_octet, uint8_t fourth_octet) { - setV4(); - (*this)[0] = first_octet; - (*this)[1] = second_octet; - (*this)[2] = third_octet; - (*this)[3] = fourth_octet; -} - -void IPAddress::ctor32(uint32_t address) { - setV4(); - v4() = address; -} - -IPAddress::IPAddress(const uint8_t *address) { - setV4(); - (*this)[0] = address[0]; - (*this)[1] = address[1]; - (*this)[2] = address[2]; - (*this)[3] = address[3]; -} - -bool IPAddress::fromString(const char *address) { - if (!fromString4(address)) { -#if LWIP_IPV6 - return fromString6(address); -#else - return false; -#endif - } - return true; -} - -bool IPAddress::fromString4(const char *address) { - // TODO: (IPv4) add support for "a", "a.b", "a.b.c" formats - - uint16_t acc = 0; // Accumulator - uint8_t dots = 0; - - while (*address) - { - char c = *address++; - if (c >= '0' && c <= '9') - { - acc = acc * 10 + (c - '0'); - if (acc > 255) { - // Value out of [0..255] range - return false; - } - } - else if (c == '.') - { - if (dots == 3) { - // Too much dots (there must be 3 dots) - return false; - } - (*this)[dots++] = acc; - acc = 0; - } - else - { - // Invalid char - return false; - } - } - - if (dots != 3) { - // Too few dots (there must be 3 dots) - return false; - } - (*this)[3] = acc; - - setV4(); - return true; -} - -IPAddress& IPAddress::operator=(const uint8_t *address) { - setV4(); - v4() = *reinterpret_cast(address); - return *this; -} - -IPAddress& IPAddress::operator=(uint32_t address) { - setV4(); - v4() = address; - return *this; -} - -bool IPAddress::operator==(const uint8_t* addr) const { - return isV4() && v4() == *reinterpret_cast(addr); -} - -size_t IPAddress::printTo(Print& p) const { - String s = toString(); - return p.print(s); -} - -String IPAddress::toString() const -{ - String s; - - if (!isSet()) - return "(IP unset)"; - -#if LWIP_IPV6 - if (isV6()) { - int count0 = 0; - for (int i = 0; i < 8; i++) { - uint16_t bit = PP_NTOHS(raw6()[i]); - if (bit || count0 < 0) { - char buff[64]; - snprintf(buff, 64, "%x", bit); - buff[63] = 0; - s += buff; - if (count0 > 0) - // no more hiding 0 - count0 = -8; - } else - count0++; - if ((i != 7 && count0 < 2) || count0 == 7) - s += ':'; - } - return s; - } -#endif - - for(int i = 0; i < 4; i++) { - char buff[16]; - snprintf(buff, 16, "%d", (*this)[i]); - buff[15] = 0; - s += buff; - if (i != 3) - s += '.'; - } - return s; - -} - -bool IPAddress::isValid(const String& arg) { - return IPAddress().fromString(arg); -} - -bool IPAddress::isValid(const char* arg) { - return IPAddress().fromString(arg); -} - -namespace arduino { -const IPAddress INADDR_ANY; // generic "0.0.0.0" for IPv4 & IPv6 -const IPAddress INADDR_NONE(255,255,255,255); -}; - -void IPAddress::clear() { - (*this) = INADDR_ANY; -} - -/**************************************/ - -#if LWIP_IPV6 - -bool IPAddress::fromString6(const char *address) { - // TODO: test test test - - uint32_t acc = 0; // Accumulator - int dots = 0, doubledots = -1; - - while (*address) - { - char c = tolower(*address++); - if (isalnum(c)) { - if (c >= 'a') - c -= 'a' - '0' - 10; - acc = acc * 16 + (c - '0'); - if (acc > 0xffff) - // Value out of range - return false; - } - else if (c == ':') { - if (*address == ':') { - if (doubledots >= 0) - // :: allowed once - return false; - // remember location - doubledots = dots + !!acc; - address++; - } - if (dots == 7) - // too many separators - return false; - raw6()[dots++] = PP_HTONS(acc); - acc = 0; - } - else - // Invalid char - return false; - } - - if (doubledots == -1 && dots != 7) - // Too few separators - return false; - raw6()[dots++] = PP_HTONS(acc); - - if (doubledots != -1) { - for (int i = dots - doubledots - 1; i >= 0; i--) - raw6()[8 - dots + doubledots + i] = raw6()[doubledots + i]; - for (int i = doubledots; i < 8 - dots + doubledots; i++) - raw6()[i] = 0; - } - - setV6(); - return true; -} - -#endif +#include "../../../ArduinoCore-API/api/IPAddress.cpp" diff --git a/cores/rp2040/api/IPAddress.h b/cores/rp2040/api/IPAddress.h index a395c29bf..caddbbe76 100644 --- a/cores/rp2040/api/IPAddress.h +++ b/cores/rp2040/api/IPAddress.h @@ -1,236 +1,2 @@ -/* - IPAddress.h - Base class that provides IPAddress - Copyright (c) 2011 Adrian McEwen. All right reserved. - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - #pragma once - -#include -#include -#include - -#include -#include -#include - - -// forward declarations of global name space friend classes -class EthernetClass; -class DhcpClass; -class DNSClient; - - -namespace arduino { - -// to display a netif id with printf: -#define NETIFID_STR "%c%c%u" -#define NETIFID_VAL(netif) \ - ((netif)? (netif)->name[0]: '-'), \ - ((netif)? (netif)->name[1]: '-'), \ - ((netif)? netif_get_index(netif): 42) - -// A class to make it easier to handle and pass around IP addresses -// IPv6 update: -// IPAddress is now a decorator class for lwIP's ip_addr_t -// fully backward compatible with legacy IPv4-only Arduino's -// with unchanged footprint when IPv6 is disabled - -class IPAddress: public Printable { - private: -#if !LWIP_IPV6 - // Ugly hack to allow Arduino Ethernet library to twiddle internal bits. - // This can only work in IPv4-only mode, of course. - union { - ip_addr_t _ip; - struct { - uint8_t bytes[4]; - } _address; - }; - static_assert(sizeof(_ip) == sizeof(_address), "IP_ADDR_T size != _ADDRESS size"); -#else - ip_addr_t _ip; -#endif - - // Access the raw byte array containing the address. Because this returns a pointer - // to the internal structure rather than a copy of the address this function should only - // be used when you know that the usage of the returned uint8_t* will be transient and not - // stored. - uint8_t* raw_address() { - return reinterpret_cast(&v4()); - } - const uint8_t* raw_address() const { - return reinterpret_cast(&v4()); - } - - void ctor32 (uint32_t); - - public: - // Constructors - IPAddress(); - IPAddress(const IPAddress& from); - IPAddress(uint8_t first_octet, uint8_t second_octet, uint8_t third_octet, uint8_t fourth_octet); - IPAddress(uint32_t address) { ctor32(address); } -// IPAddress(unsigned long address) { ctor32(address); } - IPAddress(int address) { ctor32(address); } - IPAddress(const uint8_t *address); - - bool fromString(const char *address); - bool fromString(const String &address) { return fromString(address.c_str()); } - - // Overloaded cast operator to allow IPAddress objects to be used where a pointer - // to a four-byte uint8_t array is expected - operator uint32_t() const { return isV4()? v4(): (uint32_t)0; } - operator uint32_t() { return isV4()? v4(): (uint32_t)0; } - - bool isSet () const; - operator bool () const { return isSet(); } // <- - operator bool () { return isSet(); } // <- both are needed - - // generic IPv4 wrapper to uint32-view like arduino loves to see it - const uint32_t& v4() const { return ip_2_ip4(&_ip)->addr; } // for raw_address(const) - uint32_t& v4() { return ip_2_ip4(&_ip)->addr; } - - bool operator==(const IPAddress& addr) const { - return ip_addr_cmp(&_ip, &addr._ip); - } - bool operator!=(const IPAddress& addr) const { - return !ip_addr_cmp(&_ip, &addr._ip); - } - bool operator==(uint32_t addr) const { - return isV4() && v4() == addr; - } -// bool operator==(unsigned long addr) const { -// return isV4() && v4() == (uint32_t)addr; -// } - bool operator!=(uint32_t addr) const { - return !(isV4() && v4() == addr); - } -// bool operator!=(unsigned long addr) const { -// return isV4() && v4() != (uint32_t)addr; -// } - bool operator==(const uint8_t* addr) const; - - int operator>>(int n) const { - return isV4()? v4() >> n: 0; - } - - // Overloaded index operator to allow getting and setting individual octets of the address - uint8_t operator[](int index) const { - return isV4()? *(raw_address() + index): 0; - } - uint8_t& operator[](int index) { - setV4(); - return *(raw_address() + index); - } - - // Overloaded copy operators to allow initialisation of IPAddress objects from other types - IPAddress& operator=(const uint8_t *address); - IPAddress& operator=(uint32_t address); - IPAddress& operator=(const IPAddress&) = default; - - virtual size_t printTo(Print& p) const; - String toString() const; - - void clear(); - - /* - check if input string(arg) is a valid IPV4 address or not. - return true on valid. - return false on invalid. - */ - static bool isValid(const String& arg); - static bool isValid(const char* arg); - - friend class WiFiClass; - friend class EthernetClass; - friend class UDP; - friend class Client; - friend class Server; - friend class DhcpClass; - friend class DNSClient; - - friend ::EthernetClass; - friend ::DhcpClass; - friend ::DNSClient; - - /* - lwIP address compatibility - */ - //IPAddress(const ipv4_addr& fw_addr) { setV4(); v4() = fw_addr.addr; } - //IPAddress(const ipv4_addr* fw_addr) { setV4(); v4() = fw_addr->addr; } - - //IPAddress& operator=(const ipv4_addr& fw_addr) { setV4(); v4() = fw_addr.addr; return *this; } - //IPAddress& operator=(const ipv4_addr* fw_addr) { setV4(); v4() = fw_addr->addr; return *this; } - - operator ip_addr_t () const { return _ip; } - operator const ip_addr_t*() const { return &_ip; } - operator ip_addr_t*() { return &_ip; } - - bool isV4() const { return IP_IS_V4_VAL(_ip); } - void setV4() { IP_SET_TYPE_VAL(_ip, IPADDR_TYPE_V4); } - - bool isLocal () const { return ip_addr_islinklocal(&_ip); } - - - IPAddress(const ip_addr_t& lwip_addr) { ip_addr_copy(_ip, lwip_addr); } - IPAddress(const ip_addr_t* lwip_addr) { ip_addr_copy(_ip, *lwip_addr); } - - IPAddress& operator=(const ip_addr_t& lwip_addr) { ip_addr_copy(_ip, lwip_addr); return *this; } - IPAddress& operator=(const ip_addr_t* lwip_addr) { ip_addr_copy(_ip, *lwip_addr); return *this; } - -#if LWIP_IPV6 - uint16_t* raw6() - { - setV6(); - return reinterpret_cast(ip_2_ip6(&_ip)); - } - - const uint16_t* raw6() const - { - return isV6()? reinterpret_cast(ip_2_ip6(&_ip)): nullptr; - } - - // when not IPv6, ip_addr_t == ip4_addr_t so this one would be ambiguous - // required otherwise - operator const ip4_addr_t*() const { return isV4()? ip_2_ip4(&_ip): nullptr; } - - bool isV6() const { return IP_IS_V6_VAL(_ip); } - void setV6() { IP_SET_TYPE_VAL(_ip, IPADDR_TYPE_V6); } - - protected: - bool fromString6(const char *address); - -#else - - // allow portable code when IPv6 is not enabled - - uint16_t* raw6() { return nullptr; } - const uint16_t* raw6() const { return nullptr; } - bool isV6() const { return false; } - void setV6() { } - -#endif - - protected: - bool fromString4(const char *address); - -}; - -extern const IPAddress INADDR_ANY; -extern const IPAddress INADDR_NONE; - -} +#include "../../../ArduinoCore-API/api/IPAddress.h" diff --git a/cores/rp2040/api/Interrupts.h b/cores/rp2040/api/Interrupts.h index e306fc79a..e98258c30 100644 --- a/cores/rp2040/api/Interrupts.h +++ b/cores/rp2040/api/Interrupts.h @@ -1,44 +1,2 @@ -#ifndef W_INTERRUPTS_CPP -#define W_INTERRUPTS_CPP -#ifdef __cplusplus - -#include -#include -#include -#include "Common.h" - -namespace arduino { - -template -using voidTemplateFuncPtrParam = void (*)(T param); - -template struct __container__ { - void* param; - voidTemplateFuncPtrParam function; -}; - -// C++ only overloaded version of attachInterrupt function -template void attachInterrupt(pin_size_t interruptNum, voidTemplateFuncPtrParam userFunc, PinStatus mode, T& param) { - - struct __container__ *cont = new __container__(); - cont->param = ¶m; - cont->function = userFunc; - - // TODO: check lambda scope - // TODO: add structure to delete(__container__) when detachInterrupt() is called - auto f = [](void* a) -> void - { - T param = *(T*)((struct __container__*)a)->param; - (((struct __container__*)a)->function)(param); - }; - - attachInterruptParam(interruptNum, f, mode, cont); -} - -template void attachInterrupt(pin_size_t interruptNum, voidTemplateFuncPtrParam userFunc, PinStatus mode, T* param) { - attachInterruptParam(interruptNum, (voidFuncPtrParam)userFunc, mode, (void*)param); -} - -} -#endif -#endif +#pragma once +#include "../../../ArduinoCore-API/api/Interrupts.h" diff --git a/cores/rp2040/api/PluggableUSB.cpp b/cores/rp2040/api/PluggableUSB.cpp index ca19d65db..c5ff6c9bb 100644 --- a/cores/rp2040/api/PluggableUSB.cpp +++ b/cores/rp2040/api/PluggableUSB.cpp @@ -1,101 +1 @@ -/* - PluggableUSB.cpp - Copyright (c) 2015 Arduino LLC - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -*/ - -#include "USBAPI.h" -#include "PluggableUSB.h" - -using namespace arduino; - -int PluggableUSB_::getInterface(uint8_t* interfaceCount) -{ - int sent = 0; - PluggableUSBModule* node; - for (node = rootNode; node; node = node->next) { - int res = node->getInterface(interfaceCount); - if (res < 0) - return -1; - sent += res; - } - return sent; -} - -int PluggableUSB_::getDescriptor(USBSetup& setup) -{ - PluggableUSBModule* node; - for (node = rootNode; node; node = node->next) { - int ret = node->getDescriptor(setup); - // ret!=0 -> request has been processed - if (ret) - return ret; - } - return 0; -} - -void PluggableUSB_::getShortName(char *iSerialNum) -{ - PluggableUSBModule* node; - for (node = rootNode; node; node = node->next) { - iSerialNum += node->getShortName(iSerialNum); - } - *iSerialNum = 0; -} - -bool PluggableUSB_::setup(USBSetup& setup) -{ - PluggableUSBModule* node; - for (node = rootNode; node; node = node->next) { - if (node->setup(setup)) { - return true; - } - } - return false; -} - -bool PluggableUSB_::plug(PluggableUSBModule *node) -{ - if ((lastEp + node->numEndpoints) > totalEP) { - return false; - } - - if (!rootNode) { - rootNode = node; - } else { - PluggableUSBModule *current = rootNode; - while (current->next) { - current = current->next; - } - current->next = node; - } - - node->pluggedInterface = lastIf; - node->pluggedEndpoint = lastEp; - lastIf += node->numInterfaces; - for (uint8_t i = 0; i < node->numEndpoints; i++) { - *(unsigned int*)(epBuffer(lastEp)) = node->endpointType[i]; - lastEp++; - } - return true; - // restart USB layer??? -} - -PluggableUSB_& PluggableUSB() -{ - static PluggableUSB_ obj; - return obj; -} \ No newline at end of file +#include "../../../ArduinoCore-API/api/PluggableUSB.cpp" diff --git a/cores/rp2040/api/PluggableUSB.h b/cores/rp2040/api/PluggableUSB.h index 9018f6ce8..19e91b194 100644 --- a/cores/rp2040/api/PluggableUSB.h +++ b/cores/rp2040/api/PluggableUSB.h @@ -1,78 +1,2 @@ -/* - PluggableUSB.h - Copyright (c) 2015 Arduino LLC - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -*/ - -#ifndef PUSB_h -#define PUSB_h - -#include "USBAPI.h" -#include -#include - -namespace arduino { - -class PluggableUSBModule { -public: - PluggableUSBModule(uint8_t numEps, uint8_t numIfs, unsigned int *epType) : - numEndpoints(numEps), numInterfaces(numIfs), endpointType(epType) - { } - -protected: - virtual bool setup(USBSetup& setup) = 0; - virtual int getInterface(uint8_t* interfaceCount) = 0; - virtual int getDescriptor(USBSetup& setup) = 0; - virtual uint8_t getShortName(char *name) { name[0] = 'A'+pluggedInterface; return 1; } - - uint8_t pluggedInterface; - uint8_t pluggedEndpoint; - - const uint8_t numEndpoints; - const uint8_t numInterfaces; - const unsigned int *endpointType; - - PluggableUSBModule *next = NULL; - - friend class PluggableUSB_; -}; - -class PluggableUSB_ { -public: - PluggableUSB_(); - bool plug(PluggableUSBModule *node); - int getInterface(uint8_t* interfaceCount); - int getDescriptor(USBSetup& setup); - bool setup(USBSetup& setup); - void getShortName(char *iSerialNum); - -private: - uint8_t lastIf; - uint8_t lastEp; - PluggableUSBModule* rootNode; - uint8_t totalEP; -}; -} - -// core need to define -void* epBuffer(unsigned int n); // -> returns a pointer to the Nth element of the EP buffer structure - -// Replacement for global singleton. -// This function prevents static-initialization-order-fiasco -// https://isocpp.org/wiki/faq/ctors#static-init-order-on-first-use -arduino::PluggableUSB_& PluggableUSB(); - -#endif \ No newline at end of file +#pragma once +#include "../../../ArduinoCore-API/api/PluggableUSB.h" diff --git a/cores/rp2040/api/Print.cpp b/cores/rp2040/api/Print.cpp index 23f2a6de8..20e33a5b9 100644 --- a/cores/rp2040/api/Print.cpp +++ b/cores/rp2040/api/Print.cpp @@ -1,429 +1 @@ -/* - Copyright (c) 2014 Arduino. All right reserved. - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - See the GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -*/ - -#include -#include -#include -#include -#include - -#include "Print.h" - -using namespace arduino; - -// Public Methods ////////////////////////////////////////////////////////////// - -/* default implementation: may be overridden */ -size_t Print::write(const uint8_t *buffer, size_t size) -{ - size_t n = 0; - while (size--) { - if (write(*buffer++)) n++; - else break; - } - return n; -} - -size_t Print::print(const __FlashStringHelper *ifsh) -{ -#if defined(__AVR__) - PGM_P p = reinterpret_cast(ifsh); - size_t n = 0; - while (1) { - unsigned char c = pgm_read_byte(p++); - if (c == 0) break; - if (write(c)) n++; - else break; - } - return n; -#else - return print(reinterpret_cast(ifsh)); -#endif -} - -size_t Print::print(const String &s) -{ - return write(s.c_str(), s.length()); -} - -size_t Print::print(const char str[]) -{ - return write(str); -} - -size_t Print::print(char c) -{ - return write(c); -} - -size_t Print::print(unsigned char b, int base) -{ - return print((unsigned long) b, base); -} - -size_t Print::print(int n, int base) -{ - return print((long) n, base); -} - -size_t Print::print(unsigned int n, int base) -{ - return print((unsigned long) n, base); -} - -size_t Print::print(long n, int base) -{ - if (base == 0) { - return write(n); - } else if (base == 10) { - if (n < 0) { - int t = print('-'); - n = -n; - return printNumber(n, 10) + t; - } - return printNumber(n, 10); - } else { - return printNumber(n, base); - } -} - -size_t Print::print(unsigned long n, int base) -{ - if (base == 0) return write(n); - else return printNumber(n, base); -} - -size_t Print::print(long long n, int base) -{ - if (base == 0) { - return write(n); - } else if (base == 10) { - if (n < 0) { - int t = print('-'); - n = -n; - return printULLNumber(n, 10) + t; - } - return printULLNumber(n, 10); - } else { - return printULLNumber(n, base); - } -} - -size_t Print::print(unsigned long long n, int base) -{ - if (base == 0) return write(n); - else return printULLNumber(n, base); -} - -size_t Print::print(double n, int digits) -{ - return printFloat(n, digits); -} - -size_t Print::println(const __FlashStringHelper *ifsh) -{ - size_t n = print(ifsh); - n += println(); - return n; -} - -size_t Print::print(const Printable& x) -{ - return x.printTo(*this); -} - -size_t Print::println(void) -{ - return write("\r\n"); -} - -size_t Print::println(const String &s) -{ - size_t n = print(s); - n += println(); - return n; -} - -size_t Print::println(const char c[]) -{ - size_t n = print(c); - n += println(); - return n; -} - -size_t Print::println(char c) -{ - size_t n = print(c); - n += println(); - return n; -} - -size_t Print::println(unsigned char b, int base) -{ - size_t n = print(b, base); - n += println(); - return n; -} - -size_t Print::println(int num, int base) -{ - size_t n = print(num, base); - n += println(); - return n; -} - -size_t Print::println(unsigned int num, int base) -{ - size_t n = print(num, base); - n += println(); - return n; -} - -size_t Print::println(long num, int base) -{ - size_t n = print(num, base); - n += println(); - return n; -} - -size_t Print::println(unsigned long num, int base) -{ - size_t n = print(num, base); - n += println(); - return n; -} - -size_t Print::println(long long num, int base) -{ - size_t n = print(num, base); - n += println(); - return n; -} - -size_t Print::println(unsigned long long num, int base) -{ - size_t n = print(num, base); - n += println(); - return n; -} - -size_t Print::println(double num, int digits) -{ - size_t n = print(num, digits); - n += println(); - return n; -} - -size_t Print::println(const Printable& x) -{ - size_t n = print(x); - n += println(); - return n; -} - -size_t Print::printf(const char *format, ...) { - va_list arg; - va_start(arg, format); - char temp[64]; - char* buffer = temp; - size_t len = vsnprintf(temp, sizeof(temp), format, arg); - va_end(arg); - if (len > sizeof(temp) - 1) { - buffer = new char[len + 1]; - if (!buffer) { - return 0; - } - va_start(arg, format); - vsnprintf(buffer, len + 1, format, arg); - va_end(arg); - } - len = write((const uint8_t*) buffer, len); - if (buffer != temp) { - delete[] buffer; - } - return len; -} - -// TODO - must be better way than cut-n-paste! -size_t Print::printf_P(const char *format, ...) { - va_list arg; - va_start(arg, format); - char temp[64]; - char* buffer = temp; - size_t len = vsnprintf(temp, sizeof(temp), format, arg); - va_end(arg); - if (len > sizeof(temp) - 1) { - buffer = new char[len + 1]; - if (!buffer) { - return 0; - } - va_start(arg, format); - vsnprintf(buffer, len + 1, format, arg); - va_end(arg); - } - len = write((const uint8_t*) buffer, len); - if (buffer != temp) { - delete[] buffer; - } - return len; -} - -// Private Methods ///////////////////////////////////////////////////////////// - -size_t Print::printNumber(unsigned long n, uint8_t base) -{ - char buf[8 * sizeof(long) + 1]; // Assumes 8-bit chars plus zero byte. - char *str = &buf[sizeof(buf) - 1]; - - *str = '\0'; - - // prevent crash if called with base == 1 - if (base < 2) base = 10; - - do { - char c = n % base; - n /= base; - - *--str = c < 10 ? c + '0' : c + 'A' - 10; - } while(n); - - return write(str); -} - -// REFERENCE IMPLEMENTATION FOR ULL -// size_t Print::printULLNumber(unsigned long long n, uint8_t base) -// { - // // if limited to base 10 and 16 the bufsize can be smaller - // char buf[65]; - // char *str = &buf[64]; - - // *str = '\0'; - - // // prevent crash if called with base == 1 - // if (base < 2) base = 10; - - // do { - // unsigned long long t = n / base; - // char c = n - t * base; // faster than c = n%base; - // n = t; - // *--str = c < 10 ? c + '0' : c + 'A' - 10; - // } while(n); - - // return write(str); -// } - -// FAST IMPLEMENTATION FOR ULL -size_t Print::printULLNumber(unsigned long long n64, uint8_t base) -{ - // if limited to base 10 and 16 the bufsize can be 20 - char buf[64]; - uint8_t i = 0; - uint8_t innerLoops = 0; - - // prevent crash if called with base == 1 - if (base < 2) base = 10; - - // process chunks that fit in "16 bit math". - uint16_t top = 0xFFFF / base; - uint16_t th16 = 1; - while (th16 < top) - { - th16 *= base; - innerLoops++; - } - - while (n64 > th16) - { - // 64 bit math part - uint64_t q = n64 / th16; - uint16_t r = n64 - q*th16; - n64 = q; - - // 16 bit math loop to do remainder. (note buffer is filled reverse) - for (uint8_t j=0; j < innerLoops; j++) - { - uint16_t qq = r/base; - buf[i++] = r - qq*base; - r = qq; - } - } - - uint16_t n16 = n64; - while (n16 > 0) - { - uint16_t qq = n16/base; - buf[i++] = n16 - qq*base; - n16 = qq; - } - - size_t bytes = i; - for (; i > 0; i--) - write((char) (buf[i - 1] < 10 ? - '0' + buf[i - 1] : - 'A' + buf[i - 1] - 10)); - - return bytes; -} - -size_t Print::printFloat(double number, int digits) -{ - if (digits < 0) - digits = 2; - - size_t n = 0; - - if (isnan(number)) return print("nan"); - if (isinf(number)) return print("inf"); - if (number > 4294967040.0) return print ("ovf"); // constant determined empirically - if (number <-4294967040.0) return print ("ovf"); // constant determined empirically - - // Handle negative numbers - if (number < 0.0) - { - n += print('-'); - number = -number; - } - - // Round correctly so that print(1.999, 2) prints as "2.00" - double rounding = 0.5; - for (uint8_t i=0; i 0) { - n += print("."); - } - - // Extract digits from the remainder one at a time - while (digits-- > 0) - { - remainder *= 10.0; - unsigned int toPrint = (unsigned int)remainder; - n += print(toPrint); - remainder -= toPrint; - } - - return n; -} +#include "../../../ArduinoCore-API/api/Print.cpp" diff --git a/cores/rp2040/api/Print.h b/cores/rp2040/api/Print.h index 744ad903c..fb5b7bbf7 100644 --- a/cores/rp2040/api/Print.h +++ b/cores/rp2040/api/Print.h @@ -1,100 +1,2 @@ -/* - Copyright (c) 2016 Arduino LLC. All right reserved. - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - See the GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -*/ - #pragma once - -#include -#include // for size_t - -#include "String.h" -#include "Printable.h" - -#define DEC 10 -#define HEX 16 -#define OCT 8 -#define BIN 2 - -namespace arduino { - -class Print -{ - private: - int write_error; - size_t printNumber(unsigned long, uint8_t); - size_t printULLNumber(unsigned long long, uint8_t); - size_t printFloat(double, int); - protected: - void setWriteError(int err = 1) { write_error = err; } - public: - Print() : write_error(0) {} - - int getWriteError() { return write_error; } - void clearWriteError() { setWriteError(0); } - - virtual size_t write(uint8_t) = 0; - size_t write(const char *str) { - if (str == NULL) return 0; - return write((const uint8_t *)str, strlen(str)); - } - virtual size_t write(const uint8_t *buffer, size_t size); - size_t write(const char *buffer, size_t size) { - return write((const uint8_t *)buffer, size); - } - - // default to zero, meaning "a single write may block" - // should be overriden by subclasses with buffering - virtual int availableForWrite() { return 0; } - - size_t print(const __FlashStringHelper *); - size_t print(const String &); - size_t print(const char[]); - size_t print(char); - size_t print(unsigned char, int = DEC); - size_t print(int, int = DEC); - size_t print(unsigned int, int = DEC); - size_t print(long, int = DEC); - size_t print(unsigned long, int = DEC); - size_t print(long long, int = DEC); - size_t print(unsigned long long, int = DEC); - size_t print(double, int = 2); - size_t print(const Printable&); - - size_t println(const __FlashStringHelper *); - size_t println(const String &s); - size_t println(const char[]); - size_t println(char); - size_t println(unsigned char, int = DEC); - size_t println(int, int = DEC); - size_t println(unsigned int, int = DEC); - size_t println(long, int = DEC); - size_t println(unsigned long, int = DEC); - size_t println(long long, int = DEC); - size_t println(unsigned long long, int = DEC); - size_t println(double, int = 2); - size_t println(const Printable&); - size_t println(void); - - // EFP3 - Add printf() to make life so much easier... - size_t printf(const char *format, ...); - size_t printf_P(const char *format, ...); - - virtual void flush() { /* Empty implementation for backward compatibility */ } -}; - -} -using namespace arduino; +#include "../../../ArduinoCore-API/api/Print.h" diff --git a/cores/rp2040/api/Printable.h b/cores/rp2040/api/Printable.h index 972866e81..d7d08f929 100644 --- a/cores/rp2040/api/Printable.h +++ b/cores/rp2040/api/Printable.h @@ -1,39 +1,2 @@ -/* - Copyright (c) 2016 Arduino LLC. All right reserved. - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - See the GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -*/ - #pragma once - -#include - -namespace arduino { - -class Print; - -/** The Printable class provides a way for new classes to allow themselves to be printed. - By deriving from Printable and implementing the printTo method, it will then be possible - for users to print out instances of this class by passing them into the usual - Print::print and Print::println methods. -*/ - -class Printable -{ - public: - virtual size_t printTo(Print& p) const = 0; -}; - -} \ No newline at end of file +#include "../../../ArduinoCore-API/api/Printable.h" diff --git a/cores/rp2040/api/RingBuffer.h b/cores/rp2040/api/RingBuffer.h index 833350d16..2e80ce8b7 100644 --- a/cores/rp2040/api/RingBuffer.h +++ b/cores/rp2040/api/RingBuffer.h @@ -1,141 +1 @@ -/* - Copyright (c) 2014 Arduino. All right reserved. - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - See the GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -*/ - -#ifdef __cplusplus - -#ifndef _RING_BUFFER_ -#define _RING_BUFFER_ - -#include -#include - -namespace arduino { - -// Define constants and variables for buffering incoming serial data. We're -// using a ring buffer (I think), in which head is the index of the location -// to which to write the next incoming character and tail is the index of the -// location from which to read. -#define SERIAL_BUFFER_SIZE 64 - -template -class RingBufferN -{ - public: - uint8_t _aucBuffer[N] ; - volatile int _iHead ; - volatile int _iTail ; - volatile int _numElems; - - public: - RingBufferN( void ) ; - void store_char( uint8_t c ) ; - void clear(); - int read_char(); - int available(); - int availableForStore(); - int peek(); - bool isFull(); - - private: - int nextIndex(int index); - inline bool isEmpty() const { return (_numElems == 0); } -}; - -typedef RingBufferN RingBuffer; - - -template -RingBufferN::RingBufferN( void ) -{ - memset( _aucBuffer, 0, N ) ; - clear(); -} - -template -void RingBufferN::store_char( uint8_t c ) -{ - // if we should be storing the received character into the location - // just before the tail (meaning that the head would advance to the - // current location of the tail), we're about to overflow the buffer - // and so we don't write the character or advance the head. - if (!isFull()) - { - _aucBuffer[_iHead] = c ; - _iHead = nextIndex(_iHead); - _numElems++; - } -} - -template -void RingBufferN::clear() -{ - _iHead = 0; - _iTail = 0; - _numElems = 0; -} - -template -int RingBufferN::read_char() -{ - if (isEmpty()) - return -1; - - uint8_t value = _aucBuffer[_iTail]; - _iTail = nextIndex(_iTail); - _numElems--; - - return value; -} - -template -int RingBufferN::available() -{ - return _numElems; -} - -template -int RingBufferN::availableForStore() -{ - return (N - _numElems); -} - -template -int RingBufferN::peek() -{ - if (isEmpty()) - return -1; - - return _aucBuffer[_iTail]; -} - -template -int RingBufferN::nextIndex(int index) -{ - return (uint32_t)(index + 1) % N; -} - -template -bool RingBufferN::isFull() -{ - return (_numElems == N); -} - -} - -#endif /* _RING_BUFFER_ */ -#endif /* __cplusplus */ \ No newline at end of file +#include "../../../ArduinoCore-API/api/RingBuffer.h" diff --git a/cores/rp2040/api/Server.h b/cores/rp2040/api/Server.h index 83d0cd3bd..c314192a3 100644 --- a/cores/rp2040/api/Server.h +++ b/cores/rp2040/api/Server.h @@ -1,31 +1,2 @@ -/* - Server.h - Base class that provides Server - Copyright (c) 2011 Adrian McEwen. All right reserved. - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -*/ - #pragma once - -#include "Print.h" - -namespace arduino { - -class Server : public Print { - public: - virtual void begin() = 0; -}; - -} \ No newline at end of file +#include "../../../ArduinoCore-API/api/Server.h" diff --git a/cores/rp2040/api/Stream.cpp b/cores/rp2040/api/Stream.cpp index f6f9bda6a..f34f9d460 100644 --- a/cores/rp2040/api/Stream.cpp +++ b/cores/rp2040/api/Stream.cpp @@ -1,321 +1 @@ -/* - Stream.cpp - adds parsing methods to Stream class - Copyright (c) 2008 David A. Mellis. All right reserved. - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - - Created July 2011 - parsing functions based on TextFinder library by Michael Margolis - - findMulti/findUntil routines written by Jim Leonard/Xuth - */ - -#include "Common.h" -#include "Stream.h" - -#define PARSE_TIMEOUT 1000 // default number of milli-seconds to wait - -using namespace arduino; - -// private method to read stream with timeout -int Stream::timedRead() -{ - int c; - _startMillis = millis(); - do { - c = read(); - if (c >= 0) return c; - } while(millis() - _startMillis < _timeout); - return -1; // -1 indicates timeout -} - -// private method to peek stream with timeout -int Stream::timedPeek() -{ - int c; - _startMillis = millis(); - do { - c = peek(); - if (c >= 0) return c; - } while(millis() - _startMillis < _timeout); - return -1; // -1 indicates timeout -} - -// returns peek of the next digit in the stream or -1 if timeout -// discards non-numeric characters -int Stream::peekNextDigit(LookaheadMode lookahead, bool detectDecimal) -{ - int c; - while (1) { - c = timedPeek(); - - if( c < 0 || - c == '-' || - (c >= '0' && c <= '9') || - (detectDecimal && c == '.')) return c; - - switch( lookahead ){ - case SKIP_NONE: return -1; // Fail code. - case SKIP_WHITESPACE: - switch( c ){ - case ' ': - case '\t': - case '\r': - case '\n': break; - default: return -1; // Fail code. - } - case SKIP_ALL: - break; - } - read(); // discard non-numeric - } -} - -// Public Methods -////////////////////////////////////////////////////////////// - -void Stream::setTimeout(unsigned long timeout) // sets the maximum number of milliseconds to wait -{ - _timeout = timeout; -} - - // find returns true if the target string is found -bool Stream::find(const char *target) -{ - return findUntil(target, strlen(target), NULL, 0); -} - -// reads data from the stream until the target string of given length is found -// returns true if target string is found, false if timed out -bool Stream::find(const char *target, size_t length) -{ - return findUntil(target, length, NULL, 0); -} - -// as find but search ends if the terminator string is found -bool Stream::findUntil(const char *target, const char *terminator) -{ - return findUntil(target, strlen(target), terminator, strlen(terminator)); -} - -// reads data from the stream until the target string of the given length is found -// search terminated if the terminator string is found -// returns true if target string is found, false if terminated or timed out -bool Stream::findUntil(const char *target, size_t targetLen, const char *terminator, size_t termLen) -{ - if (terminator == NULL) { - MultiTarget t[1] = {{target, targetLen, 0}}; - return findMulti(t, 1) == 0; - } else { - MultiTarget t[2] = {{target, targetLen, 0}, {terminator, termLen, 0}}; - return findMulti(t, 2) == 0; - } -} - -// returns the first valid (long) integer value from the current position. -// lookahead determines how parseInt looks ahead in the stream. -// See LookaheadMode enumeration at the top of the file. -// Lookahead is terminated by the first character that is not a valid part of an integer. -// Once parsing commences, 'ignore' will be skipped in the stream. -long Stream::parseInt(LookaheadMode lookahead, char ignore) -{ - bool isNegative = false; - long value = 0; - int c; - - c = peekNextDigit(lookahead, false); - // ignore non numeric leading characters - if(c < 0) - return 0; // zero returned if timeout - - do{ - if((char)c == ignore) - ; // ignore this character - else if(c == '-') - isNegative = true; - else if(c >= '0' && c <= '9') // is c a digit? - value = value * 10 + c - '0'; - read(); // consume the character we got with peek - c = timedPeek(); - } - while( (c >= '0' && c <= '9') || (char)c == ignore ); - - if(isNegative) - value = -value; - return value; -} - -// as parseInt but returns a floating point value -float Stream::parseFloat(LookaheadMode lookahead, char ignore) -{ - bool isNegative = false; - bool isFraction = false; - double value = 0.0; - int c; - double fraction = 1.0; - - c = peekNextDigit(lookahead, true); - // ignore non numeric leading characters - if(c < 0) - return 0; // zero returned if timeout - - do{ - if((char)c == ignore) - ; // ignore - else if(c == '-') - isNegative = true; - else if (c == '.') - isFraction = true; - else if(c >= '0' && c <= '9') { // is c a digit? - if(isFraction) { - fraction *= 0.1; - value = value + fraction * (c - '0'); - } else { - value = value * 10 + c - '0'; - } - } - read(); // consume the character we got with peek - c = timedPeek(); - } - while( (c >= '0' && c <= '9') || (c == '.' && !isFraction) || (char)c == ignore ); - - if(isNegative) - value = -value; - - return value; -} - -// read characters from stream into buffer -// terminates if length characters have been read, or timeout (see setTimeout) -// returns the number of characters placed in the buffer -// the buffer is NOT null terminated. -// -size_t Stream::readBytes(char *buffer, size_t length) -{ - size_t count = 0; - while (count < length) { - int c = timedRead(); - if (c < 0) break; - *buffer++ = (char)c; - count++; - } - return count; -} - - -// as readBytes with terminator character -// terminates if length characters have been read, timeout, or if the terminator character detected -// returns the number of characters placed in the buffer (0 means no valid data found) - -size_t Stream::readBytesUntil(char terminator, char *buffer, size_t length) -{ - size_t index = 0; - while (index < length) { - int c = timedRead(); - if (c < 0 || (char)c == terminator) break; - *buffer++ = (char)c; - index++; - } - return index; // return number of characters, not including null terminator -} - -String Stream::readString() -{ - String ret; - int c = timedRead(); - while (c >= 0) - { - ret += (char)c; - c = timedRead(); - } - return ret; -} - -String Stream::readStringUntil(char terminator) -{ - String ret; - int c = timedRead(); - while (c >= 0 && (char)c != terminator) - { - ret += (char)c; - c = timedRead(); - } - return ret; -} - -int Stream::findMulti( struct Stream::MultiTarget *targets, int tCount) { - // any zero length target string automatically matches and would make - // a mess of the rest of the algorithm. - for (struct MultiTarget *t = targets; t < targets+tCount; ++t) { - if (t->len <= 0) - return t - targets; - } - - while (1) { - int c = timedRead(); - if (c < 0) - return -1; - - for (struct MultiTarget *t = targets; t < targets+tCount; ++t) { - // the simple case is if we match, deal with that first. - if ((char)c == t->str[t->index]) { - if (++t->index == t->len) - return t - targets; - else - continue; - } - - // if not we need to walk back and see if we could have matched further - // down the stream (ie '1112' doesn't match the first position in '11112' - // but it will match the second position so we can't just reset the current - // index to 0 when we find a mismatch. - if (t->index == 0) - continue; - - int origIndex = t->index; - do { - --t->index; - // first check if current char works against the new current index - if ((char)c != t->str[t->index]) - continue; - - // if it's the only char then we're good, nothing more to check - if (t->index == 0) { - t->index++; - break; - } - - // otherwise we need to check the rest of the found string - int diff = origIndex - t->index; - size_t i; - for (i = 0; i < t->index; ++i) { - if (t->str[i] != t->str[i + diff]) - break; - } - - // if we successfully got through the previous loop then our current - // index is good. - if (i == t->index) { - t->index++; - break; - } - - // otherwise we just try the next index - } while (t->index); - } - } - // unreachable - return -1; -} +#include "../../../ArduinoCore-API/api/Stream.cpp" diff --git a/cores/rp2040/api/Stream.h b/cores/rp2040/api/Stream.h index bf4261a51..ac7229716 100644 --- a/cores/rp2040/api/Stream.h +++ b/cores/rp2040/api/Stream.h @@ -1,131 +1,2 @@ -/* - Stream.h - base class for character-based streams. - Copyright (c) 2010 David A. Mellis. All right reserved. - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - - parsing functions based on TextFinder library by Michael Margolis -*/ - #pragma once - -#include -#include "Print.h" - -// compatability macros for testing -/* -#define getInt() parseInt() -#define getInt(ignore) parseInt(ignore) -#define getFloat() parseFloat() -#define getFloat(ignore) parseFloat(ignore) -#define getString( pre_string, post_string, buffer, length) -readBytesBetween( pre_string, terminator, buffer, length) -*/ - -namespace arduino { - -// This enumeration provides the lookahead options for parseInt(), parseFloat() -// The rules set out here are used until either the first valid character is found -// or a time out occurs due to lack of input. -enum LookaheadMode{ - SKIP_ALL, // All invalid characters are ignored. - SKIP_NONE, // Nothing is skipped, and the stream is not touched unless the first waiting character is valid. - SKIP_WHITESPACE // Only tabs, spaces, line feeds & carriage returns are skipped. -}; - -#define NO_IGNORE_CHAR '\x01' // a char not found in a valid ASCII numeric field - -class Stream : public Print -{ - protected: - unsigned long _timeout; // number of milliseconds to wait for the next char before aborting timed read - unsigned long _startMillis; // used for timeout measurement - int timedRead(); // private method to read stream with timeout - int timedPeek(); // private method to peek stream with timeout - int peekNextDigit(LookaheadMode lookahead, bool detectDecimal); // returns the next numeric digit in the stream or -1 if timeout - - public: - virtual int available() = 0; - virtual int read() = 0; - virtual int peek() = 0; - - Stream() {_timeout=1000;} - -// parsing methods - - void setTimeout(unsigned long timeout); // sets maximum milliseconds to wait for stream data, default is 1 second - unsigned long getTimeout(void) { return _timeout; } - - bool find(const char *target); // reads data from the stream until the target string is found - bool find(const uint8_t *target) { return find ((const char *)target); } - // returns true if target string is found, false if timed out (see setTimeout) - - bool find(const char *target, size_t length); // reads data from the stream until the target string of given length is found - bool find(const uint8_t *target, size_t length) { return find ((const char *)target, length); } - // returns true if target string is found, false if timed out - - bool find(char target) { return find (&target, 1); } - - bool findUntil(const char *target, const char *terminator); // as find but search ends if the terminator string is found - bool findUntil(const uint8_t *target, const char *terminator) { return findUntil((const char *)target, terminator); } - - bool findUntil(const char *target, size_t targetLen, const char *terminate, size_t termLen); // as above but search ends if the terminate string is found - bool findUntil(const uint8_t *target, size_t targetLen, const char *terminate, size_t termLen) {return findUntil((const char *)target, targetLen, terminate, termLen); } - - long parseInt(LookaheadMode lookahead = SKIP_ALL, char ignore = NO_IGNORE_CHAR); - // returns the first valid (long) integer value from the current position. - // lookahead determines how parseInt looks ahead in the stream. - // See LookaheadMode enumeration at the top of the file. - // Lookahead is terminated by the first character that is not a valid part of an integer. - // Once parsing commences, 'ignore' will be skipped in the stream. - - float parseFloat(LookaheadMode lookahead = SKIP_ALL, char ignore = NO_IGNORE_CHAR); - // float version of parseInt - - size_t readBytes( char *buffer, size_t length); // read chars from stream into buffer - size_t readBytes( uint8_t *buffer, size_t length) { return readBytes((char *)buffer, length); } - // terminates if length characters have been read or timeout (see setTimeout) - // returns the number of characters placed in the buffer (0 means no valid data found) - - size_t readBytesUntil( char terminator, char *buffer, size_t length); // as readBytes with terminator character - size_t readBytesUntil( char terminator, uint8_t *buffer, size_t length) { return readBytesUntil(terminator, (char *)buffer, length); } - // terminates if length characters have been read, timeout, or if the terminator character detected - // returns the number of characters placed in the buffer (0 means no valid data found) - - // Arduino String functions to be added here - String readString(); - String readStringUntil(char terminator); - - protected: - long parseInt(char ignore) { return parseInt(SKIP_ALL, ignore); } - float parseFloat(char ignore) { return parseFloat(SKIP_ALL, ignore); } - // These overload exists for compatibility with any class that has derived - // Stream and used parseFloat/Int with a custom ignore character. To keep - // the public API simple, these overload remains protected. - - struct MultiTarget { - const char *str; // string you're searching for - size_t len; // length of string you're searching for - size_t index; // index used by the search routine. - }; - - // This allows you to search for an arbitrary number of strings. - // Returns index of the target that is found first or -1 if timeout occurs. - int findMulti(struct MultiTarget *targets, int tCount); -}; - -#undef NO_IGNORE_CHAR - -} \ No newline at end of file +#include "../../../ArduinoCore-API/api/Stream.h" diff --git a/cores/rp2040/api/String.cpp b/cores/rp2040/api/String.cpp index 1b6d4b286..4e9c276ac 100644 --- a/cores/rp2040/api/String.cpp +++ b/cores/rp2040/api/String.cpp @@ -1,768 +1 @@ -/* - String library for Wiring & Arduino - ...mostly rewritten by Paul Stoffregen... - Copyright (c) 2009-10 Hernando Barragan. All rights reserved. - Copyright 2011, Paul Stoffregen, paul@pjrc.com - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -*/ - -#include "String.h" -#include "Common.h" -#include "itoa.h" -#include "deprecated-avr-comp/avr/dtostrf.h" - -#include - -namespace arduino { - -/*********************************************/ -/* Static Member Initialisation */ -/*********************************************/ - -size_t const String::FLT_MAX_DECIMAL_PLACES; -size_t const String::DBL_MAX_DECIMAL_PLACES; - -/*********************************************/ -/* Constructors */ -/*********************************************/ - -String::String(const char *cstr) -{ - init(); - if (cstr) copy(cstr, strlen(cstr)); -} - -String::String(const char *cstr, unsigned int length) -{ - init(); - if (cstr) copy(cstr, length); -} - -String::String(const String &value) -{ - init(); - *this = value; -} - -String::String(const __FlashStringHelper *pstr) -{ - init(); - *this = pstr; -} - -#if __cplusplus >= 201103L || defined(__GXX_EXPERIMENTAL_CXX0X__) -String::String(String &&rval) -{ - init(); - move(rval); -} -String::String(StringSumHelper &&rval) -{ - init(); - move(rval); -} -#endif - -String::String(char c) -{ - init(); - char buf[2]; - buf[0] = c; - buf[1] = 0; - *this = buf; -} - -String::String(unsigned char value, unsigned char base) -{ - init(); - char buf[1 + 8 * sizeof(unsigned char)]; - utoa(value, buf, base); - *this = buf; -} - -String::String(int value, unsigned char base) -{ - init(); - char buf[2 + 8 * sizeof(int)]; - itoa(value, buf, base); - *this = buf; -} - -String::String(unsigned int value, unsigned char base) -{ - init(); - char buf[1 + 8 * sizeof(unsigned int)]; - utoa(value, buf, base); - *this = buf; -} - -String::String(long value, unsigned char base) -{ - init(); - char buf[2 + 8 * sizeof(long)]; - ltoa(value, buf, base); - *this = buf; -} - -String::String(unsigned long value, unsigned char base) -{ - init(); - char buf[1 + 8 * sizeof(unsigned long)]; - ultoa(value, buf, base); - *this = buf; -} - -String::String(float value, unsigned char decimalPlaces) -{ - static size_t const FLOAT_BUF_SIZE = FLT_MAX_10_EXP + FLT_MAX_DECIMAL_PLACES + 1 /* '-' */ + 1 /* '.' */ + 1 /* '\0' */; - init(); - char buf[FLOAT_BUF_SIZE]; - decimalPlaces = min(decimalPlaces, FLT_MAX_DECIMAL_PLACES); - *this = dtostrf(value, (decimalPlaces + 2), decimalPlaces, buf); -} - -String::String(double value, unsigned char decimalPlaces) -{ - static size_t const DOUBLE_BUF_SIZE = DBL_MAX_10_EXP + DBL_MAX_DECIMAL_PLACES + 1 /* '-' */ + 1 /* '.' */ + 1 /* '\0' */; - init(); - char buf[DOUBLE_BUF_SIZE]; - decimalPlaces = min(decimalPlaces, DBL_MAX_DECIMAL_PLACES); - *this = dtostrf(value, (decimalPlaces + 2), decimalPlaces, buf); -} - -String::~String() -{ - if (buffer) free(buffer); -} - -/*********************************************/ -/* Memory Management */ -/*********************************************/ - -inline void String::init(void) -{ - buffer = NULL; - capacity = 0; - len = 0; -} - -void String::invalidate(void) -{ - if (buffer) free(buffer); - buffer = NULL; - capacity = len = 0; -} - -unsigned char String::reserve(unsigned int size) -{ - if (buffer && capacity >= size) return 1; - if (changeBuffer(size)) { - if (len == 0) buffer[0] = 0; - return 1; - } - return 0; -} - -unsigned char String::changeBuffer(unsigned int maxStrLen) -{ - char *newbuffer = (char *)realloc(buffer, maxStrLen + 1); - if (newbuffer) { - buffer = newbuffer; - capacity = maxStrLen; - return 1; - } - return 0; -} - -/*********************************************/ -/* Copy and Move */ -/*********************************************/ - -String & String::copy(const char *cstr, unsigned int length) -{ - if (!reserve(length)) { - invalidate(); - return *this; - } - len = length; - memcpy(buffer, cstr, length); - buffer[len] = '\0'; - return *this; -} - -String & String::copy(const __FlashStringHelper *pstr, unsigned int length) -{ - if (!reserve(length)) { - invalidate(); - return *this; - } - len = length; - strcpy_P(buffer, (PGM_P)pstr); - return *this; -} - -#if __cplusplus >= 201103L || defined(__GXX_EXPERIMENTAL_CXX0X__) -void String::move(String &rhs) -{ - if (buffer) { - if (rhs && capacity >= rhs.len) { - memcpy(buffer, rhs.buffer, rhs.len); - len = rhs.len; - buffer[len] = '\0'; - rhs.len = 0; - return; - } else { - free(buffer); - } - } - buffer = rhs.buffer; - capacity = rhs.capacity; - len = rhs.len; - rhs.buffer = NULL; - rhs.capacity = 0; - rhs.len = 0; -} -#endif - -String & String::operator = (const String &rhs) -{ - if (this == &rhs) return *this; - - if (rhs.buffer) copy(rhs.buffer, rhs.len); - else invalidate(); - - return *this; -} - -#if __cplusplus >= 201103L || defined(__GXX_EXPERIMENTAL_CXX0X__) -String & String::operator = (String &&rval) -{ - if (this != &rval) move(rval); - return *this; -} - -String & String::operator = (StringSumHelper &&rval) -{ - if (this != &rval) move(rval); - return *this; -} -#endif - -String & String::operator = (const char *cstr) -{ - if (cstr) copy(cstr, strlen(cstr)); - else invalidate(); - - return *this; -} - -String & String::operator = (const __FlashStringHelper *pstr) -{ - if (pstr) copy(pstr, strlen_P((PGM_P)pstr)); - else invalidate(); - - return *this; -} - -/*********************************************/ -/* concat */ -/*********************************************/ - -unsigned char String::concat(const String &s) -{ - return concat(s.buffer, s.len); -} - -unsigned char String::concat(const char *cstr, unsigned int length) -{ - unsigned int newlen = len + length; - if (!cstr) return 0; - if (length == 0) return 1; - if (!reserve(newlen)) return 0; - memcpy(buffer + len, cstr, length); - len = newlen; - buffer[len] = '\0'; - return 1; -} - -unsigned char String::concat(const char *cstr) -{ - if (!cstr) return 0; - return concat(cstr, strlen(cstr)); -} - -unsigned char String::concat(char c) -{ - return concat(&c, 1); -} - -unsigned char String::concat(unsigned char num) -{ - char buf[1 + 3 * sizeof(unsigned char)]; - itoa(num, buf, 10); - return concat(buf); -} - -unsigned char String::concat(int num) -{ - char buf[2 + 3 * sizeof(int)]; - itoa(num, buf, 10); - return concat(buf); -} - -unsigned char String::concat(unsigned int num) -{ - char buf[1 + 3 * sizeof(unsigned int)]; - utoa(num, buf, 10); - return concat(buf); -} - -unsigned char String::concat(long num) -{ - char buf[2 + 3 * sizeof(long)]; - ltoa(num, buf, 10); - return concat(buf); -} - -unsigned char String::concat(unsigned long num) -{ - char buf[1 + 3 * sizeof(unsigned long)]; - ultoa(num, buf, 10); - return concat(buf); -} - -unsigned char String::concat(float num) -{ - char buf[20]; - char* string = dtostrf(num, 4, 2, buf); - return concat(string); -} - -unsigned char String::concat(double num) -{ - char buf[20]; - char* string = dtostrf(num, 4, 2, buf); - return concat(string); -} - -unsigned char String::concat(const __FlashStringHelper * str) -{ - if (!str) return 0; - int length = strlen_P((const char *) str); - if (length == 0) return 1; - unsigned int newlen = len + length; - if (!reserve(newlen)) return 0; - strcpy_P(buffer + len, (const char *) str); - len = newlen; - return 1; -} - -/*********************************************/ -/* Concatenate */ -/*********************************************/ - -StringSumHelper & operator + (const StringSumHelper &lhs, const String &rhs) -{ - StringSumHelper &a = const_cast(lhs); - if (!a.concat(rhs.buffer, rhs.len)) a.invalidate(); - return a; -} - -StringSumHelper & operator + (const StringSumHelper &lhs, const char *cstr) -{ - StringSumHelper &a = const_cast(lhs); - if (!cstr || !a.concat(cstr)) a.invalidate(); - return a; -} - -StringSumHelper & operator + (const StringSumHelper &lhs, char c) -{ - StringSumHelper &a = const_cast(lhs); - if (!a.concat(c)) a.invalidate(); - return a; -} - -StringSumHelper & operator + (const StringSumHelper &lhs, unsigned char num) -{ - StringSumHelper &a = const_cast(lhs); - if (!a.concat(num)) a.invalidate(); - return a; -} - -StringSumHelper & operator + (const StringSumHelper &lhs, int num) -{ - StringSumHelper &a = const_cast(lhs); - if (!a.concat(num)) a.invalidate(); - return a; -} - -StringSumHelper & operator + (const StringSumHelper &lhs, unsigned int num) -{ - StringSumHelper &a = const_cast(lhs); - if (!a.concat(num)) a.invalidate(); - return a; -} - -StringSumHelper & operator + (const StringSumHelper &lhs, long num) -{ - StringSumHelper &a = const_cast(lhs); - if (!a.concat(num)) a.invalidate(); - return a; -} - -StringSumHelper & operator + (const StringSumHelper &lhs, unsigned long num) -{ - StringSumHelper &a = const_cast(lhs); - if (!a.concat(num)) a.invalidate(); - return a; -} - -StringSumHelper & operator + (const StringSumHelper &lhs, float num) -{ - StringSumHelper &a = const_cast(lhs); - if (!a.concat(num)) a.invalidate(); - return a; -} - -StringSumHelper & operator + (const StringSumHelper &lhs, double num) -{ - StringSumHelper &a = const_cast(lhs); - if (!a.concat(num)) a.invalidate(); - return a; -} - -StringSumHelper & operator + (const StringSumHelper &lhs, const __FlashStringHelper *rhs) -{ - StringSumHelper &a = const_cast(lhs); - if (!a.concat(rhs)) a.invalidate(); - return a; -} - -/*********************************************/ -/* Comparison */ -/*********************************************/ - -int String::compareTo(const String &s) const -{ - if (!buffer || !s.buffer) { - if (s.buffer && s.len > 0) return 0 - *(unsigned char *)s.buffer; - if (buffer && len > 0) return *(unsigned char *)buffer; - return 0; - } - return strcmp(buffer, s.buffer); -} - -int String::compareTo(const char *cstr) const -{ - if (!buffer || !cstr) { - if (cstr && *cstr) return 0 - *(unsigned char *)cstr; - if (buffer && len > 0) return *(unsigned char *)buffer; - return 0; - } - return strcmp(buffer, cstr); -} - -unsigned char String::equals(const String &s2) const -{ - return (len == s2.len && compareTo(s2) == 0); -} - -unsigned char String::equals(const char *cstr) const -{ - if (len == 0) return (cstr == NULL || *cstr == 0); - if (cstr == NULL) return buffer[0] == 0; - return strcmp(buffer, cstr) == 0; -} - -unsigned char String::equalsIgnoreCase( const String &s2 ) const -{ - if (this == &s2) return 1; - if (len != s2.len) return 0; - if (len == 0) return 1; - const char *p1 = buffer; - const char *p2 = s2.buffer; - while (*p1) { - if (tolower(*p1++) != tolower(*p2++)) return 0; - } - return 1; -} - -unsigned char String::startsWith( const String &s2 ) const -{ - if (len < s2.len) return 0; - return startsWith(s2, 0); -} - -unsigned char String::startsWith( const String &s2, unsigned int offset ) const -{ - if (offset > len - s2.len || !buffer || !s2.buffer) return 0; - return strncmp( &buffer[offset], s2.buffer, s2.len ) == 0; -} - -unsigned char String::endsWith( const String &s2 ) const -{ - if ( len < s2.len || !buffer || !s2.buffer) return 0; - return strcmp(&buffer[len - s2.len], s2.buffer) == 0; -} - -/*********************************************/ -/* Character Access */ -/*********************************************/ - -char String::charAt(unsigned int loc) const -{ - return operator[](loc); -} - -void String::setCharAt(unsigned int loc, char c) -{ - if (loc < len) buffer[loc] = c; -} - -char & String::operator[](unsigned int index) -{ - static char dummy_writable_char; - if (index >= len || !buffer) { - dummy_writable_char = 0; - return dummy_writable_char; - } - return buffer[index]; -} - -char String::operator[]( unsigned int index ) const -{ - if (index >= len || !buffer) return 0; - return buffer[index]; -} - -void String::getBytes(unsigned char *buf, unsigned int bufsize, unsigned int index) const -{ - if (!bufsize || !buf) return; - if (index >= len) { - buf[0] = 0; - return; - } - unsigned int n = bufsize - 1; - if (n > len - index) n = len - index; - strncpy((char *)buf, buffer + index, n); - buf[n] = 0; -} - -/*********************************************/ -/* Search */ -/*********************************************/ - -int String::indexOf(char c) const -{ - return indexOf(c, 0); -} - -int String::indexOf( char ch, unsigned int fromIndex ) const -{ - if (fromIndex >= len) return -1; - const char* temp = strchr(buffer + fromIndex, ch); - if (temp == NULL) return -1; - return temp - buffer; -} - -int String::indexOf(const String &s2) const -{ - return indexOf(s2, 0); -} - -int String::indexOf(const String &s2, unsigned int fromIndex) const -{ - if (fromIndex >= len) return -1; - const char *found = strstr(buffer + fromIndex, s2.buffer); - if (found == NULL) return -1; - return found - buffer; -} - -int String::lastIndexOf( char theChar ) const -{ - return lastIndexOf(theChar, len - 1); -} - -int String::lastIndexOf(char ch, unsigned int fromIndex) const -{ - if (fromIndex >= len) return -1; - char tempchar = buffer[fromIndex + 1]; - buffer[fromIndex + 1] = '\0'; - char* temp = strrchr( buffer, ch ); - buffer[fromIndex + 1] = tempchar; - if (temp == NULL) return -1; - return temp - buffer; -} - -int String::lastIndexOf(const String &s2) const -{ - return lastIndexOf(s2, len - s2.len); -} - -int String::lastIndexOf(const String &s2, unsigned int fromIndex) const -{ - if (s2.len == 0 || len == 0 || s2.len > len) return -1; - if (fromIndex >= len) fromIndex = len - 1; - int found = -1; - for (char *p = buffer; p <= buffer + fromIndex; p++) { - p = strstr(p, s2.buffer); - if (!p) break; - if ((unsigned int)(p - buffer) <= fromIndex) found = p - buffer; - } - return found; -} - -String String::substring(unsigned int left, unsigned int right) const -{ - if (left > right) { - unsigned int temp = right; - right = left; - left = temp; - } - String out; - if (left >= len) return out; - if (right > len) right = len; - out.copy(buffer + left, right - left); - return out; -} - -/*********************************************/ -/* Modification */ -/*********************************************/ - -void String::replace(char find, char replace) -{ - if (!buffer) return; - for (char *p = buffer; *p; p++) { - if (*p == find) *p = replace; - } -} - -void String::replace(const String& find, const String& replace) -{ - if (len == 0 || find.len == 0) return; - int diff = replace.len - find.len; - char *readFrom = buffer; - char *foundAt; - if (diff == 0) { - while ((foundAt = strstr(readFrom, find.buffer)) != NULL) { - memcpy(foundAt, replace.buffer, replace.len); - readFrom = foundAt + replace.len; - } - } else if (diff < 0) { - unsigned int size = len; // compute size needed for result - while ((foundAt = strstr(readFrom, find.buffer)) != NULL) { - readFrom = foundAt + find.len; - diff = 0 - diff; - size -= diff; - } - if (size == len) return; - int index = len - 1; - while (index >= 0 && (index = lastIndexOf(find, index)) >= 0) { - readFrom = buffer + index + find.len; - memmove(readFrom - diff, readFrom, len - (readFrom - buffer)); - len -= diff; - buffer[len] = 0; - memcpy(buffer + index, replace.buffer, replace.len); - index--; - } - } else { - unsigned int size = len; // compute size needed for result - while ((foundAt = strstr(readFrom, find.buffer)) != NULL) { - readFrom = foundAt + find.len; - size += diff; - } - if (size == len) return; - if (size > capacity && !changeBuffer(size)) return; // XXX: tell user! - int index = len - 1; - while (index >= 0 && (index = lastIndexOf(find, index)) >= 0) { - readFrom = buffer + index + find.len; - memmove(readFrom + diff, readFrom, len - (readFrom - buffer)); - len += diff; - buffer[len] = 0; - memcpy(buffer + index, replace.buffer, replace.len); - index--; - } - } -} - -void String::remove(unsigned int index){ - // Pass the biggest integer as the count. The remove method - // below will take care of truncating it at the end of the - // string. - remove(index, (unsigned int)-1); -} - -void String::remove(unsigned int index, unsigned int count){ - if (index >= len) { return; } - if (count <= 0) { return; } - if (count > len - index) { count = len - index; } - char *writeTo = buffer + index; - len = len - count; - memmove(writeTo, buffer + index + count,len - index); - buffer[len] = 0; -} - -void String::toLowerCase(void) -{ - if (!buffer) return; - for (char *p = buffer; *p; p++) { - *p = tolower(*p); - } -} - -void String::toUpperCase(void) -{ - if (!buffer) return; - for (char *p = buffer; *p; p++) { - *p = toupper(*p); - } -} - -void String::trim(void) -{ - if (!buffer || len == 0) return; - char *begin = buffer; - while (isspace(*begin)) begin++; - char *end = buffer + len - 1; - while (isspace(*end) && end >= begin) end--; - len = end + 1 - begin; - if (begin > buffer) memmove(buffer, begin, len); - buffer[len] = 0; -} - -/*********************************************/ -/* Parsing / Conversion */ -/*********************************************/ - -long String::toInt(void) const -{ - if (buffer) return atol(buffer); - return 0; -} - -float String::toFloat(void) const -{ - return float(toDouble()); -} - -double String::toDouble(void) const -{ - if (buffer) return atof(buffer); - return 0; -} - -} // namespace arduino +#include "../../../ArduinoCore-API/api/String.cpp" diff --git a/cores/rp2040/api/String.h b/cores/rp2040/api/String.h index a3d0d9e89..0516622f1 100644 --- a/cores/rp2040/api/String.h +++ b/cores/rp2040/api/String.h @@ -1,259 +1,2 @@ -/* - String library for Wiring & Arduino - ...mostly rewritten by Paul Stoffregen... - Copyright (c) 2009-10 Hernando Barragan. All right reserved. - Copyright 2011, Paul Stoffregen, paul@pjrc.com - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -*/ - -#ifdef __cplusplus - -#ifndef __ARDUINO_STRINGS__ -#define __ARDUINO_STRINGS__ - -#include -#include -#include -#if defined(__AVR__) -#include "avr/pgmspace.h" -#else -#include "deprecated-avr-comp/avr/pgmspace.h" -#endif - -namespace arduino { - -// When compiling programs with this class, the following gcc parameters -// dramatically increase performance and memory (RAM) efficiency, typically -// with little or no increase in code size. -// -felide-constructors -// -std=c++0x - -class __FlashStringHelper; -#define F(string_literal) (reinterpret_cast(PSTR(string_literal))) - -// An inherited class for holding the result of a concatenation. These -// result objects are assumed to be writable by subsequent concatenations. -class StringSumHelper; - -// The string class -class String -{ - friend class StringSumHelper; - // use a function pointer to allow for "if (s)" without the - // complications of an operator bool(). for more information, see: - // http://www.artima.com/cppsource/safebool.html - typedef void (String::*StringIfHelperType)() const; - void StringIfHelper() const {} - - static size_t const FLT_MAX_DECIMAL_PLACES = 10; - static size_t const DBL_MAX_DECIMAL_PLACES = FLT_MAX_DECIMAL_PLACES; - -public: - // constructors - // creates a copy of the initial value. - // if the initial value is null or invalid, or if memory allocation - // fails, the string will be marked as invalid (i.e. "if (s)" will - // be false). - String(const char *cstr = ""); - String(const char *cstr, unsigned int length); - String(const uint8_t *cstr, unsigned int length) : String((const char*)cstr, length) {} - String(const String &str); - String(const __FlashStringHelper *str); - #if __cplusplus >= 201103L || defined(__GXX_EXPERIMENTAL_CXX0X__) - String(String &&rval); - String(StringSumHelper &&rval); - #endif - explicit String(char c); - explicit String(unsigned char, unsigned char base=10); - explicit String(int, unsigned char base=10); - explicit String(unsigned int, unsigned char base=10); - explicit String(long, unsigned char base=10); - explicit String(unsigned long, unsigned char base=10); - explicit String(float, unsigned char decimalPlaces=2); - explicit String(double, unsigned char decimalPlaces=2); - ~String(void); - - // memory management - // return true on success, false on failure (in which case, the string - // is left unchanged). reserve(0), if successful, will validate an - // invalid string (i.e., "if (s)" will be true afterwards) - unsigned char reserve(unsigned int size); - inline unsigned int length(void) const {return len;} - - // creates a copy of the assigned value. if the value is null or - // invalid, or if the memory allocation fails, the string will be - // marked as invalid ("if (s)" will be false). - String & operator = (const String &rhs); - String & operator = (const char *cstr); - String & operator = (const __FlashStringHelper *str); - #if __cplusplus >= 201103L || defined(__GXX_EXPERIMENTAL_CXX0X__) - String & operator = (String &&rval); - String & operator = (StringSumHelper &&rval); - #endif - - // concatenate (works w/ built-in types) - - // returns true on success, false on failure (in which case, the string - // is left unchanged). if the argument is null or invalid, the - // concatenation is considered unsucessful. - unsigned char concat(const String &str); - unsigned char concat(const char *cstr); - unsigned char concat(const char *cstr, unsigned int length); - unsigned char concat(const uint8_t *cstr, unsigned int length) {return concat((const char*)cstr, length);} - unsigned char concat(char c); - unsigned char concat(unsigned char num); - unsigned char concat(int num); - unsigned char concat(unsigned int num); - unsigned char concat(long num); - unsigned char concat(unsigned long num); - unsigned char concat(float num); - unsigned char concat(double num); - unsigned char concat(const __FlashStringHelper * str); - - // if there's not enough memory for the concatenated value, the string - // will be left unchanged (but this isn't signalled in any way) - String & operator += (const String &rhs) {concat(rhs); return (*this);} - String & operator += (const char *cstr) {concat(cstr); return (*this);} - String & operator += (char c) {concat(c); return (*this);} - String & operator += (unsigned char num) {concat(num); return (*this);} - String & operator += (int num) {concat(num); return (*this);} - String & operator += (unsigned int num) {concat(num); return (*this);} - String & operator += (long num) {concat(num); return (*this);} - String & operator += (unsigned long num) {concat(num); return (*this);} - String & operator += (float num) {concat(num); return (*this);} - String & operator += (double num) {concat(num); return (*this);} - String & operator += (const __FlashStringHelper *str){concat(str); return (*this);} - - friend StringSumHelper & operator + (const StringSumHelper &lhs, const String &rhs); - friend StringSumHelper & operator + (const StringSumHelper &lhs, const char *cstr); - friend StringSumHelper & operator + (const StringSumHelper &lhs, char c); - friend StringSumHelper & operator + (const StringSumHelper &lhs, unsigned char num); - friend StringSumHelper & operator + (const StringSumHelper &lhs, int num); - friend StringSumHelper & operator + (const StringSumHelper &lhs, unsigned int num); - friend StringSumHelper & operator + (const StringSumHelper &lhs, long num); - friend StringSumHelper & operator + (const StringSumHelper &lhs, unsigned long num); - friend StringSumHelper & operator + (const StringSumHelper &lhs, float num); - friend StringSumHelper & operator + (const StringSumHelper &lhs, double num); - friend StringSumHelper & operator + (const StringSumHelper &lhs, const __FlashStringHelper *rhs); - - // comparison (only works w/ Strings and "strings") - operator StringIfHelperType() const { return buffer ? &String::StringIfHelper : 0; } - int compareTo(const String &s) const; - int compareTo(const char *cstr) const; - unsigned char equals(const String &s) const; - unsigned char equals(const char *cstr) const; - - friend unsigned char operator == (const String &a, const String &b) { return a.equals(b); } - friend unsigned char operator == (const String &a, const char *b) { return a.equals(b); } - friend unsigned char operator == (const char *a, const String &b) { return b == a; } - friend unsigned char operator < (const String &a, const String &b) { return a.compareTo(b) < 0; } - friend unsigned char operator < (const String &a, const char *b) { return a.compareTo(b) < 0; } - friend unsigned char operator < (const char *a, const String &b) { return b.compareTo(a) > 0; } - - friend unsigned char operator != (const String &a, const String &b) { return !(a == b); } - friend unsigned char operator != (const String &a, const char *b) { return !(a == b); } - friend unsigned char operator != (const char *a, const String &b) { return !(a == b); } - friend unsigned char operator > (const String &a, const String &b) { return b < a; } - friend unsigned char operator > (const String &a, const char *b) { return b < a; } - friend unsigned char operator > (const char *a, const String &b) { return b < a; } - friend unsigned char operator <= (const String &a, const String &b) { return !(b < a); } - friend unsigned char operator <= (const String &a, const char *b) { return !(b < a); } - friend unsigned char operator <= (const char *a, const String &b) { return !(b < a); } - friend unsigned char operator >= (const String &a, const String &b) { return !(a < b); } - friend unsigned char operator >= (const String &a, const char *b) { return !(a < b); } - friend unsigned char operator >= (const char *a, const String &b) { return !(a < b); } - - unsigned char equalsIgnoreCase(const String &s) const; - unsigned char startsWith( const String &prefix) const; - unsigned char startsWith(const String &prefix, unsigned int offset) const; - unsigned char endsWith(const String &suffix) const; - - // character acccess - char charAt(unsigned int index) const; - void setCharAt(unsigned int index, char c); - char operator [] (unsigned int index) const; - char& operator [] (unsigned int index); - void getBytes(unsigned char *buf, unsigned int bufsize, unsigned int index=0) const; - void toCharArray(char *buf, unsigned int bufsize, unsigned int index=0) const - { getBytes((unsigned char *)buf, bufsize, index); } - const char* c_str() const { return buffer; } - char* begin() { return buffer; } - char* end() { return buffer + length(); } - const char* begin() const { return c_str(); } - const char* end() const { return c_str() + length(); } - - // search - int indexOf( char ch ) const; - int indexOf( char ch, unsigned int fromIndex ) const; - int indexOf( const String &str ) const; - int indexOf( const String &str, unsigned int fromIndex ) const; - int lastIndexOf( char ch ) const; - int lastIndexOf( char ch, unsigned int fromIndex ) const; - int lastIndexOf( const String &str ) const; - int lastIndexOf( const String &str, unsigned int fromIndex ) const; - String substring( unsigned int beginIndex ) const { return substring(beginIndex, len); }; - String substring( unsigned int beginIndex, unsigned int endIndex ) const; - - // modification - void replace(char find, char replace); - void replace(const String& find, const String& replace); - void remove(unsigned int index); - void remove(unsigned int index, unsigned int count); - void toLowerCase(void); - void toUpperCase(void); - void trim(void); - - // parsing/conversion - long toInt(void) const; - float toFloat(void) const; - double toDouble(void) const; - -protected: - char *buffer; // the actual char array - unsigned int capacity; // the array length minus one (for the '\0') - unsigned int len; // the String length (not counting the '\0') -protected: - void init(void); - void invalidate(void); - unsigned char changeBuffer(unsigned int maxStrLen); - - // copy and move - String & copy(const char *cstr, unsigned int length); - String & copy(const __FlashStringHelper *pstr, unsigned int length); - #if __cplusplus >= 201103L || defined(__GXX_EXPERIMENTAL_CXX0X__) - void move(String &rhs); - #endif -}; - -class StringSumHelper : public String -{ -public: - StringSumHelper(const String &s) : String(s) {} - StringSumHelper(const char *p) : String(p) {} - StringSumHelper(char c) : String(c) {} - StringSumHelper(unsigned char num) : String(num) {} - StringSumHelper(int num) : String(num) {} - StringSumHelper(unsigned int num) : String(num) {} - StringSumHelper(long num) : String(num) {} - StringSumHelper(unsigned long num) : String(num) {} - StringSumHelper(float num) : String(num) {} - StringSumHelper(double num) : String(num) {} -}; - -} // namespace arduino - -#endif // __cplusplus -#endif // __ARDUINO_STRINGS__ +#pragma once +#include "../../../ArduinoCore-API/api/String.h" diff --git a/cores/rp2040/api/USBAPI.h b/cores/rp2040/api/USBAPI.h index ba5e87cec..3d4e1522d 100644 --- a/cores/rp2040/api/USBAPI.h +++ b/cores/rp2040/api/USBAPI.h @@ -1,64 +1,2 @@ -/* - USBAPI.h - Copyright (c) 2005-2014 Arduino. All right reserved. - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -*/ - -#ifndef __USBAPI__ -#define __USBAPI__ - -#include - -namespace arduino { -//================================================================================ -//================================================================================ -// Low level API - -typedef struct __attribute__((packed)) -{ - union { - uint8_t bmRequestType; - struct { - uint8_t direction : 5; - uint8_t type : 2; - uint8_t transferDirection : 1; - }; - }; - uint8_t bRequest; - uint8_t wValueL; - uint8_t wValueH; - uint16_t wIndex; - uint16_t wLength; -} USBSetup; - -} - -//================================================================================ -// USB APIs (C scope) -//================================================================================ - -int USB_SendControl(uint8_t flags, const void* d, int len); -int USB_RecvControl(void* d, int len); -int USB_RecvControlLong(void* d, int len); - -uint8_t USB_Available(uint8_t ep); -uint8_t USB_SendSpace(uint8_t ep); -int USB_Send(uint8_t ep, const void* data, int len); // blocking -int USB_Recv(uint8_t ep, void* data, int len); // non-blocking -int USB_Recv(uint8_t ep); // non-blocking -void USB_Flush(uint8_t ep); - -#endif \ No newline at end of file +#pragma once +#include "../../../ArduinoCore-API/api/USBAPI.h" diff --git a/cores/rp2040/api/Udp.h b/cores/rp2040/api/Udp.h index 53f89f9ae..df815cd67 100644 --- a/cores/rp2040/api/Udp.h +++ b/cores/rp2040/api/Udp.h @@ -1,92 +1,2 @@ -/* - * Udp.cpp: Library to send/receive UDP packets. - * - * NOTE: UDP is fast, but has some important limitations (thanks to Warren Gray for mentioning these) - * 1) UDP does not guarantee the order in which assembled UDP packets are received. This - * might not happen often in practice, but in larger network topologies, a UDP - * packet can be received out of sequence. - * 2) UDP does not guard against lost packets - so packets *can* disappear without the sender being - * aware of it. Again, this may not be a concern in practice on small local networks. - * For more information, see http://www.cafeaulait.org/course/week12/35.html - * - * MIT License: - * Copyright (c) 2008 Bjoern Hartmann - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * bjoern@cs.stanford.edu 12/30/2008 - */ - #pragma once - -#include "Stream.h" -#include "IPAddress.h" - -namespace arduino { - -class UDP : public Stream { - -public: - virtual uint8_t begin(uint16_t) =0; // initialize, start listening on specified port. Returns 1 if successful, 0 if there are no sockets available to use - virtual uint8_t beginMulticast(IPAddress, uint16_t) { return 0; } // initialize, start listening on specified multicast IP address and port. Returns 1 if successful, 0 on failure - virtual void stop() =0; // Finish with the UDP socket - - // Sending UDP packets - - // Start building up a packet to send to the remote host specific in ip and port - // Returns 1 if successful, 0 if there was a problem with the supplied IP address or port - virtual int beginPacket(IPAddress ip, uint16_t port) =0; - // Start building up a packet to send to the remote host specific in host and port - // Returns 1 if successful, 0 if there was a problem resolving the hostname or port - virtual int beginPacket(const char *host, uint16_t port) =0; - // Finish off this packet and send it - // Returns 1 if the packet was sent successfully, 0 if there was an error - virtual int endPacket() =0; - // Write a single byte into the packet - virtual size_t write(uint8_t) =0; - // Write size bytes from buffer into the packet - virtual size_t write(const uint8_t *buffer, size_t size) =0; - - // Start processing the next available incoming packet - // Returns the size of the packet in bytes, or 0 if no packets are available - virtual int parsePacket() =0; - // Number of bytes remaining in the current packet - virtual int available() =0; - // Read a single byte from the current packet - virtual int read() =0; - // Read up to len bytes from the current packet and place them into buffer - // Returns the number of bytes read, or 0 if none are available - virtual int read(unsigned char* buffer, size_t len) =0; - // Read up to len characters from the current packet and place them into buffer - // Returns the number of characters read, or 0 if none are available - virtual int read(char* buffer, size_t len) =0; - // Return the next byte from the current packet without moving on to the next byte - virtual int peek() =0; - virtual void flush() =0; // Finish reading the current packet - - // Return the IP address of the host who sent the current incoming packet - virtual IPAddress remoteIP() =0; - // Return the port of the host who sent the current incoming packet - virtual uint16_t remotePort() =0; -protected: - uint8_t* rawIPAddress(IPAddress& addr) { return addr.raw_address(); }; -}; - -} - -using namespace arduino; +#include "../../../ArduinoCore-API/api/Udp.h" diff --git a/cores/rp2040/api/WCharacter.h b/cores/rp2040/api/WCharacter.h index 68c0e7938..a38441167 100644 --- a/cores/rp2040/api/WCharacter.h +++ b/cores/rp2040/api/WCharacter.h @@ -1,171 +1,2 @@ -/* - WCharacter.h - Character utility functions for Wiring & Arduino - Copyright (c) 2010 Hernando Barragan. All right reserved. - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef Character_h -#define Character_h - -#include - -namespace arduino { - -// WCharacter.h prototypes -inline bool isAlphaNumeric(int c) __attribute__((always_inline)); -inline bool isAlpha(int c) __attribute__((always_inline)); -inline bool isAscii(int c) __attribute__((always_inline)); -inline bool isWhitespace(int c) __attribute__((always_inline)); -inline bool isControl(int c) __attribute__((always_inline)); -inline bool isDigit(int c) __attribute__((always_inline)); -inline bool isGraph(int c) __attribute__((always_inline)); -inline bool isLowerCase(int c) __attribute__((always_inline)); -inline bool isPrintable(int c) __attribute__((always_inline)); -inline bool isPunct(int c) __attribute__((always_inline)); -inline bool isSpace(int c) __attribute__((always_inline)); -inline bool isUpperCase(int c) __attribute__((always_inline)); -inline bool isHexadecimalDigit(int c) __attribute__((always_inline)); -inline int toAscii(int c) __attribute__((always_inline)); -inline int toLowerCase(int c) __attribute__((always_inline)); -inline int toUpperCase(int c)__attribute__((always_inline)); - - -// Checks for an alphanumeric character. -// It is equivalent to (isalpha(c) || isdigit(c)). -inline bool isAlphaNumeric(int c) -{ - return ( isalnum(c) == 0 ? false : true); -} - - -// Checks for an alphabetic character. -// It is equivalent to (isupper(c) || islower(c)). -inline bool isAlpha(int c) -{ - return ( isalpha(c) == 0 ? false : true); -} - - -// Checks whether c is a 7-bit unsigned char value -// that fits into the ASCII character set. -inline bool isAscii(int c) -{ - return ( isascii (c) == 0 ? false : true); -} - - -// Checks for a blank character, that is, a space or a tab. -inline bool isWhitespace(int c) -{ - return ( isblank (c) == 0 ? false : true); -} - - -// Checks for a control character. -inline bool isControl(int c) -{ - return ( iscntrl (c) == 0 ? false : true); -} - - -// Checks for a digit (0 through 9). -inline bool isDigit(int c) -{ - return ( isdigit (c) == 0 ? false : true); -} - - -// Checks for any printable character except space. -inline bool isGraph(int c) -{ - return ( isgraph (c) == 0 ? false : true); -} - - -// Checks for a lower-case character. -inline bool isLowerCase(int c) -{ - return (islower (c) == 0 ? false : true); -} - - -// Checks for any printable character including space. -inline bool isPrintable(int c) -{ - return ( isprint (c) == 0 ? false : true); -} - - -// Checks for any printable character which is not a space -// or an alphanumeric character. -inline bool isPunct(int c) -{ - return ( ispunct (c) == 0 ? false : true); -} - - -// Checks for white-space characters. For the avr-libc library, -// these are: space, formfeed ('\f'), newline ('\n'), carriage -// return ('\r'), horizontal tab ('\t'), and vertical tab ('\v'). -inline bool isSpace(int c) -{ - return ( isspace (c) == 0 ? false : true); -} - - -// Checks for an uppercase letter. -inline bool isUpperCase(int c) -{ - return ( isupper (c) == 0 ? false : true); -} - - -// Checks for a hexadecimal digits, i.e. one of 0 1 2 3 4 5 6 7 -// 8 9 a b c d e f A B C D E F. -inline bool isHexadecimalDigit(int c) -{ - return ( isxdigit (c) == 0 ? false : true); -} - - -// Converts c to a 7-bit unsigned char value that fits into the -// ASCII character set, by clearing the high-order bits. -inline int toAscii(int c) -{ - return toascii (c); -} - - -// Warning: -// Many people will be unhappy if you use this function. -// This function will convert accented letters into random -// characters. - -// Converts the letter c to lower case, if possible. -inline int toLowerCase(int c) -{ - return tolower (c); -} - - -// Converts the letter c to upper case, if possible. -inline int toUpperCase(int c) -{ - return toupper (c); -} - -} -#endif \ No newline at end of file +#pragma once +#include "../../../ArduinoCore-API/api/WCharacter.h" diff --git a/cores/rp2040/api/deprecated-avr-comp/avr/dtostrf.c.impl b/cores/rp2040/api/deprecated-avr-comp/avr/dtostrf.c.impl index 96987a8f8..11f8665a9 100644 --- a/cores/rp2040/api/deprecated-avr-comp/avr/dtostrf.c.impl +++ b/cores/rp2040/api/deprecated-avr-comp/avr/dtostrf.c.impl @@ -1,37 +1 @@ -/* - dtostrf - Emulation for dtostrf function from avr-libc - Copyright (c) 2016 Arduino LLC. All rights reserved. - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -*/ - -// This is a default implementation for dtostrf function. -// This file should be used if the standard lib doesn't provide an -// implementation of dtostrf. - -// Create a file called "dtostrf.c" with the following include: -// #include "api/deprecated-avr-comp/avr/dtostrf.c.impl" - -#include - -char *dtostrf (double val, signed char width, unsigned char prec, char *sout) { - asm(".global _printf_float"); - - char fmt[20]; - sprintf(fmt, "%%%d.%df", width, prec); - sprintf(sout, fmt, val); - return sout; -} - +#include "../../../../../ArduinoCore-API/api/deprecated-avr-comp/avr/dtostrf.c.impl" diff --git a/cores/rp2040/api/deprecated-avr-comp/avr/dtostrf.h b/cores/rp2040/api/deprecated-avr-comp/avr/dtostrf.h index 2d287ca1b..c2b201e65 100644 --- a/cores/rp2040/api/deprecated-avr-comp/avr/dtostrf.h +++ b/cores/rp2040/api/deprecated-avr-comp/avr/dtostrf.h @@ -1,34 +1,2 @@ -/* - dtostrf - Emulation for dtostrf function from avr-libc - Copyright (c) 2015 Arduino LLC. All rights reserved. - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -*/ - #pragma once - -#if !defined(ARDUINO_ARCH_AVR) - -#ifdef __cplusplus -extern "C" { -#endif - -char *dtostrf(double val, signed char width, unsigned char prec, char *sout); - -#ifdef __cplusplus -} -#endif - -#endif +#include "../../../../../ArduinoCore-API/api/deprecated-avr-comp/avr/dtostrf.h" diff --git a/cores/rp2040/api/deprecated-avr-comp/avr/interrupt.h b/cores/rp2040/api/deprecated-avr-comp/avr/interrupt.h index 950509dde..eab8a5ee8 100644 --- a/cores/rp2040/api/deprecated-avr-comp/avr/interrupt.h +++ b/cores/rp2040/api/deprecated-avr-comp/avr/interrupt.h @@ -1,23 +1,2 @@ -/* - Copyright (c) 2015 Arduino LCC. All right reserved. - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - See the GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -*/ - -/* - Empty file. - This file is here to allow compatibility with sketches (made for AVR) - that includes -*/ +#pragma once +#include "../../../../../ArduinoCore-API/api/deprecated-avr-comp/avr/interrupt.h" diff --git a/cores/rp2040/api/deprecated-avr-comp/avr/pgmspace.h b/cores/rp2040/api/deprecated-avr-comp/avr/pgmspace.h index 42df89402..095aa21f9 100644 --- a/cores/rp2040/api/deprecated-avr-comp/avr/pgmspace.h +++ b/cores/rp2040/api/deprecated-avr-comp/avr/pgmspace.h @@ -1,158 +1,2 @@ -/* - pgmspace.h - Definitions for compatibility with AVR pgmspace macros - - Copyright (c) 2015 Arduino LLC - - Based on work of Paul Stoffregen on Teensy 3 (http://pjrc.com) - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE -*/ - -#ifndef __PGMSPACE_H_ -#define __PGMSPACE_H_ 1 - -#include - -#define PROGMEM -#define PGM_P const char * -#define PSTR(str) (str) - -#define _SFR_BYTE(n) (n) - -typedef void prog_void; -typedef char prog_char; -typedef unsigned char prog_uchar; -typedef int8_t prog_int8_t; -typedef uint8_t prog_uint8_t; -typedef int16_t prog_int16_t; -typedef uint16_t prog_uint16_t; -typedef int32_t prog_int32_t; -typedef uint32_t prog_uint32_t; -typedef int64_t prog_int64_t; -typedef uint64_t prog_uint64_t; - -typedef const void* int_farptr_t; -typedef const void* uint_farptr_t; - -#define memchr_P(s, c, n) memchr((s), (c), (n)) -#define memcmp_P(s1, s2, n) memcmp((s1), (s2), (n)) -#define memccpy_P(dest, src, c, n) memccpy((dest), (src), (c), (n)) -#define memcpy_P(dest, src, n) memcpy((dest), (src), (n)) -#define memmem_P(haystack, haystacklen, needle, needlelen) memmem((haystack), (haystacklen), (needle), (needlelen)) -#define memrchr_P(s, c, n) memrchr((s), (c), (n)) -#define strcat_P(dest, src) strcat((dest), (src)) -#define strchr_P(s, c) strchr((s), (c)) -#define strchrnul_P(s, c) strchrnul((s), (c)) -#define strcmp_P(a, b) strcmp((a), (b)) -#define strcpy_P(dest, src) strcpy((dest), (src)) -#define strcasecmp_P(s1, s2) strcasecmp((s1), (s2)) -#define strcasestr_P(haystack, needle) strcasestr((haystack), (needle)) -#define strcspn_P(s, accept) strcspn((s), (accept)) -#define strlcat_P(s1, s2, n) strlcat((s1), (s2), (n)) -#define strlcpy_P(s1, s2, n) strlcpy((s1), (s2), (n)) -#define strlen_P(a) strlen((a)) -#define strnlen_P(s, n) strnlen((s), (n)) -#define strncmp_P(s1, s2, n) strncmp((s1), (s2), (n)) -#define strncasecmp_P(s1, s2, n) strncasecmp((s1), (s2), (n)) -#define strncat_P(s1, s2, n) strncat((s1), (s2), (n)) -#define strncpy_P(s1, s2, n) strncpy((s1), (s2), (n)) -#define strpbrk_P(s, accept) strpbrk((s), (accept)) -#define strrchr_P(s, c) strrchr((s), (c)) -#define strsep_P(sp, delim) strsep((sp), (delim)) -#define strspn_P(s, accept) strspn((s), (accept)) -#define strstr_P(a, b) strstr((a), (b)) -#define strtok_P(s, delim) strtok((s), (delim)) -#define strtok_rP(s, delim, last) strtok((s), (delim), (last)) - -#define strlen_PF(a) strlen((a)) -#define strnlen_PF(src, len) strnlen((src), (len)) -#define memcpy_PF(dest, src, len) memcpy((dest), (src), (len)) -#define strcpy_PF(dest, src) strcpy((dest), (src)) -#define strncpy_PF(dest, src, len) strncpy((dest), (src), (len)) -#define strcat_PF(dest, src) strcat((dest), (src)) -#define strlcat_PF(dest, src, len) strlcat((dest), (src), (len)) -#define strncat_PF(dest, src, len) strncat((dest), (src), (len)) -#define strcmp_PF(s1, s2) strcmp((s1), (s2)) -#define strncmp_PF(s1, s2, n) strncmp((s1), (s2), (n)) -#define strcasecmp_PF(s1, s2) strcasecmp((s1), (s2)) -#define strncasecmp_PF(s1, s2, n) strncasecmp((s1), (s2), (n)) -#define strstr_PF(s1, s2) strstr((s1), (s2)) -#define strlcpy_PF(dest, src, n) strlcpy((dest), (src), (n)) -#define memcmp_PF(s1, s2, n) memcmp((s1), (s2), (n)) - -#define sprintf_P(s, f, ...) sprintf((s), (f), __VA_ARGS__) -#define snprintf_P(s, f, ...) snprintf((s), (f), __VA_ARGS__) -#define vsprintf_P(s, f, ...) vsprintf((s), (f), __VA_ARGS__) -#define vsnprintf_P(s, f, ...) vsnprintf((s), (f), __VA_ARGS__) - -#if 0 -// Requires natural aligned addresses -#define pgm_read_byte(addr) (*(const unsigned char *)(addr)) -#define pgm_read_word(addr) (*(const unsigned short *)(addr)) -#define pgm_read_dword(addr) (*(const unsigned long *)(addr)) -#define pgm_read_float(addr) (*(const float *)(addr)) -#define pgm_read_ptr(addr) (*(void *const *)(addr)) -#else -// Supports misaligned addresses -#ifdef __cplusplus -extern "C"{ -#endif -static inline unsigned char pgm_read_byte(const void *addr) { - return *(const unsigned char *)(addr); -} -static inline unsigned short pgm_read_word(const void *addr) { - const unsigned char *a = (const unsigned char *)addr; - return pgm_read_byte(a) | ( pgm_read_byte(a + 1) << 8 ); -} -static inline unsigned long pgm_read_dword(const void *addr) { - const unsigned char *a = (const unsigned char *)addr; - return pgm_read_byte(a) | ( pgm_read_byte(a + 1) << 8 ) | ( pgm_read_byte(a + 2) << 16 ) | ( pgm_read_byte(a + 3) << 24 ); -} -static inline void *pgm_read_ptr(const void *addr) { - return (void*) pgm_read_dword(addr); -} -static inline float pgm_read_float(const void *addr) { - union { - void *p; - float f; - } x; - x.p = pgm_read_ptr(addr); - return x.f; -} -#ifdef __cplusplus -} -#endif - -#endif - -#define pgm_read_byte_near(addr) pgm_read_byte(addr) -#define pgm_read_word_near(addr) pgm_read_word(addr) -#define pgm_read_dword_near(addr) pgm_read_dword(addr) -#define pgm_read_float_near(addr) pgm_read_float(addr) -#define pgm_read_ptr_near(addr) pgm_read_ptr(addr) - -#define pgm_read_byte_far(addr) pgm_read_byte(addr) -#define pgm_read_word_far(addr) pgm_read_word(addr) -#define pgm_read_dword_far(addr) pgm_read_dword(addr) -#define pgm_read_float_far(addr) pgm_read_float(addr) -#define pgm_read_ptr_far(addr) pgm_read_ptr(addr) - -#define pgm_get_far_address(addr) (&(addr)) - -#endif +#pragma once +#include "../../../../../ArduinoCore-API/api/deprecated-avr-comp/avr/pgmspace.h" diff --git a/cores/rp2040/api/itoa.h b/cores/rp2040/api/itoa.h index 55b28493e..9dcd42c70 100644 --- a/cores/rp2040/api/itoa.h +++ b/cores/rp2040/api/itoa.h @@ -1,37 +1,2 @@ -/* - Copyright (c) 2016 Arduino LLC. All right reserved. - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - See the GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -*/ - #pragma once - -// Standard C functions required in Arduino API -// If these functions are not provided by the standard library, the -// core should supply an implementation of them. - -#ifdef __cplusplus -extern "C" { -#endif - -extern char* itoa(int value, char *string, int radix); -extern char* ltoa(long value, char *string, int radix); -extern char* utoa(unsigned value, char *string, int radix); -extern char* ultoa(unsigned long value, char *string, int radix); - -#ifdef __cplusplus -} // extern "C" -#endif - +#include "../../../ArduinoCore-API/api/itoa.h" diff --git a/cores/rp2040/cyw43_wrappers.cpp b/cores/rp2040/cyw43_wrappers.cpp new file mode 100644 index 000000000..9ac0b9604 --- /dev/null +++ b/cores/rp2040/cyw43_wrappers.cpp @@ -0,0 +1,104 @@ +/* + CYW43 TCP/Ethernet wrappers + Copyright (c) 2023 Earle F. Philhower, III + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#if defined(ARDUINO_RASPBERRY_PI_PICO_W) + +#include +extern "C" { +#include +#include +} +#include +#include + +// From cyw43_ctrl.c +#define WIFI_JOIN_STATE_KIND_MASK (0x000f) +#define WIFI_JOIN_STATE_ACTIVE (0x0001) +#define WIFI_JOIN_STATE_FAIL (0x0002) +#define WIFI_JOIN_STATE_NONET (0x0003) +#define WIFI_JOIN_STATE_BADAUTH (0x0004) +#define WIFI_JOIN_STATE_AUTH (0x0200) +#define WIFI_JOIN_STATE_LINK (0x0400) +#define WIFI_JOIN_STATE_KEYED (0x0800) +#define WIFI_JOIN_STATE_ALL (0x0e01) + +// The core can't directly call a library, so put in a dummy weak one to be overridden by one in lwip_cyw43 library +extern struct netif *__getCYW43Netif() __attribute__((weak)); +struct netif *__getCYW43Netif() { + return nullptr; +} + +// CB from the cyw43 driver +extern "C" void __wrap_cyw43_cb_process_ethernet(void *cb_data, int itf, size_t len, const uint8_t *buf) { + (void) cb_data; + (void) itf; + struct netif *netif = __getCYW43Netif(); + if (netif && (netif->flags & NETIF_FLAG_LINK_UP)) { + struct pbuf *p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL); + if (p != nullptr) { + pbuf_take(p, buf, len); + if ((netif->input(p, netif) != ERR_OK)) { + pbuf_free(p); + } + CYW43_STAT_INC(PACKET_IN_COUNT); + } + } +} + +extern "C" void __wrap_cyw43_cb_tcpip_set_link_up(cyw43_t *self, int itf) { + (void) self; + (void) itf; + struct netif *netif = __getCYW43Netif(); + if (netif) { + netif_set_link_up(netif); + } +} + +extern "C" void __wrap_cyw43_cb_tcpip_set_link_down(cyw43_t *self, int itf) { + (void) self; + (void) itf; + struct netif *netif = __getCYW43Netif(); + if (netif) { + netif_set_link_down(netif); + } + self->wifi_join_state &= ~WIFI_JOIN_STATE_ACTIVE; +} + +extern "C" int __wrap_cyw43_tcpip_link_status(cyw43_t *self, int itf) { + struct netif *netif = __getCYW43Netif(); + //if ((CYW43::_netif->flags & (NETIF_FLAG_UP | NETIF_FLAG_LINK_UP)) == (NETIF_FLAG_UP | NETIF_FLAG_LINK_UP)) + // Fake this since it's only used in the SDK + if (netif && ((netif->flags & (NETIF_FLAG_LINK_UP)) == (NETIF_FLAG_LINK_UP))) { + return CYW43_LINK_UP; + } else { + return cyw43_wifi_link_status(self, itf); + } +} + +// CBs from the SDK, not needed here as we do TCP later in the game +extern "C" void __wrap_cyw43_cb_tcpip_init(cyw43_t *self, int itf) { + (void) self; + (void) itf; +} +extern "C" void __wrap_cyw43_cb_tcpip_deinit(cyw43_t *self, int itf) { + (void) self; + (void) itf; +} + +#endif diff --git a/cores/rp2040/debug_internal.h b/cores/rp2040/debug_internal.h index 4f5f8d643..81026fb9a 100644 --- a/cores/rp2040/debug_internal.h +++ b/cores/rp2040/debug_internal.h @@ -18,6 +18,8 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ +#pragma once + #if !defined(DEBUG_RP2040_PORT) #define DEBUGV(...) do { } while(0) #define DEBUGCORE(...) do { } while(0) @@ -44,3 +46,7 @@ #define DEBUGSPI(...) do { } while(0) #endif #endif + +#ifdef __cplusplus +extern void hexdump(const void* mem, uint32_t len, uint8_t cols = 16); +#endif diff --git a/cores/rp2040/libb64/AUTHORS b/cores/rp2040/libb64/AUTHORS new file mode 100755 index 000000000..af6873756 --- /dev/null +++ b/cores/rp2040/libb64/AUTHORS @@ -0,0 +1,7 @@ +libb64: Base64 Encoding/Decoding Routines +====================================== + +Authors: +------- + +Chris Venter chris.venter@gmail.com http://rocketpod.blogspot.com diff --git a/cores/rp2040/libb64/LICENSE b/cores/rp2040/libb64/LICENSE new file mode 100755 index 000000000..a6b56069e --- /dev/null +++ b/cores/rp2040/libb64/LICENSE @@ -0,0 +1,29 @@ +Copyright-Only Dedication (based on United States law) +or Public Domain Certification + +The person or persons who have associated work with this document (the +"Dedicator" or "Certifier") hereby either (a) certifies that, to the best of +his knowledge, the work of authorship identified is in the public domain of the +country from which the work is published, or (b) hereby dedicates whatever +copyright the dedicators holds in the work of authorship identified below (the +"Work") to the public domain. A certifier, moreover, dedicates any copyright +interest he may have in the associated work, and for these purposes, is +described as a "dedicator" below. + +A certifier has taken reasonable steps to verify the copyright status of this +work. Certifier recognizes that his good faith efforts may not shield him from +liability if in fact the work certified is not in the public domain. + +Dedicator makes this dedication for the benefit of the public at large and to +the detriment of the Dedicator's heirs and successors. Dedicator intends this +dedication to be an overt act of relinquishment in perpetuity of all present +and future rights under copyright law, whether vested or contingent, in the +Work. Dedicator understands that such relinquishment of all rights includes +the relinquishment of all rights to enforce (by lawsuit or otherwise) those +copyrights in the Work. + +Dedicator recognizes that, once placed in the public domain, the Work may be +freely reproduced, distributed, transmitted, used, modified, built upon, or +otherwise exploited by anyone for any purpose, commercial or non-commercial, +and in any way, including by methods that have not yet been invented or +conceived. \ No newline at end of file diff --git a/cores/rp2040/libb64/cdecode.cpp b/cores/rp2040/libb64/cdecode.cpp new file mode 100755 index 000000000..670a9714a --- /dev/null +++ b/cores/rp2040/libb64/cdecode.cpp @@ -0,0 +1,111 @@ +/* + cdecoder.c - c source to a base64 decoding algorithm implementation + + This is part of the libb64 project, and has been placed in the public domain. + For details, see http://sourceforge.net/projects/libb64 +*/ + +#include +#include +#include "cdecode.h" + +extern "C" { + + static int base64_decode_value_signed(int8_t value_in) { + static const int8_t decoding[] PROGMEM = {62, -1, -1, -1, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -2, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51}; + static const int8_t decoding_size = sizeof(decoding); + value_in -= 43; + if (value_in < 0 || value_in > decoding_size) { + return -1; + } + return pgm_read_byte(&decoding[(int)value_in]); + } + + void base64_init_decodestate(base64_decodestate* state_in) { + state_in->step = step_a; + state_in->plainchar = 0; + } + + static int base64_decode_block_signed(const int8_t* code_in, const int length_in, int8_t* plaintext_out, base64_decodestate* state_in) { + const int8_t* codechar = code_in; + int8_t* plainchar = plaintext_out; + int8_t fragment; + + *plainchar = state_in->plainchar; + + switch (state_in->step) { + while (1) { + case step_a: + do { + if (codechar == code_in + length_in) { + state_in->step = step_a; + state_in->plainchar = *plainchar; + return plainchar - plaintext_out; + } + fragment = (int8_t)base64_decode_value_signed(*codechar++); + } while (fragment < 0); + *plainchar = (fragment & 0x03f) << 2; + // falls through + case step_b: + do { + if (codechar == code_in + length_in) { + state_in->step = step_b; + state_in->plainchar = *plainchar; + return plainchar - plaintext_out; + } + fragment = (int8_t)base64_decode_value_signed(*codechar++); + } while (fragment < 0); + *plainchar++ |= (fragment & 0x030) >> 4; + *plainchar = (fragment & 0x00f) << 4; + // falls through + case step_c: + do { + if (codechar == code_in + length_in) { + state_in->step = step_c; + state_in->plainchar = *plainchar; + return plainchar - plaintext_out; + } + fragment = (int8_t)base64_decode_value_signed(*codechar++); + } while (fragment < 0); + *plainchar++ |= (fragment & 0x03c) >> 2; + *plainchar = (fragment & 0x003) << 6; + // falls through + case step_d: + do { + if (codechar == code_in + length_in) { + state_in->step = step_d; + state_in->plainchar = *plainchar; + return plainchar - plaintext_out; + } + fragment = (int8_t)base64_decode_value_signed(*codechar++); + } while (fragment < 0); + *plainchar++ |= (fragment & 0x03f); + } + } + /* control should not reach here */ + return plainchar - plaintext_out; + } + + static int base64_decode_chars_signed(const int8_t* code_in, const int length_in, int8_t* plaintext_out) { + base64_decodestate _state; + base64_init_decodestate(&_state); + int len = base64_decode_block_signed(code_in, length_in, plaintext_out, &_state); + if (len > 0) { + plaintext_out[len] = 0; + } + return len; + } + + int base64_decode_value(char value_in) { + return base64_decode_value_signed(*((int8_t *) &value_in)); + } + + int base64_decode_block(const char* code_in, const int length_in, char* plaintext_out, base64_decodestate* state_in) { + return base64_decode_block_signed((int8_t *) code_in, length_in, (int8_t *) plaintext_out, state_in); + } + + int base64_decode_chars(const char* code_in, const int length_in, char* plaintext_out) { + return base64_decode_chars_signed((int8_t *) code_in, length_in, (int8_t *) plaintext_out); + } + +}; diff --git a/cores/rp2040/libb64/cdecode.h b/cores/rp2040/libb64/cdecode.h new file mode 100755 index 000000000..3a6346137 --- /dev/null +++ b/cores/rp2040/libb64/cdecode.h @@ -0,0 +1,35 @@ +/* + cdecode.h - c header for a base64 decoding algorithm + + This is part of the libb64 project, and has been placed in the public domain. + For details, see http://sourceforge.net/projects/libb64 +*/ + +#pragma once + +#define base64_decode_expected_len(n) ((n * 3) / 4) + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum { + step_a, step_b, step_c, step_d +} base64_decodestep; + +typedef struct { + base64_decodestep step; + char plainchar; +} base64_decodestate; + +void base64_init_decodestate(base64_decodestate* state_in); + +int base64_decode_value(char value_in); + +int base64_decode_block(const char* code_in, const int length_in, char* plaintext_out, base64_decodestate* state_in); + +int base64_decode_chars(const char* code_in, const int length_in, char* plaintext_out); + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/cores/rp2040/libb64/cencode.cpp b/cores/rp2040/libb64/cencode.cpp new file mode 100755 index 000000000..c2af544f3 --- /dev/null +++ b/cores/rp2040/libb64/cencode.cpp @@ -0,0 +1,126 @@ +/* + cencoder.c - c source to a base64 encoding algorithm implementation + + This is part of the libb64 project, and has been placed in the public domain. + For details, see http://sourceforge.net/projects/libb64 +*/ + +#include "cencode.h" + +extern "C" { + + void base64_init_encodestate(base64_encodestate* state_in) { + state_in->step = step_A; + state_in->result = 0; + state_in->stepcount = 0; + state_in->stepsnewline = BASE64_CHARS_PER_LINE; + } + + + void base64_init_encodestate_nonewlines(base64_encodestate* state_in) { + base64_init_encodestate(state_in); + state_in->stepsnewline = -1; + } + + char base64_encode_value(const char n) { + char r; + + if (n < 26) { + r = n + 'A'; + } else if (n < 26 + 26) { + r = n - 26 + 'a'; + } else if (n < 26 + 26 + 10) { + r = n - 26 - 26 + '0'; + } else if (n == 62) { + r = '+'; + } else { + r = '/'; + } + return r; + } + + int base64_encode_block(const char* plaintext_in, int length_in, char* code_out, base64_encodestate* state_in) { + const char* plainchar = plaintext_in; + const char* const plaintextend = plaintext_in + length_in; + char* codechar = code_out; + char result; + char fragment; + + result = state_in->result; + + switch (state_in->step) { + while (1) { + case step_A: + if (plainchar == plaintextend) { + state_in->result = result; + state_in->step = step_A; + return codechar - code_out; + } + fragment = *plainchar++; + result = (fragment & 0x0fc) >> 2; + *codechar++ = base64_encode_value(result); + result = (fragment & 0x003) << 4; + // falls through + case step_B: + if (plainchar == plaintextend) { + state_in->result = result; + state_in->step = step_B; + return codechar - code_out; + } + fragment = *plainchar++; + result |= (fragment & 0x0f0) >> 4; + *codechar++ = base64_encode_value(result); + result = (fragment & 0x00f) << 2; + // falls through + case step_C: + if (plainchar == plaintextend) { + state_in->result = result; + state_in->step = step_C; + return codechar - code_out; + } + fragment = *plainchar++; + result |= (fragment & 0x0c0) >> 6; + *codechar++ = base64_encode_value(result); + result = (fragment & 0x03f) >> 0; + *codechar++ = base64_encode_value(result); + + ++(state_in->stepcount); + if ((state_in->stepcount == BASE64_CHARS_PER_LINE / 4) && (state_in->stepsnewline > 0)) { + *codechar++ = '\n'; + state_in->stepcount = 0; + } + } + } + /* control should not reach here */ + return codechar - code_out; + } + + int base64_encode_blockend(char* code_out, base64_encodestate* state_in) { + char* codechar = code_out; + + switch (state_in->step) { + case step_B: + *codechar++ = base64_encode_value(state_in->result); + *codechar++ = '='; + *codechar++ = '='; + break; + case step_C: + *codechar++ = base64_encode_value(state_in->result); + *codechar++ = '='; + break; + case step_A: + break; + } + *codechar = 0x00; + + return codechar - code_out; + } + + int base64_encode_chars(const char* plaintext_in, int length_in, char* code_out) { + base64_encodestate _state; + base64_init_encodestate(&_state); + int len = base64_encode_block(plaintext_in, length_in, code_out, &_state); + return len + base64_encode_blockend((code_out + len), &_state); + } + +}; diff --git a/cores/rp2040/libb64/cencode.h b/cores/rp2040/libb64/cencode.h new file mode 100755 index 000000000..ef3468f34 --- /dev/null +++ b/cores/rp2040/libb64/cencode.h @@ -0,0 +1,45 @@ +/* + cencode.h - c header for a base64 encoding algorithm + + This is part of the libb64 project, and has been placed in the public domain. + For details, see http://sourceforge.net/projects/libb64 +*/ + +#pragma once + +#define BASE64_CHARS_PER_LINE 72 + +#define base64_encode_expected_len_nonewlines(n) ((((4 * (n)) / 3) + 3) & ~3) +#define base64_encode_expected_len(n) \ + (base64_encode_expected_len_nonewlines(n) + ((n / ((BASE64_CHARS_PER_LINE * 3) / 4)) + 1)) + + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum { + step_A, step_B, step_C +} base64_encodestep; + +typedef struct { + base64_encodestep step; + char result; + int stepcount; + int stepsnewline; +} base64_encodestate; + +void base64_init_encodestate(base64_encodestate* state_in); +void base64_init_encodestate_nonewlines(base64_encodestate* state_in); + +char base64_encode_value(char value_in); + +int base64_encode_block(const char* plaintext_in, int length_in, char* code_out, base64_encodestate* state_in); + +int base64_encode_blockend(char* code_out, base64_encodestate* state_in); + +int base64_encode_chars(const char* plaintext_in, int length_in, char* code_out); + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/cores/rp2040/lock.cpp b/cores/rp2040/lock.cpp index b06e7744c..4784fdb47 100644 --- a/cores/rp2040/lock.cpp +++ b/cores/rp2040/lock.cpp @@ -25,6 +25,8 @@ #include #include +#include "_freertos.h" + // HACK ALERT // Pico-SDK defines mutex which can be at global scope, but when the auto_init_ // macros are used they are defined as static. Newlib needs global access to @@ -42,12 +44,87 @@ auto_init_mutex(__lock___dd_hash_mutex); auto_init_mutex(__lock___arc4random_mutex); #undef static +// FreeRTOS hack - Allow Newlib to use FreeRTOS mutexes which preserve TASKID which +// is needed to support multithread + +SemaphoreHandle_t __lock___sinit_recursive_mutex_freertos; +SemaphoreHandle_t __lock___sfp_recursive_mutex_freertos; +SemaphoreHandle_t __lock___atexit_recursive_mutex_freertos; +SemaphoreHandle_t __lock___at_quick_exit_mutex_freertos; +SemaphoreHandle_t __lock___malloc_recursive_mutex_freertos; +SemaphoreHandle_t __lock___env_recursive_mutex_freertos; +SemaphoreHandle_t __lock___tz_mutex_freertos; +SemaphoreHandle_t __lock___dd_hash_mutex_freertos; +SemaphoreHandle_t __lock___arc4random_mutex_freertos; + +void __initFreeRTOSMutexes() { + __lock___sinit_recursive_mutex_freertos = _freertos_recursive_mutex_create(); + __lock___sfp_recursive_mutex_freertos = _freertos_recursive_mutex_create(); + __lock___atexit_recursive_mutex_freertos = _freertos_recursive_mutex_create(); + __lock___at_quick_exit_mutex_freertos = __freertos_mutex_create(); + __lock___malloc_recursive_mutex_freertos = _freertos_recursive_mutex_create(); + __lock___env_recursive_mutex_freertos = _freertos_recursive_mutex_create(); + __lock___tz_mutex_freertos = __freertos_mutex_create(); + __lock___dd_hash_mutex_freertos = __freertos_mutex_create(); + __lock___arc4random_mutex_freertos = __freertos_mutex_create(); +} + +static SemaphoreHandle_t __getFreeRTOSMutex(_LOCK_T lock) { + mutex_t *l = (mutex_t *)lock; + if (l == &__lock___at_quick_exit_mutex) { + return __lock___at_quick_exit_mutex_freertos; + } else if (l == &__lock___tz_mutex) { + return __lock___tz_mutex_freertos; + } else if (l == &__lock___dd_hash_mutex) { + return __lock___dd_hash_mutex_freertos; + } else if (l == &__lock___arc4random_mutex) { + return __lock___arc4random_mutex_freertos; + } + return __get_freertos_mutex_for_ptr(l, false); +} + +static SemaphoreHandle_t __getFreeRTOSRecursiveMutex(_LOCK_T lock) { + recursive_mutex_t *l = (recursive_mutex_t *)lock; + if (l == &__lock___sinit_recursive_mutex) { + return __lock___sinit_recursive_mutex_freertos; + } else if (l == &__lock___sfp_recursive_mutex) { + return __lock___sfp_recursive_mutex_freertos; + } else if (l == &__lock___atexit_recursive_mutex) { + return __lock___atexit_recursive_mutex_freertos; + } else if (l == &__lock___malloc_recursive_mutex) { + return __lock___malloc_recursive_mutex_freertos; + } else if (l == &__lock___env_recursive_mutex) { + return __lock___env_recursive_mutex_freertos; + } + return __get_freertos_mutex_for_ptr((mutex_t *)l, true); +} + void __retarget_lock_init(_LOCK_T *lock) { - mutex_init((mutex_t*) lock); + if (__freeRTOSinitted) { + mutex_t *l = (mutex_t *)lock; + if ((l == &__lock___at_quick_exit_mutex) || (l == &__lock___tz_mutex) || (l == &__lock___dd_hash_mutex) || (l == &__lock___arc4random_mutex)) { + /* Already done in initFreeRTOSMutexes() */ + } else { + // Will init the mutex as well + __get_freertos_mutex_for_ptr(l, false); + } + } else { + mutex_init((mutex_t*) lock); + } } void __retarget_lock_init_recursive(_LOCK_T *lock) { - recursive_mutex_init((recursive_mutex_t*) lock); + if (__freeRTOSinitted) { + recursive_mutex_t *l = (recursive_mutex_t *)lock; + if ((l == &__lock___sinit_recursive_mutex) || (l == &__lock___sfp_recursive_mutex) || (l == &__lock___atexit_recursive_mutex) || (l == &__lock___malloc_recursive_mutex) || (l == &__lock___env_recursive_mutex)) { + /* Already done in initFreeRTOSMutexes() */ + } else { + // Will init the mutex as well + __get_freertos_mutex_for_ptr((mutex_t *)l, true); + } + } else { + recursive_mutex_init((recursive_mutex_t*) lock); + } } void __retarget_lock_close(_LOCK_T lock) { @@ -59,25 +136,59 @@ void __retarget_lock_close_recursive(_LOCK_T lock) { } void __retarget_lock_acquire(_LOCK_T lock) { - mutex_enter_blocking((mutex_t*)lock); + if (__freeRTOSinitted) { + auto mtx = __getFreeRTOSMutex(lock); + __freertos_mutex_take(mtx); + } else { + mutex_enter_blocking((mutex_t*)lock); + } } void __retarget_lock_acquire_recursive(_LOCK_T lock) { - recursive_mutex_enter_blocking((recursive_mutex_t*)lock); + if (__freeRTOSinitted) { + auto mtx = __getFreeRTOSRecursiveMutex(lock); + __freertos_recursive_mutex_take(mtx); + } else { + recursive_mutex_enter_blocking((recursive_mutex_t*)lock); + } } int __retarget_lock_try_acquire(_LOCK_T lock) { - return mutex_try_enter((mutex_t *)lock, NULL); + int ret; + if (__freeRTOSinitted) { + auto mtx = __getFreeRTOSMutex(lock); + ret = __freertos_mutex_try_take(mtx); + } else { + ret = mutex_try_enter((mutex_t *)lock, nullptr); + } + return ret; } int __retarget_lock_try_acquire_recursive(_LOCK_T lock) { - return recursive_mutex_try_enter((recursive_mutex_t*)lock, NULL); + int ret; + if (__freeRTOSinitted) { + auto mtx = __getFreeRTOSRecursiveMutex(lock); + ret = __freertos_recursive_mutex_try_take(mtx); + } else { + ret = recursive_mutex_try_enter((recursive_mutex_t*)lock, nullptr); + } + return ret; } void __retarget_lock_release(_LOCK_T lock) { - mutex_exit((mutex_t*)lock); + if (__freeRTOSinitted) { + auto mtx = __getFreeRTOSMutex(lock); + __freertos_mutex_give(mtx); + } else { + mutex_exit((mutex_t*)lock); + } } void __retarget_lock_release_recursive(_LOCK_T lock) { - recursive_mutex_exit((recursive_mutex_t*)lock); + if (__freeRTOSinitted) { + auto mtx = __getFreeRTOSRecursiveMutex(lock); + __freertos_recursive_mutex_give(mtx); + } else { + recursive_mutex_exit((recursive_mutex_t*)lock); + } } diff --git a/cores/rp2040/lwip_wrap.cpp b/cores/rp2040/lwip_wrap.cpp new file mode 100644 index 000000000..8130e864b --- /dev/null +++ b/cores/rp2040/lwip_wrap.cpp @@ -0,0 +1,307 @@ +/* + LWIP wrappers to protect against timer-based re-entrancy + + Copyright (c) 2023 Earle F. Philhower, III + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include +#include +#include +#include +#include +#include +#include +#include + +class LWIPMutex { +public: + LWIPMutex() { + cyw43_arch_lwip_begin(); + } + + ~LWIPMutex() { + cyw43_arch_lwip_end(); + } +}; + +extern "C" { + + extern u8_t __real_pbuf_header(struct pbuf *p, s16_t header_size); + u8_t __wrap_pbuf_header(struct pbuf *p, s16_t header_size) { + LWIPMutex m; + return __real_pbuf_header(p, header_size); + } + + extern u8_t __real_pbuf_free(struct pbuf *p); + u8_t __wrap_pbuf_free(struct pbuf *p) { + LWIPMutex m; + return __real_pbuf_free(p); + } + + extern struct pbuf *__real_pbuf_alloc(pbuf_layer l, u16_t length, pbuf_type type); + struct pbuf *__wrap_pbuf_alloc(pbuf_layer l, u16_t length, pbuf_type type) { + LWIPMutex m; + return __real_pbuf_alloc(l, length, type); + } + + extern err_t __real_pbuf_take(struct pbuf *buf, const void *dataptr, u16_t len); + err_t __wrap_pbuf_take(struct pbuf *buf, const void *dataptr, u16_t len) { + LWIPMutex m; + return __real_pbuf_take(buf, dataptr, len); + } + + extern u16_t __real_pbuf_copy_partial(const struct pbuf *p, void *dataptr, u16_t len, u16_t offset); + u16_t __wrap_pbuf_copy_partial(const struct pbuf *p, void *dataptr, u16_t len, u16_t offset) { + LWIPMutex m; + return __real_pbuf_copy_partial(p, dataptr, len, offset); + } + + extern void __real_pbuf_ref(struct pbuf *p); + void __wrap_pbuf_ref(struct pbuf *p) { + LWIPMutex m; + __real_pbuf_ref(p); + } + + extern u8_t __real_pbuf_get_at(const struct pbuf* p, u16_t offset); + u8_t __wrap_pbuf_get_at(const struct pbuf* p, u16_t offset) { + LWIPMutex m; + return __real_pbuf_get_at(p, offset); + } + + extern void *__real_pbuf_get_contiguous(const struct pbuf *p, void *buffer, size_t bufsize, u16_t len, u16_t offset); + void *__wrap_pbuf_get_contiguous(const struct pbuf *p, void *buffer, size_t bufsize, u16_t len, u16_t offset) { + LWIPMutex m; + return __real_pbuf_get_contiguous(p, buffer, bufsize, len, offset); + } + + extern void __real_pbuf_cat(struct pbuf *head, struct pbuf *tail); + void __wrap_pbuf_cat(struct pbuf *head, struct pbuf *tail) { + LWIPMutex m; + __real_pbuf_cat(head, tail); + } + + extern void __real_tcp_arg(struct tcp_pcb *pcb, void *arg); + void __wrap_tcp_arg(struct tcp_pcb *pcb, void *arg) { + LWIPMutex m; + __real_tcp_arg(pcb, arg); + } + + extern struct tcp_pcb *__real_tcp_new(void); + struct tcp_pcb *__wrap_tcp_new(void) { + LWIPMutex m; + return __real_tcp_new(); + } + + extern err_t __real_tcp_bind(struct tcp_pcb *pcb, ip_addr_t *ipaddr, u16_t port); + err_t __wrap_tcp_bind(struct tcp_pcb *pcb, ip_addr_t *ipaddr, u16_t port) { + LWIPMutex m; + return __real_tcp_bind(pcb, ipaddr, port); + } + + extern struct tcp_pcb *__real_tcp_listen(struct tcp_pcb *pcb); + struct tcp_pcb *__wrap_tcp_listen(struct tcp_pcb *pcb) { + LWIPMutex m; + return __real_tcp_listen(pcb); + } + + extern struct tcp_pcb *__real_tcp_listen_with_backlog(struct tcp_pcb *pcb, u8_t backlog); + struct tcp_pcb *__wrap_tcp_listen_with_backlog(struct tcp_pcb *pcb, u8_t backlog) { + LWIPMutex m; + return __real_tcp_listen_with_backlog(pcb, backlog); + } + + extern void __real_tcp_accept(struct tcp_pcb *pcb, err_t (* accept)(void *arg, struct tcp_pcb *newpcb, err_t err)); + void __wrap_tcp_accept(struct tcp_pcb *pcb, err_t (* accept)(void *arg, struct tcp_pcb *newpcb, err_t err)) { + LWIPMutex m; + __real_tcp_accept(pcb, accept); + } + + extern err_t __real_tcp_connect(struct tcp_pcb *pcb, ip_addr_t *ipaddr, u16_t port, err_t (* connected)(void *arg, struct tcp_pcb *tpcb, err_t err)); + err_t __wrap_tcp_connect(struct tcp_pcb *pcb, ip_addr_t *ipaddr, u16_t port, err_t (* connected)(void *arg, struct tcp_pcb *tpcb, err_t err)) { + LWIPMutex m; + return __real_tcp_connect(pcb, ipaddr, port, connected); + } + + extern err_t __real_tcp_write(struct tcp_pcb *pcb, const void *dataptr, u16_t len, u8_t apiflags); + err_t __wrap_tcp_write(struct tcp_pcb *pcb, const void *dataptr, u16_t len, u8_t apiflags) { + LWIPMutex m; + return __real_tcp_write(pcb, dataptr, len, apiflags); + } + + extern void __real_tcp_sent(struct tcp_pcb *pcb, err_t (* sent)(void *arg, struct tcp_pcb *tpcb, u16_t len)); + void __wrap_tcp_sent(struct tcp_pcb *pcb, err_t (* sent)(void *arg, struct tcp_pcb *tpcb, u16_t len)) { + LWIPMutex m; + __real_tcp_sent(pcb, sent); + } + + extern void __real_tcp_recv(struct tcp_pcb *pcb, err_t (* recv)(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err)); + void __wrap_tcp_recv(struct tcp_pcb *pcb, err_t (* recv)(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err)) { + LWIPMutex m; + __real_tcp_recv(pcb, recv); + } + + extern void __real_tcp_recved(struct tcp_pcb *pcb, u16_t len); + void __wrap_tcp_recved(struct tcp_pcb *pcb, u16_t len) { + LWIPMutex m; + __real_tcp_recved(pcb, len); + } + + extern void __real_tcp_poll(struct tcp_pcb *pcb, err_t (* poll)(void *arg, struct tcp_pcb *tpcb), u8_t interval); + void __wrap_tcp_poll(struct tcp_pcb *pcb, err_t (* poll)(void *arg, struct tcp_pcb *tpcb), u8_t interval) { + LWIPMutex m; + __real_tcp_poll(pcb, poll, interval); + } + + extern err_t __real_tcp_close(struct tcp_pcb *pcb); + err_t __wrap_tcp_close(struct tcp_pcb *pcb) { + LWIPMutex m; + return __real_tcp_close(pcb); + } + + extern void __real_tcp_abort(struct tcp_pcb *pcb); + void __wrap_tcp_abort(struct tcp_pcb *pcb) { + LWIPMutex m; + __real_tcp_abort(pcb); + } + + extern void __real_tcp_err(struct tcp_pcb *pcb, void (* err)(void *arg, err_t err)); + void __wrap_tcp_err(struct tcp_pcb *pcb, void (* err)(void *arg, err_t err)) { + LWIPMutex m; + __real_tcp_err(pcb, err); + } + + extern err_t __real_tcp_output(struct tcp_pcb *pcb); + err_t __wrap_tcp_output(struct tcp_pcb *pcb) { + LWIPMutex m; + return __real_tcp_output(pcb); + } + + extern void __real_tcp_setprio(struct tcp_pcb *pcb, u8_t prio); + void __wrap_tcp_setprio(struct tcp_pcb *pcb, u8_t prio) { + LWIPMutex m; + return __real_tcp_setprio(pcb, prio); + } + + extern void __real_tcp_backlog_delayed(struct tcp_pcb* pcb); + void __wrap_tcp_backlog_delayed(struct tcp_pcb* pcb) { + LWIPMutex m; + return __real_tcp_backlog_delayed(pcb); + } + + extern void __real_tcp_backlog_accepted(struct tcp_pcb* pcb); + void __wrap_tcp_backlog_accepted(struct tcp_pcb* pcb) { + LWIPMutex m; + return __real_tcp_backlog_accepted(pcb); + } + extern struct udp_pcb *__real_udp_new(void); + struct udp_pcb *__wrap_udp_new(void) { + LWIPMutex m; + return __real_udp_new(); + } + + extern void __real_udp_remove(struct udp_pcb *pcb); + void __wrap_udp_remove(struct udp_pcb *pcb) { + LWIPMutex m; + __real_udp_remove(pcb); + } + + extern err_t __real_udp_bind(struct udp_pcb *pcb, ip_addr_t *ipaddr, u16_t port); + err_t __wrap_udp_bind(struct udp_pcb *pcb, ip_addr_t *ipaddr, u16_t port) { + LWIPMutex m; + return __real_udp_bind(pcb, ipaddr, port); + } + + extern err_t __real_udp_connect(struct udp_pcb *pcb, ip_addr_t *ipaddr, u16_t port); + err_t __wrap_udp_connect(struct udp_pcb *pcb, ip_addr_t *ipaddr, u16_t port) { + LWIPMutex m; + return __real_udp_connect(pcb, ipaddr, port); + } + + extern err_t __real_udp_disconnect(struct udp_pcb *pcb); + err_t __wrap_udp_disconnect(struct udp_pcb *pcb) { + LWIPMutex m; + return __real_udp_disconnect(pcb); + } + + extern err_t __real_udp_send(struct udp_pcb *pcb, struct pbuf *p); + err_t __wrap_udp_send(struct udp_pcb *pcb, struct pbuf *p) { + LWIPMutex m; + return __real_udp_send(pcb, p); + } + + extern void __real_udp_recv(struct udp_pcb *pcb, void (* recv)(void *arg, struct udp_pcb *upcb, struct pbuf *p, ip_addr_t *addr, u16_t port), void *recv_arg); + void __wrap_udp_recv(struct udp_pcb *pcb, void (* recv)(void *arg, struct udp_pcb *upcb, struct pbuf *p, ip_addr_t *addr, u16_t port), void *recv_arg) { + LWIPMutex m; + __real_udp_recv(pcb, recv, recv_arg); + } + + extern err_t __real_udp_sendto_if(struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *dst_ip, u16_t dst_port, struct netif *netif); + err_t __wrap_udp_sendto_if(struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *dst_ip, u16_t dst_port, struct netif *netif) { + LWIPMutex m; + return __real_udp_sendto_if(pcb, p, dst_ip, dst_port, netif); + } + + // sys_check_timeouts is special case because the async process will call it. If we're already in a timeout check, just do a noop + extern void __real_sys_check_timeouts(); + void __wrap_sys_check_timeouts(void) { + LWIPMutex m; + __real_sys_check_timeouts(); + } + + extern err_t __real_dns_gethostbyname(const char *hostname, ip_addr_t *addr, dns_found_callback found, void *callback_arg); + err_t __wrap_dns_gethostbyname(const char *hostname, ip_addr_t *addr, dns_found_callback found, void *callback_arg) { + LWIPMutex m; + return __real_dns_gethostbyname(hostname, addr, found, callback_arg); + } + + extern err_t __real_dns_gethostbyname_addrtype(const char *hostname, ip_addr_t *addr, dns_found_callback found, void *callback_arg, u8_t dns_addrtype); + err_t __wrap_dns_gethostbyname_addrtype(const char *hostname, ip_addr_t *addr, dns_found_callback found, void *callback_arg, u8_t dns_addrtype) { + LWIPMutex m; + return __real_dns_gethostbyname_addrtype(hostname, addr, found, callback_arg, dns_addrtype); + } + + extern struct raw_pcb *__real_raw_new(u8_t proto); + struct raw_pcb *__wrap_raw_new(u8_t proto) { + LWIPMutex m; + return __real_raw_new(proto); + } + + extern void __real_raw_recv(struct raw_pcb *pcb, raw_recv_fn recv, void *recv_arg); + void __wrap_raw_recv(struct raw_pcb *pcb, raw_recv_fn recv, void *recv_arg) { + LWIPMutex m; + __real_raw_recv(pcb, recv, recv_arg); + } + + extern err_t __real_raw_bind(struct raw_pcb *pcb, const ip_addr_t *ipaddr); + err_t __wrap_raw_bind(struct raw_pcb *pcb, const ip_addr_t *ipaddr) { + LWIPMutex m; + return __real_raw_bind(pcb, ipaddr); + } + + extern err_t __real_raw_sendto(struct raw_pcb *pcb, struct pbuf *p, const ip_addr_t *ipaddr); + err_t __wrap_raw_sendto(struct raw_pcb *pcb, struct pbuf *p, const ip_addr_t *ipaddr) { + LWIPMutex m; + return __real_raw_sendto(pcb, p, ipaddr); + } + + extern void __real_raw_remove(struct raw_pcb *pcb); + void __wrap_raw_remove(struct raw_pcb *pcb) { + LWIPMutex m; + __real_raw_remove(pcb); + } + +}; // extern "C" diff --git a/cores/rp2040/main.cpp b/cores/rp2040/main.cpp index 0896f3ff9..74ed01226 100644 --- a/cores/rp2040/main.cpp +++ b/cores/rp2040/main.cpp @@ -22,19 +22,15 @@ #include "RP2040USB.h" #include #include -#include "LWIPMutex.h" #include RP2040 rp2040; extern "C" { volatile bool __otherCoreIdled = false; - int __holdUpPendSV = 0; }; mutex_t _pioMutex; -int LWIPMutex::_ref = 0; - extern void setup(); extern void loop(); @@ -42,6 +38,8 @@ extern void loop(); extern void initFreeRTOS() __attribute__((weak)); extern void startFreeRTOS() __attribute__((weak)); bool __isFreeRTOS; +volatile bool __freeRTOSinitted; + // Weak empty variant initialization. May be redefined by variant files. void initVariant() __attribute__((weak)); @@ -126,7 +124,6 @@ extern "C" int main() { } #endif -#ifndef NO_USB if (!__isFreeRTOS) { if (setup1 || loop1) { rp2040.fifo.begin(2); @@ -135,7 +132,6 @@ extern "C" int main() { } rp2040.fifo.registerCore(); } -#endif if (!__isFreeRTOS) { if (setup1 || loop1) { @@ -166,8 +162,7 @@ extern "C" void __register_impure_ptr(struct _reent *p) { } } - -// TODO: FreeRTOS should implement this based on thread ID (and each thread should have its own struct _reent +extern "C" struct _reent *__wrap___getreent() __attribute__((weak)); extern "C" struct _reent *__wrap___getreent() { if (get_core_num() == 0) { return _impure_ptr; @@ -175,3 +170,30 @@ extern "C" struct _reent *__wrap___getreent() { return _impure_ptr1; } } + +// ESP8266 internal debug routine +extern void hexdump(const void* mem, uint32_t len, uint8_t cols) __attribute__((weak)); +void hexdump(const void* mem, uint32_t len, uint8_t cols) { + const char* src = (const char*)mem; + printf("\n[HEXDUMP] Address: %p len: 0x%lX (%ld)", src, len, len); + while (len > 0) { + uint32_t linesize = cols > len ? len : cols; + printf("\n[%p] 0x%04x: ", src, (int)(src - (const char*)mem)); + for (uint32_t i = 0; i < linesize; i++) { + printf("%02x ", *(src + i)); + } + printf(" "); + for (uint32_t i = linesize; i < cols; i++) { + printf(" "); + } + for (uint32_t i = 0; i < linesize; i++) { + unsigned char c = *(src + i); + putc(isprint(c) ? c : '.', stdout); + } + src += linesize; + len -= linesize; + } + printf("\n"); +} + +const String emptyString = ""; diff --git a/cores/rp2040/malloc-lock.cpp b/cores/rp2040/malloc-lock.cpp new file mode 100644 index 000000000..ec8a55f79 --- /dev/null +++ b/cores/rp2040/malloc-lock.cpp @@ -0,0 +1,53 @@ +/* + Malloc/etc. interrupt locking wrappers + + Copyright (c) 2022 Earle F. Philhower, III + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include + +extern "C" void *__real_malloc(size_t size); +extern "C" void *__real_calloc(size_t count, size_t size); +extern "C" void *__real_realloc(void *mem, size_t size); +extern "C" void __real_free(void *mem); + +extern "C" void *__wrap_malloc(size_t size) { + noInterrupts(); + void *rc = __real_malloc(size); + interrupts(); + return rc; +} + +extern "C" void *__wrap_calloc(size_t count, size_t size) { + noInterrupts(); + void *rc = __real_calloc(count, size); + interrupts(); + return rc; +} + +extern "C" void *__wrap_realloc(void *mem, size_t size) { + noInterrupts(); + void *rc = __real_realloc(mem, size); + interrupts(); + return rc; +} + +extern "C" void __wrap_free(void *mem) { + noInterrupts(); + __real_free(mem); + interrupts(); +} diff --git a/cores/rp2040/posix.cpp b/cores/rp2040/posix.cpp index 19564b7de..1ee1cc6f5 100644 --- a/cores/rp2040/posix.cpp +++ b/cores/rp2040/posix.cpp @@ -90,8 +90,8 @@ extern "C" int _gettimeofday(struct timeval *tv, void *tz) { (void) tz; uint64_t now_us = to_us_since_boot(get_absolute_time()) + __timedelta_us; if (tv) { - tv->tv_sec = now_us / 1000000L; - tv->tv_usec = now_us % 1000000L; + tv->tv_sec = now_us / 1'000'000L; + tv->tv_usec = now_us % 1'000'000L; } return 0; } @@ -101,7 +101,7 @@ extern "C" int settimeofday(const struct timeval *tv, const struct timezone *tz) uint64_t now_us = to_us_since_boot(get_absolute_time()); if (tv) { uint64_t newnow_us; - newnow_us = tv->tv_sec * 1000000L; + newnow_us = tv->tv_sec * 1'000'000L; newnow_us += tv->tv_usec; __timedelta_us = newnow_us - now_us; } @@ -111,7 +111,7 @@ extern "C" int settimeofday(const struct timeval *tv, const struct timezone *tz) // For NTP extern "C" void __setSystemTime(unsigned long long sec, unsigned long usec) { uint64_t now_us = to_us_since_boot(get_absolute_time()); - uint64_t newnow_us = sec * 1000000LL + usec; + uint64_t newnow_us = sec * 1'000'000LL + usec; __timedelta_us = newnow_us - now_us; } diff --git a/cores/rp2040/sdkoverride/btstack_flash_bank.cpp b/cores/rp2040/sdkoverride/btstack_flash_bank.cpp new file mode 100644 index 000000000..08d616691 --- /dev/null +++ b/cores/rp2040/sdkoverride/btstack_flash_bank.cpp @@ -0,0 +1,178 @@ +/* + Copyright (c) 2023 Raspberry Pi (Trading) Ltd. + + SPDX-License-Identifier: BSD-3-Clause +*/ + +#if defined(ARDUINO_RASPBERRY_PI_PICO_W) +#include +#include +#include +#include +#include +#include + +const uint8_t __bluetooth_tlv[8192] __attribute__((aligned(4096))) = { 0 }; +extern const uint8_t __flash_binary_start; + +#undef PICO_FLASH_BANK_TOTAL_SIZE +#undef PICO_FLASH_BANK_STORAGE_OFFSET +#define PICO_FLASH_BANK_TOTAL_SIZE sizeof(__bluetooth_tlv) +#define PICO_FLASH_BANK_STORAGE_OFFSET ((unsigned int)(__bluetooth_tlv - &__flash_binary_start)) + +#if 0 +// Check sizes +static_assert(PICO_FLASH_BANK_TOTAL_SIZE % (FLASH_SECTOR_SIZE * 2) == 0, "PICO_FLASH_BANK_TOTAL_SIZE invalid"); +static_assert(PICO_FLASH_BANK_TOTAL_SIZE <= PICO_FLASH_SIZE_BYTES, "PICO_FLASH_BANK_TOTAL_SIZE too big"); +static_assert(PICO_FLASH_BANK_STORAGE_OFFSET + PICO_FLASH_BANK_TOTAL_SIZE <= PICO_FLASH_SIZE_BYTES, "PICO_FLASH_BANK_TOTAL_SIZE too big"); +#endif + +// Size of one bank +#define PICO_FLASH_BANK_SIZE (PICO_FLASH_BANK_TOTAL_SIZE / 2) + +#if 0 +#define DEBUG_PRINT(format,args...) printf(format, ## args) +#else +#define DEBUG_PRINT(...) +#endif + +static uint32_t pico_flash_bank_get_size(void * context) { + (void)(context); + return PICO_FLASH_BANK_SIZE; +} + +static uint32_t pico_flash_bank_get_alignment(void * context) { + (void)(context); + return 1; +} + +static void pico_flash_bank_erase(void * context, int bank) { + (void)(context); + DEBUG_PRINT("erase: bank %d\n", bank); + noInterrupts(); + rp2040.idleOtherCore(); + flash_range_erase(PICO_FLASH_BANK_STORAGE_OFFSET + (PICO_FLASH_BANK_SIZE * bank), PICO_FLASH_BANK_SIZE); + rp2040.resumeOtherCore(); + interrupts(); +} + +static void pico_flash_bank_read(void *context, int bank, uint32_t offset, uint8_t *buffer, uint32_t size) { + (void)(context); + DEBUG_PRINT("read: bank %d offset %u size %u\n", bank, offset, size); + + assert(bank <= 1); + if (bank > 1) { + return; + } + + assert(offset < PICO_FLASH_BANK_SIZE); + if (offset >= PICO_FLASH_BANK_SIZE) { + return; + } + + assert((offset + size) <= PICO_FLASH_BANK_SIZE); + if ((offset + size) > PICO_FLASH_BANK_SIZE) { + return; + } + + // Flash is xip + memcpy(buffer, (void *)(XIP_BASE + PICO_FLASH_BANK_STORAGE_OFFSET + (PICO_FLASH_BANK_SIZE * bank) + offset), size); +} + +static void pico_flash_bank_write(void * context, int bank, uint32_t offset, const uint8_t *data, uint32_t size) { + (void)(context); + DEBUG_PRINT("write: bank %d offset %u size %u\n", bank, offset, size); + + assert(bank <= 1); + if (bank > 1) { + return; + } + + assert(offset < PICO_FLASH_BANK_SIZE); + if (offset >= PICO_FLASH_BANK_SIZE) { + return; + } + + assert((offset + size) <= PICO_FLASH_BANK_SIZE); + if ((offset + size) > PICO_FLASH_BANK_SIZE) { + return; + } + + if (size == 0) { + return; + } + + // calc bank start position + const uint32_t bank_start_pos = PICO_FLASH_BANK_STORAGE_OFFSET + (PICO_FLASH_BANK_SIZE * bank); + + // Calculate first and last page in the bank + const uint32_t first_page = offset / FLASH_PAGE_SIZE; + const uint32_t last_page = (offset + size + FLASH_PAGE_SIZE - 1) / FLASH_PAGE_SIZE; + + // Now we only care about the offset in the first page + offset %= FLASH_PAGE_SIZE; + + // Amount of data we've copied + uint32_t data_pos = 0; + uint32_t size_left = size; + + // Write all the pages required + for (uint32_t page = first_page; page < last_page; page++) { + uint8_t page_data[FLASH_PAGE_SIZE]; + + assert(data_pos < size && size_left <= size); + + // Copy data we're not going to overwrite in the first page + if (page == first_page && offset > 0) { + memcpy(page_data, + (void *)(XIP_BASE + bank_start_pos + (page * FLASH_PAGE_SIZE)), + offset); + } + + // Copy the data we're not going to overwrite in the last page + if (page == last_page - 1 && (offset + size_left) < FLASH_PAGE_SIZE) { + memcpy(page_data + offset + size_left, + (void *)(XIP_BASE + bank_start_pos + (page * FLASH_PAGE_SIZE) + offset + size_left), + FLASH_PAGE_SIZE - offset - size_left); + } + + // Now copy the new data into the page + const uint32_t size_to_copy = MIN(size_left, FLASH_PAGE_SIZE - offset); + memcpy(page_data + offset, data + data_pos, size_to_copy); + + data_pos += size_to_copy; + size_left -= size_to_copy; + + // zero offset for the following pages + offset = 0; + + // Now program the entire page + noInterrupts(); + rp2040.idleOtherCore(); + flash_range_program(bank_start_pos + (page * FLASH_PAGE_SIZE), page_data, FLASH_PAGE_SIZE); + rp2040.resumeOtherCore(); + interrupts(); + } +} + +static const hal_flash_bank_t pico_flash_bank_instance_obj = { + /* uint32_t (*get_size)(..) */ &pico_flash_bank_get_size, + /* uint32_t (*get_alignment)(..); */ &pico_flash_bank_get_alignment, + /* void (*erase)(..); */ &pico_flash_bank_erase, + /* void (*read)(..); */ &pico_flash_bank_read, + /* void (*write)(..); */ &pico_flash_bank_write, +}; + +extern "C" { + const hal_flash_bank_t *pico_flash_bank_instance(void) { + +#ifndef NDEBUG + // Check we're not overlapping the binary in flash + //extern char __flash_binary_end; + // assert((uintptr_t)&__flash_binary_end - XIP_BASE <= PICO_FLASH_BANK_STORAGE_OFFSET); +#endif + + return &pico_flash_bank_instance_obj; + } +} +#endif diff --git a/cores/rp2040/sdkoverride/cyw43_arch_threadsafe_background.c b/cores/rp2040/sdkoverride/cyw43_arch_threadsafe_background.c deleted file mode 100644 index 07ef28a9f..000000000 --- a/cores/rp2040/sdkoverride/cyw43_arch_threadsafe_background.c +++ /dev/null @@ -1,349 +0,0 @@ -/* - Copyright (c) 2022 Raspberry Pi (Trading) Ltd. - - SPDX-License-Identifier: BSD-3-Clause -*/ - -// Taken from the Pico-SDK v1.4.0 and hacked by EFP3 to allow overriding the LWIP setup - -#include - -#include "pico/cyw43_arch.h" -#include "pico/mutex.h" -#include "pico/sem.h" - -#include "hardware/gpio.h" -#include "hardware/irq.h" - -#include "cyw43_stats.h" - -#include -#include "lwip/timeouts.h" - -#ifndef CYW43_PIN_WL_HOST_WAKE -#define CYW43_PIN_WL_HOST_WAKE 24 -#endif - -#ifndef CYW43_PIN_WL_REG_ON -#define CYW43_PIN_WL_REG_ON 23 -#endif - -#ifndef CYW43_WL_GPIO_COUNT -#define CYW43_WL_GPIO_COUNT 3 -#endif - -#ifndef CYW43_WL_GPIO_LED_PIN -#define CYW43_WL_GPIO_LED_PIN 0 -#endif - - -volatile bool __inLWIP = false; - -// note same code -#if PICO_CYW43_ARCH_THREADSAFE_BACKGROUND - -#if PICO_CYW43_ARCH_THREADSAFE_BACKGROUND && CYW43_LWIP && !NO_SYS -#error PICO_CYW43_ARCH_THREADSAFE_BACKGROUND requires lwIP NO_SYS=1 -#endif -#if PICO_CYW43_ARCH_THREADSAFE_BACKGROUND && CYW43_LWIP && MEM_LIBC_MALLOC -#error MEM_LIBC_MALLOC is incompatible with PICO_CYW43_ARCH_THREADSAFE_BACKGROUND -#endif -// todo right now we are now always doing a cyw43_dispatch along with a lwip one when hopping cores in low_prio_irq_schedule_dispatch - -#ifndef CYW43_SLEEP_CHECK_MS -#define CYW43_SLEEP_CHECK_MS 50 // How often to run lwip callback -#endif -static alarm_id_t periodic_alarm = -1; - -static inline uint recursive_mutex_enter_count(recursive_mutex_t *mutex) { - return mutex->enter_count; -} - -static inline lock_owner_id_t recursive_mutex_owner(recursive_mutex_t *mutex) { - return mutex->owner; -} - -#define CYW43_GPIO_IRQ_HANDLER_PRIORITY 0x40 - -enum { - CYW43_DISPATCH_SLOT_CYW43 = 0, - CYW43_DISPATCH_SLOT_ADAPTER, - CYW43_DISPATCH_SLOT_ENUM_COUNT -}; -#ifndef CYW43_DISPATCH_SLOT_COUNT -#define CYW43_DISPATCH_SLOT_COUNT CYW43_DISPATCH_SLOT_ENUM_COUNT -#endif - -typedef void (*low_prio_irq_dispatch_t)(void); -static void low_prio_irq_schedule_dispatch(size_t slot, low_prio_irq_dispatch_t f); - -static uint8_t cyw43_core_num; -#ifndef NDEBUG -static bool in_low_priority_irq; -#endif -static uint8_t low_priority_irq_num; -static bool low_priority_irq_missed; -static low_prio_irq_dispatch_t low_priority_irq_dispatch_slots[CYW43_DISPATCH_SLOT_COUNT]; -static recursive_mutex_t cyw43_mutex; -semaphore_t cyw43_irq_sem; - -// Called in low priority pendsv interrupt only to do lwip processing and check cyw43 sleep -static void periodic_worker(void) { -#if CYW43_USE_STATS && LWIP_SYS_CHECK_MS - static uint32_t counter; - if (counter++ % (30000 / LWIP_SYS_CHECK_MS) == 0) { - cyw43_dump_stats(); - } -#endif - - CYW43_STAT_INC(LWIP_RUN_COUNT); - //#if CYW43_LWIP - if (!__inLWIP) { - sys_check_timeouts(); - } - //#endif - if (cyw43_poll) { - if (cyw43_sleep > 0) { - if (--cyw43_sleep == 0) { - low_prio_irq_schedule_dispatch(CYW43_DISPATCH_SLOT_CYW43, cyw43_poll); - } - } - } -} - -// Regular callback to get lwip to check for timeouts -static int64_t periodic_alarm_handler(__unused alarm_id_t id, __unused void *user_data) { - // Do lwip processing in low priority pendsv interrupt - low_prio_irq_schedule_dispatch(CYW43_DISPATCH_SLOT_ADAPTER, periodic_worker); - return CYW43_SLEEP_CHECK_MS * 1000; -} - -void cyw43_await_background_or_timeout_us(uint32_t timeout_us) { - // if we are called from within an IRQ, then don't wait (we are only ever called in a polling loop) - if (!__get_current_exception()) { - sem_acquire_timeout_us(&cyw43_irq_sem, timeout_us); - } -} - -// GPIO interrupt handler to tell us there's cyw43 has work to do -static void gpio_irq_handler(void) { - uint32_t events = gpio_get_irq_event_mask(CYW43_PIN_WL_HOST_WAKE); - if (events & GPIO_IRQ_LEVEL_HIGH) { - // As we use a high level interrupt, it will go off forever until it's serviced - // So disable the interrupt until this is done. It's re-enabled again by CYW43_POST_POLL_HOOK - // which is called at the end of cyw43_poll_func - gpio_set_irq_enabled(CYW43_PIN_WL_HOST_WAKE, GPIO_IRQ_LEVEL_HIGH, false); - // also clear the force bit which we use to progratically cause this handler to fire (on the right core) - io_irq_ctrl_hw_t *irq_ctrl_base = get_core_num() ? - &iobank0_hw->proc1_irq_ctrl : &iobank0_hw->proc0_irq_ctrl; - hw_clear_bits(&irq_ctrl_base->intf[CYW43_PIN_WL_HOST_WAKE / 8], GPIO_IRQ_LEVEL_HIGH << (4 * (CYW43_PIN_WL_HOST_WAKE & 7))); - low_prio_irq_schedule_dispatch(CYW43_DISPATCH_SLOT_CYW43, cyw43_poll); - CYW43_STAT_INC(IRQ_COUNT); - } -} - -// Low priority interrupt handler to perform background processing -static void low_priority_irq_handler(void) { - assert(cyw43_core_num == get_core_num()); - if (recursive_mutex_try_enter(&cyw43_mutex, NULL)) { - if (recursive_mutex_enter_count(&cyw43_mutex) != 1) { - low_priority_irq_missed = true; - CYW43_STAT_INC(PENDSV_DISABLED_COUNT); - } else { - CYW43_STAT_INC(PENDSV_RUN_COUNT); -#ifndef NDEBUG - in_low_priority_irq = true; -#endif - for (size_t i = 0; i < count_of(low_priority_irq_dispatch_slots); i++) { - if (low_priority_irq_dispatch_slots[i] != NULL) { - low_prio_irq_dispatch_t f = low_priority_irq_dispatch_slots[i]; - low_priority_irq_dispatch_slots[i] = NULL; - f(); - } - } -#ifndef NDEBUG - in_low_priority_irq = false; -#endif - } - recursive_mutex_exit(&cyw43_mutex); - } else { - CYW43_STAT_INC(PENDSV_DISABLED_COUNT); - low_priority_irq_missed = true; - } - sem_release(&cyw43_irq_sem); -} - -static bool low_prio_irq_init(uint8_t priority) { - assert(get_core_num() == cyw43_core_num); - int irq = user_irq_claim_unused(false); - if (irq < 0) { - return false; - } - low_priority_irq_num = (uint8_t) irq; - irq_set_exclusive_handler(low_priority_irq_num, low_priority_irq_handler); - irq_set_enabled(low_priority_irq_num, true); - irq_set_priority(low_priority_irq_num, priority); - return true; -} - -static void low_prio_irq_deinit(void) { - if (low_priority_irq_num > 0) { - irq_set_enabled(low_priority_irq_num, false); - irq_remove_handler(low_priority_irq_num, low_priority_irq_handler); - user_irq_unclaim(low_priority_irq_num); - low_priority_irq_num = 0; - } -} - -int cyw43_arch_init(void) { - cyw43_core_num = get_core_num(); - recursive_mutex_init(&cyw43_mutex); - cyw43_init(&cyw43_state); - sem_init(&cyw43_irq_sem, 0, 1); - - // Start regular lwip callback to handle timeouts - periodic_alarm = add_alarm_in_us(CYW43_SLEEP_CHECK_MS * 1000, periodic_alarm_handler, NULL, true); - if (periodic_alarm < 0) { - return PICO_ERROR_GENERIC; - } - - gpio_add_raw_irq_handler_with_order_priority(IO_IRQ_BANK0, gpio_irq_handler, CYW43_GPIO_IRQ_HANDLER_PRIORITY); - gpio_set_irq_enabled(CYW43_PIN_WL_HOST_WAKE, GPIO_IRQ_LEVEL_HIGH, true); - irq_set_enabled(IO_IRQ_BANK0, true); - - lwip_init(); - - // start low priority handler (no background work is done before this) - bool ok = low_prio_irq_init(PICO_LOWEST_IRQ_PRIORITY); - if (!ok) { - cyw43_arch_deinit(); - return PICO_ERROR_GENERIC; - } - return PICO_OK; -} - -void cyw43_arch_deinit(void) { - if (periodic_alarm >= 0) { - cancel_alarm(periodic_alarm); - periodic_alarm = -1; - } - gpio_set_irq_enabled(CYW43_PIN_WL_HOST_WAKE, GPIO_IRQ_LEVEL_HIGH, false); - gpio_remove_raw_irq_handler(IO_IRQ_BANK0, gpio_irq_handler); - low_prio_irq_deinit(); -} - -void cyw43_post_poll_hook(void) { - gpio_set_irq_enabled(CYW43_PIN_WL_HOST_WAKE, GPIO_IRQ_LEVEL_HIGH, true); -} - -// This is called in the gpio and low_prio_irq interrupts and on either core -static void low_prio_irq_schedule_dispatch(size_t slot, low_prio_irq_dispatch_t f) { - assert(slot < count_of(low_priority_irq_dispatch_slots)); - low_priority_irq_dispatch_slots[slot] = f; - if (cyw43_core_num == get_core_num()) { - //on same core, can dispatch directly - irq_set_pending(low_priority_irq_num); - } else { - // on wrong core, so force via GPIO IRQ which itself calls this method for the CYW43 slot. - // since the CYW43 slot always uses the same function, this is fine with the addition of an - // extra (but harmless) CYW43 slot call when another SLOT is invoked. - // We could do better, but would have to track why the IRQ was called. - io_irq_ctrl_hw_t *irq_ctrl_base = cyw43_core_num ? - &iobank0_hw->proc1_irq_ctrl : &iobank0_hw->proc0_irq_ctrl; - hw_set_bits(&irq_ctrl_base->intf[CYW43_PIN_WL_HOST_WAKE / 8], GPIO_IRQ_LEVEL_HIGH << (4 * (CYW43_PIN_WL_HOST_WAKE & 7))); - } -} - -void cyw43_schedule_internal_poll_dispatch(void (*func)(void)) { - low_prio_irq_schedule_dispatch(CYW43_DISPATCH_SLOT_CYW43, func); -} - -// Prevent background processing in pensv and access by the other core -// These methods are called in pensv context and on either core -// They can be called recursively -void cyw43_thread_enter(void) { - // Lock the other core and stop low_prio_irq running - recursive_mutex_enter_blocking(&cyw43_mutex); -} - -#ifndef NDEBUG -void cyw43_thread_lock_check(void) { - // Lock the other core and stop low_prio_irq running - if (recursive_mutex_enter_count(&cyw43_mutex) < 1 || recursive_mutex_owner(&cyw43_mutex) != lock_get_caller_owner_id()) { - panic("cyw43_thread_lock_check failed"); - } -} -#endif - -// Re-enable background processing -void cyw43_thread_exit(void) { - // Run low_prio_irq if needed - if (1 == recursive_mutex_enter_count(&cyw43_mutex)) { - // note the outer release of the mutex is not via cyw43_exit in the low_priority_irq case (it is a direct mutex exit) - assert(!in_low_priority_irq); - // if (low_priority_irq_missed) { - // low_priority_irq_missed = false; - if (low_priority_irq_dispatch_slots[CYW43_DISPATCH_SLOT_CYW43]) { - low_prio_irq_schedule_dispatch(CYW43_DISPATCH_SLOT_CYW43, cyw43_poll); - } - // } - } - recursive_mutex_exit(&cyw43_mutex); -} - - -static void cyw43_delay_until(absolute_time_t until) { - // sleep can be called in IRQs, so there's not much we can do there - if (__get_current_exception()) { - busy_wait_until(until); - } else { - sleep_until(until); - } -} - -void cyw43_delay_ms(uint32_t ms) { - cyw43_delay_until(make_timeout_time_ms(ms)); -} - -void cyw43_delay_us(uint32_t us) { - cyw43_delay_until(make_timeout_time_us(us)); -} - -void cyw43_arch_poll() { - // should not be necessary - // if (cyw43_poll) { - // low_prio_irq_schedule_dispatch(CYW43_DISPATCH_SLOT_CYW43, cyw43_poll); - // } -} - -#ifdef ARDUINO_RASPBERRY_PI_PICO_W -void __attribute__((weak)) cyw43_cb_tcpip_init(cyw43_t *self, int itf); -void cyw43_cb_tcpip_init(cyw43_t *self, int itf) { - (void) self; - (void) itf; -} -void __attribute__((weak)) cyw43_cb_tcpip_deinit(cyw43_t *self, int itf); -void cyw43_cb_tcpip_deinit(cyw43_t *self, int itf) { - (void) self; - (void) itf; -} -void __attribute__((weak)) cyw43_cb_tcpip_set_link_up(cyw43_t *self, int itf); -void cyw43_cb_tcpip_set_link_up(cyw43_t *self, int itf) { - (void) self; - (void) itf; -} -void __attribute__((weak)) cyw43_cb_tcpip_set_link_down(cyw43_t *self, int itf); -void cyw43_cb_tcpip_set_link_down(cyw43_t *self, int itf) { - (void) self; - (void) itf; -} -void __attribute__((weak)) cyw43_cb_process_ethernet(void *cb_data, int itf, size_t len, const uint8_t *buf); -void cyw43_cb_process_ethernet(void *cb_data, int itf, size_t len, const uint8_t *buf) { - (void) cb_data; - (void) itf; - (void) len; - (void) buf; -} -#endif - -#endif diff --git a/cores/rp2040/sdkoverride/pico_bootsel_via_double_reset.c b/cores/rp2040/sdkoverride/pico_bootsel_via_double_reset.c new file mode 100644 index 000000000..bc9dc2110 --- /dev/null +++ b/cores/rp2040/sdkoverride/pico_bootsel_via_double_reset.c @@ -0,0 +1,90 @@ +/* + Copyright (c) 2021 Raspberry Pi (Trading) Ltd. + + Hacked by EFP3 to allow disabling unless requested + + SPDX-License-Identifier: BSD-3-Clause +*/ + +#include "pico.h" +#include "pico/time.h" +#include "pico/bootrom.h" +#include "pico/binary_info.h" + +// PICO_CONFIG: PICO_BOOTSEL_VIA_DOUBLE_RESET_TIMEOUT_MS, Window of opportunity for a second press of a reset button to enter BOOTSEL mode (milliseconds), type=int, default=200, group=pico_bootsel_via_double_reset +#ifndef PICO_BOOTSEL_VIA_DOUBLE_RESET_TIMEOUT_MS +#define PICO_BOOTSEL_VIA_DOUBLE_RESET_TIMEOUT_MS 350 +#endif + +// PICO_CONFIG: PICO_BOOTSEL_VIA_DOUBLE_RESET_ACTIVITY_LED, Optionally define a pin to use as bootloader activity LED when BOOTSEL mode is entered via reset double tap, type=int, min=0, max=29, group=pico_bootsel_via_double_reset + +// PICO_CONFIG: PICO_BOOTSEL_VIA_DOUBLE_RESET_INTERFACE_DISABLE_MASK, Optionally disable either the mass storage interface (bit 0) or the PICOBOOT interface (bit 1) when entering BOOTSEL mode via double reset, type=int, min=0, max=3, default=0, group=pico_bootsel_via_double_reset +#ifndef PICO_BOOTSEL_VIA_DOUBLE_RESET_INTERFACE_DISABLE_MASK +#define PICO_BOOTSEL_VIA_DOUBLE_RESET_INTERFACE_DISABLE_MASK 0u +#endif + +/** \defgroup pico_bootsel_via_double_reset pico_bootsel_via_double_reset + + When the 'pico_bootsel_via_double_reset' library is linked, a function is + injected before main() which will detect when the system has been reset + twice in quick succession, and enter the USB ROM bootloader (BOOTSEL mode) + when this happens. This allows a double tap of a reset button on a + development board to be used to enter the ROM bootloader, provided this + library is always linked. +*/ + +#if !PICO_NO_BI_BOOTSEL_VIA_DOUBLE_RESET +bi_decl(bi_program_feature("double reset -> BOOTSEL")); +#endif + +// Doesn't make any sense for a RAM only binary +#if !PICO_NO_FLASH +static const uint32_t magic_token[] = { + 0xf01681de, 0xbd729b29, 0xd359be7a, +}; + +// Place our marker on the 2nd core's stack...which will not have been touched when this code is executing +static uint32_t *magic_location = (uint32_t*)0x20040000; +//static uint32_t __uninitialized_ram(magic_location)[count_of(magic_token)]; + +/* Check for double reset and enter BOOTSEL mode if detected + + This function is registered to run automatically before main(). The + algorithm is: + + 1. Check for magic token in memory; enter BOOTSEL mode if found. + 2. Initialise that memory with that magic token. + 3. Do nothing for a short while (few hundred ms). + 4. Clear the magic token. + 5. Continue with normal boot. + + Resetting the device twice quickly will interrupt step 3, leaving the token + in place so that the second boot will go to the bootloader. +*/ + +/*static*/ void __attribute__((constructor)) boot_double_tap_check(void) { + for (uint i = 0; i < count_of(magic_token); i++) { + if (magic_location[i] != magic_token[i]) { + // Arm, wait, then disarm and continue booting + for (i = 0; i < count_of(magic_token); i++) { + magic_location[i] = magic_token[i]; + } + busy_wait_us(PICO_BOOTSEL_VIA_DOUBLE_RESET_TIMEOUT_MS * 1000); + magic_location[0] = 0; + return; + } + } + // Detected a double reset, so enter USB bootloader + magic_location[0] = 0; +#ifdef PICO_BOOTSEL_VIA_DOUBLE_RESET_ACTIVITY_LED + const uint32_t led_mask = 1u << PICO_BOOTSEL_VIA_DOUBLE_RESET_ACTIVITY_LED; +#else + const uint32_t led_mask = 0u; +#endif + reset_usb_boot( + led_mask, + PICO_BOOTSEL_VIA_DOUBLE_RESET_INTERFACE_DISABLE_MASK + ); +} + +#endif diff --git a/cores/rp2040/sdkoverride/tusb_absmouse.h b/cores/rp2040/sdkoverride/tusb_absmouse.h new file mode 100644 index 000000000..0cfb08a9b --- /dev/null +++ b/cores/rp2040/sdkoverride/tusb_absmouse.h @@ -0,0 +1,101 @@ +/* + Expost absolute mouse HID descriptor and report + Taken from @tobozo PR https://github.com/hathach/tinyusb/pull/1363 + TODO - remove once that PR merged with TinyUSB + + Copyright (c) 2023 Earle F. Philhower, III + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#pragma once + +#include "tusb.h" +#include "class/hid/hid_device.h" + +// Absolute Mouse: same as the Standard (relative) Mouse Report but +// with int16_t instead of int8_t for X and Y coordinates. +typedef struct TU_ATTR_PACKED { + uint8_t buttons; /**< buttons mask for currently pressed buttons in the mouse. */ + int16_t x; /**< Current x position of the mouse. */ + int16_t y; /**< Current y position of the mouse. */ + int8_t wheel; /**< Current delta wheel movement on the mouse. */ + int8_t pan; // using AC Pan +} hid_abs_mouse_report_t; + + +// Absolute Mouse Report Descriptor Template +#define TUD_HID_REPORT_DESC_ABSMOUSE(...) \ + HID_USAGE_PAGE ( HID_USAGE_PAGE_DESKTOP ) ,\ + HID_USAGE ( HID_USAGE_DESKTOP_MOUSE ) ,\ + HID_COLLECTION ( HID_COLLECTION_APPLICATION ) ,\ + /* Report ID if any */\ + __VA_ARGS__ \ + HID_USAGE ( HID_USAGE_DESKTOP_POINTER ) ,\ + HID_COLLECTION ( HID_COLLECTION_PHYSICAL ) ,\ + HID_USAGE_PAGE ( HID_USAGE_PAGE_BUTTON ) ,\ + HID_USAGE_MIN ( 1 ) ,\ + HID_USAGE_MAX ( 5 ) ,\ + HID_LOGICAL_MIN ( 0 ) ,\ + HID_LOGICAL_MAX ( 1 ) ,\ + /* Left, Right, Middle, Backward, Forward buttons */ \ + HID_REPORT_COUNT( 5 ) ,\ + HID_REPORT_SIZE ( 1 ) ,\ + HID_INPUT ( HID_DATA | HID_VARIABLE | HID_ABSOLUTE ) ,\ + /* 3 bit padding */ \ + HID_REPORT_COUNT( 1 ) ,\ + HID_REPORT_SIZE ( 3 ) ,\ + HID_INPUT ( HID_CONSTANT ) ,\ + HID_USAGE_PAGE ( HID_USAGE_PAGE_DESKTOP ) ,\ + /* X, Y absolute position [0, 32767] */ \ + HID_USAGE ( HID_USAGE_DESKTOP_X ) ,\ + HID_USAGE ( HID_USAGE_DESKTOP_Y ) ,\ + HID_LOGICAL_MIN ( 0x00 ) ,\ + HID_LOGICAL_MAX_N( 0x7FFF, 2 ) ,\ + HID_REPORT_SIZE ( 16 ) ,\ + HID_REPORT_COUNT ( 2 ) ,\ + HID_INPUT ( HID_DATA | HID_VARIABLE | HID_ABSOLUTE ) ,\ + /* Vertical wheel scroll [-127, 127] */ \ + HID_USAGE ( HID_USAGE_DESKTOP_WHEEL ) ,\ + HID_LOGICAL_MIN ( 0x81 ) ,\ + HID_LOGICAL_MAX ( 0x7f ) ,\ + HID_REPORT_COUNT( 1 ) ,\ + HID_REPORT_SIZE ( 8 ) ,\ + HID_INPUT ( HID_DATA | HID_VARIABLE | HID_RELATIVE ) ,\ + HID_USAGE_PAGE ( HID_USAGE_PAGE_CONSUMER ), \ + /* Horizontal wheel scroll [-127, 127] */ \ + HID_USAGE_N ( HID_USAGE_CONSUMER_AC_PAN, 2 ), \ + HID_LOGICAL_MIN ( 0x81 ), \ + HID_LOGICAL_MAX ( 0x7f ), \ + HID_REPORT_COUNT( 1 ), \ + HID_REPORT_SIZE ( 8 ), \ + HID_INPUT ( HID_DATA | HID_VARIABLE | HID_RELATIVE ), \ + HID_COLLECTION_END , \ + HID_COLLECTION_END \ + + +static inline bool tud_hid_abs_mouse_report(uint8_t report_id, + uint8_t buttons, int16_t x, int16_t y, int8_t vertical, int8_t horizontal) { + hid_abs_mouse_report_t report = { + .buttons = buttons, + .x = x, + .y = y, + .wheel = vertical, + .pan = horizontal + }; + + return tud_hid_n_report(0, report_id, &report, sizeof(report)); +} + diff --git a/cores/rp2040/wiring_analog.cpp b/cores/rp2040/wiring_analog.cpp index 537004ae8..0fba463c2 100644 --- a/cores/rp2040/wiring_analog.cpp +++ b/cores/rp2040/wiring_analog.cpp @@ -26,9 +26,12 @@ #include #include +void __clearADCPin(pin_size_t p); + static uint32_t analogScale = 255; static uint32_t analogFreq = 1000; -static bool pwmInitted = false; +static uint32_t pwmInitted = 0; +static bool scaleInitted = false; static bool adcInitted = false; static uint16_t analogWritePseudoScale = 1; static uint16_t analogWriteSlowScale = 1; @@ -40,31 +43,33 @@ extern "C" void analogWriteFreq(uint32_t freq) { return; } if (freq < 100) { - DEBUGCORE("ERROR: analogWriteFreq too low (%d)\n", freq); + DEBUGCORE("ERROR: analogWriteFreq too low (%lu)\n", freq); analogFreq = 100; - } else if (freq > 1000000) { - DEBUGCORE("ERROR: analogWriteFreq too high (%d)\n", freq); - analogFreq = 1000000; + } else if (freq > 10'000'000) { + DEBUGCORE("ERROR: analogWriteFreq too high (%lu)\n", freq); + analogFreq = 10'000'000; } else { analogFreq = freq; } - pwmInitted = false; + pwmInitted = 0; + scaleInitted = false; } extern "C" void analogWriteRange(uint32_t range) { if (range == analogScale) { return; } - if ((range >= 15) && (range <= 65535)) { + if ((range >= 3) && (range <= 65535)) { analogScale = range; - pwmInitted = false; + pwmInitted = 0; + scaleInitted = false; } else { - DEBUGCORE("ERROR: analogWriteRange out of range (%d)\n", range); + DEBUGCORE("ERROR: analogWriteRange out of range (%lu)\n", range); } } extern "C" void analogWriteResolution(int res) { - if ((res >= 4) && (res <= 16)) { + if ((res >= 2) && (res <= 16)) { analogWriteRange((1 << res) - 1); } else { DEBUGCORE("ERROR: analogWriteResolution out of range (%d)\n", res); @@ -78,29 +83,30 @@ extern "C" void analogWrite(pin_size_t pin, int val) { DEBUGCORE("ERROR: Illegal analogWrite pin (%d)\n", pin); return; } - if (!pwmInitted) { + __clearADCPin(pin); + if (!scaleInitted) { // For low frequencies, we need to scale the output max value up to achieve lower periods analogWritePseudoScale = 1; - while (((clock_get_hz(clk_sys) / (float)(analogScale * analogFreq)) > 255.0) && (analogScale < 32678)) { + while (((clock_get_hz(clk_sys) / ((float)analogScale * analogFreq)) > 255.0) && (analogScale < 32678)) { analogWritePseudoScale++; analogScale *= 2; - DEBUGCORE("Adjusting analogWrite values PS=%d, scale=%d\n", analogWritePseudoScale, analogScale); + DEBUGCORE("Adjusting analogWrite values PS=%d, scale=%lu\n", analogWritePseudoScale, analogScale); } // For high frequencies, we need to scale the output max value down to actually hit the frequency target analogWriteSlowScale = 1; - while (((clock_get_hz(clk_sys) / (float)(analogScale * analogFreq)) < 2.0) && (analogScale > 32)) { + while (((clock_get_hz(clk_sys) / ((float)analogScale * analogFreq)) < 1.0) && (analogScale >= 6)) { analogWriteSlowScale++; analogScale /= 2; - DEBUGCORE("Adjusting analogWrite values SS=%d, scale=%d\n", analogWriteSlowScale, analogScale); + DEBUGCORE("Adjusting analogWrite values SS=%d, scale=%lu\n", analogWriteSlowScale, analogScale); } - + scaleInitted = true; + } + if (!(pwmInitted & (1 << pwm_gpio_to_slice_num(pin)))) { pwm_config c = pwm_get_default_config(); - pwm_config_set_clkdiv(&c, clock_get_hz(clk_sys) / (float)(analogScale * analogFreq)); - pwm_config_set_wrap(&c, analogScale); - for (int i = 0; i < 30; i++) { - pwm_init(pwm_gpio_to_slice_num(i), &c, true); - } - pwmInitted = true; + pwm_config_set_clkdiv(&c, clock_get_hz(clk_sys) / ((float)analogScale * analogFreq)); + pwm_config_set_wrap(&c, analogScale - 1); + pwm_init(pwm_gpio_to_slice_num(pin), &c, true); + pwmInitted |= 1 << pwm_gpio_to_slice_num(pin); } val <<= analogWritePseudoScale; @@ -117,7 +123,13 @@ extern "C" void analogWrite(pin_size_t pin, int val) { } auto_init_mutex(_adcMutex); -static int _readBits = 10; +static uint8_t _readBits = 10; +static uint8_t _lastADCMux = 0; +static uint32_t _adcGPIOInit = 0; + +void __clearADCPin(pin_size_t p) { + _adcGPIOInit &= ~(1 << p); +} extern "C" int analogRead(pin_size_t pin) { CoreMutex m(&_adcMutex); @@ -131,13 +143,20 @@ extern "C" int analogRead(pin_size_t pin) { } if (!adcInitted) { adc_init(); + adcInitted = true; + } + if (!(_adcGPIOInit & (1 << pin))) { + adc_gpio_init(pin); + _adcGPIOInit |= 1 << pin; + } + if (_lastADCMux != pin) { + adc_select_input(pin - minPin); + _lastADCMux = pin; } - adc_gpio_init(pin); - adc_select_input(pin - minPin); return (_readBits < 12) ? adc_read() >> (12 - _readBits) : adc_read() << (_readBits - 12); } -extern "C" float analogReadTemp() { +extern "C" float analogReadTemp(float vref) { CoreMutex m(&_adcMutex); if (!m) { @@ -145,13 +164,15 @@ extern "C" float analogReadTemp() { } if (!adcInitted) { adc_init(); + adcInitted = true; } + _lastADCMux = 0; adc_set_temp_sensor_enabled(true); delay(1); // Allow things to settle. Without this, readings can be erratic adc_select_input(4); // Temperature sensor int v = adc_read(); adc_set_temp_sensor_enabled(false); - float t = 27.0f - ((v * 3.3f / 4096.0f) - 0.706f) / 0.001721f; // From the datasheet + float t = 27.0f - ((v * vref / 4096.0f) - 0.706f) / 0.001721f; // From the datasheet return t; } diff --git a/cores/rp2040/wiring_digital.cpp b/cores/rp2040/wiring_digital.cpp index a5ce3458d..277f70189 100644 --- a/cores/rp2040/wiring_digital.cpp +++ b/cores/rp2040/wiring_digital.cpp @@ -21,6 +21,8 @@ #include "Arduino.h" #include +extern void __clearADCPin(pin_size_t p); + static PinMode _pm[30]; extern "C" void pinMode(pin_size_t ulPin, PinMode ulMode) __attribute__((weak, alias("__pinMode"))); @@ -75,6 +77,10 @@ extern "C" void __pinMode(pin_size_t ulPin, PinMode ulMode) { return; } _pm[ulPin] = ulMode; + + if ((ulPin >= std::min(A0, A3)) && (ulPin <= std::max(A0, A3))) { + __clearADCPin(ulPin); + } } extern "C" void digitalWrite(pin_size_t ulPin, PinStatus ulVal) __attribute__((weak, alias("__digitalWrite"))); diff --git a/cores/rp2040/wiring_private.cpp b/cores/rp2040/wiring_private.cpp index a835f9847..06c6bc8b1 100644 --- a/cores/rp2040/wiring_private.cpp +++ b/cores/rp2040/wiring_private.cpp @@ -22,24 +22,30 @@ #include #include #include -#include #include // Support nested IRQ disable/re-enable -static std::stack _irqStack[2]; +#define maxIRQs 15 +static uint32_t _irqStackTop[2] = { 0, 0 }; +static uint32_t _irqStack[2][maxIRQs]; extern "C" void interrupts() { - if (_irqStack[get_core_num()].empty()) { + auto core = get_core_num(); + if (!_irqStackTop[core]) { // ERROR return; } - auto oldIrqs = _irqStack[get_core_num()].top(); - _irqStack[get_core_num()].pop(); - restore_interrupts(oldIrqs); + restore_interrupts(_irqStack[core][--_irqStackTop[core]]); } extern "C" void noInterrupts() { - _irqStack[get_core_num()].push(save_and_disable_interrupts()); + auto core = get_core_num(); + if (_irqStackTop[core] == maxIRQs) { + // ERROR + panic("IRQ stack overflow"); + } + + _irqStack[core][_irqStackTop[core]++] = save_and_disable_interrupts(); } // Only 1 GPIO IRQ callback for all pins, so we need to look at the pin it's for and @@ -71,7 +77,7 @@ static std::map _map; void _gpioInterruptDispatcher(uint gpio, uint32_t events) { (void) events; // Only need to lock around the std::map check, not the whole IRQ callback - CoreMutex m(&_irqMutex); + CoreMutex m(&_irqMutex, (FromISR | DebugEnable)); if (m) { auto irq = _map.find(gpio); if (irq != _map.end()) { @@ -81,6 +87,15 @@ void _gpioInterruptDispatcher(uint gpio, uint32_t events) { } } +// To be called when appropriately protected w/IRQ and mutex protects +static void _detachInterruptInternal(pin_size_t pin) { + auto irq = _map.find(pin); + if (irq != _map.end()) { + gpio_set_irq_enabled(pin, 0x0f /* all */, false); + _map.erase(pin); + } +} + extern "C" void attachInterrupt(pin_size_t pin, voidFuncPtr callback, PinStatus mode) { CoreMutex m(&_irqMutex); if (!m) { @@ -97,7 +112,7 @@ extern "C" void attachInterrupt(pin_size_t pin, voidFuncPtr callback, PinStatus default: return; // ERROR } noInterrupts(); - detachInterrupt(pin); + _detachInterruptInternal(pin); CBInfo cb(callback); _map.insert({pin, cb}); gpio_set_irq_enabled_with_callback(pin, events, true, _gpioInterruptDispatcher); @@ -120,7 +135,7 @@ void attachInterruptParam(pin_size_t pin, voidFuncPtrParam callback, PinStatus m default: return; // ERROR } noInterrupts(); - detachInterrupt(pin); + _detachInterruptInternal(pin); CBInfo cb(callback, param); _map.insert({pin, cb}); gpio_set_irq_enabled_with_callback(pin, events, true, _gpioInterruptDispatcher); @@ -134,10 +149,6 @@ extern "C" void detachInterrupt(pin_size_t pin) { } noInterrupts(); - auto irq = _map.find(pin); - if (irq != _map.end()) { - gpio_set_irq_enabled(pin, 0x0f /* all */, false); - _map.erase(pin); - } + _detachInterruptInternal(pin); interrupts(); } diff --git a/libraries/WiFi/src/wl_definitions.h b/cores/rp2040/wl_definitions.h similarity index 98% rename from libraries/WiFi/src/wl_definitions.h rename to cores/rp2040/wl_definitions.h index dbeece0f6..0ed33fb72 100644 --- a/libraries/WiFi/src/wl_definitions.h +++ b/cores/rp2040/wl_definitions.h @@ -43,7 +43,7 @@ extern "C" { #define WL_IPV4_LENGTH 4 // Maximum size of a SSID list #define WL_NETWORKS_LIST_MAXNUM 10 -// Maxmium number of socket +// Maximum number of socket #define WIFI_MAX_SOCK_NUM 10 // Socket not available constant #define SOCK_NOT_AVAIL 255 diff --git a/libraries/WiFi/src/wl_types.h b/cores/rp2040/wl_types.h similarity index 100% rename from libraries/WiFi/src/wl_types.h rename to cores/rp2040/wl_types.h diff --git a/docs/adc.rst b/docs/adc.rst new file mode 100644 index 000000000..6040e8395 --- /dev/null +++ b/docs/adc.rst @@ -0,0 +1,87 @@ +ADC Input Library +================= + +The ADC pins can be sampled and recorded by an application using the same +interface as the I2S or PWM Audio libraries. This allows analog devices which +need to be periodically sampled to be read by applications, easily, such as: + +* Analog electret microphones + +* Potentiometers + +* Light dependent resistors (LDR), etc. + + +Up to 4 analog samples can be recorded by the hardware (``A0`` ... ``A4``), and all +recording is done at 16-bit levels (but be aware that the ADC in the Pico will only +ever return values between 0...4095). + +The interface for the ``ADCInput`` device is very similar to the ``I2S`` input +device, and most code can be ported simply by instantiating a ``ADCInput`` +object in lieu of an ``I2S`` input object and choosing the pins to record. + +Since this uses the ADC hardware, no ``analogRead`` or ``analogReadTemp`` calls are +allowed while in use. + +ADC Input API +------------- + +ADCInput(pin0 [, pin1, pin2, pin3]) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Creates an ADC input object which will record the pins specified in the code. +Only pins ``A0`` ... ``A4`` can be used, and they must be specified in increasing +order (i.e. ``ADCInput(A0, A1);`` is valid, but ``ADCInput(A1, A0)`` is not. + +bool setBuffers(size_t buffers, size_t bufferWords) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Set the number of DMA buffers and their size in 32-bit words. Call before +``ADCInput::begin()``. + +When running at high sample rates, it is recommended to increase the +``bufferWords`` to 32 or higher (i.e. ``adcinput.setBuffers(4, 32);`` ). + +bool setPins(pin_size_t pin [, pin1, pin2, pin3]) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Adjusts the pin to record. Only legal before ``ADCInput::begin()``. + +bool setFrequency(long sampleRate) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Sets the ADC sampling frequency, but does not start recording (however if the +device was already running, it will continue to run at the new frequency). Note +that every pin requested will be sampled at this frequency, one after the other. +That is, if you have code like this: + +.. code:: cpp + + ADCInput adc(A0, A1); + adc.setFrequency(1000); + +``A0`` will be sampled at 0ms, 1ms, 2ms, etc. and ``A1`` will be sampled at 0.5ms +1.5ms, 2.5ms, etc. Each input is sampled at the proper frequency but offset in time +since there is only one active ADC at a time. + +bool begin()/begin(long sampleRate) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Start the ADC input up with the given sample rate, or with the value set +using the prior ``setFrequency`` call. + +void end() +~~~~~~~~~~ +Stops the ADC Input device. + +int read() +~~~~~~~~~~ +Reads a single sample of recorded ADC data, as a 16-bit value. When multiple pins are +recorded the first read will be pin 0, the second will be pin 1, etc. Applications need +to keep track of which pin is being returned (normally by always reading out all pins +at once). Will not return until data is available. + +int available() +~~~~~~~~~~~~~~~ +Returns the number of samples that can be read without potentially blocking. + +void onReceive(void (\*fn)(void)) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Sets a callback to be called when a ADC input DMA buffer is fully filled. +Will be in an interrupt context so the specified function must operate +quickly and not use blocking calls like delay(). diff --git a/docs/analog.rst b/docs/analog.rst index 6df315458..3959bd0b2 100644 --- a/docs/analog.rst +++ b/docs/analog.rst @@ -14,13 +14,14 @@ Returns a value from 0...4095 correspionding to the ADC reading of the specific pin. void analogReadResolution(int bits) -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Determines the resolution (in bits) of the value returned by the analogRead() function. Default resolution is 10bit. -float analogReadTemp() -~~~~~~~~~~~~~~~~~~~~~~ +float analogReadTemp(float vref = 3.3f) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Returns the temperature, in Celsius, of the onboard thermal sensor. +If you have a custom Vref for the ADC on your RP2040 board, you can pass it in as a parameter. Calling with no parameters assumes the normal, 3.3V Vref. This reading is not exceedingly accurate and of relatively low resolution, so it is not a replacement for an external temperature sensor in many cases. diff --git a/docs/bluetooth.rst b/docs/bluetooth.rst new file mode 100644 index 000000000..71d9bcf8a --- /dev/null +++ b/docs/bluetooth.rst @@ -0,0 +1,49 @@ +Bluetooth on PicoW Support +========================== + +As of the Pico-SDK version 1.5.0, the PicoW has **BETA** Bluetooth support. +So, since this core builds off the SDK the best that can be suggested it +that we have **ALPHA** Bluetooth support. As such, bug reports are welcome, +but Pull Requests fixing problems you find are seriously appreciated. + +Enabling Bluetooth +------------------ +To enable Bluetooth (BT), use the ``Tools->IP/Bluetooth Stack`` menu. It +requires around 80KB of flash and 20KB of RAM when enabled. + +Both Bluetooth Classic and BluetoothBLE are enabled in ``btstack_config.h``. + +Included Bluetooth Libraries +---------------------------- +You may use the ``KeyboardBT``, ``MouseBT``, or ``JoystickBT`` to emulate a +Bluetooth Classic HID device using the same API as their USB versions. + +You may use the ``KeyboardBLE``, ``MouseBLE``, or ``JoystickBLE`` to emulate a +Bluetooth Low Energy (BLE) HID device using the same API as their USB versions. + +The ``SerialBT`` library implements a very simple SPP (Serial Port Profile) +Serial-compatible port. + +Writing Custom Bluetooth Applications +------------------------------------- +You may also write full applications using the ``BTStack`` standard callback +method, but please be aware that the Raspberry Pi team has built an +interrupt-driven version of the BT execute loop, so there is no need +to actually call ``btstack_run_loop_execute`` because the ``async_context`` +handler will do it for you. + +There is no need to call ``cyw43_arch_init`` in your code, either, as that +is part of the PicoW variant booting process. + +For many BTStack examples, you simply need call the included +``btstack_main()`` and make sure that ``hci_power_control(HCI_POWER_ON);`` is +called afterwards to start processing (in the background). + +You will also need to acquire the BT ``async_context`` system lock before +calling any BTStack APIs. See the ``libraries/PicoBluetoothHID`` helper +class for an example of how to do this. + +Note that if you need to modify the system ``btstack_config.h`` file, do so +in the ``tools/libpico`` directory and rebuild the Pico SDK static library. +Otherwise the change will not take effect in the precompiled code, leading +to really bad behavior. diff --git a/docs/conf.py b/docs/conf.py index 7d2795a35..fb226599d 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -54,9 +54,9 @@ # built documents. # # The short X.Y version. -version = u'2.4.0' +version = u'3.2.0' # The full version, including alpha/beta/rc tags. -release = u'2.4.0' +release = u'3.2.0' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. diff --git a/docs/contrib.rst b/docs/contrib.rst new file mode 100644 index 000000000..8c8f7a757 --- /dev/null +++ b/docs/contrib.rst @@ -0,0 +1,100 @@ +Contributing and Porting to the Core +==================================== + +First of all, thank you for contributing to the project. It's a lot of work +keeping up with all the different uses of the RP2040, so the more people +working on the code, the better. Your assistance can help the project +succeed. + +Contributing to the Core (Pull Requests) +---------------------------------------- + +We use the standard GitHub Pull Request model. If you're unfamiliar with it, +this `guide `__ +gives a simple overview of the process. + +All pull requests have to pass a set of Continuous Integration (CI) checks +which help make sure the code compiles under different configurations and has +no spelling or style errors. + +Tips for a Good Pull Request (PR) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +All code in the core and libraries, except for INO sketches, uses a 4-space +indent with cuddled brackets. When in doubt, copy your formatting from the +surrounding code. You should install ``astyle`` and run ``tests/restyle.sh`` +on your machine before committing and pushing any pull requests to ensure +the formatting is correct. + +Describe the change you're proposing and why it's important in your +``git commit`` message. If it fixes an open issue, place ``Fixes #xxxx`` +(where xxxx is the issue number) in the message to link the two. + +Try and only change one thing per pull request. That makes it easier to +review and prioritize. Opening up a separate PR per change also helps keep +track of them when release messages are generated. + +Adding a New Board +------------------ + +Adding a new board requires: + +* Updated ``tools/makeboards.py`` script +* Updated ``boards.txt`` file, generated by ``makeboard.py`` +* Updated ``package_pico_index.template.json`` file, generated by ``makeboard.py`` +* New ``tools/json/BOARD_NAME.json`` board file for Platform.IO +* New ``variants/BOARD_NAME/pins_arduino.h`` header defining the I/O pins + +To add a new RP2040 board you will need to update the ``tools/makeboards.py`` +script. Do *NOT* manually edit ``boards.txt``, that file is machine generated. +You will need to add a ``MakeBoard`` call at the end of the file. Please be sure +to add your board so that it sorts alphabetically, starting with the company name +and then the board name. Otherwise it is hard to find a specific board in the menu. + +Run ``python3 tools/makeboards.py`` to update the ``boards.txt`` file and generate +a Platform.IO JSON file in the ``tools/json`` directory. + +Create a folder called ``variants/BOARD_NAME`` and place in a ``pins_arduino.h`` +file in it that contains your default pin name mapping (i.e. SPI0/1 pins, UART +pins, LED_DEFAULT, etc.). Copying one of the existing ones as a template can +make this task much simpler. + +In your ``git commit`` be sure to add the newly generated ``tools/json/XXX.json`` +file as well as the modified ``makeboards`` script and ``boards.txt``, the new +``pins_arduino.h`` header you generated, and the Arduino packaging JSON +``package/package_pico_index.template.json``. You should also add a note in +the ``README.md`` file listing your new board. + +Submit the updated commit as a PR and, if all goes well, your board will be in +on the next core release. + + +Porting Libraries and Applications to the Core +---------------------------------------------- + +We try and follow Arduino standards so, with luck, porting to this core should +be relatively straightforward. The ``WiFi`` library and associates support +libraries like ``WebServer`` are modeled after the ESP32 and ESP8266 versions +of those libraries, combined with the "standard" Arduino ``WiFi`` one. + +Compiler Defines for Porting +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +If you are adding RP2040 support to an existing library and need to isolate +code that only runs on this core, use the following define. + +.. code:: cpp + + #if defined(ARDUINO_ARCH_RP2040) && !defined(__MBED__) + ~~~ your changes ~~~ + #endif + +Library Architectures +~~~~~~~~~~~~~~~~~~~~~ + +After adding support in the code, libraries need their ``library.properties`` +and ``library.json`` files updated to indicate support, or the IDE will +not know your new code is compatible here. + +Add ``rp2040`` to ``architectures`` (in ``library.properties``) and +``"rp2040"`` to ``platforms[]`` (in ``library.json``) to let the tools know. diff --git a/docs/fs.rst b/docs/fs.rst index 6fb376701..384acdc22 100644 --- a/docs/fs.rst +++ b/docs/fs.rst @@ -98,9 +98,19 @@ The included ``SD`` library is the Arduino standard one. Please refer to the [Arduino SD reference](https://www.arduino.cc/en/reference/SD) for more information. +Using Second SPI port for SD +---------------------------- +The ``SD`` library ``begin()`` has been modified to allow you to use the +second SPI port, ``SPI1``. Just use the following call in place of +``SD.begin(cspin)`` + +.. code:: cpp + + SD.begin(cspin, SPI1); + File system object (LittleFS/SD/SDFS) --------------------------------------------- +------------------------------------- setConfig ~~~~~~~~~ diff --git a/docs/help.rst b/docs/help.rst index 2ac2d95a0..0584a037a 100644 --- a/docs/help.rst +++ b/docs/help.rst @@ -1,5 +1,5 @@ -Getting Help and Contributing -============================= +Getting Help +============ This is a community supported project and has multiple ways to get assistance. Posting complete details, in a polite and organized way will get the best diff --git a/docs/httpclient.rst b/docs/httpclient.rst new file mode 100644 index 000000000..a466729f6 --- /dev/null +++ b/docs/httpclient.rst @@ -0,0 +1,40 @@ +HTTPClient Library +================== + +A simple HTTP requestor that can handle both HTTP and HTTP requests is +included as the ``HTTPClient`` library. + +Check the examples for use under HTTP and HTTPS configurations. In general, +for HTTP connections (unsecured and very uncommon on the internet today) simply +passing in a URL and performiung a GET is sufficient to transfer data. + +.. code:: cpp + + // Error checking is left as an exercise for the reader... + HTTPClient http; + if (http.begin("http://my.server/url")) { + if (http.GET() > 0) { + String data = http.getString(); + } + http.end(); + } + +For HTTPS connections, simply add the appropriate WiFiClientSecure calls +as needed (i.e. ``setInsecure()``, ``setTrustAnchor``, etc.). See the +WiFiClientSecure documentation for more details. + +.. code:: cpp + + // Error checking is left as an exercise for the reader... + HTTPClient https; + https.setInsecure(); // Use certs, but do not check their authenticity + if (https.begin("https://my.secure.server/url")) { + if (https.GET() > 0) { + String data = https.getString(); + } + https.end(); + } + +Unlike the ESP8266 and ESP32 ``HTTPClient`` implementations it is not necessary +to create a ``WiFiClient`` or ``WiFiClientSecure`` to pass in to the ``HTTPClient`` +object. diff --git a/docs/i2s.rst b/docs/i2s.rst index cb784cf3f..c988e1a4d 100644 --- a/docs/i2s.rst +++ b/docs/i2s.rst @@ -58,6 +58,19 @@ Sets the word clock frequency, but does not start the I2S device if not already running. May be called after ``I2S::begin()`` to change the sample rate on-the-fly. +bool setLSBJFormat() +~~~~~~~~~~~~~~~~~~~~ +Enables LSB-J format for I2S output. In this mode the MSB comes out at the +same time as the LRCLK changes, and not the normal 1-cycle delay. Useful for +DAC chips like the PT8211. + +bool swapClocks() +~~~~~~~~~~~~~~~~~ +Certain boards are hardwired with the WCLK before the BCLK, instead of the normal +way around. This call swaps the WCLK and BCLK pins. Note that you still call +``setBCLK(x)`` with ``x`` being the lowest pin ID (i.e. in swapClocks mode the +``setBCLK`` call actually sets LRCLK). + bool begin()/begin(long sampleRate) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Start the I2S device up with the given sample rate, or with the value set diff --git a/docs/ide.rst b/docs/ide.rst index 106b69475..453246a2e 100644 --- a/docs/ide.rst +++ b/docs/ide.rst @@ -38,7 +38,7 @@ for normal operations. Generic RP2040 Support ---------------------- If your RP2040 board isn't in the menus you can still use it with the -IDE bu using the `Board->Generic RP2040` menu option. You will need to +IDE by using the `Board->Generic RP2040` menu option. You will need to then set the flash size (see above) and tell the IDE how to communicate with the flash chip using the `Tools->Boot Stage 2` menu. diff --git a/docs/images/longpath.png b/docs/images/longpath.png new file mode 100644 index 000000000..90f22d255 Binary files /dev/null and b/docs/images/longpath.png differ diff --git a/docs/index.rst b/docs/index.rst index cf191af22..ef872f92a 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -16,7 +16,9 @@ For the latest version, always check https://github.com/earlephilhower/arduino-p :maxdepth: 2 :caption: Contents: - Getting Help and Contributing + Getting Help + Contributing + Installation IDE Menus @@ -30,6 +32,8 @@ For the latest version, always check https://github.com/earlephilhower/arduino-p Digital I/O EEPROM I2S Audio + PWM Audio + Microphone (and Analog Sensor) Input Serial USB and UARTs "Software Serial" PIO UART Servo @@ -39,6 +43,10 @@ For the latest version, always check https://github.com/earlephilhower/arduino-p USB (Arduino and Adafruit_TinyUSB) Multicore Processing + Bluetooth (Alpha/Beta) + + Single File USB Drive + FreeRTOS SMP (multicore) WiFi (Pico-W Support) @@ -50,6 +58,8 @@ For the latest version, always check https://github.com/earlephilhower/arduino-p WiFiClientSecure (TLS/SSL/HTTPS) WiFiServerSecure (TLS/SSL/HTTPS) + HTTP/HTTPS Client + Over-the-Air (OTA) Updates Ported/Optimized Libraries diff --git a/docs/install.rst b/docs/install.rst index 7da187a84..a53dc1a7c 100644 --- a/docs/install.rst +++ b/docs/install.rst @@ -5,10 +5,23 @@ The Arduino-Pico core can be installed using the Arduino IDE Boards Manager or using `git`. If you want to simply write programs for your RP2040 board, the Boards Manager installation will suffice, but if you want to try the latest pre-release versions and submit improvements, you will need the `git` -instllation. +installation. Installing via Arduino Boards Manager ------------------------------------- +1. Open up the Arduino IDE and go to File->Preferences. +2. In the dialog that pops up, enter the following URL in the "Additional Boards Manager URLs" field: https://github.com/earlephilhower/arduino-pico/releases/download/global/package_rp2040_index.json + + .. image:: images/install1.png + +3. Hit OK to close the dialog. +4. Go to Tools->Boards->Board Manager in the IDE +5. Type "pico" in the search box and select "Add": + + .. image:: images/install2.png + +Arduino IDE Installation Warning +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ **Note for Windows Users**: Please do not use the Windows Store version of the actual Arduino application because it has issues detecting attached Pico boards. Use the "Windows ZIP" or plain "Windows" executable (EXE) download @@ -17,16 +30,29 @@ it suggests. Otherwise the Pico board may not be detected. Also, if trying out the 2.0 beta Arduino please install the release 1.8 version beforehand to ensure needed device drivers are present. -1. Open up the Arduino IDE and go to File->Preferences. -2. In the dialog that pops up, enter the following URL in the "Additional Boards Manager URLs" field: https://github.com/earlephilhower/arduino-pico/releases/download/global/package_rp2040_index.json +**Note for Linux Users**: If you installed the Arduino IDE using Flatpak, which +is common in Pop!_OS, Fedora, and Mint, among others, you may need to configure +Flatpak to allow the IDE access to files outside your home folder. The RP2040 +device is sometimes mounted as a folder in /opt or /media, which Flatpak will +prevent the Arduino IDE from accessing. For Arduino IDE V2, override the filesystem +restriction using ``flatpak override --user --filesystem=host cc.arduino.IDE2`` . For +For Arduino IDE < V2, use ``flatpak override --user --filesystem=host cc.arduino.arduinoide``. - .. image:: images/install1.png +Installing via Arduino CLI +-------------------------- +To install using the Arduino command line tool (arduino-cli): -3. Hit OK to close the dialog. -4. Go to Tools->Boards->Board Manager in the IDE -5. Type "pico" in the search box and select "Add": +.. code:: bash - .. image:: images/install2.png + arduino-cli config add board_manager.additional_urls https://github.com/earlephilhower/arduino-pico/releases/download/global/package_rp2040_index.json + arduino-cli core update-index + arduino-cli core install rp2040:rp2040 + +To list the supported boards: + +.. code:: bash + + arduino-cli board listall | grep rp2040 Installing via GIT ------------------ @@ -65,25 +91,14 @@ Them hit the upload button and your sketch should upload and run. In some cases the Pico will encounter a hard hang and its USB port will not respond to the auto-reset request. Should this happen, just follow the initial procedure of holding the BOOTSEL button down while plugging in the Pico to enter the ROM bootloader. -Unable to Upload First Sketch ------------------------------ -If the Arduino IDE has never seen a serial port from a working device (Pico, AVR, or any other serial port), you -may not be able to install using the prior directions because the ``Tools->Port`` menu will be grayed out and -empty. In this case, a special workaround identified by @fjansson in `this issue report `_ . - -To allow subsequent uploads to automatically work, you will need to manually install a UF2 binary onto the Raspberry Pi Pico one time to -allow it to present a Serial port for the Arduino IDE to detect and save. - -Perform the following steps to program a dummy sketch: - -1. Open a new, empty sketch (doesn't work with a read-only example sketch). -2. Compile it by pressing the "Verify" checkmark button. -3. Select the ``Sketch -> Export Compiled Binary`` menu. Select a location e.g. the desktop. A folder is created there, containing a file ending in .uf2 -4. Copy this file to the Pico's drive, by drag and drop in the Explorer. - -The Pico restarts and now now has a serial port. Now the Port menu in Arduino is not gray anymore, select the port there. -After this, normal uploading from the Arduino editor should work. +Uploading the First Sketch +-------------------------- +The first time you upload a sketch to a board, you'll need to use the built-in ROM bootloader to handle the upload and not a serial port. +1. Hold the BOOTSEL button while plugging in the board. +2. Select ``Tools->Port->UF2 Board`` from the menu. +3. Upload as normal. +4. After the board boots up, select the new serial port from the ``Tools->Port`` menu. Windows 7 Driver Notes ---------------------- @@ -136,6 +151,28 @@ For detailed usage information, please check the repo documentation available at * https://arduino-pico.readthedocs.io/en/latest/fs.html +Uploading Sketches with Picotool +-------------------------------- +Because the Picotool uses a custom device driver in the Pico to handle upload, when using the ``Upload Method->Picotool`` mode custom code needs to be run on the Pico which is not included by default for compatibility and code savings. + +So for the first sketch you will need to rebuild (with the ``Upload Method->Picotool`` selected in them menus) and then manually hold down BOOTSEL and insert the Pico USB cable to enter the ROM bootloader. + +After the initial upload, as long as the running binary was built using the ``Picotool`` upload method, then the normal upload process should work. + +Under MacOS, it may be necessary to install the USB support libraries from a command terminal before the ``Picotool`` upload method can be used: + +.. code:: + + brew install libusb + +For Ubuntu and other Linux operating systems you may need to add the following lines to a new `udev` config file(``99-picotool.rules``) to allow normal users to access the special USB device the Pico exports: + +.. code:: + + echo 'SUBSYSTEM=="usb", ATTRS{idVendor}=="2e8a", ATTRS{idProduct}=="0003", MODE="660", GROUP="plugdev"' | sudo tee -a /etc/udev/rules.d/98-Picotool.rules + echo 'SUBSYSTEM=="usb", ATTRS{idVendor}=="2e8a", ATTRS{idProduct}=="000a", MODE="660", GROUP="plugdev"' | sudo tee -a /etc/udev/rules.d/98-Picotool.rules + sudo udevadm control --reload + Uploading Sketches with Picoprobe --------------------------------- If you have built a Raspberry Pi Picoprobe, you can use OpenOCD to handle your sketch uploads and for debugging with GDB. diff --git a/docs/ota.rst b/docs/ota.rst old mode 100755 new mode 100644 index d8305ab76..1e255c920 --- a/docs/ota.rst +++ b/docs/ota.rst @@ -10,8 +10,9 @@ OTA (Over the Air) update is the process of uploading firmware to a Pico using a OTA may be done using: - `Arduino IDE <#arduino-ide>`__ -- `Web Browser <#web-browser>`__ - Coming soon -- `HTTP Server <#http-server>`__ - Coming soon +- `Web Browser <#web-browser>`__ +- `HTTP Server <#http-server>`__ +- Any other method (ZModen receive over a UART port, etc.) by using the ``Updater`` object in your sketch The Arduino IDE option is intended primarily for the software development phase. The other two options would be more useful after deployment, to provide the module with application updates either manually with a web browser, or automatically using an HTTP server. @@ -48,16 +49,16 @@ Check functionality provided with the `ArduinoOTA `__ and espota.py use `Digest-MD5 `__ to authenticate uploads. Integrity of transferred data is verified on the ESP side using `MD5 `__ checksum. +Certain basic protection is already built in and does not require any additional coding by the developer. `ArduinoOTA `__ and espota.py use `Digest-MD5 `__ to authenticate uploads. Integrity of transferred data is verified on the Pico side using `MD5 `__ checksum. -Make your own risk analysis and, depending on the application, decide what library functions to implement. If required, consider implementation of other means of protection from being hacked, like exposing modules for uploads only according to a specific schedule, triggering OTA only when the user presses a dedicated “Update” button wired to the ESP, etc. +Make your own risk analysis and, depending on the application, decide what library functions to implement. If required, consider implementation of other means of protection from being hacked, like exposing modules for uploads only according to a specific schedule, triggering OTA only when the user presses a dedicated “Update” button wired to the Pico, etc. Advanced Security - Signed Updates ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ While the above password-based security will dissuade casual hacking attempts, it is not highly secure. For applications where a higher level of security is needed, cryptographically signed OTA updates can be required. This uses SHA256 hashing in place of MD5 (which is known to be cryptographically broken) and RSA-2048 bit level public-key encryption to guarantee that only the holder of a cryptographic private key can produce signed updates accepted by the OTA update mechanisms. -Signed updates are updates whose compiled binaries are signed with a private key (held by the developer) and verified with a public key (stored in the application and available for all to see). The signing process computes a hash of the binary code, encrypts the hash with the developer's private key, and appends this encrypted hash (also called a signature) to the binary that is uploaded (via OTA, web, or HTTP server). If the code is modified or replaced in any way by anyone except the holder of the developer's private key, the signature will not match and the ESP8266 will reject the upload. +Signed updates are updates whose compiled binaries are signed with a private key (held by the developer) and verified with a public key (stored in the application and available for all to see). The signing process computes a hash of the binary code, encrypts the hash with the developer's private key, and appends this encrypted hash (also called a signature) to the binary that is uploaded (via OTA, web, or HTTP server). If the code is modified or replaced in any way by anyone except the holder of the developer's private key, the signature will not match and the Pico will reject the upload. Cryptographic signing only protects against tampering with binaries delivered via OTA. If someone has physical access, they will always be able to flash the device over the serial port. Signing also does not encrypt anything but the hash (so that it can't be modified), so this does not protect code inside the device: if a user has physical access they can read out your program. @@ -134,7 +135,7 @@ Compile the sketch normally and, once a `.bin` file is available, sign it using .. code:: bash - /tools/signing.py --mode sign --privatekey --bin --out + /tools/signing.py --mode sign --privatekey --bin --out Compression ----------- @@ -155,14 +156,14 @@ If signing is desired, sign the gzip compressed file *after* compression. .. code:: bash gzip -9 sketch.bin - /tools/signing.py --mode sign --privatekey --bin sketch.bin.gz --out sketch.bin.gz.signed + /tools/signing.py --mode sign --privatekey --bin sketch.bin.gz --out sketch.bin.gz.signed Safety ~~~~~~ -The OTA process consumes some of the ESP’s resources and bandwidth during upload. Then, the module is restarted and a new sketch executed. Analyse and test how this affects the functionality of the existing and new sketches. +The OTA process consumes some of the Pico’s resources and bandwidth during upload. Then, the module is restarted and a new sketch executed. Analyse and test how this affects the functionality of the existing and new sketches. -If the ESP is in a remote location and controlling some equipment, you should devote additional attention to what happens if operation of this equipment is suddenly interrupted by the update process. Therefore, decide how to put this equipment into a safe state before starting the update. For instance, your module may be controlling a garden watering system in a sequence. If this sequence is not properly shut down and a water valve is left open, the garden may be flooded. +If the Pico is in a remote location and controlling some equipment, you should devote additional attention to what happens if operation of this equipment is suddenly interrupted by the update process. Therefore, decide how to put this equipment into a safe state before starting the update. For instance, your module may be controlling a garden watering system in a sequence. If this sequence is not properly shut down and a water valve is left open, the garden may be flooded. The following functions are provided with the `ArduinoOTA `__ library and intended to handle functionality of your application during specific stages of OTA, or on an OTA error: @@ -215,6 +216,125 @@ You will not be prompted for a reentering the same password next time. Arduino I Please note, it is possible to reveal password entered previously in Arduino IDE, if IDE has not been closed since last upload. This can be done by enabling *Show verbose output during: upload* in *File > Preferences* and attempting to upload the module. + + + +Web Browser +----------- + +Updates described in this chapter are done with a web browser that can be useful in the following typical scenarios: + +- after application deployment if loading directly from Arduino IDE is inconvenient or not possible, +- after deployment if user is unable to expose module for OTA from external update server, +- to provide updates after deployment to small quantity of modules when setting an update server is not practicable. + +Requirements +~~~~~~~~~~~~ + +- The Pico and the computer must be connected to the same network, or the IP of the Pico should be known if on a different network. + +Implementation Overview +~~~~~~~~~~~~~~~~~~~~~~~ + +Updates with a web browser are implemented using ``HTTPUpdateServer`` class together with ``WebServer`` and ``LEAmDNS`` classes. The following code is required to get it work: + +setup() + +.. code:: cpp + + MDNS.begin(host); + + httpUpdater.setup(&httpServer); + httpServer.begin(); + + MDNS.addService("http", "tcp", 80); + +loop() + +.. code:: cpp + + httpServer.handleClient(); + +In case OTA update fails dead after entering modifications in your sketch, you can always recover module by loading it over a serial port. Then diagnose the issue with sketch using Serial Monitor. Once the issue is fixed try OTA again. + + +HTTP Server +----------- + +``HTTPUpdate`` class can check for updates and download a binary file from HTTP web server. It is possible to download updates from every IP or domain address on the network or Internet. + +Note that by default this class closes all other connections except the one used by the update, this is because the update method blocks. This means that if there's another application receiving data then TCP packets will build up in the buffer leading to out of memory errors causing the OTA update to fail. There's also a limited number of receive buffers available and all may be used up by other applications. + +There are some cases where you know that you won't be receiving any data but would still like to send progress updates. +It's possible to disable the default behaviour (and keep connections open) by calling closeConnectionsOnUpdate(false). + +Requirements +~~~~~~~~~~~~ + +- web server + +Arduino code +~~~~~~~~~~~~ + +Simple updater +^^^^^^^^^^^^^^ + +Simple updater downloads the file every time the function is called. + +.. code:: cpp + + WiFiClient client; + HTTPUpdate.update(client, "192.168.0.2", 80, "/arduino.bin"); + +Advanced updater +^^^^^^^^^^^^^^^^ + +Its possible to point the update function to a script on the server. If a version string argument is given, it will be sent to the server. The server side script can use this string to check whether an update should be performed. + +The server-side script can respond as follows: - response code 200, and send the firmware image, - or response code 304 to notify Pico that no update is required. + +.. code:: cpp + + WiFiClient client; + t_httpUpdate_return ret = HTTPUpdate.update(client, "192.168.0.2", 80, "/pico/update/arduino.php", "optional current version string here"); + switch(ret) { + case HTTP_UPDATE_FAILED: + Serial.println("[update] Update failed."); + break; + case HTTP_UPDATE_NO_UPDATES: + Serial.println("[update] Update no Update."); + break; + case HTTP_UPDATE_OK: + Serial.println("[update] Update ok."); // may not be called since we reboot the RP2040 + break; + } + +TLS updater +^^^^^^^^^^^ + +Please read and try the examples provided with the library. + +Server request handling +~~~~~~~~~~~~~~~~~~~~~~~ + +Simple updater +^^^^^^^^^^^^^^ + +For the simple updater the server only needs to deliver the binary file for update. + +Advanced updater +^^^^^^^^^^^^^^^^ + +For advanced update management a script (such as a PHP script) can run on the server side. It will receive the following headers which it may use to choose a specific firmware file to serve: + +:: + [User-Agent] => Pico-HTTP-Update + [x-Pico-STA-MAC] => 18:FE:AA:AA:AA:AA + [x-Pico-AP-MAC] => 1A:FE:AA:AA:AA:AA + [x-Pico-Version] => DOOR-7-g14f53a19 + [x-Pico-Mode] => sketch + + Stream Interface ---------------- @@ -233,7 +353,7 @@ A firmware file is uploaded via any method (Ethernet, WiFi, serial ZModem, etc.) The ROM layout consists of: -... code: +.. code:: cpp [boot2.S] [OTA Bootloader] [0-pad] [OTA partition table] [Main sketch] [LittleFS filesystem] [EEPROM] diff --git a/docs/platformio.rst b/docs/platformio.rst index f87b059eb..65924792c 100644 --- a/docs/platformio.rst +++ b/docs/platformio.rst @@ -23,6 +23,46 @@ Especially useful is the `Getting started with VSCode + PlatformIO Computer Configuration > Administrative Templates > System > Filesystem. + +3. Double click Enable NTFS/Win32 long paths and close the dialog. + + .. image:: images/longpath.png + + +Step 3: Reboot the computer +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Once the two prior stages are complete, please do a full reboot or power cycle so that the new settings will take effect. + + Current state of development ---------------------------- @@ -234,6 +274,17 @@ The lwIP stack can be configured to support only IPv4 (default) or additionally to the ``platformio.ini``. +Bluetooth Stack +--------------- + +The Bluetooth Classic (BTC) and Bluetooth Low Energy (BLE) stack can be activated by adding + +.. code:: ini + + ; BTC and BLE + build_flags = -DPIO_FRAMEWORK_ARDUINO_ENABLE_BLUETOOTH + +to the ``platformio.ini``. Selecting a different core version ---------------------------------- @@ -290,10 +341,15 @@ To specify the debugging adapter, use ``debug_tool`` (`documentation `_) and is then connected to the target Raspberry Pi Pico board (see `documentation `_ chapter "Picoprobe Wiring"). Remember that on Windows, you have to use `Zadig `_ to also load "WinUSB" drivers for the "Picoprobe (Interface 2)" device so that OpenOCD can speak to it. +Especially the PicoProbe method is convenient when you have two Raspberry Pi Pico boards. One of them can be flashed with the PicoProbe firmware (`documentation `__) and is then connected to the target Raspberry Pi Pico board (see `documentation `__ chapter "Picoprobe Wiring"). Remember that on Windows, you have to use `Zadig `_ to also load "WinUSB" drivers for the "Picoprobe (Interface 2)" device so that OpenOCD can speak to it. + +.. note:: + Newer PicoProbe firmware versions have dropped the proprietary "PicoProbe" USB communication protocol and emulate a **CMSIS-DAP** instead. Meaning, you have to use ``debug_tool = cmsis-dap`` for these newer firmwares, such as those obtained from `raspberrypi/picoprobe `__ With that set up, debugging can be started via the left debugging sidebar and works nicely: Setup breakpoints, inspect the value of variables in the code, step through the code line by line. When a breakpoint is hit or execution is halted, you can even see the execution state both Cortex-M0+ cores of the RP2040. @@ -301,6 +357,30 @@ With that set up, debugging can be started via the left debugging sidebar and wo For further information on customizing debug options, like the initial breakpoint or debugging / SWD speed, consult `the documentation `_. +.. note:: + For the BlackMagicProbe debugging probe (as can be e.g., created by simply flashing a STM32F103C8 "Bluepill" board), you currently have to use the branch ``fix/rp2040-flash-reliability`` (or at least commit ``1d001bc``) **and** use the `official ARM provided toolchain `_. + + You can obtain precompiled binaries from `here `__. A flashing guide is available `here `__. You then have to configure the target serial port ("GDB port") in your project per `documentation `__. + +.. note:: + For the pico-debug (`download `__) debugging way, *which needs to no additional debug probe*, add this snippet to your ``platformio.ini`` and follow the given procedure: + + .. code:: ini + + upload_protocol = pico-debug + debug_tool = pico-debug + build_flags = -DPIO_FRAMEWORK_ARDUINO_NO_USB + + 1. Build your firmware normally + 2. Plug in the Pico in BOOTSEL mode + 3. Drag and drop your ``.pio/build//firmware.uf2`` onto the boot drive + 4. Unplug and replug your Pico back into BOOTSEL mode for the second time + 5. Drag and drop the downloaded ``pico-debug-gimmecache.uf2`` file onto the boot drive + 6. A CMSIS-DAP device should now appear on your computer + 7. Start debugging via the debug sidebar as normal + + Note the restrictions: The second core cannot be used, the USB port cannot be used (no USB serial, only UART serial), 16KB less RAM is available. + Filesystem Uploading -------------------- @@ -315,3 +395,7 @@ The files you want to upload should be placed in a folder called ``data`` inside The task "Build Filesystem Image" will take all files in the data directory and create a ``littlefs.bin`` file from it using the ``mklittlefs`` tool. The task "Upload Filesystem Image" will upload the filesystem image to the Pico via the specified ``upload_protocol``. + +.. note:: + Set the space available for the filesystem in the ``platformio.ini`` using e.g., ``board_build.filesystem_size = 0.5m``, or filesystem + creation will fail! \ No newline at end of file diff --git a/docs/pwm.rst b/docs/pwm.rst new file mode 100644 index 000000000..b272ee7cb --- /dev/null +++ b/docs/pwm.rst @@ -0,0 +1,97 @@ +PWM Audio Library +================= + +Relatively good quality analog audio out can be generated by using the +RP2040 onboard PWM hardware. It can drive an amplifier for speaker output, +or be decoupled using a capacitor to drive a headphone-level signal. Mono +and stereo signals can be generated. + +All samples are sent to the ``PWMAudio`` library as **signed 16 bits per sample**. +Due to frequency limitations of the PWM hardware, at higher bit rates +these 16-bits will automatically be reduced to the maximum the hardware +can handle. + +Multiple ``PWMAudio`` devices are supported, depending on availability of +DMA channels. + +The interface for the ``PWMAudio`` device is very similar to the ``I2S`` +device, and most code can be ported simply by instantiating a ``PWMAudio`` +object in lieu of an ``I2S`` object. + +PWM Class API +------------- + +PWMAudio(pin) +~~~~~~~~~~~~~ +Creates a mono PWM output port. Any pin can be used, but no ``analogWrite`` +calls are allowed to any other pins using that pin's PWM slice hardware. +See the RP2040 datasheet for more details about PWM slices. + +PWMAudio(pin, true) +~~~~~~~~~~~~~~~~~~~ +Creates a stereo PWM output port. Only even pins (left signal) can be used, the next odd +pin will automatically be assigned to the right channel (i.e. ``PWMAudio pwm(0, true);`` +will make GP0 as the left channel, GP1 as the right channel). The same restriction as +in mono mode applies. + +bool setBuffers(size_t buffers, size_t bufferWords) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Set the number of DMA buffers and their size in 32-bit words. +Call before ``PWMAudio::begin()``. + +When running at high sample rates, it is recommended to increase the +``bufferWords`` to 32 or higher (i.e. ``pwm.setBuffers(4, 32);`` ). + +bool setPin(pin_size_t pin) +~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Adjusts the pin to connect to the PWM audio output. Only legal before +``PWMAudio::begin()``. + +bool setStereo(bool stereo) +~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Adjusts the mono/stereo setting of the PWM audio output. Only legal before +``PWMAudio::begin()``. + +bool setFrequency(long sampleRate) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Sets the sample frequency, but does not start the PWM device (however if the +device was already running, it will wontinue to run at the new frequency). + +bool begin()/begin(long sampleRate) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Start the PWM Audio device up with the given sample rate, or with the value set +using the prior ``setFrequency`` call. + +void end() +~~~~~~~~~~ +Stops the PWMAudio device. + +void flush() +~~~~~~~~~~~~ +Waits until all the PWM Audio buffers have been output. + +size_t write(int16_t sample, bool sync = true) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Writes a single 16-bit sample to the buffer. It is up to the user to keep track +of left/right channels when in stereo mode. In mono mode, one sample is written +per timestep while in stereo mode two ``write()`` calls are required. + +This call will block (wait) until space is available to actually write +the data if ``sync`` is not specified or set to ``true``. + +size_t write(const uint8_t \*buffer, size_t size) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Transfers number of bytes from an application buffer to the PWM Audio output buffer. +Be aware that ``size`` is in *bytes** and not samples. Size must be a multiple +of **4 bytes**. Will not block, so check the return value to find out how +many bytes were actually written. + +int availableForWrite() +~~~~~~~~~~~~~~~~~~~~~~~ +Returns the number of samples that can be written without potentially blocking. + +void onTransmit(void (\*fn)(void)) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Sets a callback to be called when a PWM Audio DMA buffer is fully transmitted. +Will be in an interrupt context so the specified function must operate +quickly and not use blocking calls like delay() or write to the PWM Audio. diff --git a/docs/rp2040.rst b/docs/rp2040.rst index 5d39dc187..97a302ef2 100644 --- a/docs/rp2040.rst +++ b/docs/rp2040.rst @@ -13,6 +13,10 @@ Returns the current frequency of the core clock. This is read at runtime, versus the constant ``F_CPU`` macro that is also available. This is useful in cases where your code changes the core clock (i.e. low power modes, etc.) +int rp2040.cpuid() +~~~~~~~~~~~~~~~~~~ +Returns the current core ID (0 or 1) of the executing task. + uint32_t rp2040.getCycleCount() ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Returns a 32-bit cycle count from then the core started running. Because it @@ -33,10 +37,27 @@ values returned may not meet the most stringent random tests. **If your application needs absolute bulletproof random numbers, consider using dedicated external hardware.** -void reboot() -~~~~~~~~~~~~~ +void rp2040.reboot() +~~~~~~~~~~~~~~~~~~~~ Forces a hardware reboot of the Pico. +Hardware Watchdog +----------------- + +void rp2040.wdt_begin(uint32_t delay_ms) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Enables the hardware watchdog timer with a delay value of delay_ms +milliseconds. Note that on the RP2040, once this function has called, the +hardware watchdog can _not_ be disabled. + +The maximum ``delay_ms`` allowed in this call is ``8300``, corresponding +to 8.3 seconds. Any higher values will be truncated by the hardware. + +void rp2040.wdt_reset() +~~~~~~~~~~~~~~~~~~~~~~~ +Reloads the watchdog's counter with the amount of time set by wdt_begin. + + Memory Information ------------------ @@ -47,8 +68,8 @@ that because there is some overhead, and there may be heap fragmentation, this number is an *upper bound* and you generally will only be able to allocate less than this returned number. -int rp2040.getUsedHeap -~~~~~~~~~~~~~~~~~~~~~~ +int rp2040.getUsedHeap() +~~~~~~~~~~~~~~~~~~~~~~~~ Returns the number of bytes allocated out of the heap. int rp2040.getTotalHeap() @@ -56,3 +77,21 @@ int rp2040.getTotalHeap() Returns the total heap that was available to this program at compile time (i.e. the Pico RAM size minus things like the ``.data`` and ``.bss`` sections and other overhead). + +Hardware Identification +----------------------- + +bool isPicoW() +~~~~~~~~~~~~~~ +Returns the core's best guess if this code is running on a Raspberry Pi Pico W. +This would let you, possibly, use the same UF2 for Pico and PicoW by simply not +doing any WiFi calls. + +Bootloader +---------- + +void rp2040.enableDoubleResetBootloader() +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Add a call anywhere in the sketch to ``rp2040.enableDoubleResetBootloader()`` and +the core will check for a double-tap on reset, and if found will start the USB +bootloader. diff --git a/docs/singlefile.rst b/docs/singlefile.rst new file mode 100644 index 000000000..75c2498d3 --- /dev/null +++ b/docs/singlefile.rst @@ -0,0 +1,82 @@ +SingleFileDrive +=============== + +USB drive mode is supported through the ``SingleFileDrive`` class which +allows the Pico to emulate a FAT-formatted USB stick while preserving the +onboard LittleFS filesystem. A single file can be exported this way without +needing to use FAT as the onboard filesystem (FAT is not appropriate for +flash-based devices without complicated wear leveling because of the update +frequency of the FAT tables). + +This emulation is very simple and only allows for the reading of the single +file, and deleting it. + +Callbacks, Interrupt Safety, and File Operations +------------------------------------------------ + +The ``SingleFileDrive`` library allows your application to get a callback +when a PC attempts to mount or unmount the Pico as a drive. Your app can +also get a callback if the user attempts to delete the file (but your +sketch does not actually need to delete the file, it's up to you). + +Note that when the USB drive is mounted by a PC it is not safe for your +main sketch to make changes to the LittleFS filesystem or the file being +exported. So, normally, your ``onPlug`` callback will set a flag letting +your application know not to touch the filesystem, with the ``onUnplug`` +callback clearing this flag. + +Also, because the USB port can be connected at any time, it is important +to disable interrupts using ``noInterrupts()`` before writing to a file +you will be exporting (and restoring them with ``interrupts()`` afterwards). +It is also important to ``close()`` the file after each update, or the +on-flash version the ``SingleFileDrive`` will attempt to export may not be +up to date causing issues later on. + +See the included ``DataLoggerUSB`` sketch for an example of working with +these limitations. + +Using SingleFileDrive +--------------------- + +Implementing the drive requires including the header file, starting LittleFS, +defining your callbacks, and telling the library what file to export. No +polling or other calls are required outside of your ``setup()``. (Note that +the callback routines allow for a parameter to be passed to them, but in most +cases this can be safely ignored.) + +.. code:: cpp + + #include + #include + + void myPlugCB(uint32_t data) { + // Tell my app not to write to flash, we're connected + } + + void myUnplugCB(uint32_t data) { + // I can start writing to flash again + } + + void myDeleteDB(uint32_t data) { + // Maybe LittleFS.remove("myfile.txt")? or do nothing + } + + void setup() { + LittleFS.begin(); + singleFileDrive.onPlug(myPlugCB); + singleFileDrive.onUnplug(myUnplugCB); + singleFileDrive.onDelete(myDeleteCB); + singleFileDrive.begin("littlefsfile.csv", "Data Recorder.csv"); + // ... rest of setup ... + } + + void loop() { + // Take some measurements, delay, etc. + if (okay-to-write) { + noInterrupts(); + File f = LittleFS.open("littlefsfile.csv", "a"); + f.printf("%d,%d,%d\n", data1, data2, data3); + f.close(); + interrupts(); + } + } diff --git a/docs/wifi.rst b/docs/wifi.rst index 07b6880b1..44b470408 100644 --- a/docs/wifi.rst +++ b/docs/wifi.rst @@ -1,7 +1,7 @@ WiFi (Raspberry Pi Pico W) Support ================================== -WiFi is supported on the Raspberry Pi Pico W by selecting the "Raspbery Pi Pico W" board in the Boards Manager. It is generally compatible with the `Arduino WiFi library `__ and the `ESP8266 Arduino WiFi library `__. +WiFi is supported on the Raspberry Pi Pico W by selecting the "Raspberry Pi Pico W" board in the Boards Manager. It is generally compatible with the `Arduino WiFi library `__ and the `ESP8266 Arduino WiFi library `__. Enable WiFi support by selecting the `Raspberry Pi Pico W` board in the IDE and adding ``#include `` in your sketch. @@ -40,8 +40,6 @@ Please note that WiFi on the Pico W is a work-in-progress and there are some imp * Combined STA/AP mode is not supported - * Certain WiFi status values (RSSI, BSSID, etc.) are not available. - * Multicore is supported, but only one core may run ``WiFi`` code. * FreeRTOS is not yet supported due to the requirement for a very different LWIP implementation. PRs always appreciated! diff --git a/include/btstack_config.h b/include/btstack_config.h new file mode 100644 index 000000000..3d1ee3576 --- /dev/null +++ b/include/btstack_config.h @@ -0,0 +1,74 @@ +#pragma once + +// BTstack features that can be enabled +#define ENABLE_LOG_INFO +#define ENABLE_LOG_ERROR +#define ENABLE_PRINTF_HEXDUMP +#define ENABLE_SCO_OVER_HCI + +#ifdef ENABLE_CLASSIC +#define ENABLE_L2CAP_ENHANCED_RETRANSMISSION_MODE +#endif + +#ifdef ENABLE_BLE +#define ENABLE_L2CAP_LE_CREDIT_BASED_FLOW_CONTROL_MODE +#define ENABLE_LE_PERIPHERAL +#define ENABLE_LE_CENTRAL +#endif + +// BTstack configuration. buffers, sizes, ... +#define HCI_OUTGOING_PRE_BUFFER_SIZE 4 +#define HCI_ACL_PAYLOAD_SIZE (1691 + 4) +#define HCI_ACL_CHUNK_SIZE_ALIGNMENT 4 +#define MAX_NR_AVDTP_CONNECTIONS 1 +#define MAX_NR_AVDTP_STREAM_ENDPOINTS 1 +#define MAX_NR_AVRCP_CONNECTIONS 2 +#define MAX_NR_BNEP_CHANNELS 1 +#define MAX_NR_BNEP_SERVICES 1 +#define MAX_NR_BTSTACK_LINK_KEY_DB_MEMORY_ENTRIES 2 +#define MAX_NR_GATT_CLIENTS 1 +#define MAX_NR_HCI_CONNECTIONS 2 +#define MAX_NR_HID_HOST_CONNECTIONS 1 +#define MAX_NR_HIDS_CLIENTS 1 +#define MAX_NR_HFP_CONNECTIONS 1 +#define MAX_NR_L2CAP_CHANNELS 4 +#define MAX_NR_L2CAP_SERVICES 3 +#define MAX_NR_RFCOMM_CHANNELS 1 +#define MAX_NR_RFCOMM_MULTIPLEXERS 1 +#define MAX_NR_RFCOMM_SERVICES 1 +#define MAX_NR_SERVICE_RECORD_ITEMS 4 +#define MAX_NR_SM_LOOKUP_ENTRIES 3 +#define MAX_NR_WHITELIST_ENTRIES 16 +#define MAX_NR_LE_DEVICE_DB_ENTRIES 16 + +// Limit number of ACL/SCO Buffer to use by stack to avoid cyw43 shared bus overrun +#define MAX_NR_CONTROLLER_ACL_BUFFERS 3 +#define MAX_NR_CONTROLLER_SCO_PACKETS 3 + +// Enable and configure HCI Controller to Host Flow Control to avoid cyw43 shared bus overrun +#define ENABLE_HCI_CONTROLLER_TO_HOST_FLOW_CONTROL +#define HCI_HOST_ACL_PACKET_LEN 1024 +#define HCI_HOST_ACL_PACKET_NUM 3 +#define HCI_HOST_SCO_PACKET_LEN 120 +#define HCI_HOST_SCO_PACKET_NUM 3 + +// Link Key DB and LE Device DB using TLV on top of Flash Sector interface +#define NVM_NUM_DEVICE_DB_ENTRIES 16 +#define NVM_NUM_LINK_KEYS 16 + +// We don't give btstack a malloc, so use a fixed-size ATT DB. +#define MAX_ATT_DB_SIZE 512 + +// BTstack HAL configuration +#define HAVE_EMBEDDED_TIME_MS + +// map btstack_assert onto Pico SDK assert() +#define HAVE_ASSERT + +// Some USB dongles take longer to respond to HCI reset (e.g. BCM20702A). +#define HCI_RESET_RESEND_TIMEOUT_MS 1000 + +#define ENABLE_SOFTWARE_AES128 +#define ENABLE_MICRO_ECC_FOR_LE_SECURE_CONNECTIONS + +#undef HAVE_BTSTACK_STDIN diff --git a/include/lwipopts.h b/include/lwipopts.h index 697b9548c..0dc0ed683 100644 --- a/include/lwipopts.h +++ b/include/lwipopts.h @@ -13,6 +13,9 @@ extern void interrupts(); #define SYS_ARCH_PROTECT(lev) noInterrupts #define SYS_ARCH_UNPROTECT(lev) interrupts +extern unsigned long get_rand_32(void); +#define LWIP_RAND() get_rand_32() + // Common settings used in most of the pico_w examples // (see https://www.nongnu.org/lwip/2_1_x/group__lwip__opts.html for details) @@ -25,7 +28,7 @@ extern void interrupts(); #define MEMP_NUM_TCP_SEG 32 #define MEMP_NUM_ARP_QUEUE 10 #define PBUF_POOL_SIZE 24 -#define LWIP_ARP 1 +#define LWIP_ARP 2 #define LWIP_ETHERNET 1 #define LWIP_ICMP 1 #define LWIP_RAW 1 @@ -53,6 +56,9 @@ extern void interrupts(); #define DHCP_DOES_ARP_CHECK 0 #define LWIP_DHCP_DOES_ACD_CHECK 0 +// See #1285 +#define MEMP_NUM_UDP_PCB 6 + #if LWIP_IPV6 #define LWIP_IPV6_DHCP6 1 #endif diff --git a/include/pico_base/pico/version.h b/include/pico_base/pico/version.h index 2c584d5ef..c7a1be0c5 100644 --- a/include/pico_base/pico/version.h +++ b/include/pico_base/pico/version.h @@ -12,8 +12,8 @@ #define _PICO_VERSION_H #define PICO_SDK_VERSION_MAJOR 1 -#define PICO_SDK_VERSION_MINOR 4 +#define PICO_SDK_VERSION_MINOR 5 #define PICO_SDK_VERSION_REVISION 0 -#define PICO_SDK_VERSION_STRING "1.4.0" +#define PICO_SDK_VERSION_STRING "1.5.0" #endif diff --git a/include/tusb_config.h b/include/tusb_config.h index 5e3b624e9..91c9c1a7a 100644 --- a/include/tusb_config.h +++ b/include/tusb_config.h @@ -72,15 +72,14 @@ //------------- CLASS -------------// #define CFG_TUD_HID (2) #define CFG_TUD_CDC (1) -#define CFG_TUD_MSC (0) +#define CFG_TUD_MSC (1) #define CFG_TUD_MIDI (0) #define CFG_TUD_VENDOR (0) #define CFG_TUD_CDC_RX_BUFSIZE (256) #define CFG_TUD_CDC_TX_BUFSIZE (256) -#define CFG_TUD_MIDI_RX_BUFSIZE (64) -#define CFG_TUD_MIDI_TX_BUFSIZE (64) +#define CFG_TUD_MSC_EP_BUFSIZE (64) // HID buffer size Should be sufficient to hold ID (if any) + Data #define CFG_TUD_HID_EP_BUFSIZE (64) diff --git a/keywords.txt b/keywords.txt index d61747078..98b4fa6e0 100644 --- a/keywords.txt +++ b/keywords.txt @@ -2,6 +2,8 @@ # Syntax Coloring Map ####################################### +Arduino KEYWORD3 RESERVED_WORD + ####################################### # Datatypes (KEYWORD1) ####################################### @@ -30,15 +32,35 @@ usToPIOCycles KEYWORD2 f_cpu KEYWORD2 getCycleCount KEYWORD2 getCycleCount64 KEYWORD2 + +getFreeHeap KEYWORD2 +getUsedHeap KEYWORD2 +getTotalHeap KEYWORD2 + idleOtherCore KEYWORD2 resumeOtherCore KEYWORD2 +restartCore1 KEYWORD2 +reboot KEYWORD2 +restart KEYWORD2 + +isPicoW KEYWORD2 + +getChipID KEYWORD2 + +hwrand32 KEYWORD2 + PIOProgram KEYWORD2 prepare KEYWORD2 SerialPIO KEYWORD2 setFIFOSize KEYWORD2 setPollingMode KEYWORD2 +digitalWriteFast KEYWORD2 +digitalReadFast KEYWORD2 + +enableDoubleResetBootloader KEYWORD2 + OUTPUT_2MA LITERAL1 OUTPUT_4MA LITERAL1 OUTPUT_8MA LITERAL1 diff --git a/lib/libpico-ipv6.a b/lib/libpico-ipv6.a deleted file mode 100644 index b425d48a7..000000000 Binary files a/lib/libpico-ipv6.a and /dev/null differ diff --git a/lib/libpico.a b/lib/libpico.a index 57a0a8f58..e1313c113 100644 Binary files a/lib/libpico.a and b/lib/libpico.a differ diff --git a/lib/libpicow-ipv6-btc-ble.a b/lib/libpicow-ipv6-btc-ble.a new file mode 100644 index 000000000..dc9143ad9 Binary files /dev/null and b/lib/libpicow-ipv6-btc-ble.a differ diff --git a/lib/libpicow-ipv6-nobtc-noble.a b/lib/libpicow-ipv6-nobtc-noble.a new file mode 100644 index 000000000..8aaff6ee4 Binary files /dev/null and b/lib/libpicow-ipv6-nobtc-noble.a differ diff --git a/lib/libpicow-noipv6-btc-ble.a b/lib/libpicow-noipv6-btc-ble.a new file mode 100644 index 000000000..33aa58d7b Binary files /dev/null and b/lib/libpicow-noipv6-btc-ble.a differ diff --git a/lib/libpicow-noipv6-nobtc-noble.a b/lib/libpicow-noipv6-nobtc-noble.a new file mode 100644 index 000000000..430015f6f Binary files /dev/null and b/lib/libpicow-noipv6-nobtc-noble.a differ diff --git a/lib/memmap_default.ld b/lib/memmap_default.ld index 90dde3ce6..127abba36 100644 --- a/lib/memmap_default.ld +++ b/lib/memmap_default.ld @@ -132,15 +132,6 @@ SECTIONS } > FLASH __exidx_end = .; - /* Machine inspectable binary information */ - . = ALIGN(4); - __binary_info_start = .; - .binary_info : - { - KEEP(*(.binary_info.keep.*)) - *(.binary_info.*) - } > FLASH - __binary_info_end = .; . = ALIGN(4); /* End of .text-like segments */ @@ -200,11 +191,6 @@ SECTIONS __data_end__ = .; } > RAM AT> FLASH - .uninitialized_data (COPY): { - . = ALIGN(4); - *(.uninitialized_data*) - } > RAM - /* Start and end symbols must be word-aligned */ .scratch_x : { __scratch_x_start__ = .; @@ -222,7 +208,7 @@ SECTIONS } > SCRATCH_Y AT > FLASH __scratch_y_source__ = LOADADDR(.scratch_y); - .bss : { + .bss : { . = ALIGN(4); __bss_start__ = .; *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.bss*))) @@ -231,6 +217,15 @@ SECTIONS __bss_end__ = .; } > RAM + /* At most one of the following two will be engaged, depending on the SDK version */ + .uninitialized_ram MAX(0x20003000, .) (NOLOAD) : { + *(.uninitialized_ram*) + } > RAM + + .uninitialized_data MAX(0x20003000, .) (NOLOAD) : { + *(.uninitialized_data*) + } > RAM + .heap (COPY): { __end__ = .; diff --git a/lib/ota.o b/lib/ota.o index 0b330e25a..02c16a4bd 100644 Binary files a/lib/ota.o and b/lib/ota.o differ diff --git a/lib/picodebug.tcl b/lib/picodebug.tcl new file mode 100644 index 000000000..91334d899 --- /dev/null +++ b/lib/picodebug.tcl @@ -0,0 +1 @@ +source [find board/pico-debug.cfg] diff --git a/lib/picoprobe.tcl b/lib/picoprobe.tcl new file mode 100644 index 000000000..df4c20c5e --- /dev/null +++ b/lib/picoprobe.tcl @@ -0,0 +1,2 @@ +source [find interface/picoprobe.cfg] +source [find target/rp2040.cfg] diff --git a/lib/picoprobe_cmsis_dap.tcl b/lib/picoprobe_cmsis_dap.tcl new file mode 100644 index 000000000..3364c595e --- /dev/null +++ b/lib/picoprobe_cmsis_dap.tcl @@ -0,0 +1,3 @@ +source [find interface/cmsis-dap.cfg] +adapter speed 5000 +source [find target/rp2040.cfg] diff --git a/lib/platform_inc.txt b/lib/platform_inc.txt index c4863439a..c0f3d8f87 100644 --- a/lib/platform_inc.txt +++ b/lib/platform_inc.txt @@ -9,6 +9,7 @@ -iwithprefixbefore/pico-sdk/src/common/pico_stdlib/include -iwithprefixbefore/pico-sdk/src/common/pico_sync/include -iwithprefixbefore/pico-sdk/src/common/pico_time/include +-iwithprefixbefore/pico-sdk/src/common/pico_usb_reset_interface/include -iwithprefixbefore/pico-sdk/src/common/pico_util/include -iwithprefixbefore/pico-sdk/src/rp2040/hardware_regs/include -iwithprefixbefore/pico-sdk/src/rp2040/hardware_structs/include @@ -39,8 +40,11 @@ -iwithprefixbefore/pico-sdk/src/rp2_common/hardware_vreg/include -iwithprefixbefore/pico-sdk/src/rp2_common/hardware_watchdog/include -iwithprefixbefore/pico-sdk/src/rp2_common/hardware_xosc/include +-iwithprefixbefore/pico-sdk/src/rp2_common/pico_async_context/include -iwithprefixbefore/pico-sdk/src/rp2_common/pico_bootrom/include +-iwithprefixbefore/pico-sdk/src/rp2_common/pico_btstack/include -iwithprefixbefore/pico-sdk/src/rp2_common/pico_cyw43_arch/include +-iwithprefixbefore/pico-sdk/src/rp2_common/pico_cyw43_driver/include -iwithprefixbefore/pico-sdk/src/rp2_common/pico_double/include -iwithprefixbefore/pico-sdk/src/rp2_common/pico_float/include -iwithprefixbefore/pico-sdk/src/rp2_common/pico_int64_ops/include @@ -49,8 +53,11 @@ -iwithprefixbefore/pico-sdk/src/rp2_common/pico_platform/include -iwithprefixbefore/pico-sdk/src/rp2_common/pico_printf/include -iwithprefixbefore/pico-sdk/src/rp2_common/pico_runtime/include +-iwithprefixbefore/pico-sdk/src/rp2_common/pico_rand/include -iwithprefixbefore/pico-sdk/src/rp2_common/pico_stdio/include -iwithprefixbefore/pico-sdk/src/rp2_common/pico_stdio_uart/include -iwithprefixbefore/pico-sdk/src/rp2_common/pico_unique_id/include -iwithprefixbefore/pico-sdk/lib/cyw43-driver/src -iwithprefixbefore/pico-sdk/lib/lwip/src/include +-iwithprefixbefore/pico-sdk/lib/btstack/src +-iwithprefixbefore/pico-sdk/lib/btstack/platform/embedded diff --git a/lib/platform_wrap.txt b/lib/platform_wrap.txt index 29542dd96..703bc68cc 100644 --- a/lib/platform_wrap.txt +++ b/lib/platform_wrap.txt @@ -144,4 +144,70 @@ -Wl,--wrap=tanhf -Wl,--wrap=trunc -Wl,--wrap=truncf + -Wl,--wrap=__getreent + +-Wl,--wrap=malloc +-Wl,--wrap=calloc +-Wl,--wrap=realloc +-Wl,--wrap=free + +-Wl,--wrap=pbuf_header +-Wl,--wrap=pbuf_free +-Wl,--wrap=pbuf_alloc +-Wl,--wrap=pbuf_take +-Wl,--wrap=pbuf_copy_partial +-Wl,--wrap=pbuf_ref +-Wl,--wrap=pbuf_get_at +-Wl,--wrap=pbuf_get_contiguous +-Wl,--wrap=pbuf_cat + +-Wl,--wrap=tcp_arg +-Wl,--wrap=tcp_new +-Wl,--wrap=tcp_listen +-Wl,--wrap=tcp_listen_with_backlog +-Wl,--wrap=tcp_accept +-Wl,--wrap=tcp_connect +-Wl,--wrap=tcp_write +-Wl,--wrap=tcp_sent +-Wl,--wrap=tcp_recv +-Wl,--wrap=tcp_recved +-Wl,--wrap=tcp_poll +-Wl,--wrap=tcp_close +-Wl,--wrap=tcp_abort +-Wl,--wrap=tcp_err +-Wl,--wrap=tcp_output +-Wl,--wrap=tcp_setprio +-Wl,--wrap=tcp_backlog_delayed +-Wl,--wrap=tcp_backlog_accepted + +-Wl,--wrap=udp_new +-Wl,--wrap=udp_remove +-Wl,--wrap=udp_bind +-Wl,--wrap=udp_connect +-Wl,--wrap=udp_disconnect +-Wl,--wrap=udp_send +-Wl,--wrap=udp_recv +-Wl,--wrap=udp_sendto_if + +-Wl,--wrap=sys_check_timeouts + +-Wl,--wrap=dns_gethostbyname +-Wl,--wrap=dns_gethostbyname_addrtype + +-Wl,--wrap=raw_new +-Wl,--wrap=raw_recv +-Wl,--wrap=raw_bind +-Wl,--wrap=raw_sendto +-Wl,--wrap=raw_remove + +-Wl,--wrap=cyw43_cb_process_ethernet +-Wl,--wrap=cyw43_cb_tcpip_set_link_up +-Wl,--wrap=cyw43_cb_tcpip_set_link_down +-Wl,--wrap=cyw43_tcpip_link_status +-Wl,--wrap=cyw43_cb_tcpip_init +-Wl,--wrap=cyw43_cb_tcpip_deinit + +-Wl,--wrap=get_rand_64 +-Wl,--wrap=get_rand_32 +-Wl,--wrap=sleep_until diff --git a/libraries/ADCInput/examples/AnalogMicrophone/AnalogMicrophone.ino b/libraries/ADCInput/examples/AnalogMicrophone/AnalogMicrophone.ino new file mode 100644 index 000000000..f7d8b096f --- /dev/null +++ b/libraries/ADCInput/examples/AnalogMicrophone/AnalogMicrophone.ino @@ -0,0 +1,30 @@ +/* + Mono analog microphone example using electret mike on A0 + Run using the Arduino Serial Plotter to see waveform. + Released to the Public Domain by Earle F. Philhower, III + + Wire the mike's VCC to 3.3V on the Pico, connect the mike's + GND to a convenient Pico GND, and then connect mike OUT to A0 +*/ + +#include + +ADCInput mike(A0); +// For stereo/dual mikes, could use this line instead +// ADCInput(A0, A1); + +void setup() { + Serial.begin(115200); + + mike.begin(8000); + + while (1) { + Serial.printf("%d\n", mike.read()); + // For stereo/dual mikes, use this line instead + // Serial.printf("%d %d\n", mike.read(), mike.read()); + } +} + +void loop() { + /* Nothing here */ +} diff --git a/libraries/ADCInput/keywords.txt b/libraries/ADCInput/keywords.txt new file mode 100644 index 000000000..7cfcdbf76 --- /dev/null +++ b/libraries/ADCInput/keywords.txt @@ -0,0 +1,25 @@ +####################################### +# Syntax Coloring Map +####################################### + +####################################### +# Datatypes (KEYWORD1) +####################################### + +ADCInput KEYWORD1 + +####################################### +# Methods and Functions (KEYWORD2) +####################################### +begin KEYWORD2 +end KEYWORD2 + +setPins KEYWORD2 +setFrequency KEYWORD2 +setBuffers KEYWORD2 + +onReceive KEYWORD2 + +####################################### +# Constants (LITERAL1) +####################################### diff --git a/libraries/ADCInput/library.properties b/libraries/ADCInput/library.properties new file mode 100644 index 000000000..6ced00f00 --- /dev/null +++ b/libraries/ADCInput/library.properties @@ -0,0 +1,10 @@ +name=ADCInput +version=1.0 +author=Earle F. Philhower, III +maintainer=Earle F. Philhower, III +sentence=Records ADC values (i.e. microphone, sensors) and presents an I2S-like callback/immediate read interface +paragraph=Records ADC values (i.e. microphone, sensors) and presents an I2S-like callback/immediate read interface +category=Communication +url=http://github.com/earlephilhower/arduino-pico +architectures=rp2040 +dot_a_linkage=true diff --git a/libraries/ADCInput/src/ADCInput.cpp b/libraries/ADCInput/src/ADCInput.cpp new file mode 100644 index 000000000..4656614ee --- /dev/null +++ b/libraries/ADCInput/src/ADCInput.cpp @@ -0,0 +1,172 @@ +/* + ADCInput + Records ADC values (i.e. microphone, sensors) and presents an I2S-like + callback/immediate read interface + + Copyright (c) 2023 Earle F. Philhower, III + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include +#include "ADCInput.h" +#include + +ADCInput::ADCInput(pin_size_t p0, pin_size_t p1, pin_size_t p2, pin_size_t p3) { + _running = false; + setPins(p0, p1, p2, p3); + _freq = 48000; + _arb = nullptr; + _cb = nullptr; + _buffers = 8; + _bufferWords = 0; +} + +ADCInput::~ADCInput() { + end(); +} + +bool ADCInput::setBuffers(size_t buffers, size_t bufferWords) { + if (_running || (buffers < 3) || (bufferWords < 8)) { + return false; + } + _buffers = buffers; + _bufferWords = bufferWords; + return true; +} + +int ADCInput::_mask(pin_size_t p) { + switch (p) { + case 26: return 1; + case 27: return 2; + case 28: return 4; + case 29: return 8; + default: return 0; + } +} + +bool ADCInput::setPins(pin_size_t pin0, pin_size_t pin1, pin_size_t pin2, pin_size_t pin3) { + if (_running) { + return false; + } + _pinMask = _mask(pin0) | _mask(pin1) | _mask(pin2) | _mask(pin3); + return true; +} + +bool ADCInput::setFrequency(int newFreq) { + _freq = newFreq * __builtin_popcount(_pinMask); // Want to sample all channels at given frequency + adc_set_clkdiv(48000000.0f / _freq - 1.0f); + return true; +} + +void ADCInput::onReceive(void(*fn)(void)) { + _cb = fn; + if (_running) { + _arb->setCallback(_cb); + } +} + +bool ADCInput::begin() { + _running = true; + + _isHolding = 0; + + if (!_bufferWords) { + _bufferWords = 16; + } + + // Set up the GPIOs to go to ADC + adc_init(); + int cnt = 0; + for (int mask = 1, pin = 26; pin <= 29; mask <<= 1, pin++) { + if (_pinMask & mask) { + if (!cnt) { + adc_select_input(pin - 26); + } + cnt++; + adc_gpio_init(pin); + } + } + adc_set_round_robin(_pinMask); + adc_fifo_setup(true, true, 1, false, false); + + setFrequency(_freq); + + _arb = new AudioBufferManager(_buffers, _bufferWords, 0, INPUT, DMA_SIZE_16); + _arb->begin(DREQ_ADC, (volatile void*)&adc_hw->fifo); + _arb->setCallback(_cb); + + adc_fifo_drain(); + + adc_run(true); + + return true; +} + +void ADCInput::end() { + if (_running) { + _running = false; + delete _arb; + _arb = nullptr; + } + adc_run(false); + adc_fifo_drain(); +} + +int ADCInput::available() { + if (!_running) { + return 0; + } else { + return _arb->available(); + } +} + +int ADCInput::read() { + if (!_running) { + return -1; + } + + if (_hasPeeked) { + _hasPeeked = false; + return _peekSaved; + } + + if (_isHolding <= 0) { + _arb->read(&_holdWord, true); + _isHolding = 32; + } + + int ret = _holdWord & 0x0fff; + _holdWord >>= 16; + _isHolding -= 16; + return ret; +} + +int ADCInput::peek() { + if (!_running) { + return -1; + } + if (!_hasPeeked) { + _peekSaved = read(); + _hasPeeked = true; + } + return _peekSaved; +} + +void ADCInput::flush() { + if (_running) { + _arb->flush(); + } +} diff --git a/libraries/ADCInput/src/ADCInput.h b/libraries/ADCInput/src/ADCInput.h new file mode 100644 index 000000000..3f34872a4 --- /dev/null +++ b/libraries/ADCInput/src/ADCInput.h @@ -0,0 +1,87 @@ +/* + ADCInput + Records ADC values (i.e. microphone, sensors) and presents an I2S-like + callback/immediate read interface + + Copyright (c) 2023 Earle F. Philhower, III + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#pragma once +#include +#include "AudioBufferManager.h" + +class ADCInput : public Stream { +public: + ADCInput(pin_size_t pin0, pin_size_t pin1 = 255, pin_size_t pin2 = 255, pin_size_t pin3 = 255); + virtual ~ADCInput(); + + bool setBuffers(size_t buffers, size_t bufferWords); + bool setFrequency(int newFreq); + bool setPins(pin_size_t pin0, pin_size_t pin1 = 255, pin_size_t pin2 = 255, pin_size_t pin3 = 255); + + bool begin(long sampleRate) { + setFrequency(sampleRate); + return begin(); + } + + bool begin(); + void end(); + + // from Stream + virtual int available() override; + virtual int read() override; + virtual int peek() override; + virtual void flush() override; + + // from Print, not supported + virtual size_t write(const uint8_t *buffer, size_t size) override { + (void) buffer; + (void) size; + return -1; + } + virtual size_t write(uint8_t x) override { + (void) x; + return -1; + } + virtual int availableForWrite() override { + return 0; + } + + // Note that these callback are called from **INTERRUPT CONTEXT** and hence + // should be in RAM, not FLASH, and should be quick to execute. + void onReceive(void(*)(void)); + +private: + uint32_t _pinMask; + + int _freq; + + size_t _buffers; + size_t _bufferWords; + + bool _running; + void (*_cb)(); + + bool _hasPeeked; + uint32_t _peekSaved; + uint32_t _holdWord = 0; + int _isHolding = 0; + + int _mask(pin_size_t pin); + + AudioBufferManager *_arb; +}; diff --git a/libraries/ArduinoOTA/src/ArduinoOTA.cpp b/libraries/ArduinoOTA/src/ArduinoOTA.cpp index e60f28eac..de462a586 100644 --- a/libraries/ArduinoOTA/src/ArduinoOTA.cpp +++ b/libraries/ArduinoOTA/src/ArduinoOTA.cpp @@ -1,3 +1,24 @@ +/* + Arduino OTA.cpp - Simple Arduino IDE OTA handler + Modified 2022 Earle F. Philhower, III. All rights reserved. + + Taken from the ESP8266 core libraries, (c) various authors. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + #include #include #include "ArduinoOTA.h" @@ -89,7 +110,7 @@ void ArduinoOTAClass::begin(bool useMDNS) { _useMDNS = useMDNS; if (!_hostname.length()) { - char tmp[15]; + char tmp[2 * PICO_UNIQUE_BOARD_ID_SIZE_BYTES + 6]; sprintf(tmp, "pico-%s", rp2040.getChipID()); _hostname = tmp; } @@ -243,6 +264,19 @@ void ArduinoOTAClass::_onRx() { void ArduinoOTAClass::_runUpdate() { IPAddress ota_ip = _ota_ip; + if (!LittleFS.begin()) { +#ifdef OTA_DEBUG + OTA_DEBUG.println("LittleFS Begin Error"); +#endif + _udp_ota->append("ERR: ", 5); + _udp_ota->append("No Filesystem", 13); + _udp_ota->send(ota_ip, _ota_udp_port); + delay(100); + _udp_ota->listen(IP_ADDR_ANY, _port); + _state = OTA_IDLE; + return; + } + if (!Update.begin(_size, _cmd)) { #ifdef OTA_DEBUG OTA_DEBUG.println("Update Begin Error"); @@ -261,15 +295,6 @@ void ArduinoOTAClass::_runUpdate() { _state = OTA_IDLE; return; } - if (!LittleFS.begin()) { - _udp_ota->append("ERR: ", 5); - _udp_ota->append("nofilesystem", 6); - _udp_ota->send(ota_ip, _ota_udp_port); - delay(100); - _udp_ota->listen(IP_ADDR_ANY, _port); - _state = OTA_IDLE; - return; - } _udp_ota->append("OK", 2); _udp_ota->send(ota_ip, _ota_udp_port); diff --git a/libraries/ArduinoOTA/src/ArduinoOTA.h b/libraries/ArduinoOTA/src/ArduinoOTA.h index c236b748a..5d3804f98 100644 --- a/libraries/ArduinoOTA/src/ArduinoOTA.h +++ b/libraries/ArduinoOTA/src/ArduinoOTA.h @@ -1,3 +1,24 @@ +/* + Arduino OTA.h - Simple Arduino IDE OTA handler + Modified 2022 Earle F. Philhower, III. All rights reserved. + + Taken from the ESP8266 core libraries, (c) various authors. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + #pragma once #include @@ -38,10 +59,10 @@ class ArduinoOTAClass { void setHostname(const char *hostname); String getHostname(); - //Sets the password that will be required for OTA. Default NULL + //Sets the password that will be required for OTA. Default nullptr void setPassword(const char *password); - //Sets the password as above but in the form MD5(password). Default NULL + //Sets the password as above but in the form MD5(password). Default nullptr void setPasswordHash(const char *password); //Sets if the device should be rebooted after successful update. Default true diff --git a/libraries/AudioBufferManager/library.properties b/libraries/AudioBufferManager/library.properties new file mode 100644 index 000000000..38219422a --- /dev/null +++ b/libraries/AudioBufferManager/library.properties @@ -0,0 +1,10 @@ +name=AudioBufferManager +version=1.0.0 +author=Earle F. Philhower, III +maintainer=Earle F. Philhower, III +sentence=Manages DMA buffers for audio output +paragraph=Manages DMA buffers for audio output +category=Device Control +url=https://github.com/earlephilhower/arduino-pico +architectures=rp2040 +dot_a_linkage=true diff --git a/libraries/AudioBufferManager/src/AudioBufferManager.cpp b/libraries/AudioBufferManager/src/AudioBufferManager.cpp new file mode 100644 index 000000000..2d51e4141 --- /dev/null +++ b/libraries/AudioBufferManager/src/AudioBufferManager.cpp @@ -0,0 +1,284 @@ +/* + AudioBufferManager for Raspnerry Pi Pico RP2040 + Implements a DMA controlled linked-list series of buffers + + Copyright (c) 2022 Earle F. Philhower, III + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include +#include "hardware/dma.h" +#include "hardware/irq.h" +#include "AudioBufferManager.h" + +static int __channelCount = 0; // # of channels left. When we hit 0, then remove our handler +static AudioBufferManager* __channelMap[12]; // Lets the IRQ handler figure out where to dispatch to + +AudioBufferManager::AudioBufferManager(size_t bufferCount, size_t bufferWords, int32_t silenceSample, PinMode direction, enum dma_channel_transfer_size dmaSize) { + _running = false; + + // Need at least 2 DMA buffers and 1 user or this isn't going to work at all + if (bufferCount < 3) { + bufferCount = 3; + } + + _bufferCount = bufferCount; + _wordsPerBuffer = bufferWords; + _isOutput = direction == OUTPUT; + _dmaSize = dmaSize; + _overunderflow = false; + _callback = nullptr; + _userOff = 0; + + // Create the silence buffer, fill with appropriate value + _silence = new AudioBuffer; + _silence->next = nullptr; + _silence->buff = new uint32_t[_wordsPerBuffer]; + for (uint32_t x = 0; x < _wordsPerBuffer; x++) { + _silence->buff[x] = silenceSample; + } + + // No filled buffers yet + _filled = nullptr; + + // Create all buffers on the empty chain + _empty = nullptr; + for (size_t i = 0; i < bufferCount; i++) { + auto ab = new AudioBuffer; + ab->buff = new uint32_t[_wordsPerBuffer]; + bzero(ab->buff, _wordsPerBuffer * 4); + ab->next = nullptr; + _addToList(&_empty, ab); + } + + _active[0] = _silence; + _active[1] = _silence; +} + +AudioBufferManager::~AudioBufferManager() { + noInterrupts(); + if (_running) { + _running = false; + for (auto i = 0; i < 2; i++) { + dma_channel_set_irq0_enabled(_channelDMA[i], false); + __channelMap[_channelDMA[i]] = nullptr; + dma_channel_abort(_channelDMA[i]); + dma_channel_unclaim(_channelDMA[i]); + dma_channel_acknowledge_irq0(_channelDMA[i]); + } + __channelCount--; + if (!__channelCount) { + irq_set_enabled(DMA_IRQ_0, false); + // TODO - how can we know if there are no other parts of the core using DMA0 IRQ?? + irq_remove_handler(DMA_IRQ_0, _irq); + } + } + interrupts(); + for (int i = 0; i < 2; i++) { + if (_active[i] != _silence) { + _deleteAudioBuffer(_active[i]); + } + } + while (_filled) { + auto x = _filled->next; + _deleteAudioBuffer(_filled); + _filled = x; + } + while (_empty) { + auto x = _empty->next; + _deleteAudioBuffer(_empty); + _empty = x; + } + _deleteAudioBuffer(_silence); +} + +void AudioBufferManager::setCallback(void (*fn)()) { + _callback = fn; +} + +bool AudioBufferManager::begin(int dreq, volatile void *pioFIFOAddr) { + _running = true; + + // Get ping and pong DMA channels + for (auto i = 0; i < 2; i++) { + _channelDMA[i] = dma_claim_unused_channel(true); + if (_channelDMA[i] == -1) { + if (i == 1) { + dma_channel_unclaim(_channelDMA[0]); + } + return false; + } + } + bool needSetIRQ = __channelCount == 0; + // Need to know both channels to set up ping-pong, so do in 2 stages + for (auto i = 0; i < 2; i++) { + dma_channel_config c = dma_channel_get_default_config(_channelDMA[i]); + channel_config_set_transfer_data_size(&c, _dmaSize); // 16b/32b transfers into PIO FIFO + if (_isOutput) { + channel_config_set_read_increment(&c, true); // Reading incrementing addresses + channel_config_set_write_increment(&c, false); // Writing to the same FIFO address + } else { + channel_config_set_read_increment(&c, false); // Reading same FIFO address + channel_config_set_write_increment(&c, true); // Writing to incrememting buffers + } + channel_config_set_dreq(&c, dreq); // Wait for the PIO TX FIFO specified + channel_config_set_chain_to(&c, _channelDMA[i ^ 1]); // Start other channel when done + channel_config_set_irq_quiet(&c, false); // Need IRQs + + if (_isOutput) { + dma_channel_configure(_channelDMA[i], &c, pioFIFOAddr, _silence->buff, _wordsPerBuffer * (_dmaSize == DMA_SIZE_16 ? 2 : 1), false); + } else { + _active[i] = _takeFromList(&_empty); + dma_channel_configure(_channelDMA[i], &c, _active[i]->buff, pioFIFOAddr, _wordsPerBuffer * (_dmaSize == DMA_SIZE_16 ? 2 : 1), false); + } + dma_channel_set_irq0_enabled(_channelDMA[i], true); + __channelMap[_channelDMA[i]] = this; + __channelCount++; + } + if (needSetIRQ) { + irq_add_shared_handler(DMA_IRQ_0, _irq, PICO_SHARED_IRQ_HANDLER_DEFAULT_ORDER_PRIORITY); + irq_set_enabled(DMA_IRQ_0, true); + } + + dma_channel_start(_channelDMA[0]); + return true; +} + +// Following 2 routines use volatile because the IRQ may update the "this" +// pointer and change the list head while we are waiting. Volatile will +// cause GCC to keep re-reading from memory and not use cached value read +// on the first pass. + +bool AudioBufferManager::write(uint32_t v, bool sync) { + if (!_running || !_isOutput) { + return false; + } + AudioBuffer ** volatile p = (AudioBuffer ** volatile)&_empty; + if (!*p) { + if (!sync) { + return false; + } else { + while (!*p) { + /* noop busy wait */ + } + } + } + (*p)->buff[_userOff++] = v; + if (_userOff == _wordsPerBuffer) { + _addToList(&_filled, _takeFromList(p)); + _userOff = 0; + } + return true; +} + +bool AudioBufferManager::read(uint32_t *v, bool sync) { + if (!_running || _isOutput) { + return false; + } + + AudioBuffer ** volatile p = (AudioBuffer ** volatile)&_filled; + if (!*p) { + if (!sync) { + return false; + } else { + while (!*p) { + /* noop busy wait */ + } + } + } + auto ret = (*p)->buff[_userOff++]; + if (_userOff == _wordsPerBuffer) { + _addToList(&_empty, _takeFromList(p)); + _userOff = 0; + } + *v = ret; + return true; +} + +bool AudioBufferManager::getOverUnderflow() { + bool hold = _overunderflow; + _overunderflow = false; + return hold; +} + +int AudioBufferManager::available() { + AudioBuffer *p = _isOutput ? _empty : _filled; + + if (!_running || !p) { + // No buffers available... + return 0; + } + + int avail = _wordsPerBuffer - _userOff; // Currently available in this buffer + + // Each add'l buffer has wpb spaces... + auto x = p->next; + while (x) { + avail += _wordsPerBuffer; + x = x->next; + } + return avail; +} + +void AudioBufferManager::flush() { + AudioBuffer ** volatile a = (AudioBuffer ** volatile)&_active[0]; + AudioBuffer ** volatile b = (AudioBuffer ** volatile)&_active[1]; + AudioBuffer ** volatile c = (AudioBuffer ** volatile)&_filled; + while (*c && (*b != (AudioBuffer * volatile)_silence) && (*a != (AudioBuffer * volatile)_silence)) { + // busy wait until all user written data enroute + } +} + +void __not_in_flash_func(AudioBufferManager::_dmaIRQ)(int channel) { + if (!_running) { + return; + } + if (_isOutput) { + if (_active[0] != _silence) { + _addToList(&_empty, _active[0]); + } + _active[0] = _active[1]; + if (!_filled) { + _active[1] = _silence; + } else { + _active[1] = _takeFromList(&_filled); + } + _overunderflow = _overunderflow | (_active[1] == _silence); + dma_channel_set_read_addr(channel, _active[0]->buff, false); + } else { + if (_empty) { + _addToList(&_filled, _active[0]); + _active[0] = _active[1]; + _active[1] = _takeFromList(&_empty); + } else { + _overunderflow = true; + } + dma_channel_set_write_addr(channel, _active[0]->buff, false); + } + dma_channel_set_trans_count(channel, _wordsPerBuffer * (_dmaSize == DMA_SIZE_16 ? 2 : 1), false); + dma_channel_acknowledge_irq0(channel); + if (_callback) { + _callback(); + } +} + +void __not_in_flash_func(AudioBufferManager::_irq)() { + for (size_t i = 0; i < sizeof(__channelMap); i++) { + if (dma_channel_get_irq0_status(i) && __channelMap[i]) { + __channelMap[i]->_dmaIRQ(i); + } + } +} diff --git a/libraries/AudioBufferManager/src/AudioBufferManager.h b/libraries/AudioBufferManager/src/AudioBufferManager.h new file mode 100644 index 000000000..96f9f5fbe --- /dev/null +++ b/libraries/AudioBufferManager/src/AudioBufferManager.h @@ -0,0 +1,102 @@ +/* + AudioBufferManager for Rasperry Pi Pico + Implements a DMA controlled linked-list series of buffers + + Copyright (c) 2022 Earle F. Philhower, III + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#pragma once +#include +#include "hardware/dma.h" + +class AudioBufferManager { +public: + AudioBufferManager(size_t bufferCount, size_t bufferWords, int32_t silenceSample, PinMode direction = OUTPUT, enum dma_channel_transfer_size dmaSize = DMA_SIZE_32); + ~AudioBufferManager(); + + void setCallback(void (*fn)()); + + bool begin(int dreq, volatile void *pioFIFOAddr); + + bool write(uint32_t v, bool sync = true); + bool read(uint32_t *v, bool sync = true); + void flush(); + + bool getOverUnderflow(); + int available(); + +private: + void _dmaIRQ(int channel); + static void _irq(); + + typedef struct AudioBuffer { + struct AudioBuffer *next; + uint32_t *buff; + } AudioBuffer; + + bool _running = false; + + AudioBuffer *_silence = nullptr; // A single silence buffer to be looped on underflow + AudioBuffer *_filled = nullptr; // List of buffers ready to be played + AudioBuffer *_empty = nullptr; // List of buffers waiting to be filled. *_empty = currently writing + AudioBuffer *_active[2] = { nullptr, nullptr }; // The 2 buffers currently in use for DMA + + // Can't use std::list because we need to put in RAM for IRQ use, so roll our own + void __not_in_flash_func(_addToList)(AudioBuffer **list, AudioBuffer *element) { + noInterrupts(); + // Find end of list, if any + while ((*list) && ((*list)->next != nullptr)) { + list = &(*list)->next; + } + if (*list) { + (*list)->next = element; + } else { + *list = element; + } + element->next = nullptr; // Belt and braces + interrupts(); + } + + AudioBuffer *__not_in_flash_func(_takeFromList)(AudioBuffer **list) { + noInterrupts(); + auto ret = *list; + if (ret) { + *list = ret->next; + } + interrupts(); + return ret; + } + + void _deleteAudioBuffer(AudioBuffer *ab) { + delete[] ab->buff; + delete ab; + } + + int _bitsPerSample; + size_t _wordsPerBuffer; + size_t _bufferCount; + enum dma_channel_transfer_size _dmaSize; + bool _isOutput; + + int _channelDMA[2]; + void (*_callback)(); + + bool _overunderflow; + + // User buffer pointer + size_t _userOff = 0; +}; diff --git a/libraries/BTstackLib/README.rp2040 b/libraries/BTstackLib/README.rp2040 new file mode 100644 index 000000000..52a4ef76e --- /dev/null +++ b/libraries/BTstackLib/README.rp2040 @@ -0,0 +1 @@ +This is the BTstack ports/arduino library, with compile errors fixed only. diff --git a/libraries/BTstackLib/examples/ANCS/ANCS.ino b/libraries/BTstackLib/examples/ANCS/ANCS.ino new file mode 100644 index 000000000..10c2f3d20 --- /dev/null +++ b/libraries/BTstackLib/examples/ANCS/ANCS.ino @@ -0,0 +1,105 @@ +#include +#include +#include "ble/att_server.h" +#include "ble/gatt_client.h" +#include "ble/gatt-service/ancs_client.h" +#include "ble/sm.h" +#include "btstack_event.h" +#include + +/* + EXAMPLE_START(ANCS): ANCS Client +*/ + +/* + @section Advertisement + @text An ANCS Client needs to include the ANCS UUID in its advertisement to + get recognized by iOS +*/ + +/* LISTING_START(ANCSAdvertisement): ANCS Advertisement */ +const uint8_t adv_data[] = { + // Flags general discoverable + 0x02, 0x01, 0x02, + // Name + 0x05, 0x09, 'A', 'N', 'C', 'S', + // Service Solicitation, 128-bit UUIDs - ANCS (little endian) + 0x11, 0x15, 0xD0, 0x00, 0x2D, 0x12, 0x1E, 0x4B, 0x0F, 0xA4, 0x99, 0x4E, 0xCE, 0xB5, 0x31, 0xF4, 0x05, 0x79 +}; +/* LISTING_END(ANCSAdvertisement): ANCS Advertisement */ + +/* + @section Setup + + @text In the setup, the LE Security Manager is configured to accept pairing requests. + Then, the ANCS Client library is initialized and and ancs_callback registered. + Finally, the Advertisement data is set and Advertisements are started. +*/ + +/* LISTING_START(ANCSSetup): ANCS Setup */ +void setup(void) { + + Serial.begin(9600); + Serial.println("BTstack ANCS Client starting up..."); + + // startup BTstack and configure log_info/log_error + BTstack.setup(); + + sm_set_io_capabilities(IO_CAPABILITY_DISPLAY_ONLY); + sm_set_authentication_requirements(SM_AUTHREQ_BONDING); + + // setup ANCS Client + ancs_client_init(); + ancs_client_register_callback(&ancs_callback); + + // enable advertisements + BTstack.setAdvData(sizeof(adv_data), adv_data); + BTstack.startAdvertising(); +} +/* LISTING_END(ANCSSetup): ANCS Setup */ + +void loop(void) { + BTstack.loop(); +} + +/* + @section ANCS Callback + @text In the ANCS Callback, connect and disconnect events are received. + For actual notifications, ancs_client_attribute_name_for_id allows to + look up the name. To get the notification body, e.g., the actual message, + the GATT Client needs to be used directly. +*/ + + +/* LISTING_START(ANCSCallback): ANCS Callback */ +void ancs_callback(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size) { + (void) packet_type; + (void) channel; + (void) size; + const char * attribute_name; + if (hci_event_packet_get_type(packet) != HCI_EVENT_ANCS_META) { + return; + } + switch (hci_event_ancs_meta_get_subevent_code(packet)) { + case ANCS_SUBEVENT_CLIENT_CONNECTED: + Serial.println("ANCS Client: Connected"); + break; + case ANCS_SUBEVENT_CLIENT_DISCONNECTED: + Serial.println("ANCS Client: Disconnected"); + break; + case ANCS_SUBEVENT_CLIENT_NOTIFICATION: + attribute_name = ancs_client_attribute_name_for_id(ancs_subevent_client_notification_get_attribute_id(packet)); + if (!attribute_name) { + break; + } + Serial.print("Notification: "); + Serial.print(attribute_name); + Serial.print(" - "); + Serial.println(ancs_subevent_client_notification_get_text(packet)); + break; + default: + break; + } +} +/* LISTING_END(ANCSCallback): ANCS Callback */ + diff --git a/libraries/BTstackLib/examples/LECentral/LECentral.ino b/libraries/BTstackLib/examples/LECentral/LECentral.ino new file mode 100644 index 000000000..88673a216 --- /dev/null +++ b/libraries/BTstackLib/examples/LECentral/LECentral.ino @@ -0,0 +1,328 @@ +#include +#include + +/* + EXAMPLE_START(LECentral): LE Central + + @text Compared with the other examples, the LE Central is + a bit more complex. This is because it performs multiple + steps in sequence as it is common with GATT Client APIs. + + It shows how to first scan for other + devices and then connect to one. When connected, a series of + GATT Client operations are performed: first the list of + GATT Services is queried. If a particular service is found, + the list of its GATT Characteristics is retrieved and a set + of known Characteristics are cached for later access. +*/ + +/* + @section Characteristic Summary + @text As multiple Characteristics need to be found, a custom + struct is used to collect all information about it. This allows + to define the list of necessary characteristics in the + characteristics[] array +*/ +/* LISTING_START(LECentralSummary): Characteristic Summary */ + +// BLE Shield Service V2 incl. used Characteristics +UUID bleShieldServiceV2UUID("B8E06067-62AD-41BA-9231-206AE80AB550"); + +typedef struct characteristic_summary { + UUID uuid; + const char * name; + bool found; + BLECharacteristic characteristic; +} characteristic_summary_t; + +typedef enum characteristicIDs { + charRX = 0, + charTX, + charBaud, + charBdAddr, + numCharacteristics /* last one */ +} characteristicIDs_t; + +characteristic_summary characteristics[] = { + { UUID("f897177b-aee8-4767-8ecc-cc694fd5fcee"), "RX", false, BLECharacteristic() }, + { UUID("bf45e40a-de2a-4bc8-bba0-e5d6065f1b4b"), "TX", false, BLECharacteristic() }, + { UUID("2fbc0f31-726a-4014-b9fe-c8be0652e982"), "Baudrate", false, BLECharacteristic() }, + { UUID("65c228da-bad1-4f41-b55f-3d177f4e2196"), "BD ADDR", false, BLECharacteristic() } +}; + +/* LISTING_END(LECentralSummary): Characteristic Summary */ + +// Application state +BLEDevice myBLEDevice; +BLEService myBLEService; +bool serviceFound; +bool sendCounter = false; + +int counter = 0; +char counterString[20]; + +// static btstack_timer_source_t heartbeat; + +/* + @section Setup + @text In the setup, various callbacks are registered. After that + we start scanning for other devices +*/ +/* LISTING_START(LECentralSetup): LE Central Setup */ +void setup(void) { + Serial.begin(9600); + BTstack.setBLEAdvertisementCallback(advertisementCallback); + BTstack.setBLEDeviceConnectedCallback(deviceConnectedCallback); + BTstack.setBLEDeviceDisconnectedCallback(deviceDisconnectedCallback); + BTstack.setGATTServiceDiscoveredCallback(gattServiceDiscovered); + BTstack.setGATTCharacteristicDiscoveredCallback(gattCharacteristicDiscovered); + BTstack.setGATTCharacteristicNotificationCallback(gattCharacteristicNotification); + BTstack.setGATTCharacteristicReadCallback(gattReadCallback); + BTstack.setGATTCharacteristicWrittenCallback(gattWrittenCallback); + BTstack.setGATTCharacteristicSubscribedCallback(gattSubscribedCallback); + BTstack.setup(); + BTstack.bleStartScanning(); +} +/* LISTING_END(LECentralSetup): LE Central Setup */ + +/* + @section Loop + + @text In the standard Arduino loop() function, BTstack's loop() is called first + If we're connected, we send the string "BTstack" plus a counter as fast as possible. + As the Bluetooth module might be busy, it's important to check the result of the + writeCharacteristicWithoutResponse() call. If it's not ok, we just try again in the + next loop iteration. +*/ +/* LISTING_START(LECentralLoop): Loop */ +void loop(void) { + BTstack.loop(); + + // send counter as fast as possible + if (sendCounter) { + sprintf(counterString, "BTstack %u\n", counter); + int result = myBLEDevice.writeCharacteristicWithoutResponse(&characteristics[charTX].characteristic, (uint8_t*) counterString, strlen(counterString)); + if (result == 0) { + Serial.print("Wrote without response: "); + Serial.println(counterString); + counter++; + } + } +} +/* LISTING_END(LECentralLoop): Loop */ + +/* + @section Advertisement Callback + + @text When an Advertisement is received, we check if it contains + the UUID of the service we're interested in. Only a single service + with a 128-bit UUID can be contained in and Advertisement and not + all BLE devices provides this. Other options are to match on the + reported device name or the BD ADDR prefix. + + If we found an interesting device, we try to connect to it. +*/ +/* LISTING_START(LECentralAdvertisementCallback): Advertisement Callback */ +void advertisementCallback(BLEAdvertisement *bleAdvertisement) { + Serial.print("Device discovered: "); + Serial.print(bleAdvertisement->getBdAddr()->getAddressString()); + Serial.print(", RSSI: "); + Serial.println(bleAdvertisement->getRssi()); + if (bleAdvertisement->containsService(&bleShieldServiceV2UUID)) { + Serial.println("\nBLE ShieldService V2 found!\n"); + BTstack.bleStopScanning(); + BTstack.bleConnect(bleAdvertisement, 10000); // 10 s + } +} +/* LISTING_END(LECentralAdvertisementCallback): Advertisement Callback */ + +/* + @section Device Connected Callback + + @text At the end of bleConnect(), the device connected callback is callec. + The status argument tells if the connection timed out, or if the connection + was established successfully. + + On a successful connection, a GATT Service Discovery is started. +*/ +/* LISTING_START(LECentralDeviceConnectedCallback): Device Connected Callback */ +void deviceConnectedCallback(BLEStatus status, BLEDevice *device) { + switch (status) { + case BLE_STATUS_OK: + Serial.println("Device connected!"); + myBLEDevice = *device; + counter = 0; + myBLEDevice.discoverGATTServices(); + break; + case BLE_STATUS_CONNECTION_TIMEOUT: + Serial.println("Error while Connecting the Peripheral"); + BTstack.bleStartScanning(); + break; + default: + break; + } +} +/* LISTING_END(LECentralDeviceConnectedCallback): Device Connected Callback */ + +/* + @section Device Disconnected Callback + + @text If the connection to a device breaks, the device disconnected callback + is called. Here, we start scanning for new devices again. +*/ +/* LISTING_START(LECentralDeviceDisconnectedCallback): Device Disconnected Callback */ +void deviceDisconnectedCallback(BLEDevice * device) { + (void) device; + Serial.println("Disconnected, starting over.."); + sendCounter = false; + BTstack.bleStartScanning(); +} +/* LISTING_END(LECentralDeviceDisconnectedCallback): Device Disconnected Callback */ + +/* + @section Service Discovered Callback + + @text The service discovered callback is called for each service and after the + service discovery is complete. The status argument is provided for this. + + The main information about a discovered Service is its UUID. + If we find our service, we store the reference to this service. + This allows to discover the Characteristics for our service after + the service discovery is complete. +*/ +/* LISTING_START(LECentralServiceDiscoveredCallback): Service Discovered Callback */ +void gattServiceDiscovered(BLEStatus status, BLEDevice *device, BLEService *bleService) { + switch (status) { + case BLE_STATUS_OK: + Serial.print("Service Discovered: :"); + Serial.println(bleService->getUUID()->getUuidString()); + if (bleService->matches(&bleShieldServiceV2UUID)) { + serviceFound = true; + Serial.println("Our service located!"); + myBLEService = *bleService; + } + break; + case BLE_STATUS_DONE: + Serial.println("Service discovery finished"); + if (serviceFound) { + device->discoverCharacteristicsForService(&myBLEService); + } + break; + default: + Serial.println("Service discovery error"); + break; + } +} +/* LISTING_END(LECentralServiceDiscoveredCallback): Service Discovered Callback */ + +/* + @section Characteristic Discovered Callback + + @text Similar to the Service Discovered callback, the Characteristic Discovered + callback is called for each Characteristic found and after the discovery is complete. + + The main information is again its UUID. If we find a Characteristic that we're + interested in, it's name is printed and a reference stored for later. + + On discovery complete, we subscribe to a particular Characteristic to receive + Characteristic Value updates in the Notificaation Callback. +*/ +/* LISTING_START(LECentralCharacteristicDiscoveredCallback): Characteristic Discovered Callback */ +void gattCharacteristicDiscovered(BLEStatus status, BLEDevice *device, BLECharacteristic *characteristic) { + switch (status) { + case BLE_STATUS_OK: + Serial.print("Characteristic Discovered: "); + Serial.print(characteristic->getUUID()->getUuidString()); + Serial.print(", handle 0x"); + Serial.println(characteristic->getCharacteristic()->value_handle, HEX); + int i; + for (i = 0; i < numCharacteristics; i++) { + if (characteristic->matches(&characteristics[i].uuid)) { + Serial.print("Characteristic found: "); + Serial.println(characteristics[i].name); + characteristics[i].found = 1; + characteristics[i].characteristic = *characteristic; + break; + } + } + break; + case BLE_STATUS_DONE: + Serial.print("Characteristic discovery finished, status "); + Serial.println(status, HEX); + if (characteristics[charRX].found) { + device->subscribeForNotifications(&characteristics[charRX].characteristic); + } + break; + default: + Serial.println("Characteristics discovery error"); + break; + } +} +/* LISTING_END(LECentralCharacteristicDiscoveredCallback): Characteristic Discovered Callback */ + +/* + @section Subscribed Callback + + @text After the subscribe operation is complete, we get notified if it was + successful. In this example, we read the Characteristic that contains the + BD ADDR of the other device. This isn't strictly necessary as we already + know the device address from the Advertisement, but it's a common pattern + with iOS as the device address is hidden from applications. +*/ +/* LISTING_START(LECentralSubscribedCallback): Subscribed Callback */ +void gattSubscribedCallback(BLEStatus status, BLEDevice * device) { + (void) status; + device->readCharacteristic(&characteristics[charBdAddr].characteristic); +} +/* LISTING_END(LECentralSubscribedCallback): Subscribed Callback */ + +/* + @section Read Callback + + @text The Read callback is called with the result from a read operation. + Here, we write to the TX Characteristic next. +*/ +/* LISTING_START(LECentralReadCallback): Read Callback */ +void gattReadCallback(BLEStatus status, BLEDevice *device, uint8_t *value, uint16_t length) { + (void) status; + (void) length; + Serial.print("Read callback: "); + Serial.println((const char *)value); + device->writeCharacteristic(&characteristics[charTX].characteristic, (uint8_t*) "Hello!", 6); +} +/* LISTING_END(LECentralReadCallback): Read Callback */ + +/* + @section Written Callback + + @text After the write operation is complete, the Written Callback is callbed with + the result in the status argument. As we're done with the initial setup of the remote + device, we set the flag to write the test string as fast as possible. +*/ +/* LISTING_START(LECentralWrittenCallback): Written Callback */ +void gattWrittenCallback(BLEStatus status, BLEDevice *device) { + (void) status; + (void) device; + sendCounter = true; +} +/* LISTING_END(LECentralWrittenCallback): Written Callback */ + +/* + @section Notification Callback + + @text Notifications for Characteristic Value Updates are delivered via the + Notification Callback. When more than one Characteristic is subscribed, + the value handle can be used to distinguish between them. The + BLECharacteristic.isValueHandle(int handle) allows to test if a value handle + belongs to a particular Characteristic. +*/ +/* LISTING_START(LECentralNotificationCallback): Notification Callback */ +void gattCharacteristicNotification(BLEDevice *device, uint16_t value_handle, uint8_t *value, uint16_t length) { + (void) device; + (void) value_handle; + (void) length; + Serial.print("Notification: "); + Serial.println((const char *)value); +} +/* LISTING_END(LECentralNotificationCallback): Notification Callback */ + diff --git a/libraries/BTstackLib/examples/LEPeripheral/LEPeripheral.ino b/libraries/BTstackLib/examples/LEPeripheral/LEPeripheral.ino new file mode 100644 index 000000000..8cc959d51 --- /dev/null +++ b/libraries/BTstackLib/examples/LEPeripheral/LEPeripheral.ino @@ -0,0 +1,120 @@ +// LE Peripheral Example - not working yet +#include +#include + +/* + EXAMPLE_START(LEPeripheral): LE Peripheral + + @text BTstack allows to setup a GATT Services and Characteristics directly + from the setup function without using other tools outside of the Arduino IDE. + + @section Setup + + @text First, a number of callbacks are set. Then, a Service with a Read-only + Characteristic and a dynamic Characteristic is added to the GATT database. + In BTstack, a dynamic Characteristic is a Characteristic where reads and writes + are forwarded to the Sketch. In this example, the dynamic Characteristic is + provided by the single byte variable characteristic_data. +*/ + +/* LISTING_START(LEPeripheralSetup): Setup */ +static char characteristic_data = 'H'; + +void setup(void) { + + Serial.begin(9600); + + // set callbacks + BTstack.setBLEDeviceConnectedCallback(deviceConnectedCallback); + BTstack.setBLEDeviceDisconnectedCallback(deviceDisconnectedCallback); + BTstack.setGATTCharacteristicRead(gattReadCallback); + BTstack.setGATTCharacteristicWrite(gattWriteCallback); + + // setup GATT Database + BTstack.addGATTService(new UUID("B8E06067-62AD-41BA-9231-206AE80AB551")); + BTstack.addGATTCharacteristic(new UUID("f897177b-aee8-4767-8ecc-cc694fd5fcef"), ATT_PROPERTY_READ, "This is a String!"); + BTstack.addGATTCharacteristicDynamic(new UUID("f897177b-aee8-4767-8ecc-cc694fd5fce0"), ATT_PROPERTY_READ | ATT_PROPERTY_WRITE | ATT_PROPERTY_NOTIFY, 0); + + // startup Bluetooth and activate advertisements + BTstack.setup(); + BTstack.startAdvertising(); +} +/* LISTING_END(LEPeripheralSetup): Setup */ + +void loop(void) { + BTstack.loop(); +} + +/* + @section Device Connected Callback + + @text When a remove device connects, device connected callback is callec. +*/ +/* LISTING_START(LEPeripheralDeviceConnectedCallback): Device Connected Callback */ +void deviceConnectedCallback(BLEStatus status, BLEDevice *device) { + (void) device; + switch (status) { + case BLE_STATUS_OK: + Serial.println("Device connected!"); + break; + default: + break; + } +} +/* LISTING_END(LEPeripheralDeviceConnectedCallback): Device Connected Callback */ + +/* + @section Device Disconnected Callback + + @text If the connection to a device breaks, the device disconnected callback + is called. +*/ +/* LISTING_START(LEPeripheralDeviceDisconnectedCallback): Device Disconnected Callback */ +void deviceDisconnectedCallback(BLEDevice * device) { + (void) device; + Serial.println("Disconnected."); +} +/* LISTING_END(LEPeripheralDeviceDisconnectedCallback): Device Disconnected Callback */ + +/* + @section Read Callback + + @text In BTstack, the Read Callback is first called to query the size of the + Characteristic Value, before it is called to provide the data. + Both times, the size has to be returned. The data is only stored in the provided + buffer, if the buffer argeument is not NULL. + If more than one dynamic Characteristics is used, the value handle is used + to distinguish them. +*/ +/* LISTING_START(LEPeripheralReadCallback): Read Callback */ +uint16_t gattReadCallback(uint16_t value_handle, uint8_t * buffer, uint16_t buffer_size) { + (void) value_handle; + (void) buffer_size; + if (buffer) { + Serial.print("gattReadCallback, value: "); + Serial.println(characteristic_data, HEX); + buffer[0] = characteristic_data; + } + return 1; +} +/* LISTING_END(LEPeripheralDeviceDisconnectedCallback): Read Callback */ + +/* + @section Write Callback + + @text When the remove device writes a Characteristic Value, the Write callback + is called. The buffer arguments points to the data of size size/ + If more than one dynamic Characteristics is used, the value handle is used + to distinguish them. +*/ +/* LISTING_START(LEPeripheralWriteCallback): Write Callback */ +int gattWriteCallback(uint16_t value_handle, uint8_t *buffer, uint16_t size) { + (void) value_handle; + (void) size; + characteristic_data = buffer[0]; + Serial.print("gattWriteCallback , value "); + Serial.println(characteristic_data, HEX); + return 0; +} +/* LISTING_END(LEPeripheralWriteCallback): Write Callback */ + diff --git a/libraries/BTstackLib/examples/iBeacon/iBeacon.ino b/libraries/BTstackLib/examples/iBeacon/iBeacon.ino new file mode 100644 index 000000000..a6a685fb3 --- /dev/null +++ b/libraries/BTstackLib/examples/iBeacon/iBeacon.ino @@ -0,0 +1,25 @@ +#include +#include +#include + +/* EXAMPLE_START(iBeacon): iBeacon Simulator + + @section Setup + + @text After BTstack.setup(), iBeaconConfigure() configures BTstack + to send out iBeacons Advertisements with the provided Major ID, + Minor ID and UUID. +*/ +/* LISTING_START(iBeaconSetup): iBeacon Setup */ +UUID uuid("E2C56DB5-DFFB-48D2-B060-D0F5A71096E0"); +void setup(void) { + Serial.begin(9600); + BTstack.setup(); + BTstack.iBeaconConfigure(&uuid, 4711, 2); + BTstack.startAdvertising(); +} +/* LISTING_END(iBeaconSetup) */ + +void loop(void) { + BTstack.loop(); +} diff --git a/libraries/BTstackLib/examples/iBeaconScanner/iBeaconScanner.ino b/libraries/BTstackLib/examples/iBeaconScanner/iBeaconScanner.ino new file mode 100644 index 000000000..3c0c9c7b4 --- /dev/null +++ b/libraries/BTstackLib/examples/iBeaconScanner/iBeaconScanner.ino @@ -0,0 +1,58 @@ +#include +#include + +/* EXAMPLE_START(iBeaconScanner): iBeacon Scanner + + @section Setup + + @text After BTstack.setup(), BTstack is configured to call + advertisementCallback whenever an Advertisement was received. + Then, a device discovery is started +*/ + +/* LISTING_START(iBeaconSetup): iBeacon Scanner Setup */ +void setup(void) { + Serial.begin(9600); + BTstack.setup(); + BTstack.setBLEAdvertisementCallback(advertisementCallback); + BTstack.bleStartScanning(); +} +/* LISTING_END(iBeaconSetup): iBeacon Scanner Setup */ + +void loop(void) { + BTstack.loop(); +} + +/* + @section Advertisement Callback + + @text Whenever an Advertisement is received, isIBeacon() checks if + it contains an iBeacon. If yes, the Major ID, Minor ID, and UUID + is printed. + If it's not an iBeacon, only the BD_ADDR and the received signal strength + (RSSI) is shown. +*/ +/* LISTING_START(iBeaconCallback): iBeacon Scanner Callback */ +void advertisementCallback(BLEAdvertisement *adv) { + if (adv->isIBeacon()) { + Serial.print("iBeacon found "); + Serial.print(adv->getBdAddr()->getAddressString()); + Serial.print(", RSSI "); + Serial.print(adv->getRssi()); + Serial.print(", UUID "); + Serial.print(adv->getIBeaconUUID()->getUuidString()); + Serial.print(", MajorID "); + Serial.print(adv->getIBeaconMajorID()); + Serial.print(", MinorID "); + Serial.print(adv->getIBecaonMinorID()); + Serial.print(", Measured Power "); + Serial.println(adv->getiBeaconMeasuredPower()); + } else { + Serial.print("Device discovered: "); + Serial.print(adv->getBdAddr()->getAddressString()); + Serial.print(", RSSI "); + Serial.println(adv->getRssi()); + } +} +/* LISTING_END(iBeaconCallback): iBeacon Scanner Callback */ + diff --git a/libraries/BTstackLib/keywords.txt b/libraries/BTstackLib/keywords.txt new file mode 100644 index 000000000..21f12dc68 --- /dev/null +++ b/libraries/BTstackLib/keywords.txt @@ -0,0 +1,100 @@ +####################################### +# Syntax Coloring Map +####################################### + +####################################### +# Library (KEYWORD3) +####################################### + +BTstack KEYWORD3 RESERVED_WORD + +####################################### +# Datatypes (KEYWORD1) +####################################### + +BLEStatus KEYWORD2 +UUID KEYWORD2 +BD_ADDR_TYPE KEYWORD2 +BD_ADDR KEYWORD2 +BLEAdvertisement KEYWORD2 +BLECharacteristic KEYWORD2 +BLEService KEYWORD2 +BLEDevice KEYWORD2 +BTstackManager KEYWORD2 + +####################################### +# Methods and Functions (KEYWORD2) +####################################### + +getUuidString KEYWORD2 +getUuid128String KEYWORD2 +getUuid KEYWORD2 +matches KEYWORD2 +getAddress KEYWORD2 +getAddressString KEYWORD2 +getAddressType KEYWORD2 +getBdAddr KEYWORD2 +getBdAddrType KEYWORD2 +getRssi KEYWORD2 +containsService KEYWORD2 +nameHasPrefix KEYWORD2 +getAdvData KEYWORD2 +isIBeacon KEYWORD2 +getIBeaconUUID KEYWORD2 +getIBeaconMajorID KEYWORD2 +getIBecaonMinorID KEYWORD2 +getiBeaconMeasuredPower KEYWORD2 +isValueHandle KEYWORD2 +getCharacteristic KEYWORD2 +getUUID KEYWORD2 +getService KEYWORD2 +getHandle KEYWORD2 +discoverGATTServices KEYWORD2 +discoverCharacteristicsForService KEYWORD2 +readCharacteristic KEYWORD2 +writeCharacteristic KEYWORD2 +writeCharacteristicWithoutResponse KEYWORD2 +subscribeForNotifications KEYWORD2 +unsubscribeFromNotifications KEYWORD2 +subscribeForIndications KEYWORD2 +unsubscribeFromIndications KEYWORD2 +setPublicBdAddr KEYWORD2 +enablePacketLogger KEYWORD2 +enableDebugLogger KEYWORD2 +setAdvData KEYWORD2 +iBeaconConfigure KEYWORD2 +startAdvertising KEYWORD2 +stopAdvertising KEYWORD2 +bleStartScanning KEYWORD2 +bleStopScanning KEYWORD2 +bleConnect KEYWORD2 +bleDisconnect KEYWORD2 +setBLEAdvertisementCallback KEYWORD2 +setBLEDeviceConnectedCallback KEYWORD2 +setBLEDeviceDisconnectedCallback KEYWORD2 +setGATTServiceDiscoveredCallback KEYWORD2 +setGATTCharacteristicDiscoveredCallback KEYWORD2 +setGATTCharacteristicReadCallback KEYWORD2 +setGATTCharacteristicNotificationCallback KEYWORD2 +setGATTCharacteristicIndicationCallback KEYWORD2 +setGATTDoneCallback KEYWORD2 +setGATTCharacteristicWrittenCallback KEYWORD2 +setGATTCharacteristicSubscribedCallback KEYWORD2 +setGATTCharacteristicUnsubscribedCallback KEYWORD2 +setGATTCharacteristicRead KEYWORD2 +setGATTCharacteristicWrite KEYWORD2 +addGATTService KEYWORD2 +addGATTCharacteristic KEYWORD2 +addGATTCharacteristicDynamic KEYWORD2 + +####################################### +# Constants (LITERAL1) +####################################### + +BLE_STATUS_OK LITERAL1 +BLE_STATUS_DONE LITERAL1 +BLE_STATUS_CONNECTION_TIMEOUT LITERAL1 +BLE_STATUS_CONNECTION_ERROR LITERAL1 +BLE_STATUS_OTHER_ERROR LITERAL1 +PUBLIC_ADDRESS LITERAL1 +PRIVAT_ADDRESS LITERAL1 diff --git a/libraries/BTstackLib/library.properties b/libraries/BTstackLib/library.properties new file mode 100644 index 000000000..8cb738051 --- /dev/null +++ b/libraries/BTstackLib/library.properties @@ -0,0 +1,10 @@ +name=BTstack +version=1.0 +author=bluekitchen-gmbh +maintainer=Earle Philhower +sentence=BTstack Arduino library distributed with BTstack +paragraph= +category=Data Processing +url= +architectures=rp2040 +dot_a_linkage=true diff --git a/libraries/BTstackLib/src/BTstackLib.cpp b/libraries/BTstackLib/src/BTstackLib.cpp new file mode 100644 index 000000000..439422133 --- /dev/null +++ b/libraries/BTstackLib/src/BTstackLib.cpp @@ -0,0 +1,907 @@ +/** + Arduino Wrapper for BTstack +*/ + +#include +#include + +#ifdef __AVR__ +#include +#endif + +#if __arm__ +//#include // also provides NVIC_SystemReset +#endif + +#include "BTstackLib.h" + +#include "btstack_memory.h" +#include "hal_tick.h" +#include "hal_cpu.h" +#include "hci_cmd.h" +#include "btstack_util.h" +#include "btstack_run_loop.h" +#include "btstack_event.h" +#include "btstack_run_loop_embedded.h" +#include "hci_transport.h" +#include "hci_transport_h4.h" + +#include "ad_parser.h" +//#include "btstack_chipset_em9301.h" +#include "btstack_debug.h" +#include "gap.h" +#include "hci.h" +#include "hci_dump.h" +#include "hci_dump_embedded_stdout.h" +#include "l2cap.h" +#include "ble/att_db.h" +#include "ble/att_server.h" +#include "ble/att_db_util.h" +#include "ble/le_device_db.h" +#include "ble/sm.h" + +// Pin 13 has an LED connected on most Arduino boards. +//#define PIN_LED 13 + +// prototypes +extern "C" void hal_uart_dma_process(void); + +enum { + SET_ADVERTISEMENT_PARAMS = 1 << 0, + SET_ADVERTISEMENT_DATA = 1 << 1, + SET_ADVERTISEMENT_ENABLED = 1 << 2, +}; + +typedef enum gattAction { + gattActionWrite, + gattActionSubscribe, + gattActionUnsubscribe, + gattActionServiceQuery, + gattActionCharacteristicQuery, + gattActionRead, +} gattAction_t; + +static gattAction_t gattAction; + +// btstack state +static int btstack_state; + +static const uint8_t iBeaconAdvertisement01[] = { 0x02, 0x01 }; +static const uint8_t iBeaconAdvertisement38[] = { 0x1a, 0xff, 0x4c, 0x00, 0x02, 0x15 }; +static uint8_t adv_data[31]; +static uint16_t adv_data_len = 0; +//static int gatt_is_characteristics_query; + +static uint16_t le_peripheral_todos = 0; +static bool have_custom_addr; +static bd_addr_t public_bd_addr; + +static btstack_timer_source_t connection_timer; + +static void (*bleAdvertismentCallback)(BLEAdvertisement * bleAdvertisement) = NULL; +static void (*bleDeviceConnectedCallback)(BLEStatus status, BLEDevice * device) = NULL; +static void (*bleDeviceDisconnectedCallback)(BLEDevice * device) = NULL; +static void (*gattServiceDiscoveredCallback)(BLEStatus status, BLEDevice * device, BLEService * bleService) = NULL; +static void (*gattCharacteristicDiscoveredCallback)(BLEStatus status, BLEDevice * device, BLECharacteristic * characteristic) = NULL; +static void (*gattCharacteristicNotificationCallback)(BLEDevice * device, uint16_t value_handle, uint8_t* value, uint16_t length) = NULL; +static void (*gattCharacteristicIndicationCallback)(BLEDevice * device, uint16_t value_handle, uint8_t* value, uint16_t length) = NULL; +static void (*gattCharacteristicReadCallback)(BLEStatus status, BLEDevice * device, uint8_t * value, uint16_t length) = NULL; +static void (*gattCharacteristicWrittenCallback)(BLEStatus status, BLEDevice * device) = NULL; +static void (*gattCharacteristicSubscribedCallback)(BLEStatus status, BLEDevice * device) = NULL; +static void (*gattCharacteristicUnsubscribedCallback)(BLEStatus status, BLEDevice * device) = NULL; + + +// retarget printf to Serial +#ifdef ENERGIA +extern "C" int putchar(int c) { + Serial.write((uint8_t)c); + return c; +} +#else +#ifdef __AVR__ +static FILE uartout = {0} ; +static int uart_putchar(char c, FILE *stream) { + Serial.write(c); + return 0; +} +#endif +// added for Arduino Zero. Arduino Due already has tis own _write(..) implementation +// in /Users/mringwal/Library/Arduino15/packages/arduino/hardware/sam/1.6.4/cores/arduino/syscalls_sam3.c +#if defined(__SAMD21G18A__) +// #ifdef __arm__ +extern "C" int _write(int file, char *ptr, int len) { + int i; + for (i = 0; i < len; i++) { + if (ptr[i] == '\n') { + Serial.write((uint8_t)'\r'); + } + Serial.write((uint8_t)ptr[i]); + } + return i; +} +#endif +#endif + +// HAL CPU Implementation +extern "C" void hal_cpu_disable_irqs(void) { } +extern "C" void hal_cpu_enable_irqs(void) { } +extern "C" void hal_cpu_enable_irqs_and_sleep(void) { } + +// +static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size) { + (void) channel; + (void) size; + hci_con_handle_t con_handle; + + switch (packet_type) { + + case HCI_EVENT_PACKET: + switch (packet[0]) { + + case BTSTACK_EVENT_STATE: + btstack_state = packet[2]; + // bt stack activated, get started + if (btstack_event_state_get_state(packet) == HCI_STATE_WORKING) { + le_peripheral_todos |= SET_ADVERTISEMENT_PARAMS + | SET_ADVERTISEMENT_DATA + | SET_ADVERTISEMENT_ENABLED; + bd_addr_t addr; + gap_local_bd_addr(addr); + printf("BTstack up and running at %s\n", bd_addr_to_str(addr)); + } + break; + + case HCI_EVENT_DISCONNECTION_COMPLETE: + if (bleDeviceDisconnectedCallback) { + con_handle = little_endian_read_16(packet, 3); + BLEDevice device(con_handle); + (*bleDeviceDisconnectedCallback)(&device); + } + le_peripheral_todos |= SET_ADVERTISEMENT_ENABLED; + break; + + case GAP_EVENT_ADVERTISING_REPORT: { + if (bleAdvertismentCallback) { + BLEAdvertisement advertisement(packet); + (*bleAdvertismentCallback)(&advertisement); + } + break; + } + + case HCI_EVENT_LE_META: + switch (packet[2]) { + case HCI_SUBEVENT_LE_CONNECTION_COMPLETE: + con_handle = little_endian_read_16(packet, 4); + printf("Connection complete, con_handle 0x%04x\n", con_handle); + btstack_run_loop_remove_timer(&connection_timer); + if (!bleDeviceConnectedCallback) { + break; + } + if (packet[3]) { + (*bleDeviceConnectedCallback)(BLE_STATUS_CONNECTION_ERROR, NULL); + } else { + BLEDevice device(con_handle); + (*bleDeviceConnectedCallback)(BLE_STATUS_OK, &device); + } + break; + default: + break; + } + break; + } + } +} + +static void extract_service(gatt_client_service_t * service, uint8_t * packet) { + service->start_group_handle = little_endian_read_16(packet, 4); + service->end_group_handle = little_endian_read_16(packet, 6); + service->uuid16 = 0; + reverse_128(&packet[8], service->uuid128); + if (uuid_has_bluetooth_prefix(service->uuid128)) { + service->uuid16 = big_endian_read_32(service->uuid128, 0); + } +} + +static void extract_characteristic(gatt_client_characteristic_t * characteristic, uint8_t * packet) { + characteristic->start_handle = little_endian_read_16(packet, 4); + characteristic->value_handle = little_endian_read_16(packet, 6); + characteristic->end_handle = little_endian_read_16(packet, 8); + characteristic->properties = little_endian_read_16(packet, 10); + characteristic->uuid16 = 0; + reverse_128(&packet[12], characteristic->uuid128); + if (uuid_has_bluetooth_prefix(characteristic->uuid128)) { + characteristic->uuid16 = big_endian_read_32(characteristic->uuid128, 0); + } +} + +static void gatt_client_callback(uint8_t packet_type, uint16_t channel, uint8_t * packet, uint16_t size) { + (void) channel; + (void) packet_type; + (void) size; + // if (hci) event is not 4-byte aligned, event->handle causes crash + // workaround: check event type, assuming GATT event types are contagious + if (packet[0] < GATT_EVENT_QUERY_COMPLETE) { + return; + } + if (packet[0] > GATT_EVENT_MTU) { + return; + } + + hci_con_handle_t con_handle = little_endian_read_16(packet, 2); + uint8_t status; + uint8_t * value; + uint16_t value_handle; + uint16_t value_length; + + BLEDevice device(con_handle); + switch (hci_event_packet_get_type(packet)) { + case GATT_EVENT_SERVICE_QUERY_RESULT: + if (gattServiceDiscoveredCallback) { + gatt_client_service_t service; + extract_service(&service, packet); + BLEService bleService(service); + (*gattServiceDiscoveredCallback)(BLE_STATUS_OK, &device, &bleService); + } + break; + case GATT_EVENT_CHARACTERISTIC_QUERY_RESULT: + if (gattCharacteristicDiscoveredCallback) { + gatt_client_characteristic_t characteristic; + extract_characteristic(&characteristic, packet); + BLECharacteristic bleCharacteristic(characteristic); + (*gattCharacteristicDiscoveredCallback)(BLE_STATUS_OK, &device, &bleCharacteristic); + } + break; + case GATT_EVENT_QUERY_COMPLETE: + status = little_endian_read_16(packet, 4); + switch (gattAction) { + case gattActionWrite: + if (gattCharacteristicWrittenCallback) { + gattCharacteristicWrittenCallback(status ? BLE_STATUS_OTHER_ERROR : BLE_STATUS_OK, &device); + } + break; + case gattActionSubscribe: + if (gattCharacteristicSubscribedCallback) { + gattCharacteristicSubscribedCallback(status ? BLE_STATUS_OTHER_ERROR : BLE_STATUS_OK, &device); + } + break; + case gattActionUnsubscribe: + if (gattCharacteristicUnsubscribedCallback) { + gattCharacteristicUnsubscribedCallback(status ? BLE_STATUS_OTHER_ERROR : BLE_STATUS_OK, &device); + } + break; + case gattActionServiceQuery: + if (gattServiceDiscoveredCallback) { + gattServiceDiscoveredCallback(BLE_STATUS_DONE, &device, NULL); + } + break; + case gattActionCharacteristicQuery: + if (gattCharacteristicDiscoveredCallback) { + gattCharacteristicDiscoveredCallback(BLE_STATUS_DONE, &device, NULL); + } + break; + default: + break; + }; + break; + case GATT_EVENT_NOTIFICATION: + if (gattCharacteristicNotificationCallback) { + value_handle = little_endian_read_16(packet, 4); + value_length = little_endian_read_16(packet, 6); + value = &packet[8]; + (*gattCharacteristicNotificationCallback)(&device, value_handle, value, value_length); + } + break; + case GATT_EVENT_INDICATION: + if (gattCharacteristicIndicationCallback) { + value_handle = little_endian_read_16(packet, 4); + value_length = little_endian_read_16(packet, 6); + value = &packet[8]; + (*gattCharacteristicIndicationCallback)(&device, value_handle, value, value_length); + } + break; + case GATT_EVENT_CHARACTERISTIC_VALUE_QUERY_RESULT: + if (gattCharacteristicReadCallback) { + value_handle = little_endian_read_16(packet, 4); + value_length = little_endian_read_16(packet, 6); + value = &packet[8]; + (*gattCharacteristicReadCallback)(BLE_STATUS_OK, &device, value, value_length); + } + break; + default: + break; + } +} + +static void connection_timeout_handler(btstack_timer_source_t * timer) { + (void) timer; + // log_info("Cancel outgoing connection"); + gap_connect_cancel(); + if (!bleDeviceConnectedCallback) { + return; + } + (*bleDeviceConnectedCallback)(BLE_STATUS_CONNECTION_TIMEOUT, NULL); // page timeout 0x04 +} + +// + +/// UUID class +UUID::UUID(void) { + memset(uuid, 0, 16); +} + +UUID::UUID(const uint8_t uuid[16]) { + memcpy(this->uuid, uuid, 16); +} + +UUID::UUID(const char * uuidStr) { + memset(uuid, 0, 16); + int len = strlen(uuidStr); + if (len <= 4) { + // Handle 4 Bytes HEX + unsigned int uuid16; + int result = sscanf((char *) uuidStr, "%x", &uuid16); + if (result == 1) { + uuid_add_bluetooth_prefix(uuid, uuid16); + } + return; + } + + // quick UUID parser, ignoring dashes + int i = 0; + int data = 0; + int have_nibble = 0; + while (*uuidStr && i < 16) { + const char c = *uuidStr++; + if (c == '-') { + continue; + } + data = data << 4 | nibble_for_char(c); + if (!have_nibble) { + have_nibble = 1; + continue; + } + uuid[i++] = data; + data = 0; + have_nibble = 0; + } +} + +const uint8_t * UUID::getUuid(void) const { + return uuid; +} + +static char uuid16_buffer[5]; +const char * UUID::getUuidString() const { + // TODO: fix uuid_has_bluetooth_prefix call to use const + if (uuid_has_bluetooth_prefix((uint8_t*)uuid)) { + sprintf(uuid16_buffer, "%04x", (uint16_t) big_endian_read_32(uuid, 0)); + return uuid16_buffer; + } else { + // TODO: fix uuid128_to_str + return uuid128_to_str((uint8_t*)uuid); + } +} + +const char * UUID::getUuid128String() const { + return uuid128_to_str((uint8_t*)uuid); +} + +bool UUID::matches(UUID *other) const { + return memcmp(this->uuid, other->uuid, 16) == 0; +} + + +// BD_ADDR class +BD_ADDR::BD_ADDR(void) { +} + +BD_ADDR::BD_ADDR(const char * address_string, BD_ADDR_TYPE address_type) : address_type(address_type) { + (void) address_string; + // TODO: implement + // log_error("BD_ADDR::BD_ADDR(const char *, BD_ADDR_TYPE) not implemented yet!"); +} + +BD_ADDR::BD_ADDR(const uint8_t address[6], BD_ADDR_TYPE address_type) : address_type(address_type) { + memcpy(this->address, address, 6); +} + +const uint8_t * BD_ADDR::getAddress(void) { + return address; +} + +const char * BD_ADDR::getAddressString(void) { + return bd_addr_to_str(address); +} + +BD_ADDR_TYPE BD_ADDR::getAddressType(void) { + return address_type; +} + + +BLEAdvertisement::BLEAdvertisement(uint8_t * event_packet) : + advertising_event_type(event_packet[2]), + rssi(event_packet[10]), + data_length(event_packet[11]), + iBeacon_UUID(NULL) { + bd_addr_t addr; + reverse_bd_addr(&event_packet[4], addr); + bd_addr = BD_ADDR(addr, (BD_ADDR_TYPE)event_packet[3]); + memcpy(data, &event_packet[12], LE_ADVERTISING_DATA_SIZE); +} + +BLEAdvertisement::~BLEAdvertisement() { + if (iBeacon_UUID) { + delete (iBeacon_UUID); + } +} + +const uint8_t * BLEAdvertisement::getAdvData(void) { + return data; +} + +BD_ADDR * BLEAdvertisement::getBdAddr(void) { + return &bd_addr; +} + +int BLEAdvertisement::getRssi(void) { + return rssi > 127 ? rssi - 256 : rssi; +} + + +bool BLEAdvertisement::containsService(UUID * service) { + return ad_data_contains_uuid128(data_length, data, (uint8_t*) service->getUuid()); +} + +bool BLEAdvertisement::nameHasPrefix(const char * name_prefix) { + ad_context_t context; + int name_prefix_len = strlen(name_prefix); + for (ad_iterator_init(&context, data_length, data) ; ad_iterator_has_more(&context) ; ad_iterator_next(&context)) { + uint8_t data_type = ad_iterator_get_data_type(&context); + uint8_t data_len = ad_iterator_get_data_len(&context); + const uint8_t * data = ad_iterator_get_data(&context); + int compare_len = name_prefix_len; + switch (data_type) { + case 8: // shortented local name + case 9: // complete local name + if (compare_len > data_len) { + compare_len = data_len; + } + if (strncmp(name_prefix, (const char*) data, compare_len) == 0) { + return true; + } + break; + default: + break; + } + } + return false; +}; + +bool BLEAdvertisement::isIBeacon(void) { + return ((memcmp(iBeaconAdvertisement01, data, sizeof(iBeaconAdvertisement01)) == 0) + && (memcmp(iBeaconAdvertisement38, &data[3], sizeof(iBeaconAdvertisement38)) == 0)); +} + +const UUID * BLEAdvertisement::getIBeaconUUID(void) { + if (!iBeacon_UUID) { + iBeacon_UUID = new UUID(&data[9]); + } + return iBeacon_UUID; +}; +uint16_t BLEAdvertisement::getIBeaconMajorID(void) { + return big_endian_read_16(data, 25); +}; +uint16_t BLEAdvertisement::getIBecaonMinorID(void) { + return big_endian_read_16(data, 27); +}; +uint8_t BLEAdvertisement::getiBeaconMeasuredPower(void) { + return data[29]; +} + + +BLECharacteristic::BLECharacteristic(void) { +} + +BLECharacteristic::BLECharacteristic(gatt_client_characteristic_t characteristic) + : characteristic(characteristic), uuid(characteristic.uuid128) { +} + +const UUID * BLECharacteristic::getUUID(void) { + return &uuid; +} + +bool BLECharacteristic::matches(UUID * uuid) { + return this->uuid.matches(uuid); +} + +bool BLECharacteristic::isValueHandle(uint16_t value_handle) { + return characteristic.value_handle == value_handle; +} + +const gatt_client_characteristic_t * BLECharacteristic::getCharacteristic(void) { + return &characteristic; +} + + +BLEService::BLEService(void) { +} + +BLEService::BLEService(gatt_client_service_t service) + : service(service), uuid(service.uuid128) { +} + +const UUID * BLEService::getUUID(void) { + return &uuid; +} + +bool BLEService::matches(UUID * uuid) { + return this->uuid.matches(uuid); +} + +const gatt_client_service_t * BLEService::getService(void) { + return &service; +} + +// discovery of services and characteristics +BLEDevice::BLEDevice(void) { +} +BLEDevice::BLEDevice(hci_con_handle_t handle) + : handle(handle) { +} +uint16_t BLEDevice::getHandle(void) { + return handle; +} +int BLEDevice::discoverGATTServices(void) { + return BTstack.discoverGATTServices(this); +} +int BLEDevice::discoverCharacteristicsForService(BLEService * service) { + return BTstack.discoverCharacteristicsForService(this, service); +} +int BLEDevice::readCharacteristic(BLECharacteristic * characteristic) { + return BTstack.readCharacteristic(this, characteristic); +} +int BLEDevice::writeCharacteristic(BLECharacteristic * characteristic, uint8_t * data, uint16_t size) { + return BTstack.writeCharacteristic(this, characteristic, data, size); +} +int BLEDevice::writeCharacteristicWithoutResponse(BLECharacteristic * characteristic, uint8_t * data, uint16_t size) { + return BTstack.writeCharacteristicWithoutResponse(this, characteristic, data, size); +} +int BLEDevice::subscribeForNotifications(BLECharacteristic * characteristic) { + return BTstack.subscribeForNotifications(this, characteristic); +} +int BLEDevice::unsubscribeFromNotifications(BLECharacteristic * characteristic) { + return BTstack.unsubscribeFromNotifications(this, characteristic); +} +int BLEDevice::subscribeForIndications(BLECharacteristic * characteristic) { + return BTstack.subscribeForIndications(this, characteristic); +} +int BLEDevice::unsubscribeFromIndications(BLECharacteristic * characteristic) { + return BTstack.unsubscribeFromIndications(this, characteristic); +} + + + +static uint16_t (*gattReadCallback)(uint16_t characteristic_id, uint8_t * buffer, uint16_t buffer_size); +static int (*gattWriteCallback)(uint16_t characteristic_id, uint8_t *buffer, uint16_t buffer_size); + +// ATT Client Read Callback for Dynamic Data +// - if buffer == NULL, don't copy data, just return size of value +// - if buffer != NULL, copy data and return number bytes copied +// @param offset defines start of attribute value +static uint16_t att_read_callback(hci_con_handle_t con_handle, uint16_t att_handle, uint16_t offset, uint8_t * buffer, uint16_t buffer_size) { + (void) con_handle; + (void) offset; + if (gattReadCallback) { + return gattReadCallback(att_handle, buffer, buffer_size); + } + return 0; +} +/* LISTING_END */ + + +/* + @section ATT Write + + @text The only valid ATT write in this example is to the Client Characteristic Configuration, which configures notification + and indication. If the ATT handle matches the client configuration handle, the new configuration value is stored and used + in the heartbeat handler to decide if a new value should be sent. See Listing attWrite. +*/ + +/* LISTING_START(attWrite): ATT Write */ +static int att_write_callback(hci_con_handle_t con_handle, uint16_t att_handle, uint16_t transaction_mode, uint16_t offset, uint8_t *buffer, uint16_t buffer_size) { + (void) con_handle; + (void) transaction_mode; + (void) offset; + if (gattWriteCallback) { + gattWriteCallback(att_handle, buffer, buffer_size); + } + return 0; +} + + + +BTstackManager::BTstackManager(void) { + // client_packet_handler = NULL; + have_custom_addr = false; + // reset handler + bleAdvertismentCallback = NULL; + bleDeviceConnectedCallback = NULL; + bleDeviceDisconnectedCallback = NULL; + gattServiceDiscoveredCallback = NULL; + gattCharacteristicDiscoveredCallback = NULL; + gattCharacteristicNotificationCallback = NULL; + + att_db_util_init(); + + // disable LOG_INFO messages + hci_dump_enable_log_level(HCI_DUMP_LOG_LEVEL_INFO, 0); + +#ifdef __AVR__ + // configure stdout to go via Serial + fdev_setup_stream(&uartout, uart_putchar, NULL, _FDEV_SETUP_WRITE); + stdout = &uartout; +#endif +} + +void BTstackManager::setBLEAdvertisementCallback(void (*callback)(BLEAdvertisement * bleAdvertisement)) { + bleAdvertismentCallback = callback; +} +void BTstackManager::setBLEDeviceConnectedCallback(void (*callback)(BLEStatus status, BLEDevice * device)) { + bleDeviceConnectedCallback = callback; +} +void BTstackManager::setBLEDeviceDisconnectedCallback(void (*callback)(BLEDevice * device)) { + bleDeviceDisconnectedCallback = callback; +} +void BTstackManager::setGATTServiceDiscoveredCallback(void (*callback)(BLEStatus status, BLEDevice * device, BLEService * bleService)) { + gattServiceDiscoveredCallback = callback; +} +void BTstackManager::setGATTCharacteristicDiscoveredCallback(void (*callback)(BLEStatus status, BLEDevice * device, BLECharacteristic * characteristic)) { + gattCharacteristicDiscoveredCallback = callback; +} +void BTstackManager::setGATTCharacteristicNotificationCallback(void (*callback)(BLEDevice * device, uint16_t value_handle, uint8_t* value, uint16_t length)) { + gattCharacteristicNotificationCallback = callback; +} +void BTstackManager::setGATTCharacteristicIndicationCallback(void (*callback)(BLEDevice * device, uint16_t value_handle, uint8_t* value, uint16_t length)) { + gattCharacteristicIndicationCallback = callback; +} +void BTstackManager::setGATTCharacteristicReadCallback(void (*callback)(BLEStatus status, BLEDevice * device, uint8_t * value, uint16_t length)) { + gattCharacteristicReadCallback = callback; +} +void BTstackManager::setGATTCharacteristicWrittenCallback(void (*callback)(BLEStatus status, BLEDevice * device)) { + gattCharacteristicWrittenCallback = callback; +} +void BTstackManager::setGATTCharacteristicSubscribedCallback(void (*callback)(BLEStatus status, BLEDevice * device)) { + gattCharacteristicSubscribedCallback = callback; +} +void BTstackManager::setGATTCharacteristicUnsubscribedCallback(void (*callback)(BLEStatus status, BLEDevice * device)) { + gattCharacteristicUnsubscribedCallback = callback; +} + +int BTstackManager::discoverGATTServices(BLEDevice * device) { + gattAction = gattActionServiceQuery; + return gatt_client_discover_primary_services(gatt_client_callback, device->getHandle()); +} +int BTstackManager::discoverCharacteristicsForService(BLEDevice * device, BLEService * service) { + gattAction = gattActionCharacteristicQuery; + return gatt_client_discover_characteristics_for_service(gatt_client_callback, device->getHandle(), (gatt_client_service_t*) service->getService()); +} +int BTstackManager::readCharacteristic(BLEDevice * device, BLECharacteristic * characteristic) { + return gatt_client_read_value_of_characteristic(gatt_client_callback, device->getHandle(), (gatt_client_characteristic_t*) characteristic->getCharacteristic()); +} +int BTstackManager::writeCharacteristic(BLEDevice * device, BLECharacteristic * characteristic, uint8_t * data, uint16_t size) { + gattAction = gattActionWrite; + return gatt_client_write_value_of_characteristic(gatt_client_callback, device->getHandle(), characteristic->getCharacteristic()->value_handle, + size, data); +} +int BTstackManager::writeCharacteristicWithoutResponse(BLEDevice * device, BLECharacteristic * characteristic, uint8_t * data, uint16_t size) { + return gatt_client_write_value_of_characteristic_without_response(device->getHandle(), characteristic->getCharacteristic()->value_handle, + size, data); +} +int BTstackManager::subscribeForNotifications(BLEDevice * device, BLECharacteristic * characteristic) { + gattAction = gattActionSubscribe; + return gatt_client_write_client_characteristic_configuration(gatt_client_callback, device->getHandle(), (gatt_client_characteristic_t*) characteristic->getCharacteristic(), + GATT_CLIENT_CHARACTERISTICS_CONFIGURATION_NOTIFICATION); +} +int BTstackManager::subscribeForIndications(BLEDevice * device, BLECharacteristic * characteristic) { + gattAction = gattActionSubscribe; + return gatt_client_write_client_characteristic_configuration(gatt_client_callback, device->getHandle(), (gatt_client_characteristic_t*) characteristic->getCharacteristic(), + GATT_CLIENT_CHARACTERISTICS_CONFIGURATION_INDICATION); +} +int BTstackManager::unsubscribeFromNotifications(BLEDevice * device, BLECharacteristic * characteristic) { + gattAction = gattActionUnsubscribe; + return gatt_client_write_client_characteristic_configuration(gatt_client_callback, device->getHandle(), (gatt_client_characteristic_t*) characteristic->getCharacteristic(), + GATT_CLIENT_CHARACTERISTICS_CONFIGURATION_NONE); +} +int BTstackManager::unsubscribeFromIndications(BLEDevice * device, BLECharacteristic * characteristic) { + gattAction = gattActionUnsubscribe; + return gatt_client_write_client_characteristic_configuration(gatt_client_callback, device->getHandle(), (gatt_client_characteristic_t*) characteristic->getCharacteristic(), + GATT_CLIENT_CHARACTERISTICS_CONFIGURATION_NONE); +} +void BTstackManager::bleConnect(BLEAdvertisement * advertisement, int timeout_ms) { + bleConnect(advertisement->getBdAddr(), timeout_ms); +} +void BTstackManager::bleConnect(BD_ADDR * address, int timeout_ms) { + bleConnect(address->getAddressType(), address->getAddress(), timeout_ms); +} +void BTstackManager::bleConnect(BD_ADDR_TYPE address_type, const char * address, int timeout_ms) { + (void) address_type; + (void) address; + (void) timeout_ms; + // TODO: implement + // log_error("BTstackManager::bleConnect(BD_ADDR_TYPE address_type, const char * address, int timeout_ms) not implemented"); +} +void BTstackManager::bleConnect(BD_ADDR_TYPE address_type, const uint8_t address[6], int timeout_ms) { + gap_connect((uint8_t*)address, (bd_addr_type_t) address_type); + if (!timeout_ms) { + return; + } + btstack_run_loop_set_timer(&connection_timer, timeout_ms); + btstack_run_loop_set_timer_handler(&connection_timer, connection_timeout_handler); + btstack_run_loop_add_timer(&connection_timer); +} + +void BTstackManager::bleDisconnect(BLEDevice * device) { + btstack_run_loop_remove_timer(&connection_timer); + gap_disconnect(device->getHandle()); +} + +void BTstackManager::setPublicBdAddr(bd_addr_t addr) { + have_custom_addr = true; + memcpy(public_bd_addr, addr, 6); +} + +void bluetooth_hardware_error(uint8_t error) { + printf("Bluetooth Hardware Error event 0x%02x. Restarting...\n\n\n", error); +#ifdef __AVR__ + wdt_enable(WDTO_15MS); + // wait for watchdog to trigger +#endif + +#ifdef __arm__ + // NVIC_SystemReset(); +#endif + while (1); +} +#if 0 +static hci_transport_config_uart_t config = { + HCI_TRANSPORT_CONFIG_UART, + 115200, + 0, // main baudrate + 1, // flow control + NULL, +}; +#endif +static btstack_packet_callback_registration_t hci_event_callback_registration; + +void BTstackManager::setup(void) { + + //#ifdef PIN_LED + // pinMode(PIN_LED, OUTPUT); + //#endif + + // printf("BTstackManager::setup()\n"); +#if 0 + btstack_memory_init(); + btstack_run_loop_init(btstack_run_loop_embedded_get_instance()); + + const hci_transport_t * transport = hci_transport_h4_instance(btstack_uart_block_embedded_instance()); + hci_init(transport, (void*) &config); + hci_set_chipset(btstack_chipset_em9301_instance()); + + if (have_custom_addr) { + hci_set_bd_addr(public_bd_addr); + } + + hci_set_hardware_error_callback(&bluetooth_hardware_error); + +#endif + // inform about BTstack state + hci_event_callback_registration.callback = &packet_handler; + hci_add_event_handler(&hci_event_callback_registration); + l2cap_init(); + + // setup central device db + le_device_db_init(); + + sm_init(); + + att_server_init(att_db_util_get_address(), att_read_callback, att_write_callback); + + gatt_client_init(); + + // setup advertisements params + uint16_t adv_int_min = 0x0030; + uint16_t adv_int_max = 0x0030; + uint8_t adv_type = 0; + bd_addr_t null_addr; + memset(null_addr, 0, 6); + gap_advertisements_set_params(adv_int_min, adv_int_max, adv_type, 0, null_addr, 0x07, 0x00); + + // setup advertisements data + int pos = 0; + const uint8_t flags[] = { 0x02, 0x01, 0x02 }; + memcpy(&adv_data[pos], flags, sizeof(flags)); + pos += sizeof(flags); + const char * name = "BTstack LE Shield"; + adv_data[pos++] = strlen(name) + 1; + adv_data[pos++] = 0x09; + memcpy(&adv_data[pos], name, strlen(name)); + pos += strlen(name); + adv_data_len = pos; + gap_advertisements_set_data(adv_data_len, adv_data); + + // turn on! + btstack_state = 0; + hci_power_control(HCI_POWER_ON); +} + +void BTstackManager::enablePacketLogger(void) { + hci_dump_init(hci_dump_embedded_stdout_get_instance()); +} + +void BTstackManager::enableDebugLogger() { + // enable LOG_INFO messages + hci_dump_enable_log_level(HCI_DUMP_LOG_LEVEL_INFO, 1); +} + + +void BTstackManager::loop(void) { + // process data from/to Bluetooth module + // hal_uart_dma_process(); + // BTstack Run Loop + // btstack_run_loop_embedded_execute_once(); +} + +void BTstackManager::bleStartScanning(void) { + // printf("Start scanning\n"); + gap_start_scan(); +} +void BTstackManager::bleStopScanning(void) { + gap_stop_scan(); +} + +void BTstackManager::setGATTCharacteristicRead(uint16_t (*cb)(uint16_t characteristic_id, uint8_t * buffer, uint16_t buffer_size)) { + gattReadCallback = cb; +} +void BTstackManager::setGATTCharacteristicWrite(int (*cb)(uint16_t characteristic_id, uint8_t *buffer, uint16_t buffer_size)) { + gattWriteCallback = cb; +} +void BTstackManager::addGATTService(UUID * uuid) { + att_db_util_add_service_uuid128((uint8_t*)uuid->getUuid()); +} +uint16_t BTstackManager::addGATTCharacteristic(UUID * uuid, uint16_t flags, const char * text) { + return att_db_util_add_characteristic_uuid128((uint8_t*)uuid->getUuid(), flags, ATT_SECURITY_NONE, ATT_SECURITY_NONE, (uint8_t*)text, strlen(text)); +} +uint16_t BTstackManager::addGATTCharacteristic(UUID * uuid, uint16_t flags, uint8_t * data, uint16_t data_len) { + return att_db_util_add_characteristic_uuid128((uint8_t*)uuid->getUuid(), flags, ATT_SECURITY_NONE, ATT_SECURITY_NONE, data, data_len); +} +uint16_t BTstackManager::addGATTCharacteristicDynamic(UUID * uuid, uint16_t flags, uint16_t characteristic_id) { + (void) characteristic_id; + return att_db_util_add_characteristic_uuid128((uint8_t*)uuid->getUuid(), flags | ATT_PROPERTY_DYNAMIC, ATT_SECURITY_NONE, ATT_SECURITY_NONE, NULL, 0); +} +void BTstackManager::setAdvData(uint16_t adv_data_len, const uint8_t * adv_data) { + gap_advertisements_set_data(adv_data_len, (uint8_t*) adv_data); +} +void BTstackManager::startAdvertising() { + gap_advertisements_enable(1); +} +void BTstackManager::stopAdvertising() { + gap_advertisements_enable(0); +} +void BTstackManager::iBeaconConfigure(UUID * uuid, uint16_t major_id, uint16_t minor_id, uint8_t measured_power) { + memcpy(adv_data, iBeaconAdvertisement01, sizeof(iBeaconAdvertisement01)); + adv_data[2] = 0x06; + memcpy(&adv_data[3], iBeaconAdvertisement38, sizeof(iBeaconAdvertisement38)); + memcpy(&adv_data[9], uuid->getUuid(), 16); + big_endian_store_16(adv_data, 25, major_id); + big_endian_store_16(adv_data, 27, minor_id); + adv_data[29] = measured_power; + adv_data_len = 30; + gap_advertisements_set_data(adv_data_len, adv_data); +} +// 02 01 06 1A FF 4C 00 02 15 -- F8 97 17 7B AE E8 47 67 8E CC CC 69 4F D5 FC EE -- 12 67 00 02 00 00 +// 02 01 06 1a ff 4c 00 02 15 -- FB 0B 57 A2 82 28 44 CD 91 3A 94 A1 22 BA 12 06 -- 00 01 00 02 D1 00 + + +BTstackManager BTstack; + diff --git a/libraries/BTstackLib/src/BTstackLib.h b/libraries/BTstackLib/src/BTstackLib.h new file mode 100644 index 000000000..39542352a --- /dev/null +++ b/libraries/BTstackLib/src/BTstackLib.h @@ -0,0 +1,204 @@ +/** + Arduino Wrapper for BTstack +*/ + +#include <_needsbt.h> + +#ifndef __ARDUINO_BTSTACK_H +#define __ARDUINO_BTSTACK_H + +#if defined __cplusplus +extern "C" { +#endif + +#include "ble/att_db.h" +#include "btstack_util.h" +#include "ble/gatt_client.h" +#include "hci.h" +#include + + typedef enum BLEStatus { + BLE_STATUS_OK, + BLE_STATUS_DONE, // e.g. for service or characteristic discovery done + BLE_STATUS_CONNECTION_TIMEOUT, + BLE_STATUS_CONNECTION_ERROR, + BLE_STATUS_OTHER_ERROR + } BLEStatus; + + typedef void (*btstack_packet_handler_t)(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size); + + class UUID { + private: + uint8_t uuid[16]; + public: + UUID(); + UUID(const uint8_t uuid[16]); + UUID(const char * uuidStr); + const char * getUuidString() const; + const char * getUuid128String() const; + const uint8_t * getUuid(void) const; + bool matches(UUID *uuid) const; + }; + + typedef enum BD_ADDR_TYPE { + PUBLIC_ADDRESS = 0, + PRIVAT_ADDRESS + } BD_ADDR_TYPE; + + class BD_ADDR { + private: + uint8_t address[6]; + BD_ADDR_TYPE address_type; + public: + BD_ADDR(); + BD_ADDR(const char * address_string, BD_ADDR_TYPE address_type = PUBLIC_ADDRESS); + BD_ADDR(const uint8_t address[6], BD_ADDR_TYPE address_type = PUBLIC_ADDRESS); + const uint8_t * getAddress(); + const char * getAddressString(); + BD_ADDR_TYPE getAddressType(); + }; + + class BLEAdvertisement { + private: + uint8_t advertising_event_type; + uint8_t rssi; + uint8_t data_length; + uint8_t data[10 + LE_ADVERTISING_DATA_SIZE]; + BD_ADDR bd_addr; + UUID * iBeacon_UUID; + public: + BLEAdvertisement(uint8_t * event_packet); + ~BLEAdvertisement(); + BD_ADDR * getBdAddr(); + BD_ADDR_TYPE getBdAddrType(); + int getRssi(); + bool containsService(UUID * service); + bool nameHasPrefix(const char * namePrefix); + const uint8_t * getAdvData(); + bool isIBeacon(); + const UUID * getIBeaconUUID(); + uint16_t getIBeaconMajorID(); + uint16_t getIBecaonMinorID(); + uint8_t getiBeaconMeasuredPower(); + }; + + class BLECharacteristic { + private: + gatt_client_characteristic_t characteristic; + UUID uuid; + public: + BLECharacteristic(); + BLECharacteristic(gatt_client_characteristic_t characteristic); + const UUID * getUUID(); + bool matches(UUID * uuid); + bool isValueHandle(uint16_t value_handle); + const gatt_client_characteristic_t * getCharacteristic(); + }; + + class BLEService { + private: + gatt_client_service_t service; + UUID uuid; + public: + BLEService(); + BLEService(gatt_client_service_t service); + const UUID * getUUID(); + bool matches(UUID * uuid); + const gatt_client_service_t * getService(); + }; + + class BLEDevice { + private: + hci_con_handle_t handle; + public: + BLEDevice(); + BLEDevice(hci_con_handle_t handle); + hci_con_handle_t getHandle(); + + // discovery of services and characteristics + int discoverGATTServices(); + int discoverCharacteristicsForService(BLEService * service); + + // read/write + int readCharacteristic(BLECharacteristic * characteristic); + int writeCharacteristic(BLECharacteristic * characteristic, uint8_t * data, uint16_t size); + int writeCharacteristicWithoutResponse(BLECharacteristic * characteristic, uint8_t * data, uint16_t size); + + // subscribe/unsubscribe + int subscribeForNotifications(BLECharacteristic * characteristic); + int unsubscribeFromNotifications(BLECharacteristic * characteristic); + int subscribeForIndications(BLECharacteristic * characteristic); + int unsubscribeFromIndications(BLECharacteristic * characteristic); + }; + + class BTstackManager { + public: + BTstackManager(void); + void setup(void); + void loop(void); + + void setPublicBdAddr(bd_addr_t addr); + void enablePacketLogger(); + void enableDebugLogger(); + + void setAdvData(uint16_t size, const uint8_t * data); + void iBeaconConfigure(UUID * uuid, uint16_t major_id, uint16_t minor_id, uint8_t measured_power = 0xc6); + void startAdvertising(); + void stopAdvertising(); + + void bleStartScanning(); + void bleStopScanning(); + + // connection management + void bleConnect(BD_ADDR_TYPE address_type, const uint8_t address[6], int timeout_ms); + void bleConnect(BD_ADDR_TYPE address_type, const char * address, int timeout_ms); + void bleConnect(BD_ADDR * address, int timeout_ms); + void bleConnect(BLEAdvertisement * advertisement, int timeout_ms); + void bleDisconnect(BLEDevice * device); + + // discovery of services and characteristics + int discoverGATTServices(BLEDevice * device); + int discoverCharacteristicsForService(BLEDevice * peripheral, BLEService * service); + + // read/write + int readCharacteristic(BLEDevice * device, BLECharacteristic * characteristic); + int writeCharacteristic(BLEDevice * device, BLECharacteristic * characteristic, uint8_t * data, uint16_t size); + int writeCharacteristicWithoutResponse(BLEDevice * device, BLECharacteristic * characteristic, uint8_t * data, uint16_t size); + + // subscribe/unsubscribe notification and indications + int subscribeForNotifications(BLEDevice * device, BLECharacteristic * characteristic); + int unsubscribeFromNotifications(BLEDevice * device, BLECharacteristic * characteristic); + int subscribeForIndications(BLEDevice * device, BLECharacteristic * characteristic); + int unsubscribeFromIndications(BLEDevice * device, BLECharacteristic * characteristic); + + // Callbacks + void setBLEAdvertisementCallback(void (*)(BLEAdvertisement * bleAdvertisement)); + void setBLEDeviceConnectedCallback(void (*)(BLEStatus status, BLEDevice * device)); + void setBLEDeviceDisconnectedCallback(void (*)(BLEDevice * device)); + void setGATTServiceDiscoveredCallback(void (*)(BLEStatus status, BLEDevice * device, BLEService * bleService)); + void setGATTCharacteristicDiscoveredCallback(void (*)(BLEStatus status, BLEDevice * device, BLECharacteristic * characteristic)); + void setGATTCharacteristicReadCallback(void (*)(BLEStatus status, BLEDevice * device, uint8_t * value, uint16_t length)); + void setGATTCharacteristicNotificationCallback(void (*)(BLEDevice * device, uint16_t value_handle, uint8_t* value, uint16_t length)); + void setGATTCharacteristicIndicationCallback(void (*)(BLEDevice * device, uint16_t value_handle, uint8_t* value, uint16_t length)); + void setGATTDoneCallback(void (*)(BLEStatus status, BLEDevice * device)); + + void setGATTCharacteristicWrittenCallback(void (*)(BLEStatus status, BLEDevice * device)); + void setGATTCharacteristicSubscribedCallback(void (*)(BLEStatus status, BLEDevice * device)); + void setGATTCharacteristicUnsubscribedCallback(void (*)(BLEStatus status, BLEDevice * device)); + + void setGATTCharacteristicRead(uint16_t (*)(uint16_t characteristic_id, uint8_t * buffer, uint16_t buffer_size)); + void setGATTCharacteristicWrite(int (*)(uint16_t characteristic_id, uint8_t *buffer, uint16_t buffer_size)); + + void addGATTService(UUID * uuid); + uint16_t addGATTCharacteristic(UUID * uuid, uint16_t flags, const char * text); + uint16_t addGATTCharacteristic(UUID * uuid, uint16_t flags, uint8_t * data, uint16_t data_len); + uint16_t addGATTCharacteristicDynamic(UUID * uuid, uint16_t flags, uint16_t characteristic_id); + }; + + extern BTstackManager BTstack; + +#if defined __cplusplus +} +#endif + +#endif // __ARDUINO_BTSTACK_H diff --git a/libraries/DNSServer/examples/CaptivePortal/CaptivePortal.ino b/libraries/DNSServer/examples/CaptivePortal/CaptivePortal.ino new file mode 100644 index 000000000..6774fffa1 --- /dev/null +++ b/libraries/DNSServer/examples/CaptivePortal/CaptivePortal.ino @@ -0,0 +1,36 @@ +#include +#include +#include + +const byte DNS_PORT = 53; +IPAddress apIP(172, 217, 28, 1); +DNSServer dnsServer; +WebServer webServer(80); + +String responseHTML = "" + "" + "" + "CaptivePortal" + "

Hello World!

This is a captive portal example." + " All requests will be redirected here.

"; + +void setup() { + WiFi.mode(WIFI_AP); + WiFi.softAPConfig(apIP, apIP, IPAddress(255, 255, 255, 0)); + WiFi.softAP("DNSServer CaptivePortal example"); + + // if DNSServer is started with "*" for domain name, it will reply with + // provided IP to all DNS request + dnsServer.start(DNS_PORT, "*", apIP); + + // replay to all requests with same HTML + webServer.onNotFound([]() { + webServer.send(200, "text/html", responseHTML); + }); + webServer.begin(); +} + +void loop() { + dnsServer.processNextRequest(); + webServer.handleClient(); +} diff --git a/libraries/DNSServer/examples/CaptivePortalAdvanced/CaptivePortalAdvanced.ino b/libraries/DNSServer/examples/CaptivePortalAdvanced/CaptivePortalAdvanced.ino new file mode 100644 index 000000000..74e9990f0 --- /dev/null +++ b/libraries/DNSServer/examples/CaptivePortalAdvanced/CaptivePortalAdvanced.ino @@ -0,0 +1,145 @@ +#include +#include +#include +#include +#include +#include + +/* + This example serves a "hello world" on a WLAN and a SoftAP at the same time. + The SoftAP allow you to configure WLAN parameters at run time. They are not setup in the sketch but saved on EEPROM. + + Connect your computer or cell phone to wifi network pico_ap with password 12345678. A popup may appear and it allow you to go to WLAN config. If it does not then navigate to http://192.168.4.1/wifi and config it there. + Then wait for the module to connect to your wifi and take note of the WLAN IP it got. Then you can disconnect from pico_ap and return to your regular WLAN. + + Now the Pico is in your network. You can reach it through http://192.168.x.x/ (the IP you took note of) or maybe at http://picow.local too. + + This is a captive portal because through the softAP it will redirect any http request to http://192.168.4.1/ +*/ + +/* Set these to your desired softAP credentials. They are not configurable at runtime */ +#ifndef APSSID +#define APSSID "pico_ap" +#define APPSK "12345678" +#endif + +const char *softAP_ssid = APSSID; +const char *softAP_password = APPSK; + +/* hostname for mDNS. Should work at least on windows. Try http://picow.local */ +const char *myHostname = "picow"; + +/* Don't set this wifi credentials. They are configurated at runtime and stored on EEPROM */ +char ssid[33] = ""; +char password[65] = ""; + +// DNS server +const byte DNS_PORT = 53; +DNSServer dnsServer; + +// Web server +WebServer server(80); + +/* Soft AP network parameters */ +IPAddress apIP(172, 217, 28, 1); +IPAddress netMsk(255, 255, 255, 0); + + +/** Should I connect to WLAN asap? */ +boolean connect; + +/** Last time I tried to connect to WLAN */ +unsigned long lastConnectTry = 0; + +/** Current WLAN status */ +unsigned int status = WL_IDLE_STATUS; + +void setup() { + delay(1000); + Serial.begin(115200); + Serial.println(); + Serial.println("Configuring access point..."); + /* You can remove the password parameter if you want the AP to be open. */ + WiFi.softAPConfig(apIP, apIP, netMsk); + WiFi.softAP(softAP_ssid, softAP_password); + delay(500); // Without delay I've seen the IP address blank + Serial.print("AP IP address: "); + Serial.println(WiFi.softAPIP()); + + /* Setup the DNS server redirecting all the domains to the apIP */ + dnsServer.setErrorReplyCode(DNSReplyCode::NoError); + dnsServer.start(DNS_PORT, "*", apIP); + + /* Setup web pages: root, wifi config pages, SO captive portal detectors and not found. */ + server.on("/", handleRoot); + server.on("/wifi", handleWifi); + server.on("/wifisave", handleWifiSave); + server.on("/generate_204", handleRoot); // Android captive portal. Maybe not needed. Might be handled by notFound handler. + server.on("/fwlink", handleRoot); // Microsoft captive portal. Maybe not needed. Might be handled by notFound handler. + server.onNotFound(handleNotFound); + server.begin(); // Web server start + Serial.println("HTTP server started"); + //loadCredentials(); // Load WLAN credentials from network + ssid[0] = 0; + password[0] = 0; + connect = strlen(ssid) > 0; // Request WLAN connect if there is a SSID +} + +void connectWifi() { + Serial.println("Connecting as wifi client..."); + WiFi.disconnect(); + WiFi.end(); + WiFi.begin(ssid, password); + int connRes = WiFi.waitForConnectResult(); + Serial.print("connRes: "); + Serial.println(connRes); +} + +void loop() { + if (connect) { + Serial.println("Connect requested"); + connect = false; + connectWifi(); + lastConnectTry = millis(); + } + { + unsigned int s = WiFi.status(); + if (s == 0 && millis() > (lastConnectTry + 60000)) { + /* If WLAN disconnected and idle try to connect */ + /* Don't set retry time too low as retry interfere the softAP operation */ + connect = true; + } + if (status != s) { // WLAN status change + Serial.print("Status: "); + Serial.println(s); + status = s; + if (s == WL_CONNECTED) { + /* Just connected to WLAN */ + Serial.println(""); + Serial.print("Connected to "); + Serial.println(ssid); + Serial.print("IP address: "); + Serial.println(WiFi.localIP()); + + // Setup MDNS responder + if (!MDNS.begin(myHostname)) { + Serial.println("Error setting up MDNS responder!"); + } else { + Serial.println("mDNS responder started"); + // Add service to MDNS-SD + MDNS.addService("http", "tcp", 80); + } + } else if (s == WL_NO_SSID_AVAIL) { + WiFi.disconnect(); + } + } + if (s == WL_CONNECTED) { + MDNS.update(); + } + } + // Do work: + // DNS + dnsServer.processNextRequest(); + // HTTP + server.handleClient(); +} diff --git a/libraries/DNSServer/examples/CaptivePortalAdvanced/credentials.ino b/libraries/DNSServer/examples/CaptivePortalAdvanced/credentials.ino new file mode 100644 index 000000000..a5e76fb7c --- /dev/null +++ b/libraries/DNSServer/examples/CaptivePortalAdvanced/credentials.ino @@ -0,0 +1,27 @@ +/** Load WLAN credentials from EEPROM */ +void loadCredentials() { + EEPROM.begin(512); + EEPROM.get(0, ssid); + EEPROM.get(0 + sizeof(ssid), password); + char ok[2 + 1]; + EEPROM.get(0 + sizeof(ssid) + sizeof(password), ok); + EEPROM.end(); + if (String(ok) != String("OK")) { + ssid[0] = 0; + password[0] = 0; + } + Serial.println("Recovered credentials:"); + Serial.println(ssid); + Serial.println(strlen(password) > 0 ? "********" : ""); +} + +/** Store WLAN credentials to EEPROM */ +void saveCredentials() { + EEPROM.begin(512); + EEPROM.put(0, ssid); + EEPROM.put(0 + sizeof(ssid), password); + char ok[2 + 1] = "OK"; + EEPROM.put(0 + sizeof(ssid) + sizeof(password), ok); + EEPROM.commit(); + EEPROM.end(); +} diff --git a/libraries/DNSServer/examples/CaptivePortalAdvanced/handleHttp.ino b/libraries/DNSServer/examples/CaptivePortalAdvanced/handleHttp.ino new file mode 100644 index 000000000..fda749006 --- /dev/null +++ b/libraries/DNSServer/examples/CaptivePortalAdvanced/handleHttp.ino @@ -0,0 +1,126 @@ +/** Handle root or redirect to captive portal */ +void handleRoot() { + if (captivePortal()) { // If caprive portal redirect instead of displaying the page. + return; + } + server.sendHeader("Cache-Control", "no-cache, no-store, must-revalidate"); + server.sendHeader("Pragma", "no-cache"); + server.sendHeader("Expires", "-1"); + + String Page; + Page += F("" + "" + "CaptivePortal" + "

HELLO WORLD!!

"); + if (server.client().localIP() == apIP) { + Page += String(F("

You are connected through the soft AP: ")) + softAP_ssid + F("

"); + } else { + Page += String(F("

You are connected through the wifi network: ")) + ssid + F("

"); + } + Page += F("

You may want to config the wifi connection.

" + ""); + + server.send(200, "text/html", Page); +} + +/** Redirect to captive portal if we got a request for another domain. Return true in that case so the page handler do not try to handle the request again. */ +boolean captivePortal() { + if (!isIp(server.hostHeader()) && server.hostHeader() != (String(myHostname) + ".local")) { + Serial.println("Request redirected to captive portal"); + server.sendHeader("Location", String("http://") + toStringIp(server.client().localIP()), true); + server.send(302, "text/plain", ""); // Empty content inhibits Content-length header so we have to close the socket ourselves. + server.client().stop(); // Stop is needed because we sent no content length + return true; + } + return false; +} + +/** Wifi config page handler */ +void handleWifi() { + server.sendHeader("Cache-Control", "no-cache, no-store, must-revalidate"); + server.sendHeader("Pragma", "no-cache"); + server.sendHeader("Expires", "-1"); + + String Page; + Page += F("" + "" + "CaptivePortal" + "

Wifi config

"); + if (server.client().localIP() == apIP) { + Page += String(F("

You are connected through the soft AP: ")) + softAP_ssid + F("

"); + } else { + Page += String(F("

You are connected through the wifi network: ")) + ssid + F("

"); + } + Page += String(F("\r\n
" + "" + "" + "" + "
SoftAP config
SSID ")) + + String(softAP_ssid) + F("
IP ") + + toStringIp(WiFi.softAPIP()) + F("
" + "\r\n
" + "" + "" + "" + "
WLAN config
SSID ") + + String(ssid) + F("
IP ") + + toStringIp(WiFi.localIP()) + F("
" + "\r\n
" + ""); + Serial.println("scan start"); + int n = WiFi.scanNetworks(); + Serial.println("scan done"); + if (n > 0) { + for (int i = 0; i < n; i++) { + Page += String(F("\r\n"); + } + } else { + Page += F(""); + } + Page += F("
WLAN list (refresh if any missing)
SSID ")) + WiFi.SSID(i) + ((WiFi.encryptionType(i) == ENC_TYPE_NONE) ? F(" ") : F(" *")) + F(" (") + WiFi.RSSI(i) + F(")
No WLAN found
" + "\r\n

Connect to network:

" + "" + "
" + "
" + "

You may want to return to the home page.

" + ""); + server.send(200, "text/html", Page); + server.client().stop(); // Stop is needed because we sent no content length +} + +/** Handle the WLAN save form and redirect to WLAN config page again */ +void handleWifiSave() { + Serial.println("wifi save"); + server.arg("n").toCharArray(ssid, sizeof(ssid) - 1); + server.arg("p").toCharArray(password, sizeof(password) - 1); + server.sendHeader("Location", "wifi", true); + server.sendHeader("Cache-Control", "no-cache, no-store, must-revalidate"); + server.sendHeader("Pragma", "no-cache"); + server.sendHeader("Expires", "-1"); + server.send(302, "text/plain", ""); // Empty content inhibits Content-length header so we have to close the socket ourselves. + server.client().stop(); // Stop is needed because we sent no content length + saveCredentials(); + connect = strlen(ssid) > 0; // Request WLAN connect with new credentials if there is a SSID +} + +void handleNotFound() { + if (captivePortal()) { // If caprive portal redirect instead of displaying the error page. + return; + } + String message = F("File Not Found\n\n"); + message += F("URI: "); + message += server.uri(); + message += F("\nMethod: "); + message += (server.method() == HTTP_GET) ? "GET" : "POST"; + message += F("\nArguments: "); + message += server.args(); + message += F("\n"); + + for (uint8_t i = 0; i < server.args(); i++) { + message += String(F(" ")) + server.argName(i) + F(": ") + server.arg(i) + F("\n"); + } + server.sendHeader("Cache-Control", "no-cache, no-store, must-revalidate"); + server.sendHeader("Pragma", "no-cache"); + server.sendHeader("Expires", "-1"); + server.send(404, "text/plain", message); +} diff --git a/libraries/DNSServer/examples/CaptivePortalAdvanced/tools.ino b/libraries/DNSServer/examples/CaptivePortalAdvanced/tools.ino new file mode 100644 index 000000000..6ed7b05b7 --- /dev/null +++ b/libraries/DNSServer/examples/CaptivePortalAdvanced/tools.ino @@ -0,0 +1,20 @@ +/** Is this an IP? */ +boolean isIp(String str) { + for (size_t i = 0; i < str.length(); i++) { + int c = str.charAt(i); + if (c != '.' && (c < '0' || c > '9')) { + return false; + } + } + return true; +} + +/** IP to String? */ +String toStringIp(IPAddress ip) { + String res = ""; + for (int i = 0; i < 3; i++) { + res += String((ip >> (8 * i)) & 0xFF) + "."; + } + res += String(((ip >> 8 * 3)) & 0xFF); + return res; +} diff --git a/libraries/DNSServer/examples/DNSServer/DNSServer.ino b/libraries/DNSServer/examples/DNSServer/DNSServer.ino new file mode 100644 index 000000000..ee7236799 --- /dev/null +++ b/libraries/DNSServer/examples/DNSServer/DNSServer.ino @@ -0,0 +1,41 @@ +#include +#include +#include + +const byte DNS_PORT = 53; +IPAddress apIP(172, 217, 28, 1); +DNSServer dnsServer; +WebServer webServer(80); + +void setup() { + WiFi.mode(WIFI_AP); + WiFi.softAPConfig(apIP, apIP, IPAddress(255, 255, 255, 0)); + WiFi.softAP("picow", "12345678"); + + // modify TTL associated with the domain name (in seconds) + // default is 60 seconds + dnsServer.setTTL(300); + // set which return code will be used for all other domains (e.g. sending + // ServerFailure instead of NonExistentDomain will reduce number of queries + // sent by clients) + // default is DNSReplyCode::NonExistentDomain + dnsServer.setErrorReplyCode(DNSReplyCode::ServerFailure); + + // start DNS server for a specific domain name + dnsServer.start(DNS_PORT, "www.example.com", apIP); + + // simple HTTP server to see that DNS server is working + webServer.onNotFound([]() { + String message = "Hello World!\n\n"; + message += "URI: "; + message += webServer.uri(); + + webServer.send(200, "text/plain", message); + }); + webServer.begin(); +} + +void loop() { + dnsServer.processNextRequest(); + webServer.handleClient(); +} diff --git a/libraries/DNSServer/keywords.txt b/libraries/DNSServer/keywords.txt new file mode 100644 index 000000000..80f03834c --- /dev/null +++ b/libraries/DNSServer/keywords.txt @@ -0,0 +1,45 @@ +####################################### +# Syntax Coloring Map For DNSServer +####################################### + +####################################### +# Library (KEYWORD3) +####################################### + +DNSServer KEYWORD3 RESERVED_WORD + +####################################### +# Datatypes (KEYWORD1) +####################################### + +DNSReplyCode KEYWORD1 DATA_TYPE +DNSHeader KEYWORD1 DATA_TYPE +DNSServer KEYWORD1 DATA_TYPE + +####################################### +# Methods and Functions (KEYWORD2) +####################################### + +processNextRequest KEYWORD2 +setErrorReplyCode KEYWORD2 +setTTL KEYWORD2 +start KEYWORD2 +stop KEYWORD2 + +####################################### +# Constants (LITERAL1) +####################################### + +DNS_QR_QUERY LITERAL1 RESERVED_WORD_2 +DNS_QR_RESPONSE LITERAL1 RESERVED_WORD_2 +DNS_OPCODE_QUERY LITERAL1 RESERVED_WORD_2 +MAX_DNSNAME_LENGTH LITERAL1 RESERVED_WORD_2 +NoError LITERAL1 RESERVED_WORD_2 +FormError LITERAL1 RESERVED_WORD_2 +ServerFailure LITERAL1 RESERVED_WORD_2 +NonExistentDomain LITERAL1 RESERVED_WORD_2 +NotImplemented LITERAL1 RESERVED_WORD_2 +Refused LITERAL1 RESERVED_WORD_2 +YXDomain LITERAL1 RESERVED_WORD_2 +YXRRSet LITERAL1 RESERVED_WORD_2 +NXRRSet LITERAL1 RESERVED_WORD_2 diff --git a/libraries/DNSServer/library.properties b/libraries/DNSServer/library.properties new file mode 100644 index 000000000..1b999d80a --- /dev/null +++ b/libraries/DNSServer/library.properties @@ -0,0 +1,10 @@ +name=DNSServer +version=1.1.1 +author=Kristijan Novoselić +maintainer=Earle F. Philhower, III +sentence=A simple DNS server for ESP8266, ported to the Pico +paragraph=This library implements a simple DNS server. +category=Communication +url= +architectures=rp2040 +dot_a_linkage=true diff --git a/libraries/DNSServer/src/DNSServer.cpp b/libraries/DNSServer/src/DNSServer.cpp new file mode 100644 index 000000000..f18d3076f --- /dev/null +++ b/libraries/DNSServer/src/DNSServer.cpp @@ -0,0 +1,456 @@ +/* + DNSServer.cpp - Simple DNS server for the Pico + Modified 2022 Earle F. Philhower, III. All rights reserved. + + Taken from the ESP8266 core libraries, (c) various authors. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include "WiFi.h" +#include "DNSServer.h" +#include +#include + +#ifdef DEBUG_ESP_PORT +#define CONSOLE DEBUG_ESP_PORT +#else +#define CONSOLE Serial +#endif + +#define _PRINTF(a, ...) printf(PSTR(a), ##__VA_ARGS__) +#define _PRINT(a) print(String(F(a))) +#define _PRINTLN(a) println(String(F(a))) +#define _PRINTLN2(a, b) println(String(F(a)) + b ) + +#define CONSOLE_PRINTF CONSOLE._PRINTF +#define CONSOLE_PRINT CONSOLE._PRINT +#define CONSOLE_PRINTLN CONSOLE._PRINTLN +#define CONSOLE_PRINTLN2 CONSOLE._PRINTLN2 + + +#ifdef DEBUG_DNSSERVER +#define DEBUG_PRINTF CONSOLE_PRINTF +#define DEBUG_PRINT CONSOLE_PRINT +#define DEBUG_PRINTLN CONSOLE_PRINTLN +#define DEBUG_PRINTLN2 CONSOLE_PRINTLN2 +#define DBGLOG_FAIL LOG_FAIL + +#define DEBUG_(...) do { (__VA_ARGS__); } while(false) +#define DEBUG__(...) __VA_ARGS__ +#define LOG_FAIL(a, fmt, ...) do { if (!(a)) { CONSOLE.printf( PSTR(fmt " line: %d, function: %s\r\n"), ##__VA_ARGS__, __LINE__, __FUNCTION__ ); } } while(false); + +#else +#define DEBUG_PRINTF(...) do { } while(false) +#define DEBUG_PRINT(...) do { } while(false) +#define DEBUG_PRINTLN(...) do { } while(false) +#define DEBUG_PRINTLN2(...) do { } while(false) +#define DEBUG_(...) do { } while(false) +#define DEBUG__(...) do { } while(false) +#define LOG_FAIL(a, ...) do { a; } while(false) +#define DBGLOG_FAIL(...) do { } while(false) +#endif + +#define DNS_HEADER_SIZE sizeof(DNSHeader) + +// Want to keep IDs unique across restarts and continquious +static uint32_t _ids __attribute__((section(".noinit"))); + +DNSServer::DNSServer() { + // I have observed that using 0 for captive and non-zero (600) when + // forwarding, will help Android devices recognize the change in connectivity. + // They will then report connected. + _ttl = lwip_htonl(60); + + srand(rp2040.getCycleCount()); + _ids = random(0, (1UL << 16) - 1); + + _errorReplyCode = DNSReplyCode::NonExistentDomain; +} + +void DNSServer::disableForwarder(const String &domainName, bool freeResources) { + _forwarder = false; + if (domainName != "") { + _domainName = domainName; + downcaseAndRemoveWwwPrefix(_domainName); + } + if (freeResources) { + _dns = (uint32_t)0; + if (_que) { + _que = nullptr; + DEBUG_PRINTF("from stop, deleted _que\r\n"); + DEBUG_(({ + if (_que_ov) { + DEBUG_PRINTLN2("DNS forwarder que overflow or no reply to request: ", (_que_ov)); + } + if (_que_drop) { + DEBUG_PRINTLN2("DNS forwarder que wrapped, reply dropped: ", (_que_drop)); + } + })); + } + } +} + +bool DNSServer::enableForwarder(const String &domainName, const IPAddress &dns) { + disableForwarder(domainName, false); // Just happens to have the same logic needed here. + + if (dns.isSet()) { + _dns = dns; + } + + if (_dns.isSet()) { + if (!_que) { + _que = std::unique_ptr (new (std::nothrow) DNSS_REQUESTER[kDNSSQueSize]); + DEBUG_PRINTF("Created new _que\r\n"); + if (_que) { + for (size_t i = 0; i < kDNSSQueSize; i++) { + _que[i].ip = 0; + } + DEBUG_((_que_ov = 0)); + DEBUG_((_que_drop = 0)); + } + } + if (_que) { + _forwarder = true; + } + } + return _forwarder; +} + +bool DNSServer::start(const uint16_t &port, const String &domainName, + const IPAddress &resolvedIP, const IPAddress &dns) { + _port = (port) ? port : IANA_DNS_PORT; + + _resolvedIP[0] = resolvedIP[0]; + _resolvedIP[1] = resolvedIP[1]; + _resolvedIP[2] = resolvedIP[2]; + _resolvedIP[3] = resolvedIP[3]; + + if (!enableForwarder(domainName, dns) && (dns.isSet() || _dns.isSet())) { + return false; + } + + return _udp.begin(_port) == 1; +} + +void DNSServer::setErrorReplyCode(const DNSReplyCode &replyCode) { + _errorReplyCode = replyCode; +} + +void DNSServer::setTTL(const uint32_t &ttl) { + _ttl = lwip_htonl(ttl); +} + +uint32_t DNSServer::getTTL() { + return lwip_ntohl(_ttl); +} + +void DNSServer::stop() { + _udp.stop(); + disableForwarder("", true); +} + +void DNSServer::downcaseAndRemoveWwwPrefix(String &domainName) { + domainName.toLowerCase(); + if (domainName.startsWith("www.")) { + domainName.remove(0, 4); + } +} + +void DNSServer::forwardReply(uint8_t *buffer, size_t length) { + if (!_forwarder || !_que) { + return; + } + DNSHeader *dnsHeader = (DNSHeader *)buffer; + uint16_t id = dnsHeader->ID; + // if (kDNSSQueSize <= (uint16_t)((uint16_t)_ids - id)) { + if ((uint16_t)kDNSSQueSize <= (uint16_t)_ids - id) { + DEBUG_((++_que_drop)); + DEBUG_PRINTLN2("Forward reply ID: 0x", (String(id, HEX) + F(" dropped!"))); + return; + } + size_t i = id & (kDNSSQueSize - 1); + + // Drop duplicate packets + if (0 == _que[i].ip) { + DEBUG_PRINTLN2("Duplicate reply dropped ID: 0x", String(id, HEX)); + return; + } + dnsHeader->ID = _que[i].id; + _udp.beginPacket(_que[i].ip, _que[i].port); + _udp.write(buffer, length); + _udp.endPacket(); + DEBUG_PRINTLN2("Forward reply ID: 0x", (String(id, HEX) + F(" to ") + IPAddress(_que[i].ip).toString())); + _que[i].ip = 0; // This gets used to detect duplicate packets and overflow +} + +void DNSServer::forwardRequest(uint8_t *buffer, size_t length) { + if (!_forwarder || !_dns.isSet() || !_que) { + return; + } + DNSHeader *dnsHeader = (DNSHeader *)buffer; + ++_ids; + size_t i = _ids & (kDNSSQueSize - 1); + DEBUG_(({ + if (0 != _que[i].ip) { + ++_que_ov; + } + })); + _que[i].ip = _udp.remoteIP(); + _que[i].port = _udp.remotePort(); + _que[i].id = dnsHeader->ID; + dnsHeader->ID = (uint16_t)_ids; + _udp.beginPacket(_dns, IANA_DNS_PORT); + _udp.write(buffer, length); + _udp.endPacket(); + DEBUG_PRINTLN2("Forward request ID: 0x", (String(dnsHeader->ID, HEX) + F(" to ") + _dns.toString())); +} + +bool DNSServer::respondToRequest(uint8_t *buffer, size_t length) { + DNSHeader *dnsHeader; + uint8_t *query, *start; + const char *matchString; + size_t remaining, labelLength, queryLength; + uint16_t qtype, qclass; + + dnsHeader = (DNSHeader *)buffer; + + // Must be a query for us to do anything with it + if (dnsHeader->QR != DNS_QR_QUERY) { + return false; + } + + // If operation is anything other than query, we don't do it + if (dnsHeader->OPCode != DNS_OPCODE_QUERY) { + replyWithError(dnsHeader, DNSReplyCode::NotImplemented); + return false; + } + + // Only support requests containing single queries - everything else + // is badly defined + if (dnsHeader->QDCount != lwip_htons(1)) { + replyWithError(dnsHeader, DNSReplyCode::FormError); + return false; + } + + // We must return a FormError in the case of a non-zero ARCount to + // be minimally compatible with EDNS resolvers + if (dnsHeader->ANCount != 0 || dnsHeader->NSCount != 0 + || dnsHeader->ARCount != 0) { + replyWithError(dnsHeader, DNSReplyCode::FormError); + return false; + } + + // Even if we're not going to use the query, we need to parse it + // so we can check the address type that's being queried + + query = start = buffer + DNS_HEADER_SIZE; + remaining = length - DNS_HEADER_SIZE; + while (remaining != 0 && *start != 0) { + labelLength = *start; + if (labelLength + 1 > remaining) { + replyWithError(dnsHeader, DNSReplyCode::FormError); + return false; + } + remaining -= (labelLength + 1); + start += (labelLength + 1); + } + + // 1 octet labelLength, 2 octet qtype, 2 octet qclass + if (remaining < 5) { + replyWithError(dnsHeader, DNSReplyCode::FormError); + return false; + } + + start += 1; // Skip the 0 length label that we found above + + memcpy(&qtype, start, sizeof(qtype)); + start += 2; + memcpy(&qclass, start, sizeof(qclass)); + start += 2; + + queryLength = start - query; + + if (qclass != lwip_htons(DNS_QCLASS_ANY) + && qclass != lwip_htons(DNS_QCLASS_IN)) { + replyWithError(dnsHeader, DNSReplyCode::NonExistentDomain, query, queryLength); + return false; + } + + if (qtype != lwip_htons(DNS_QTYPE_A) + && qtype != lwip_htons(DNS_QTYPE_ANY)) { + replyWithError(dnsHeader, DNSReplyCode::NonExistentDomain, query, queryLength); + return false; + } + + // If we have no domain name configured, just return an error + if (_domainName == "") { + if (_forwarder) { + return true; + } else { + replyWithError(dnsHeader, _errorReplyCode, query, queryLength); + return false; + } + } + + // If we're running with a wildcard we can just return a result now + if (_domainName == "*") { + DEBUG_PRINTF("dnsServer - replyWithIP\r\n"); + replyWithIP(dnsHeader, query, queryLength); + return false; + } + + matchString = _domainName.c_str(); + + start = query; + + // If there's a leading 'www', skip it + if (*start == 3 && strncasecmp("www", (char *) start + 1, 3) == 0) { + start += 4; + } + + while (*start != 0) { + labelLength = *start; + start += 1; + while (labelLength > 0) { + if (tolower(*start) != *matchString) { + if (_forwarder) { + return true; + } else { + replyWithError(dnsHeader, _errorReplyCode, query, queryLength); + return false; + } + } + ++start; + ++matchString; + --labelLength; + } + if (*start == 0 && *matchString == '\0') { + replyWithIP(dnsHeader, query, queryLength); + return false; + } + + if (*matchString != '.') { + replyWithError(dnsHeader, _errorReplyCode, query, queryLength); + return false; + } + ++matchString; + } + + replyWithError(dnsHeader, _errorReplyCode, query, queryLength); + return false; +} + +void DNSServer::processNextRequest() { + size_t currentPacketSize; + + currentPacketSize = _udp.parsePacket(); + if (currentPacketSize == 0) { + return; + } + + // The DNS RFC requires that DNS packets be less than 512 bytes in size, + // so just discard them if they are larger + if (currentPacketSize > MAX_DNS_PACKETSIZE) { + return; + } + + // If the packet size is smaller than the DNS header, then someone is + // messing with us + if (currentPacketSize < DNS_HEADER_SIZE) { + return; + } + + std::unique_ptr buffer(new (std::nothrow) uint8_t[currentPacketSize]); + if (buffer == nullptr) { + return; + } + + _udp.read(buffer.get(), currentPacketSize); + if (_dns.isSet() && _udp.remoteIP() == _dns) { + // _forwarder may have been set to false; however, for now allow in-flight + // replies to finish. //?? + forwardReply(buffer.get(), currentPacketSize); + } else if (respondToRequest(buffer.get(), currentPacketSize)) { + forwardRequest(buffer.get(), currentPacketSize); + } +} + +void DNSServer::writeNBOShort(uint16_t value) { + _udp.write((unsigned char *)&value, 2); +} + +void DNSServer::replyWithIP(DNSHeader *dnsHeader, + unsigned char * query, + size_t queryLength) { + uint16_t value; + + dnsHeader->QR = DNS_QR_RESPONSE; + dnsHeader->QDCount = lwip_htons(1); + dnsHeader->ANCount = lwip_htons(1); + dnsHeader->NSCount = 0; + dnsHeader->ARCount = 0; + + _udp.beginPacket(_udp.remoteIP(), _udp.remotePort()); + _udp.write((unsigned char *) dnsHeader, sizeof(DNSHeader)); + _udp.write(query, queryLength); + + // Rather than restate the name here, we use a pointer to the name contained + // in the query section. Pointers have the top two bits set. + value = 0xC000 | DNS_HEADER_SIZE; + writeNBOShort(lwip_htons(value)); + + // Answer is type A (an IPv4 address) + writeNBOShort(lwip_htons(DNS_QTYPE_A)); + + // Answer is in the Internet Class + writeNBOShort(lwip_htons(DNS_QCLASS_IN)); + + // Output TTL (already NBO) + _udp.write((unsigned char*)&_ttl, 4); + + // Length of RData is 4 bytes (because, in this case, RData is IPv4) + writeNBOShort(lwip_htons(sizeof(_resolvedIP))); + _udp.write(_resolvedIP, sizeof(_resolvedIP)); + _udp.endPacket(); +} + +void DNSServer::replyWithError(DNSHeader *dnsHeader, + DNSReplyCode rcode, + unsigned char *query, + size_t queryLength) { + dnsHeader->QR = DNS_QR_RESPONSE; + dnsHeader->RCode = (unsigned char) rcode; + if (query) { + dnsHeader->QDCount = lwip_htons(1); + } else { + dnsHeader->QDCount = 0; + } + dnsHeader->ANCount = 0; + dnsHeader->NSCount = 0; + dnsHeader->ARCount = 0; + + _udp.beginPacket(_udp.remoteIP(), _udp.remotePort()); + _udp.write((unsigned char *)dnsHeader, sizeof(DNSHeader)); + if (query != nullptr) { + _udp.write(query, queryLength); + } + _udp.endPacket(); +} + +void DNSServer::replyWithError(DNSHeader *dnsHeader, + DNSReplyCode rcode) { + replyWithError(dnsHeader, rcode, nullptr, 0); +} diff --git a/libraries/DNSServer/src/DNSServer.h b/libraries/DNSServer/src/DNSServer.h new file mode 100644 index 000000000..c5f597441 --- /dev/null +++ b/libraries/DNSServer/src/DNSServer.h @@ -0,0 +1,170 @@ +/* + DNSServer.h - Simple DNS server for the Pico + Modified 2022 Earle F. Philhower, III. All rights reserved. + + Taken from the ESP8266 core libraries, (c) various authors. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#pragma once + +#include +#include + +// #define DEBUG_DNSSERVER + +// https://www.iana.org/assignments/service-names-port-numbers/service-names-port-numbers.txt +#ifndef IANA_DNS_PORT +#define IANA_DNS_PORT 53 // AKA domain +constexpr inline uint16_t kIanaDnsPort = IANA_DNS_PORT; +#endif + +#define DNS_QR_QUERY 0 +#define DNS_QR_RESPONSE 1 +#define DNS_OPCODE_QUERY 0 + +#define DNS_QCLASS_IN 1 +#define DNS_QCLASS_ANY 255 + +#define DNS_QTYPE_A 1 +#define DNS_QTYPE_ANY 255 + +#define MAX_DNSNAME_LENGTH 253 +#define MAX_DNS_PACKETSIZE 512 + +enum class DNSReplyCode { + NoError = 0, + FormError = 1, + ServerFailure = 2, + NonExistentDomain = 3, + NotImplemented = 4, + Refused = 5, + YXDomain = 6, + YXRRSet = 7, + NXRRSet = 8 +}; + +struct DNSHeader { + uint16_t ID; // identification number + unsigned char RD : 1; // recursion desired + unsigned char TC : 1; // truncated message + unsigned char AA : 1; // authoritative answer + unsigned char OPCode : 4; // message_type + unsigned char QR : 1; // query/response flag + unsigned char RCode : 4; // response code + unsigned char Z : 3; // its z! reserved + unsigned char RA : 1; // recursion available + uint16_t QDCount; // number of question entries + uint16_t ANCount; // number of answer entries + uint16_t NSCount; // number of authority entries + uint16_t ARCount; // number of resource entries +}; + +constexpr inline size_t kDNSSQueSizeAddrBits = 3; // The number of bits used to address que entries +constexpr inline size_t kDNSSQueSize = (1UL << (kDNSSQueSizeAddrBits)); + +struct DNSS_REQUESTER { + uint32_t ip; + uint16_t port; + uint16_t id; +}; + +class DNSServer { +public: + DNSServer(); + ~DNSServer() { + stop(); + }; + /* + If specified, `enableForwarder` will update the `domainName` that is used + to match DNS request to this AP's IP Address. A non-matching request will + be forwarded to the DNS server specified by `dns`. + + Returns `true` on success. + + Returns `false`, + when forwarding `dns` is not set, or + unable to allocate resources for managing the DNS forward function. + */ + bool enableForwarder(const String &domainName = String(""), const IPAddress &dns = (uint32_t)0); + /* + `disableForwarder` will stop forwarding DNS requests. If specified, + updates the `domainName` that is matched for returning this AP's IP Address. + Optionally, resources used for the DNS forward function can be freed. + */ + void disableForwarder(const String &domainName = String(""), bool freeResources = false); + bool isForwarding() { + return _forwarder && _dns.isSet(); + } + void setDNS(const IPAddress& dns) { + _dns = dns; + } + IPAddress getDNS() { + return _dns; + } + bool isDNSSet() { + return _dns.isSet(); + } + + void processNextRequest(); + void setErrorReplyCode(const DNSReplyCode &replyCode); + void setTTL(const uint32_t &ttl); + uint32_t getTTL(); + String getDomainName() { + return _domainName; + } + + // Returns true if successful, false if there are no sockets available + bool start(const uint16_t &port, + const String &domainName, + const IPAddress &resolvedIP, + const IPAddress &dns = (uint32_t)0); + // stops the DNS server + void stop(); + +private: + WiFiUDP _udp; + String _domainName; + IPAddress _dns; + std::unique_ptr _que; + uint32_t _ttl; +#ifdef DEBUG_DNSSERVER + // There are 2 possibilities for overflow: + // 1) we have more than kDNSSQueSize request already outstanding. + // 2) we have request that never received a reply. + uint32_t _que_ov; + uint32_t _que_drop; +#endif + DNSReplyCode _errorReplyCode; + bool _forwarder; + unsigned char _resolvedIP[4]; + uint16_t _port; + + void downcaseAndRemoveWwwPrefix(String &domainName); + void replyWithIP(DNSHeader *dnsHeader, + unsigned char * query, + size_t queryLength); + void replyWithError(DNSHeader *dnsHeader, + DNSReplyCode rcode, + unsigned char *query, + size_t queryLength); + void replyWithError(DNSHeader *dnsHeader, + DNSReplyCode rcode); + bool respondToRequest(uint8_t *buffer, size_t length); + void forwardRequest(uint8_t *buffer, size_t length); + void forwardReply(uint8_t *buffer, size_t length); + void writeNBOShort(uint16_t value); +}; diff --git a/libraries/EEPROM/EEPROM.cpp b/libraries/EEPROM/src/EEPROM.cpp similarity index 97% rename from libraries/EEPROM/EEPROM.cpp rename to libraries/EEPROM/src/EEPROM.cpp index 95e7d0c13..06e6a9cc2 100644 --- a/libraries/EEPROM/EEPROM.cpp +++ b/libraries/EEPROM/src/EEPROM.cpp @@ -45,7 +45,7 @@ void EEPROMClass::begin(size_t size) { size = 4096; } - _size = (size + 255) & (~255); // Flash writes limited to 256 byte boundaries + size = (size + 255) & (~255); // Flash writes limited to 256 byte boundaries // In case begin() is called a 2nd+ time, don't reallocate if size is the same if (_data && size != _size) { @@ -55,6 +55,8 @@ void EEPROMClass::begin(size_t size) { _data = new uint8_t[size]; } + _size = size; + memcpy(_data, _sector, _size); _dirty = false; //make sure dirty is cleared in case begin() is called 2nd+ time diff --git a/libraries/EEPROM/EEPROM.h b/libraries/EEPROM/src/EEPROM.h similarity index 94% rename from libraries/EEPROM/EEPROM.h rename to libraries/EEPROM/src/EEPROM.h index 21d8be91a..fbf3e8eff 100644 --- a/libraries/EEPROM/EEPROM.h +++ b/libraries/EEPROM/src/EEPROM.h @@ -19,8 +19,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ -#ifndef EEPROM_h -#define EEPROM_h +#pragma once #include #include @@ -62,6 +61,10 @@ class EEPROMClass { return t; } + template + const T &update(int const address, const T &t) { + return put(address, t); + } size_t length() { return _size; } @@ -81,6 +84,3 @@ class EEPROMClass { }; extern EEPROMClass EEPROM; - -#endif - diff --git a/libraries/FreeRTOS/examples/Multicore-FreeRTOS/Multicore-FreeRTOS.ino b/libraries/FreeRTOS/examples/Multicore-FreeRTOS/Multicore-FreeRTOS.ino index aeaaf1fe4..b96ac9802 100644 --- a/libraries/FreeRTOS/examples/Multicore-FreeRTOS/Multicore-FreeRTOS.ino +++ b/libraries/FreeRTOS/examples/Multicore-FreeRTOS/Multicore-FreeRTOS.ino @@ -30,7 +30,7 @@ void ps() { Serial.printf("# Tasks: %d\n", tasks); Serial.println("ID, NAME, STATE, PRIO, CYCLES"); for (int i=0; i < tasks; i++) { - Serial.printf("%d: %-16s %-10s %d %lu\n", i, pxTaskStatusArray[i].pcTaskName, eTaskStateName[pxTaskStatusArray[i].eCurrentState], pxTaskStatusArray[i].uxCurrentPriority, pxTaskStatusArray[i].ulRunTimeCounter); + Serial.printf("%d: %-16s %-10s %d %lu\n", i, pxTaskStatusArray[i].pcTaskName, eTaskStateName[pxTaskStatusArray[i].eCurrentState], (int)pxTaskStatusArray[i].uxCurrentPriority, pxTaskStatusArray[i].ulRunTimeCounter); } delete[] pxTaskStatusArray; } diff --git a/libraries/FreeRTOS/examples/StaticMulticore-FreeRTOS/StaticMulticore-FreeRTOS.ino b/libraries/FreeRTOS/examples/StaticMulticore-FreeRTOS/StaticMulticore-FreeRTOS.ino new file mode 100644 index 000000000..7656dd212 --- /dev/null +++ b/libraries/FreeRTOS/examples/StaticMulticore-FreeRTOS/StaticMulticore-FreeRTOS.ino @@ -0,0 +1,80 @@ +/* The code in this example is mostly derived from the official FreeRTOS + * code examples. + * + * For more information on static allocation and to read the original + * code visit the following links: + * https://www.freertos.org/Static_Vs_Dynamic_Memory_Allocation.html + * https://www.freertos.org/xTaskCreateStatic.html + * https://www.freertos.org/xSemaphoreCreateMutexStatic.html + */ + +#include +#include +#include + +#define SERIAL_PORT Serial1 +#define BLINK_ON_TIME 250 +#define BLINK_OFF_TIME 500 + +/* Dimensions of the buffer that the task being created will use as its stack. + NOTE: This is the number of words the stack will hold, not the number of + bytes. For example, if each stack item is 32-bits, and this is set to 100, + then 400 bytes (100 * 32-bits) will be allocated. */ +#define STACK_SIZE 200 + +/* Structure that will hold the TCB of the task being created. */ +StaticTask_t xTaskBuffer_A; +StaticTask_t xTaskBuffer_B; + +/* Buffer that the task being created will use as its stack. Note this is + an array of StackType_t variables. The size of StackType_t is dependent on + the RTOS port. */ +StackType_t xStack_A[ STACK_SIZE ]; +StackType_t xStack_B[ STACK_SIZE ]; + +SemaphoreHandle_t xSemaphore = NULL; +StaticSemaphore_t xMutexBuffer; + +void setup() { + SERIAL_PORT.begin(115200); + pinMode(LED_BUILTIN, OUTPUT); + + /* Create a mutex semaphore without using any dynamic memory + allocation. The mutex's data structures will be saved into + the xMutexBuffer variable. */ + xSemaphore = xSemaphoreCreateMutexStatic( &xMutexBuffer ); + + xTaskCreateStatic(led_ON, "led_ON", STACK_SIZE, NULL, configMAX_PRIORITIES - 1, xStack_A, &xTaskBuffer_A); + xTaskCreateStatic(led_OFF, "led_OFF", STACK_SIZE, NULL, configMAX_PRIORITIES - 1, xStack_B, &xTaskBuffer_B); +} + +void led_ON(void *pvParameters) +{ + (void) pvParameters; + while (1) + { + xSemaphoreTake( xSemaphore, ( TickType_t ) portMAX_DELAY ); + SERIAL_PORT.println("LED ON!"); + digitalWrite(LED_BUILTIN, HIGH); + delay(BLINK_ON_TIME); + xSemaphoreGive( xSemaphore ); + } +} + +void led_OFF(void *pvParameters) +{ + (void) pvParameters; + while (1) + { + xSemaphoreTake( xSemaphore, ( TickType_t ) portMAX_DELAY ); + SERIAL_PORT.println("LED OFF!"); + digitalWrite(LED_BUILTIN, LOW); + delay(BLINK_OFF_TIME); + xSemaphoreGive( xSemaphore ); + } +} + +void loop() { + SERIAL_PORT.println("Hello!"); + delay(1000); +} diff --git a/libraries/FreeRTOS/examples/Stress.ino b/libraries/FreeRTOS/examples/Stress.ino new file mode 100644 index 000000000..6c9414bc2 --- /dev/null +++ b/libraries/FreeRTOS/examples/Stress.ino @@ -0,0 +1,319 @@ +// FreeRTOS system call/mutex stress test + +#include +#include +#include +#include +#define DELAY 1 +#define SERIAL_DEBUG Serial1 +#define STACK_SIZE 512 +#define CORE_0 (1 << 0) +#define CORE_1 (1 << 1) + +void semphrTakeConditional(bool useMutexOn, SemaphoreHandle_t xSemaphore); +void semphrGiveConditional(bool useMutexOn, SemaphoreHandle_t xSemaphore); + +/* + I want to keep the possibility of using different and independent + mutexes for each of the functions that operate on the heap. + + If you want to enable the use of these mutexes remove the defines + on lines 30 and 31 and enable the their initialization in setup() +*/ +SemaphoreHandle_t xSemaphoreMalloc = NULL; +// SemaphoreHandle_t xSemaphoreRealloc = NULL; +// SemaphoreHandle_t xSemaphoreFree = NULL; + +/* + A lazy way to use the same mutex for malloc, realloc and free + in order to bring us back to the same situation as the MCVE + posted here: https://github.com/earlephilhower/arduino-pico/issues/795#issuecomment-1227122082 +*/ +#define xSemaphoreRealloc xSemaphoreMalloc +#define xSemaphoreFree xSemaphoreMalloc + +const bool useMutexOnMalloc = false; +const bool useMutexOnRealloc = false; +const bool useMutexOnFree = false; + +/* + Enabling this, a realloc will be performed and the string "_realloc" + will be concateneted to *tmp +*/ +const bool tryRealloc = true; + +TaskHandle_t loop2Handle = NULL; +TaskHandle_t loop3Handle = NULL; +TaskHandle_t loop4Handle = NULL; +TaskHandle_t loop5Handle = NULL; +TaskHandle_t loop6Handle = NULL; +TaskHandle_t loop7Handle = NULL; + +void loop2(void *pvPramaters); +void loop3(void *pvPramaters); +void loop4(void *pvPramaters); +void loop5(void *pvPramaters); +void loop6(void *pvPramaters); +void loop7(void *pvPramaters); + +void setup() +{ + pinMode(LED_BUILTIN, OUTPUT); + + xSemaphoreMalloc = xSemaphoreCreateMutex(); + // xSemaphoreRealloc = xSemaphoreCreateMutex(); + // xSemaphoreFree = xSemaphoreCreateMutex(); + + xTaskCreate(loop2, "loop2", STACK_SIZE, NULL, 1, &loop2Handle); + vTaskCoreAffinitySet(loop2Handle, CORE_0); + xTaskCreate(loop3, "loop3", STACK_SIZE, NULL, 1, &loop3Handle); + vTaskCoreAffinitySet(loop3Handle, CORE_1); + xTaskCreate(loop4, "loop4", STACK_SIZE, NULL, 1, &loop4Handle); + vTaskCoreAffinitySet(loop4Handle, CORE_0); + xTaskCreate(loop5, "loop5", STACK_SIZE, NULL, 1, &loop5Handle); + vTaskCoreAffinitySet(loop5Handle, CORE_1); + // xTaskCreate(loop6, "loop6", STACK_SIZE, NULL, 1, &loop6Handle); + // vTaskCoreAffinitySet(loop6Handle, CORE_0); + // xTaskCreate(loop7, "loop7", STACK_SIZE, NULL, 1, &loop7Handle); + // vTaskCoreAffinitySet(loop7Handle, CORE_1); +} +static int _loop[8]; + +void loop() +{ + while (1) + { + _loop[0]++; + digitalWrite(LED_BUILTIN, HIGH); + delay(500); + digitalWrite(LED_BUILTIN, LOW); + delay(500); + for (int i=0; i<8; i++) Serial.printf("%d ", _loop[i]); + Serial.println(""); + } +} + +void loop1() +{ + while (1) + { + _loop[1]++; + char *tmp; + + semphrTakeConditional(useMutexOnMalloc, xSemaphoreMalloc); + tmp = (char *)malloc(10 * sizeof(char)); + semphrGiveConditional(useMutexOnMalloc, xSemaphoreMalloc); + + strcpy(tmp, "foo"); + + if (tryRealloc) + { + semphrTakeConditional(useMutexOnRealloc, xSemaphoreRealloc); + tmp = (char *)realloc(tmp, 20 * sizeof(char)); + semphrGiveConditional(useMutexOnRealloc, xSemaphoreRealloc); + strcat(tmp, "_realloc"); + } + + semphrTakeConditional(useMutexOnFree, xSemaphoreFree); + free(tmp); + semphrGiveConditional(useMutexOnFree, xSemaphoreFree); + + delay(DELAY); + } +} + +void loop2(void *pvPramaters) +{ + (void) pvPramaters; + while (1) + { + _loop[2]++; + char *tmp; + + semphrTakeConditional(useMutexOnMalloc, xSemaphoreMalloc); + tmp = (char *)malloc(10 * sizeof(char)); + semphrGiveConditional(useMutexOnMalloc, xSemaphoreMalloc); + + strcpy(tmp, "bar"); + + if (tryRealloc) + { + semphrTakeConditional(useMutexOnRealloc, xSemaphoreRealloc); + tmp = (char *)realloc(tmp, 20 * sizeof(char)); + semphrGiveConditional(useMutexOnRealloc, xSemaphoreRealloc); + strcat(tmp, "_realloc"); + } + + semphrTakeConditional(useMutexOnFree, xSemaphoreFree); + free(tmp); + semphrGiveConditional(useMutexOnFree, xSemaphoreFree); + + delay(DELAY); + } +} + +void loop3(void *pvPramaters) +{ + (void) pvPramaters; + while (1) + { + _loop[3]++; + char *tmp; + + semphrTakeConditional(useMutexOnMalloc, xSemaphoreMalloc); + tmp = (char *)malloc(10 * sizeof(char)); + semphrGiveConditional(useMutexOnMalloc, xSemaphoreMalloc); + + strcpy(tmp, "yeah"); + + if (tryRealloc) + { + semphrTakeConditional(useMutexOnRealloc, xSemaphoreRealloc); + tmp = (char *)realloc(tmp, 20 * sizeof(char)); + semphrGiveConditional(useMutexOnRealloc, xSemaphoreRealloc); + strcat(tmp, "_realloc"); + } + + semphrTakeConditional(useMutexOnFree, xSemaphoreFree); + free(tmp); + semphrGiveConditional(useMutexOnFree, xSemaphoreFree); + + delay(DELAY); + } +} + +void loop4(void *pvPramaters) +{ + (void) pvPramaters; + while (1) + { + _loop[4]++; + char *tmp; + + semphrTakeConditional(useMutexOnMalloc, xSemaphoreMalloc); + tmp = (char *)malloc(10 * sizeof(char)); + semphrGiveConditional(useMutexOnMalloc, xSemaphoreMalloc); + + strcpy(tmp, "baz"); + + if (tryRealloc) + { + semphrTakeConditional(useMutexOnRealloc, xSemaphoreRealloc); + tmp = (char *)realloc(tmp, 20 * sizeof(char)); + semphrGiveConditional(useMutexOnRealloc, xSemaphoreRealloc); + strcat(tmp, "_realloc"); + } + + semphrTakeConditional(useMutexOnFree, xSemaphoreFree); + free(tmp); + semphrGiveConditional(useMutexOnFree, xSemaphoreFree); + + delay(DELAY); + } +} + +void loop5(void *pvPramaters) +{ + (void) pvPramaters; + while (1) + { + _loop[5]++; + char *tmp; + + semphrTakeConditional(useMutexOnMalloc, xSemaphoreMalloc); + tmp = (char *)malloc(10 * sizeof(char)); + semphrGiveConditional(useMutexOnMalloc, xSemaphoreMalloc); + + strcpy(tmp, "asd"); + + if (tryRealloc) + { + semphrTakeConditional(useMutexOnRealloc, xSemaphoreRealloc); + tmp = (char *)realloc(tmp, 20 * sizeof(char)); + semphrGiveConditional(useMutexOnRealloc, xSemaphoreRealloc); + strcat(tmp, "_realloc"); + } + + semphrTakeConditional(useMutexOnFree, xSemaphoreFree); + free(tmp); + semphrGiveConditional(useMutexOnFree, xSemaphoreFree); + + delay(DELAY); + } +} + +void loop6(void *pvPramaters) +{ + (void) pvPramaters; + while (1) + { + _loop[6]++; + char *tmp; + + semphrTakeConditional(useMutexOnMalloc, xSemaphoreMalloc); + tmp = (char *)malloc(10 * sizeof(char)); + semphrGiveConditional(useMutexOnMalloc, xSemaphoreMalloc); + + strcpy(tmp, "lol"); + + if (tryRealloc) + { + semphrTakeConditional(useMutexOnRealloc, xSemaphoreRealloc); + tmp = (char *)realloc(tmp, 20 * sizeof(char)); + semphrGiveConditional(useMutexOnRealloc, xSemaphoreRealloc); + strcat(tmp, "_realloc"); + } + + semphrTakeConditional(useMutexOnFree, xSemaphoreFree); + free(tmp); + semphrGiveConditional(useMutexOnFree, xSemaphoreFree); + + delay(DELAY); + } +} + +void loop7(void *pvPramaters) +{ + (void) pvPramaters; + while (1) + { + _loop[7]++; + char *tmp; + + semphrTakeConditional(useMutexOnMalloc, xSemaphoreMalloc); + tmp = (char *)malloc(10 * sizeof(char)); + semphrGiveConditional(useMutexOnMalloc, xSemaphoreMalloc); + + strcpy(tmp, "yay"); + + if (tryRealloc) + { + semphrTakeConditional(useMutexOnRealloc, xSemaphoreRealloc); + tmp = (char *)realloc(tmp, 20 * sizeof(char)); + semphrGiveConditional(useMutexOnRealloc, xSemaphoreRealloc); + strcat(tmp, "_realloc"); + } + + semphrTakeConditional(useMutexOnFree, xSemaphoreFree); + free(tmp); + semphrGiveConditional(useMutexOnFree, xSemaphoreFree); + + delay(DELAY); + } +} + +void semphrTakeConditional(bool useMutexOn, SemaphoreHandle_t xSemaphore) +{ + if (useMutexOn) + { + xSemaphoreTake(xSemaphore, TickType_t(portMAX_DELAY)); + } +} + +void semphrGiveConditional(bool useMutexOn, SemaphoreHandle_t xSemaphore) +{ + if (useMutexOn) + { + xSemaphoreGive(xSemaphore); + } +} diff --git a/libraries/FreeRTOS/keywords.txt b/libraries/FreeRTOS/keywords.txt index 410c1285d..d11db89bd 100644 --- a/libraries/FreeRTOS/keywords.txt +++ b/libraries/FreeRTOS/keywords.txt @@ -2,6 +2,8 @@ # https://arduino.github.io/arduino-cli/library-specification/#keywords # Formatted by a single true tab (not spaces) +FreeRTOS KEYWORD1 + # Datatypes (KEYWORD1) StackType_t KEYWORD1 BaseType_t KEYWORD1 @@ -34,6 +36,7 @@ pcTaskGetName KEYWORD2 ulTaskNotifyTake KEYWORD2 vTaskNotifyGiveFromISR KEYWORD2 taskYIELD KEYWORD2 +vTaskCoreAffinitySet KEYWORD2 vTaskSuspend KEYWORD2 vTaskResume KEYWORD2 xTaskResumeFromISR KEYWORD2 @@ -41,6 +44,7 @@ xTaskGetTickCount KEYWORD2 xTaskGetTickCountFromISR KEYWORD2 uxTaskGetNumberOfTasks KEYWORD2 uxTaskGetStackHighWaterMark KEYWORD2 +uxTaskGetSystemState KEYWORD2 # Instances (KEYWORD2) diff --git a/libraries/FreeRTOS/src/FreeRTOSConfig.h b/libraries/FreeRTOS/src/FreeRTOSConfig.h index f8279192d..8edf6ed4c 100644 --- a/libraries/FreeRTOS/src/FreeRTOSConfig.h +++ b/libraries/FreeRTOS/src/FreeRTOSConfig.h @@ -24,15 +24,12 @@ #define configUSE_COUNTING_SEMAPHORES 1 #define configUSE_QUEUE_SETS 1 #define configSUPPORT_DYNAMIC_ALLOCATION 1 -#define configSUPPORT_STATIC_ALLOCATION 0 +#define configSUPPORT_STATIC_ALLOCATION 1 #define configSTACK_DEPTH_TYPE uint32_t #define configUSE_TASK_PREEMPTION_DISABLE 1 #define configUSE_NEWLIB_REENTRANT 1 -#define configNEWLIB_REENTRANT_IS_DYNAMIC 0 /* Note that we have a different config option, portSET_IMPURE_PTR */ -#include -extern void __register_impure_ptr(struct _reent *p); -#define portSET_IMPURE_PTR(x) __register_impure_ptr(x) +#define configNEWLIB_REENTRANT_IS_DYNAMIC 1 /* Run time stats related definitions. */ void vMainConfigureTimerForRunTimeStats(void); diff --git a/libraries/FreeRTOS/src/tasks.c b/libraries/FreeRTOS/src/tasks.c index eb3e06951..8fbf74d0d 100644 --- a/libraries/FreeRTOS/src/tasks.c +++ b/libraries/FreeRTOS/src/tasks.c @@ -1 +1,14 @@ #include "../lib/FreeRTOS-Kernel/tasks.c" + +//See https://github.com/FreeRTOS/FreeRTOS-Kernel/pull/496 +struct _reent* __wrap___getreent(void) { + // No lock needed because if this changes, we won't be running anymore. + TCB_t *pxCurTask = xTaskGetCurrentTaskHandle(); + if (pxCurTask == NULL) { + // No task running. Return global struct. + return _GLOBAL_REENT; + } else { + // We have a task; return its reentrant struct. + return &pxCurTask->xNewLib_reent; + } +} diff --git a/libraries/FreeRTOS/src/variantHooks.cpp b/libraries/FreeRTOS/src/variantHooks.cpp index 4ba8fbcd5..8414f601a 100644 --- a/libraries/FreeRTOS/src/variantHooks.cpp +++ b/libraries/FreeRTOS/src/variantHooks.cpp @@ -25,24 +25,74 @@ */ #include +/* FreeRTOS includes. */ +#include "FreeRTOS.h" +#include "task.h" +#include "timers.h" +#include "semphr.h" + /* Arduino Core includes */ #include #include #include "tusb.h" - /* Raspberry PI Pico includes */ #include #include -/* FreeRTOS includes. */ -#include "FreeRTOS.h" -#include "task.h" -#include "timers.h" +#include <_freertos.h> + +// Interfaces for the main core to use FreeRTOS mutexes +extern "C" { + extern volatile bool __otherCoreIdled; + + SemaphoreHandle_t __freertos_mutex_create() { + return xSemaphoreCreateMutex(); + } + + SemaphoreHandle_t _freertos_recursive_mutex_create() { + return xSemaphoreCreateRecursiveMutex(); + } + + void __freertos_mutex_take(SemaphoreHandle_t mtx) { + xSemaphoreTake(mtx, portMAX_DELAY); + } + + void __freertos_mutex_take_from_isr(SemaphoreHandle_t mtx) { + xSemaphoreTakeFromISR(mtx, NULL); + } + + int __freertos_mutex_try_take(SemaphoreHandle_t mtx) { + return xSemaphoreTake(mtx, 0); + } + + void __freertos_mutex_give(SemaphoreHandle_t mtx) { + xSemaphoreGive(mtx); + } + + void __freertos_mutex_give_from_isr(SemaphoreHandle_t mtx) { + xSemaphoreGiveFromISR(mtx, NULL); + } + + void __freertos_recursive_mutex_take(SemaphoreHandle_t mtx) { + xSemaphoreTakeRecursive(mtx, portMAX_DELAY); + } + + int __freertos_recursive_mutex_try_take(SemaphoreHandle_t mtx) { + return xSemaphoreTakeRecursive(mtx, 0); + } + + void __freertos_recursive_mutex_give(SemaphoreHandle_t mtx) { + xSemaphoreGiveRecursive(mtx); + } +} + /*-----------------------------------------------------------*/ +extern void __initFreeRTOSMutexes(); void initFreeRTOS(void) { + __initFreeRTOSMutexes(); } extern void setup() __attribute__((weak)); @@ -55,7 +105,7 @@ volatile bool __usbInitted = false; static void __core0(void *params) { (void) params; -#ifndef NO_USB +#if !defined(NO_USB) && !defined(USE_TINYUSB) while (!__usbInitted) { delay(1); } @@ -77,7 +127,7 @@ static void __core0(void *params) { static void __core1(void *params) { (void) params; -#ifndef NO_USB +#if !defined(NO_USB) && !defined(USE_TINYUSB) while (!__usbInitted) { delay(1); } @@ -104,10 +154,44 @@ extern "C" void yield() { taskYIELD(); } +static TaskHandle_t __idleCoreTask[2]; +static void __no_inline_not_in_flash_func(IdleThisCore)(void *param) { + (void) param; + while (true) { + ulTaskNotifyTake(pdTRUE, portMAX_DELAY); + vTaskPreemptionDisable(nullptr); + portDISABLE_INTERRUPTS(); + __otherCoreIdled = true; + while (__otherCoreIdled) { + /* noop */ + } + portENABLE_INTERRUPTS(); + vTaskPreemptionEnable(nullptr); + } +} + +extern "C" void __no_inline_not_in_flash_func(__freertos_idle_other_core)() { + vTaskPreemptionDisable(nullptr); + xTaskNotifyGive(__idleCoreTask[ 1 ^ sio_hw->cpuid ]); + while (!__otherCoreIdled) { + /* noop */ + } + portDISABLE_INTERRUPTS(); + vTaskSuspendAll(); +} + +extern "C" void __no_inline_not_in_flash_func(__freertos_resume_other_core)() { + __otherCoreIdled = false; + portENABLE_INTERRUPTS(); + xTaskResumeAll(); + vTaskPreemptionEnable(nullptr); +} + + extern mutex_t __usb_mutex; static TaskHandle_t __usbTask; static void __usb(void *param); - +extern volatile bool __freeRTOSinitted; void startFreeRTOS(void) { TaskHandle_t c0; @@ -120,7 +204,14 @@ void startFreeRTOS(void) { vTaskCoreAffinitySet(c1, 1 << 1); } + // Create the idle-other-core tasks (for when flash is being written) + xTaskCreate(IdleThisCore, "IdleCore0", 128, 0, configMAX_PRIORITIES - 1, __idleCoreTask + 0); + vTaskCoreAffinitySet(__idleCoreTask[0], 1 << 0); + xTaskCreate(IdleThisCore, "IdleCore1", 128, 0, configMAX_PRIORITIES - 1, __idleCoreTask + 1); + vTaskCoreAffinitySet(__idleCoreTask[1], 1 << 1); + // Initialise and run the freeRTOS scheduler. Execution should never return here. + __freeRTOSinitted = true; vTaskStartScheduler(); while (true) { @@ -211,16 +302,20 @@ void vApplicationTickHook(void) { Private function to enable board led to use it in application hooks */ void prvSetMainLedOn(void) { +#ifdef LED_BUILTIN gpio_init(LED_BUILTIN); gpio_set_dir(LED_BUILTIN, true); gpio_put(LED_BUILTIN, true); +#endif } /** Private function to blink board led to use it in application hooks */ void prvBlinkMainLed(void) { +#ifdef LED_BUILTIN gpio_put(LED_BUILTIN, !gpio_get(LED_BUILTIN)); +#endif } #endif @@ -371,9 +466,10 @@ static void __usb(void *param) { __usbInitted = true; while (true) { - if (mutex_try_enter(&__usb_mutex, NULL)) { + auto m = __get_freertos_mutex_for_ptr(&__usb_mutex); + if (xSemaphoreTake(m, 0)) { tud_task(); - mutex_exit(&__usb_mutex); + xSemaphoreGive(m); } vTaskDelay(1 / portTICK_PERIOD_MS); } @@ -388,7 +484,9 @@ void __USBStart() { __SetupDescHIDReport(); __SetupUSBDescriptor(); - // Make highest prio and locked to core 0 - xTaskCreate(__usb, "USB", 256, 0, configMAX_PRIORITIES - 1, &__usbTask); + // Make high prio and locked to core 0 + xTaskCreate(__usb, "USB", 256, 0, configMAX_PRIORITIES - 2, &__usbTask); vTaskCoreAffinitySet(__usbTask, 1 << 0); } + + diff --git a/libraries/HID_Bluetooth/keywords.txt b/libraries/HID_Bluetooth/keywords.txt new file mode 100644 index 000000000..501a9cc16 --- /dev/null +++ b/libraries/HID_Bluetooth/keywords.txt @@ -0,0 +1,30 @@ +####################################### +# Syntax Coloring Map +####################################### + +####################################### +# Datatypes (KEYWORD1) +####################################### + +PicoBluetoothHID KEYWORD1 +PicoBluetoothBLEHID KEYWORD1 + +####################################### +# Methods and Functions (KEYWORD2) +####################################### + +setOpenedCB KEYWORD2 +setClosedCB KEYWORD2 +setCanSendNowCB KEYWORD2 +startHID KEYWORD2 +connected KEYWORD2 +send KEYWORD2 +lockBluetooth KEYWORD2 +unlockBluetooth KEYWORD2 +getCID KEYWORD2 +setBattery KEYWORD2 + +####################################### +# Constants (LITERAL1) +####################################### + diff --git a/libraries/HID_Bluetooth/library.properties b/libraries/HID_Bluetooth/library.properties new file mode 100644 index 000000000..518d9a0ec --- /dev/null +++ b/libraries/HID_Bluetooth/library.properties @@ -0,0 +1,9 @@ +name=HID_Bluetooth +version=1.0.0 +author=Earle F. Philhower, III +maintainer=Earle F. Philhower, III +sentence=Implements a HID device base class for PicoW Bluetooth +paragraph=Implements a HID device base class for PicoW Bluetooth +category=Device Control +url=https://github.com/earlephilhower/arduino-pico +architectures=rp2040 diff --git a/libraries/HID_Bluetooth/src/HID_Bluetooth.h b/libraries/HID_Bluetooth/src/HID_Bluetooth.h new file mode 100644 index 000000000..58e0434dc --- /dev/null +++ b/libraries/HID_Bluetooth/src/HID_Bluetooth.h @@ -0,0 +1,7 @@ +#ifdef ENABLE_CLASSIC +#include "PicoBluetoothHID.h" +#endif + +#ifdef ENABLE_BLE +#include "PicoBluetoothBLEHID.h" +#endif diff --git a/libraries/HID_Bluetooth/src/PicoBluetoothBLEHID.cpp b/libraries/HID_Bluetooth/src/PicoBluetoothBLEHID.cpp new file mode 100644 index 000000000..a639817c1 --- /dev/null +++ b/libraries/HID_Bluetooth/src/PicoBluetoothBLEHID.cpp @@ -0,0 +1,23 @@ +/* + PicoBluetoothBLEHID.h - Simple wrapper for BT-HID objects like + keyboards, mice, gamepads. + Copyright (c) 2023 Earle F. Philhower, III. All rights reserved. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include "PicoBluetoothBLEHID.h" + +PicoBluetoothBLEHID_ PicoBluetoothBLEHID; diff --git a/libraries/HID_Bluetooth/src/PicoBluetoothBLEHID.h b/libraries/HID_Bluetooth/src/PicoBluetoothBLEHID.h new file mode 100644 index 000000000..d755c3e33 --- /dev/null +++ b/libraries/HID_Bluetooth/src/PicoBluetoothBLEHID.h @@ -0,0 +1,485 @@ +/* + PicoBluetoothBLEHID.h - Simple wrapper for BT-HID objects like + keyboards, mice, gamepads using Bluetooth LE mode + Based off of the BTStack HID main loop + Copyright (c) 2023 Earle F. Philhower, III. All rights reserved. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#pragma once + +#include <_needsbt.h> +#include +#include +#include +#include + +// The BTStack has redefinitions of this USB enum (same values, just redefined), so hide it to allow easy compilation +#define HID_REPORT_TYPE_INPUT HID_REPORT_TYPE_INPUT_BT +#define HID_REPORT_TYPE_OUTPUT HID_REPORT_TYPE_OUTPUT_BT +#define HID_REPORT_TYPE_FEATURE HID_REPORT_TYPE_FEATURE_BT +#define hid_report_type_t hid_report_type_t_bt +#include +#undef hid_report_type_t +#undef HID_REPORT_TYPE_FEATURE +#undef HID_REPORT_TYPE_OUTPUT +#undef HID_REPORT_TYPE_INPUT + +#include +#include +#include +#include +#include +#include + +class PicoBluetoothBLEHID_; +extern PicoBluetoothBLEHID_ PicoBluetoothBLEHID; + +class PicoBluetoothBLEHID_ { +public: + PicoBluetoothBLEHID_() { + } + + ~PicoBluetoothBLEHID_() { + } + + // Optional callback, not used presently + // Usage: PicoBluetoothHID.setCanSendNowCB(std::bind(&kbd::onCanSendNow, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4)); + typedef std::function BTCallback; + + void setOpenedCB(BTCallback cb) { + _onOpened = cb; + } + + void setClosedCB(BTCallback cb) { + _onClosed = cb; + } + + void setCanSendNowCB(BTCallback cb) { + _onCanSendNow = cb; + } + + bool startHID(const char *localName, const char *hidName, uint16_t appearance, const uint8_t *hidDescriptor, uint16_t hidDescriptorSize, int battery = 100) { + if (_running) { + return false; + } + _running = true; + + _buildAdvData(localName, appearance); + _buildAttdb(hidName); + + _battery = battery; + + // Setup L2CAP + l2cap_init(); + + // Setup SM + sm_init(); + sm_set_io_capabilities(IO_CAPABILITY_NO_INPUT_NO_OUTPUT); + sm_set_authentication_requirements(SM_AUTHREQ_SECURE_CONNECTION | SM_AUTHREQ_BONDING); + + // Setup ATT server + att_server_init(_attdb, NULL, NULL); + + // Setup battery service + battery_service_server_init(battery); + + // Setup device information service + device_information_service_server_init(); + + // Setup HID Device service + hids_device_init(0, hidDescriptor, hidDescriptorSize); + + // Setup advertisements + uint16_t adv_int_min = 0x0030; + uint16_t adv_int_max = 0x0030; + uint8_t adv_type = 0; + bd_addr_t null_addr; + memset(null_addr, 0, 6); + gap_advertisements_set_params(adv_int_min, adv_int_max, adv_type, 0, null_addr, 0x07, 0x00); + gap_advertisements_set_data(_advDataLen, _advData); + gap_advertisements_enable(1); + + // Register for HCI events + _hci_event_callback_registration.callback = PacketHandlerWrapper; + hci_add_event_handler(&_hci_event_callback_registration); + + // Register for SM events + _sm_event_callback_registration.callback = PacketHandlerWrapper; + sm_add_event_handler(&_sm_event_callback_registration); + + // Register for HIDS events + hids_device_register_packet_handler(PacketHandlerWrapper); + + // GO! + hci_power_control(HCI_POWER_ON); + return true; + } + + static void PacketHandlerWrapper(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t packet_size) { + PicoBluetoothBLEHID.packetHandler(packet_type, channel, packet, packet_size); + } + + void packetHandler(uint8_t type, uint16_t channel, uint8_t *packet, uint16_t size) { + if (type != HCI_EVENT_PACKET) { + return; + } + switch (hci_event_packet_get_type(packet)) { + case HCI_EVENT_DISCONNECTION_COMPLETE: + _con_handle = HCI_CON_HANDLE_INVALID; + if (_onClosed) { + _onClosed(type, channel, packet, size); + } + break; + case SM_EVENT_JUST_WORKS_REQUEST: + sm_just_works_confirm(sm_event_just_works_request_get_handle(packet)); + break; + case SM_EVENT_NUMERIC_COMPARISON_REQUEST: + // printf("Confirming numeric comparison: %"PRIu32"\n", sm_event_numeric_comparison_request_get_passkey(packet)); + sm_numeric_comparison_confirm(sm_event_passkey_display_number_get_handle(packet)); + break; + case SM_EVENT_PASSKEY_DISPLAY_NUMBER: + //printf("Display Passkey: %"PRIu32"\n", sm_event_passkey_display_number_get_passkey(packet)); + break; + case HCI_EVENT_HIDS_META: + switch (hci_event_hids_meta_get_subevent_code(packet)) { + case HIDS_SUBEVENT_INPUT_REPORT_ENABLE: + _con_handle = hids_subevent_input_report_enable_get_con_handle(packet); + if (_onOpened) { + _onOpened(type, channel, packet, size); + } + break; + case HIDS_SUBEVENT_BOOT_KEYBOARD_INPUT_REPORT_ENABLE: + _con_handle = hids_subevent_boot_keyboard_input_report_enable_get_con_handle(packet); + if (_onOpened) { + _onOpened(type, channel, packet, size); + } + break; + case HIDS_SUBEVENT_PROTOCOL_MODE: + _protocol_mode = hids_subevent_protocol_mode_get_protocol_mode(packet); + break; + case HIDS_SUBEVENT_CAN_SEND_NOW: + switch (_protocol_mode) { + case 0: + hids_device_send_boot_keyboard_input_report(_con_handle, (const uint8_t *)_sendReport, _sendReportLen); + break; + case 1: + hids_device_send_input_report(_con_handle, (const uint8_t *)_sendReport, _sendReportLen); + break; + default: + break; + } + _needToSend = false; + if (_onCanSendNow) { + _onCanSendNow(type, channel, packet, size); + } + break; + } + break; + default: + break; + } + } + + bool end() { + if (_running) { + hci_power_control(HCI_POWER_OFF); + } + _running = false; + _needToSend = false; + return true; + } + + bool connected() { + return _con_handle != HCI_CON_HANDLE_INVALID; + } + + bool send(void *rpt, int len) { + _needToSend = true; + _sendReport = rpt; + _sendReportLen = len; + lockBluetooth(); + hids_device_request_can_send_now_event(_con_handle); + unlockBluetooth(); + while (connected() && _needToSend) { + /* noop busy wait */ + } + return connected(); + } + + bool setBattery(int level) { + if (!_running || (level < 0) || (level > 100)) { + return false; + } + battery_service_server_set_battery_value(level); + return true; + } + + static void lockBluetooth() { + async_context_acquire_lock_blocking(cyw43_arch_async_context()); + } + + static void unlockBluetooth() { + async_context_release_lock(cyw43_arch_async_context()); + } + +private: + bool _running = false; + + BTCallback _onOpened = nullptr; + BTCallback _onClosed = nullptr; + BTCallback _onCanSendNow = nullptr; + + btstack_packet_callback_registration_t _hci_event_callback_registration; + btstack_packet_callback_registration_t _sm_event_callback_registration; + uint8_t _battery = 100; + hci_con_handle_t _con_handle = HCI_CON_HANDLE_INVALID; + uint8_t _protocol_mode = 1; + + void _buildAdvData(const char *completeLocalName, uint16_t appearance) { + free(_advData); + _advDataLen = 13 + strlen(completeLocalName); + _advData = (uint8_t*) malloc(_advDataLen); + int i = 0; + // Flags general discoverable, BR/EDR not supported + // 0x02, BLUETOOTH_DATA_TYPE_FLAGS, 0x06, + _advData[i++] = 0x02; + _advData[i++] = BLUETOOTH_DATA_TYPE_FLAGS; + _advData[i++] = 0x06; + // Name + // 0x0d, BLUETOOTH_DATA_TYPE_COMPLETE_LOCAL_NAME, + _advData[i++] = 1 + strlen(completeLocalName); + _advData[i++] = BLUETOOTH_DATA_TYPE_COMPLETE_LOCAL_NAME; + memcpy(_advData + i, completeLocalName, strlen(completeLocalName)); + i += strlen(completeLocalName); + // 16-bit Service UUIDs + // 0x03, BLUETOOTH_DATA_TYPE_COMPLETE_LIST_OF_16_BIT_SERVICE_CLASS_UUIDS, ORG_BLUETOOTH_SERVICE_HUMAN_INTERFACE_DEVICE & 0xff, ORG_BLUETOOTH_SERVICE_HUMAN_INTERFACE_DEVICE >> 8, + _advData[i++] = 0x03; + _advData[i++] = BLUETOOTH_DATA_TYPE_COMPLETE_LIST_OF_16_BIT_SERVICE_CLASS_UUIDS; + _advData[i++] = ORG_BLUETOOTH_SERVICE_HUMAN_INTERFACE_DEVICE & 0xff; + _advData[i++] = ORG_BLUETOOTH_SERVICE_HUMAN_INTERFACE_DEVICE >> 8; + // Appearance HID - Keyboard (Category 15, Sub-Category 1) + // 0x03, BLUETOOTH_DATA_TYPE_APPEARANCE, 0xC1, 0x03, + _advData[i++] = 0x03; + _advData[i++] = BLUETOOTH_DATA_TYPE_APPEARANCE; + _advData[i++] = appearance & 0xff; + _advData[i++] = appearance >> 8; + } + uint8_t *_advData = nullptr; + uint8_t _advDataLen = 0; + + void _buildAttdb(const char *hidName) { + free(_attdb); + _attdbLen = sizeof(_attdb_head) + 8 + strlen(hidName) + sizeof(_attdb_tail); + _attdb = (uint8_t *) malloc(_attdbLen); + memcpy(_attdb, _attdb_head, sizeof(_attdb_head)); + // 0x0003 VALUE CHARACTERISTIC-GAP_DEVICE_NAME - READ -'HID Mouse' + // READ_ANYBODY + // 0x11, 0x00, 0x02, 0x00, 0x03, 0x00, 0x00, 0x2a, 0x48, 0x49, 0x44, 0x20, 0x4d, 0x6f, 0x75, 0x73, 0x65, + int i = sizeof(_attdb_head); + _attdb[i++] = 8 + strlen(hidName); + _attdb[i++] = 0x00; + _attdb[i++] = 0x02; + _attdb[i++] = 0x00; + _attdb[i++] = 0x03; + _attdb[i++] = 0x00; + _attdb[i++] = 0x00; + _attdb[i++] = 0x2a; + memcpy(_attdb + i, hidName, strlen(hidName)); + i += strlen(hidName); + memcpy(_attdb + i, _attdb_tail, sizeof(_attdb_tail)); + } + uint8_t *_attdb = nullptr; + int _attdbLen = 0; + + static constexpr const uint8_t _attdb_head[] = { + // ATT DB Version + 1, + + // 0x0001 PRIMARY_SERVICE-GAP_SERVICE + 0x0a, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x28, 0x00, 0x18, + // 0x0002 CHARACTERISTIC-GAP_DEVICE_NAME - READ + 0x0d, 0x00, 0x02, 0x00, 0x02, 0x00, 0x03, 0x28, 0x02, 0x03, 0x00, 0x00, 0x2a, + }; + + static constexpr const uint8_t _attdb_tail[] = { + // #import -- BEGIN + // Specification Type org.bluetooth.service.battery_service + // https://www.bluetooth.com/api/gatt/xmlfile?xmlFileName=org.bluetooth.service.battery_service.xml + // Battery Service 180F + // 0x0004 PRIMARY_SERVICE-ORG_BLUETOOTH_SERVICE_BATTERY_SERVICE + 0x0a, 0x00, 0x02, 0x00, 0x04, 0x00, 0x00, 0x28, 0x0f, 0x18, + // 0x0005 CHARACTERISTIC-ORG_BLUETOOTH_CHARACTERISTIC_BATTERY_LEVEL - DYNAMIC | READ | NOTIFY + 0x0d, 0x00, 0x02, 0x00, 0x05, 0x00, 0x03, 0x28, 0x12, 0x06, 0x00, 0x19, 0x2a, + // 0x0006 VALUE CHARACTERISTIC-ORG_BLUETOOTH_CHARACTERISTIC_BATTERY_LEVEL - DYNAMIC | READ | NOTIFY + // READ_ANYBODY + 0x08, 0x00, 0x02, 0x01, 0x06, 0x00, 0x19, 0x2a, + // 0x0007 CLIENT_CHARACTERISTIC_CONFIGURATION + // READ_ANYBODY, WRITE_ANYBODY + 0x0a, 0x00, 0x0e, 0x01, 0x07, 0x00, 0x02, 0x29, 0x00, 0x00, + // #import -- END + // add Device ID Service + + // #import -- BEGIN + // Specification Type org.bluetooth.service.device_information + // https://www.bluetooth.com/api/gatt/xmlfile?xmlFileName=org.bluetooth.service.device_information.xml + // Device Information 180A + // 0x0008 PRIMARY_SERVICE-ORG_BLUETOOTH_SERVICE_DEVICE_INFORMATION + 0x0a, 0x00, 0x02, 0x00, 0x08, 0x00, 0x00, 0x28, 0x0a, 0x18, + // 0x0009 CHARACTERISTIC-ORG_BLUETOOTH_CHARACTERISTIC_MANUFACTURER_NAME_STRING - DYNAMIC | READ + 0x0d, 0x00, 0x02, 0x00, 0x09, 0x00, 0x03, 0x28, 0x02, 0x0a, 0x00, 0x29, 0x2a, + // 0x000a VALUE CHARACTERISTIC-ORG_BLUETOOTH_CHARACTERISTIC_MANUFACTURER_NAME_STRING - DYNAMIC | READ + // READ_ANYBODY + 0x08, 0x00, 0x02, 0x01, 0x0a, 0x00, 0x29, 0x2a, + // 0x000b CHARACTERISTIC-ORG_BLUETOOTH_CHARACTERISTIC_MODEL_NUMBER_STRING - DYNAMIC | READ + 0x0d, 0x00, 0x02, 0x00, 0x0b, 0x00, 0x03, 0x28, 0x02, 0x0c, 0x00, 0x24, 0x2a, + // 0x000c VALUE CHARACTERISTIC-ORG_BLUETOOTH_CHARACTERISTIC_MODEL_NUMBER_STRING - DYNAMIC | READ + // READ_ANYBODY + 0x08, 0x00, 0x02, 0x01, 0x0c, 0x00, 0x24, 0x2a, + // 0x000d CHARACTERISTIC-ORG_BLUETOOTH_CHARACTERISTIC_SERIAL_NUMBER_STRING - DYNAMIC | READ + 0x0d, 0x00, 0x02, 0x00, 0x0d, 0x00, 0x03, 0x28, 0x02, 0x0e, 0x00, 0x25, 0x2a, + // 0x000e VALUE CHARACTERISTIC-ORG_BLUETOOTH_CHARACTERISTIC_SERIAL_NUMBER_STRING - DYNAMIC | READ + // READ_ANYBODY + 0x08, 0x00, 0x02, 0x01, 0x0e, 0x00, 0x25, 0x2a, + // 0x000f CHARACTERISTIC-ORG_BLUETOOTH_CHARACTERISTIC_HARDWARE_REVISION_STRING - DYNAMIC | READ + 0x0d, 0x00, 0x02, 0x00, 0x0f, 0x00, 0x03, 0x28, 0x02, 0x10, 0x00, 0x27, 0x2a, + // 0x0010 VALUE CHARACTERISTIC-ORG_BLUETOOTH_CHARACTERISTIC_HARDWARE_REVISION_STRING - DYNAMIC | READ + // READ_ANYBODY + 0x08, 0x00, 0x02, 0x01, 0x10, 0x00, 0x27, 0x2a, + // 0x0011 CHARACTERISTIC-ORG_BLUETOOTH_CHARACTERISTIC_FIRMWARE_REVISION_STRING - DYNAMIC | READ + 0x0d, 0x00, 0x02, 0x00, 0x11, 0x00, 0x03, 0x28, 0x02, 0x12, 0x00, 0x26, 0x2a, + // 0x0012 VALUE CHARACTERISTIC-ORG_BLUETOOTH_CHARACTERISTIC_FIRMWARE_REVISION_STRING - DYNAMIC | READ + // READ_ANYBODY + 0x08, 0x00, 0x02, 0x01, 0x12, 0x00, 0x26, 0x2a, + // 0x0013 CHARACTERISTIC-ORG_BLUETOOTH_CHARACTERISTIC_SOFTWARE_REVISION_STRING - DYNAMIC | READ + 0x0d, 0x00, 0x02, 0x00, 0x13, 0x00, 0x03, 0x28, 0x02, 0x14, 0x00, 0x28, 0x2a, + // 0x0014 VALUE CHARACTERISTIC-ORG_BLUETOOTH_CHARACTERISTIC_SOFTWARE_REVISION_STRING - DYNAMIC | READ + // READ_ANYBODY + 0x08, 0x00, 0x02, 0x01, 0x14, 0x00, 0x28, 0x2a, + // 0x0015 CHARACTERISTIC-ORG_BLUETOOTH_CHARACTERISTIC_SYSTEM_ID - DYNAMIC | READ + 0x0d, 0x00, 0x02, 0x00, 0x15, 0x00, 0x03, 0x28, 0x02, 0x16, 0x00, 0x23, 0x2a, + // 0x0016 VALUE CHARACTERISTIC-ORG_BLUETOOTH_CHARACTERISTIC_SYSTEM_ID - DYNAMIC | READ + // READ_ANYBODY + 0x08, 0x00, 0x02, 0x01, 0x16, 0x00, 0x23, 0x2a, + // 0x0017 CHARACTERISTIC-ORG_BLUETOOTH_CHARACTERISTIC_IEEE_11073_20601_REGULATORY_CERTIFICATION_DATA_LIST - DYNAMIC | READ + 0x0d, 0x00, 0x02, 0x00, 0x17, 0x00, 0x03, 0x28, 0x02, 0x18, 0x00, 0x2a, 0x2a, + // 0x0018 VALUE CHARACTERISTIC-ORG_BLUETOOTH_CHARACTERISTIC_IEEE_11073_20601_REGULATORY_CERTIFICATION_DATA_LIST - DYNAMIC | READ + // READ_ANYBODY + 0x08, 0x00, 0x02, 0x01, 0x18, 0x00, 0x2a, 0x2a, + // 0x0019 CHARACTERISTIC-ORG_BLUETOOTH_CHARACTERISTIC_PNP_ID - DYNAMIC | READ + 0x0d, 0x00, 0x02, 0x00, 0x19, 0x00, 0x03, 0x28, 0x02, 0x1a, 0x00, 0x50, 0x2a, + // 0x001a VALUE CHARACTERISTIC-ORG_BLUETOOTH_CHARACTERISTIC_PNP_ID - DYNAMIC | READ + // READ_ANYBODY + 0x08, 0x00, 0x02, 0x01, 0x1a, 0x00, 0x50, 0x2a, + // #import -- END + + // #import -- BEGIN + // Specification Type org.bluetooth.service.human_interface_device + // https://www.bluetooth.com/api/gatt/xmlfile?xmlFileName=org.bluetooth.service.human_interface_device.xml + // Human Interface Device 1812 + // 0x001b PRIMARY_SERVICE-ORG_BLUETOOTH_SERVICE_HUMAN_INTERFACE_DEVICE + 0x0a, 0x00, 0x02, 0x00, 0x1b, 0x00, 0x00, 0x28, 0x12, 0x18, + // 0x001c CHARACTERISTIC-ORG_BLUETOOTH_CHARACTERISTIC_PROTOCOL_MODE - DYNAMIC | READ | WRITE_WITHOUT_RESPONSE + 0x0d, 0x00, 0x02, 0x00, 0x1c, 0x00, 0x03, 0x28, 0x06, 0x1d, 0x00, 0x4e, 0x2a, + // 0x001d VALUE CHARACTERISTIC-ORG_BLUETOOTH_CHARACTERISTIC_PROTOCOL_MODE - DYNAMIC | READ | WRITE_WITHOUT_RESPONSE + // READ_ANYBODY, WRITE_ANYBODY + 0x08, 0x00, 0x06, 0x01, 0x1d, 0x00, 0x4e, 0x2a, + // 0x001e CHARACTERISTIC-ORG_BLUETOOTH_CHARACTERISTIC_REPORT - DYNAMIC | READ | WRITE | NOTIFY | ENCRYPTION_KEY_SIZE_16 + 0x0d, 0x00, 0x02, 0x00, 0x1e, 0x00, 0x03, 0x28, 0x1a, 0x1f, 0x00, 0x4d, 0x2a, + // 0x001f VALUE CHARACTERISTIC-ORG_BLUETOOTH_CHARACTERISTIC_REPORT - DYNAMIC | READ | WRITE | NOTIFY | ENCRYPTION_KEY_SIZE_16 + // READ_ENCRYPTED, WRITE_ENCRYPTED, ENCRYPTION_KEY_SIZE=16 + 0x08, 0x00, 0x0b, 0xf5, 0x1f, 0x00, 0x4d, 0x2a, + // 0x0020 CLIENT_CHARACTERISTIC_CONFIGURATION + // READ_ANYBODY, WRITE_ENCRYPTED, ENCRYPTION_KEY_SIZE=16 + 0x0a, 0x00, 0x0f, 0xf1, 0x20, 0x00, 0x02, 0x29, 0x00, 0x00, + // fixed report id = 1, type = Input (1) + // 0x0021 REPORT_REFERENCE-READ-1-1 + 0x0a, 0x00, 0x02, 0x00, 0x21, 0x00, 0x08, 0x29, 0x1, 0x1, + // 0x0022 CHARACTERISTIC-ORG_BLUETOOTH_CHARACTERISTIC_REPORT - DYNAMIC | READ | WRITE | NOTIFY | ENCRYPTION_KEY_SIZE_16 + 0x0d, 0x00, 0x02, 0x00, 0x22, 0x00, 0x03, 0x28, 0x1a, 0x23, 0x00, 0x4d, 0x2a, + // 0x0023 VALUE CHARACTERISTIC-ORG_BLUETOOTH_CHARACTERISTIC_REPORT - DYNAMIC | READ | WRITE | NOTIFY | ENCRYPTION_KEY_SIZE_16 + // READ_ENCRYPTED, WRITE_ENCRYPTED, ENCRYPTION_KEY_SIZE=16 + 0x08, 0x00, 0x0b, 0xf5, 0x23, 0x00, 0x4d, 0x2a, + // 0x0024 CLIENT_CHARACTERISTIC_CONFIGURATION + // READ_ANYBODY, WRITE_ENCRYPTED, ENCRYPTION_KEY_SIZE=16 + 0x0a, 0x00, 0x0f, 0xf1, 0x24, 0x00, 0x02, 0x29, 0x00, 0x00, + // fixed report id = 2, type = Output (2) + // 0x0025 REPORT_REFERENCE-READ-2-2 + 0x0a, 0x00, 0x02, 0x00, 0x25, 0x00, 0x08, 0x29, 0x2, 0x2, + // 0x0026 CHARACTERISTIC-ORG_BLUETOOTH_CHARACTERISTIC_REPORT - DYNAMIC | READ | WRITE | NOTIFY | ENCRYPTION_KEY_SIZE_16 + 0x0d, 0x00, 0x02, 0x00, 0x26, 0x00, 0x03, 0x28, 0x1a, 0x27, 0x00, 0x4d, 0x2a, + // 0x0027 VALUE CHARACTERISTIC-ORG_BLUETOOTH_CHARACTERISTIC_REPORT - DYNAMIC | READ | WRITE | NOTIFY | ENCRYPTION_KEY_SIZE_16 + // READ_ENCRYPTED, WRITE_ENCRYPTED, ENCRYPTION_KEY_SIZE=16 + 0x08, 0x00, 0x0b, 0xf5, 0x27, 0x00, 0x4d, 0x2a, + // 0x0028 CLIENT_CHARACTERISTIC_CONFIGURATION + // READ_ANYBODY, WRITE_ENCRYPTED, ENCRYPTION_KEY_SIZE=16 + 0x0a, 0x00, 0x0f, 0xf1, 0x28, 0x00, 0x02, 0x29, 0x00, 0x00, + // fixed report id = 3, type = Feature (3) + // 0x0029 REPORT_REFERENCE-READ-3-3 + 0x0a, 0x00, 0x02, 0x00, 0x29, 0x00, 0x08, 0x29, 0x3, 0x3, + // 0x002a CHARACTERISTIC-ORG_BLUETOOTH_CHARACTERISTIC_REPORT_MAP - DYNAMIC | READ + 0x0d, 0x00, 0x02, 0x00, 0x2a, 0x00, 0x03, 0x28, 0x02, 0x2b, 0x00, 0x4b, 0x2a, + // 0x002b VALUE CHARACTERISTIC-ORG_BLUETOOTH_CHARACTERISTIC_REPORT_MAP - DYNAMIC | READ + // READ_ANYBODY + 0x08, 0x00, 0x02, 0x01, 0x2b, 0x00, 0x4b, 0x2a, + // 0x002c CHARACTERISTIC-ORG_BLUETOOTH_CHARACTERISTIC_BOOT_KEYBOARD_INPUT_REPORT - DYNAMIC | READ | WRITE | NOTIFY + 0x0d, 0x00, 0x02, 0x00, 0x2c, 0x00, 0x03, 0x28, 0x1a, 0x2d, 0x00, 0x22, 0x2a, + // 0x002d VALUE CHARACTERISTIC-ORG_BLUETOOTH_CHARACTERISTIC_BOOT_KEYBOARD_INPUT_REPORT - DYNAMIC | READ | WRITE | NOTIFY + // READ_ANYBODY, WRITE_ANYBODY + 0x08, 0x00, 0x0a, 0x01, 0x2d, 0x00, 0x22, 0x2a, + // 0x002e CLIENT_CHARACTERISTIC_CONFIGURATION + // READ_ANYBODY, WRITE_ANYBODY + 0x0a, 0x00, 0x0e, 0x01, 0x2e, 0x00, 0x02, 0x29, 0x00, 0x00, + // 0x002f CHARACTERISTIC-ORG_BLUETOOTH_CHARACTERISTIC_BOOT_KEYBOARD_OUTPUT_REPORT - DYNAMIC | READ | WRITE | WRITE_WITHOUT_RESPONSE + 0x0d, 0x00, 0x02, 0x00, 0x2f, 0x00, 0x03, 0x28, 0x0e, 0x30, 0x00, 0x32, 0x2a, + // 0x0030 VALUE CHARACTERISTIC-ORG_BLUETOOTH_CHARACTERISTIC_BOOT_KEYBOARD_OUTPUT_REPORT - DYNAMIC | READ | WRITE | WRITE_WITHOUT_RESPONSE + // READ_ANYBODY, WRITE_ANYBODY + 0x08, 0x00, 0x0e, 0x01, 0x30, 0x00, 0x32, 0x2a, + // 0x0031 CHARACTERISTIC-ORG_BLUETOOTH_CHARACTERISTIC_BOOT_MOUSE_INPUT_REPORT - DYNAMIC | READ | WRITE | NOTIFY + 0x0d, 0x00, 0x02, 0x00, 0x31, 0x00, 0x03, 0x28, 0x1a, 0x32, 0x00, 0x33, 0x2a, + // 0x0032 VALUE CHARACTERISTIC-ORG_BLUETOOTH_CHARACTERISTIC_BOOT_MOUSE_INPUT_REPORT - DYNAMIC | READ | WRITE | NOTIFY + // READ_ANYBODY, WRITE_ANYBODY + 0x08, 0x00, 0x0a, 0x01, 0x32, 0x00, 0x33, 0x2a, + // 0x0033 CLIENT_CHARACTERISTIC_CONFIGURATION + // READ_ANYBODY, WRITE_ANYBODY + 0x0a, 0x00, 0x0e, 0x01, 0x33, 0x00, 0x02, 0x29, 0x00, 0x00, + // bcdHID = 0x101 (v1.0.1), bCountryCode 0, remote wakeable = 0 | normally connectable 2 + // 0x0034 CHARACTERISTIC-ORG_BLUETOOTH_CHARACTERISTIC_HID_INFORMATION - READ + 0x0d, 0x00, 0x02, 0x00, 0x34, 0x00, 0x03, 0x28, 0x02, 0x35, 0x00, 0x4a, 0x2a, + // 0x0035 VALUE CHARACTERISTIC-ORG_BLUETOOTH_CHARACTERISTIC_HID_INFORMATION - READ -'01 01 00 02' + // READ_ANYBODY + 0x0c, 0x00, 0x02, 0x00, 0x35, 0x00, 0x4a, 0x2a, 0x01, 0x01, 0x00, 0x02, + // 0x0036 CHARACTERISTIC-ORG_BLUETOOTH_CHARACTERISTIC_HID_CONTROL_POINT - DYNAMIC | WRITE_WITHOUT_RESPONSE + 0x0d, 0x00, 0x02, 0x00, 0x36, 0x00, 0x03, 0x28, 0x04, 0x37, 0x00, 0x4c, 0x2a, + // 0x0037 VALUE CHARACTERISTIC-ORG_BLUETOOTH_CHARACTERISTIC_HID_CONTROL_POINT - DYNAMIC | WRITE_WITHOUT_RESPONSE + // WRITE_ANYBODY + 0x08, 0x00, 0x04, 0x01, 0x37, 0x00, 0x4c, 0x2a, + // #import -- END + // 0x0038 PRIMARY_SERVICE-GATT_SERVICE + 0x0a, 0x00, 0x02, 0x00, 0x38, 0x00, 0x00, 0x28, 0x01, 0x18, + // 0x0039 CHARACTERISTIC-GATT_DATABASE_HASH - READ + 0x0d, 0x00, 0x02, 0x00, 0x39, 0x00, 0x03, 0x28, 0x02, 0x3a, 0x00, 0x2a, 0x2b, + // 0x003a VALUE CHARACTERISTIC-GATT_DATABASE_HASH - READ -'' + // READ_ANYBODY + 0x18, 0x00, 0x02, 0x00, 0x3a, 0x00, 0x2a, 0x2b, 0xc2, 0x10, 0xf5, 0x75, 0xf3, 0x9f, 0x50, 0xb6, 0x83, 0xc7, 0xfa, 0xac, 0xa6, 0x1b, 0x7d, 0x32, + // END + 0x00, 0x00 + }; + + volatile bool _needToSend = false; + void *_sendReport; + int _sendReportLen; +}; diff --git a/libraries/HID_Bluetooth/src/PicoBluetoothHID.cpp b/libraries/HID_Bluetooth/src/PicoBluetoothHID.cpp new file mode 100644 index 000000000..07f5e74b6 --- /dev/null +++ b/libraries/HID_Bluetooth/src/PicoBluetoothHID.cpp @@ -0,0 +1,23 @@ +/* + PicoBluetoothHID.h - Simple wrapper for BT-HID objects like + keyboards, mice, gamepads. + Copyright (c) 2023 Earle F. Philhower, III. All rights reserved. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include "PicoBluetoothHID.h" + +PicoBluetoothHID_ PicoBluetoothHID; diff --git a/libraries/HID_Bluetooth/src/PicoBluetoothHID.h b/libraries/HID_Bluetooth/src/PicoBluetoothHID.h new file mode 100644 index 000000000..227bd793a --- /dev/null +++ b/libraries/HID_Bluetooth/src/PicoBluetoothHID.h @@ -0,0 +1,256 @@ +/* + PicoBluetoothHID.h - Simple wrapper for BT-HID objects like + keyboards, mice, gamepads. + Based off of the BTStack HID main loop + Copyright (c) 2023 Earle F. Philhower, III. All rights reserved. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#pragma once + +#include <_needsbt.h> +#include +#include +#include +#include + +// The BTStack has redefinitions of this USB enum (same values, just redefined), so hide it to allow easy compilation +#define HID_REPORT_TYPE_INPUT HID_REPORT_TYPE_INPUT_BT +#define HID_REPORT_TYPE_OUTPUT HID_REPORT_TYPE_OUTPUT_BT +#define HID_REPORT_TYPE_FEATURE HID_REPORT_TYPE_FEATURE_BT +#define hid_report_type_t hid_report_type_t_bt +#include +#undef hid_report_type_t +#undef HID_REPORT_TYPE_FEATURE +#undef HID_REPORT_TYPE_OUTPUT +#undef HID_REPORT_TYPE_INPUT + +class PicoBluetoothHID_; +extern PicoBluetoothHID_ PicoBluetoothHID; + +class PicoBluetoothHID_ { +public: + PicoBluetoothHID_() { + } + + ~PicoBluetoothHID_() { + } + + // Optional callback, not used presently + // Usage: PicoBluetoothHID.setCanSendNowCB(std::bind(&kbd::onCanSendNow, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4)); + typedef std::function BTCallback; + + void setOpenedCB(BTCallback cb) { + _onOpened = cb; + } + + void setClosedCB(BTCallback cb) { + _onClosed = cb; + } + + void setCanSendNowCB(BTCallback cb) { + _onCanSendNow = cb; + } + + bool startHID(const char *localName, const char *hidName, uint16_t hidClass, uint8_t hidSubclass, const uint8_t *hidDescriptor, uint16_t hidDescriptorSize) { + if (_running) { + return false; + } + _running = true; + // Allow finding via inquiry + gap_discoverable_control(1); + // Use Limited Discoverable Mode; Peripheral; Keyboard as CoD + gap_set_class_of_device(hidClass); + // Set local name to be identified - zeroes will be replaced by actual BD ADDR + gap_set_local_name(localName); + // Allow for role switch in general and sniff mode + gap_set_default_link_policy_settings(LM_LINK_POLICY_ENABLE_ROLE_SWITCH | LM_LINK_POLICY_ENABLE_SNIFF_MODE); + // Allow for role switch on outgoing connections - this allow HID Host to become master when we re-connect to it + gap_set_allow_role_switch(true); + + // L2CAP + l2cap_init(); +#ifdef ENABLE_BLE + // Initialize LE Security Manager. Needed for cross-transport key derivation + sm_init(); +#endif + + // SDP Server + sdp_init(); + bzero(_hid_service_buffer, sizeof(_hid_service_buffer)); + + const uint8_t hid_boot_device = 0; + const uint8_t hid_virtual_cable = 0; + const uint8_t hid_remote_wake = 1; + const uint8_t hid_reconnect_initiate = 1; + const uint8_t hid_normally_connectable = 1; + // When not set to 0xffff, sniff and sniff subrating are enabled + const uint16_t host_max_latency = 1600; + const uint16_t host_min_timeout = 3200; + + hid_sdp_record_t hid_params = { + hidClass, hidSubclass, + hid_virtual_cable, hid_remote_wake, + hid_reconnect_initiate, (bool)hid_normally_connectable, + (bool)hid_boot_device, + host_max_latency, host_min_timeout, + 3200, + hidDescriptor, + hidDescriptorSize, + hidName + }; + + hid_create_sdp_record(_hid_service_buffer, 0x10001, &hid_params); + sdp_register_service(_hid_service_buffer); + + // See https://www.bluetooth.com/specifications/assigned-numbers/company-identifiers if you don't have a USB Vendor ID and need a Bluetooth Vendor ID + // device info: BlueKitchen GmbH, product 1, version 1 + device_id_create_sdp_record(_device_id_sdp_service_buffer, 0x10003, DEVICE_ID_VENDOR_ID_SOURCE_BLUETOOTH, BLUETOOTH_COMPANY_ID_BLUEKITCHEN_GMBH, 1, 1); + sdp_register_service(_device_id_sdp_service_buffer); + + // HID Device + hid_device_init(hid_boot_device, hidDescriptorSize, hidDescriptor); + + // register for HCI events + _hci_event_callback_registration.callback = PacketHandlerWrapper; + hci_add_event_handler(&_hci_event_callback_registration); + + // register for HID events + hid_device_register_packet_handler(PacketHandlerWrapper); + + hci_power_control(HCI_POWER_ON); + return true; + } + + static void PacketHandlerWrapper(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t packet_size) { + PicoBluetoothHID.packetHandler(packet_type, channel, packet, packet_size); + } + + void packetHandler(uint8_t type, uint16_t channel, uint8_t *packet, uint16_t size) { + uint8_t status; + if (type != HCI_EVENT_PACKET) { + return; + } + switch (hci_event_packet_get_type(packet)) { + case BTSTACK_EVENT_STATE: + if (btstack_event_state_get_state(packet) != HCI_STATE_WORKING) { + return; + } + _appState = APP_NOT_CONNECTED; + break; + + case HCI_EVENT_USER_CONFIRMATION_REQUEST: + // ssp: inform about user confirmation request + //log_info("SSP User Confirmation Request with numeric value '%06" PRIu32 "'\n", hci_event_user_confirmation_request_get_numeric_value(packet)); + //log_info("SSP User Confirmation Auto accept\n"); + break; + + case HCI_EVENT_HID_META: + switch (hci_event_hid_meta_get_subevent_code(packet)) { + case HID_SUBEVENT_CONNECTION_OPENED: + status = hid_subevent_connection_opened_get_status(packet); + if (status != ERROR_CODE_SUCCESS) { + // outgoing connection failed + _appState = APP_NOT_CONNECTED; + _hid_cid = 0; + return; + } + _appState = APP_CONNECTED; + _hid_cid = hid_subevent_connection_opened_get_hid_cid(packet); + if (_onOpened) { + _onOpened(type, channel, packet, size); + } + break; + case HID_SUBEVENT_CONNECTION_CLOSED: + _appState = APP_NOT_CONNECTED; + _hid_cid = 0; + if (_onClosed) { + _onClosed(type, channel, packet, size); + } + break; + case HID_SUBEVENT_CAN_SEND_NOW: + uint8_t report[2 + _sendReportLen]; + report[0] = 0xa1; + report[1] = _sendReportID; + memcpy(report + 2, _sendReport, _sendReportLen); + hid_device_send_interrupt_message(getCID(), report, sizeof(report)); + _needToSend = false; + if (_onCanSendNow) { + _onCanSendNow(type, channel, packet, size); + } + break; + } + } + } + + bool end() { + if (_running) { + hci_power_control(HCI_POWER_OFF); + } + _running = false; + _needToSend = false; + return true; + } + + bool connected() { + return _appState == APP_CONNECTED; + } + + bool send(int id, void *rpt, int len) { + _needToSend = true; + _sendReportID = id; + _sendReport = rpt; + _sendReportLen = len; + lockBluetooth(); + hid_device_request_can_send_now_event(getCID()); + unlockBluetooth(); + while (connected() && _needToSend) { + /* noop busy wait */ + } + return connected(); + } + + static void lockBluetooth() { + async_context_acquire_lock_blocking(cyw43_arch_async_context()); + } + + static void unlockBluetooth() { + async_context_release_lock(cyw43_arch_async_context()); + } + + uint16_t getCID() { + return _hid_cid; + } + +private: + bool _running = false; + + enum {APP_BOOTING, APP_NOT_CONNECTED, APP_CONNECTING, APP_CONNECTED} _appState = APP_BOOTING; + + BTCallback _onOpened = nullptr; + BTCallback _onClosed = nullptr; + BTCallback _onCanSendNow = nullptr; + + uint8_t _hid_service_buffer[300]; + uint8_t _device_id_sdp_service_buffer[100]; + btstack_packet_callback_registration_t _hci_event_callback_registration; + uint16_t _hid_cid; + + volatile bool _needToSend = false; + int _sendReportID; + void *_sendReport; + int _sendReportLen; +}; diff --git a/libraries/HID_Joystick b/libraries/HID_Joystick new file mode 160000 index 000000000..4eb3e28dc --- /dev/null +++ b/libraries/HID_Joystick @@ -0,0 +1 @@ +Subproject commit 4eb3e28dc20d44afe676a6c7e0e6264e29f82abb diff --git a/libraries/HID_Keyboard b/libraries/HID_Keyboard new file mode 160000 index 000000000..c0f474695 --- /dev/null +++ b/libraries/HID_Keyboard @@ -0,0 +1 @@ +Subproject commit c0f474695f83d63209fe4ad73ec5d90f27cd9e64 diff --git a/libraries/HID_Mouse b/libraries/HID_Mouse new file mode 160000 index 000000000..8bd9d96bd --- /dev/null +++ b/libraries/HID_Mouse @@ -0,0 +1 @@ +Subproject commit 8bd9d96bd9aa20df2923b9db69fda7744843a143 diff --git a/libraries/HTTPClient/examples/Authorization/Authorization.ino b/libraries/HTTPClient/examples/Authorization/Authorization.ino new file mode 100644 index 000000000..c1355b2c1 --- /dev/null +++ b/libraries/HTTPClient/examples/Authorization/Authorization.ino @@ -0,0 +1,87 @@ +/** + Authorization.ino + + Created on: 09.12.2015 + +*/ + +#include +#include +#include + +#ifndef STASSID +#define STASSID "your-ssid" +#define STAPSK "your-password" +#endif + +const char *ssid = STASSID; +const char *pass = STAPSK; + +WiFiMulti WiFiMulti; + +void setup() { + + Serial.begin(115200); + // Serial.setDebugOutput(true); + + Serial.println(); + Serial.println(); + Serial.println(); + + for (uint8_t t = 4; t > 0; t--) { + Serial.printf("[SETUP] WAIT %d...\n", t); + Serial.flush(); + delay(1000); + } + + WiFi.mode(WIFI_STA); + WiFiMulti.addAP(ssid, pass); +} + +void loop() { + // wait for WiFi connection + if ((WiFiMulti.run() == WL_CONNECTED)) { + + HTTPClient http; + http.setInsecure(); + + Serial.print("[HTTP] begin...\n"); + // configure traged server and url + + + http.begin("https://guest:guest@jigsaw.w3.org/HTTP/Basic/"); + + /* + // or + http.begin(client, "http://jigsaw.w3.org/HTTP/Basic/"); + http.setAuthorization("guest", "guest"); + + // or + http.begin(client, "http://jigsaw.w3.org/HTTP/Basic/"); + http.setAuthorization("Z3Vlc3Q6Z3Vlc3Q="); + */ + + + Serial.print("[HTTP] GET...\n"); + // start connection and send HTTP header + int httpCode = http.GET(); + + // httpCode will be negative on error + if (httpCode > 0) { + // HTTP header has been send and Server response header has been handled + Serial.printf("[HTTP] GET... code: %d\n", httpCode); + + // file found at server + if (httpCode == HTTP_CODE_OK) { + String payload = http.getString(); + Serial.println(payload); + } + } else { + Serial.printf("[HTTP] GET... failed, error: %s\n", http.errorToString(httpCode).c_str()); + } + + http.end(); + } + + delay(10000); +} diff --git a/libraries/HTTPClient/examples/BasicHttpClient/BasicHttpClient.ino b/libraries/HTTPClient/examples/BasicHttpClient/BasicHttpClient.ino new file mode 100644 index 000000000..c0efbcb95 --- /dev/null +++ b/libraries/HTTPClient/examples/BasicHttpClient/BasicHttpClient.ino @@ -0,0 +1,75 @@ +/** + BasicHTTPClient.ino + + Created on: 24.05.2015 + +*/ + +#include +#include +#include + +#ifndef STASSID +#define STASSID "your-ssid" +#define STAPSK "your-password" +#endif + +const char *ssid = STASSID; +const char *pass = STAPSK; + +WiFiMulti WiFiMulti; + +void setup() { + + Serial.begin(115200); + // Serial.setDebugOutput(true); + + Serial.println(); + Serial.println(); + Serial.println(); + + for (uint8_t t = 4; t > 0; t--) { + Serial.printf("[SETUP] WAIT %d...\n", t); + Serial.flush(); + delay(1000); + } + + WiFiMulti.addAP(ssid, pass); +} + +void loop() { + // wait for WiFi connection + if ((WiFiMulti.run() == WL_CONNECTED)) { + + HTTPClient http; + + Serial.print("[HTTP] begin...\n"); + if (http.begin("http://httpbin.org")) { // HTTP + + + Serial.print("[HTTP] GET...\n"); + // start connection and send HTTP header + int httpCode = http.GET(); + + // httpCode will be negative on error + if (httpCode > 0) { + // HTTP header has been send and Server response header has been handled + Serial.printf("[HTTP] GET... code: %d\n", httpCode); + + // file found at server + if (httpCode == HTTP_CODE_OK || httpCode == HTTP_CODE_MOVED_PERMANENTLY) { + String payload = http.getString(); + Serial.println(payload); + } + } else { + Serial.printf("[HTTP] GET... failed, error: %s\n", http.errorToString(httpCode).c_str()); + } + + http.end(); + } else { + Serial.printf("[HTTP} Unable to connect\n"); + } + } + + delay(10000); +} diff --git a/libraries/HTTPClient/examples/BasicHttpsClient-Hard/BasicHttpsClient-Hard.ino b/libraries/HTTPClient/examples/BasicHttpsClient-Hard/BasicHttpsClient-Hard.ino new file mode 100644 index 000000000..f6276237e --- /dev/null +++ b/libraries/HTTPClient/examples/BasicHttpsClient-Hard/BasicHttpsClient-Hard.ino @@ -0,0 +1,80 @@ +/** + BasicHTTPSClient-Hard.ino + + Demonstrates the manual way of making a WiFiClient and passing it in to the HTTPClient + + Created on: 20.08.2018 + +*/ + +#include +#include +#include + +#ifndef STASSID +#define STASSID "your-ssid" +#define STAPSK "your-password" +#endif + +const char *ssid = STASSID; +const char *pass = STAPSK; + +WiFiMulti WiFiMulti; + +void setup() { + + Serial.begin(115200); + + Serial.println(); + Serial.println(); + Serial.println(); + + for (uint8_t t = 4; t > 0; t--) { + Serial.printf("[SETUP] WAIT %d...\n", t); + Serial.flush(); + delay(1000); + } + + WiFi.mode(WIFI_STA); + WiFiMulti.addAP(ssid, pass); +} + +void loop() { + // wait for WiFi connection + if ((WiFiMulti.run() == WL_CONNECTED)) { + + WiFiClientSecure client; + client.setInsecure(); // Not safe against MITM attacks + + HTTPClient https; + + Serial.print("[HTTPS] begin...\n"); + if (https.begin(client, "https://jigsaw.w3.org/HTTP/connection.html")) { // HTTPS + + Serial.print("[HTTPS] GET...\n"); + // start connection and send HTTP header + int httpCode = https.GET(); + + // httpCode will be negative on error + if (httpCode > 0) { + // HTTP header has been send and Server response header has been handled + Serial.printf("[HTTPS] GET... code: %d\n", httpCode); + + // file found at server + if (httpCode == HTTP_CODE_OK || httpCode == HTTP_CODE_MOVED_PERMANENTLY) { + String payload = https.getString(); + Serial.println(payload); + } + } else { + Serial.printf("[HTTPS] GET... failed, error: %s\n", https.errorToString(httpCode).c_str()); + } + + https.end(); + } else { + Serial.printf("[HTTPS] Unable to connect\n"); + } + } + + Serial.println("Wait 10s before next round..."); + delay(10000); +} diff --git a/libraries/HTTPClient/examples/BasicHttpsClient/BasicHttpsClient.ino b/libraries/HTTPClient/examples/BasicHttpsClient/BasicHttpsClient.ino new file mode 100644 index 000000000..646951a97 --- /dev/null +++ b/libraries/HTTPClient/examples/BasicHttpsClient/BasicHttpsClient.ino @@ -0,0 +1,125 @@ +/** + BasicHTTPSClient.ino + + Created on: 20.08.2018 + +*/ + +#include +#include +#include + +#ifndef STASSID +#define STASSID "your-ssid" +#define STAPSK "your-password" +#endif + +const char *ssid = STASSID; +const char *pass = STAPSK; + +WiFiMulti WiFiMulti; + +void setup() { + + Serial.begin(115200); + // Serial.setDebugOutput(true); + + Serial.println(); + Serial.println(); + Serial.println(); + + for (uint8_t t = 4; t > 0; t--) { + Serial.printf("[SETUP] WAIT %d...\n", t); + Serial.flush(); + delay(1000); + } + + WiFi.mode(WIFI_STA); + WiFiMulti.addAP(ssid, pass); +} + +const char *jigsaw_cert = R"EOF( +-----BEGIN CERTIFICATE----- +MIIFKTCCBM+gAwIBAgIQAbTKhAICxb7iDJbE6qU/NzAKBggqhkjOPQQDAjBKMQsw +CQYDVQQGEwJVUzEZMBcGA1UEChMQQ2xvdWRmbGFyZSwgSW5jLjEgMB4GA1UEAxMX +Q2xvdWRmbGFyZSBJbmMgRUNDIENBLTMwHhcNMjIwMzE3MDAwMDAwWhcNMjMwMzE2 +MjM1OTU5WjB1MQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQG +A1UEBxMNU2FuIEZyYW5jaXNjbzEZMBcGA1UEChMQQ2xvdWRmbGFyZSwgSW5jLjEe +MBwGA1UEAxMVc25pLmNsb3VkZmxhcmVzc2wuY29tMFkwEwYHKoZIzj0CAQYIKoZI +zj0DAQcDQgAEYnkGDyrIltjRnxoVdy/xgndo+WGMOASzs2hHeCjbJ1KplKJc/ciK +XCWq/4+pTzSiVgTFhRmCdLcU1Fa05YFNQaOCA2owggNmMB8GA1UdIwQYMBaAFKXO +N+rrsHUOlGeItEX62SQQh5YfMB0GA1UdDgQWBBRIzOWGCDBB/PMrMucSrjIKqlgE +uDAvBgNVHREEKDAmghVzbmkuY2xvdWRmbGFyZXNzbC5jb22CDWppZ3Nhdy53My5v +cmcwDgYDVR0PAQH/BAQDAgeAMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcD +AjB7BgNVHR8EdDByMDegNaAzhjFodHRwOi8vY3JsMy5kaWdpY2VydC5jb20vQ2xv +dWRmbGFyZUluY0VDQ0NBLTMuY3JsMDegNaAzhjFodHRwOi8vY3JsNC5kaWdpY2Vy +dC5jb20vQ2xvdWRmbGFyZUluY0VDQ0NBLTMuY3JsMD4GA1UdIAQ3MDUwMwYGZ4EM +AQICMCkwJwYIKwYBBQUHAgEWG2h0dHA6Ly93d3cuZGlnaWNlcnQuY29tL0NQUzB2 +BggrBgEFBQcBAQRqMGgwJAYIKwYBBQUHMAGGGGh0dHA6Ly9vY3NwLmRpZ2ljZXJ0 +LmNvbTBABggrBgEFBQcwAoY0aHR0cDovL2NhY2VydHMuZGlnaWNlcnQuY29tL0Ns +b3VkZmxhcmVJbmNFQ0NDQS0zLmNydDAMBgNVHRMBAf8EAjAAMIIBfwYKKwYBBAHW +eQIEAgSCAW8EggFrAWkAdQDoPtDaPvUGNTLnVyi8iWvJA9PL0RFr7Otp4Xd9bQa9 +bgAAAX+aFPh6AAAEAwBGMEQCICivjuh2ywUYvVpTKHo65JEheR8dFq8QvBgEiXfw +m6q6AiAkxAgz77oboGQGetNmab45+peY+nAGOfyW9vi9S1gMaAB3ADXPGRu/sWxX +vw+tTG1Cy7u2JyAmUeo/4SrvqAPDO9ZMAAABf5oU+GEAAAQDAEgwRgIhANKeTNMy +GqUsCo7ph7YMWzrhMuDeyP8xPSiCtFzKcn/eAiEAyv5lgCUQ6K14V13zYfL99wZD +LFcIP/KZ1y7nuPAksTAAdwCzc3cH4YRQ+GOG1gWp3BEJSnktsWcMC4fc8AMOeTal +mgAAAX+aFPiWAAAEAwBIMEYCIQD6535jWw776D4vjyupP2fBw26CBMpVT5++k4rR +xqeOXwIhAIbEaEKkEq6JtpWWfVpTyDkMpMfTuiqYVe6REy2XsmEhMAoGCCqGSM49 +BAMCA0gAMEUCIH3r/puXZcX1bfUoBq2njuHe0bxWtvzDaz5k6WLYrazTAiEA+ePL +N6K5xrmaof185pVCxACPLc/BoKyUwMeC8iXCm00= +-----END CERTIFICATE----- +)EOF"; + +static int cnt = 0; + +void loop() { + // wait for WiFi connection + if ((WiFiMulti.run() == WL_CONNECTED)) { + HTTPClient https; + switch (cnt) { + case 0: + Serial.println("[HTTPS] using insecure SSL, not validating certificate"); + https.setInsecure(); // Note this is unsafe against MITM attacks + cnt++; + break; + case 1: + Serial.println("[HTTPS] using secure SSL, validating certificate"); + https.setCACert(jigsaw_cert); + cnt++; + break; + default: + Serial.println("[HTTPS] not setting any SSL verification settings, will fail"); + cnt = 0; + } + + Serial.print("[HTTPS] begin...\n"); + if (https.begin("https://jigsaw.w3.org/HTTP/connection.html")) { // HTTPS + + Serial.print("[HTTPS] GET...\n"); + // start connection and send HTTP header + int httpCode = https.GET(); + + // httpCode will be negative on error + if (httpCode > 0) { + // HTTP header has been send and Server response header has been handled + Serial.printf("[HTTPS] GET... code: %d\n", httpCode); + + // file found at server + if (httpCode == HTTP_CODE_OK || httpCode == HTTP_CODE_MOVED_PERMANENTLY) { + String payload = https.getString(); + Serial.println(payload); + } + } else { + Serial.printf("[HTTPS] GET... failed, error: %s\n", https.errorToString(httpCode).c_str()); + } + + https.end(); + } else { + Serial.printf("[HTTPS] Unable to connect\n"); + } + } + + Serial.println("Wait 10s before next round..."); + delay(10000); +} diff --git a/libraries/HTTPClient/examples/ChunkedClient/ChunkedClient.ino b/libraries/HTTPClient/examples/ChunkedClient/ChunkedClient.ino new file mode 100644 index 000000000..54d8cc450 --- /dev/null +++ b/libraries/HTTPClient/examples/ChunkedClient/ChunkedClient.ino @@ -0,0 +1,75 @@ +/** + ChunkedClient.ino + +*/ + +#include +#include +#include + +#ifndef STASSID +#define STASSID "your-ssid" +#define STAPSK "your-password" +#endif + +const char *ssid = STASSID; +const char *pass = STAPSK; + +WiFiMulti WiFiMulti; + +void setup() { + + Serial.begin(115200); + // Serial.setDebugOutput(true); + + Serial.println(); + Serial.println(); + Serial.println(); + + for (uint8_t t = 4; t > 0; t--) { + Serial.printf("[SETUP] WAIT %d...\n", t); + Serial.flush(); + delay(1000); + } + + WiFi.mode(WIFI_STA); + WiFiMulti.addAP(ssid, pass); +} + +void loop() { + // wait for WiFi connection + if ((WiFiMulti.run() == WL_CONNECTED)) { + HTTPClient http; + + Serial.print("[HTTP] begin...\n"); + if (http.begin("http://anglesharp.azurewebsites.net/Chunked")) { + + Serial.print("[HTTP] GET...\n"); + // start connection and send HTTP header + int httpCode = http.GET(); + + // httpCode will be negative on error + if (httpCode > 0) { + // HTTP header has been send and Server response header has been handled + Serial.printf("[HTTP] GET... code: %d\n", httpCode); + + // file found at server + if (httpCode == HTTP_CODE_OK || httpCode == HTTP_CODE_MOVED_PERMANENTLY) { + String payload = http.getString(); + Serial.println(payload); + } + } else { + Serial.printf("[HTTP] GET... failed, error: %s\n", http.errorToString(httpCode).c_str()); + } + + http.end(); + } else { + Serial.printf("[HTTP] Unable to connect\n"); + } + } + + Serial.println("Wait forever..."); + while (1) { + continue; + } +} diff --git a/libraries/HTTPClient/examples/DigestAuthorization/DigestAuthorization.ino b/libraries/HTTPClient/examples/DigestAuthorization/DigestAuthorization.ino new file mode 100644 index 000000000..def7eb2a8 --- /dev/null +++ b/libraries/HTTPClient/examples/DigestAuthorization/DigestAuthorization.ino @@ -0,0 +1,140 @@ +/* + This sketch shows how to handle HTTP Digest Authorization. + + Written by Parham Alvani and Sajjad Rahnama, 2018-01-07. + + This example is released into public domain, + or, at your option, CC0 licensed. +*/ + +#include + +#include + +#ifndef STASSID +#define STASSID "NOBABIES" +#define STAPSK "ElephantsAreGreat" +#endif + +const char* ssid = STASSID; +const char* ssidPassword = STAPSK; + +const char* username = "admin"; +const char* password = "admin"; + +const char* server = "http://httpbin.org"; +const char* uri = "/digest-auth/auth/admin/admin/MD5"; + +String exractParam(String& authReq, const String& param, const char delimit) { + int _begin = authReq.indexOf(param); + if (_begin == -1) { + return ""; + } + return authReq.substring(_begin + param.length(), authReq.indexOf(delimit, _begin + param.length())); +} + +String getCNonce(const int len) { + static const char alphanum[] = "0123456789" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "abcdefghijklmnopqrstuvwxyz"; + String s = ""; + + for (int i = 0; i < len; ++i) { + s += alphanum[rand() % (sizeof(alphanum) - 1)]; + } + + return s; +} + +String getDigestAuth(String& authReq, const String& username, const String& password, const String& method, const String& uri, unsigned int counter) { + // extracting required parameters for RFC 2069 simpler Digest + String realm = exractParam(authReq, "realm=\"", '"'); + String nonce = exractParam(authReq, "nonce=\"", '"'); + String cNonce = getCNonce(8); + + char nc[9]; + snprintf(nc, sizeof(nc), "%08x", counter); + + // parameters for the RFC 2617 newer Digest + MD5Builder md5; + md5.begin(); + md5.add(username + ":" + realm + ":" + password); // md5 of the user:realm:user + md5.calculate(); + String h1 = md5.toString(); + + md5.begin(); + md5.add(method + ":" + uri); + md5.calculate(); + String h2 = md5.toString(); + + md5.begin(); + md5.add(h1 + ":" + nonce + ":" + String(nc) + ":" + cNonce + ":" + "auth" + ":" + h2); + md5.calculate(); + String response = md5.toString(); + + String authorization = "Digest username=\"" + username + "\", realm=\"" + realm + "\", nonce=\"" + nonce + "\", uri=\"" + uri + "\", algorithm=\"MD5\", qop=auth, nc=" + String(nc) + ", cnonce=\"" + cNonce + "\", response=\"" + response + "\""; + Serial.println(authorization); + + return authorization; +} + +void setup() { + Serial.begin(115200); + + WiFi.mode(WIFI_STA); + WiFi.begin(ssid, ssidPassword); + + while (WiFi.status() != WL_CONNECTED) { + delay(500); + Serial.print("."); + } + + Serial.println(""); + Serial.println("WiFi connected"); + Serial.println("IP address: "); + Serial.println(WiFi.localIP()); + + srand(rp2040.getCycleCount()); +} + +void loop() { + HTTPClient http; + + Serial.print("[HTTP] begin...\n"); + + // configure target server and url + http.begin(String(server) + String(uri)); + + + const char* keys[] = { "WWW-Authenticate" }; + http.collectHeaders(keys, 1); + + Serial.print("[HTTP] GET...\n"); + // start connection and send HTTP header + int httpCode = http.GET(); + + if (httpCode > 0) { + String authReq = http.header("WWW-Authenticate"); + Serial.println(authReq); + + String authorization = getDigestAuth(authReq, String(username), String(password), "GET", String(uri), 1); + + http.end(); + http.begin(String(server) + String(uri)); + + http.addHeader("Authorization", authorization); + + int httpCode = http.GET(); + if (httpCode > 0) { + String payload = http.getString(); + Serial.println(payload); + } else { + Serial.printf("[HTTP] GET... failed, error: %s\n", http.errorToString(httpCode).c_str()); + } + } else { + Serial.printf("[HTTP] GET... failed, error: %s\n", http.errorToString(httpCode).c_str()); + } + + http.end(); + delay(10000); +} diff --git a/libraries/HTTPClient/examples/PostHttpClient/PostHttpClient.ino b/libraries/HTTPClient/examples/PostHttpClient/PostHttpClient.ino new file mode 100644 index 000000000..34d5fadb0 --- /dev/null +++ b/libraries/HTTPClient/examples/PostHttpClient/PostHttpClient.ino @@ -0,0 +1,71 @@ +/** + PostHTTPClient.ino + + Created on: 21.11.2016 + +*/ + +#include +#include + +#ifndef STASSID +#define STASSID "your-ssid" +#define STAPSK "your-password" +#endif + +void setup() { + + Serial.begin(115200); + + Serial.println(); + Serial.println(); + Serial.println(); + + WiFi.begin(STASSID, STAPSK); + + while (WiFi.status() != WL_CONNECTED) { + delay(500); + Serial.print("."); + } + Serial.println(""); + Serial.print("Connected! IP address: "); + Serial.println(WiFi.localIP()); +} + +void loop() { + // wait for WiFi connection + if ((WiFi.status() == WL_CONNECTED)) { + + HTTPClient http; + http.setInsecure(); + + Serial.print("[HTTP] begin...\n"); + // configure target server and url + http.begin("https://httpbin.org/post"); + http.addHeader("Content-Type", "application/json"); + + Serial.print("[HTTP] POST...\n"); + // start connection and send HTTP header and body + int httpCode = http.POST("{\"hello\":\"world\"}"); + + // httpCode will be negative on error + if (httpCode > 0) { + // HTTP header has been send and Server response header has been handled + Serial.printf("[HTTP] POST... code: %d\n", httpCode); + + // file found at server + if (httpCode == HTTP_CODE_OK) { + const String& payload = http.getString(); + Serial.println("received payload:\n<<"); + Serial.println(payload); + Serial.println(">>"); + } + } else { + Serial.printf("[HTTP] POST... failed, error: %s\n", http.errorToString(httpCode).c_str()); + } + + http.end(); + } + + delay(10000); +} diff --git a/libraries/HTTPClient/examples/ReuseConnectionV2/ReuseConnectionV2.ino b/libraries/HTTPClient/examples/ReuseConnectionV2/ReuseConnectionV2.ino new file mode 100644 index 000000000..73f4266fc --- /dev/null +++ b/libraries/HTTPClient/examples/ReuseConnectionV2/ReuseConnectionV2.ino @@ -0,0 +1,81 @@ +/** + reuseConnectionV2.ino + + Created on: 22.11.2015 + + This example reuses the http connection and also restores the connection if the connection is lost +*/ + + +#include +#include +#include + +#ifndef STASSID +#define STASSID "your-ssid" +#define STAPSK "your-password" +#endif + +WiFiMulti WiFiMulti; + +HTTPClient http; + +void setup() { + + Serial.begin(115200); + // Serial.setDebugOutput(true); + + Serial.println(); + Serial.println(); + Serial.println("Connecting to WiFi..."); + + WiFi.mode(WIFI_STA); + WiFiMulti.addAP(STASSID, STAPSK); + + // wait for WiFi connection + while ((WiFiMulti.run() != WL_CONNECTED)) { + Serial.write('.'); + delay(500); + } + Serial.println(" connected to WiFi"); + + // allow reuse (if server supports it) + http.setReuse(true); + http.setInsecure(); + + http.begin("https://jigsaw.w3.org/HTTP/connection.html"); + // http.begin(client, "jigsaw.w3.org", 80, "/HTTP/connection.html"); +} + +int pass = 0; + +void loop() { + // First 10 loop()s, retrieve the URL + if (pass < 10) { + pass++; + Serial.printf("Reuse connection example, GET url for the %d time\n", pass); + int httpCode = http.GET(); + if (httpCode > 0) { + Serial.printf("[HTTP] GET... code: %d\n", httpCode); + + // file found at server + if (httpCode == HTTP_CODE_OK) { + http.writeToStream(&Serial); + } + } else { + Serial.printf("[HTTP] GET... failed, error: %s\n", http.errorToString(httpCode).c_str()); + // Something went wrong with the connection, try to reconnect + http.end(); + http.begin("https://jigsaw.w3.org/HTTP/connection.html"); + // http.begin(client, "jigsaw.w3.org", 80, "/HTTP/connection.html"); + } + + if (pass == 10) { + http.end(); + Serial.println("Done testing"); + } else { + Serial.println("\n\n\nWait 5 second...\n"); + delay(5000); + } + } +} diff --git a/libraries/HTTPClient/examples/StreamHttpsClient/StreamHttpsClient.ino b/libraries/HTTPClient/examples/StreamHttpsClient/StreamHttpsClient.ino new file mode 100644 index 000000000..5584f6939 --- /dev/null +++ b/libraries/HTTPClient/examples/StreamHttpsClient/StreamHttpsClient.ino @@ -0,0 +1,105 @@ +/** + StreamHTTPClient.ino + + Created on: 24.05.2015 + +*/ + +#include +#include +#include + +#ifndef STASSID +#define STASSID "your-ssid" +#define STAPSK "your-password" +#endif + +const char *ssid = STASSID; +const char *pass = STAPSK; + +WiFiMulti WiFiMulti; + +void setup() { + + Serial.begin(115200); + // Serial.setDebugOutput(true); + + Serial.println(); + Serial.println(); + Serial.println(); + + for (uint8_t t = 4; t > 0; t--) { + Serial.printf("[SETUP] WAIT %d...\n", t); + Serial.flush(); + delay(1000); + } + + WiFi.mode(WIFI_STA); + WiFiMulti.addAP(ssid, pass); +} + +void loop() { + // wait for WiFi connection + if ((WiFiMulti.run() == WL_CONNECTED)) { + + Serial.print("[HTTPS] begin...\n"); + + // configure server and url + const char *fp = "41:FA:FD:B6:96:5F:33:09:F4:ED:09:28:BF:66:4D:5B:A2:88:03:65"; + + HTTPClient https; + https.setFingerprint(fp); + + if (https.begin("https://www.trustedfirmware.org/projects/mbed-tls")) { + + Serial.print("[HTTPS] GET...\n"); + // start connection and send HTTP header + int httpCode = https.GET(); + if (httpCode > 0) { + // HTTP header has been send and Server response header has been handled + Serial.printf("[HTTPS] GET... code: %d\n", httpCode); + + // file found at server + if (httpCode == HTTP_CODE_OK) { + + // get length of document (is -1 when Server sends no Content-Length header) + int len = https.getSize(); + + // create buffer for read + static uint8_t buff[128] = { 0 }; + + // read all data from server + while (https.connected() && (len > 0 || len == -1)) { + // get available data size + size_t size = https.getStreamPtr()->available(); + + if (size) { + // read up to 128 byte + int c = https.getStreamPtr()->readBytes(buff, ((size > sizeof(buff)) ? sizeof(buff) : size)); + + // write it to Serial + Serial.write(buff, c); + + if (len > 0) { + len -= c; + } + } + delay(1); + } + + Serial.println(); + Serial.print("[HTTPS] connection closed or file end.\n"); + } + } else { + Serial.printf("[HTTPS] GET... failed, error: %s\n", https.errorToString(httpCode).c_str()); + } + + https.end(); + } else { + Serial.printf("Unable to connect\n"); + } + } + + Serial.println("Wait 10s before the next round..."); + delay(10000); +} diff --git a/libraries/HTTPClient/keywords.txt b/libraries/HTTPClient/keywords.txt new file mode 100644 index 000000000..fe79fdcd4 --- /dev/null +++ b/libraries/HTTPClient/keywords.txt @@ -0,0 +1,149 @@ +####################################### +# Syntax Coloring Map For HTTPClient +####################################### + +####################################### +# Library (KEYWORD3) +####################################### + +HTTPClient KEYWORD3 RESERVED_WORD + +####################################### +# Datatypes (KEYWORD1) +####################################### + +t_http_codes KEYWORD1 DATA_TYPE +transferEncoding_t KEYWORD1 DATA_TYPE +TransportTraits KEYWORD1 DATA_TYPE +TransportTraitsPtr KEYWORD1 DATA_TYPE +StreamString KEYWORD1 DATA_TYPE +HTTPClient KEYWORD1 DATA_TYPE + +####################################### +# Methods and Functions (KEYWORD2) +####################################### + +begin KEYWORD2 +end KEYWORD2 +connected KEYWORD2 +setReuse KEYWORD2 +setUserAgent KEYWORD2 +setAuthorization KEYWORD2 +setTimeout KEYWORD2 +useHTTP10 KEYWORD2 +GET KEYWORD2 +POST KEYWORD2 +PUT KEYWORD2 +PATCH KEYWORD2 +sendRequest KEYWORD2 +addHeader KEYWORD2 +collectHeaders KEYWORD2 +header KEYWORD2 +headerName KEYWORD2 +headers KEYWORD2 +hasHeader KEYWORD2 +getSize KEYWORD2 +getStream KEYWORD2 +getStreamPtr KEYWORD2 +writeToStream KEYWORD2 +getString KEYWORD2 +errorToString KEYWORD2 + +setSession KEYWORD2 +setInsecure KEYWORD2 +setKnownKey KEYWORD2 +setFingerprint KEYWORD2 +allowSelfSignedCerts KEYWORD2 +setTrustAnchors KEYWORD2 +setX509Time KEYWORD2 +setClientRSACert KEYWORD2 +setClientECCert KEYWORD2 +setBufferSizes KEYWORD2 +setCertStore KEYWORD2 +setCiphers KEYWORD2 +setCiphersLessSecure KEYWORD2 +setSSLVersion KEYWORD2 +setCACert KEYWORD2 +setCertificate KEYWORD2 +setPrivateKey KEYWORD2 +loadCACert KEYWORD2 +loadCertificate KEYWORD2 +loadPrivateKey KEYWORD2 + +####################################### +# Constants (LITERAL1) +####################################### + +HTTPCLIENT_DEFAULT_TCP_TIMEOUT LITERAL1 RESERVED_WORD_2 +HTTPC_ERROR_CONNECTION_REFUSED LITERAL1 RESERVED_WORD_2 +HTTPC_ERROR_SEND_HEADER_FAILED LITERAL1 RESERVED_WORD_2 +HTTPC_ERROR_SEND_PAYLOAD_FAILED LITERAL1 RESERVED_WORD_2 +HTTPC_ERROR_NOT_CONNECTED LITERAL1 RESERVED_WORD_2 +HTTPC_ERROR_CONNECTION_LOST LITERAL1 RESERVED_WORD_2 +HTTPC_ERROR_NO_STREAM LITERAL1 RESERVED_WORD_2 +HTTPC_ERROR_NO_HTTP_SERVER LITERAL1 RESERVED_WORD_2 +HTTPC_ERROR_TOO_LESS_RAM LITERAL1 RESERVED_WORD_2 +HTTPC_ERROR_ENCODING LITERAL1 RESERVED_WORD_2 +HTTPC_ERROR_STREAM_WRITE LITERAL1 RESERVED_WORD_2 +HTTPC_ERROR_READ_TIMEOUT LITERAL1 RESERVED_WORD_2 +HTTP_TCP_BUFFER_SIZE LITERAL1 RESERVED_WORD_2 +HTTP_CODE_CONTINUE LITERAL1 RESERVED_WORD_2 +HTTP_CODE_SWITCHING_PROTOCOLS LITERAL1 RESERVED_WORD_2 +HTTP_CODE_PROCESSING LITERAL1 RESERVED_WORD_2 +HTTP_CODE_OK LITERAL1 RESERVED_WORD_2 +HTTP_CODE_CREATED LITERAL1 RESERVED_WORD_2 +HTTP_CODE_ACCEPTED LITERAL1 RESERVED_WORD_2 +HTTP_CODE_NON_AUTHORITATIVE_INFORMATION LITERAL1 RESERVED_WORD_2 +HTTP_CODE_NO_CONTENT LITERAL1 RESERVED_WORD_2 +HTTP_CODE_RESET_CONTENT LITERAL1 RESERVED_WORD_2 +HTTP_CODE_PARTIAL_CONTENT LITERAL1 RESERVED_WORD_2 +HTTP_CODE_MULTI_STATUS LITERAL1 RESERVED_WORD_2 +HTTP_CODE_ALREADY_REPORTED LITERAL1 RESERVED_WORD_2 +HTTP_CODE_IM_USED LITERAL1 RESERVED_WORD_2 +HTTP_CODE_MULTIPLE_CHOICES LITERAL1 RESERVED_WORD_2 +HTTP_CODE_MOVED_PERMANENTLY LITERAL1 RESERVED_WORD_2 +HTTP_CODE_FOUND LITERAL1 RESERVED_WORD_2 +HTTP_CODE_SEE_OTHER LITERAL1 RESERVED_WORD_2 +HTTP_CODE_NOT_MODIFIED LITERAL1 RESERVED_WORD_2 +HTTP_CODE_USE_PROXY LITERAL1 RESERVED_WORD_2 +HTTP_CODE_TEMPORARY_REDIRECT LITERAL1 RESERVED_WORD_2 +HTTP_CODE_PERMANENT_REDIRECT LITERAL1 RESERVED_WORD_2 +HTTP_CODE_BAD_REQUEST LITERAL1 RESERVED_WORD_2 +HTTP_CODE_UNAUTHORIZED LITERAL1 RESERVED_WORD_2 +HTTP_CODE_PAYMENT_REQUIRED LITERAL1 RESERVED_WORD_2 +HTTP_CODE_FORBIDDEN LITERAL1 RESERVED_WORD_2 +HTTP_CODE_NOT_FOUND LITERAL1 RESERVED_WORD_2 +HTTP_CODE_METHOD_NOT_ALLOWED LITERAL1 RESERVED_WORD_2 +HTTP_CODE_NOT_ACCEPTABLE LITERAL1 RESERVED_WORD_2 +HTTP_CODE_PROXY_AUTHENTICATION_REQUIRED LITERAL1 RESERVED_WORD_2 +HTTP_CODE_REQUEST_TIMEOUT LITERAL1 RESERVED_WORD_2 +HTTP_CODE_CONFLICT LITERAL1 RESERVED_WORD_2 +HTTP_CODE_GONE LITERAL1 RESERVED_WORD_2 +HTTP_CODE_LENGTH_REQUIRED LITERAL1 RESERVED_WORD_2 +HTTP_CODE_PRECONDITION_FAILED LITERAL1 RESERVED_WORD_2 +HTTP_CODE_PAYLOAD_TOO_LARGE LITERAL1 RESERVED_WORD_2 +HTTP_CODE_URI_TOO_LONG LITERAL1 RESERVED_WORD_2 +HTTP_CODE_UNSUPPORTED_MEDIA_TYPE LITERAL1 RESERVED_WORD_2 +HTTP_CODE_RANGE_NOT_SATISFIABLE LITERAL1 RESERVED_WORD_2 +HTTP_CODE_EXPECTATION_FAILED LITERAL1 RESERVED_WORD_2 +HTTP_CODE_MISDIRECTED_REQUEST LITERAL1 RESERVED_WORD_2 +HTTP_CODE_UNPROCESSABLE_ENTITY LITERAL1 RESERVED_WORD_2 +HTTP_CODE_LOCKED LITERAL1 RESERVED_WORD_2 +HTTP_CODE_FAILED_DEPENDENCY LITERAL1 RESERVED_WORD_2 +HTTP_CODE_UPGRADE_REQUIRED LITERAL1 RESERVED_WORD_2 +HTTP_CODE_PRECONDITION_REQUIRED LITERAL1 RESERVED_WORD_2 +HTTP_CODE_TOO_MANY_REQUESTS LITERAL1 RESERVED_WORD_2 +HTTP_CODE_REQUEST_HEADER_FIELDS_TOO_LARGE LITERAL1 RESERVED_WORD_2 +HTTP_CODE_INTERNAL_SERVER_ERROR LITERAL1 RESERVED_WORD_2 +HTTP_CODE_NOT_IMPLEMENTED LITERAL1 RESERVED_WORD_2 +HTTP_CODE_BAD_GATEWAY LITERAL1 RESERVED_WORD_2 +HTTP_CODE_SERVICE_UNAVAILABLE LITERAL1 RESERVED_WORD_2 +HTTP_CODE_GATEWAY_TIMEOUT LITERAL1 RESERVED_WORD_2 +HTTP_CODE_HTTP_VERSION_NOT_SUPPORTED LITERAL1 RESERVED_WORD_2 +HTTP_CODE_VARIANT_ALSO_NEGOTIATES LITERAL1 RESERVED_WORD_2 +HTTP_CODE_INSUFFICIENT_STORAGE LITERAL1 RESERVED_WORD_2 +HTTP_CODE_LOOP_DETECTED LITERAL1 RESERVED_WORD_2 +HTTP_CODE_NOT_EXTENDED LITERAL1 RESERVED_WORD_2 +HTTP_CODE_NETWORK_AUTHENTICATION_REQUIRED LITERAL1 RESERVED_WORD_2 +HTTPC_TE_IDENTITY LITERAL1 RESERVED_WORD_2 +HTTPC_TE_CHUNKED LITERAL1 RESERVED_WORD_2 diff --git a/libraries/HTTPClient/library.properties b/libraries/HTTPClient/library.properties new file mode 100644 index 000000000..cb6eef0cc --- /dev/null +++ b/libraries/HTTPClient/library.properties @@ -0,0 +1,10 @@ +name=HTTPClient +version=1.2 +author=Markus Sattler +maintainer=Earle F. Philhower, III +sentence=http Client for ESP8266, portes to the Pico +paragraph= +category=Communication +url=https://github.com/earlephilhower/arduino-pico/blob/master/libraries/HTTPClient +architectures=rp2040 +dot_a_linkage=true diff --git a/libraries/HTTPClient/src/HTTPClient.cpp b/libraries/HTTPClient/src/HTTPClient.cpp new file mode 100644 index 000000000..0d1cd1f47 --- /dev/null +++ b/libraries/HTTPClient/src/HTTPClient.cpp @@ -0,0 +1,1212 @@ +/** + HTTPClient.cpp + + Created on: 02.11.2015 + + Copyright (c) 2015 Markus Sattler. All rights reserved. + This file is part of the ESP8266HTTPClient for Arduino. + + Modified 2022 by Earle F. Philhower, III for the Pico RP2040 + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +*/ +#include + +#include "HTTPClient.h" +#include +#include "base64.h" + +// per https://github.com/esp8266/Arduino/issues/8231 +// make sure HTTPClient can be utilized as a movable class member +static_assert(std::is_default_constructible_v, ""); +static_assert(!std::is_copy_constructible_v, ""); +static_assert(std::is_move_constructible_v, ""); +static_assert(std::is_move_assignable_v, ""); + +static const char defaultUserAgentPstr[] PROGMEM = "Pico"; +const String HTTPClient::defaultUserAgent = defaultUserAgentPstr; + +//static int StreamReportToHttpClientReport (Stream::Report streamSendError) +//{ +// switch (streamSendError) +// { +// case Stream::Report::TimedOut: return HTTPC_ERROR_READ_TIMEOUT; +// case Stream::Report::ReadError: return HTTPC_ERROR_NO_STREAM; +// case Stream::Report::WriteError: return HTTPC_ERROR_STREAM_WRITE; +// case Stream::Report::ShortOperation: return HTTPC_ERROR_STREAM_WRITE; +// case Stream::Report::Success: return 0; +// } +// return 0; // never reached, keep gcc quiet +//} + +// Wrappers for ESP8266-specific Arduino API changes +static size_t StreamSendSize(Stream *s, Print *c, int size) { + int sent = 0; + if (size < 0) { + size = 999999; // Transfer until read fails + } + uint32_t start = millis(); + while ((sent < size) && (millis() - start < 5000)) { + int x = s->read(); + if (x < 0) { + break; + } else if (c->write(x)) { + sent++; + } else { + break; + } + } + return sent; +} + +class StreamConstPtr { +public: + StreamConstPtr(const uint8_t *payload, size_t size) { + _payload = payload; + _size = size; + } + StreamConstPtr(const String& string) { + _payload = (const uint8_t *)string.c_str(); + _size = string.length(); + } + size_t sendAll(Client *dst) { + uint32_t start = millis(); + size_t sent = 0; + while ((sent < _size) && (millis() - start < 5000)) { + size_t towrite = std::min((size_t)128, _size - sent); + auto wrote = dst->write(_payload, towrite); + if (wrote <= 0) { + break; + } + sent += wrote; + _payload += wrote; + } + return sent; + } + const uint8_t *_payload; + size_t _size; +}; + + +void HTTPClient::clear() { + _returnCode = 0; + _size = -1; + _headers = ""; + _location = ""; + _payload.reset(); +} + + + +/** + parsing the url for all needed parameters + @param client Client& + @param url String + @param https bool + @return success bool +*/ +bool HTTPClient::begin(String url) { + // check for : (http: or https:) + int index = url.indexOf(':'); + if (index < 0) { + DEBUG_HTTPCLIENT("[HTTP-Client][begin] failed to parse protocol\n"); + return false; + } + + String protocol = url.substring(0, index); + protocol.toLowerCase(); + if (protocol != "http" && protocol != "https") { + DEBUG_HTTPCLIENT("[HTTP-Client][begin] unknown protocol '%s'\n", protocol.c_str()); + return false; + } + + _port = (protocol == "https" ? 443 : 80); + if (!_client()) { + if (protocol == "https") { + _tls(); + } else { + _clientMade = new WiFiClient(); + _clientGiven = false; + } + } + + return beginInternal(url, protocol.c_str()); +} + + +/** + directly supply all needed parameters + @param client Client& + @param host String + @param port uint16_t + @param uri String + @param https bool + @return success bool +*/ +bool HTTPClient::begin(String host, uint16_t port, String uri, bool https) { + // Disconnect when reusing HTTPClient to talk to a different host + if (_host != host) { + _canReuse = false; + disconnect(true); + } + + clear(); + + _host = host; + _port = port; + _uri = uri; + _protocol = (https ? "https" : "http"); + if (!_client()) { + if (https) { + _tls(); + } else { + _clientMade = new WiFiClient(); + _clientGiven = false; + } + } + return true; +} + + + +/** + parsing the url for all needed parameters + @param client Client& + @param url String + @param https bool + @return success bool +*/ +bool HTTPClient::begin(WiFiClient &client, const String& url) { + // check for : (http: or https:) + int index = url.indexOf(':'); + if (index < 0) { + DEBUG_HTTPCLIENT("[HTTP-Client][begin] failed to parse protocol\n"); + return false; + } + + String protocol = url.substring(0, index); + protocol.toLowerCase(); + if (protocol != "http" && protocol != "https") { + DEBUG_HTTPCLIENT("[HTTP-Client][begin] unknown protocol '%s'\n", protocol.c_str()); + return false; + } + + _port = (protocol == "https" ? 443 : 80); + _clientIn = client.clone(); + _clientGiven = true; + if (_clientMade) { + delete _clientMade; + _clientMade = nullptr; + } + + + return beginInternal(url, protocol.c_str()); +} + + +/** + directly supply all needed parameters + @param client Client& + @param host String + @param port uint16_t + @param uri String + @param https bool + @return success bool +*/ +bool HTTPClient::begin(WiFiClient &client, const String& host, uint16_t port, const String& uri, bool https) { + // Disconnect when reusing HTTPClient to talk to a different host + if ((_host != "") && (_host != host)) { + _canReuse = false; + disconnect(true); + } + + _clientIn = client.clone(); + _clientGiven = true; + if (_clientMade) { + delete _clientMade; + _clientMade = nullptr; + } + + clear(); + + _host = host; + _port = port; + _uri = uri; + _protocol = (https ? "https" : "http"); + return true; +} + + + + + +bool HTTPClient::beginInternal(const String& __url, const char* expectedProtocol) { + String url(__url); + + DEBUG_HTTPCLIENT("[HTTP-Client][begin] url: %s\n", url.c_str()); + clear(); + + // check for : (http: or https: + int index = url.indexOf(':'); + if (index < 0) { + DEBUG_HTTPCLIENT("[HTTP-Client][begin] failed to parse protocol\n"); + return false; + } + + _protocol = url.substring(0, index); + _protocol.toLowerCase(); + url.remove(0, (index + 3)); // remove http:// or https:// + + if (_protocol == "http") { + // set default port for 'http' + _port = 80; + } else if (_protocol == "https") { + // set default port for 'https' + _port = 443; + } else { + DEBUG_HTTPCLIENT("[HTTP-Client][begin] unsupported protocol: %s\n", _protocol.c_str()); + return false; + } + + index = url.indexOf('/'); + String host = url.substring(0, index); + url.remove(0, index); // remove host part + + // get Authorization + index = host.indexOf('@'); + if (index >= 0) { + // auth info + String auth = host.substring(0, index); + host.remove(0, index + 1); // remove auth part including @ + _base64Authorization = base64::encode(auth, false /* doNewLines */); + } + + const String oldHost = _host; + + // get port + index = host.indexOf(':'); + if (index >= 0) { + _host = host.substring(0, index); // hostname + host.remove(0, (index + 1)); // remove hostname + : + _port = host.toInt(); // get port + } else { + _host = host; + } + + // Disconnect when reusing HTTPClient to talk to a different host + if (oldHost != "" && _host != oldHost) { + _canReuse = false; + disconnect(true); + } + + _uri = url; + + if (expectedProtocol != nullptr && _protocol != expectedProtocol) { + DEBUG_HTTPCLIENT("[HTTP-Client][begin] unexpected protocol: %s, expected %s\n", _protocol.c_str(), expectedProtocol); + return false; + } + DEBUG_HTTPCLIENT("[HTTP-Client][begin] host: %s port: %d url: %s\n", _host.c_str(), _port, _uri.c_str()); + return true; +} + + +/** + end + called after the payload is handled +*/ +void HTTPClient::end(void) { + disconnect(false); + clear(); + if (_clientMade) { + delete _clientMade; + _clientMade = nullptr; + _clientTLS = false; + } +} + +/** + disconnect + close the TCP socket +*/ +void HTTPClient::disconnect(bool preserveClient) { + if (connected()) { + if (_client()->available() > 0) { + DEBUG_HTTPCLIENT("[HTTP-Client][end] still data in buffer (%d), clean up.\n", _client()->available()); + while (_client()->available() > 0) { + _client()->read(); + } + } + + if (_reuse && _canReuse) { + DEBUG_HTTPCLIENT("[HTTP-Client][end] tcp keep open for reuse\n"); + } else { + DEBUG_HTTPCLIENT("[HTTP-Client][end] tcp stop\n"); + if (_client()) { + _client()->stop(); + if (!preserveClient) { + _clientIn = nullptr; + if (_clientMade) { + delete _clientMade; + _clientMade = nullptr; + } + _clientGiven = false; + } + } + } + } else { + if (!preserveClient && _client()) { // Also destroy _client if not connected() + _clientIn = nullptr; + if (_clientMade) { + delete _clientMade; + _clientMade = nullptr; + } + _clientGiven = false; + } + + DEBUG_HTTPCLIENT("[HTTP-Client][end] tcp is closed\n"); + } +} + +/** + connected + @return connected status +*/ +bool HTTPClient::connected() { + if (_client()) { + return (_client()->connected() || (_client()->available() > 0)); + } + return false; +} + +/** + try to reuse the connection to the server + keep-alive + @param reuse bool +*/ +void HTTPClient::setReuse(bool reuse) { + _reuse = reuse; +} + +/** + set User Agent + @param userAgent const char +*/ +void HTTPClient::setUserAgent(const String& userAgent) { + _userAgent = userAgent; +} + +/** + set the Authorizatio for the http request + @param user const char + @param password const char +*/ +void HTTPClient::setAuthorization(const char * user, const char * password) { + if (user && password) { + String auth = user; + auth += ':'; + auth += password; + _base64Authorization = base64::encode(auth, false /* doNewLines */); + } +} + +/** + set the Authorization for the http request + @param auth const char * base64 +*/ +void HTTPClient::setAuthorization(const char * auth) { + if (auth) { + setAuthorization(String(auth)); + } +} + +/** + set the Authorization for the http request + @param auth String base64 +*/ +void HTTPClient::setAuthorization(String auth) { + _base64Authorization = std::move(auth); + _base64Authorization.replace(String('\n'), ""); +} + +/** + set the timeout for the TCP connection + @param timeout unsigned int +*/ +void HTTPClient::setTimeout(uint16_t timeout) { + _tcpTimeout = timeout; + if (connected()) { + _client()->setTimeout(timeout); + } +} + +/** + set the URL to a new value. Handy for following redirects. + @param url +*/ +bool HTTPClient::setURL(const String& url) { + // if the new location is only a path then only update the URI + if (url && url[0] == '/') { + _uri = url; + clear(); + return true; + } + + if (!url.startsWith(_protocol + ':')) { + DEBUG_HTTPCLIENT("[HTTP-Client][setURL] new URL not the same protocol, expected '%s', URL: '%s'\n", _protocol.c_str(), url.c_str()); + return false; + } + // disconnect but preserve _client (clear _canReuse so disconnect will close the connection) + _canReuse = false; + disconnect(true); + return beginInternal(url, nullptr); +} + +/** + set redirect follow mode. See `followRedirects_t` enum for available modes. + @param follow +*/ +void HTTPClient::setFollowRedirects(followRedirects_t follow) { + _followRedirects = follow; +} + +void HTTPClient::setRedirectLimit(uint16_t limit) { + _redirectLimit = limit; +} + +/** + use HTTP1.0 + @param useHTTP10 bool +*/ +void HTTPClient::useHTTP10(bool useHTTP10) { + _useHTTP10 = useHTTP10; + _reuse = !useHTTP10; +} + +/** + send a GET request + @return http code +*/ +int HTTPClient::GET() { + return sendRequest("GET"); +} +/** + send a DELETE request + @return http code +*/ +int HTTPClient::DELETE() { + return sendRequest("DELETE"); +} + +/** + sends a post request to the server + @param payload const uint8_t + @param size size_t + @return http code +*/ +int HTTPClient::POST(const uint8_t* payload, size_t size) { + return sendRequest("POST", payload, size); +} + +int HTTPClient::POST(const String& payload) { + return POST((uint8_t *) payload.c_str(), payload.length()); +} + +/** + sends a put request to the server + @param payload uint8_t + @param size size_t + @return http code +*/ +int HTTPClient::PUT(const uint8_t* payload, size_t size) { + return sendRequest("PUT", payload, size); +} + +int HTTPClient::PUT(const String& payload) { + return PUT((const uint8_t *) payload.c_str(), payload.length()); +} + +/** + sends a patch request to the server + @param payload const uint8_t + @param size size_t + @return http code +*/ +int HTTPClient::PATCH(const uint8_t * payload, size_t size) { + return sendRequest("PATCH", payload, size); +} + +int HTTPClient::PATCH(const String& payload) { + return PATCH((const uint8_t *) payload.c_str(), payload.length()); +} + +/** + sendRequest + @param type const char * "GET", "POST", .... + @param payload String data for the message body + @return +*/ +int HTTPClient::sendRequest(const char * type, const String& payload) { + return sendRequest(type, (const uint8_t *) payload.c_str(), payload.length()); +} + +/** + sendRequest + @param type const char * "GET", "POST", .... + @param payload const uint8_t * data for the message body if null not send + @param size size_t size for the message body if 0 not send + @return -1 if no info or > 0 when Content-Length is set by server +*/ +int HTTPClient::sendRequest(const char * type, const uint8_t * payload, size_t size) { + int code; + bool redirect = false; + uint16_t redirectCount = 0; + do { + // wipe out any existing headers from previous request + for (size_t i = 0; i < _headerKeysCount; i++) { + if (_currentHeaders[i].value.length() > 0) { + _currentHeaders[i].value = ""; + } + } + + DEBUG_HTTPCLIENT("[HTTP-Client][sendRequest] type: '%s' redirCount: %d\n", type, redirectCount); + + // connect to server + if (!connect()) { + return returnError(HTTPC_ERROR_CONNECTION_FAILED); + } + + addHeader(F("Content-Length"), String(payload && size > 0 ? size : 0)); + + // send Header + if (!sendHeader(type)) { + return returnError(HTTPC_ERROR_SEND_HEADER_FAILED); + } + + // transfer all of it, with send-timeout + if (size && StreamConstPtr(payload, size).sendAll(_client()) != size) { + return returnError(HTTPC_ERROR_SEND_PAYLOAD_FAILED); + } + + // handle Server Response (Header) + code = handleHeaderResponse(); + + // + // Handle redirections as stated in RFC document: + // https://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html + // + // Implementing HTTP_CODE_FOUND as redirection with GET method, + // to follow most of existing user agent implementations. + // + redirect = false; + if ( + _followRedirects != HTTPC_DISABLE_FOLLOW_REDIRECTS && + redirectCount < _redirectLimit && + _location.length() > 0 + ) { + switch (code) { + // redirecting using the same method + case HTTP_CODE_MOVED_PERMANENTLY: + case HTTP_CODE_TEMPORARY_REDIRECT: { + if ( + // allow to force redirections on other methods + // (the RFC require user to accept the redirection) + _followRedirects == HTTPC_FORCE_FOLLOW_REDIRECTS || + // allow GET and HEAD methods without force + !strcmp(type, "GET") || + !strcmp(type, "HEAD") + ) { + redirectCount += 1; + DEBUG_HTTPCLIENT("[HTTP-Client][sendRequest] following redirect (the same method): '%s' redirCount: %d\n", _location.c_str(), redirectCount); + if (!setURL(_location)) { + DEBUG_HTTPCLIENT("[HTTP-Client][sendRequest] failed setting URL for redirection\n"); + // no redirection + break; + } + // redirect using the same request method and payload, different URL + redirect = true; + } + break; + } + // redirecting with method dropped to GET or HEAD + // note: it does not need `HTTPC_FORCE_FOLLOW_REDIRECTS` for any method + case HTTP_CODE_FOUND: + case HTTP_CODE_SEE_OTHER: { + redirectCount += 1; + DEBUG_HTTPCLIENT("[HTTP-Client][sendRequest] following redirect (dropped to GET/HEAD): '%s' redirCount: %d\n", _location.c_str(), redirectCount); + if (!setURL(_location)) { + DEBUG_HTTPCLIENT("[HTTP-Client][sendRequest] failed setting URL for redirection\n"); + // no redirection + break; + } + // redirect after changing method to GET/HEAD and dropping payload + type = "GET"; + payload = nullptr; + size = 0; + redirect = true; + break; + } + + default: + break; + } + } + } while (redirect); + + // handle Server Response (Header) + return returnError(code); +} + +/** + sendRequest + @param type const char * "GET", "POST", .... + @param stream Stream * data stream for the message body + @param size size_t size for the message body if 0 not Content-Length is send + @return -1 if no info or > 0 when Content-Length is set by server +*/ +int HTTPClient::sendRequest(const char * type, Stream * stream, size_t size) { + + if (!stream) { + return returnError(HTTPC_ERROR_NO_STREAM); + } + + // connect to server + if (!connect()) { + return returnError(HTTPC_ERROR_CONNECTION_FAILED); + } + + if (size > 0) { + addHeader(F("Content-Length"), String(size)); + } + + // send Header + if (!sendHeader(type)) { + return returnError(HTTPC_ERROR_SEND_HEADER_FAILED); + } + + // transfer all of it, with timeout + size_t transferred = StreamSendSize(stream, _client(), size); + if (transferred != size) { + DEBUG_HTTPCLIENT("[HTTP-Client][sendRequest] short write, asked for %zu but got %zu failed.\n", size, transferred); + return returnError(HTTPC_ERROR_SEND_PAYLOAD_FAILED); + } + + // handle Server Response (Header) + return returnError(handleHeaderResponse()); +} + +/** + size of message body / payload + @return -1 if no info or > 0 when Content-Length is set by server +*/ +int HTTPClient::getSize(void) { + return _size; +} + +/** + Location if redirect +*/ +const String& HTTPClient::getLocation(void) { + return _location; +} + +/** + returns the stream of the tcp connection + @return WiFiClient +*/ +WiFiClient& HTTPClient::getStream(void) { + if (connected()) { + return *_client(); + } + + DEBUG_HTTPCLIENT("[HTTP-Client] getStream: not connected\n"); + static WiFiClient empty; + return empty; +} + +/** + returns the stream of the tcp connection + @return WiFiClient +*/ +WiFiClient* HTTPClient::getStreamPtr(void) { + if (connected()) { + return _client(); + } + + DEBUG_HTTPCLIENT("[HTTP-Client] getStreamPtr: not connected\n"); + return nullptr; +} + +/** + write all message body / payload to Stream + @param stream Stream + @return bytes written ( negative values are error codes ) +*/ +int HTTPClient::writeToStream(Stream * stream) { + return writeToPrint(stream); +} + +/** + write all message body / payload to Print + @param print Print + @return bytes written ( negative values are error codes ) +*/ +int HTTPClient::writeToPrint(Print * print) { + + if (!print) { + return returnError(HTTPC_ERROR_NO_STREAM); + } + + // Only return error if not connected and no data available, because otherwise ::getString() will return an error instead of an empty + // string when the server returned a http code 204 (no content) + if (!connected() && _transferEncoding != HTTPC_TE_IDENTITY && _size > 0) { + return returnError(HTTPC_ERROR_NOT_CONNECTED); + } + + // get length of document (is -1 when Server sends no Content-Length header) + int len = _size; + int ret = 0; + + if (_transferEncoding == HTTPC_TE_IDENTITY) { + // len < 0: transfer all of it, with timeout + // len >= 0: max:len, with timeout + ret = StreamSendSize(_client(), print, len); + + if (len > 0 && ret != len) { + return HTTPC_ERROR_NO_STREAM; + } + // do we have an error? + // if(_client->getLastSendReport() != Stream::Report::Success) { + // return returnError(StreamReportToHttpClientReport(_client->getLastSendReport())); + // } + } else if (_transferEncoding == HTTPC_TE_CHUNKED) { + int size = 0; + while (1) { + if (!connected()) { + return returnError(HTTPC_ERROR_CONNECTION_LOST); + } + String chunkHeader = _client()->readStringUntil('\n'); + + if (chunkHeader.length() <= 0) { + return returnError(HTTPC_ERROR_READ_TIMEOUT); + } + + chunkHeader.trim(); // remove \r + DEBUG_HTTPCLIENT("[HTTP-Client] chunk header: '%s'\n", chunkHeader.c_str()); + + // read size of chunk + len = (uint32_t) strtol((const char *) chunkHeader.c_str(), nullptr, 16); + size += len; + DEBUG_HTTPCLIENT("[HTTP-Client] read chunk len: %d\n", len); + + // data left? + if (len > 0) { + // read len bytes with timeout + int r = StreamSendSize(_client(), print, len); + if (r != len) { + return HTTPC_ERROR_NO_STREAM; + } + + // if (_client->getLastSendReport() != Stream::Report::Success) + // // not all data transferred + // return returnError(StreamReportToHttpClientReport(_client->getLastSendReport())); + ret += r; + } else { + + // if no length Header use global chunk size + if (_size <= 0) { + _size = size; + } + + // check if we have write all data out + if (ret != _size) { + return returnError(HTTPC_ERROR_STREAM_WRITE); + } + break; + } + + // read trailing \r\n at the end of the chunk + char buf[2]; + auto trailing_seq_len = _client()->readBytes((uint8_t*)buf, 2); + if (trailing_seq_len != 2 || buf[0] != '\r' || buf[1] != '\n') { + return returnError(HTTPC_ERROR_READ_TIMEOUT); + } + } + } else { + return returnError(HTTPC_ERROR_ENCODING); + } + + disconnect(true); + return ret; +} + +/** + return all payload as String (may need lot of ram or trigger out of memory!) + @return String +*/ +const String& HTTPClient::getString(void) { + if (_payload) { + return *_payload; + } + + _payload.reset(new StreamString()); + + if (_size > 0) { + // try to reserve needed memory + if (!_payload->reserve((_size + 1))) { + DEBUG_HTTPCLIENT("[HTTP-Client][getString] not enough memory to reserve a string! need: %d\n", (_size + 1)); + return *_payload; + } + } + + writeToStream(_payload.get()); + return *_payload; +} + +/** + converts error code to String + @param error int + @return String +*/ +String HTTPClient::errorToString(int error) { + switch (error) { + case HTTPC_ERROR_CONNECTION_FAILED: + return F("connection failed"); + case HTTPC_ERROR_SEND_HEADER_FAILED: + return F("send header failed"); + case HTTPC_ERROR_SEND_PAYLOAD_FAILED: + return F("send payload failed"); + case HTTPC_ERROR_NOT_CONNECTED: + return F("not connected"); + case HTTPC_ERROR_CONNECTION_LOST: + return F("connection lost"); + case HTTPC_ERROR_NO_STREAM: + return F("no stream"); + case HTTPC_ERROR_NO_HTTP_SERVER: + return F("no HTTP server"); + case HTTPC_ERROR_TOO_LESS_RAM: + return F("not enough ram"); + case HTTPC_ERROR_ENCODING: + return F("Transfer-Encoding not supported"); + case HTTPC_ERROR_STREAM_WRITE: + return F("Stream write error"); + case HTTPC_ERROR_READ_TIMEOUT: + return F("read Timeout"); + default: + return String(); + } +} + +/** + adds Header to the request + @param name + @param value + @param first +*/ +void HTTPClient::addHeader(const String& name, const String& value, bool first, bool replace) { + // not allow set of Header handled by code + if (!name.equalsIgnoreCase(F("Connection")) && + !name.equalsIgnoreCase(F("User-Agent")) && + !name.equalsIgnoreCase(F("Host")) && + !(name.equalsIgnoreCase(F("Authorization")) && _base64Authorization.length())) { + + String headerLine; + headerLine.reserve(name.length() + value.length() + 4); + headerLine += name; + headerLine += ": "; + + if (replace) { + int headerStart = _headers.indexOf(headerLine); + if (headerStart != -1) { + int headerEnd = _headers.indexOf('\n', headerStart); + _headers = _headers.substring(0, headerStart) + _headers.substring(headerEnd + 1); + } + } + + headerLine += value; + headerLine += "\r\n"; + if (first) { + _headers = headerLine + _headers; + } else { + _headers += headerLine; + } + } +} + +void HTTPClient::collectHeaders(const char* headerKeys[], const size_t headerKeysCount) { + _headerKeysCount = headerKeysCount; + _currentHeaders = std::make_unique(_headerKeysCount); + for (size_t i = 0; i < _headerKeysCount; i++) { + _currentHeaders[i].key = headerKeys[i]; + } +} + +String HTTPClient::header(const char* name) { + for (size_t i = 0; i < _headerKeysCount; ++i) { + if (_currentHeaders[i].key == name) { + return _currentHeaders[i].value; + } + } + return String(); +} + +String HTTPClient::header(size_t i) { + if (i < _headerKeysCount) { + return _currentHeaders[i].value; + } + return String(); +} + +String HTTPClient::headerName(size_t i) { + if (i < _headerKeysCount) { + return _currentHeaders[i].key; + } + return String(); +} + +int HTTPClient::headers() { + return _headerKeysCount; +} + +bool HTTPClient::hasHeader(const char* name) { + for (size_t i = 0; i < _headerKeysCount; ++i) { + if ((_currentHeaders[i].key == name) && (_currentHeaders[i].value.length() > 0)) { + return true; + } + } + return false; +} + +/** + init TCP connection and handle ssl verify if needed + @return true if connection is ok +*/ +bool HTTPClient::connect(void) { + if (_reuse && _canReuse && connected()) { + DEBUG_HTTPCLIENT("[HTTP-Client] connect: already connected, reusing connection\n"); + // clear _client's output (all of it, no timeout) + while (_client()->available()) { + _client()->read(); + } + return true; + } + + if (!_client()) { + DEBUG_HTTPCLIENT("[HTTP-Client] connect: HTTPClient::begin was not called or returned error\n"); + return false; + } + + _client()->setTimeout(_tcpTimeout); + + if (!_client()->connect(_host.c_str(), _port)) { + DEBUG_HTTPCLIENT("[HTTP-Client] failed connect to %s:%u\n", _host.c_str(), _port); + return false; + } + + DEBUG_HTTPCLIENT("[HTTP-Client] connected to %s:%u\n", _host.c_str(), _port); + _client()->setNoDelay(true); + return connected(); +} + +/** + sends HTTP request header + @param type (GET, POST, ...) + @return status +*/ +bool HTTPClient::sendHeader(const char * type) { + if (!connected()) { + return false; + } + + String header; + // 128: Arbitrarily chosen to have enough buffer space for avoiding internal reallocations + header.reserve(_headers.length() + _uri.length() + + _base64Authorization.length() + _host.length() + _userAgent.length() + 128); + header += type; + header += ' '; + if (_uri.length()) { + header += _uri; + } else { + header += '/'; + } + header += F(" HTTP/1."); + + if (_useHTTP10) { + header += '0'; + } else { + header += '1'; + } + + header += F("\r\nHost: "); + header += _host; + if (_port != 80 && _port != 443) { + header += ':'; + header += String(_port); + } + if (_userAgent.length()) { + header += F("\r\nUser-Agent: "); + header += _userAgent; + } + + if (!_useHTTP10) { + header += F("\r\nAccept-Encoding: identity;q=1,chunked;q=0.1,*;q=0"); + } + + if (_base64Authorization.length()) { + header += F("\r\nAuthorization: Basic "); + header += _base64Authorization; + } + + header += F("\r\nConnection: "); + header += _reuse ? F("keep-alive") : F("close"); + header += "\r\n"; + + header += _headers; + header += "\r\n"; + + DEBUG_HTTPCLIENT("[HTTP-Client] sending request header\n-----\n%s-----\n", header.c_str()); + + // transfer all of it, with timeout + return StreamConstPtr(header).sendAll(_client()) == header.length(); +} + +/** + reads the response from the server + @return int http code +*/ +int HTTPClient::handleHeaderResponse() { + + if (!connected()) { + return HTTPC_ERROR_NOT_CONNECTED; + } + + clear(); + + _canReuse = _reuse; + + String transferEncoding; + + _transferEncoding = HTTPC_TE_IDENTITY; + unsigned long lastDataTime = millis(); + + while (connected()) { + size_t len = _client()->available(); + if (len > 0) { + int headerSeparator = -1; + String headerLine = _client()->readStringUntil('\n'); + + lastDataTime = millis(); + + DEBUG_HTTPCLIENT("[HTTP-Client][handleHeaderResponse] RX: '%s'\n", headerLine.c_str()); + + if (headerLine.startsWith(F("HTTP/1."))) { + + constexpr auto httpVersionIdx = sizeof "HTTP/1." - 1; + _canReuse = _canReuse && (headerLine[httpVersionIdx] != '0'); + _returnCode = headerLine.substring(httpVersionIdx + 2, headerLine.indexOf(' ', httpVersionIdx + 2)).toInt(); + _canReuse = _canReuse && (_returnCode > 0) && (_returnCode < 500); + + } else if ((headerSeparator = headerLine.indexOf(':')) > 0) { + String headerName = headerLine.substring(0, headerSeparator); + String headerValue = headerLine.substring(headerSeparator + 1); + headerValue.trim(); + + if (headerName.equalsIgnoreCase(F("Content-Length"))) { + _size = headerValue.toInt(); + } + + if (_canReuse && headerName.equalsIgnoreCase(F("Connection"))) { + if (headerValue.indexOf(F("close")) >= 0 && + headerValue.indexOf(F("keep-alive")) < 0) { + _canReuse = false; + } + } + + if (headerName.equalsIgnoreCase(F("Transfer-Encoding"))) { + transferEncoding = headerValue; + } + + if (headerName.equalsIgnoreCase(F("Location"))) { + _location = headerValue; + } + + for (size_t i = 0; i < _headerKeysCount; i++) { + if (_currentHeaders[i].key.equalsIgnoreCase(headerName)) { + if (_currentHeaders[i].value != "") { + // Existing value, append this one with a comma + _currentHeaders[i].value += ','; + _currentHeaders[i].value += headerValue; + } else { + _currentHeaders[i].value = headerValue; + } + break; // We found a match, stop looking + } + } + continue; + } + + headerLine.trim(); // remove \r + + if (headerLine == "") { + DEBUG_HTTPCLIENT("[HTTP-Client][handleHeaderResponse] code: %d\n", _returnCode); + + if (_size > 0) { + DEBUG_HTTPCLIENT("[HTTP-Client][handleHeaderResponse] size: %d\n", _size); + } + + if (transferEncoding.length() > 0) { + DEBUG_HTTPCLIENT("[HTTP-Client][handleHeaderResponse] Transfer-Encoding: %s\n", transferEncoding.c_str()); + if (transferEncoding.equalsIgnoreCase(F("chunked"))) { + _transferEncoding = HTTPC_TE_CHUNKED; + } else { + _returnCode = HTTPC_ERROR_ENCODING; + return _returnCode; + } + } else { + _transferEncoding = HTTPC_TE_IDENTITY; + } + + if (_returnCode <= 0) { + DEBUG_HTTPCLIENT("[HTTP-Client][handleHeaderResponse] Remote host is not an HTTP Server!"); + _returnCode = HTTPC_ERROR_NO_HTTP_SERVER; + } + return _returnCode; + } + + } else { + if ((millis() - lastDataTime) > _tcpTimeout) { + return HTTPC_ERROR_READ_TIMEOUT; + } + } + } + + return HTTPC_ERROR_CONNECTION_LOST; +} + +/** + called to handle error return, may disconnect the connection if still exists + @param error + @return error +*/ +int HTTPClient::returnError(int error) { + if (error < 0) { + DEBUG_HTTPCLIENT("[HTTP-Client][returnError] error(%d): %s\n", error, errorToString(error).c_str()); + if (connected()) { + DEBUG_HTTPCLIENT("[HTTP-Client][returnError] tcp stop\n"); + _client()->stop(); + } + } + return error; +} diff --git a/libraries/HTTPClient/src/HTTPClient.h b/libraries/HTTPClient/src/HTTPClient.h new file mode 100644 index 000000000..e1d154ca5 --- /dev/null +++ b/libraries/HTTPClient/src/HTTPClient.h @@ -0,0 +1,373 @@ +/** + HTTPClient.h + + Modified 2022 by Earle F. Philhower, III + + Created on: 02.11.2015 + + Copyright (c) 2015 Markus Sattler. All rights reserved. + This file is part of the ESP8266HTTPClient for Arduino. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Modified by Jeroen Döll, June 2018 +*/ + +#pragma once + +#include +#include +#include +#include + +#include + +#ifdef DEBUG_ESP_HTTP_CLIENT +#ifdef DEBUG_ESP_PORT +#define DEBUG_HTTPCLIENT(fmt, ...) DEBUG_ESP_PORT.printf_P( (PGM_P)PSTR(fmt), ## __VA_ARGS__ ) +#endif +#endif + +//#define DEBUG_HTTPCLIENT(fmt, ...) Serial.printf(fmt, ## __VA_ARGS__ ) +#ifndef DEBUG_HTTPCLIENT +#define DEBUG_HTTPCLIENT(...) do { (void)0; } while (0) +#endif + + +#define HTTPCLIENT_DEFAULT_TCP_TIMEOUT (5000) + +/// HTTP client errors +#define HTTPC_ERROR_CONNECTION_FAILED (-1) +#define HTTPC_ERROR_SEND_HEADER_FAILED (-2) +#define HTTPC_ERROR_SEND_PAYLOAD_FAILED (-3) +#define HTTPC_ERROR_NOT_CONNECTED (-4) +#define HTTPC_ERROR_CONNECTION_LOST (-5) +#define HTTPC_ERROR_NO_STREAM (-6) +#define HTTPC_ERROR_NO_HTTP_SERVER (-7) +#define HTTPC_ERROR_TOO_LESS_RAM (-8) +#define HTTPC_ERROR_ENCODING (-9) +#define HTTPC_ERROR_STREAM_WRITE (-10) +#define HTTPC_ERROR_READ_TIMEOUT (-11) + +constexpr int HTTPC_ERROR_CONNECTION_REFUSED __attribute__((deprecated)) = HTTPC_ERROR_CONNECTION_FAILED; + +/// size for the stream handling +#define HTTP_TCP_BUFFER_SIZE (1460) + +/// HTTP codes see RFC7231 +typedef enum { + HTTP_CODE_CONTINUE = 100, + HTTP_CODE_SWITCHING_PROTOCOLS = 101, + HTTP_CODE_PROCESSING = 102, + HTTP_CODE_OK = 200, + HTTP_CODE_CREATED = 201, + HTTP_CODE_ACCEPTED = 202, + HTTP_CODE_NON_AUTHORITATIVE_INFORMATION = 203, + HTTP_CODE_NO_CONTENT = 204, + HTTP_CODE_RESET_CONTENT = 205, + HTTP_CODE_PARTIAL_CONTENT = 206, + HTTP_CODE_MULTI_STATUS = 207, + HTTP_CODE_ALREADY_REPORTED = 208, + HTTP_CODE_IM_USED = 226, + HTTP_CODE_MULTIPLE_CHOICES = 300, + HTTP_CODE_MOVED_PERMANENTLY = 301, + HTTP_CODE_FOUND = 302, + HTTP_CODE_SEE_OTHER = 303, + HTTP_CODE_NOT_MODIFIED = 304, + HTTP_CODE_USE_PROXY = 305, + HTTP_CODE_TEMPORARY_REDIRECT = 307, + HTTP_CODE_PERMANENT_REDIRECT = 308, + HTTP_CODE_BAD_REQUEST = 400, + HTTP_CODE_UNAUTHORIZED = 401, + HTTP_CODE_PAYMENT_REQUIRED = 402, + HTTP_CODE_FORBIDDEN = 403, + HTTP_CODE_NOT_FOUND = 404, + HTTP_CODE_METHOD_NOT_ALLOWED = 405, + HTTP_CODE_NOT_ACCEPTABLE = 406, + HTTP_CODE_PROXY_AUTHENTICATION_REQUIRED = 407, + HTTP_CODE_REQUEST_TIMEOUT = 408, + HTTP_CODE_CONFLICT = 409, + HTTP_CODE_GONE = 410, + HTTP_CODE_LENGTH_REQUIRED = 411, + HTTP_CODE_PRECONDITION_FAILED = 412, + HTTP_CODE_PAYLOAD_TOO_LARGE = 413, + HTTP_CODE_URI_TOO_LONG = 414, + HTTP_CODE_UNSUPPORTED_MEDIA_TYPE = 415, + HTTP_CODE_RANGE_NOT_SATISFIABLE = 416, + HTTP_CODE_EXPECTATION_FAILED = 417, + HTTP_CODE_MISDIRECTED_REQUEST = 421, + HTTP_CODE_UNPROCESSABLE_ENTITY = 422, + HTTP_CODE_LOCKED = 423, + HTTP_CODE_FAILED_DEPENDENCY = 424, + HTTP_CODE_UPGRADE_REQUIRED = 426, + HTTP_CODE_PRECONDITION_REQUIRED = 428, + HTTP_CODE_TOO_MANY_REQUESTS = 429, + HTTP_CODE_REQUEST_HEADER_FIELDS_TOO_LARGE = 431, + HTTP_CODE_INTERNAL_SERVER_ERROR = 500, + HTTP_CODE_NOT_IMPLEMENTED = 501, + HTTP_CODE_BAD_GATEWAY = 502, + HTTP_CODE_SERVICE_UNAVAILABLE = 503, + HTTP_CODE_GATEWAY_TIMEOUT = 504, + HTTP_CODE_HTTP_VERSION_NOT_SUPPORTED = 505, + HTTP_CODE_VARIANT_ALSO_NEGOTIATES = 506, + HTTP_CODE_INSUFFICIENT_STORAGE = 507, + HTTP_CODE_LOOP_DETECTED = 508, + HTTP_CODE_NOT_EXTENDED = 510, + HTTP_CODE_NETWORK_AUTHENTICATION_REQUIRED = 511 +} t_http_codes; + +typedef enum { + HTTPC_TE_IDENTITY, + HTTPC_TE_CHUNKED +} transferEncoding_t; + +/** + redirection follow mode. + + `HTTPC_DISABLE_FOLLOW_REDIRECTS` - no redirection will be followed. + + `HTTPC_STRICT_FOLLOW_REDIRECTS` - strict RFC2616, only requests using + GET or HEAD methods will be redirected (using the same method), + since the RFC requires end-user confirmation in other cases. + + `HTTPC_FORCE_FOLLOW_REDIRECTS` - all redirections will be followed, + regardless of a used method. New request will use the same method, + and they will include the same body data and the same headers. + In the sense of the RFC, it's just like every redirection is confirmed. +*/ +typedef enum { + HTTPC_DISABLE_FOLLOW_REDIRECTS, + HTTPC_STRICT_FOLLOW_REDIRECTS, + HTTPC_FORCE_FOLLOW_REDIRECTS +} followRedirects_t; + +class TransportTraits; +typedef std::unique_ptr TransportTraitsPtr; + +class HTTPClient { +public: + HTTPClient() = default; + ~HTTPClient() = default; + HTTPClient(HTTPClient&&) = default; + HTTPClient& operator=(HTTPClient&&) = default; + + // The easier way + bool begin(String url); + bool begin(String host, uint16_t port, String uri = "/", bool https = false); + bool begin(String url, const uint8_t httpsFingerprint[20]) { + setFingerprint(httpsFingerprint); + return begin(url); + } + bool begin(String host, uint16_t port, String uri, const uint8_t httpsFingerprint[20]) { + setFingerprint(httpsFingerprint); + return begin(host, port, uri); + } + + // Let's do it the hard way, too + bool begin(WiFiClient &client, const String& url); + bool begin(WiFiClient &client, const String& host, uint16_t port, const String& uri = "/", bool https = false); + + + void end(void); + + bool connected(void); + + void setReuse(bool reuse); /// keep-alive + void setUserAgent(const String& userAgent); + void setAuthorization(const char * user, const char * password); + void setAuthorization(const char * auth); + void setAuthorization(String auth); + void setTimeout(uint16_t timeout); + + // Redirections + void setFollowRedirects(followRedirects_t follow); + void setRedirectLimit(uint16_t limit); // max redirects to follow for a single request + + bool setURL(const String& url); // handy for handling redirects + void useHTTP10(bool usehttp10 = true); + + /// request handling + int GET(); + int DELETE(); + int POST(const uint8_t* payload, size_t size); + int POST(const String& payload); + int PUT(const uint8_t* payload, size_t size); + int PUT(const String& payload); + int PATCH(const uint8_t* payload, size_t size); + int PATCH(const String& payload); + int sendRequest(const char* type, const String& payload); + int sendRequest(const char* type, const uint8_t* payload = nullptr, size_t size = 0); + int sendRequest(const char* type, Stream * stream, size_t size = 0); + + void addHeader(const String& name, const String& value, bool first = false, bool replace = true); + + /// Response handling + void collectHeaders(const char* headerKeys[], const size_t headerKeysCount); + String header(const char* name); // get request header value by name + String header(size_t i); // get request header value by number + String headerName(size_t i); // get request header name by number + int headers(); // get header count + bool hasHeader(const char* name); // check if header exists + + + int getSize(void); + const String& getLocation(void); // Location header from redirect if 3XX + + WiFiClient& getStream(void); + WiFiClient* getStreamPtr(void); + int writeToPrint(Print* print); + int writeToStream(Stream* stream); + const String& getString(void); + static String errorToString(int error); + + // ---------------------------------------------------------------------------------------------- + // HTTPS support, mirrors the WiFiClientSecure interface + // Could possibly use a virtual interface class between the two, but for now it is more + // straightforward to simply feed calls through manually here. + void setSession(Session *session) { + _tls()->setSession(session); + } + void setInsecure() { + _tls()->setInsecure(); + } + void setKnownKey(const PublicKey *pk, unsigned usages = BR_KEYTYPE_KEYX | BR_KEYTYPE_SIGN) { + _tls()->setKnownKey(pk, usages); + } + bool setFingerprint(const uint8_t fingerprint[20]) { + return _tls()->setFingerprint(fingerprint); + } + bool setFingerprint(const char *fpStr) { + return _tls()->setFingerprint(fpStr); + } + void allowSelfSignedCerts() { + _tls()->allowSelfSignedCerts(); + } + void setTrustAnchors(const X509List *ta) { + _tls()->setTrustAnchors(ta); + } + void setX509Time(time_t now) { + _tls()->setX509Time(now); + } + void setClientRSACert(const X509List *cert, const PrivateKey *sk) { + _tls()->setClientRSACert(cert, sk); + } + void setClientECCert(const X509List *cert, const PrivateKey *sk, unsigned allowed_usages, unsigned cert_issuer_key_type) { + _tls()->setClientECCert(cert, sk, allowed_usages, cert_issuer_key_type); + } + void setBufferSizes(int recv, int xmit) { + _tls()->setBufferSizes(recv, xmit); + } + void setCertStore(CertStoreBase *certStore) { + _tls()->setCertStore(certStore); + } + bool setCiphers(const uint16_t *cipherAry, int cipherCount) { + return _tls()->setCiphers(cipherAry, cipherCount); + } + bool setCiphers(const std::vector& list) { + return _tls()->setCiphers(list); + } + bool setCiphersLessSecure() { + return _tls()->setCiphersLessSecure(); + } + bool setSSLVersion(uint32_t min = BR_TLS10, uint32_t max = BR_TLS12) { + return _tls()->setSSLVersion(min, max); + } + void setCACert(const char *rootCA) { + _tls()->setCACert(rootCA); + } + void setCertificate(const char *client_ca) { + _tls()->setCertificate(client_ca); + } + void setPrivateKey(const char *private_key) { + _tls()->setPrivateKey(private_key); + } + bool loadCACert(Stream& stream, size_t size) { + return _tls()->loadCACert(stream, size); + } + bool loadCertificate(Stream& stream, size_t size) { + return _tls()->loadCertificate(stream, size); + } + bool loadPrivateKey(Stream& stream, size_t size) { + return _tls()->loadPrivateKey(stream, size); + } + + + +protected: + // HTTPS helpers + WiFiClientSecure *_tls() { + if (!_clientMade) { + _clientMade = new WiFiClientSecure(); + _clientGiven = false; + } + _clientTLS = true; + return (WiFiClientSecure*)_clientMade; + } + + struct RequestArgument { + String key; + String value; + }; + + bool beginInternal(const String& url, const char* expectedProtocol); + void disconnect(bool preserveClient = false); + void clear(); + int returnError(int error); + bool connect(void); + bool sendHeader(const char * type); + int handleHeaderResponse(); + int writeToStreamDataBlock(Stream * stream, int len); + + WiFiClient *_clientMade = nullptr; + bool _clientTLS = false; + + std::unique_ptr _clientIn; + bool _clientGiven = false; + + WiFiClient *_client() { + if (_clientGiven) { + return _clientIn.get(); + } else { + return _clientMade; + } + } + + /// request handling + String _host; + uint16_t _port = 0; + bool _reuse = true; + uint16_t _tcpTimeout = HTTPCLIENT_DEFAULT_TCP_TIMEOUT; + bool _useHTTP10 = false; + + String _uri; + String _protocol; + String _headers; + String _base64Authorization; + + static const String defaultUserAgent; + String _userAgent = defaultUserAgent; + + /// Response handling + std::unique_ptr _currentHeaders; + size_t _headerKeysCount = 0; + + int _returnCode = 0; + int _size = -1; + bool _canReuse = false; + followRedirects_t _followRedirects = HTTPC_DISABLE_FOLLOW_REDIRECTS; + uint16_t _redirectLimit = 10; + String _location; + transferEncoding_t _transferEncoding = HTTPC_TE_IDENTITY; + std::unique_ptr _payload; + + +}; diff --git a/libraries/HTTPClient/src/base64.cpp b/libraries/HTTPClient/src/base64.cpp new file mode 100644 index 000000000..64fd1b495 --- /dev/null +++ b/libraries/HTTPClient/src/base64.cpp @@ -0,0 +1,69 @@ +/** + base64.cpp + + Created on: 09.12.2015 + + Copyright (c) 2015 Markus Sattler. All rights reserved. + This file is part of the ESP8266 core for Arduino. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +*/ + +#include "Arduino.h" +extern "C" { +#include "libb64/cencode.h" +} +#include "base64.h" + +/** + convert input data to base64 + @param data const uint8_t + @param length size_t + @return String +*/ +String base64::encode(const uint8_t * data, size_t length, bool doNewLines) { + String base64; + + // base64 needs more size then the source data, use cencode.h macros + size_t size = ((doNewLines ? base64_encode_expected_len(length) + : base64_encode_expected_len_nonewlines(length)) + 1); + + if (base64.reserve(size)) { + + base64_encodestate _state; + if (doNewLines) { + base64_init_encodestate(&_state); + } else { + base64_init_encodestate_nonewlines(&_state); + } + + constexpr size_t BUFSIZE = 48; + char buf[BUFSIZE + 1 /* newline */ + 1 /* NUL */]; + for (size_t len = 0; len < length; len += BUFSIZE * 3 / 4) { + size_t blocklen = base64_encode_block((const char*) data + len, + std::min(BUFSIZE * 3 / 4, length - len), buf, &_state); + buf[blocklen] = '\0'; + base64 += buf; + } + if (base64_encode_blockend(buf, &_state)) { + base64 += buf; + } + } else { + base64 = F("-FAIL-"); + } + + return base64; +} diff --git a/libraries/HTTPClient/src/base64.h b/libraries/HTTPClient/src/base64.h new file mode 100644 index 000000000..32ae7776f --- /dev/null +++ b/libraries/HTTPClient/src/base64.h @@ -0,0 +1,48 @@ +/** + base64.h + + Created on: 09.12.2015 + + Copyright (c) 2015 Markus Sattler. All rights reserved. + This file is part of the ESP8266 core for Arduino. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +*/ + +#pragma once + +#include + +class base64 { +public: + // NOTE: The default behaviour of backend (lib64) + // is to add a newline every 72 (encoded) characters output. + // This may 'break' longer uris and json variables + static String encode(const uint8_t * data, size_t length, bool doNewLines); + static inline String encode(const String& text, bool doNewLines) { + return encode((const uint8_t *) text.c_str(), text.length(), doNewLines); + } + + // esp32 compat: + + static inline String encode(const uint8_t * data, size_t length) { + return encode(data, length, false); + } + + static inline String encode(const String& text) { + return encode(text, false); + } +}; diff --git a/libraries/HTTPUpdate/examples/httpUpdate/httpUpdate.ino b/libraries/HTTPUpdate/examples/httpUpdate/httpUpdate.ino new file mode 100644 index 000000000..8b7e05429 --- /dev/null +++ b/libraries/HTTPUpdate/examples/httpUpdate/httpUpdate.ino @@ -0,0 +1,83 @@ +/** + httpUpdate.ino + + Created on: 27.11.2015 + +*/ + +#include + +#include +#include +#include + +#ifndef STASSID +#define STASSID "your-ssid" +#define STAPSK "your-password" +#endif + +const char *ssid = STASSID; +const char *pass = STAPSK; + +#define UPDATE_URL "http://192.168.1.8/xfer/file.bin" + +WiFiMulti WiFiMulti; + +void setup() { + + Serial.begin(115200); + + Serial.println(); + Serial.println(); + Serial.println(); + + for (uint8_t t = 4; t > 0; t--) { + Serial.printf("[SETUP] WAIT %d...\n", t); + Serial.flush(); + delay(1000); + } + + WiFi.mode(WIFI_STA); + WiFiMulti.addAP(ssid, pass); +} + +void update_started() { + Serial.println("CALLBACK: HTTP update process started"); +} + +void update_finished() { + Serial.println("CALLBACK: HTTP update process finished"); +} + +void update_progress(int cur, int total) { + Serial.printf("CALLBACK: HTTP update process at %d of %d bytes...\n", cur, total); +} + +void update_error(int err) { + Serial.printf("CALLBACK: HTTP update fatal error code %d\n", err); +} + + +void loop() { + // wait for WiFi connection + if ((WiFiMulti.run() == WL_CONNECTED)) { + + // Add optional callback notifiers + httpUpdate.onStart(update_started); + httpUpdate.onEnd(update_finished); + httpUpdate.onProgress(update_progress); + httpUpdate.onError(update_error); + + t_httpUpdate_return ret = httpUpdate.update(UPDATE_URL); + // Or: + // t_httpUpdate_return ret = httpUpdate.update("server", 80, "file.bin"); + + switch (ret) { + case HTTP_UPDATE_FAILED: Serial.printf("HTTP_UPDATE_FAILD Error (%d): %s\n", httpUpdate.getLastError(), httpUpdate.getLastErrorString().c_str()); break; + + case HTTP_UPDATE_NO_UPDATES: Serial.println("HTTP_UPDATE_NO_UPDATES"); break; + + case HTTP_UPDATE_OK: Serial.println("HTTP_UPDATE_OK"); break; + } + } +} diff --git a/libraries/HTTPUpdate/examples/httpUpdateSecure/httpUpdateSecure.ino b/libraries/HTTPUpdate/examples/httpUpdateSecure/httpUpdateSecure.ino new file mode 100644 index 000000000..38461c9a2 --- /dev/null +++ b/libraries/HTTPUpdate/examples/httpUpdateSecure/httpUpdateSecure.ino @@ -0,0 +1,85 @@ +/** + httpUpdateSecure.ino + + Created on: 27.11.2015 + +*/ + +#include + +#include +#include +#include + +#ifndef STASSID +#define STASSID "your-ssid" +#define STAPSK "your-password" +#endif + +const char *ssid = STASSID; +const char *pass = STAPSK; + +#define UPDATE_URL "https://www.ziplabel.com/file.bin" + +WiFiMulti WiFiMulti; + +void setup() { + + Serial.begin(115200); + + Serial.println(); + Serial.println(); + Serial.println(); + + for (uint8_t t = 4; t > 0; t--) { + Serial.printf("[SETUP] WAIT %d...\n", t); + Serial.flush(); + delay(1000); + } + + WiFi.mode(WIFI_STA); + WiFiMulti.addAP(ssid, pass); +} + +void update_started() { + Serial.println("CALLBACK: HTTP update process started"); +} + +void update_finished() { + Serial.println("CALLBACK: HTTP update process finished"); +} + +void update_progress(int cur, int total) { + Serial.printf("CALLBACK: HTTP update process at %d of %d bytes...\n", cur, total); +} + +void update_error(int err) { + Serial.printf("CALLBACK: HTTP update fatal error code %d\n", err); +} + + +void loop() { + // wait for WiFi connection + if ((WiFiMulti.run() == WL_CONNECTED)) { + + // Add optional callback notifiers + httpUpdate.onStart(update_started); + httpUpdate.onEnd(update_finished); + httpUpdate.onProgress(update_progress); + httpUpdate.onError(update_error); + + WiFiClientSecure client; + client.setInsecure(); + t_httpUpdate_return ret = httpUpdate.update(client, UPDATE_URL); + // Or: + // t_httpUpdate_return ret = httpUpdate.update("server", 80, "file.bin"); + + switch (ret) { + case HTTP_UPDATE_FAILED: Serial.printf("HTTP_UPDATE_FAILD Error (%d): %s\n", httpUpdate.getLastError(), httpUpdate.getLastErrorString().c_str()); break; + + case HTTP_UPDATE_NO_UPDATES: Serial.println("HTTP_UPDATE_NO_UPDATES"); break; + + case HTTP_UPDATE_OK: Serial.println("HTTP_UPDATE_OK"); break; + } + } +} diff --git a/libraries/HTTPUpdate/keywords.txt b/libraries/HTTPUpdate/keywords.txt new file mode 100644 index 000000000..0872b6a97 --- /dev/null +++ b/libraries/HTTPUpdate/keywords.txt @@ -0,0 +1,44 @@ +####################################### +# Syntax Coloring Map For ESP8266httpUpdate +####################################### + +####################################### +# Library (KEYWORD3) +####################################### + +HTTPUpdate KEYWORD3 RESERVED_WORD + +####################################### +# Datatypes (KEYWORD1) +####################################### + +HTTPUpdateResult KEYWORD1 DATA_TYPE +ESPhttpUpdate KEYWORD1 DATA_TYPE + +####################################### +# Methods and Functions (KEYWORD2) +####################################### + +rebootOnUpdate KEYWORD2 +update KEYWORD2 +updateSpiffs KEYWORD2 +getLastError KEYWORD2 +getLastErrorString KEYWORD2 +setAuthorization KEYWORD2 + +####################################### +# Constants (LITERAL1) +####################################### + +HTTP_UE_TOO_LESS_SPACE LITERAL1 RESERVED_WORD_2 +HTTP_UE_SERVER_NOT_REPORT_SIZE LITERAL1 RESERVED_WORD_2 +HTTP_UE_SERVER_FILE_NOT_FOUND LITERAL1 RESERVED_WORD_2 +HTTP_UE_SERVER_FORBIDDEN LITERAL1 RESERVED_WORD_2 +HTTP_UE_SERVER_WRONG_HTTP_CODE LITERAL1 RESERVED_WORD_2 +HTTP_UE_SERVER_FAULTY_MD5 LITERAL1 RESERVED_WORD_2 +HTTP_UE_BIN_VERIFY_HEADER_FAILED LITERAL1 RESERVED_WORD_2 +HTTP_UE_BIN_FOR_WRONG_FLASH LITERAL1 RESERVED_WORD_2 +HTTP_UE_SERVER_UNAUTHORIZED LITERAL1 RESERVED_WORD_2 +HTTP_UPDATE_FAILED LITERAL1 RESERVED_WORD_2 +HTTP_UPDATE_NO_UPDATES LITERAL1 RESERVED_WORD_2 +HTTP_UPDATE_OK LITERAL1 RESERVED_WORD_2 diff --git a/libraries/HTTPUpdate/library.properties b/libraries/HTTPUpdate/library.properties new file mode 100644 index 000000000..d8bc2093e --- /dev/null +++ b/libraries/HTTPUpdate/library.properties @@ -0,0 +1,10 @@ +name=HTTPUpdate +version=1.3 +author=Markus Sattler +maintainer=Earle F. Philhower, III +sentence=Http Update for ESP8266, ported to Pico +paragraph= +category=Data Processing +url=https://github.com/earlephilhower/arduino-pico +architectures=rp2040 +dot_a_linkage=true diff --git a/libraries/HTTPUpdate/src/HTTPUpdate.cpp b/libraries/HTTPUpdate/src/HTTPUpdate.cpp new file mode 100755 index 000000000..d65ac225f --- /dev/null +++ b/libraries/HTTPUpdate/src/HTTPUpdate.cpp @@ -0,0 +1,392 @@ +/** + + @file HTTPUpdate.cpp + @date 21.06.2015 + @author Markus Sattler + + Copyright (c) 2015 Markus Sattler. All rights reserved. + This file is part of the Http Updater. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +*/ + +#include "HTTPUpdate.h" +#include + +extern uint8_t _FS_start; +extern uint8_t _FS_end; + +HTTPUpdate::HTTPUpdate(void) + : _httpClientTimeout(8000) { +} + +HTTPUpdate::HTTPUpdate(int httpClientTimeout) + : _httpClientTimeout(httpClientTimeout) { +} + +HTTPUpdate::~HTTPUpdate(void) { +} + +/** + set the Authorization for the http request + @param user const String& + @param password const String& +*/ +void HTTPUpdate::setAuthorization(const String &user, const String &password) { + _user = user; + _password = password; +} + +/** + set the Authorization for the http request + @param auth const String& base64 +*/ +void HTTPUpdate::setAuthorization(const String &auth) { + _auth = auth; +} + +HTTPUpdateResult HTTPUpdate::update(WiFiClient& client, const String& url, const String& currentVersion) { + HTTPClient http; + http.begin(client, url); + return handleUpdate(http, currentVersion, false); +} + +HTTPUpdateResult HTTPUpdate::updateFS(WiFiClient& client, const String& url, const String& currentVersion) { + HTTPClient http; + http.begin(client, url); + return handleUpdate(http, currentVersion, true); +} + +HTTPUpdateResult HTTPUpdate::update(WiFiClient& client, const String& host, uint16_t port, const String& uri, + const String& currentVersion) { + HTTPClient http; + http.begin(client, host, port, uri); + return handleUpdate(http, currentVersion, false); +} + +HTTPUpdateResult HTTPUpdate::update(const String& url, const String& currentVersion) { + HTTPClient http; + http.begin(url); + return handleUpdate(http, currentVersion, false); +} + +HTTPUpdateResult HTTPUpdate::update(const String& host, uint16_t port, const String& uri, const String& currentVersion) { + HTTPClient http; + http.begin(host, port, uri); + return handleUpdate(http, currentVersion, false); +} + +HTTPUpdateResult HTTPUpdate::updateFS(const String& url, const String& currentVersion) { + HTTPClient http; + http.begin(url); + return handleUpdate(http, currentVersion, true); +} + +/** + return error code as int + @return int error code +*/ +int HTTPUpdate::getLastError(void) { + return _lastError; +} + +/** + return error code as String + @return String error +*/ +String HTTPUpdate::getLastErrorString(void) { + + if (_lastError == 0) { + return String(); // no error + } + + // error from Update class + if (_lastError > 0) { + StreamString error; + Update.printError(error); + error.trim(); // remove line ending + return String(F("Update error: ")) + error; + } + + // error from http client + if (_lastError > -100) { + return String(F("HTTP error: ")) + HTTPClient::errorToString(_lastError); + } + + switch (_lastError) { + case HTTP_UE_TOO_LESS_SPACE: + return F("Not Enough space"); + case HTTP_UE_SERVER_NOT_REPORT_SIZE: + return F("Server Did Not Report Size"); + case HTTP_UE_SERVER_FILE_NOT_FOUND: + return F("File Not Found (404)"); + case HTTP_UE_SERVER_FORBIDDEN: + return F("Forbidden (403)"); + case HTTP_UE_SERVER_WRONG_HTTP_CODE: + return F("Wrong HTTP Code"); + case HTTP_UE_SERVER_FAULTY_MD5: + return F("Wrong MD5"); + case HTTP_UE_BIN_VERIFY_HEADER_FAILED: + return F("Verify Bin Header Failed"); + case HTTP_UE_BIN_FOR_WRONG_FLASH: + return F("New Binary Does Not Fit Flash Size"); + case HTTP_UE_SERVER_UNAUTHORIZED: + return F("Unauthorized (401)"); + } + + return String(); +} + + +/** + + @param http HTTPClient + @param currentVersion const char + @return HTTPUpdateResult +*/ +HTTPUpdateResult HTTPUpdate::handleUpdate(HTTPClient& http, const String& currentVersion, bool spiffs) { + + HTTPUpdateResult ret = HTTP_UPDATE_FAILED; + + // use HTTP/1.0 for update since the update handler not support any transfer Encoding + http.useHTTP10(true); + http.setTimeout(_httpClientTimeout); + http.setFollowRedirects(_followRedirects); + http.setUserAgent(F("Pico-HTTP-Update")); + http.addHeader(F("x-Pico-Chip-ID"), String(rp2040.getChipID())); + http.addHeader(F("x-Pico-STA-MAC"), WiFi.macAddress()); + http.addHeader(F("x-Pico-AP-MAC"), WiFi.softAPmacAddress()); + + if (spiffs) { + http.addHeader(F("x-Pico-Mode"), F("spiffs")); + } else { + http.addHeader(F("x-Pico-Mode"), F("sketch")); + } + + if (currentVersion && currentVersion[0] != 0x00) { + http.addHeader(F("x-Pico-Version"), currentVersion); + } + + if (_user != "" && _password != "") { + http.setAuthorization(_user.c_str(), _password.c_str()); + } + + if (_auth != "") { + http.setAuthorization(_auth.c_str()); + } + + const char * headerkeys[] = { "x-MD5" }; + size_t headerkeyssize = sizeof(headerkeys) / sizeof(char*); + + // track these headers + http.collectHeaders(headerkeys, headerkeyssize); + + + int code = http.GET(); + int len = http.getSize(); + + if (code <= 0) { + DEBUG_HTTP_UPDATE("[httpUpdate] HTTP error: %s\n", http.errorToString(code).c_str()); + _setLastError(code); + http.end(); + return HTTP_UPDATE_FAILED; + } + + + DEBUG_HTTP_UPDATE("[httpUpdate] Header read fin.\n"); + DEBUG_HTTP_UPDATE("[httpUpdate] Server header:\n"); + DEBUG_HTTP_UPDATE("[httpUpdate] - code: %d\n", code); + DEBUG_HTTP_UPDATE("[httpUpdate] - len: %d\n", len); + + String md5; + if (_md5Sum.length()) { + md5 = _md5Sum; + } else if (http.hasHeader("x-MD5")) { + md5 = http.header("x-MD5"); + } + if (md5.length()) { + DEBUG_HTTP_UPDATE("[httpUpdate] - MD5: %s\n", md5.c_str()); + } + + DEBUG_HTTP_UPDATE("[httpUpdate] info:\n"); + + if (currentVersion && currentVersion[0] != 0x00) { + DEBUG_HTTP_UPDATE("[httpUpdate] - current version: %s\n", currentVersion.c_str()); + } + + switch (code) { + case HTTP_CODE_OK: ///< OK (Start Update) + if (len > 0) { + bool startUpdate = true; + if (spiffs) { + size_t spiffsSize = ((size_t)&_FS_end - (size_t)&_FS_start); + if (len > (int) spiffsSize) { + DEBUG_HTTP_UPDATE("[httpUpdate] spiffsSize to low (%d) needed: %d\n", spiffsSize, len); + startUpdate = false; + } + } + + if (!startUpdate) { + _setLastError(HTTP_UE_TOO_LESS_SPACE); + ret = HTTP_UPDATE_FAILED; + } else { + // Warn main app we're starting up... + if (_cbStart) { + _cbStart(); + } + + WiFiClient * tcp = http.getStreamPtr(); + if (!tcp) { + DEBUG_HTTP_UPDATE("[httpUpdate] WiFiClient connection unexpectedly absent\n"); + _setLastError(HTTPC_ERROR_CONNECTION_LOST); + http.end(); + return HTTP_UPDATE_FAILED; + } + + if (_closeConnectionsOnUpdate) { + WiFiUDP::stopAll(); + WiFiClient::stopAllExcept(tcp); + } + + delay(100); + + int command; + + if (spiffs) { + command = U_FS; + DEBUG_HTTP_UPDATE("[httpUpdate] runUpdate filesystem...\n"); + } else { + command = U_FLASH; + DEBUG_HTTP_UPDATE("[httpUpdate] runUpdate flash...\n"); + } + + if (runUpdate(*tcp, len, md5, command)) { + ret = HTTP_UPDATE_OK; + DEBUG_HTTP_UPDATE("[httpUpdate] Update ok\n"); + http.end(); + // Warn main app we're all done + if (_cbEnd) { + _cbEnd(); + } + +#ifdef ATOMIC_FS_UPDATE + if (_rebootOnUpdate) { +#else + if (_rebootOnUpdate && !spiffs) { +#endif + rp2040.restart(); + } + + } else { + ret = HTTP_UPDATE_FAILED; + DEBUG_HTTP_UPDATE("[httpUpdate] Update failed\n"); + } + } + } else { + _setLastError(HTTP_UE_SERVER_NOT_REPORT_SIZE); + ret = HTTP_UPDATE_FAILED; + DEBUG_HTTP_UPDATE("[httpUpdate] Content-Length was 0 or wasn't set by Server?!\n"); + } + break; + case HTTP_CODE_NOT_MODIFIED: + ///< Not Modified (No updates) + ret = HTTP_UPDATE_NO_UPDATES; + break; + case HTTP_CODE_NOT_FOUND: + _setLastError(HTTP_UE_SERVER_FILE_NOT_FOUND); + ret = HTTP_UPDATE_FAILED; + break; + case HTTP_CODE_FORBIDDEN: + _setLastError(HTTP_UE_SERVER_FORBIDDEN); + ret = HTTP_UPDATE_FAILED; + break; + case HTTP_CODE_UNAUTHORIZED: + _setLastError(HTTP_UE_SERVER_UNAUTHORIZED); + ret = HTTP_UPDATE_FAILED; + break; + default: + _setLastError(HTTP_UE_SERVER_WRONG_HTTP_CODE); + ret = HTTP_UPDATE_FAILED; + DEBUG_HTTP_UPDATE("[httpUpdate] HTTP Code is (%d)\n", code); + //http.writeToStream(&Serial1); + break; + } + + http.end(); + return ret; +} + +/** + write Update to flash + @param in Stream& + @param size uint32_t + @param md5 String + @return true if Update ok +*/ +bool HTTPUpdate::runUpdate(Stream& in, uint32_t size, const String& md5, int command) { + + StreamString error; + + if (_cbProgress) { + Update.onProgress(_cbProgress); + } + + if (!Update.begin(size, command)) { + _setLastError(Update.getError()); + Update.printError(error); + error.trim(); // remove line ending + DEBUG_HTTP_UPDATE("[httpUpdate] Update.begin failed! (%s)\n", error.c_str()); + return false; + } + + if (_cbProgress) { + _cbProgress(0, size); + } + + if (md5.length()) { + if (!Update.setMD5(md5.c_str())) { + _setLastError(HTTP_UE_SERVER_FAULTY_MD5); + DEBUG_HTTP_UPDATE("[httpUpdate] Update.setMD5 failed! (%s)\n", md5.c_str()); + return false; + } + } + + if (Update.writeStream(in) != size) { + _setLastError(Update.getError()); + Update.printError(error); + error.trim(); // remove line ending + DEBUG_HTTP_UPDATE("[httpUpdate] Update.writeStream failed! (%s)\n", error.c_str()); + return false; + } + + if (_cbProgress) { + _cbProgress(size, size); + } + + if (!Update.end()) { + _setLastError(Update.getError()); + Update.printError(error); + error.trim(); // remove line ending + DEBUG_HTTP_UPDATE("[httpUpdate] Update.end failed! (%s)\n", error.c_str()); + return false; + } + + return true; +} + +#if !defined(NO_GLOBAL_INSTANCES) && !defined(NO_GLOBAL_HTTPUPDATE) +HTTPUpdate httpUpdate; +#endif diff --git a/libraries/HTTPUpdate/src/HTTPUpdate.h b/libraries/HTTPUpdate/src/HTTPUpdate.h new file mode 100755 index 000000000..36cec80e8 --- /dev/null +++ b/libraries/HTTPUpdate/src/HTTPUpdate.h @@ -0,0 +1,163 @@ +/** + + @file ESP8266HTTPUpdate.h + @date 21.06.2015 + @author Markus Sattler + + Copyright (c) 2015 Markus Sattler. All rights reserved. + This file is part of the ESP8266 Http Updater. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +*/ + +#pragma once + +#include +#include +#include +#include +#include + +#ifdef DEBUG_ESP_HTTP_UPDATE +#ifdef DEBUG_ESP_PORT +#define DEBUG_HTTP_UPDATE(fmt, ...) DEBUG_ESP_PORT.printf_P( (PGM_P)PSTR(fmt), ## __VA_ARGS__ ) +#endif +#endif + +#ifndef DEBUG_HTTP_UPDATE +#define DEBUG_HTTP_UPDATE(...) do { (void)0; } while(0) +#endif + +/// note we use HTTP client errors too so we start at 100 +//TODO - in v3.0.0 make this an enum +constexpr int HTTP_UE_TOO_LESS_SPACE = (-100); +constexpr int HTTP_UE_SERVER_NOT_REPORT_SIZE = (-101); +constexpr int HTTP_UE_SERVER_FILE_NOT_FOUND = (-102); +constexpr int HTTP_UE_SERVER_FORBIDDEN = (-103); +constexpr int HTTP_UE_SERVER_WRONG_HTTP_CODE = (-104); +constexpr int HTTP_UE_SERVER_FAULTY_MD5 = (-105); +constexpr int HTTP_UE_BIN_VERIFY_HEADER_FAILED = (-106); +constexpr int HTTP_UE_BIN_FOR_WRONG_FLASH = (-107); +constexpr int HTTP_UE_SERVER_UNAUTHORIZED = (-108); + +enum HTTPUpdateResult { + HTTP_UPDATE_FAILED, + HTTP_UPDATE_NO_UPDATES, + HTTP_UPDATE_OK +}; + +typedef HTTPUpdateResult t_httpUpdate_return; // backward compatibility + +using HTTPUpdateStartCB = std::function; +using HTTPUpdateEndCB = std::function; +using HTTPUpdateErrorCB = std::function; +using HTTPUpdateProgressCB = std::function; + +class HTTPUpdate { +public: + HTTPUpdate(void); + HTTPUpdate(int httpClientTimeout); + ~HTTPUpdate(void); + + void rebootOnUpdate(bool reboot) { + _rebootOnUpdate = reboot; + } + + /** + set true to follow redirects. + @param follow + @deprecated Please use `setFollowRedirects(followRedirects_t follow)` + */ + void followRedirects(bool follow) __attribute__((deprecated)) { + _followRedirects = follow ? HTTPC_STRICT_FOLLOW_REDIRECTS : HTTPC_DISABLE_FOLLOW_REDIRECTS; + } + /** + set redirect follow mode. See `followRedirects_t` enum for available modes. + @param follow + */ + void setFollowRedirects(followRedirects_t follow) { + _followRedirects = follow; + } + + void closeConnectionsOnUpdate(bool sever) { + _closeConnectionsOnUpdate = sever; + } + + void setMD5sum(const String &md5Sum) { + _md5Sum = md5Sum; + } + + void setAuthorization(const String& user, const String& password); + void setAuthorization(const String& auth); + + t_httpUpdate_return update(WiFiClient& client, const String& url, const String& currentVersion = ""); + t_httpUpdate_return update(WiFiClient& client, const String& host, uint16_t port, const String& uri = "/", + const String& currentVersion = ""); + t_httpUpdate_return updateFS(WiFiClient& client, const String& url, const String& currentVersion = ""); + + t_httpUpdate_return update(const String& url, const String& currentVersion = ""); + t_httpUpdate_return update(const String& host, uint16_t port, const String& uri = "/", const String& currentVersion = ""); + t_httpUpdate_return updateFS(const String& url, const String& currentVersion = ""); + + // Notification callbacks + void onStart(HTTPUpdateStartCB cbOnStart) { + _cbStart = cbOnStart; + } + void onEnd(HTTPUpdateEndCB cbOnEnd) { + _cbEnd = cbOnEnd; + } + void onError(HTTPUpdateErrorCB cbOnError) { + _cbError = cbOnError; + } + void onProgress(HTTPUpdateProgressCB cbOnProgress) { + _cbProgress = cbOnProgress; + } + + int getLastError(void); + String getLastErrorString(void); + +protected: + t_httpUpdate_return handleUpdate(HTTPClient& http, const String& currentVersion, bool spiffs = false); + bool runUpdate(Stream& in, uint32_t size, const String& md5, int command = U_FLASH); + + // Set the error and potentially use a CB to notify the application + void _setLastError(int err) { + _lastError = err; + if (_cbError) { + _cbError(err); + } + } + int _lastError; + bool _rebootOnUpdate = true; + bool _closeConnectionsOnUpdate = true; + String _user; + String _password; + String _auth; + String _md5Sum; +private: + int _httpClientTimeout; + followRedirects_t _followRedirects = HTTPC_DISABLE_FOLLOW_REDIRECTS; + + // Callbacks + HTTPUpdateStartCB _cbStart; + HTTPUpdateEndCB _cbEnd; + HTTPUpdateErrorCB _cbError; + HTTPUpdateProgressCB _cbProgress; +}; + +#if !defined(NO_GLOBAL_INSTANCES) && !defined(NO_GLOBAL_HTTPUPDATE) +extern HTTPUpdate httpUpdate; +#endif diff --git a/libraries/HTTPUpdateServer/examples/SecureBearSSLUpdater/SecureBearSSLUpdater.ino b/libraries/HTTPUpdateServer/examples/SecureBearSSLUpdater/SecureBearSSLUpdater.ino new file mode 100644 index 000000000..ba73a5111 --- /dev/null +++ b/libraries/HTTPUpdateServer/examples/SecureBearSSLUpdater/SecureBearSSLUpdater.ino @@ -0,0 +1,122 @@ +/* + SecureBearSSLUpdater - SSL encrypted, password-protected firmware update + + This example starts a HTTPS server on the Pico to allow firmware updates + to be performed. All communication, including the username and password, + is encrypted via SSL. Be sure to update the SSID and PASSWORD before running + to allow connection to your WiFi network. + + To upload through terminal you can use: + curl -u admin:admin -F "image=@firmware.bin" picow-webupdate.local/firmware + + Adapted by Earle F. Philhower, III, from the SecureWebUpdater.ino example. + This example is released into the public domain. +*/ + +#include +#include +#include +#include +#include + +#ifndef STASSID +#define STASSID "your-ssid" +#define STAPSK "your-password" +#endif + +const char* host = "picow-webupdate"; +const char* update_path = "/firmware"; +const char* update_username = "admin"; +const char* update_password = "admin"; +const char* ssid = STASSID; +const char* password = STAPSK; + +WebServerSecure httpServer(443); +HTTPUpdateServerSecure httpUpdater; + +static const char serverCert[] PROGMEM = R"EOF( +-----BEGIN CERTIFICATE----- +MIIDSzCCAjMCCQD2ahcfZAwXxDANBgkqhkiG9w0BAQsFADCBiTELMAkGA1UEBhMC +VVMxEzARBgNVBAgMCkNhbGlmb3JuaWExFjAUBgNVBAcMDU9yYW5nZSBDb3VudHkx +EDAOBgNVBAoMB1ByaXZhZG8xGjAYBgNVBAMMEXNlcnZlci56bGFiZWwuY29tMR8w +HQYJKoZIhvcNAQkBFhBlYXJsZUB6bGFiZWwuY29tMB4XDTE4MDMwNjA1NDg0NFoX +DTE5MDMwNjA1NDg0NFowRTELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3Rh +dGUxITAfBgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDCCASIwDQYJKoZI +hvcNAQEBBQADggEPADCCAQoCggEBAPVKBwbZ+KDSl40YCDkP6y8Sv4iNGvEOZg8Y +X7sGvf/xZH7UiCBWPFIRpNmDSaZ3yjsmFqm6sLiYSGSdrBCFqdt9NTp2r7hga6Sj +oASSZY4B9pf+GblDy5m10KDx90BFKXdPMCLT+o76Nx9PpCvw13A848wHNG3bpBgI +t+w/vJCX3bkRn8yEYAU6GdMbYe7v446hX3kY5UmgeJFr9xz1kq6AzYrMt/UHhNzO +S+QckJaY0OGWvmTNspY3xCbbFtIDkCdBS8CZAw+itnofvnWWKQEXlt6otPh5njwy ++O1t/Q+Z7OMDYQaH02IQx3188/kW3FzOY32knER1uzjmRO+jhA8CAwEAATANBgkq +hkiG9w0BAQsFAAOCAQEAnDrROGRETB0woIcI1+acY1yRq4yAcH2/hdq2MoM+DCyM +E8CJaOznGR9ND0ImWpTZqomHOUkOBpvu7u315blQZcLbL1LfHJGRTCHVhvVrcyEb +fWTnRtAQdlirUm/obwXIitoz64VSbIVzcqqfg9C6ZREB9JbEX98/9Wp2gVY+31oC +JfUvYadSYxh3nblvA4OL+iEZiW8NE3hbW6WPXxvS7Euge0uWMPc4uEcnsE0ZVG3m ++TGimzSdeWDvGBRWZHXczC2zD4aoE5vrl+GD2i++c6yjL/otHfYyUpzUfbI2hMAA +5tAF1D5vAAwA8nfPysumlLsIjohJZo4lgnhB++AlOg== +-----END CERTIFICATE----- +)EOF"; + +static const char serverKey[] PROGMEM = R"EOF( +-----BEGIN RSA PRIVATE KEY----- +MIIEpQIBAAKCAQEA9UoHBtn4oNKXjRgIOQ/rLxK/iI0a8Q5mDxhfuwa9//FkftSI +IFY8UhGk2YNJpnfKOyYWqbqwuJhIZJ2sEIWp2301OnavuGBrpKOgBJJljgH2l/4Z +uUPLmbXQoPH3QEUpd08wItP6jvo3H0+kK/DXcDzjzAc0bdukGAi37D+8kJfduRGf +zIRgBToZ0xth7u/jjqFfeRjlSaB4kWv3HPWSroDNisy39QeE3M5L5ByQlpjQ4Za+ +ZM2yljfEJtsW0gOQJ0FLwJkDD6K2eh++dZYpAReW3qi0+HmePDL47W39D5ns4wNh +BofTYhDHfXzz+RbcXM5jfaScRHW7OOZE76OEDwIDAQABAoIBAQDKov5NFbNFQNR8 +djcM1O7Is6dRaqiwLeH4ZH1pZ3d9QnFwKanPdQ5eCj9yhfhJMrr5xEyCqT0nMn7T +yEIGYDXjontfsf8WxWkH2TjvrfWBrHOIOx4LJEvFzyLsYxiMmtZXvy6YByD+Dw2M +q2GH/24rRdI2klkozIOyazluTXU8yOsSGxHr/aOa9/sZISgLmaGOOuKI/3Zqjdhr +eHeSqoQFt3xXa8jw01YubQUDw/4cv9rk2ytTdAoQUimiKtgtjsggpP1LTq4xcuqN +d4jWhTcnorWpbD2cVLxrEbnSR3VuBCJEZv5axg5ZPxLEnlcId8vMtvTRb5nzzszn +geYUWDPhAoGBAPyKVNqqwQl44oIeiuRM2FYenMt4voVaz3ExJX2JysrG0jtCPv+Y +84R6Cv3nfITz3EZDWp5sW3OwoGr77lF7Tv9tD6BptEmgBeuca3SHIdhG2MR+tLyx +/tkIAarxQcTGsZaSqra3gXOJCMz9h2P5dxpdU+0yeMmOEnAqgQ8qtNBfAoGBAPim +RAtnrd0WSlCgqVGYFCvDh1kD5QTNbZc+1PcBHbVV45EmJ2fLXnlDeplIZJdYxmzu +DMOxZBYgfeLY9exje00eZJNSj/csjJQqiRftrbvYY7m5njX1kM5K8x4HlynQTDkg +rtKO0YZJxxmjRTbFGMegh1SLlFLRIMtehNhOgipRAoGBAPnEEpJGCS9GGLfaX0HW +YqwiEK8Il12q57mqgsq7ag7NPwWOymHesxHV5mMh/Dw+NyBi4xAGWRh9mtrUmeqK +iyICik773Gxo0RIqnPgd4jJWN3N3YWeynzulOIkJnSNx5BforOCTc3uCD2s2YB5X +jx1LKoNQxLeLRN8cmpIWicf/AoGBANjRSsZTKwV9WWIDJoHyxav/vPb+8WYFp8lZ +zaRxQbGM6nn4NiZI7OF62N3uhWB/1c7IqTK/bVHqFTuJCrCNcsgld3gLZ2QWYaMV +kCPgaj1BjHw4AmB0+EcajfKilcqtSroJ6MfMJ6IclVOizkjbByeTsE4lxDmPCDSt +/9MKanBxAoGAY9xo741Pn9WUxDyRplww606ccdNf/ksHWNc/Y2B5SPwxxSnIq8nO +j01SmsCUYVFAgZVOTiiycakjYLzxlc6p8BxSVqy6LlJqn95N8OXoQ+bkwUux/ekg +gz5JWYhbD6c38khSzJb0pNXCo3EuYAVa36kDM96k1BtWuhRS10Q1VXk= +-----END RSA PRIVATE KEY----- +)EOF"; + + +void setup() { + + Serial.begin(115200); + Serial.println(); + Serial.println("Booting Sketch..."); + WiFi.mode(WIFI_STA); + WiFi.begin(ssid, password); + + while (WiFi.waitForConnectResult() != WL_CONNECTED) { + WiFi.begin(ssid, password); + Serial.println("WiFi failed, retrying."); + } + + configTime(3 * 3600, 0, "pool.ntp.org", "time.nist.gov"); + + MDNS.begin(host); + + httpServer.getServer().setRSACert(new BearSSL::X509List(serverCert), new BearSSL::PrivateKey(serverKey)); + httpUpdater.setup(&httpServer, update_path, update_username, update_password); + httpServer.begin(); + + MDNS.addService("https", "tcp", 443); + Serial.printf("BearSSLUpdateServer ready!\nOpen https://%s.local%s in " + "your browser and login with username '%s' and password " + "'%s'\n", + host, update_path, update_username, update_password); +} + +void loop() { + httpServer.handleClient(); + MDNS.update(); +} diff --git a/libraries/HTTPUpdateServer/examples/WebUpdater/WebUpdater.ino b/libraries/HTTPUpdateServer/examples/WebUpdater/WebUpdater.ino new file mode 100644 index 000000000..54178a7ef --- /dev/null +++ b/libraries/HTTPUpdateServer/examples/WebUpdater/WebUpdater.ino @@ -0,0 +1,48 @@ +/* + To upload through terminal you can use: curl -F "image=@firmware.bin" picow-webupdate.local/update +*/ + +#include +#include +#include +#include +#include + +#ifndef STASSID +#define STASSID "your-ssid" +#define STAPSK "your-password" +#endif + +const char* host = "picow-webupdate"; +const char* ssid = STASSID; +const char* password = STAPSK; + +WebServer httpServer(80); +HTTPUpdateServer httpUpdater; + +void setup(void) { + + Serial.begin(115200); + Serial.println(); + Serial.println("Booting Sketch..."); + WiFi.mode(WIFI_STA); + WiFi.begin(ssid, password); + + while (WiFi.waitForConnectResult() != WL_CONNECTED) { + WiFi.begin(ssid, password); + Serial.println("WiFi failed, retrying."); + } + + MDNS.begin(host); + + httpUpdater.setup(&httpServer); + httpServer.begin(); + + MDNS.addService("http", "tcp", 80); + Serial.printf("HTTPUpdateServer ready! Open http://%s.local/update in your browser\n", host); +} + +void loop(void) { + httpServer.handleClient(); + MDNS.update(); +} diff --git a/libraries/HTTPUpdateServer/examples/WebUpdaterAuth/WebUpdaterAuth.ino b/libraries/HTTPUpdateServer/examples/WebUpdaterAuth/WebUpdaterAuth.ino new file mode 100644 index 000000000..a7ca3e2a6 --- /dev/null +++ b/libraries/HTTPUpdateServer/examples/WebUpdaterAuth/WebUpdaterAuth.ino @@ -0,0 +1,51 @@ +/* + To upload through terminal you can use: curl -u admin:admin -F "image=@firmware.bin" picow-webupdate.local/firmware +*/ + +#include +#include +#include +#include +#include + +#ifndef STASSID +#define STASSID "your-ssid" +#define STAPSK "your-password" +#endif + +const char* host = "picow-webupdate"; +const char* update_path = "/firmware"; +const char* update_username = "admin"; +const char* update_password = "admin"; +const char* ssid = STASSID; +const char* password = STAPSK; + +WebServer httpServer(80); +HTTPUpdateServer httpUpdater; + +void setup(void) { + + Serial.begin(115200); + Serial.println(); + Serial.println("Booting Sketch..."); + WiFi.mode(WIFI_STA); + WiFi.begin(ssid, password); + + while (WiFi.waitForConnectResult() != WL_CONNECTED) { + WiFi.begin(ssid, password); + Serial.println("WiFi failed, retrying."); + } + + MDNS.begin(host); + + httpUpdater.setup(&httpServer, update_path, update_username, update_password); + httpServer.begin(); + + MDNS.addService("http", "tcp", 80); + Serial.printf("HTTPUpdateServer ready! Open http://%s.local%s in your browser and login with username '%s' and password '%s'\n", host, update_path, update_username, update_password); +} + +void loop(void) { + httpServer.handleClient(); + MDNS.update(); +} diff --git a/libraries/HTTPUpdateServer/keywords.txt b/libraries/HTTPUpdateServer/keywords.txt new file mode 100644 index 000000000..1c2c6d5ab --- /dev/null +++ b/libraries/HTTPUpdateServer/keywords.txt @@ -0,0 +1,21 @@ +####################################### +# Syntax Coloring Map For HTTPUpdateServer +####################################### + +####################################### +# Datatypes (KEYWORD1) +####################################### + +HTTPUpdateServer KEYWORD1 +HTTPUpdateServerSecure KEYWORD1 + +####################################### +# Methods and Functions (KEYWORD2) +####################################### + +begin KEYWORD2 +setup KEYWORD2 + +####################################### +# Constants (LITERAL1) +####################################### diff --git a/libraries/HTTPUpdateServer/library.properties b/libraries/HTTPUpdateServer/library.properties new file mode 100644 index 000000000..fb201cf31 --- /dev/null +++ b/libraries/HTTPUpdateServer/library.properties @@ -0,0 +1,10 @@ +name=HTTPUpdateServer +version=1.0 +author=Ivan Grokhotkov, Miguel Angel Ajo +maintainer=Earle F. Philhower, III +sentence=Simple HTTP Update server based on the Pico WebServer +paragraph=The library accepts HTTP post requests to the /update url, and updates the Pico firmware. +category=Communication +url=https://github.com/earlephilhower/arduino-pico +architectures=rp2040 +dot_a_linkage=false diff --git a/libraries/HTTPUpdateServer/src/HTTPUpdateServer-impl.h b/libraries/HTTPUpdateServer/src/HTTPUpdateServer-impl.h new file mode 100644 index 000000000..2e1b5f4a6 --- /dev/null +++ b/libraries/HTTPUpdateServer/src/HTTPUpdateServer-impl.h @@ -0,0 +1,182 @@ +/* + HTTPUpdateServer - Support simple web based OTA + Modified 2022 Earle F. Philhower, III. All rights reserved. + + Ported from the ESP8266 Arduino core, (c) copyright multiple authors + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#pragma once + +#include +#include +#include +#include +#include +#include +#include "StreamString.h" +#include "HTTPUpdateServer.h" + +extern uint8_t _FS_start; +extern uint8_t _FS_end; + + +static const char serverIndex[] PROGMEM = + R"( + + + + + + +
+ Firmware:
+ + +
+
+ FileSystem:
+ + +
+ + )"; +static const char successResponse[] PROGMEM = + "Update Success! Rebooting..."; + +template +HTTPUpdateServerTemplate::HTTPUpdateServerTemplate(bool serial_debug) { + _serial_output = serial_debug; + _server = nullptr; + _username = ""; + _password = ""; + _authenticated = false; +} + +template +void HTTPUpdateServerTemplate::setup(WebServerTemplate *server, const String& path, const String& username, const String& password) { + _server = server; + _username = username; + _password = password; + + // handler for the /update form page + _server->on(path.c_str(), HTTP_GET, [&]() { + if (_username != "" && _password != "" && !_server->authenticate(_username.c_str(), _password.c_str())) { + return _server->requestAuthentication(); + } + _server->send_P(200, PSTR("text/html"), serverIndex); + }); + + // handler for the /update form page - preflight options + _server->on(path.c_str(), HTTP_OPTIONS, [&]() { + _server->sendHeader("Access-Control-Allow-Headers", "*"); + _server->sendHeader("Access-Control-Allow-Origin", "*"); + _server->send(200, F("text/html"), String(F("y"))); + }, [&]() { + _authenticated = (_username == "" || _password == "" || _server->authenticate(_username.c_str(), _password.c_str())); + if (!_authenticated) { + if (_serial_output) { + Serial.printf("Unauthenticated Update\n"); + } + return; + } + }); + + // handler for the /update form POST (once file upload finishes) + _server->on(path.c_str(), HTTP_POST, [&]() { + _server->sendHeader("Access-Control-Allow-Headers", "*"); + _server->sendHeader("Access-Control-Allow-Origin", "*"); + if (!_authenticated) { + return _server->requestAuthentication(); + } + if (Update.hasError()) { + _server->send(200, F("text/html"), String(F("Update error: ")) + _updaterError); + } else { + _server->client().setNoDelay(true); + _server->send_P(200, PSTR("text/html"), successResponse); + delay(100); + _server->client().stop(); + rp2040.restart(); + } + }, [&]() { + // handler for the file upload, gets the sketch bytes, and writes + // them through the Update object + HTTPUpload& upload = _server->upload(); + + if (upload.status == UPLOAD_FILE_START) { + _updaterError = ""; + + _authenticated = (_username == "" || _password == "" || _server->authenticate(_username.c_str(), _password.c_str())); + if (!_authenticated) { + if (_serial_output) { + Serial.printf("Unauthenticated Update\n"); + } + return; + } + + if (_serial_output) { + Serial.printf("Update: %s\n", upload.filename.c_str()); + } + if (upload.name == "filesystem") { + size_t fsSize = ((size_t)&_FS_end - (size_t)&_FS_start); + LittleFS.end(); + if (!Update.begin(fsSize, U_FS)) { //start with max available size + if (_serial_output) { + Update.printError(Serial); + } + } + } else { + FSInfo64 i; + LittleFS.begin(); + LittleFS.info64(i); + uint32_t maxSketchSpace = i.totalBytes - i.usedBytes; + if (!Update.begin(maxSketchSpace, U_FLASH)) { //start with max available size + _setUpdaterError(); + } + } + } else if (_authenticated && upload.status == UPLOAD_FILE_WRITE && !_updaterError.length()) { + if (_serial_output) { + Serial.printf("."); + } + if (Update.write(upload.buf, upload.currentSize) != upload.currentSize) { + _setUpdaterError(); + } + } else if (_authenticated && upload.status == UPLOAD_FILE_END && !_updaterError.length()) { + if (Update.end(true)) { //true to set the size to the current progress + if (_serial_output) { + Serial.printf("Update Success: %zu\nRebooting...\n", upload.totalSize); + } + } else { + _setUpdaterError(); + } + } else if (_authenticated && upload.status == UPLOAD_FILE_ABORTED) { + Update.end(); + if (_serial_output) { + Serial.println("Update was aborted"); + } + } + }); +} + +template +void HTTPUpdateServerTemplate::_setUpdaterError() { + if (_serial_output) { + Update.printError(Serial); + } + StreamString str; + Update.printError(str); + _updaterError = str.c_str(); +} diff --git a/libraries/HTTPUpdateServer/src/HTTPUpdateServer.h b/libraries/HTTPUpdateServer/src/HTTPUpdateServer.h new file mode 100644 index 000000000..704bb7ea5 --- /dev/null +++ b/libraries/HTTPUpdateServer/src/HTTPUpdateServer.h @@ -0,0 +1,65 @@ +/* + HTTPUpdateServer - Support simple web based OTA + Modified 2022 Earle F. Philhower, III. All rights reserved. + + Ported from the ESP8266 Arduino core, (c) copyright multiple authors + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#pragma once + +#include + +template +class HTTPUpdateServerTemplate { +public: + HTTPUpdateServerTemplate(bool serial_debug = false); + + void setup(WebServerTemplate *server) { + setup(server, "", ""); + } + + void setup(WebServerTemplate *server, const String& path) { + setup(server, path, "", ""); + } + + void setup(WebServerTemplate *server, const String& username, const String& password) { + setup(server, "/update", username, password); + } + + void setup(WebServerTemplate *server, const String& path, const String& username, const String& password); + + void updateCredentials(const String& username, const String& password) { + _username = username; + _password = password; + } + +protected: + void _setUpdaterError(); + +private: + bool _serial_output; + WebServerTemplate *_server; + String _username; + String _password; + bool _authenticated; + String _updaterError; +}; + +#include "HTTPUpdateServer-impl.h" + +using HTTPUpdateServer = HTTPUpdateServerTemplate; +using HTTPUpdateServerSecure = HTTPUpdateServerTemplate; diff --git a/libraries/Hash/examples/sha1/sha1.ino b/libraries/Hash/examples/sha1/sha1.ino new file mode 100644 index 000000000..4fe9f8a9c --- /dev/null +++ b/libraries/Hash/examples/sha1/sha1.ino @@ -0,0 +1,29 @@ +/** + simple demo to show sha1 calculation +*/ +#include +#include + +void setup() { + Serial.begin(115200); +} + +void loop() { + + // usage as String + // SHA1:a9993e364706816aba3e25717850c26c9cd0d89d + + Serial.print("SHA1:"); + Serial.println(sha1("abc")); + + // usage as ptr + // SHA1:a94a8fe5ccb19ba61c4c0873d391e987982fbbd3 + uint8_t hash[20]; + sha1("test", &hash[0]); + + Serial.print("SHA1:"); + for (uint16_t i = 0; i < 20; i++) { Serial.printf("%02x", hash[i]); } + Serial.println(); + + delay(1000); +} diff --git a/libraries/Hash/keywords.txt b/libraries/Hash/keywords.txt new file mode 100644 index 000000000..e97cbceea --- /dev/null +++ b/libraries/Hash/keywords.txt @@ -0,0 +1,23 @@ +####################################### +# Syntax Coloring Map For Hash +####################################### + +####################################### +# Library (KEYWORD3) +####################################### + +Hash KEYWORD3 RESERVED_WORD + +####################################### +# Datatypes (KEYWORD1) +####################################### + +####################################### +# Methods and Functions (KEYWORD2) +####################################### + +sha1 KEYWORD2 + +####################################### +# Constants (LITERAL1) +####################################### diff --git a/libraries/Hash/library.properties b/libraries/Hash/library.properties new file mode 100644 index 000000000..152184d2e --- /dev/null +++ b/libraries/Hash/library.properties @@ -0,0 +1,10 @@ +name=Hash +version=1.0 +author=Markus Sattler +maintainer=Markus Sattler +sentence=Generate Hash from data +paragraph= +category=Data Processing +url= +architectures=rp2040 +dot_a_linkage=true diff --git a/libraries/Hash/src/Hash.cpp b/libraries/Hash/src/Hash.cpp new file mode 100644 index 000000000..2d8866361 --- /dev/null +++ b/libraries/Hash/src/Hash.cpp @@ -0,0 +1,96 @@ +/** + * @file Hash.cpp + * @date 20.05.2015 + * @author Markus Sattler + * + * Copyright (c) 2015 Markus Sattler. All rights reserved. + * This file is part of the esp8266 core for Arduino environment. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#include +#include + +#include "Hash.h" + +/** + * create a sha1 hash from data + * @param data uint8_t * + * @param size uint32_t + * @param hash uint8_t[20] + */ +void sha1(const uint8_t* data, uint32_t size, uint8_t hash[20]) { + br_sha1_context ctx; + +#ifdef DEBUG_SHA1 + os_printf("DATA:"); + for(uint16_t i = 0; i < size; i++) { + os_printf("%02X", data[i]); + } + os_printf("\n"); + os_printf("DATA:"); + for(uint16_t i = 0; i < size; i++) { + os_printf("%c", data[i]); + } + os_printf("\n"); +#endif + + br_sha1_init(&ctx); + br_sha1_update(&ctx, data, size); + br_sha1_out(&ctx, hash); + +#ifdef DEBUG_SHA1 + os_printf("SHA1:"); + for(uint16_t i = 0; i < 20; i++) { + os_printf("%02X", hash[i]); + } + os_printf("\n\n"); +#endif +} + +void sha1(const char* data, uint32_t size, uint8_t hash[20]) { + sha1((const uint8_t *) data, size, hash); +} + +void sha1(const String& data, uint8_t hash[20]) { + sha1(data.c_str(), data.length(), hash); +} + +String sha1(const uint8_t* data, uint32_t size) { + uint8_t hash[20]; + String hashStr((const char*)nullptr); + hashStr.reserve(20 * 2 + 1); + + sha1(&data[0], size, &hash[0]); + + for(uint16_t i = 0; i < 20; i++) { + char hex[3]; + snprintf(hex, sizeof(hex), "%02x", hash[i]); + hashStr += hex; + } + + return hashStr; +} + +String sha1(const char* data, uint32_t size) { + return sha1((const uint8_t*) data, size); +} + +String sha1(const String& data) { + return sha1(data.c_str(), data.length()); +} + diff --git a/libraries/Hash/src/Hash.h b/libraries/Hash/src/Hash.h new file mode 100644 index 000000000..67a315112 --- /dev/null +++ b/libraries/Hash/src/Hash.h @@ -0,0 +1,38 @@ +/** + * @file Hash.h + * @date 20.05.2015 + * @author Markus Sattler + * + * Copyright (c) 2015 Markus Sattler. All rights reserved. + * This file is part of the esp8266 core for Arduino environment. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifndef HASH_H_ +#define HASH_H_ + +//#define DEBUG_SHA1 + +void sha1(const uint8_t* data, uint32_t size, uint8_t hash[20]); +void sha1(const char* data, uint32_t size, uint8_t hash[20]); +void sha1(const String& data, uint8_t hash[20]); + +String sha1(const uint8_t* data, uint32_t size); +String sha1(const char* data, uint32_t size); +String sha1(const String& data); + +#endif /* HASH_H_ */ diff --git a/libraries/I2S/examples/I2SInput/I2SInput.ino b/libraries/I2S/examples/I2SInput/I2SInput.ino index 883970af5..f1db6fde1 100644 --- a/libraries/I2S/examples/I2SInput/I2SInput.ino +++ b/libraries/I2S/examples/I2SInput/I2SInput.ino @@ -10,6 +10,19 @@ +-- ------------------------------------ --+ left RPI | (1) GND (2) DIN (3) BCLK (4) LRCLK (5) 3.3V | AIY right logo +---------------------------------------------+ logo + + For an Adfruit I2S MEMS microphone (https://www.adafruit.com/product/3421), + connect the pins as follows: + + DOUT -> GPIO0 + BCLK <- GPIO1 + LRCL <- GPIO2 # LRCLK = BCLK + 1 + GND <-> GND + 3V <-> 3V3OUT + + The other idiosyncrasy of most modern MEMS microphones is that they + require a minimum clock rate to wake up. For example, the SPH0645 + microphone needs at least 1MHz. */ #include @@ -20,15 +33,21 @@ void setup() { Serial.begin(115200); i2s.setDATA(0); - i2s.setBCLK(1); // LRCLK = GP2 + i2s.setBCLK(1); // Note: LRCLK = BCLK + 1 i2s.setBitsPerSample(16); i2s.setFrequency(22050); + // NOTE: The following values are known to work with the Adafruit microphone: + // i2s.setBitsPerSample(32); + // i2s.setFrequency(16000); i2s.begin(); while (1) { int16_t l, r; i2s.read16(&l, &r); - Serial.printf("%d %d\n", l, r); + // NOTE: Adafruit microphone word size needs to match the BPS above. + // int32_t l, r; + // i2s.read32(&l, &r); + Serial.printf("%d %d\r\n", l, r); } } diff --git a/libraries/I2S/keywords.txt b/libraries/I2S/keywords.txt index 203e9a54c..d6c4e9433 100644 --- a/libraries/I2S/keywords.txt +++ b/libraries/I2S/keywords.txt @@ -18,6 +18,9 @@ setBCLK KEYWORD2 setDATA KEYWORD2 setBitsPerSample KEYWORD2 setFrequency KEYWORD2 +setBuffers KEYWORD2 +setLSBJFormat KEYWORD2 +swapClocks KEYWORD2 read8 KEYWORD2 read16 KEYWORD2 diff --git a/libraries/I2S/src/AudioRingBuffer.cpp b/libraries/I2S/src/AudioRingBuffer.cpp deleted file mode 100644 index 83f4d7a57..000000000 --- a/libraries/I2S/src/AudioRingBuffer.cpp +++ /dev/null @@ -1,256 +0,0 @@ -/* - AudioRingBuffer for Raspnerry Pi Pico RP2040 - Implements a ring buffer for PIO DMA for I2S read or write - - Copyright (c) 2022 Earle F. Philhower, III - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -*/ - -#include -#include -#include "hardware/dma.h" -#include "hardware/irq.h" -#include "hardware/pio.h" -#include "pio_i2s.pio.h" -#include "AudioRingBuffer.h" - -static int __channelCount = 0; // # of channels left. When we hit 0, then remove our handler -static AudioRingBuffer* __channelMap[12]; // Lets the IRQ handler figure out where to dispatch to - -AudioRingBuffer::AudioRingBuffer(size_t bufferCount, size_t bufferWords, int32_t silenceSample, PinMode direction) { - _running = false; - _silenceSample = silenceSample; - _bufferCount = bufferCount; - _wordsPerBuffer = bufferWords; - _isOutput = direction == OUTPUT; - _overunderflow = false; - _callback = nullptr; - _userBuffer = -1; - _userOff = 0; - for (size_t i = 0; i < bufferCount; i++) { - auto ab = new AudioBuffer; - ab->buff = new uint32_t[_wordsPerBuffer]; - ab->empty = true; - _buffers.push_back(ab); - } -} - -AudioRingBuffer::~AudioRingBuffer() { - if (_running) { - for (auto i = 0; i < 2; i++) { - dma_channel_set_irq0_enabled(_channelDMA[i], false); - dma_channel_unclaim(_channelDMA[i]); - __channelMap[_channelDMA[i]] = nullptr; - } - while (_buffers.size()) { - auto ab = _buffers.back(); - _buffers.pop_back(); - delete[] ab->buff; - delete ab; - } - __channelCount--; - if (!__channelCount) { - irq_set_enabled(DMA_IRQ_0, false); - // TODO - how can we know if there are no other parts of the core using DMA0 IRQ?? - irq_remove_handler(DMA_IRQ_0, _irq); - } - } -} - -void AudioRingBuffer::setCallback(void (*fn)()) { - _callback = fn; -} - -bool AudioRingBuffer::begin(int dreq, volatile void *pioFIFOAddr) { - _running = true; - // Set all buffers to silence, empty - for (auto buff : _buffers) { - buff->empty = true; - if (_isOutput) { - for (uint32_t x = 0; x < _wordsPerBuffer; x++) { - buff->buff[x] = _silenceSample; - } - } - } - // Get ping and pong DMA channels - for (auto i = 0; i < 2; i++) { - _channelDMA[i] = dma_claim_unused_channel(true); - if (_channelDMA[i] == -1) { - if (i == 1) { - dma_channel_unclaim(_channelDMA[0]); - } - return false; - } - } - bool needSetIRQ = __channelCount == 0; - // Need to know both channels to set up ping-pong, so do in 2 stages - for (auto i = 0; i < 2; i++) { - dma_channel_config c = dma_channel_get_default_config(_channelDMA[i]); - channel_config_set_transfer_data_size(&c, DMA_SIZE_32); // 32b transfers into PIO FIFO - if (_isOutput) { - channel_config_set_read_increment(&c, true); // Reading incrementing addresses - channel_config_set_write_increment(&c, false); // Writing to the same FIFO address - } else { - channel_config_set_read_increment(&c, false); // Reading same FIFO address - channel_config_set_write_increment(&c, true); // Writing to incrememting buffers - } - channel_config_set_dreq(&c, dreq); // Wait for the PIO TX FIFO specified - channel_config_set_chain_to(&c, _channelDMA[i ^ 1]); // Start other channel when done - channel_config_set_irq_quiet(&c, false); // Need IRQs - - if (_isOutput) { - dma_channel_configure(_channelDMA[i], &c, pioFIFOAddr, _buffers[i]->buff, _wordsPerBuffer, false); - } else { - dma_channel_configure(_channelDMA[i], &c, _buffers[i]->buff, pioFIFOAddr, _wordsPerBuffer, false); - } - dma_channel_set_irq0_enabled(_channelDMA[i], true); - __channelMap[_channelDMA[i]] = this; - __channelCount++; - } - if (needSetIRQ) { - irq_add_shared_handler(DMA_IRQ_0, _irq, PICO_SHARED_IRQ_HANDLER_DEFAULT_ORDER_PRIORITY); - irq_set_enabled(DMA_IRQ_0, true); - } - _curBuffer = 0; - _nextBuffer = 2 % _bufferCount; - dma_channel_start(_channelDMA[0]); - return true; -} - -bool AudioRingBuffer::write(uint32_t v, bool sync) { - if (!_running || !_isOutput) { - return false; - } - if (_userBuffer == -1) { - // First write or overflow, pick spot 2 buffers out - _userBuffer = (_nextBuffer + 2) % _bufferCount; - _userOff = 0; - } - if (!_buffers[_userBuffer]->empty) { - if (!sync) { - return false; - } else { - while (!_buffers[_userBuffer]->empty) { - /* noop busy wait */ - } - } - } - if (_userBuffer == _curBuffer) { - if (!sync) { - return false; - } else { - while (_userBuffer == _curBuffer) { - /* noop busy wait */ - } - } - } - _buffers[_userBuffer]->buff[_userOff++] = v; - if (_userOff == _wordsPerBuffer) { - _buffers[_userBuffer]->empty = false; - _userBuffer = (_userBuffer + 1) % _bufferCount; - _userOff = 0; - } - return true; -} - -bool AudioRingBuffer::read(uint32_t *v, bool sync) { - if (!_running || _isOutput) { - return false; - } - if (_userBuffer == -1) { - // First write or overflow, pick last filled buffer - _userBuffer = (_curBuffer - 1 + _bufferCount) % _bufferCount; - _userOff = 0; - } - if (_buffers[_userBuffer]->empty) { - if (!sync) { - return false; - } else { - while (_buffers[_userBuffer]->empty) { - /* noop busy wait */ - } - } - } - if (_userBuffer == _curBuffer) { - if (!sync) { - return false; - } else { - while (_userBuffer == _curBuffer) { - /* noop busy wait */ - } - } - } - auto ret = _buffers[_userBuffer]->buff[_userOff++]; - if (_userOff == _wordsPerBuffer) { - _buffers[_userBuffer]->empty = true; - _userBuffer = (_userBuffer + 1) % _bufferCount; - _userOff = 0; - } - *v = ret; - return true; -} - -bool AudioRingBuffer::getOverUnderflow() { - bool hold = _overunderflow; - _overunderflow = false; - return hold; -} - -int AudioRingBuffer::available() { - if (!_running) { - return 0; - } - int avail; - avail = _wordsPerBuffer - _userOff; - avail += ((_bufferCount + _curBuffer - _userBuffer) % _bufferCount) * _wordsPerBuffer; - return avail; -} - -void AudioRingBuffer::flush() { - while (_curBuffer != _userBuffer) { - // busy wait - } -} - -void __not_in_flash_func(AudioRingBuffer::_dmaIRQ)(int channel) { - if (_isOutput) { - for (uint32_t x = 0; x < _wordsPerBuffer; x++) { - _buffers[_curBuffer]->buff[x] = _silenceSample; - } - _buffers[_curBuffer]-> empty = true; - _overunderflow = _overunderflow | _buffers[_nextBuffer]->empty; - dma_channel_set_read_addr(channel, _buffers[_nextBuffer]->buff, false); - } else { - _buffers[_curBuffer]-> empty = false; - _overunderflow = _overunderflow | !_buffers[_nextBuffer]->empty; - dma_channel_set_write_addr(channel, _buffers[_nextBuffer]->buff, false); - } - dma_channel_set_trans_count(channel, _wordsPerBuffer, false); - _curBuffer = (_curBuffer + 1) % _bufferCount; - _nextBuffer = (_nextBuffer + 1) % _bufferCount; - dma_channel_acknowledge_irq0(channel); - if (_callback) { - _callback(); - } -} - -void __not_in_flash_func(AudioRingBuffer::_irq)() { - for (size_t i = 0; i < sizeof(__channelMap); i++) { - if (dma_channel_get_irq0_status(i) && __channelMap[i]) { - __channelMap[i]->_dmaIRQ(i); - } - } -} diff --git a/libraries/I2S/src/AudioRingBuffer.h b/libraries/I2S/src/AudioRingBuffer.h deleted file mode 100644 index 5a4d2dde1..000000000 --- a/libraries/I2S/src/AudioRingBuffer.h +++ /dev/null @@ -1,69 +0,0 @@ -/* - AudioRingBuffer for Rasperry Pi Pico - Implements a ring buffer for PIO DMA for I2S read or write - - Copyright (c) 2022 Earle F. Philhower, III - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -*/ - -#pragma once -#include -#include - -class AudioRingBuffer { -public: - AudioRingBuffer(size_t bufferCount, size_t bufferWords, int32_t silenceSample, PinMode direction = OUTPUT); - ~AudioRingBuffer(); - - void setCallback(void (*fn)()); - - bool begin(int dreq, volatile void *pioFIFOAddr); - - bool write(uint32_t v, bool sync = true); - bool read(uint32_t *v, bool sync = true); - void flush(); - - bool getOverUnderflow(); - int available(); - -private: - void _dmaIRQ(int channel); - static void _irq(); - - typedef struct { - uint32_t *buff; - volatile bool empty; - } AudioBuffer; - - bool _running = false; - std::vector _buffers; - volatile int _curBuffer; - volatile int _nextBuffer; - size_t _chunkSampleCount; - int _bitsPerSample; - size_t _wordsPerBuffer; - size_t _bufferCount; - bool _isOutput; - int32_t _silenceSample; - int _channelDMA[2]; - void (*_callback)(); - - bool _overunderflow; - - // User buffer pointer - int _userBuffer = -1; - size_t _userOff = 0; -}; diff --git a/libraries/I2S/src/I2S.cpp b/libraries/I2S/src/I2S.cpp index 7d3a0acf9..36713aa47 100644 --- a/libraries/I2S/src/I2S.cpp +++ b/libraries/I2S/src/I2S.cpp @@ -27,15 +27,32 @@ I2S::I2S(PinMode direction) { _running = false; _bps = 16; _writtenHalf = false; + _isOutput = direction == OUTPUT; _pinBCLK = 26; _pinDOUT = 28; +#ifdef PIN_I2S_BCLK + _pinBCLK = PIN_I2S_BCLK; +#endif + +#ifdef PIN_I2S_DOUT + if (_isOutput) { + _pinDOUT = PIN_I2S_DOUT; + } +#endif + +#ifdef PIN_I2S_DIN + if (!_isOutput) { + _pinDOUT = PIN_I2S_DIN; + } +#endif _freq = 48000; _arb = nullptr; - _isOutput = direction == OUTPUT; _cb = nullptr; _buffers = 8; - _bufferWords = 16; + _bufferWords = 0; _silenceSample = 0; + _isLSBJ = false; + _swapClocks = false; } I2S::~I2S() { @@ -84,6 +101,22 @@ bool I2S::setFrequency(int newFreq) { return true; } +bool I2S::setLSBJFormat() { + if (_running || !_isOutput) { + return false; + } + _isLSBJ = true; + return true; +} + +bool I2S::swapClocks() { + if (_running || !_isOutput) { + return false; + } + _swapClocks = true; + return true; +} + void I2S::onTransmit(void(*fn)(void)) { if (_isOutput) { _cb = fn; @@ -106,12 +139,20 @@ bool I2S::begin() { _running = true; _hasPeeked = false; int off = 0; - _i2s = new PIOProgram(_isOutput ? &pio_i2s_out_program : &pio_i2s_in_program); + if (!_swapClocks) { + _i2s = new PIOProgram(_isOutput ? (_isLSBJ ? &pio_lsbj_out_program : &pio_i2s_out_program) : &pio_i2s_in_program); + } else { + _i2s = new PIOProgram(_isOutput ? (_isLSBJ ? &pio_lsbj_out_swap_program : &pio_i2s_out_swap_program) : &pio_i2s_in_swap_program); + } _i2s->prepare(&_pio, &_sm, &off); if (_isOutput) { - pio_i2s_out_program_init(_pio, _sm, off, _pinDOUT, _pinBCLK, _bps); + if (_isLSBJ) { + pio_lsbj_out_program_init(_pio, _sm, off, _pinDOUT, _pinBCLK, _bps, _swapClocks); + } else { + pio_i2s_out_program_init(_pio, _sm, off, _pinDOUT, _pinBCLK, _bps, _swapClocks); + } } else { - pio_i2s_in_program_init(_pio, _sm, off, _pinDOUT, _pinBCLK, _bps); + pio_i2s_in_program_init(_pio, _sm, off, _pinDOUT, _pinBCLK, _bps, _swapClocks); } setFrequency(_freq); if (_bps == 8) { @@ -121,7 +162,10 @@ bool I2S::begin() { uint16_t a = _silenceSample & 0xffff; _silenceSample = (a << 16) | a; } - _arb = new AudioRingBuffer(_buffers, _bufferWords, _silenceSample, _isOutput ? OUTPUT : INPUT); + if (!_bufferWords) { + _bufferWords = 16 * (_bps == 32 ? 2 : 1); + } + _arb = new AudioBufferManager(_buffers, _bufferWords, _silenceSample, _isOutput ? OUTPUT : INPUT); _arb->begin(pio_get_dreq(_pio, _sm, _isOutput), _isOutput ? &_pio->txf[_sm] : (volatile void*)&_pio->rxf[_sm]); _arb->setCallback(_cb); pio_sm_set_enabled(_pio, _sm, true); @@ -130,18 +174,24 @@ bool I2S::begin() { } void I2S::end() { - _running = false; - delete _arb; - _arb = nullptr; - delete _i2s; - _i2s = nullptr; + if (_running) { + pio_sm_set_enabled(_pio, _sm, false); + _running = false; + delete _arb; + _arb = nullptr; + delete _i2s; + _i2s = nullptr; + } } int I2S::available() { - if (!_running || _isOutput) { + if (!_running) { return 0; + } else if (_isOutput) { + return availableForWrite(); // Do what I mean, not what I say + } else { + return _arb->available(); } - return _arb->available(); } int I2S::read() { @@ -154,9 +204,9 @@ int I2S::read() { return _peekSaved; } - if (_wasHolding <= 0) { + if (_isHolding <= 0) { read(&_holdWord, true); - _wasHolding = 32; + _isHolding = 32; } int ret; @@ -164,18 +214,18 @@ int I2S::read() { case 8: ret = _holdWord >> 24; _holdWord <<= 8; - _wasHolding -= 8; + _isHolding -= 8; return ret; case 16: ret = _holdWord >> 16; _holdWord <<= 16; - _wasHolding -= 32; + _isHolding -= 32; return ret; case 24: case 32: default: ret = _holdWord; - _wasHolding = 0; + _isHolding = 0; return ret; } } @@ -204,26 +254,26 @@ size_t I2S::_writeNatural(int32_t s) { switch (_bps) { case 8: _holdWord |= s & 0xff; - if (_wasHolding >= 24) { + if (_isHolding >= 24) { auto ret = write(_holdWord, true); _holdWord = 0; - _wasHolding = 0; + _isHolding = 0; return ret; } else { _holdWord <<= 8; - _wasHolding += 8; + _isHolding += 8; return 1; } case 16: _holdWord |= s & 0xffff; - if (_wasHolding) { + if (_isHolding) { auto ret = write(_holdWord, true); _holdWord = 0; - _wasHolding = 0; + _isHolding = 0; return ret; } else { _holdWord <<= 16; - _wasHolding = 16; + _isHolding = 16; return 1; } case 24: @@ -280,13 +330,13 @@ bool I2S::read8(int8_t *l, int8_t *r) { if (!_running || _isOutput) { return false; } - if (_wasHolding) { + if (_isHolding) { *l = (_holdWord >> 8) & 0xff; *r = (_holdWord >> 0) & 0xff; - _wasHolding = 0; + _isHolding = 0; } else { read(&_holdWord, true); - _wasHolding = 16; + _isHolding = 16; *l = (_holdWord >> 24) & 0xff; *r = (_holdWord >> 16) & 0xff; } diff --git a/libraries/I2S/src/I2S.h b/libraries/I2S/src/I2S.h index 97100a685..93710e098 100644 --- a/libraries/I2S/src/I2S.h +++ b/libraries/I2S/src/I2S.h @@ -21,8 +21,7 @@ #pragma once #include -#include -#include "AudioRingBuffer.h" +#include "AudioBufferManager.h" class I2S : public Stream { public: @@ -34,6 +33,8 @@ class I2S : public Stream { bool setBitsPerSample(int bps); bool setBuffers(size_t buffers, size_t bufferWords, int32_t silenceSample = 0); bool setFrequency(int newFreq); + bool setLSBJFormat(); + bool swapClocks(); bool begin(long sampleRate) { setFrequency(sampleRate); @@ -74,7 +75,7 @@ class I2S : public Stream { return write((uint32_t)s); } - // Write 32 bit value to port, user responsbile for packing/alignment, etc. + // Write 32 bit value to port, user responsible for packing/alignment, etc. size_t write(int32_t val, bool sync); // Write sample to I2S port, will block until completed @@ -83,7 +84,7 @@ class I2S : public Stream { size_t write24(int32_t l, int32_t r); // Note that 24b must have values left-aligned (i.e. 0xABCDEF00) size_t write32(int32_t l, int32_t r); - // Read 32 bit value to port, user responsbile for packing/alignment, etc. + // Read 32 bit value to port, user responsible for packing/alignment, etc. size_t read(int32_t *val, bool sync); // Read samples from I2S port, will block until data available @@ -105,7 +106,9 @@ class I2S : public Stream { size_t _buffers; size_t _bufferWords; int32_t _silenceSample; + bool _isLSBJ; bool _isOutput; + bool _swapClocks; bool _running; @@ -117,11 +120,11 @@ class I2S : public Stream { bool _writtenHalf; int32_t _holdWord = 0; - int _wasHolding = 0; + int _isHolding = 0; void (*_cb)(); - AudioRingBuffer *_arb; + AudioBufferManager *_arb; PIOProgram *_i2s; PIO _pio; int _sm; diff --git a/libraries/I2S/src/pio_i2s.pio b/libraries/I2S/src/pio_i2s.pio index 2b09c2cd1..646d94b8a 100644 --- a/libraries/I2S/src/pio_i2s.pio +++ b/libraries/I2S/src/pio_i2s.pio @@ -41,6 +41,73 @@ right: out pins, 1 side 0b00 ; Last bit of right also has WCLK change ; Loop back to beginning... +.program pio_i2s_out_swap +.side_set 2 ; 0 = wclk, 1=bclk + +; The C code should place (number of bits/sample - 2) in Y and +; also update the SHIFTCTRL to be 24 or 32 as appropriate + +; +----- BCLK +; |+---- WCLK + mov x, y side 0b10 +left: + out pins, 1 side 0b00 + jmp x--, left side 0b10 + out pins, 1 side 0b01 ; Last bit of left has WCLK change per I2S spec + + mov x, y side 0b11 +right: + out pins, 1 side 0b01 + jmp x--, right side 0b11 + out pins, 1 side 0b00 ; Last bit of right also has WCLK change + ; Loop back to beginning... + + + +.program pio_lsbj_out +.side_set 2 ; 0 = bclk, 1=wclk + +; The C code should place (number of bits/sample - 2) in Y and +; also update the SHIFTCTRL to be 24 or 32 as appropriate + +; +----- WCLK +; |+---- BCLK + mov x, y side 0b01 +left: + out pins, 1 side 0b10 + jmp x--, left side 0b11 + out pins, 1 side 0b10 + + mov x, y side 0b11 +right: + out pins, 1 side 0b00 + jmp x--, right side 0b01 + out pins, 1 side 0b00 + ; Loop back to beginning... + + +.program pio_lsbj_out_swap +.side_set 2 ; 0 = wclk, 1=bclk + +; The C code should place (number of bits/sample - 2) in Y and +; also update the SHIFTCTRL to be 24 or 32 as appropriate + +; +----- BCLK +; |+---- WCLK + mov x, y side 0b10 +left: + out pins, 1 side 0b01 + jmp x--, left side 0b11 + out pins, 1 side 0b01 + + mov x, y side 0b11 +right: + out pins, 1 side 0b00 + jmp x--, right side 0b10 + out pins, 1 side 0b00 + ; Loop back to beginning... + + .program pio_i2s_in ; Note this is the same as _out, just "in" and not "out" .side_set 2 ; 0 = bclk, 1=wclk @@ -63,17 +130,61 @@ right: in pins, 1 side 0b01 ; Last bit of right also has WCLK change ; Loop back to beginning... - + +.program pio_i2s_in_swap ; Note this is the same as _out, just "in" and not "out" +.side_set 2 ; 0 = wclk, 1=bclk + +; The C code should place (number of bits/sample - 2) in Y and +; also update the SHIFTCTRL to be 24 or 32 as appropriate + +; +----- BCLK +; |+---- WCLK + mov x, y side 0b00 +left: + in pins, 1 side 0b10 + jmp x--, left side 0b00 + in pins, 1 side 0b11 ; Last bit of left has WCLK change per I2S spec + + mov x, y side 0b01 +right: + in pins, 1 side 0b11 + jmp x--, right side 0b01 + in pins, 1 side 0b10 ; Last bit of right also has WCLK change + ; Loop back to beginning... + + + % c-sdk { -static inline void pio_i2s_out_program_init(PIO pio, uint sm, uint offset, uint data_pin, uint clock_pin_base, uint bits) { +static inline void pio_i2s_out_program_init(PIO pio, uint sm, uint offset, uint data_pin, uint clock_pin_base, uint bits, bool swap) { pio_gpio_init(pio, data_pin); pio_gpio_init(pio, clock_pin_base); pio_gpio_init(pio, clock_pin_base + 1); - pio_sm_config sm_config = pio_i2s_out_program_get_default_config(offset); - + pio_sm_config sm_config = swap ? pio_i2s_out_swap_program_get_default_config(offset) : pio_i2s_out_program_get_default_config(offset); + + sm_config_set_out_pins(&sm_config, data_pin, 1); + sm_config_set_sideset_pins(&sm_config, clock_pin_base); + sm_config_set_out_shift(&sm_config, false, true, (bits <= 16) ? 2 * bits : bits); + sm_config_set_fifo_join(&sm_config, PIO_FIFO_JOIN_TX); + + pio_sm_init(pio, sm, offset, &sm_config); + + uint pin_mask = (1u << data_pin) | (3u << clock_pin_base); + pio_sm_set_pindirs_with_mask(pio, sm, pin_mask, pin_mask); + pio_sm_set_pins(pio, sm, 0); // clear pins + + pio_sm_exec(pio, sm, pio_encode_set(pio_y, bits - 2)); +} + +static inline void pio_lsbj_out_program_init(PIO pio, uint sm, uint offset, uint data_pin, uint clock_pin_base, uint bits, bool swap) { + pio_gpio_init(pio, data_pin); + pio_gpio_init(pio, clock_pin_base); + pio_gpio_init(pio, clock_pin_base + 1); + + pio_sm_config sm_config = swap ? pio_lsbj_out_swap_program_get_default_config(offset) : pio_lsbj_out_program_get_default_config(offset); + sm_config_set_out_pins(&sm_config, data_pin, 1); sm_config_set_sideset_pins(&sm_config, clock_pin_base); sm_config_set_out_shift(&sm_config, false, true, (bits <= 16) ? 2 * bits : bits); @@ -88,12 +199,12 @@ static inline void pio_i2s_out_program_init(PIO pio, uint sm, uint offset, uint pio_sm_exec(pio, sm, pio_encode_set(pio_y, bits - 2)); } -static inline void pio_i2s_in_program_init(PIO pio, uint sm, uint offset, uint data_pin, uint clock_pin_base, uint bits) { +static inline void pio_i2s_in_program_init(PIO pio, uint sm, uint offset, uint data_pin, uint clock_pin_base, uint bits, bool swap) { pio_gpio_init(pio, data_pin); pio_gpio_init(pio, clock_pin_base); pio_gpio_init(pio, clock_pin_base + 1); - pio_sm_config sm_config = pio_i2s_in_program_get_default_config(offset); + pio_sm_config sm_config = swap ? pio_i2s_in_swap_program_get_default_config(offset) : pio_i2s_in_program_get_default_config(offset); sm_config_set_in_pins(&sm_config, data_pin); sm_config_set_sideset_pins(&sm_config, clock_pin_base); diff --git a/libraries/I2S/src/pio_i2s.pio.h b/libraries/I2S/src/pio_i2s.pio.h index e9a16fad9..c094e5f56 100644 --- a/libraries/I2S/src/pio_i2s.pio.h +++ b/libraries/I2S/src/pio_i2s.pio.h @@ -43,6 +43,111 @@ static inline pio_sm_config pio_i2s_out_program_get_default_config(uint offset) } #endif +// ---------------- // +// pio_i2s_out_swap // +// ---------------- // + +#define pio_i2s_out_swap_wrap_target 0 +#define pio_i2s_out_swap_wrap 7 + +static const uint16_t pio_i2s_out_swap_program_instructions[] = { + // .wrap_target + 0xb022, // 0: mov x, y side 2 + 0x6001, // 1: out pins, 1 side 0 + 0x1041, // 2: jmp x--, 1 side 2 + 0x6801, // 3: out pins, 1 side 1 + 0xb822, // 4: mov x, y side 3 + 0x6801, // 5: out pins, 1 side 1 + 0x1845, // 6: jmp x--, 5 side 3 + 0x6001, // 7: out pins, 1 side 0 + // .wrap +}; + +#if !PICO_NO_HARDWARE +static const struct pio_program pio_i2s_out_swap_program = { + .instructions = pio_i2s_out_swap_program_instructions, + .length = 8, + .origin = -1, +}; + +static inline pio_sm_config pio_i2s_out_swap_program_get_default_config(uint offset) { + pio_sm_config c = pio_get_default_sm_config(); + sm_config_set_wrap(&c, offset + pio_i2s_out_swap_wrap_target, offset + pio_i2s_out_swap_wrap); + sm_config_set_sideset(&c, 2, false, false); + return c; +} +#endif + +// ------------ // +// pio_lsbj_out // +// ------------ // + +#define pio_lsbj_out_wrap_target 0 +#define pio_lsbj_out_wrap 7 + +static const uint16_t pio_lsbj_out_program_instructions[] = { + // .wrap_target + 0xa822, // 0: mov x, y side 1 + 0x7001, // 1: out pins, 1 side 2 + 0x1841, // 2: jmp x--, 1 side 3 + 0x7001, // 3: out pins, 1 side 2 + 0xb822, // 4: mov x, y side 3 + 0x6001, // 5: out pins, 1 side 0 + 0x0845, // 6: jmp x--, 5 side 1 + 0x6001, // 7: out pins, 1 side 0 + // .wrap +}; + +#if !PICO_NO_HARDWARE +static const struct pio_program pio_lsbj_out_program = { + .instructions = pio_lsbj_out_program_instructions, + .length = 8, + .origin = -1, +}; + +static inline pio_sm_config pio_lsbj_out_program_get_default_config(uint offset) { + pio_sm_config c = pio_get_default_sm_config(); + sm_config_set_wrap(&c, offset + pio_lsbj_out_wrap_target, offset + pio_lsbj_out_wrap); + sm_config_set_sideset(&c, 2, false, false); + return c; +} +#endif + +// ----------------- // +// pio_lsbj_out_swap // +// ----------------- // + +#define pio_lsbj_out_swap_wrap_target 0 +#define pio_lsbj_out_swap_wrap 7 + +static const uint16_t pio_lsbj_out_swap_program_instructions[] = { + // .wrap_target + 0xb022, // 0: mov x, y side 2 + 0x6801, // 1: out pins, 1 side 1 + 0x1841, // 2: jmp x--, 1 side 3 + 0x6801, // 3: out pins, 1 side 1 + 0xb822, // 4: mov x, y side 3 + 0x6001, // 5: out pins, 1 side 0 + 0x1045, // 6: jmp x--, 5 side 2 + 0x6001, // 7: out pins, 1 side 0 + // .wrap +}; + +#if !PICO_NO_HARDWARE +static const struct pio_program pio_lsbj_out_swap_program = { + .instructions = pio_lsbj_out_swap_program_instructions, + .length = 8, + .origin = -1, +}; + +static inline pio_sm_config pio_lsbj_out_swap_program_get_default_config(uint offset) { + pio_sm_config c = pio_get_default_sm_config(); + sm_config_set_wrap(&c, offset + pio_lsbj_out_swap_wrap_target, offset + pio_lsbj_out_swap_wrap); + sm_config_set_sideset(&c, 2, false, false); + return c; +} +#endif + // ---------- // // pio_i2s_in // // ---------- // @@ -76,12 +181,62 @@ static inline pio_sm_config pio_i2s_in_program_get_default_config(uint offset) { sm_config_set_sideset(&c, 2, false, false); return c; } +#endif + +// --------------- // +// pio_i2s_in_swap // +// --------------- // + +#define pio_i2s_in_swap_wrap_target 0 +#define pio_i2s_in_swap_wrap 7 + +static const uint16_t pio_i2s_in_swap_program_instructions[] = { + // .wrap_target + 0xa022, // 0: mov x, y side 0 + 0x5001, // 1: in pins, 1 side 2 + 0x0041, // 2: jmp x--, 1 side 0 + 0x5801, // 3: in pins, 1 side 3 + 0xa822, // 4: mov x, y side 1 + 0x5801, // 5: in pins, 1 side 3 + 0x0845, // 6: jmp x--, 5 side 1 + 0x5001, // 7: in pins, 1 side 2 + // .wrap +}; + +#if !PICO_NO_HARDWARE +static const struct pio_program pio_i2s_in_swap_program = { + .instructions = pio_i2s_in_swap_program_instructions, + .length = 8, + .origin = -1, +}; + +static inline pio_sm_config pio_i2s_in_swap_program_get_default_config(uint offset) { + pio_sm_config c = pio_get_default_sm_config(); + sm_config_set_wrap(&c, offset + pio_i2s_in_swap_wrap_target, offset + pio_i2s_in_swap_wrap); + sm_config_set_sideset(&c, 2, false, false); + return c; +} -static inline void pio_i2s_out_program_init(PIO pio, uint sm, uint offset, uint data_pin, uint clock_pin_base, uint bits) { +static inline void pio_i2s_out_program_init(PIO pio, uint sm, uint offset, uint data_pin, uint clock_pin_base, uint bits, bool swap) { + pio_gpio_init(pio, data_pin); + pio_gpio_init(pio, clock_pin_base); + pio_gpio_init(pio, clock_pin_base + 1); + pio_sm_config sm_config = swap ? pio_i2s_out_swap_program_get_default_config(offset) : pio_i2s_out_program_get_default_config(offset); + sm_config_set_out_pins(&sm_config, data_pin, 1); + sm_config_set_sideset_pins(&sm_config, clock_pin_base); + sm_config_set_out_shift(&sm_config, false, true, (bits <= 16) ? 2 * bits : bits); + sm_config_set_fifo_join(&sm_config, PIO_FIFO_JOIN_TX); + pio_sm_init(pio, sm, offset, &sm_config); + uint pin_mask = (1u << data_pin) | (3u << clock_pin_base); + pio_sm_set_pindirs_with_mask(pio, sm, pin_mask, pin_mask); + pio_sm_set_pins(pio, sm, 0); // clear pins + pio_sm_exec(pio, sm, pio_encode_set(pio_y, bits - 2)); +} +static inline void pio_lsbj_out_program_init(PIO pio, uint sm, uint offset, uint data_pin, uint clock_pin_base, uint bits, bool swap) { pio_gpio_init(pio, data_pin); pio_gpio_init(pio, clock_pin_base); pio_gpio_init(pio, clock_pin_base + 1); - pio_sm_config sm_config = pio_i2s_out_program_get_default_config(offset); + pio_sm_config sm_config = swap ? pio_lsbj_out_swap_program_get_default_config(offset) : pio_lsbj_out_program_get_default_config(offset); sm_config_set_out_pins(&sm_config, data_pin, 1); sm_config_set_sideset_pins(&sm_config, clock_pin_base); sm_config_set_out_shift(&sm_config, false, true, (bits <= 16) ? 2 * bits : bits); @@ -92,11 +247,11 @@ static inline void pio_i2s_out_program_init(PIO pio, uint sm, uint offset, uint pio_sm_set_pins(pio, sm, 0); // clear pins pio_sm_exec(pio, sm, pio_encode_set(pio_y, bits - 2)); } -static inline void pio_i2s_in_program_init(PIO pio, uint sm, uint offset, uint data_pin, uint clock_pin_base, uint bits) { +static inline void pio_i2s_in_program_init(PIO pio, uint sm, uint offset, uint data_pin, uint clock_pin_base, uint bits, bool swap) { pio_gpio_init(pio, data_pin); pio_gpio_init(pio, clock_pin_base); pio_gpio_init(pio, clock_pin_base + 1); - pio_sm_config sm_config = pio_i2s_in_program_get_default_config(offset); + pio_sm_config sm_config = swap ? pio_i2s_in_swap_program_get_default_config(offset) : pio_i2s_in_program_get_default_config(offset); sm_config_set_in_pins(&sm_config, data_pin); sm_config_set_sideset_pins(&sm_config, clock_pin_base); sm_config_set_in_shift(&sm_config, false, true, (bits <= 16) ? 2 * bits : bits); diff --git a/libraries/Joystick b/libraries/Joystick index af745f3e6..4eb3e28dc 160000 --- a/libraries/Joystick +++ b/libraries/Joystick @@ -1 +1 @@ -Subproject commit af745f3e62377de71b7708b15f263dab8773e0c5 +Subproject commit 4eb3e28dc20d44afe676a6c7e0e6264e29f82abb diff --git a/libraries/JoystickBLE/README.adoc b/libraries/JoystickBLE/README.adoc new file mode 100644 index 000000000..111014198 --- /dev/null +++ b/libraries/JoystickBLE/README.adoc @@ -0,0 +1,34 @@ +:repository-owner: arduino-libraries +:repository-name: Joystick + += {repository-name} Library for Arduino (RP2040 based boards) = + +This library allows an RaspberryPi RP2040 board to act as a Joystick when +Earle F. Philhower`s [arduino-pico](https://github.com/earlephilhower/arduino-pico) +Core is used. + +It was forked from the original upstream USB Joystick library by Benjamin Aigner + +== Acknowledgements / Credits == + +* [arduino-pico](https://github.com/earlephilhower/arduino-pico) Earle F. Philhower providing the Arduino Core, on which this library is based on, available under LGPL. +* [tinyUSB] (https://github.com/hathach/tinyusb) Ha Thach for providing tinyUSB under MIT license, which covers most of the USB functionality. + + +== License == + +Copyright (c) Benjamin Aigner All right reserved. + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA diff --git a/libraries/JoystickBLE/docs/api.md b/libraries/JoystickBLE/docs/api.md new file mode 100644 index 000000000..bbf7dcab9 --- /dev/null +++ b/libraries/JoystickBLE/docs/api.md @@ -0,0 +1,435 @@ +# Joystick library + +## Methods + +### `Joystick.begin()` + +Must be called before starting using the Joystick emulation. To end control, use `Joystick.end()`. + +#### Syntax + +``` +Joystick.begin() +``` + +#### Parameters + +None. + +#### Returns + +None. + +#### Example + +``` +#include + +void setup() { + pinMode(2, INPUT_PULLUP); +} + +void loop() { + // Initialize the Joystick library when button is pressed + if (digitalRead(2) == LOW) { + Joystick.begin(); + } +} +``` + +#### See also + + +* [Joystick.button()](#joystickbutton) +* [Joystick.end()](#joystickend) +* [Joystick.send_now()](#joysticksend_now) +* [Joystick.position()](#joystickposition) +* [Joystick.X()](#joystickx) +* [Joystick.hat()](#joystickhat) +* [Joystick.use8bit()](#joystickuse8bit) +* [Joystick.useManualSend()](#joystickuseManualSend) + +### `Joystick.button()` + +Updates a button of the USB joystick. + +#### Syntax + +``` +Joystick.button(1,true); +delay(250); +Joystick.button(1,false); +``` + +#### Parameters + +* `button`: number of Joystick button, which status should be changed +* `val`: state of button, `true` for pressed, `false` for released + +#### Returns + +None. + +#### Example + +``` +#include + +void setup() { + pinMode(2, INPUT_PULLUP); + Joystick.begin(); +} + +void loop() { + uint8_t i = 1; //counter for the button number 1-32 + if (digitalRead(2) == LOW) { //if button is pressed + Joystick.button(i,true); //"press" the Joystick button + delay(250); //wait for 0.25s + Joystick.button(i,false); //"release" the Joystick button + i = i + 1; //increment & use next Joystick button number + if(i > 32) i = 1; //we have 32 buttons available, wrap-around + } +} +``` + +#### Notes + +* Up to 32 buttons are available, numbered as button 1 to button 32. +* If manual_send is active, call `Joystick.send_now()` to send an update to the host. + +#### See also + +* [Joystick.send_now()](#joysticksend_now) +* [Joystick.useManualSend()](#joystickuseManualSend) +* [Joystick.X()](#joystickx) +* [Joystick.hat()](#joystickhat) + + +### `Joystick.end()` + +Stops emulating the Joystick connected to a computer. To start control, use `Joystick.begin()`. + +#### Syntax + +``` +Joystick.end() +``` + +#### Parameters + +None. + +#### Returns + +None. + +#### Example + +``` +#include + +void setup() { + pinMode(2, INPUT_PULLUP); + // Initiate the Joystick library + Joystick.begin(); +} + +void loop() { + // If the button is pressed, send a button 1 press / release + if (digitalRead(2) == LOW) { + Joystick.button(1,true); + delay(250); + Joystick.button(1,false); + // Then end the Joystick emulation + Joystick.end(); + } +} +``` + +#### See also + +* [Joystick.begin()](#joystickbegin) + +### `Joystick.use8bit()` + +Switch axis value range between 10bit and 8bit. +* Default: 10bit, range for an axis from 0 to 1023 +* 8bit mode: range from -127 to 127. + +__Note:__ due to the gamepad descriptor of tinyUSB, the maximum range is -127/127. 10bit mode enables mapping, not a higher resolution. + + +#### Syntax + +``` +Joystick.use8bit(true) +``` + +#### Parameters + +* `mode`: true, if values from -127/127 are used. False to use a range from 0 to 1023. + +#### Returns + +None. + +#### Example + +``` +#include + +void setup() { + pinMode(2, INPUT_PULLUP); + Joystick.begin(); +} + +void loop() { + //send middle position in default 10bit mode + Joystick.position(512,512); + delay(250); + //enable 8bit mode + Joystick.use8bit(true); + //send middle position in 8bit mode + Joystick.position(0,0); + delay(250); + + //send maximum left in 10bit mode + Joystick.use8bit(false); + Joystick.position(0,0); + delay(250); + //enable 8bit mode + Joystick.use8bit(true); + //send left position in 8bit mode + Joystick.position(-127,-127); +} +``` + +#### See also + +* [Joystick.position()](#joystickposition) +* [Joystick.X()](#joystickx) +* [Joystick.Y()](#joysticky) +* [Joystick.Z()](#joystickz) +* [Joystick.Zrotate()](#joystickrotate) +* [Joystick.slider()](#joystickslider) +* [Joystick.sliderLeft()](#joysticksliderleft) +* [Joystick.sliderRight()](#joysticksliderright) + + +### `Joystick.useManualSend()` + +To fully control transmitting the USB-HID reports, enable manual sending. +If disabled, each call to a function updating the Joystick status (buttons, all axis, hat) +will send a HID report. If you update in a loop, the time between updates (at least 1ms) is too short and something might be not transmitted correctly. +If enabled, update all your axis values, buttons, hat and then send one report via `Joystick.send_now()`. + +#### Syntax + +``` +Joystick.useManualSend(true) +``` + +#### Parameters + +* `mode`: false is sending report each Joystick update, true enables manual sending via send_now(). + +#### Returns + +None. + +#### Example + +``` +#include + +void setup() { + pinMode(2, INPUT_PULLUP); + Joystick.begin(); +} + +void loop() { + if (digitalRead(2) == LOW) { + // send data in 4 different reports + Joystick.button(1,true); + Joystick.button(2,true); + Joystick.button(3,true); + Joystick.button(4,true); + + //enable manual send + Joystick.useManualSend(true); + + //send same data in one report + Joystick.button(1,false); + Joystick.button(2,false); + Joystick.button(3,false); + Joystick.button(4,false); + Joystick.send_now(); + } +} +``` + +#### See also + +* [Joystick.send_now()](#joysticksend_now) + + + +### `Joystick.send_now()` + +Send a HID report now. Used together with manual sending, see `Joystick.useManualSend()`. + +#### Syntax + +``` +Joystick.send_now() +``` + +#### Parameters + +None. + +#### Returns + +None. + +#### Example + +``` +#include + +void setup() { + pinMode(2, INPUT_PULLUP); + Joystick.begin(); + //enable manual sending in setup + Joystick.useManualSend(true); +} + +void loop() { + if (digitalRead(2) == LOW) { + // update all buttons, but nothing is sent to the host + for(uint8_t i = 1; i<=32; i++) Joystick.button(i,true); + Joystick.X(256); + Joystick.sliderLeft(0); + + //now send in one HID report + Joystick.send_now(); + } +} +``` + +#### See also + +* [Joystick.useManualSend()](#joystickusemanualsend) + + +### `Joystick.X()` + +Update X axis. +__Note:__ If [manual send](#joystickusemanualsend) is active, the value is sent to the host only after calling [send_now](#joysticksend_now). +__Note:__ If in 10bit mode (default), the parameter is interpreted from 0 to 1023. +In 8bit mode from -127 to 127. The internal resolution is always 8bit. Change setting with [use8bit](#joystickuse8bit). + +#### Syntax + +``` +Joystick.X(0) +``` + +#### Parameters + +* `val`: value from 0 to 1023 (default) or -127 to 127 (8bit mode) + +#### Returns + +None. + +#### Example + +``` +#include + +void setup() { + pinMode(2, INPUT_PULLUP); + Joystick.begin(); +} + +void loop() { + if (digitalRead(2) == LOW) { + Joystick.X(256); + delay(500); + Joystick.X(512); + } +} +``` + +#### See also + +* [Joystick.Y()](#joysticky) +* [Joystick.Z()](#joystickz) +* [Joystick.Zrotate()](#joystickrotate) +* [Joystick.slider()](#joystickslider) +* [Joystick.sliderLeft()](#joysticksliderleft) +* [Joystick.sliderRight()](#joysticksliderright) +* [Joystick.send_now()](#joysticksend_now) +* [Joystick.position()](#joystickposition) +* [Joystick.hat()](#joystickhat) +* [Joystick.use8bit()](#joystickuse8bit) +* [Joystick.useManualSend()](#joystickuseManualSend) + +### `Joystick.Y()` + +Update Y axis. Please refer to [Joystick.X()](#joystickx). + +### `Joystick.Z()` + +Update Z axis. Please refer to [Joystick.X()](#joystickx). + +### `Joystick.Zrotate()` + +Update Z rotate axis. Please refer to [Joystick.X()](#joystickx). + +### `Joystick.sliderLeft()` + +Left slider value. Please refer to [Joystick.X()](#joystickx). + +### `Joystick.sliderRight()` + +Right slider value. Please refer to [Joystick.X()](#joystickx). + +### `Joystick.slider()` + +Same as [Joystick.sliderLeft()](#joysticksliderleft). + +### `Joystick.position()` + +Sets X and Y axis in one call. If autosending is active, one report is generated. Please refer to [Joystick.X()](#joystickx). + +#### Syntax + +``` +Joystick.position(512,512) +``` + +#### Parameters + +* `X`: value from 0 to 1023 (default) or -127 to 127 (8bit mode); for X axis +* `Y`: value from 0 to 1023 (default) or -127 to 127 (8bit mode); for Y axis + +#### See also + +* [Joystick.X()](#joystickx) +* [Joystick.Y()](#joysticky) + +### `Joystick.hat()` + +Set the hat value to selection angle or rest position. + +#### Syntax + +``` +Joystick.hat(-1), // released/rest position +``` + +#### Parameters + +* `angle` Angle value from 0-360 degrees or -1 for released resting position. Mapped to 8 different directions. diff --git a/libraries/JoystickBLE/docs/readme.md b/libraries/JoystickBLE/docs/readme.md new file mode 100644 index 000000000..4bec23450 --- /dev/null +++ b/libraries/JoystickBLE/docs/readme.md @@ -0,0 +1,14 @@ +# Joystick library + +The Joystick functions enable a RP2040 board to act as a HID game controller. + +To use this library: + +``` +#include +``` + + +## Examples + +* [Joystick-AllFunctions] Includes example calls for each Joystick function diff --git a/libraries/JoystickBLE/examples/BLEJoystick-AllFunctions/BLEJoystick-AllFunctions.ino b/libraries/JoystickBLE/examples/BLEJoystick-AllFunctions/BLEJoystick-AllFunctions.ino new file mode 100644 index 000000000..06807d83f --- /dev/null +++ b/libraries/JoystickBLE/examples/BLEJoystick-AllFunctions/BLEJoystick-AllFunctions.ino @@ -0,0 +1,110 @@ +/* Benjamin Aigner, 2022 */ +/* Public domain / CC 0 */ + +/** example code using all possibilities of the Joystick class + for the RP2040. +*/ + +#include + +void setup() { + Serial.begin(115200); + Serial.println("Use BOOTSEL to start the Joystick demo."); + JoystickBLE.begin(); +} + +void loop() { + if (BOOTSEL) { + Serial.println("Joystick buttons"); + for (uint8_t i = 1; i <= 32; i++) { + JoystickBLE.button(i, true); + delay(250); + JoystickBLE.button(i, false); + delay(10); //we need a short delay here, sending packets with less than 1ms leads to packet loss! + } + //alternativ with manual send: + JoystickBLE.useManualSend(true); + Serial.println("Joystick buttons - manual send"); + for (uint8_t i = 1; i <= 32; i++) { + JoystickBLE.button(i, true); + JoystickBLE.send_now(); + delay(250); + JoystickBLE.button(i, false); + } + JoystickBLE.useManualSend(false); + + //iterate all joystick axis + //Note: although you can use 0-1023 here (10bit), internally 8bits are used (-127 to 127) + Serial.println("Joystick X"); + for (uint16_t i = 0; i < 1023; i++) { + JoystickBLE.X(i); + delay(2); + } JoystickBLE.X(512); + Serial.println("Joystick Y"); + for (uint16_t i = 0; i < 1023; i++) { + JoystickBLE.Y(i); + delay(2); + } JoystickBLE.Y(512); + Serial.println("Joystick Z"); + for (uint16_t i = 0; i < 1023; i++) { + JoystickBLE.Z(i); + delay(2); + } JoystickBLE.Z(512); + Serial.println("Joystick Zrotate"); + for (uint16_t i = 0; i < 1023; i++) { + JoystickBLE.Zrotate(i); + delay(2); + } JoystickBLE.Zrotate(512); + Serial.println("Joystick sliderLeft"); + for (uint16_t i = 0; i < 1023; i++) { + JoystickBLE.sliderLeft(i); + delay(2); + } JoystickBLE.sliderLeft(0); + Serial.println("Joystick sliderRight"); + for (uint16_t i = 0; i < 1023; i++) { + JoystickBLE.sliderRight(i); + delay(2); + } JoystickBLE.sliderRight(0); + Serial.println("Joystick hat"); + for (uint16_t i = 0; i < 360; i++) { + JoystickBLE.hat(i); + delay(20); + } JoystickBLE.hat(-1); + + //use int8 mode for the axis. + //Note: hat is not used differently. + Serial.println("Now all axis in 8bit mode, -127 to 127"); + JoystickBLE.use8bit(true); + Serial.println("Joystick X"); + for (int16_t i = -127; i < 128; i++) { + JoystickBLE.X(i); + delay(2); + } JoystickBLE.X(0); + Serial.println("Joystick Y"); + for (int16_t i = -127; i < 128; i++) { + JoystickBLE.Y(i); + delay(2); + } JoystickBLE.Y(0); + Serial.println("Joystick Z"); + for (int16_t i = -127; i < 128; i++) { + JoystickBLE.Z(i); + delay(2); + } JoystickBLE.Z(0); + Serial.println("Joystick Zrotate"); + for (int16_t i = -127; i < 128; i++) { + JoystickBLE.Zrotate(i); + delay(2); + } JoystickBLE.Zrotate(0); + Serial.println("Joystick sliderLeft"); + for (int16_t i = -127; i < 128; i++) { + JoystickBLE.sliderLeft(i); + delay(2); + } JoystickBLE.sliderLeft(0); + Serial.println("Joystick sliderRight"); + for (int16_t i = -127; i < 128; i++) { + JoystickBLE.sliderRight(i); + delay(2); + } JoystickBLE.sliderRight(0); + JoystickBLE.use8bit(false); + } +} diff --git a/libraries/JoystickBLE/keywords.txt b/libraries/JoystickBLE/keywords.txt new file mode 100644 index 000000000..60f7dcccf --- /dev/null +++ b/libraries/JoystickBLE/keywords.txt @@ -0,0 +1,34 @@ +####################################### +# Syntax Coloring Map +####################################### + +####################################### +# Datatypes (KEYWORD1) +####################################### + +JoystickBLE KEYWORD1 + +####################################### +# Methods and Functions (KEYWORD2) +####################################### + +begin KEYWORD2 +end KEYWORD2 +use8bit KEYWORD2 +X KEYWORD2 +Y KEYWORD2 +button KEYWORD2 +position KEYWORD2 +Z KEYWORD2 +Zrotate KEYWORD2 +sliderLeft KEYWORD2 +slider KEYWORD2 +sliderRight KEYWORD2 +hat KEYWORD2 +useManualSend KEYWORD2 +send_now KEYWORD2 +setBattery KEYWORD2 + +####################################### +# Constants (LITERAL1) +####################################### diff --git a/libraries/JoystickBLE/library.properties b/libraries/JoystickBLE/library.properties new file mode 100644 index 000000000..7d308cf4f --- /dev/null +++ b/libraries/JoystickBLE/library.properties @@ -0,0 +1,9 @@ +name=JoystickBLE +version=1.0.1 +author=Benjamin Aigner +maintainer=Earle F. Philhower, III +sentence=Allows any PicoW board to act as a BLE joystick/gamepad +paragraph=Allows any PicoW board to act as a BLE joystick/gamepad +category=Device Control +url=https://github.com/earlephilhower/arduino-pico +architectures=rp2040 diff --git a/libraries/JoystickBLE/src/JoystickBLE.cpp b/libraries/JoystickBLE/src/JoystickBLE.cpp new file mode 100644 index 000000000..356227fad --- /dev/null +++ b/libraries/JoystickBLE/src/JoystickBLE.cpp @@ -0,0 +1,63 @@ +/* + JoystickBLE.cpp + + Copyright (c) 2022, Benjamin Aigner + Modified for BLE 2023 by Earle F. Philhower, III + + Implementation loosely based on: + Mouse library from https://github.com/earlephilhower/arduino-pico + Joystick functions from Teensyduino https://github.com/PaulStoffregen + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include "JoystickBLE.h" +#include +#include + +//================================================================================ +//================================================================================ +// Joystick/Gamepad + +JoystickBLE_::JoystickBLE_(void) { + // Member vars set in base constructor +} + +#define REPORT_ID 0x01 +static const uint8_t desc_joystick[] = {TUD_HID_REPORT_DESC_GAMEPAD(HID_REPORT_ID(REPORT_ID))}; + +void JoystickBLE_::begin(const char *localName, const char *hidName) { + if (!localName) { + localName = "PicoW BLE Joystick"; + } + if (!hidName) { + hidName = localName; + } + PicoBluetoothBLEHID.startHID(localName, hidName, 0x03c4, desc_joystick, sizeof(desc_joystick)); +} + +void JoystickBLE_::end() { + PicoBluetoothBLEHID.end(); +} + +void JoystickBLE_::setBattery(int lvl) { + PicoBluetoothBLEHID.setBattery(lvl); +} + +void JoystickBLE_::send_now() { + PicoBluetoothBLEHID.send(&data, sizeof(data)); +} + +JoystickBLE_ JoystickBLE; diff --git a/libraries/JoystickBLE/src/JoystickBLE.h b/libraries/JoystickBLE/src/JoystickBLE.h new file mode 100644 index 000000000..a491f96e0 --- /dev/null +++ b/libraries/JoystickBLE/src/JoystickBLE.h @@ -0,0 +1,36 @@ +/* + JoystickBLE.h + + Copyright (c) 2022, Benjamin Aigner + Modified for BT 2023 by Earle F. Philhower, III + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#pragma once + +#include +#include "class/hid/hid.h" + +//====================================================================== +class JoystickBLE_ : public HID_Joystick { +public: + JoystickBLE_(); + void begin(const char *localName = nullptr, const char *hidName = nullptr); + void end(); + virtual void send_now() override; + void setBattery(int lvl); +}; +extern JoystickBLE_ JoystickBLE; diff --git a/libraries/JoystickBT/README.adoc b/libraries/JoystickBT/README.adoc new file mode 100644 index 000000000..111014198 --- /dev/null +++ b/libraries/JoystickBT/README.adoc @@ -0,0 +1,34 @@ +:repository-owner: arduino-libraries +:repository-name: Joystick + += {repository-name} Library for Arduino (RP2040 based boards) = + +This library allows an RaspberryPi RP2040 board to act as a Joystick when +Earle F. Philhower`s [arduino-pico](https://github.com/earlephilhower/arduino-pico) +Core is used. + +It was forked from the original upstream USB Joystick library by Benjamin Aigner + +== Acknowledgements / Credits == + +* [arduino-pico](https://github.com/earlephilhower/arduino-pico) Earle F. Philhower providing the Arduino Core, on which this library is based on, available under LGPL. +* [tinyUSB] (https://github.com/hathach/tinyusb) Ha Thach for providing tinyUSB under MIT license, which covers most of the USB functionality. + + +== License == + +Copyright (c) Benjamin Aigner All right reserved. + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA diff --git a/libraries/JoystickBT/docs/api.md b/libraries/JoystickBT/docs/api.md new file mode 100644 index 000000000..bbf7dcab9 --- /dev/null +++ b/libraries/JoystickBT/docs/api.md @@ -0,0 +1,435 @@ +# Joystick library + +## Methods + +### `Joystick.begin()` + +Must be called before starting using the Joystick emulation. To end control, use `Joystick.end()`. + +#### Syntax + +``` +Joystick.begin() +``` + +#### Parameters + +None. + +#### Returns + +None. + +#### Example + +``` +#include + +void setup() { + pinMode(2, INPUT_PULLUP); +} + +void loop() { + // Initialize the Joystick library when button is pressed + if (digitalRead(2) == LOW) { + Joystick.begin(); + } +} +``` + +#### See also + + +* [Joystick.button()](#joystickbutton) +* [Joystick.end()](#joystickend) +* [Joystick.send_now()](#joysticksend_now) +* [Joystick.position()](#joystickposition) +* [Joystick.X()](#joystickx) +* [Joystick.hat()](#joystickhat) +* [Joystick.use8bit()](#joystickuse8bit) +* [Joystick.useManualSend()](#joystickuseManualSend) + +### `Joystick.button()` + +Updates a button of the USB joystick. + +#### Syntax + +``` +Joystick.button(1,true); +delay(250); +Joystick.button(1,false); +``` + +#### Parameters + +* `button`: number of Joystick button, which status should be changed +* `val`: state of button, `true` for pressed, `false` for released + +#### Returns + +None. + +#### Example + +``` +#include + +void setup() { + pinMode(2, INPUT_PULLUP); + Joystick.begin(); +} + +void loop() { + uint8_t i = 1; //counter for the button number 1-32 + if (digitalRead(2) == LOW) { //if button is pressed + Joystick.button(i,true); //"press" the Joystick button + delay(250); //wait for 0.25s + Joystick.button(i,false); //"release" the Joystick button + i = i + 1; //increment & use next Joystick button number + if(i > 32) i = 1; //we have 32 buttons available, wrap-around + } +} +``` + +#### Notes + +* Up to 32 buttons are available, numbered as button 1 to button 32. +* If manual_send is active, call `Joystick.send_now()` to send an update to the host. + +#### See also + +* [Joystick.send_now()](#joysticksend_now) +* [Joystick.useManualSend()](#joystickuseManualSend) +* [Joystick.X()](#joystickx) +* [Joystick.hat()](#joystickhat) + + +### `Joystick.end()` + +Stops emulating the Joystick connected to a computer. To start control, use `Joystick.begin()`. + +#### Syntax + +``` +Joystick.end() +``` + +#### Parameters + +None. + +#### Returns + +None. + +#### Example + +``` +#include + +void setup() { + pinMode(2, INPUT_PULLUP); + // Initiate the Joystick library + Joystick.begin(); +} + +void loop() { + // If the button is pressed, send a button 1 press / release + if (digitalRead(2) == LOW) { + Joystick.button(1,true); + delay(250); + Joystick.button(1,false); + // Then end the Joystick emulation + Joystick.end(); + } +} +``` + +#### See also + +* [Joystick.begin()](#joystickbegin) + +### `Joystick.use8bit()` + +Switch axis value range between 10bit and 8bit. +* Default: 10bit, range for an axis from 0 to 1023 +* 8bit mode: range from -127 to 127. + +__Note:__ due to the gamepad descriptor of tinyUSB, the maximum range is -127/127. 10bit mode enables mapping, not a higher resolution. + + +#### Syntax + +``` +Joystick.use8bit(true) +``` + +#### Parameters + +* `mode`: true, if values from -127/127 are used. False to use a range from 0 to 1023. + +#### Returns + +None. + +#### Example + +``` +#include + +void setup() { + pinMode(2, INPUT_PULLUP); + Joystick.begin(); +} + +void loop() { + //send middle position in default 10bit mode + Joystick.position(512,512); + delay(250); + //enable 8bit mode + Joystick.use8bit(true); + //send middle position in 8bit mode + Joystick.position(0,0); + delay(250); + + //send maximum left in 10bit mode + Joystick.use8bit(false); + Joystick.position(0,0); + delay(250); + //enable 8bit mode + Joystick.use8bit(true); + //send left position in 8bit mode + Joystick.position(-127,-127); +} +``` + +#### See also + +* [Joystick.position()](#joystickposition) +* [Joystick.X()](#joystickx) +* [Joystick.Y()](#joysticky) +* [Joystick.Z()](#joystickz) +* [Joystick.Zrotate()](#joystickrotate) +* [Joystick.slider()](#joystickslider) +* [Joystick.sliderLeft()](#joysticksliderleft) +* [Joystick.sliderRight()](#joysticksliderright) + + +### `Joystick.useManualSend()` + +To fully control transmitting the USB-HID reports, enable manual sending. +If disabled, each call to a function updating the Joystick status (buttons, all axis, hat) +will send a HID report. If you update in a loop, the time between updates (at least 1ms) is too short and something might be not transmitted correctly. +If enabled, update all your axis values, buttons, hat and then send one report via `Joystick.send_now()`. + +#### Syntax + +``` +Joystick.useManualSend(true) +``` + +#### Parameters + +* `mode`: false is sending report each Joystick update, true enables manual sending via send_now(). + +#### Returns + +None. + +#### Example + +``` +#include + +void setup() { + pinMode(2, INPUT_PULLUP); + Joystick.begin(); +} + +void loop() { + if (digitalRead(2) == LOW) { + // send data in 4 different reports + Joystick.button(1,true); + Joystick.button(2,true); + Joystick.button(3,true); + Joystick.button(4,true); + + //enable manual send + Joystick.useManualSend(true); + + //send same data in one report + Joystick.button(1,false); + Joystick.button(2,false); + Joystick.button(3,false); + Joystick.button(4,false); + Joystick.send_now(); + } +} +``` + +#### See also + +* [Joystick.send_now()](#joysticksend_now) + + + +### `Joystick.send_now()` + +Send a HID report now. Used together with manual sending, see `Joystick.useManualSend()`. + +#### Syntax + +``` +Joystick.send_now() +``` + +#### Parameters + +None. + +#### Returns + +None. + +#### Example + +``` +#include + +void setup() { + pinMode(2, INPUT_PULLUP); + Joystick.begin(); + //enable manual sending in setup + Joystick.useManualSend(true); +} + +void loop() { + if (digitalRead(2) == LOW) { + // update all buttons, but nothing is sent to the host + for(uint8_t i = 1; i<=32; i++) Joystick.button(i,true); + Joystick.X(256); + Joystick.sliderLeft(0); + + //now send in one HID report + Joystick.send_now(); + } +} +``` + +#### See also + +* [Joystick.useManualSend()](#joystickusemanualsend) + + +### `Joystick.X()` + +Update X axis. +__Note:__ If [manual send](#joystickusemanualsend) is active, the value is sent to the host only after calling [send_now](#joysticksend_now). +__Note:__ If in 10bit mode (default), the parameter is interpreted from 0 to 1023. +In 8bit mode from -127 to 127. The internal resolution is always 8bit. Change setting with [use8bit](#joystickuse8bit). + +#### Syntax + +``` +Joystick.X(0) +``` + +#### Parameters + +* `val`: value from 0 to 1023 (default) or -127 to 127 (8bit mode) + +#### Returns + +None. + +#### Example + +``` +#include + +void setup() { + pinMode(2, INPUT_PULLUP); + Joystick.begin(); +} + +void loop() { + if (digitalRead(2) == LOW) { + Joystick.X(256); + delay(500); + Joystick.X(512); + } +} +``` + +#### See also + +* [Joystick.Y()](#joysticky) +* [Joystick.Z()](#joystickz) +* [Joystick.Zrotate()](#joystickrotate) +* [Joystick.slider()](#joystickslider) +* [Joystick.sliderLeft()](#joysticksliderleft) +* [Joystick.sliderRight()](#joysticksliderright) +* [Joystick.send_now()](#joysticksend_now) +* [Joystick.position()](#joystickposition) +* [Joystick.hat()](#joystickhat) +* [Joystick.use8bit()](#joystickuse8bit) +* [Joystick.useManualSend()](#joystickuseManualSend) + +### `Joystick.Y()` + +Update Y axis. Please refer to [Joystick.X()](#joystickx). + +### `Joystick.Z()` + +Update Z axis. Please refer to [Joystick.X()](#joystickx). + +### `Joystick.Zrotate()` + +Update Z rotate axis. Please refer to [Joystick.X()](#joystickx). + +### `Joystick.sliderLeft()` + +Left slider value. Please refer to [Joystick.X()](#joystickx). + +### `Joystick.sliderRight()` + +Right slider value. Please refer to [Joystick.X()](#joystickx). + +### `Joystick.slider()` + +Same as [Joystick.sliderLeft()](#joysticksliderleft). + +### `Joystick.position()` + +Sets X and Y axis in one call. If autosending is active, one report is generated. Please refer to [Joystick.X()](#joystickx). + +#### Syntax + +``` +Joystick.position(512,512) +``` + +#### Parameters + +* `X`: value from 0 to 1023 (default) or -127 to 127 (8bit mode); for X axis +* `Y`: value from 0 to 1023 (default) or -127 to 127 (8bit mode); for Y axis + +#### See also + +* [Joystick.X()](#joystickx) +* [Joystick.Y()](#joysticky) + +### `Joystick.hat()` + +Set the hat value to selection angle or rest position. + +#### Syntax + +``` +Joystick.hat(-1), // released/rest position +``` + +#### Parameters + +* `angle` Angle value from 0-360 degrees or -1 for released resting position. Mapped to 8 different directions. diff --git a/libraries/JoystickBT/docs/readme.md b/libraries/JoystickBT/docs/readme.md new file mode 100644 index 000000000..4bec23450 --- /dev/null +++ b/libraries/JoystickBT/docs/readme.md @@ -0,0 +1,14 @@ +# Joystick library + +The Joystick functions enable a RP2040 board to act as a HID game controller. + +To use this library: + +``` +#include +``` + + +## Examples + +* [Joystick-AllFunctions] Includes example calls for each Joystick function diff --git a/libraries/JoystickBT/examples/BTJoystick-AllFunctions/BTJoystick-AllFunctions.ino b/libraries/JoystickBT/examples/BTJoystick-AllFunctions/BTJoystick-AllFunctions.ino new file mode 100644 index 000000000..b32efee85 --- /dev/null +++ b/libraries/JoystickBT/examples/BTJoystick-AllFunctions/BTJoystick-AllFunctions.ino @@ -0,0 +1,110 @@ +/* Benjamin Aigner, 2022 */ +/* Public domain / CC 0 */ + +/** example code using all possibilities of the Joystick class + for the RP2040. +*/ + +#include + +void setup() { + Serial.begin(115200); + Serial.println("Use BOOTSEL to start the Joystick demo."); + JoystickBT.begin("PicoJoy Demo"); +} + +void loop() { + if (BOOTSEL) { + Serial.println("Joystick buttons"); + for (uint8_t i = 1; i <= 32; i++) { + JoystickBT.button(i, true); + delay(250); + JoystickBT.button(i, false); + delay(10); //we need a short delay here, sending packets with less than 1ms leads to packet loss! + } + //alternativ with manual send: + JoystickBT.useManualSend(true); + Serial.println("Joystick buttons - manual send"); + for (uint8_t i = 1; i <= 32; i++) { + JoystickBT.button(i, true); + JoystickBT.send_now(); + delay(250); + JoystickBT.button(i, false); + } + JoystickBT.useManualSend(false); + + //iterate all joystick axis + //Note: although you can use 0-1023 here (10bit), internally 8bits are used (-127 to 127) + Serial.println("Joystick X"); + for (uint16_t i = 0; i < 1023; i++) { + JoystickBT.X(i); + delay(2); + } JoystickBT.X(512); + Serial.println("Joystick Y"); + for (uint16_t i = 0; i < 1023; i++) { + JoystickBT.Y(i); + delay(2); + } JoystickBT.Y(512); + Serial.println("Joystick Z"); + for (uint16_t i = 0; i < 1023; i++) { + JoystickBT.Z(i); + delay(2); + } JoystickBT.Z(512); + Serial.println("Joystick Zrotate"); + for (uint16_t i = 0; i < 1023; i++) { + JoystickBT.Zrotate(i); + delay(2); + } JoystickBT.Zrotate(512); + Serial.println("Joystick sliderLeft"); + for (uint16_t i = 0; i < 1023; i++) { + JoystickBT.sliderLeft(i); + delay(2); + } JoystickBT.sliderLeft(0); + Serial.println("Joystick sliderRight"); + for (uint16_t i = 0; i < 1023; i++) { + JoystickBT.sliderRight(i); + delay(2); + } JoystickBT.sliderRight(0); + Serial.println("Joystick hat"); + for (uint16_t i = 0; i < 360; i++) { + JoystickBT.hat(i); + delay(20); + } JoystickBT.hat(-1); + + //use int8 mode for the axis. + //Note: hat is not used differently. + Serial.println("Now all axis in 8bit mode, -127 to 127"); + JoystickBT.use8bit(true); + Serial.println("Joystick X"); + for (int16_t i = -127; i < 128; i++) { + JoystickBT.X(i); + delay(2); + } JoystickBT.X(0); + Serial.println("Joystick Y"); + for (int16_t i = -127; i < 128; i++) { + JoystickBT.Y(i); + delay(2); + } JoystickBT.Y(0); + Serial.println("Joystick Z"); + for (int16_t i = -127; i < 128; i++) { + JoystickBT.Z(i); + delay(2); + } JoystickBT.Z(0); + Serial.println("Joystick Zrotate"); + for (int16_t i = -127; i < 128; i++) { + JoystickBT.Zrotate(i); + delay(2); + } JoystickBT.Zrotate(0); + Serial.println("Joystick sliderLeft"); + for (int16_t i = -127; i < 128; i++) { + JoystickBT.sliderLeft(i); + delay(2); + } JoystickBT.sliderLeft(0); + Serial.println("Joystick sliderRight"); + for (int16_t i = -127; i < 128; i++) { + JoystickBT.sliderRight(i); + delay(2); + } JoystickBT.sliderRight(0); + JoystickBT.use8bit(false); + } +} diff --git a/libraries/JoystickBT/keywords.txt b/libraries/JoystickBT/keywords.txt new file mode 100644 index 000000000..4f0b6c046 --- /dev/null +++ b/libraries/JoystickBT/keywords.txt @@ -0,0 +1,33 @@ +####################################### +# Syntax Coloring Map +####################################### + +####################################### +# Datatypes (KEYWORD1) +####################################### + +JoystickBT KEYWORD1 + +####################################### +# Methods and Functions (KEYWORD2) +####################################### + +begin KEYWORD2 +end KEYWORD2 +use8bit KEYWORD2 +X KEYWORD2 +Y KEYWORD2 +button KEYWORD2 +position KEYWORD2 +Z KEYWORD2 +Zrotate KEYWORD2 +sliderLeft KEYWORD2 +slider KEYWORD2 +sliderRight KEYWORD2 +hat KEYWORD2 +useManualSend KEYWORD2 +send_now KEYWORD2 + +####################################### +# Constants (LITERAL1) +####################################### diff --git a/libraries/JoystickBT/library.properties b/libraries/JoystickBT/library.properties new file mode 100644 index 000000000..2a9fb6621 --- /dev/null +++ b/libraries/JoystickBT/library.properties @@ -0,0 +1,9 @@ +name=JoystickBT +version=1.0.1 +author=Benjamin Aigner +maintainer=Earle F. Philhower, III +sentence=Allows any PicoW board to act as a BT joystick/gamepad +paragraph=Allows any PicoW board to act as a BT joystick/gamepad +category=Device Control +url=https://github.com/earlephilhower/arduino-pico +architectures=rp2040 diff --git a/libraries/JoystickBT/src/JoystickBT.cpp b/libraries/JoystickBT/src/JoystickBT.cpp new file mode 100644 index 000000000..b7e3aee67 --- /dev/null +++ b/libraries/JoystickBT/src/JoystickBT.cpp @@ -0,0 +1,60 @@ +/* + Joystick.cpp + + Copyright (c) 2022, Benjamin Aigner + Modified for BT 2023 by Earle F. Philhower, III + + Implementation loosely based on: + Mouse library from https://github.com/earlephilhower/arduino-pico + Joystick functions from Teensyduino https://github.com/PaulStoffregen + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include "JoystickBT.h" +#include +#include + +//================================================================================ +//================================================================================ +// Joystick/Gamepad + +JoystickBT_::JoystickBT_() { + // HID_Joystick sets up all the member vars +} + +#define REPORT_ID 0x01 +static const uint8_t desc_joystick[] = {TUD_HID_REPORT_DESC_GAMEPAD(HID_REPORT_ID(REPORT_ID))}; + +void JoystickBT_::begin(const char *localName, const char *hidName) { + if (!localName) { + localName = "PicoW BT Joystick"; + } + if (!hidName) { + hidName = localName; + } + PicoBluetoothHID.startHID(localName, hidName, 0x2508, 33, desc_joystick, sizeof(desc_joystick)); +} + +void JoystickBT_::end() { + PicoBluetoothHID.end(); +} + +//immediately send an HID report +void JoystickBT_::send_now() { + PicoBluetoothHID.send(REPORT_ID, &data, sizeof(data)); +} + +JoystickBT_ JoystickBT; diff --git a/libraries/JoystickBT/src/JoystickBT.h b/libraries/JoystickBT/src/JoystickBT.h new file mode 100644 index 000000000..1af68caf8 --- /dev/null +++ b/libraries/JoystickBT/src/JoystickBT.h @@ -0,0 +1,35 @@ +/* + JoystickBT.h + + Copyright (c) 2022, Benjamin Aigner + Modified for BT 2023 by Earle F. Philhower, III + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#pragma once + +#include +#include "class/hid/hid.h" + +//====================================================================== +class JoystickBT_ : public HID_Joystick { +public: + JoystickBT_(); + void begin(const char *localName = nullptr, const char *hidName = nullptr); + void end(); + virtual void send_now() override; +}; +extern JoystickBT_ JoystickBT; diff --git a/libraries/Keyboard b/libraries/Keyboard index a6498d622..c0f474695 160000 --- a/libraries/Keyboard +++ b/libraries/Keyboard @@ -1 +1 @@ -Subproject commit a6498d6228347ff8337a91b9c1ce934350214dd6 +Subproject commit c0f474695f83d63209fe4ad73ec5d90f27cd9e64 diff --git a/libraries/KeyboardBLE/LICENSE b/libraries/KeyboardBLE/LICENSE new file mode 100644 index 000000000..0a041280b --- /dev/null +++ b/libraries/KeyboardBLE/LICENSE @@ -0,0 +1,165 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + + This version of the GNU Lesser General Public License incorporates +the terms and conditions of version 3 of the GNU General Public +License, supplemented by the additional permissions listed below. + + 0. Additional Definitions. + + As used herein, "this License" refers to version 3 of the GNU Lesser +General Public License, and the "GNU GPL" refers to version 3 of the GNU +General Public License. + + "The Library" refers to a covered work governed by this License, +other than an Application or a Combined Work as defined below. + + An "Application" is any work that makes use of an interface provided +by the Library, but which is not otherwise based on the Library. +Defining a subclass of a class defined by the Library is deemed a mode +of using an interface provided by the Library. + + A "Combined Work" is a work produced by combining or linking an +Application with the Library. The particular version of the Library +with which the Combined Work was made is also called the "Linked +Version". + + The "Minimal Corresponding Source" for a Combined Work means the +Corresponding Source for the Combined Work, excluding any source code +for portions of the Combined Work that, considered in isolation, are +based on the Application, and not on the Linked Version. + + The "Corresponding Application Code" for a Combined Work means the +object code and/or source code for the Application, including any data +and utility programs needed for reproducing the Combined Work from the +Application, but excluding the System Libraries of the Combined Work. + + 1. Exception to Section 3 of the GNU GPL. + + You may convey a covered work under sections 3 and 4 of this License +without being bound by section 3 of the GNU GPL. + + 2. Conveying Modified Versions. + + If you modify a copy of the Library, and, in your modifications, a +facility refers to a function or data to be supplied by an Application +that uses the facility (other than as an argument passed when the +facility is invoked), then you may convey a copy of the modified +version: + + a) under this License, provided that you make a good faith effort to + ensure that, in the event an Application does not supply the + function or data, the facility still operates, and performs + whatever part of its purpose remains meaningful, or + + b) under the GNU GPL, with none of the additional permissions of + this License applicable to that copy. + + 3. Object Code Incorporating Material from Library Header Files. + + The object code form of an Application may incorporate material from +a header file that is part of the Library. You may convey such object +code under terms of your choice, provided that, if the incorporated +material is not limited to numerical parameters, data structure +layouts and accessors, or small macros, inline functions and templates +(ten or fewer lines in length), you do both of the following: + + a) Give prominent notice with each copy of the object code that the + Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the object code with a copy of the GNU GPL and this license + document. + + 4. Combined Works. + + You may convey a Combined Work under terms of your choice that, +taken together, effectively do not restrict modification of the +portions of the Library contained in the Combined Work and reverse +engineering for debugging such modifications, if you also do each of +the following: + + a) Give prominent notice with each copy of the Combined Work that + the Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the Combined Work with a copy of the GNU GPL and this license + document. + + c) For a Combined Work that displays copyright notices during + execution, include the copyright notice for the Library among + these notices, as well as a reference directing the user to the + copies of the GNU GPL and this license document. + + d) Do one of the following: + + 0) Convey the Minimal Corresponding Source under the terms of this + License, and the Corresponding Application Code in a form + suitable for, and under terms that permit, the user to + recombine or relink the Application with a modified version of + the Linked Version to produce a modified Combined Work, in the + manner specified by section 6 of the GNU GPL for conveying + Corresponding Source. + + 1) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (a) uses at run time + a copy of the Library already present on the user's computer + system, and (b) will operate properly with a modified version + of the Library that is interface-compatible with the Linked + Version. + + e) Provide Installation Information, but only if you would otherwise + be required to provide such information under section 6 of the + GNU GPL, and only to the extent that such information is + necessary to install and execute a modified version of the + Combined Work produced by recombining or relinking the + Application with a modified version of the Linked Version. (If + you use option 4d0, the Installation Information must accompany + the Minimal Corresponding Source and Corresponding Application + Code. If you use option 4d1, you must provide the Installation + Information in the manner specified by section 6 of the GNU GPL + for conveying Corresponding Source.) + + 5. Combined Libraries. + + You may place library facilities that are a work based on the +Library side by side in a single library together with other library +facilities that are not Applications and are not covered by this +License, and convey such a combined library under terms of your +choice, if you do both of the following: + + a) Accompany the combined library with a copy of the same work based + on the Library, uncombined with any other library facilities, + conveyed under the terms of this License. + + b) Give prominent notice with the combined library that part of it + is a work based on the Library, and explaining where to find the + accompanying uncombined form of the same work. + + 6. Revised Versions of the GNU Lesser General Public License. + + The Free Software Foundation may publish revised and/or new versions +of the GNU Lesser General Public License from time to time. Such new +versions will be similar in spirit to the present version, but may +differ in detail to address new problems or concerns. + + Each version is given a distinguishing version number. If the +Library as you received it specifies that a certain numbered version +of the GNU Lesser General Public License "or any later version" +applies to it, you have the option of following the terms and +conditions either of that published version or of any later version +published by the Free Software Foundation. If the Library as you +received it does not specify a version number of the GNU Lesser +General Public License, you may choose any version of the GNU Lesser +General Public License ever published by the Free Software Foundation. + + If the Library as you received it specifies that a proxy can decide +whether future versions of the GNU Lesser General Public License shall +apply, that proxy's public statement of acceptance of any version is +permanent authorization for you to choose that version for the +Library. diff --git a/libraries/KeyboardBLE/README.adoc b/libraries/KeyboardBLE/README.adoc new file mode 100644 index 000000000..9b5f9baa2 --- /dev/null +++ b/libraries/KeyboardBLE/README.adoc @@ -0,0 +1,31 @@ +:repository-owner: arduino-libraries +:repository-name: Keyboard + += {repository-name} Library for Arduino = + +image:https://github.com/{repository-owner}/{repository-name}/actions/workflows/check-arduino.yml/badge.svg["Check Arduino status", link="https://github.com/{repository-owner}/{repository-name}/actions/workflows/check-arduino.yml"] +image:https://github.com/{repository-owner}/{repository-name}/actions/workflows/compile-examples.yml/badge.svg["Compile Examples status", link="https://github.com/{repository-owner}/{repository-name}/actions/workflows/compile-examples.yml"] +image:https://github.com/{repository-owner}/{repository-name}/actions/workflows/spell-check.yml/badge.svg["Spell Check status", link="https://github.com/{repository-owner}/{repository-name}/actions/workflows/spell-check.yml"] + +This library allows an Arduino board with USB capabilities to act as a keyboard. + +For more information about this library please visit us at +https://www.arduino.cc/reference/en/language/functions/usb/keyboard/ + +== License == + +Copyright (c) Arduino LLC. All right reserved. + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA diff --git a/libraries/KeyboardBLE/examples/BLEKeyboardPassword/BLEKeyboardPassword.ino b/libraries/KeyboardBLE/examples/BLEKeyboardPassword/BLEKeyboardPassword.ino new file mode 100644 index 000000000..36b2e78f6 --- /dev/null +++ b/libraries/KeyboardBLE/examples/BLEKeyboardPassword/BLEKeyboardPassword.ino @@ -0,0 +1,21 @@ +/* Released into the public domain */ +/* Earle F. Philhower, III */ + +#include + +void setup() { + Serial.begin(115200); + KeyboardBLE.begin(); + delay(5000); + Serial.printf("Arduino USB Password Typer\n"); + Serial.printf("Press BOOTSEL to enter your super-secure(not!) password\n\n"); +} + +void loop() { + if (BOOTSEL) { + Serial.println("Typing password for you...shhhh...."); + KeyboardBLE.print("ThisPasswordIsWeakLikeABaby"); + KeyboardBLE.setBattery(random(0, 101)); // Set between 0...100% + while (BOOTSEL); + } +} diff --git a/libraries/KeyboardBLE/examples/BLESerial/BLESerial.ino b/libraries/KeyboardBLE/examples/BLESerial/BLESerial.ino new file mode 100644 index 000000000..b45c929b3 --- /dev/null +++ b/libraries/KeyboardBLE/examples/BLESerial/BLESerial.ino @@ -0,0 +1,39 @@ +/* + Keyboard test + + For the Arduino Leonardo, Micro or Due + + Reads a byte from the serial port, sends a keystroke back. + The sent keystroke is one higher than what's received, e.g. if you send a, + you get b, send A you get B, and so forth. + + The circuit: + - none + + created 21 Oct 2011 + modified 27 Mar 2012 + by Tom Igoe + + This example code is in the public domain. + + https://www.arduino.cc/en/Tutorial/BuiltInExamples/KeyboardSerial +*/ + +#include + +void setup() { + // open the serial port: + Serial.begin(9600); + // initialize control over the keyboard: + KeyboardBLE.begin(); +} + +void loop() { + // check for incoming serial data: + if (Serial.available() > 0) { + // read incoming serial data: + char inChar = Serial.read(); + // Type the next ASCII value from what you received: + KeyboardBLE.write(inChar + 1); + } +} diff --git a/libraries/KeyboardBLE/keywords.txt b/libraries/KeyboardBLE/keywords.txt new file mode 100644 index 000000000..89cddddf5 --- /dev/null +++ b/libraries/KeyboardBLE/keywords.txt @@ -0,0 +1,24 @@ +####################################### +# Syntax Coloring Map For Keyboard +####################################### + +####################################### +# Datatypes (KEYWORD1) +####################################### + +KeyboardBLE KEYWORD1 + +####################################### +# Methods and Functions (KEYWORD2) +####################################### + +begin KEYWORD2 +write KEYWORD2 +press KEYWORD2 +release KEYWORD2 +releaseAll KEYWORD2 +setBattery KEYWORD2 + +####################################### +# Constants (LITERAL1) +####################################### diff --git a/libraries/KeyboardBLE/library.properties b/libraries/KeyboardBLE/library.properties new file mode 100644 index 000000000..d29880d08 --- /dev/null +++ b/libraries/KeyboardBLE/library.properties @@ -0,0 +1,9 @@ +name=KeyboardBLE +version=1.0.3 +author=Arduino and EFP3 +maintainer=Earle F. Philhower, III +sentence=Allows a RP2040 to act as a Keyboard. +paragraph=Port of pure Arduino Keyboard to PicoW BLE +category=Device Control +url=https://www.arduino.cc/reference/en/language/functions/usb/keyboard/ +architectures=rp2040 diff --git a/libraries/KeyboardBLE/src/KeyboardBLE.cpp b/libraries/KeyboardBLE/src/KeyboardBLE.cpp new file mode 100644 index 000000000..cdf4cc1e2 --- /dev/null +++ b/libraries/KeyboardBLE/src/KeyboardBLE.cpp @@ -0,0 +1,71 @@ +/* + KeyboardBLE.cpp + + Modified by Earle F. Philhower, III + Main Arduino Library Copyright (c) 2015, Arduino LLC + Original code (pre-library): Copyright (c) 2011, Peter Barrett + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include "KeyboardBLE.h" +#include "KeyboardLayout.h" +#include + +//================================================================================ +//================================================================================ +// Keyboard + +KeyboardBLE_::KeyboardBLE_(void) { + // Base class clears the members we care about +} + +#define REPORT_ID 0x01 + +static const uint8_t desc_keyboard[] = {TUD_HID_REPORT_DESC_KEYBOARD(HID_REPORT_ID(REPORT_ID))}; + +void KeyboardBLE_::begin(const char *localName, const char *hidName, const uint8_t *layout) { + if (!localName) { + localName = "PicoW BLE Keyboard"; + } + if (!hidName) { + hidName = localName; + } + _asciimap = layout; + PicoBluetoothBLEHID.startHID(localName, hidName, 0x03c1, desc_keyboard, sizeof(desc_keyboard)); +} + +void KeyboardBLE_::end(void) { + PicoBluetoothBLEHID.end(); +} + +void KeyboardBLE_::setBattery(int lvl) { + PicoBluetoothBLEHID.setBattery(lvl); +} + +void KeyboardBLE_::sendReport(KeyReport* keys) { + hid_keyboard_report_t data; + data.modifier = keys->modifiers; + data.reserved = 0; + memcpy(data.keycode, keys->keys, sizeof(data.keycode)); + PicoBluetoothBLEHID.send(&data, sizeof(data)); +} + +void KeyboardBLE_::sendConsumerReport(uint16_t key) { + (void) key; + // TODO - Need some BLE-specific code to send 2nd report +} + +KeyboardBLE_ KeyboardBLE; diff --git a/libraries/KeyboardBLE/src/KeyboardBLE.h b/libraries/KeyboardBLE/src/KeyboardBLE.h new file mode 100644 index 000000000..9d570f6df --- /dev/null +++ b/libraries/KeyboardBLE/src/KeyboardBLE.h @@ -0,0 +1,40 @@ +/* + KeyboardBLE.h + + Modified by Earle F. Philhower, III + Main Arduino Library Copyright (c) 2015, Arduino LLC + Original code (pre-library): Copyright (c) 2011, Peter Barrett + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#ifndef KEYBOARDBLE_h +#define KEYBOARDBLE_h + +#include + +class KeyboardBLE_ : public HID_Keyboard { +private: + virtual void sendReport(KeyReport* keys) override; + virtual void sendConsumerReport(uint16_t key) override; +public: + KeyboardBLE_(void); + void begin(const char *localName = nullptr, const char *hidName = nullptr, const uint8_t *layout = KeyboardLayout_en_US); + void end(void); + void setBattery(int lvl); +}; +extern KeyboardBLE_ KeyboardBLE; + +#endif diff --git a/libraries/KeyboardBT/LICENSE b/libraries/KeyboardBT/LICENSE new file mode 100644 index 000000000..0a041280b --- /dev/null +++ b/libraries/KeyboardBT/LICENSE @@ -0,0 +1,165 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + + This version of the GNU Lesser General Public License incorporates +the terms and conditions of version 3 of the GNU General Public +License, supplemented by the additional permissions listed below. + + 0. Additional Definitions. + + As used herein, "this License" refers to version 3 of the GNU Lesser +General Public License, and the "GNU GPL" refers to version 3 of the GNU +General Public License. + + "The Library" refers to a covered work governed by this License, +other than an Application or a Combined Work as defined below. + + An "Application" is any work that makes use of an interface provided +by the Library, but which is not otherwise based on the Library. +Defining a subclass of a class defined by the Library is deemed a mode +of using an interface provided by the Library. + + A "Combined Work" is a work produced by combining or linking an +Application with the Library. The particular version of the Library +with which the Combined Work was made is also called the "Linked +Version". + + The "Minimal Corresponding Source" for a Combined Work means the +Corresponding Source for the Combined Work, excluding any source code +for portions of the Combined Work that, considered in isolation, are +based on the Application, and not on the Linked Version. + + The "Corresponding Application Code" for a Combined Work means the +object code and/or source code for the Application, including any data +and utility programs needed for reproducing the Combined Work from the +Application, but excluding the System Libraries of the Combined Work. + + 1. Exception to Section 3 of the GNU GPL. + + You may convey a covered work under sections 3 and 4 of this License +without being bound by section 3 of the GNU GPL. + + 2. Conveying Modified Versions. + + If you modify a copy of the Library, and, in your modifications, a +facility refers to a function or data to be supplied by an Application +that uses the facility (other than as an argument passed when the +facility is invoked), then you may convey a copy of the modified +version: + + a) under this License, provided that you make a good faith effort to + ensure that, in the event an Application does not supply the + function or data, the facility still operates, and performs + whatever part of its purpose remains meaningful, or + + b) under the GNU GPL, with none of the additional permissions of + this License applicable to that copy. + + 3. Object Code Incorporating Material from Library Header Files. + + The object code form of an Application may incorporate material from +a header file that is part of the Library. You may convey such object +code under terms of your choice, provided that, if the incorporated +material is not limited to numerical parameters, data structure +layouts and accessors, or small macros, inline functions and templates +(ten or fewer lines in length), you do both of the following: + + a) Give prominent notice with each copy of the object code that the + Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the object code with a copy of the GNU GPL and this license + document. + + 4. Combined Works. + + You may convey a Combined Work under terms of your choice that, +taken together, effectively do not restrict modification of the +portions of the Library contained in the Combined Work and reverse +engineering for debugging such modifications, if you also do each of +the following: + + a) Give prominent notice with each copy of the Combined Work that + the Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the Combined Work with a copy of the GNU GPL and this license + document. + + c) For a Combined Work that displays copyright notices during + execution, include the copyright notice for the Library among + these notices, as well as a reference directing the user to the + copies of the GNU GPL and this license document. + + d) Do one of the following: + + 0) Convey the Minimal Corresponding Source under the terms of this + License, and the Corresponding Application Code in a form + suitable for, and under terms that permit, the user to + recombine or relink the Application with a modified version of + the Linked Version to produce a modified Combined Work, in the + manner specified by section 6 of the GNU GPL for conveying + Corresponding Source. + + 1) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (a) uses at run time + a copy of the Library already present on the user's computer + system, and (b) will operate properly with a modified version + of the Library that is interface-compatible with the Linked + Version. + + e) Provide Installation Information, but only if you would otherwise + be required to provide such information under section 6 of the + GNU GPL, and only to the extent that such information is + necessary to install and execute a modified version of the + Combined Work produced by recombining or relinking the + Application with a modified version of the Linked Version. (If + you use option 4d0, the Installation Information must accompany + the Minimal Corresponding Source and Corresponding Application + Code. If you use option 4d1, you must provide the Installation + Information in the manner specified by section 6 of the GNU GPL + for conveying Corresponding Source.) + + 5. Combined Libraries. + + You may place library facilities that are a work based on the +Library side by side in a single library together with other library +facilities that are not Applications and are not covered by this +License, and convey such a combined library under terms of your +choice, if you do both of the following: + + a) Accompany the combined library with a copy of the same work based + on the Library, uncombined with any other library facilities, + conveyed under the terms of this License. + + b) Give prominent notice with the combined library that part of it + is a work based on the Library, and explaining where to find the + accompanying uncombined form of the same work. + + 6. Revised Versions of the GNU Lesser General Public License. + + The Free Software Foundation may publish revised and/or new versions +of the GNU Lesser General Public License from time to time. Such new +versions will be similar in spirit to the present version, but may +differ in detail to address new problems or concerns. + + Each version is given a distinguishing version number. If the +Library as you received it specifies that a certain numbered version +of the GNU Lesser General Public License "or any later version" +applies to it, you have the option of following the terms and +conditions either of that published version or of any later version +published by the Free Software Foundation. If the Library as you +received it does not specify a version number of the GNU Lesser +General Public License, you may choose any version of the GNU Lesser +General Public License ever published by the Free Software Foundation. + + If the Library as you received it specifies that a proxy can decide +whether future versions of the GNU Lesser General Public License shall +apply, that proxy's public statement of acceptance of any version is +permanent authorization for you to choose that version for the +Library. diff --git a/libraries/KeyboardBT/README.adoc b/libraries/KeyboardBT/README.adoc new file mode 100644 index 000000000..9b5f9baa2 --- /dev/null +++ b/libraries/KeyboardBT/README.adoc @@ -0,0 +1,31 @@ +:repository-owner: arduino-libraries +:repository-name: Keyboard + += {repository-name} Library for Arduino = + +image:https://github.com/{repository-owner}/{repository-name}/actions/workflows/check-arduino.yml/badge.svg["Check Arduino status", link="https://github.com/{repository-owner}/{repository-name}/actions/workflows/check-arduino.yml"] +image:https://github.com/{repository-owner}/{repository-name}/actions/workflows/compile-examples.yml/badge.svg["Compile Examples status", link="https://github.com/{repository-owner}/{repository-name}/actions/workflows/compile-examples.yml"] +image:https://github.com/{repository-owner}/{repository-name}/actions/workflows/spell-check.yml/badge.svg["Spell Check status", link="https://github.com/{repository-owner}/{repository-name}/actions/workflows/spell-check.yml"] + +This library allows an Arduino board with USB capabilities to act as a keyboard. + +For more information about this library please visit us at +https://www.arduino.cc/reference/en/language/functions/usb/keyboard/ + +== License == + +Copyright (c) Arduino LLC. All right reserved. + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA diff --git a/libraries/KeyboardBT/examples/BTKeyboardPassword/BTKeyboardPassword.ino b/libraries/KeyboardBT/examples/BTKeyboardPassword/BTKeyboardPassword.ino new file mode 100644 index 000000000..dd869c11a --- /dev/null +++ b/libraries/KeyboardBT/examples/BTKeyboardPassword/BTKeyboardPassword.ino @@ -0,0 +1,33 @@ +/* Released into the public domain */ +/* Earle F. Philhower, III */ + +#include + +void ledCB(bool numlock, bool capslock, bool scrolllock, bool compose, bool kana, void *cbData) { + (void) numlock; + (void) scrolllock; + (void) compose; + (void) kana; + (void) cbData; + digitalWrite(LED_BUILTIN, capslock ? HIGH : LOW); +} + +void setup() { + Serial.begin(115200); + KeyboardBT.begin("PicoW Password"); + pinMode(LED_BUILTIN, OUTPUT); + digitalWrite(LED_BUILTIN, LOW); + KeyboardBT.onLED(ledCB); + KeyboardBT.begin(); + delay(5000); + Serial.printf("Arduino USB Password Typer\n"); + Serial.printf("Press BOOTSEL to enter your super-secure(not!) password\n\n"); +} + +void loop() { + if (BOOTSEL) { + Serial.println("Typing password for you...shhhh...."); + KeyboardBT.print("ThisPasswordIsWeakLikeABaby"); + while (BOOTSEL); + } +} diff --git a/libraries/KeyboardBT/examples/BTSerial/BTSerial.ino b/libraries/KeyboardBT/examples/BTSerial/BTSerial.ino new file mode 100644 index 000000000..078b6f108 --- /dev/null +++ b/libraries/KeyboardBT/examples/BTSerial/BTSerial.ino @@ -0,0 +1,39 @@ +/* + Keyboard test + + For the Arduino Leonardo, Micro or Due + + Reads a byte from the serial port, sends a keystroke back. + The sent keystroke is one higher than what's received, e.g. if you send a, + you get b, send A you get B, and so forth. + + The circuit: + - none + + created 21 Oct 2011 + modified 27 Mar 2012 + by Tom Igoe + + This example code is in the public domain. + + https://www.arduino.cc/en/Tutorial/BuiltInExamples/KeyboardSerial +*/ + +#include + +void setup() { + // open the serial port: + Serial.begin(9600); + // initialize control over the keyboard: + KeyboardBT.begin(); +} + +void loop() { + // check for incoming serial data: + if (Serial.available() > 0) { + // read incoming serial data: + char inChar = Serial.read(); + // Type the next ASCII value from what you received: + KeyboardBT.write(inChar + 1); + } +} diff --git a/libraries/KeyboardBT/keywords.txt b/libraries/KeyboardBT/keywords.txt new file mode 100644 index 000000000..09ba29429 --- /dev/null +++ b/libraries/KeyboardBT/keywords.txt @@ -0,0 +1,24 @@ +####################################### +# Syntax Coloring Map For Keyboard +####################################### + +####################################### +# Datatypes (KEYWORD1) +####################################### + +KeyboardBT KEYWORD1 + +####################################### +# Methods and Functions (KEYWORD2) +####################################### + +begin KEYWORD2 +write KEYWORD2 +press KEYWORD2 +release KEYWORD2 +releaseAll KEYWORD2 + +####################################### +# Constants (LITERAL1) +####################################### + diff --git a/libraries/KeyboardBT/library.properties b/libraries/KeyboardBT/library.properties new file mode 100644 index 000000000..a2ea368f3 --- /dev/null +++ b/libraries/KeyboardBT/library.properties @@ -0,0 +1,9 @@ +name=KeyboardBT +version=1.0.3 +author=Arduino and EFP3 +maintainer=Earle F. Philhower, III +sentence=Allows a RP2040 to act as a Keyboard. +paragraph=Port of pure Arduino Keyboard to PicoW BT +category=Device Control +url=https://www.arduino.cc/reference/en/language/functions/usb/keyboard/ +architectures=rp2040 diff --git a/libraries/KeyboardBT/src/KeyboardBT.cpp b/libraries/KeyboardBT/src/KeyboardBT.cpp new file mode 100644 index 000000000..de5c7de18 --- /dev/null +++ b/libraries/KeyboardBT/src/KeyboardBT.cpp @@ -0,0 +1,78 @@ +/* + KeyboardBT.cpp + + Modified by Earle F. Philhower, III + Main Arduino Library Copyright (c) 2015, Arduino LLC + Original code (pre-library): Copyright (c) 2011, Peter Barrett + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include "KeyboardBT.h" +#include "KeyboardLayout.h" +#include + +//================================================================================ +//================================================================================ +// Keyboard + +KeyboardBT_::KeyboardBT_(void) { + // Base class clears the members we care about +} + +#define REPORT_ID 0x01 + +static const uint8_t desc_keyboard[] = {TUD_HID_REPORT_DESC_KEYBOARD(HID_REPORT_ID(REPORT_ID)), TUD_HID_REPORT_DESC_CONSUMER(HID_REPORT_ID(REPORT_ID + 1))}; + +static void _hidReportCB(uint16_t cid, hid_report_type_t report_type, uint16_t report_id, int report_size, uint8_t *report) { + (void) cid; + (void) report_id; + if ((report_type == HID_REPORT_TYPE_OUTPUT) && (report_size > 0) && (KeyboardBT._ledCB)) { + uint8_t const kbd_leds = report[0]; + KeyboardBT._ledCB(kbd_leds & KEYBOARD_LED_NUMLOCK, kbd_leds & KEYBOARD_LED_CAPSLOCK, kbd_leds & KEYBOARD_LED_SCROLLLOCK, kbd_leds & KEYBOARD_LED_COMPOSE, kbd_leds & KEYBOARD_LED_KANA, KeyboardBT._ledCBdata); + } +} + +void KeyboardBT_::begin(const char *localName, const char *hidName, const uint8_t *layout) { + if (!localName) { + localName = "PicoW BT Keyboard"; + } + if (!hidName) { + hidName = localName; + } + _asciimap = layout; + // Required because the hid_report_type_t overlap in BTStack and TUSB + auto *fcn = (void (*)(short unsigned int, hid_report_type_t_bt, short unsigned int, int, unsigned char*))_hidReportCB; + hid_device_register_report_data_callback(fcn); + PicoBluetoothHID.startHID(localName, hidName, 0x2540, 33, desc_keyboard, sizeof(desc_keyboard)); +} + +void KeyboardBT_::end(void) { + PicoBluetoothHID.end(); +} + +void KeyboardBT_::sendReport(KeyReport* keys) { + hid_keyboard_report_t data; + data.modifier = keys->modifiers; + data.reserved = 0; + memcpy(data.keycode, keys->keys, sizeof(data.keycode)); + PicoBluetoothHID.send(REPORT_ID, &data, sizeof(data)); +} + +void KeyboardBT_::sendConsumerReport(uint16_t key) { + PicoBluetoothHID.send(REPORT_ID + 1, &key, sizeof(key)); +} + +KeyboardBT_ KeyboardBT; diff --git a/libraries/KeyboardBT/src/KeyboardBT.h b/libraries/KeyboardBT/src/KeyboardBT.h new file mode 100644 index 000000000..92a50f8b1 --- /dev/null +++ b/libraries/KeyboardBT/src/KeyboardBT.h @@ -0,0 +1,39 @@ +/* + KeyboardBT.h + + Modified by Earle F. Philhower, III + Main Arduino Library Copyright (c) 2015, Arduino LLC + Original code (pre-library): Copyright (c) 2011, Peter Barrett + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#ifndef KEYBOARDBT_h +#define KEYBOARDBT_h + +#include + +class KeyboardBT_ : public HID_Keyboard { +protected: + virtual void sendReport(KeyReport* keys) override; + virtual void sendConsumerReport(uint16_t key) override; +public: + KeyboardBT_(void); + void begin(const char *localName = nullptr, const char *hidName = nullptr, const uint8_t *layout = KeyboardLayout_en_US); + void end(void); +}; +extern KeyboardBT_ KeyboardBT; + +#endif diff --git a/libraries/LEAmDNS/src/LEAmDNS.cpp b/libraries/LEAmDNS/src/LEAmDNS.cpp index ef86b5605..c1b3e2eb3 100644 --- a/libraries/LEAmDNS/src/LEAmDNS.cpp +++ b/libraries/LEAmDNS/src/LEAmDNS.cpp @@ -28,7 +28,6 @@ #include "ESP8266mDNS.h" #include "LEAmDNS_Priv.h" #include // LwipIntf::stateUpCB() -#include // LwipIntf::stateUpCB() #include #include diff --git a/libraries/LEAmDNS/src/LEAmDNS.h b/libraries/LEAmDNS/src/LEAmDNS.h index a837f360e..8116bf165 100644 --- a/libraries/LEAmDNS/src/LEAmDNS.h +++ b/libraries/LEAmDNS/src/LEAmDNS.h @@ -1100,7 +1100,7 @@ class MDNSResponder { }; public: - uint16_t m_u16ID; // Query ID (used only in lagacy queries) + uint16_t m_u16ID; // Query ID (used only in legacy queries) stcMDNS_RRQuestion* m_pQuestions; // A list of queries uint8_t m_u8HostReplyMask; // Flags for reply components/answers bool m_bLegacyQuery; // Flag: Legacy query diff --git a/libraries/LEAmDNS/src/LEAmDNS_Control.cpp b/libraries/LEAmDNS/src/LEAmDNS_Control.cpp index 72dc69e31..64f026bae 100644 --- a/libraries/LEAmDNS/src/LEAmDNS_Control.cpp +++ b/libraries/LEAmDNS/src/LEAmDNS_Control.cpp @@ -1980,7 +1980,7 @@ uint8_t MDNSResponder::_replyMaskForHost(const MDNSResponder::stcMDNS_RRHeader& #ifdef MDNS_IP6_SUPPORT // TODO #endif - } // Address qeuest + } // Address quest stcMDNS_RRDomain hostDomain; if ((_buildDomainForHost(m_pcHostname, hostDomain)) diff --git a/libraries/LEAmDNS/src/LEAmDNS_Priv.h b/libraries/LEAmDNS/src/LEAmDNS_Priv.h index e59b70ec1..fbabf86bc 100644 --- a/libraries/LEAmDNS/src/LEAmDNS_Priv.h +++ b/libraries/LEAmDNS/src/LEAmDNS_Priv.h @@ -22,8 +22,7 @@ */ -#ifndef MDNS_PRIV_H -#define MDNS_PRIV_H +#pragma once namespace esp8266 { @@ -186,5 +185,3 @@ namespace MDNSImplementation { // Include the main header, so the submodlues only need to include this header #include "LEAmDNS.h" - -#endif // MDNS_PRIV_H diff --git a/libraries/LEAmDNS/src/LEAmDNS_lwIPdefs.h b/libraries/LEAmDNS/src/LEAmDNS_lwIPdefs.h index ea2128a9e..69f13f20b 100644 --- a/libraries/LEAmDNS/src/LEAmDNS_lwIPdefs.h +++ b/libraries/LEAmDNS/src/LEAmDNS_lwIPdefs.h @@ -22,9 +22,6 @@ */ -#ifndef MDNS_LWIPDEFS_H -#define MDNS_LWIPDEFS_H +#pragma once #include // DNS_RRTYPE_xxx, DNS_MQUERY_PORT - -#endif // MDNS_LWIPDEFS_H diff --git a/libraries/LittleFS/examples/SpeedTest/SpeedTest.ino b/libraries/LittleFS/examples/SpeedTest/SpeedTest.ino index 31f1ed715..6478128ad 100644 --- a/libraries/LittleFS/examples/SpeedTest/SpeedTest.ino +++ b/libraries/LittleFS/examples/SpeedTest/SpeedTest.ino @@ -3,6 +3,7 @@ #include #include +#include // Choose the filesystem to test // WARNING: The filesystem will be formatted at the start of the test! diff --git a/libraries/LittleFS/src/LittleFS.h b/libraries/LittleFS/src/LittleFS.h index 866dc0958..189c1c930 100644 --- a/libraries/LittleFS/src/LittleFS.h +++ b/libraries/LittleFS/src/LittleFS.h @@ -23,9 +23,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ - -#ifndef __LITTLEFS_H -#define __LITTLEFS_H +#pragma once #include #include @@ -459,14 +457,14 @@ class LittleFSFileImpl : public FileImpl { if (_creation) { int rc = lfs_setattr(_fs->getFS(), _name.get(), 'c', (const void *)&_creation, sizeof(_creation)); if (rc < 0) { - DEBUGV("Unable to set creation time on '%s' to %d\n", _name.get(), _creation); + DEBUGV("Unable to set creation time on '%s' to %lld\n", _name.get(), _creation); } } // Add metadata with last write time time_t now = _timeCallback(); int rc = lfs_setattr(_fs->getFS(), _name.get(), 't', (const void *)&now, sizeof(now)); if (rc < 0) { - DEBUGV("Unable to set last write time on '%s' to %d\n", _name.get(), now); + DEBUGV("Unable to set last write time on '%s' to %lld\n", _name.get(), now); } } } @@ -681,6 +679,3 @@ class LittleFSDirImpl : public DirImpl { extern FS LittleFS; using littlefs_impl::LittleFSConfig; #endif // ARDUINO - - -#endif // !defined(__LITTLEFS_H) diff --git a/libraries/Mouse b/libraries/Mouse deleted file mode 160000 index be7395a59..000000000 --- a/libraries/Mouse +++ /dev/null @@ -1 +0,0 @@ -Subproject commit be7395a597c748eda75ea40821637a63e596f09d diff --git a/libraries/Mouse/README.adoc b/libraries/Mouse/README.adoc new file mode 100644 index 000000000..c9df074f8 --- /dev/null +++ b/libraries/Mouse/README.adoc @@ -0,0 +1,31 @@ +:repository-owner: arduino-libraries +:repository-name: Mouse + += {repository-name} Library for Arduino = + +image:https://github.com/{repository-owner}/{repository-name}/actions/workflows/check-arduino.yml/badge.svg["Check Arduino status", link="https://github.com/{repository-owner}/{repository-name}/actions/workflows/check-arduino.yml"] +image:https://github.com/{repository-owner}/{repository-name}/actions/workflows/compile-examples.yml/badge.svg["Compile Examples status", link="https://github.com/{repository-owner}/{repository-name}/actions/workflows/compile-examples.yml"] +image:https://github.com/{repository-owner}/{repository-name}/actions/workflows/spell-check.yml/badge.svg["Spell Check status", link="https://github.com/{repository-owner}/{repository-name}/actions/workflows/spell-check.yml"] + +This library allows an Arduino board with USB capabilities to act as a Mouse. + +For more information about this library please visit us at +https://www.arduino.cc/reference/en/language/functions/usb/mouse/ + +== License == + +Copyright (c) Arduino LLC. All right reserved. + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA diff --git a/libraries/Mouse/docs/api.md b/libraries/Mouse/docs/api.md new file mode 100644 index 000000000..99bee66e1 --- /dev/null +++ b/libraries/Mouse/docs/api.md @@ -0,0 +1,428 @@ +# Mouse library + +## Methods + +### `Mouse.begin()` + +Begins emulating the mouse connected to a computer. `begin()` must be called before controlling the computer. To end control, use `Mouse.end()`. + +#### Syntax + +``` +Mouse.begin() +``` + +#### Parameters + +None. + +#### Returns + +None. + +#### Example + +``` +#include + +void setup() { + pinMode(2, INPUT); +} + +void loop() { + // Initialize the Mouse library when button is pressed + if (digitalRead(2) == HIGH) { + Mouse.begin(); + } +} +``` + +#### See also + +* [Mouse.click()](#mouseclick) +* [Mouse.end()](#mouseend) +* [Mouse.move()](#mousemove) +* [Mouse.press()](#mousepress) +* [Mouse.release()](#mouserelease) +* [Mouse.isPressed()](#mouseispressed) + +### `Mouse.click()` + +Sends a momentary click to the computer at the location of the cursor. This is the same as pressing and immediately releasing the mouse button. + +`Mouse.click()` defaults to the left mouse button. + +#### Syntax + +``` +Mouse.click() +Mouse.click(button) +``` + +#### Parameters + +* `button`: which mouse button to press (MOUSE_LEFT, MOUSE_RIGHT or MOUSE_MIDDLE, default is MOUSE_LEFT). + +#### Returns + +None. + +#### Example + +``` +#include + +void setup() { + pinMode(2, INPUT); + // Initialize the Mouse library + Mouse.begin(); +} + +void loop() { + // If the button is pressed, send a left mouse click + if (digitalRead(2) == HIGH) { + Mouse.click(); + } +} +``` + +#### Notes and warnings + +When you use the `Mouse.click()` command, the Arduino takes over your mouse! Make sure you have control before you use the command. A pushbutton to toggle the mouse control state is effective. + +#### See also + +* [Mouse.begin()](#mousebegin) +* [Mouse.end()](#mouseend) +* [Mouse.move()](#mousemove) +* [Mouse.press()](#mousepress) +* [Mouse.release()](#mouserelease) +* [Mouse.isPressed()](#mouseispressed) + +### `Mouse.end()` + +Stops emulating the mouse connected to a computer. To start control, use `Mouse.begin()`. + +#### Syntax + +``` +Mouse.end() +``` + +#### Parameters + +None. + +#### Returns + +None. + +#### Example + +``` +#include + +void setup() { + pinMode(2, INPUT); + // Initiate the Mouse library + Mouse.begin(); +} + +void loop() { + // If the button is pressed, send a left mouse click + if (digitalRead(2) == HIGH) { + Mouse.click(); + // Then end the Mouse emulation + Mouse.end(); + } +} +``` + +#### See also + +* [Mouse.begin()](#mousebegin) +* [Mouse.click()](#mouseclick) +* [Mouse.move()](#mousemove) +* [Mouse.press()](#mousepress) +* [Mouse.release()](#mouserelease) +* [Mouse.isPressed()](#mouseispressed) + +### `Mouse.move()` + +Moves the cursor on a connected computer. The motion onscreen is always relative to the cursor’s current location. Before using `Mouse.move()` you must call `Mouse.begin()`. + +#### Syntax + +``` +Mouse.move(xVal, yVal, wheel) +``` + +#### Parameters + +* `xVal`: amount to move along the x-axis. Allowed data types: signed char. +* `yVal`: amount to move along the y-axis. Allowed data types: signed char. +* `wheel`: amount to move scroll wheel. Allowed data types: signed char. + +#### Returns + +None. + +#### Example + +``` +#include + +const int xAxis = A1; // Analog sensor for X axis +const int yAxis = A2; // Analog sensor for Y axis + +int range = 12; // Output range of X or Y movement +int responseDelay = 2; // Response delay of the mouse, in ms +int threshold = range / 4; // Resting threshold +int center = range / 2; // Resting position value +int minima[] = {1023, 1023}; // Actual analogRead minima for (x, y) +int maxima[] = {0, 0}; // Actual analogRead maxima for (x, y) +int axis[] = {xAxis, yAxis}; // Pin numbers for (x, y) +int mouseReading[2]; // Final mouse readings for (x, y) + +void setup() { + // Initialize the Mouse library + Mouse.begin(); +} + +void loop() { + // Read and scale the two axes + int xReading = readAxis(0); + int yReading = readAxis(1); + + // Move the mouse + Mouse.move(xReading, yReading, 0); + delay(responseDelay); +} + +/* + Reads an axis (0 or 1 for x or y) and scales the + analog input range to a range from 0 to +*/ +int readAxis(int axisNumber) { + int distance = 0; // Distance from center of the output range + + // Read the analog input + int reading = analogRead(axis[axisNumber]); + + // Of the current reading exceeds the max or min for this axis, reset the max or min + if (reading < minima[axisNumber]) { + minima[axisNumber] = reading; + } + if (reading > maxima[axisNumber]) { + maxima[axisNumber] = reading; + } + + // Map the reading from the analog input range to the output range + reading = map(reading, minima[axisNumber], maxima[axisNumber], 0, range); + + // If the output reading is outside from the rest position threshold, use it + if (abs(reading - center) > threshold) { + distance = (reading - center); + } + + // The Y axis needs to be inverted in order to map the movement correctly + if (axisNumber == 1) { + distance = -distance; + } + + // Return the distance for this axis + return distance; +} +``` + +#### Notes and warnings + +When you use the `Mouse.move()` command, the Arduino takes over your mouse! Make sure you have control before you use the command. A pushbutton to toggle the mouse control state is effective. + +#### See also + +* [Mouse.begin()](#mousebegin) +* [Mouse.click()](#mouseclick) +* [Mouse.end()](#mouseend) +* [Mouse.press()](#mousepress) +* [Mouse.release()](#mouserelease) +* [Mouse.isPressed()](#mouseispressed) + +### `Mouse.press()` + +Sends a button press to a connected computer. A press is the equivalent of clicking and continuously holding the mouse button. A press is cancelled with `Mouse.release()`. Before using `Mouse.press()`, you need to start communication with `Mouse.begin()`. `Mouse.press()` defaults to a left button press. + +#### Syntax + +``` +Mouse.press() +Mouse.press(button) +``` + +#### Parameters + +* `button`: which mouse button to press (MOUSE_LEFT, MOUSE_RIGHT or MOUSE_MIDDLE, default is MOUSE_LEFT). + +#### Returns + +None. + +#### Example + +``` +#include + +void setup() { + // The switch that will initiate the Mouse press + pinMode(2, INPUT); + // The switch that will terminate the Mouse press + pinMode(3, INPUT); + // Initialize the Mouse library + Mouse.begin(); +} + +void loop() { + // If the switch attached to pin 2 is closed, press and hold the left mouse button + if (digitalRead(2) == HIGH) { + Mouse.press(); + } + // If the switch attached to pin 3 is closed, release the left mouse button + if (digitalRead(3) == HIGH) { + Mouse.release(); + } +} +``` + +#### Notes and warnings + +When you use the `Mouse.press()` command, the Arduino takes over your mouse! Make sure you have control before you use the command. A pushbutton to toggle the mouse control state is effective. + +#### See also + +* [Mouse.begin()](#mousebegin) +* [Mouse.click()](#mouseclick) +* [Mouse.end()](#mouseend) +* [Mouse.move()](#mousemove) +* [Mouse.release()](#mouserelease) +* [Mouse.isPressed()](#mouseispressed) + +### `Mouse.release()` + +Sends a message that a previously pressed button (invoked through `Mouse.press()`) is released. `Mouse.release()` defaults to the left button. + +#### Syntax + +``` +Mouse.press() +Mouse.press(button) +``` + +#### Parameters + +* `button`: which mouse button was released (MOUSE_LEFT, MOUSE_RIGHT or MOUSE_MIDDLE, default is MOUSE_LEFT). + +#### Returns + +None. + +#### Example + +``` +#include + +void setup() { + // The switch that will initiate the Mouse press + pinMode(2, INPUT); + // The switch that will terminate the Mouse press + pinMode(3, INPUT); + // Initialize the Mouse library + Mouse.begin(); +} + +void loop() { + // If the switch attached to pin 2 is closed, press and hold the left mouse button + if (digitalRead(2) == HIGH) { + Mouse.press(); + } + // If the switch attached to pin 3 is closed, release the left mouse button + if (digitalRead(3) == HIGH) { + Mouse.release(); + } +} +``` + +#### Notes and warnings + +When you use the `Mouse.release()` command, the Arduino takes over your mouse! Make sure you have control before you use the command. A pushbutton to toggle the mouse control state is effective. + +#### See also + +* [Mouse.begin()](#mousebegin) +* [Mouse.click()](#mouseclick) +* [Mouse.end()](#mouseend) +* [Mouse.move()](#mousemove) +* [Mouse.press()](#mousepress) +* [Mouse.isPressed()](#mouseispressed) + +### `Mouse.isPressed()` + +Checks the current status of all mouse buttons, and reports if any are pressed or not. By default, it checks the status of the left mouse button. + +#### Syntax + +``` +Mouse.isPressed(); +Mouse.isPressed(button); +``` + +#### Parameters + +* `button`: which mouse button was released (MOUSE_LEFT, MOUSE_RIGHT or MOUSE_MIDDLE, default is MOUSE_LEFT). + +#### Returns + +1 if a button was pressed, 0 if a not. + +#### Example + +``` +#include + +void setup() { + // The switch that will initiate the Mouse press + pinMode(2, INPUT); + // The switch that will terminate the Mouse press + pinMode(3, INPUT); + // Start serial communication with the computer + Serial.begin(9600); + // Initialize the Mouse library + Mouse.begin(); +} + +void loop() { + // A variable for checking the button's state + int mouseState = 0; + // If the switch attached to pin 2 is closed, press and hold the left mouse button and save the state ina variable + if (digitalRead(2) == HIGH) { + Mouse.press(); + mouseState = Mouse.isPressed(); + } + // If the switch attached to pin 3 is closed, release the left mouse button and save the state in a variable + if (digitalRead(3) == HIGH) { + Mouse.release(); + mouseState = Mouse.isPressed(); + } + // Print out the current mouse button state + Serial.println(mouseState); + delay(10); +} +``` + +#### See also + +* [Mouse.begin()](#mousebegin) +* [Mouse.click()](#mouseclick) +* [Mouse.end()](#mouseend) +* [Mouse.move()](#mousemove) +* [Mouse.press()](#mousepress) +* [Mouse.release()](#mouserelease) \ No newline at end of file diff --git a/libraries/Mouse/docs/readme.md b/libraries/Mouse/docs/readme.md new file mode 100644 index 000000000..f2f50bd6a --- /dev/null +++ b/libraries/Mouse/docs/readme.md @@ -0,0 +1,23 @@ +# Mouse library + +The mouse functions enable 32u4 or SAMD micro based boards to control cursor movement on a connected computer through their micro’s native USB port. When updating the cursor position, it is always relative to the cursor’s previous location. + +To use this library: + +``` +#include +``` + +## Notes and warnings + +These core libraries allow the 32u4 and SAMD based boards (Leonardo, Esplora, Zero, Due and MKR Family) to appear as a native Mouse and/or Keyboard to a connected computer. + +**A word of caution on using the Mouse and Keyboard libraries**: if the Mouse or Keyboard library is constantly running, it will be difficult to program your board. Functions such as `Mouse.move()` and `Keyboard.print()` will move your cursor or send keystrokes to a connected computer and should only be called when you are ready to handle them. It is recommended to use a control system to turn this functionality on, like a physical switch or only responding to specific input you can control. Refer to the Mouse and Keyboard examples for some ways to handle this. + +When using the Mouse or Keyboard library, it may be best to test your output first using `Serial.print()`. This way, you can be sure you know what values are being reported. + +## Examples + +* [KeyboardAndMouseControl](https://www.arduino.cc/en/Tutorial/BuiltInExamples/KeyboardAndMouseControl): Demonstrates the Mouse and Keyboard commands in one program. +* [ButtonMouseControl](https://www.arduino.cc/en/Tutorial/BuiltInExamples/ButtonMouseControl): Control cursor movement with 5 pushbuttons. +* [JoystickMouseControl](https://www.arduino.cc/en/Tutorial/BuiltInExamples/JoystickMouseControl): Controls a computer’s cursor movement with a Joystick when a button is pressed. \ No newline at end of file diff --git a/libraries/Mouse/examples/Circle/Circle.ino b/libraries/Mouse/examples/Circle/Circle.ino new file mode 100644 index 000000000..fde1ad3f9 --- /dev/null +++ b/libraries/Mouse/examples/Circle/Circle.ino @@ -0,0 +1,34 @@ +/* Earle F. Philhower, III */ +/* Released to the public domain */ + + +#include + +void setup() { + Serial.begin(115200); + Mouse.begin(); + delay(5000); + Serial.printf("Press BOOTSEL to move the mouse in a circle\n"); +} + +void loop() { + if (BOOTSEL) { + Serial.println("BARREL ROLL!!!"); + float r = 100; + float ox = 0.0; + float oy = 0.0; + for (float a = 0; a < 2.0 * 3.14159; a += 0.1) { + float ax = r * cos(a); + float ay = r * sin(a); + float dx = ax - ox; + float dy = ay - oy; + Mouse.move(dx, dy, 0); + ox = ax; + oy = ay; + delay(10); + } + while (BOOTSEL) { + delay(1); + } + } +} diff --git a/libraries/Mouse/keywords.txt b/libraries/Mouse/keywords.txt new file mode 100644 index 000000000..c669a93dc --- /dev/null +++ b/libraries/Mouse/keywords.txt @@ -0,0 +1,24 @@ +####################################### +# Syntax Coloring Map For Mouse +####################################### + +####################################### +# Datatypes (KEYWORD1) +####################################### + +Mouse KEYWORD1 + +####################################### +# Methods and Functions (KEYWORD2) +####################################### + +begin KEYWORD2 +click KEYWORD2 +move KEYWORD2 +press KEYWORD2 +release KEYWORD2 +isPressed KEYWORD2 + +####################################### +# Constants (LITERAL1) +####################################### diff --git a/libraries/Mouse/library.properties b/libraries/Mouse/library.properties new file mode 100644 index 000000000..972fd7139 --- /dev/null +++ b/libraries/Mouse/library.properties @@ -0,0 +1,9 @@ +name=Mouse +version=1.0.1 +author=Arduino and EFP3 +maintainer=Earle F. Philhower, III +sentence=Allows an Arduino board with USB capabilities to act as a Mouse. +paragraph=Allows the RP2040 to emulate a USB mouse +category=Device Control +url=https://www.arduino.cc/reference/en/language/functions/usb/mouse/ +architectures=rp2040 diff --git a/libraries/Mouse/src/Mouse.cpp b/libraries/Mouse/src/Mouse.cpp new file mode 100644 index 000000000..d3f747c02 --- /dev/null +++ b/libraries/Mouse/src/Mouse.cpp @@ -0,0 +1,53 @@ +/* + Mouse.cpp + + Copyright (c) 2015, Arduino LLC + Original code (pre-library): Copyright (c) 2011, Peter Barrett + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include "Mouse.h" +#include + +#include "tusb.h" +#include "class/hid/hid_device.h" + +// Weak function override to add our descriptor to the TinyUSB list +void __USBInstallMouse() { /* noop */ } + +//================================================================================ +//================================================================================ +// Mouse + +/* This function is for limiting the input value for x and y + axis to -127 <= x/y <= 127 since this is the allowed value + range for a USB HID device. +*/ + +Mouse_::Mouse_(void) { + /* noop */ +} + +void Mouse_::move(int x, int y, signed char wheel) { + CoreMutex m(&__usb_mutex); + tud_task(); + if (tud_hid_ready()) { + tud_hid_mouse_report(__USBGetMouseReportID(), _buttons, limit_xy(x), limit_xy(y), wheel, 0); + } + tud_task(); +} + +Mouse_ Mouse; diff --git a/libraries/Mouse/src/Mouse.h b/libraries/Mouse/src/Mouse.h new file mode 100644 index 000000000..839dbb302 --- /dev/null +++ b/libraries/Mouse/src/Mouse.h @@ -0,0 +1,34 @@ +/* + Mouse.h + + Copyright (c) 2015, Arduino LLC + Original code (pre-library): Copyright (c) 2011, Peter Barrett + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#ifndef MOUSE_h +#define MOUSE_h + +#include + +class Mouse_ : public HID_Mouse { +public: + Mouse_(void); + virtual void move(int x, int y, signed char wheel = 0) override; +}; +extern Mouse_ Mouse; + +#endif diff --git a/libraries/MouseAbsolute/README.adoc b/libraries/MouseAbsolute/README.adoc new file mode 100644 index 000000000..c9df074f8 --- /dev/null +++ b/libraries/MouseAbsolute/README.adoc @@ -0,0 +1,31 @@ +:repository-owner: arduino-libraries +:repository-name: Mouse + += {repository-name} Library for Arduino = + +image:https://github.com/{repository-owner}/{repository-name}/actions/workflows/check-arduino.yml/badge.svg["Check Arduino status", link="https://github.com/{repository-owner}/{repository-name}/actions/workflows/check-arduino.yml"] +image:https://github.com/{repository-owner}/{repository-name}/actions/workflows/compile-examples.yml/badge.svg["Compile Examples status", link="https://github.com/{repository-owner}/{repository-name}/actions/workflows/compile-examples.yml"] +image:https://github.com/{repository-owner}/{repository-name}/actions/workflows/spell-check.yml/badge.svg["Spell Check status", link="https://github.com/{repository-owner}/{repository-name}/actions/workflows/spell-check.yml"] + +This library allows an Arduino board with USB capabilities to act as a Mouse. + +For more information about this library please visit us at +https://www.arduino.cc/reference/en/language/functions/usb/mouse/ + +== License == + +Copyright (c) Arduino LLC. All right reserved. + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA diff --git a/libraries/MouseAbsolute/docs/api.md b/libraries/MouseAbsolute/docs/api.md new file mode 100644 index 000000000..99bee66e1 --- /dev/null +++ b/libraries/MouseAbsolute/docs/api.md @@ -0,0 +1,428 @@ +# Mouse library + +## Methods + +### `Mouse.begin()` + +Begins emulating the mouse connected to a computer. `begin()` must be called before controlling the computer. To end control, use `Mouse.end()`. + +#### Syntax + +``` +Mouse.begin() +``` + +#### Parameters + +None. + +#### Returns + +None. + +#### Example + +``` +#include + +void setup() { + pinMode(2, INPUT); +} + +void loop() { + // Initialize the Mouse library when button is pressed + if (digitalRead(2) == HIGH) { + Mouse.begin(); + } +} +``` + +#### See also + +* [Mouse.click()](#mouseclick) +* [Mouse.end()](#mouseend) +* [Mouse.move()](#mousemove) +* [Mouse.press()](#mousepress) +* [Mouse.release()](#mouserelease) +* [Mouse.isPressed()](#mouseispressed) + +### `Mouse.click()` + +Sends a momentary click to the computer at the location of the cursor. This is the same as pressing and immediately releasing the mouse button. + +`Mouse.click()` defaults to the left mouse button. + +#### Syntax + +``` +Mouse.click() +Mouse.click(button) +``` + +#### Parameters + +* `button`: which mouse button to press (MOUSE_LEFT, MOUSE_RIGHT or MOUSE_MIDDLE, default is MOUSE_LEFT). + +#### Returns + +None. + +#### Example + +``` +#include + +void setup() { + pinMode(2, INPUT); + // Initialize the Mouse library + Mouse.begin(); +} + +void loop() { + // If the button is pressed, send a left mouse click + if (digitalRead(2) == HIGH) { + Mouse.click(); + } +} +``` + +#### Notes and warnings + +When you use the `Mouse.click()` command, the Arduino takes over your mouse! Make sure you have control before you use the command. A pushbutton to toggle the mouse control state is effective. + +#### See also + +* [Mouse.begin()](#mousebegin) +* [Mouse.end()](#mouseend) +* [Mouse.move()](#mousemove) +* [Mouse.press()](#mousepress) +* [Mouse.release()](#mouserelease) +* [Mouse.isPressed()](#mouseispressed) + +### `Mouse.end()` + +Stops emulating the mouse connected to a computer. To start control, use `Mouse.begin()`. + +#### Syntax + +``` +Mouse.end() +``` + +#### Parameters + +None. + +#### Returns + +None. + +#### Example + +``` +#include + +void setup() { + pinMode(2, INPUT); + // Initiate the Mouse library + Mouse.begin(); +} + +void loop() { + // If the button is pressed, send a left mouse click + if (digitalRead(2) == HIGH) { + Mouse.click(); + // Then end the Mouse emulation + Mouse.end(); + } +} +``` + +#### See also + +* [Mouse.begin()](#mousebegin) +* [Mouse.click()](#mouseclick) +* [Mouse.move()](#mousemove) +* [Mouse.press()](#mousepress) +* [Mouse.release()](#mouserelease) +* [Mouse.isPressed()](#mouseispressed) + +### `Mouse.move()` + +Moves the cursor on a connected computer. The motion onscreen is always relative to the cursor’s current location. Before using `Mouse.move()` you must call `Mouse.begin()`. + +#### Syntax + +``` +Mouse.move(xVal, yVal, wheel) +``` + +#### Parameters + +* `xVal`: amount to move along the x-axis. Allowed data types: signed char. +* `yVal`: amount to move along the y-axis. Allowed data types: signed char. +* `wheel`: amount to move scroll wheel. Allowed data types: signed char. + +#### Returns + +None. + +#### Example + +``` +#include + +const int xAxis = A1; // Analog sensor for X axis +const int yAxis = A2; // Analog sensor for Y axis + +int range = 12; // Output range of X or Y movement +int responseDelay = 2; // Response delay of the mouse, in ms +int threshold = range / 4; // Resting threshold +int center = range / 2; // Resting position value +int minima[] = {1023, 1023}; // Actual analogRead minima for (x, y) +int maxima[] = {0, 0}; // Actual analogRead maxima for (x, y) +int axis[] = {xAxis, yAxis}; // Pin numbers for (x, y) +int mouseReading[2]; // Final mouse readings for (x, y) + +void setup() { + // Initialize the Mouse library + Mouse.begin(); +} + +void loop() { + // Read and scale the two axes + int xReading = readAxis(0); + int yReading = readAxis(1); + + // Move the mouse + Mouse.move(xReading, yReading, 0); + delay(responseDelay); +} + +/* + Reads an axis (0 or 1 for x or y) and scales the + analog input range to a range from 0 to +*/ +int readAxis(int axisNumber) { + int distance = 0; // Distance from center of the output range + + // Read the analog input + int reading = analogRead(axis[axisNumber]); + + // Of the current reading exceeds the max or min for this axis, reset the max or min + if (reading < minima[axisNumber]) { + minima[axisNumber] = reading; + } + if (reading > maxima[axisNumber]) { + maxima[axisNumber] = reading; + } + + // Map the reading from the analog input range to the output range + reading = map(reading, minima[axisNumber], maxima[axisNumber], 0, range); + + // If the output reading is outside from the rest position threshold, use it + if (abs(reading - center) > threshold) { + distance = (reading - center); + } + + // The Y axis needs to be inverted in order to map the movement correctly + if (axisNumber == 1) { + distance = -distance; + } + + // Return the distance for this axis + return distance; +} +``` + +#### Notes and warnings + +When you use the `Mouse.move()` command, the Arduino takes over your mouse! Make sure you have control before you use the command. A pushbutton to toggle the mouse control state is effective. + +#### See also + +* [Mouse.begin()](#mousebegin) +* [Mouse.click()](#mouseclick) +* [Mouse.end()](#mouseend) +* [Mouse.press()](#mousepress) +* [Mouse.release()](#mouserelease) +* [Mouse.isPressed()](#mouseispressed) + +### `Mouse.press()` + +Sends a button press to a connected computer. A press is the equivalent of clicking and continuously holding the mouse button. A press is cancelled with `Mouse.release()`. Before using `Mouse.press()`, you need to start communication with `Mouse.begin()`. `Mouse.press()` defaults to a left button press. + +#### Syntax + +``` +Mouse.press() +Mouse.press(button) +``` + +#### Parameters + +* `button`: which mouse button to press (MOUSE_LEFT, MOUSE_RIGHT or MOUSE_MIDDLE, default is MOUSE_LEFT). + +#### Returns + +None. + +#### Example + +``` +#include + +void setup() { + // The switch that will initiate the Mouse press + pinMode(2, INPUT); + // The switch that will terminate the Mouse press + pinMode(3, INPUT); + // Initialize the Mouse library + Mouse.begin(); +} + +void loop() { + // If the switch attached to pin 2 is closed, press and hold the left mouse button + if (digitalRead(2) == HIGH) { + Mouse.press(); + } + // If the switch attached to pin 3 is closed, release the left mouse button + if (digitalRead(3) == HIGH) { + Mouse.release(); + } +} +``` + +#### Notes and warnings + +When you use the `Mouse.press()` command, the Arduino takes over your mouse! Make sure you have control before you use the command. A pushbutton to toggle the mouse control state is effective. + +#### See also + +* [Mouse.begin()](#mousebegin) +* [Mouse.click()](#mouseclick) +* [Mouse.end()](#mouseend) +* [Mouse.move()](#mousemove) +* [Mouse.release()](#mouserelease) +* [Mouse.isPressed()](#mouseispressed) + +### `Mouse.release()` + +Sends a message that a previously pressed button (invoked through `Mouse.press()`) is released. `Mouse.release()` defaults to the left button. + +#### Syntax + +``` +Mouse.press() +Mouse.press(button) +``` + +#### Parameters + +* `button`: which mouse button was released (MOUSE_LEFT, MOUSE_RIGHT or MOUSE_MIDDLE, default is MOUSE_LEFT). + +#### Returns + +None. + +#### Example + +``` +#include + +void setup() { + // The switch that will initiate the Mouse press + pinMode(2, INPUT); + // The switch that will terminate the Mouse press + pinMode(3, INPUT); + // Initialize the Mouse library + Mouse.begin(); +} + +void loop() { + // If the switch attached to pin 2 is closed, press and hold the left mouse button + if (digitalRead(2) == HIGH) { + Mouse.press(); + } + // If the switch attached to pin 3 is closed, release the left mouse button + if (digitalRead(3) == HIGH) { + Mouse.release(); + } +} +``` + +#### Notes and warnings + +When you use the `Mouse.release()` command, the Arduino takes over your mouse! Make sure you have control before you use the command. A pushbutton to toggle the mouse control state is effective. + +#### See also + +* [Mouse.begin()](#mousebegin) +* [Mouse.click()](#mouseclick) +* [Mouse.end()](#mouseend) +* [Mouse.move()](#mousemove) +* [Mouse.press()](#mousepress) +* [Mouse.isPressed()](#mouseispressed) + +### `Mouse.isPressed()` + +Checks the current status of all mouse buttons, and reports if any are pressed or not. By default, it checks the status of the left mouse button. + +#### Syntax + +``` +Mouse.isPressed(); +Mouse.isPressed(button); +``` + +#### Parameters + +* `button`: which mouse button was released (MOUSE_LEFT, MOUSE_RIGHT or MOUSE_MIDDLE, default is MOUSE_LEFT). + +#### Returns + +1 if a button was pressed, 0 if a not. + +#### Example + +``` +#include + +void setup() { + // The switch that will initiate the Mouse press + pinMode(2, INPUT); + // The switch that will terminate the Mouse press + pinMode(3, INPUT); + // Start serial communication with the computer + Serial.begin(9600); + // Initialize the Mouse library + Mouse.begin(); +} + +void loop() { + // A variable for checking the button's state + int mouseState = 0; + // If the switch attached to pin 2 is closed, press and hold the left mouse button and save the state ina variable + if (digitalRead(2) == HIGH) { + Mouse.press(); + mouseState = Mouse.isPressed(); + } + // If the switch attached to pin 3 is closed, release the left mouse button and save the state in a variable + if (digitalRead(3) == HIGH) { + Mouse.release(); + mouseState = Mouse.isPressed(); + } + // Print out the current mouse button state + Serial.println(mouseState); + delay(10); +} +``` + +#### See also + +* [Mouse.begin()](#mousebegin) +* [Mouse.click()](#mouseclick) +* [Mouse.end()](#mouseend) +* [Mouse.move()](#mousemove) +* [Mouse.press()](#mousepress) +* [Mouse.release()](#mouserelease) \ No newline at end of file diff --git a/libraries/MouseAbsolute/docs/readme.md b/libraries/MouseAbsolute/docs/readme.md new file mode 100644 index 000000000..f2f50bd6a --- /dev/null +++ b/libraries/MouseAbsolute/docs/readme.md @@ -0,0 +1,23 @@ +# Mouse library + +The mouse functions enable 32u4 or SAMD micro based boards to control cursor movement on a connected computer through their micro’s native USB port. When updating the cursor position, it is always relative to the cursor’s previous location. + +To use this library: + +``` +#include +``` + +## Notes and warnings + +These core libraries allow the 32u4 and SAMD based boards (Leonardo, Esplora, Zero, Due and MKR Family) to appear as a native Mouse and/or Keyboard to a connected computer. + +**A word of caution on using the Mouse and Keyboard libraries**: if the Mouse or Keyboard library is constantly running, it will be difficult to program your board. Functions such as `Mouse.move()` and `Keyboard.print()` will move your cursor or send keystrokes to a connected computer and should only be called when you are ready to handle them. It is recommended to use a control system to turn this functionality on, like a physical switch or only responding to specific input you can control. Refer to the Mouse and Keyboard examples for some ways to handle this. + +When using the Mouse or Keyboard library, it may be best to test your output first using `Serial.print()`. This way, you can be sure you know what values are being reported. + +## Examples + +* [KeyboardAndMouseControl](https://www.arduino.cc/en/Tutorial/BuiltInExamples/KeyboardAndMouseControl): Demonstrates the Mouse and Keyboard commands in one program. +* [ButtonMouseControl](https://www.arduino.cc/en/Tutorial/BuiltInExamples/ButtonMouseControl): Control cursor movement with 5 pushbuttons. +* [JoystickMouseControl](https://www.arduino.cc/en/Tutorial/BuiltInExamples/JoystickMouseControl): Controls a computer’s cursor movement with a Joystick when a button is pressed. \ No newline at end of file diff --git a/libraries/MouseAbsolute/examples/CircleAbsolute/CircleAbsolute.ino b/libraries/MouseAbsolute/examples/CircleAbsolute/CircleAbsolute.ino new file mode 100644 index 000000000..06f9f60a7 --- /dev/null +++ b/libraries/MouseAbsolute/examples/CircleAbsolute/CircleAbsolute.ino @@ -0,0 +1,32 @@ +/* Earle F. Philhower, III */ +/* Released to the public domain */ + + +#include + +void setup() { + Serial.begin(115200); + MouseAbsolute.begin(); + delay(5000); + Serial.printf("Press BOOTSEL to move the mouse in a series of circles\n"); +} + +void loop() { + if (BOOTSEL) { + Serial.println("BARREL ROLLS!!!"); + float r = 1000; + for (float cx = 1000; cx <= 16000; cx += 4000) { + for (float cy = 1000; cy <= 16000; cy += 4000) { + for (float a = 0; a < 2.0 * 3.14159; a += 0.1) { + float ax = r * cos(a); + float ay = r * sin(a); + MouseAbsolute.move(ax + cx, ay + cy, 0); + delay(10); + } + } + } + while (BOOTSEL) { + delay(1); + } + } +} diff --git a/libraries/MouseAbsolute/keywords.txt b/libraries/MouseAbsolute/keywords.txt new file mode 100644 index 000000000..58e0d1ea1 --- /dev/null +++ b/libraries/MouseAbsolute/keywords.txt @@ -0,0 +1,24 @@ +####################################### +# Syntax Coloring Map +####################################### + +####################################### +# Datatypes (KEYWORD1) +####################################### + +MouseAbsolute KEYWORD1 + +####################################### +# Methods and Functions (KEYWORD2) +####################################### + +begin KEYWORD2 +click KEYWORD2 +move KEYWORD2 +press KEYWORD2 +release KEYWORD2 +isPressed KEYWORD2 + +####################################### +# Constants (LITERAL1) +####################################### diff --git a/libraries/MouseAbsolute/library.properties b/libraries/MouseAbsolute/library.properties new file mode 100644 index 000000000..7b5d5cb26 --- /dev/null +++ b/libraries/MouseAbsolute/library.properties @@ -0,0 +1,9 @@ +name=MouseAbsolute +version=1.0.1 +author=Arduino and EFP3 +maintainer=Earle F. Philhower, III +sentence=Allows an Arduino board with USB capabilities to act as a Mouse. +paragraph=Allows the RP2040 to emulate a USB mouse +category=Device Control +url=https://www.arduino.cc/reference/en/language/functions/usb/mouse/ +architectures=rp2040 diff --git a/libraries/MouseAbsolute/src/MouseAbsolute.cpp b/libraries/MouseAbsolute/src/MouseAbsolute.cpp new file mode 100644 index 000000000..b57e0d49f --- /dev/null +++ b/libraries/MouseAbsolute/src/MouseAbsolute.cpp @@ -0,0 +1,45 @@ +/* + Mouse.cpp + + Copyright (c) 2015, Arduino LLC + Original code (pre-library): Copyright (c) 2011, Peter Barrett + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include "MouseAbsolute.h" +#include + +#include "tusb.h" +#include "class/hid/hid_device.h" +#include + +// Weak function override to add our descriptor to the TinyUSB list +void __USBInstallAbsoluteMouse() { /* noop */ } + +MouseAbsolute_::MouseAbsolute_(void) : HID_Mouse(true) { + /* noop */ +} + +void MouseAbsolute_::move(int x, int y, signed char wheel) { + CoreMutex m(&__usb_mutex); + tud_task(); + if (tud_hid_ready()) { + tud_hid_abs_mouse_report(__USBGetMouseReportID(), _buttons, limit_xy(x), limit_xy(y), wheel, 0); + } + tud_task(); +} + +MouseAbsolute_ MouseAbsolute; diff --git a/libraries/MouseAbsolute/src/MouseAbsolute.h b/libraries/MouseAbsolute/src/MouseAbsolute.h new file mode 100644 index 000000000..44165134a --- /dev/null +++ b/libraries/MouseAbsolute/src/MouseAbsolute.h @@ -0,0 +1,34 @@ +/* + Mouse.h + + Copyright (c) 2015, Arduino LLC + Original code (pre-library): Copyright (c) 2011, Peter Barrett + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#ifndef MOUSEABSOLUTE_h +#define MOUSEABSOLUTE_h + +#include + +class MouseAbsolute_ : public HID_Mouse { +public: + MouseAbsolute_(void); + virtual void move(int x, int y, signed char wheel = 0) override; +}; +extern MouseAbsolute_ MouseAbsolute; + +#endif diff --git a/libraries/MouseBLE/README.adoc b/libraries/MouseBLE/README.adoc new file mode 100644 index 000000000..c9df074f8 --- /dev/null +++ b/libraries/MouseBLE/README.adoc @@ -0,0 +1,31 @@ +:repository-owner: arduino-libraries +:repository-name: Mouse + += {repository-name} Library for Arduino = + +image:https://github.com/{repository-owner}/{repository-name}/actions/workflows/check-arduino.yml/badge.svg["Check Arduino status", link="https://github.com/{repository-owner}/{repository-name}/actions/workflows/check-arduino.yml"] +image:https://github.com/{repository-owner}/{repository-name}/actions/workflows/compile-examples.yml/badge.svg["Compile Examples status", link="https://github.com/{repository-owner}/{repository-name}/actions/workflows/compile-examples.yml"] +image:https://github.com/{repository-owner}/{repository-name}/actions/workflows/spell-check.yml/badge.svg["Spell Check status", link="https://github.com/{repository-owner}/{repository-name}/actions/workflows/spell-check.yml"] + +This library allows an Arduino board with USB capabilities to act as a Mouse. + +For more information about this library please visit us at +https://www.arduino.cc/reference/en/language/functions/usb/mouse/ + +== License == + +Copyright (c) Arduino LLC. All right reserved. + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA diff --git a/libraries/MouseBLE/docs/api.md b/libraries/MouseBLE/docs/api.md new file mode 100644 index 000000000..99bee66e1 --- /dev/null +++ b/libraries/MouseBLE/docs/api.md @@ -0,0 +1,428 @@ +# Mouse library + +## Methods + +### `Mouse.begin()` + +Begins emulating the mouse connected to a computer. `begin()` must be called before controlling the computer. To end control, use `Mouse.end()`. + +#### Syntax + +``` +Mouse.begin() +``` + +#### Parameters + +None. + +#### Returns + +None. + +#### Example + +``` +#include + +void setup() { + pinMode(2, INPUT); +} + +void loop() { + // Initialize the Mouse library when button is pressed + if (digitalRead(2) == HIGH) { + Mouse.begin(); + } +} +``` + +#### See also + +* [Mouse.click()](#mouseclick) +* [Mouse.end()](#mouseend) +* [Mouse.move()](#mousemove) +* [Mouse.press()](#mousepress) +* [Mouse.release()](#mouserelease) +* [Mouse.isPressed()](#mouseispressed) + +### `Mouse.click()` + +Sends a momentary click to the computer at the location of the cursor. This is the same as pressing and immediately releasing the mouse button. + +`Mouse.click()` defaults to the left mouse button. + +#### Syntax + +``` +Mouse.click() +Mouse.click(button) +``` + +#### Parameters + +* `button`: which mouse button to press (MOUSE_LEFT, MOUSE_RIGHT or MOUSE_MIDDLE, default is MOUSE_LEFT). + +#### Returns + +None. + +#### Example + +``` +#include + +void setup() { + pinMode(2, INPUT); + // Initialize the Mouse library + Mouse.begin(); +} + +void loop() { + // If the button is pressed, send a left mouse click + if (digitalRead(2) == HIGH) { + Mouse.click(); + } +} +``` + +#### Notes and warnings + +When you use the `Mouse.click()` command, the Arduino takes over your mouse! Make sure you have control before you use the command. A pushbutton to toggle the mouse control state is effective. + +#### See also + +* [Mouse.begin()](#mousebegin) +* [Mouse.end()](#mouseend) +* [Mouse.move()](#mousemove) +* [Mouse.press()](#mousepress) +* [Mouse.release()](#mouserelease) +* [Mouse.isPressed()](#mouseispressed) + +### `Mouse.end()` + +Stops emulating the mouse connected to a computer. To start control, use `Mouse.begin()`. + +#### Syntax + +``` +Mouse.end() +``` + +#### Parameters + +None. + +#### Returns + +None. + +#### Example + +``` +#include + +void setup() { + pinMode(2, INPUT); + // Initiate the Mouse library + Mouse.begin(); +} + +void loop() { + // If the button is pressed, send a left mouse click + if (digitalRead(2) == HIGH) { + Mouse.click(); + // Then end the Mouse emulation + Mouse.end(); + } +} +``` + +#### See also + +* [Mouse.begin()](#mousebegin) +* [Mouse.click()](#mouseclick) +* [Mouse.move()](#mousemove) +* [Mouse.press()](#mousepress) +* [Mouse.release()](#mouserelease) +* [Mouse.isPressed()](#mouseispressed) + +### `Mouse.move()` + +Moves the cursor on a connected computer. The motion onscreen is always relative to the cursor’s current location. Before using `Mouse.move()` you must call `Mouse.begin()`. + +#### Syntax + +``` +Mouse.move(xVal, yVal, wheel) +``` + +#### Parameters + +* `xVal`: amount to move along the x-axis. Allowed data types: signed char. +* `yVal`: amount to move along the y-axis. Allowed data types: signed char. +* `wheel`: amount to move scroll wheel. Allowed data types: signed char. + +#### Returns + +None. + +#### Example + +``` +#include + +const int xAxis = A1; // Analog sensor for X axis +const int yAxis = A2; // Analog sensor for Y axis + +int range = 12; // Output range of X or Y movement +int responseDelay = 2; // Response delay of the mouse, in ms +int threshold = range / 4; // Resting threshold +int center = range / 2; // Resting position value +int minima[] = {1023, 1023}; // Actual analogRead minima for (x, y) +int maxima[] = {0, 0}; // Actual analogRead maxima for (x, y) +int axis[] = {xAxis, yAxis}; // Pin numbers for (x, y) +int mouseReading[2]; // Final mouse readings for (x, y) + +void setup() { + // Initialize the Mouse library + Mouse.begin(); +} + +void loop() { + // Read and scale the two axes + int xReading = readAxis(0); + int yReading = readAxis(1); + + // Move the mouse + Mouse.move(xReading, yReading, 0); + delay(responseDelay); +} + +/* + Reads an axis (0 or 1 for x or y) and scales the + analog input range to a range from 0 to +*/ +int readAxis(int axisNumber) { + int distance = 0; // Distance from center of the output range + + // Read the analog input + int reading = analogRead(axis[axisNumber]); + + // Of the current reading exceeds the max or min for this axis, reset the max or min + if (reading < minima[axisNumber]) { + minima[axisNumber] = reading; + } + if (reading > maxima[axisNumber]) { + maxima[axisNumber] = reading; + } + + // Map the reading from the analog input range to the output range + reading = map(reading, minima[axisNumber], maxima[axisNumber], 0, range); + + // If the output reading is outside from the rest position threshold, use it + if (abs(reading - center) > threshold) { + distance = (reading - center); + } + + // The Y axis needs to be inverted in order to map the movement correctly + if (axisNumber == 1) { + distance = -distance; + } + + // Return the distance for this axis + return distance; +} +``` + +#### Notes and warnings + +When you use the `Mouse.move()` command, the Arduino takes over your mouse! Make sure you have control before you use the command. A pushbutton to toggle the mouse control state is effective. + +#### See also + +* [Mouse.begin()](#mousebegin) +* [Mouse.click()](#mouseclick) +* [Mouse.end()](#mouseend) +* [Mouse.press()](#mousepress) +* [Mouse.release()](#mouserelease) +* [Mouse.isPressed()](#mouseispressed) + +### `Mouse.press()` + +Sends a button press to a connected computer. A press is the equivalent of clicking and continuously holding the mouse button. A press is cancelled with `Mouse.release()`. Before using `Mouse.press()`, you need to start communication with `Mouse.begin()`. `Mouse.press()` defaults to a left button press. + +#### Syntax + +``` +Mouse.press() +Mouse.press(button) +``` + +#### Parameters + +* `button`: which mouse button to press (MOUSE_LEFT, MOUSE_RIGHT or MOUSE_MIDDLE, default is MOUSE_LEFT). + +#### Returns + +None. + +#### Example + +``` +#include + +void setup() { + // The switch that will initiate the Mouse press + pinMode(2, INPUT); + // The switch that will terminate the Mouse press + pinMode(3, INPUT); + // Initialize the Mouse library + Mouse.begin(); +} + +void loop() { + // If the switch attached to pin 2 is closed, press and hold the left mouse button + if (digitalRead(2) == HIGH) { + Mouse.press(); + } + // If the switch attached to pin 3 is closed, release the left mouse button + if (digitalRead(3) == HIGH) { + Mouse.release(); + } +} +``` + +#### Notes and warnings + +When you use the `Mouse.press()` command, the Arduino takes over your mouse! Make sure you have control before you use the command. A pushbutton to toggle the mouse control state is effective. + +#### See also + +* [Mouse.begin()](#mousebegin) +* [Mouse.click()](#mouseclick) +* [Mouse.end()](#mouseend) +* [Mouse.move()](#mousemove) +* [Mouse.release()](#mouserelease) +* [Mouse.isPressed()](#mouseispressed) + +### `Mouse.release()` + +Sends a message that a previously pressed button (invoked through `Mouse.press()`) is released. `Mouse.release()` defaults to the left button. + +#### Syntax + +``` +Mouse.press() +Mouse.press(button) +``` + +#### Parameters + +* `button`: which mouse button was released (MOUSE_LEFT, MOUSE_RIGHT or MOUSE_MIDDLE, default is MOUSE_LEFT). + +#### Returns + +None. + +#### Example + +``` +#include + +void setup() { + // The switch that will initiate the Mouse press + pinMode(2, INPUT); + // The switch that will terminate the Mouse press + pinMode(3, INPUT); + // Initialize the Mouse library + Mouse.begin(); +} + +void loop() { + // If the switch attached to pin 2 is closed, press and hold the left mouse button + if (digitalRead(2) == HIGH) { + Mouse.press(); + } + // If the switch attached to pin 3 is closed, release the left mouse button + if (digitalRead(3) == HIGH) { + Mouse.release(); + } +} +``` + +#### Notes and warnings + +When you use the `Mouse.release()` command, the Arduino takes over your mouse! Make sure you have control before you use the command. A pushbutton to toggle the mouse control state is effective. + +#### See also + +* [Mouse.begin()](#mousebegin) +* [Mouse.click()](#mouseclick) +* [Mouse.end()](#mouseend) +* [Mouse.move()](#mousemove) +* [Mouse.press()](#mousepress) +* [Mouse.isPressed()](#mouseispressed) + +### `Mouse.isPressed()` + +Checks the current status of all mouse buttons, and reports if any are pressed or not. By default, it checks the status of the left mouse button. + +#### Syntax + +``` +Mouse.isPressed(); +Mouse.isPressed(button); +``` + +#### Parameters + +* `button`: which mouse button was released (MOUSE_LEFT, MOUSE_RIGHT or MOUSE_MIDDLE, default is MOUSE_LEFT). + +#### Returns + +1 if a button was pressed, 0 if a not. + +#### Example + +``` +#include + +void setup() { + // The switch that will initiate the Mouse press + pinMode(2, INPUT); + // The switch that will terminate the Mouse press + pinMode(3, INPUT); + // Start serial communication with the computer + Serial.begin(9600); + // Initialize the Mouse library + Mouse.begin(); +} + +void loop() { + // A variable for checking the button's state + int mouseState = 0; + // If the switch attached to pin 2 is closed, press and hold the left mouse button and save the state ina variable + if (digitalRead(2) == HIGH) { + Mouse.press(); + mouseState = Mouse.isPressed(); + } + // If the switch attached to pin 3 is closed, release the left mouse button and save the state in a variable + if (digitalRead(3) == HIGH) { + Mouse.release(); + mouseState = Mouse.isPressed(); + } + // Print out the current mouse button state + Serial.println(mouseState); + delay(10); +} +``` + +#### See also + +* [Mouse.begin()](#mousebegin) +* [Mouse.click()](#mouseclick) +* [Mouse.end()](#mouseend) +* [Mouse.move()](#mousemove) +* [Mouse.press()](#mousepress) +* [Mouse.release()](#mouserelease) \ No newline at end of file diff --git a/libraries/MouseBLE/docs/readme.md b/libraries/MouseBLE/docs/readme.md new file mode 100644 index 000000000..f2f50bd6a --- /dev/null +++ b/libraries/MouseBLE/docs/readme.md @@ -0,0 +1,23 @@ +# Mouse library + +The mouse functions enable 32u4 or SAMD micro based boards to control cursor movement on a connected computer through their micro’s native USB port. When updating the cursor position, it is always relative to the cursor’s previous location. + +To use this library: + +``` +#include +``` + +## Notes and warnings + +These core libraries allow the 32u4 and SAMD based boards (Leonardo, Esplora, Zero, Due and MKR Family) to appear as a native Mouse and/or Keyboard to a connected computer. + +**A word of caution on using the Mouse and Keyboard libraries**: if the Mouse or Keyboard library is constantly running, it will be difficult to program your board. Functions such as `Mouse.move()` and `Keyboard.print()` will move your cursor or send keystrokes to a connected computer and should only be called when you are ready to handle them. It is recommended to use a control system to turn this functionality on, like a physical switch or only responding to specific input you can control. Refer to the Mouse and Keyboard examples for some ways to handle this. + +When using the Mouse or Keyboard library, it may be best to test your output first using `Serial.print()`. This way, you can be sure you know what values are being reported. + +## Examples + +* [KeyboardAndMouseControl](https://www.arduino.cc/en/Tutorial/BuiltInExamples/KeyboardAndMouseControl): Demonstrates the Mouse and Keyboard commands in one program. +* [ButtonMouseControl](https://www.arduino.cc/en/Tutorial/BuiltInExamples/ButtonMouseControl): Control cursor movement with 5 pushbuttons. +* [JoystickMouseControl](https://www.arduino.cc/en/Tutorial/BuiltInExamples/JoystickMouseControl): Controls a computer’s cursor movement with a Joystick when a button is pressed. \ No newline at end of file diff --git a/libraries/MouseBLE/examples/BLECircle/BLECircle.ino b/libraries/MouseBLE/examples/BLECircle/BLECircle.ino new file mode 100644 index 000000000..dc7942a21 --- /dev/null +++ b/libraries/MouseBLE/examples/BLECircle/BLECircle.ino @@ -0,0 +1,34 @@ +/* Earle F. Philhower, III */ +/* Released to the public domain */ + +#include + +void setup() { + Serial.begin(115200); + MouseBLE.begin("CircleBLE Mouse"); + delay(5000); + Serial.printf("Press BOOTSEL to move the mouse in a circle\n"); +} + +void loop() { + if (BOOTSEL) { + Serial.println("BARREL ROLL!!!"); + float r = 100; + float ox = 0.0; + float oy = 0.0; + for (float a = 0; a < 2.0 * 3.14159; a += 0.1) { + float ax = r * cos(a); + float ay = r * sin(a); + float dx = ax - ox; + float dy = ay - oy; + MouseBLE.move(dx, dy, 0); + ox = ax; + oy = ay; + delay(10); + } + MouseBLE.setBattery(random(0, 101)); // Set between 0...100% + while (BOOTSEL) { + delay(1); + } + } +} diff --git a/libraries/MouseBLE/examples/BLECircleAbsolute/BLECircleAbsolute.ino b/libraries/MouseBLE/examples/BLECircleAbsolute/BLECircleAbsolute.ino new file mode 100644 index 000000000..598fcbdd9 --- /dev/null +++ b/libraries/MouseBLE/examples/BLECircleAbsolute/BLECircleAbsolute.ino @@ -0,0 +1,33 @@ +/* Earle F. Philhower, III */ +/* Released to the public domain */ + +#include + +void setup() { + Serial.begin(115200); + MouseBLE.setAbsolute(true); + MouseBLE.begin("CircleBLE Mouse"); + delay(5000); + Serial.printf("Press BOOTSEL to move the mouse in a circle\n"); +} + +void loop() { + if (BOOTSEL) { + Serial.println("BARREL ROLLS!!!"); + float r = 1000; + for (float cx = 1000; cx <= 16000; cx += 4000) { + for (float cy = 1000; cy <= 16000; cy += 4000) { + for (float a = 0; a < 2.0 * 3.14159; a += 0.1) { + float ax = r * cos(a); + float ay = r * sin(a); + MouseBLE.move(ax + cx, ay + cy, 0); + delay(10); + } + } + } + MouseBLE.setBattery(random(0, 101)); // Set between 0...100% + while (BOOTSEL) { + delay(1); + } + } +} diff --git a/libraries/MouseBLE/keywords.txt b/libraries/MouseBLE/keywords.txt new file mode 100644 index 000000000..8c7f78889 --- /dev/null +++ b/libraries/MouseBLE/keywords.txt @@ -0,0 +1,26 @@ +####################################### +# Syntax Coloring Map +####################################### + +####################################### +# Datatypes (KEYWORD1) +####################################### + +MouseBLE KEYWORD1 + +####################################### +# Methods and Functions (KEYWORD2) +####################################### + +begin KEYWORD2 +click KEYWORD2 +move KEYWORD2 +press KEYWORD2 +release KEYWORD2 +isPressed KEYWORD2 +setBattery KEYWORD2 +setAbsolute KEYWORD2 + +####################################### +# Constants (LITERAL1) +####################################### diff --git a/libraries/MouseBLE/library.properties b/libraries/MouseBLE/library.properties new file mode 100644 index 000000000..2b0cda7f8 --- /dev/null +++ b/libraries/MouseBLE/library.properties @@ -0,0 +1,9 @@ +name=MouseBLE +version=1.0.1 +author=Arduino and EFP3 +maintainer=Earle F. Philhower, III +sentence=Allows an Arduino board with USB capabilities to act as a Mouse. +paragraph=Allows the RP2040 to emulate a USB mouse over BLE +category=Device Control +url=https://www.arduino.cc/reference/en/language/functions/usb/mouse/ +architectures=rp2040 diff --git a/libraries/MouseBLE/src/MouseBLE.cpp b/libraries/MouseBLE/src/MouseBLE.cpp new file mode 100644 index 000000000..d29949f45 --- /dev/null +++ b/libraries/MouseBLE/src/MouseBLE.cpp @@ -0,0 +1,83 @@ +/* + MouseBLE.cpp + + Copyright (c) 2015, Arduino LLC + Original code (pre-library): Copyright (c) 2011, Peter Barrett + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include "MouseBLE.h" +#include +#include + +MouseBLE_::MouseBLE_(bool absolute) : HID_Mouse(absolute) { + _running = false; +} + +#define REPORT_ID 0x01 +const uint8_t desc_mouse[] = {TUD_HID_REPORT_DESC_MOUSE(HID_REPORT_ID(REPORT_ID))}; +const uint8_t desc_absmouse[] = {TUD_HID_REPORT_DESC_ABSMOUSE(HID_REPORT_ID(REPORT_ID))}; +void MouseBLE_::begin(const char *localName, const char *hidName) { + if (!localName) { + localName = "PicoW BLE Mouse"; + } + if (!hidName) { + hidName = localName; + } + PicoBluetoothBLEHID.startHID(localName, hidName, 0x03c2, _absolute ? desc_absmouse : desc_mouse, _absolute ? sizeof(desc_absmouse) : sizeof(desc_mouse)); + _running = true; +} + +void MouseBLE_::end(void) { + if (_running) { + PicoBluetoothBLEHID.end(); + } + _running = false; +} + +void MouseBLE_::setBattery(int lvl) { + if (_running) { + PicoBluetoothBLEHID.setBattery(lvl); + } +} + +void MouseBLE_::setAbsolute(bool absolute) { + if (!_running) { + _absolute = absolute; + } +} + +void MouseBLE_::move(int x, int y, signed char wheel) { + if (!_absolute) { + hid_mouse_report_t data; + data.buttons = _buttons; + data.x = limit_xy(x); + data.y = limit_xy(y); + data.wheel = wheel; + data.pan = 0; + PicoBluetoothBLEHID.send(&data, sizeof(data)); + } else { + hid_abs_mouse_report_t data; + data.buttons = _buttons; + data.x = limit_xy(x); + data.y = limit_xy(y); + data.wheel = wheel; + data.pan = 0; + PicoBluetoothBLEHID.send(&data, sizeof(data)); + } +} + +MouseBLE_ MouseBLE; diff --git a/libraries/MouseBLE/src/MouseBLE.h b/libraries/MouseBLE/src/MouseBLE.h new file mode 100644 index 000000000..71c79c16d --- /dev/null +++ b/libraries/MouseBLE/src/MouseBLE.h @@ -0,0 +1,41 @@ +/* + MouseBLE.h + + Copyright (c) 2015, Arduino LLC + Original code (pre-library): Copyright (c) 2011, Peter Barrett + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#ifndef MOUSEBLE_h +#define MOUSEBLE_h + +#include + +class MouseBLE_ : public HID_Mouse { +private: + bool _running; + +public: + MouseBLE_(bool absolute = false); + void begin(const char *localName = nullptr, const char *hidName = nullptr); + void end(void); + virtual void move(int x, int y, signed char wheel = 0) override; + void setBattery(int lvl); + void setAbsolute(bool absolute = true); +}; +extern MouseBLE_ MouseBLE; + +#endif diff --git a/libraries/MouseBT/README.adoc b/libraries/MouseBT/README.adoc new file mode 100644 index 000000000..c9df074f8 --- /dev/null +++ b/libraries/MouseBT/README.adoc @@ -0,0 +1,31 @@ +:repository-owner: arduino-libraries +:repository-name: Mouse + += {repository-name} Library for Arduino = + +image:https://github.com/{repository-owner}/{repository-name}/actions/workflows/check-arduino.yml/badge.svg["Check Arduino status", link="https://github.com/{repository-owner}/{repository-name}/actions/workflows/check-arduino.yml"] +image:https://github.com/{repository-owner}/{repository-name}/actions/workflows/compile-examples.yml/badge.svg["Compile Examples status", link="https://github.com/{repository-owner}/{repository-name}/actions/workflows/compile-examples.yml"] +image:https://github.com/{repository-owner}/{repository-name}/actions/workflows/spell-check.yml/badge.svg["Spell Check status", link="https://github.com/{repository-owner}/{repository-name}/actions/workflows/spell-check.yml"] + +This library allows an Arduino board with USB capabilities to act as a Mouse. + +For more information about this library please visit us at +https://www.arduino.cc/reference/en/language/functions/usb/mouse/ + +== License == + +Copyright (c) Arduino LLC. All right reserved. + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA diff --git a/libraries/MouseBT/docs/api.md b/libraries/MouseBT/docs/api.md new file mode 100644 index 000000000..99bee66e1 --- /dev/null +++ b/libraries/MouseBT/docs/api.md @@ -0,0 +1,428 @@ +# Mouse library + +## Methods + +### `Mouse.begin()` + +Begins emulating the mouse connected to a computer. `begin()` must be called before controlling the computer. To end control, use `Mouse.end()`. + +#### Syntax + +``` +Mouse.begin() +``` + +#### Parameters + +None. + +#### Returns + +None. + +#### Example + +``` +#include + +void setup() { + pinMode(2, INPUT); +} + +void loop() { + // Initialize the Mouse library when button is pressed + if (digitalRead(2) == HIGH) { + Mouse.begin(); + } +} +``` + +#### See also + +* [Mouse.click()](#mouseclick) +* [Mouse.end()](#mouseend) +* [Mouse.move()](#mousemove) +* [Mouse.press()](#mousepress) +* [Mouse.release()](#mouserelease) +* [Mouse.isPressed()](#mouseispressed) + +### `Mouse.click()` + +Sends a momentary click to the computer at the location of the cursor. This is the same as pressing and immediately releasing the mouse button. + +`Mouse.click()` defaults to the left mouse button. + +#### Syntax + +``` +Mouse.click() +Mouse.click(button) +``` + +#### Parameters + +* `button`: which mouse button to press (MOUSE_LEFT, MOUSE_RIGHT or MOUSE_MIDDLE, default is MOUSE_LEFT). + +#### Returns + +None. + +#### Example + +``` +#include + +void setup() { + pinMode(2, INPUT); + // Initialize the Mouse library + Mouse.begin(); +} + +void loop() { + // If the button is pressed, send a left mouse click + if (digitalRead(2) == HIGH) { + Mouse.click(); + } +} +``` + +#### Notes and warnings + +When you use the `Mouse.click()` command, the Arduino takes over your mouse! Make sure you have control before you use the command. A pushbutton to toggle the mouse control state is effective. + +#### See also + +* [Mouse.begin()](#mousebegin) +* [Mouse.end()](#mouseend) +* [Mouse.move()](#mousemove) +* [Mouse.press()](#mousepress) +* [Mouse.release()](#mouserelease) +* [Mouse.isPressed()](#mouseispressed) + +### `Mouse.end()` + +Stops emulating the mouse connected to a computer. To start control, use `Mouse.begin()`. + +#### Syntax + +``` +Mouse.end() +``` + +#### Parameters + +None. + +#### Returns + +None. + +#### Example + +``` +#include + +void setup() { + pinMode(2, INPUT); + // Initiate the Mouse library + Mouse.begin(); +} + +void loop() { + // If the button is pressed, send a left mouse click + if (digitalRead(2) == HIGH) { + Mouse.click(); + // Then end the Mouse emulation + Mouse.end(); + } +} +``` + +#### See also + +* [Mouse.begin()](#mousebegin) +* [Mouse.click()](#mouseclick) +* [Mouse.move()](#mousemove) +* [Mouse.press()](#mousepress) +* [Mouse.release()](#mouserelease) +* [Mouse.isPressed()](#mouseispressed) + +### `Mouse.move()` + +Moves the cursor on a connected computer. The motion onscreen is always relative to the cursor’s current location. Before using `Mouse.move()` you must call `Mouse.begin()`. + +#### Syntax + +``` +Mouse.move(xVal, yVal, wheel) +``` + +#### Parameters + +* `xVal`: amount to move along the x-axis. Allowed data types: signed char. +* `yVal`: amount to move along the y-axis. Allowed data types: signed char. +* `wheel`: amount to move scroll wheel. Allowed data types: signed char. + +#### Returns + +None. + +#### Example + +``` +#include + +const int xAxis = A1; // Analog sensor for X axis +const int yAxis = A2; // Analog sensor for Y axis + +int range = 12; // Output range of X or Y movement +int responseDelay = 2; // Response delay of the mouse, in ms +int threshold = range / 4; // Resting threshold +int center = range / 2; // Resting position value +int minima[] = {1023, 1023}; // Actual analogRead minima for (x, y) +int maxima[] = {0, 0}; // Actual analogRead maxima for (x, y) +int axis[] = {xAxis, yAxis}; // Pin numbers for (x, y) +int mouseReading[2]; // Final mouse readings for (x, y) + +void setup() { + // Initialize the Mouse library + Mouse.begin(); +} + +void loop() { + // Read and scale the two axes + int xReading = readAxis(0); + int yReading = readAxis(1); + + // Move the mouse + Mouse.move(xReading, yReading, 0); + delay(responseDelay); +} + +/* + Reads an axis (0 or 1 for x or y) and scales the + analog input range to a range from 0 to +*/ +int readAxis(int axisNumber) { + int distance = 0; // Distance from center of the output range + + // Read the analog input + int reading = analogRead(axis[axisNumber]); + + // Of the current reading exceeds the max or min for this axis, reset the max or min + if (reading < minima[axisNumber]) { + minima[axisNumber] = reading; + } + if (reading > maxima[axisNumber]) { + maxima[axisNumber] = reading; + } + + // Map the reading from the analog input range to the output range + reading = map(reading, minima[axisNumber], maxima[axisNumber], 0, range); + + // If the output reading is outside from the rest position threshold, use it + if (abs(reading - center) > threshold) { + distance = (reading - center); + } + + // The Y axis needs to be inverted in order to map the movement correctly + if (axisNumber == 1) { + distance = -distance; + } + + // Return the distance for this axis + return distance; +} +``` + +#### Notes and warnings + +When you use the `Mouse.move()` command, the Arduino takes over your mouse! Make sure you have control before you use the command. A pushbutton to toggle the mouse control state is effective. + +#### See also + +* [Mouse.begin()](#mousebegin) +* [Mouse.click()](#mouseclick) +* [Mouse.end()](#mouseend) +* [Mouse.press()](#mousepress) +* [Mouse.release()](#mouserelease) +* [Mouse.isPressed()](#mouseispressed) + +### `Mouse.press()` + +Sends a button press to a connected computer. A press is the equivalent of clicking and continuously holding the mouse button. A press is cancelled with `Mouse.release()`. Before using `Mouse.press()`, you need to start communication with `Mouse.begin()`. `Mouse.press()` defaults to a left button press. + +#### Syntax + +``` +Mouse.press() +Mouse.press(button) +``` + +#### Parameters + +* `button`: which mouse button to press (MOUSE_LEFT, MOUSE_RIGHT or MOUSE_MIDDLE, default is MOUSE_LEFT). + +#### Returns + +None. + +#### Example + +``` +#include + +void setup() { + // The switch that will initiate the Mouse press + pinMode(2, INPUT); + // The switch that will terminate the Mouse press + pinMode(3, INPUT); + // Initialize the Mouse library + Mouse.begin(); +} + +void loop() { + // If the switch attached to pin 2 is closed, press and hold the left mouse button + if (digitalRead(2) == HIGH) { + Mouse.press(); + } + // If the switch attached to pin 3 is closed, release the left mouse button + if (digitalRead(3) == HIGH) { + Mouse.release(); + } +} +``` + +#### Notes and warnings + +When you use the `Mouse.press()` command, the Arduino takes over your mouse! Make sure you have control before you use the command. A pushbutton to toggle the mouse control state is effective. + +#### See also + +* [Mouse.begin()](#mousebegin) +* [Mouse.click()](#mouseclick) +* [Mouse.end()](#mouseend) +* [Mouse.move()](#mousemove) +* [Mouse.release()](#mouserelease) +* [Mouse.isPressed()](#mouseispressed) + +### `Mouse.release()` + +Sends a message that a previously pressed button (invoked through `Mouse.press()`) is released. `Mouse.release()` defaults to the left button. + +#### Syntax + +``` +Mouse.press() +Mouse.press(button) +``` + +#### Parameters + +* `button`: which mouse button was released (MOUSE_LEFT, MOUSE_RIGHT or MOUSE_MIDDLE, default is MOUSE_LEFT). + +#### Returns + +None. + +#### Example + +``` +#include + +void setup() { + // The switch that will initiate the Mouse press + pinMode(2, INPUT); + // The switch that will terminate the Mouse press + pinMode(3, INPUT); + // Initialize the Mouse library + Mouse.begin(); +} + +void loop() { + // If the switch attached to pin 2 is closed, press and hold the left mouse button + if (digitalRead(2) == HIGH) { + Mouse.press(); + } + // If the switch attached to pin 3 is closed, release the left mouse button + if (digitalRead(3) == HIGH) { + Mouse.release(); + } +} +``` + +#### Notes and warnings + +When you use the `Mouse.release()` command, the Arduino takes over your mouse! Make sure you have control before you use the command. A pushbutton to toggle the mouse control state is effective. + +#### See also + +* [Mouse.begin()](#mousebegin) +* [Mouse.click()](#mouseclick) +* [Mouse.end()](#mouseend) +* [Mouse.move()](#mousemove) +* [Mouse.press()](#mousepress) +* [Mouse.isPressed()](#mouseispressed) + +### `Mouse.isPressed()` + +Checks the current status of all mouse buttons, and reports if any are pressed or not. By default, it checks the status of the left mouse button. + +#### Syntax + +``` +Mouse.isPressed(); +Mouse.isPressed(button); +``` + +#### Parameters + +* `button`: which mouse button was released (MOUSE_LEFT, MOUSE_RIGHT or MOUSE_MIDDLE, default is MOUSE_LEFT). + +#### Returns + +1 if a button was pressed, 0 if a not. + +#### Example + +``` +#include + +void setup() { + // The switch that will initiate the Mouse press + pinMode(2, INPUT); + // The switch that will terminate the Mouse press + pinMode(3, INPUT); + // Start serial communication with the computer + Serial.begin(9600); + // Initialize the Mouse library + Mouse.begin(); +} + +void loop() { + // A variable for checking the button's state + int mouseState = 0; + // If the switch attached to pin 2 is closed, press and hold the left mouse button and save the state ina variable + if (digitalRead(2) == HIGH) { + Mouse.press(); + mouseState = Mouse.isPressed(); + } + // If the switch attached to pin 3 is closed, release the left mouse button and save the state in a variable + if (digitalRead(3) == HIGH) { + Mouse.release(); + mouseState = Mouse.isPressed(); + } + // Print out the current mouse button state + Serial.println(mouseState); + delay(10); +} +``` + +#### See also + +* [Mouse.begin()](#mousebegin) +* [Mouse.click()](#mouseclick) +* [Mouse.end()](#mouseend) +* [Mouse.move()](#mousemove) +* [Mouse.press()](#mousepress) +* [Mouse.release()](#mouserelease) \ No newline at end of file diff --git a/libraries/MouseBT/docs/readme.md b/libraries/MouseBT/docs/readme.md new file mode 100644 index 000000000..f2f50bd6a --- /dev/null +++ b/libraries/MouseBT/docs/readme.md @@ -0,0 +1,23 @@ +# Mouse library + +The mouse functions enable 32u4 or SAMD micro based boards to control cursor movement on a connected computer through their micro’s native USB port. When updating the cursor position, it is always relative to the cursor’s previous location. + +To use this library: + +``` +#include +``` + +## Notes and warnings + +These core libraries allow the 32u4 and SAMD based boards (Leonardo, Esplora, Zero, Due and MKR Family) to appear as a native Mouse and/or Keyboard to a connected computer. + +**A word of caution on using the Mouse and Keyboard libraries**: if the Mouse or Keyboard library is constantly running, it will be difficult to program your board. Functions such as `Mouse.move()` and `Keyboard.print()` will move your cursor or send keystrokes to a connected computer and should only be called when you are ready to handle them. It is recommended to use a control system to turn this functionality on, like a physical switch or only responding to specific input you can control. Refer to the Mouse and Keyboard examples for some ways to handle this. + +When using the Mouse or Keyboard library, it may be best to test your output first using `Serial.print()`. This way, you can be sure you know what values are being reported. + +## Examples + +* [KeyboardAndMouseControl](https://www.arduino.cc/en/Tutorial/BuiltInExamples/KeyboardAndMouseControl): Demonstrates the Mouse and Keyboard commands in one program. +* [ButtonMouseControl](https://www.arduino.cc/en/Tutorial/BuiltInExamples/ButtonMouseControl): Control cursor movement with 5 pushbuttons. +* [JoystickMouseControl](https://www.arduino.cc/en/Tutorial/BuiltInExamples/JoystickMouseControl): Controls a computer’s cursor movement with a Joystick when a button is pressed. \ No newline at end of file diff --git a/libraries/MouseBT/examples/BTCircle/BTCircle.ino b/libraries/MouseBT/examples/BTCircle/BTCircle.ino new file mode 100644 index 000000000..e4ea95af7 --- /dev/null +++ b/libraries/MouseBT/examples/BTCircle/BTCircle.ino @@ -0,0 +1,34 @@ +/* Earle F. Philhower, III */ +/* Released to the public domain */ + + +#include + +void setup() { + Serial.begin(115200); + MouseBT.begin("BarrelMouse"); + delay(5000); + Serial.printf("Press BOOTSEL to move the mouse in a circle\n"); +} + +void loop() { + if (BOOTSEL) { + Serial.println("BARREL ROLL!!!"); + float r = 100; + float ox = 0.0; + float oy = 0.0; + for (float a = 0; a < 2.0 * 3.14159; a += 0.1) { + float ax = r * cos(a); + float ay = r * sin(a); + float dx = ax - ox; + float dy = ay - oy; + MouseBT.move(dx, dy, 0); + ox = ax; + oy = ay; + delay(10); + } + while (BOOTSEL) { + delay(1); + } + } +} diff --git a/libraries/MouseBT/examples/BTCircleAbsolute/BTCircleAbsolute.ino b/libraries/MouseBT/examples/BTCircleAbsolute/BTCircleAbsolute.ino new file mode 100644 index 000000000..56f36cbfa --- /dev/null +++ b/libraries/MouseBT/examples/BTCircleAbsolute/BTCircleAbsolute.ino @@ -0,0 +1,32 @@ +/* Earle F. Philhower, III */ +/* Released to the public domain */ + +#include + +void setup() { + Serial.begin(115200); + MouseBT.setAbsolute(true); + MouseBT.begin("CircleBT Mouse"); + delay(5000); + Serial.printf("Press BOOTSEL to move the mouse in a circle\n"); +} + +void loop() { + if (BOOTSEL) { + Serial.println("BARREL ROLLS!!!"); + float r = 1000; + for (float cx = 1000; cx <= 16000; cx += 4000) { + for (float cy = 1000; cy <= 16000; cy += 4000) { + for (float a = 0; a < 2.0 * 3.14159; a += 0.1) { + float ax = r * cos(a); + float ay = r * sin(a); + MouseBT.move(ax + cx, ay + cy, 0); + delay(10); + } + } + } + while (BOOTSEL) { + delay(1); + } + } +} diff --git a/libraries/MouseBT/keywords.txt b/libraries/MouseBT/keywords.txt new file mode 100644 index 000000000..edb3caa6a --- /dev/null +++ b/libraries/MouseBT/keywords.txt @@ -0,0 +1,26 @@ +####################################### +# Syntax Coloring Map +####################################### + +####################################### +# Datatypes (KEYWORD1) +####################################### + +MouseBT KEYWORD1 + +####################################### +# Methods and Functions (KEYWORD2) +####################################### + +begin KEYWORD2 +click KEYWORD2 +move KEYWORD2 +press KEYWORD2 +release KEYWORD2 +isPressed KEYWORD2 +setAbsolute KEYWORD2 + + +####################################### +# Constants (LITERAL1) +####################################### diff --git a/libraries/MouseBT/library.properties b/libraries/MouseBT/library.properties new file mode 100644 index 000000000..b8c20f75f --- /dev/null +++ b/libraries/MouseBT/library.properties @@ -0,0 +1,9 @@ +name=MouseBT +version=1.0.1 +author=Arduino and EFP3 +maintainer=Earle F. Philhower, III +sentence=Allows an Arduino board with USB capabilities to act as a Mouse. +paragraph=Allows the RP2040 to emulate a USB mouse over BT +category=Device Control +url=https://www.arduino.cc/reference/en/language/functions/usb/mouse/ +architectures=rp2040 diff --git a/libraries/MouseBT/src/MouseBT.cpp b/libraries/MouseBT/src/MouseBT.cpp new file mode 100644 index 000000000..2a3de9e27 --- /dev/null +++ b/libraries/MouseBT/src/MouseBT.cpp @@ -0,0 +1,78 @@ +/* + MouseBT.cpp + + Copyright (c) 2015, Arduino LLC + Original code (pre-library): Copyright (c) 2011, Peter Barrett + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include "MouseBT.h" +#include +#include + +MouseBT_::MouseBT_(bool absolute) : HID_Mouse(absolute) { + _running = false; +} + +#define REPORT_ID 0x01 +const uint8_t desc_mouse[] = {TUD_HID_REPORT_DESC_MOUSE(HID_REPORT_ID(REPORT_ID))}; +const uint8_t desc_absmouse[] = {TUD_HID_REPORT_DESC_ABSMOUSE(HID_REPORT_ID(REPORT_ID))}; + +void MouseBT_::begin(const char *localName, const char *hidName) { + if (!localName) { + localName = "PicoW Mouse 00:00:00:00:00:00"; + } + if (!hidName) { + hidName = localName; + } + PicoBluetoothHID.startHID(localName, hidName, 0x2580, 33, _absolute ? desc_absmouse : desc_mouse, _absolute ? sizeof(desc_absmouse) : sizeof(desc_mouse)); + _running = true; +} + +void MouseBT_::end(void) { + if (_running) { + PicoBluetoothHID.end(); + } + _running = false; +} + +void MouseBT_::setAbsolute(bool absolute) { + if (!_running) { + _absolute = absolute; + } +} + +void MouseBT_::move(int x, int y, signed char wheel) { + if (!_absolute) { + hid_mouse_report_t data; + data.buttons = _buttons; + data.x = limit_xy(x); + data.y = limit_xy(y); + data.wheel = wheel; + data.pan = 0; + PicoBluetoothHID.send(REPORT_ID, &data, sizeof(data)); + } else { + hid_abs_mouse_report_t data; + data.buttons = _buttons; + data.x = limit_xy(x); + data.y = limit_xy(y); + data.wheel = wheel; + data.pan = 0; + PicoBluetoothHID.send(REPORT_ID, &data, sizeof(data)); + } +} + +MouseBT_ MouseBT; diff --git a/libraries/MouseBT/src/MouseBT.h b/libraries/MouseBT/src/MouseBT.h new file mode 100644 index 000000000..394d93898 --- /dev/null +++ b/libraries/MouseBT/src/MouseBT.h @@ -0,0 +1,40 @@ +/* + MouseBT.h + + Copyright (c) 2015, Arduino LLC + Original code (pre-library): Copyright (c) 2011, Peter Barrett + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#ifndef MOUSEBT_h +#define MOUSEBT_h + +#include + +class MouseBT_ : public HID_Mouse { +private: + bool _running; + +public: + MouseBT_(bool absolute = false); + void begin(const char *localName = nullptr, const char *hidName = nullptr); + void end(void); + virtual void move(int x, int y, signed char wheel = 0) override; + void setAbsolute(bool absolute = true); +}; +extern MouseBT_ MouseBT; + +#endif diff --git a/libraries/PDM/examples/PDMSerialPlotter/PDMSerialPlotter.ino b/libraries/PDM/examples/PDMSerialPlotter/PDMSerialPlotter.ino index 35ff3e9f2..f376553ee 100644 --- a/libraries/PDM/examples/PDMSerialPlotter/PDMSerialPlotter.ino +++ b/libraries/PDM/examples/PDMSerialPlotter/PDMSerialPlotter.ino @@ -52,7 +52,7 @@ void loop() { // Print samples to the serial monitor or plotter for (int i = 0; i < samplesRead; i++) { - if(channels == 2) { + if (channels == 2) { Serial.print("L:"); Serial.print(sampleBuffer[i]); Serial.print(" R:"); @@ -67,9 +67,9 @@ void loop() { } /** - * Callback function to process the data from the PDM microphone. - * NOTE: This callback is executed as part of an ISR. - * Therefore using `Serial` to print messages inside this function isn't supported. + Callback function to process the data from the PDM microphone. + NOTE: This callback is executed as part of an ISR. + Therefore using `Serial` to print messages inside this function isn't supported. * */ void onPDMdata() { // Query the number of available bytes diff --git a/libraries/PDM/src/PDM.h b/libraries/PDM/src/PDM.h index 906476265..e0c56ea8d 100644 --- a/libraries/PDM/src/PDM.h +++ b/libraries/PDM/src/PDM.h @@ -1,74 +1,75 @@ /* - Copyright (c) 2019 Arduino LLC. All right reserved. + Copyright (c) 2019 Arduino LLC. All right reserved. - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - See the GNU Lesser General Public License for more details. + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU Lesser General Public License for more details. - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ -#ifndef _PDM_H_INCLUDED -#define _PDM_H_INCLUDED +#pragma once #include //#include #include "utility/PDMDoubleBuffer.h" -class PDMClass -{ +class PDMClass { public: - PDMClass(int dinPin, int clkPin, int pwrPin); - virtual ~PDMClass(); + PDMClass(int dinPin, int clkPin, int pwrPin); + virtual ~PDMClass(); - int begin(int channels, int sampleRate); - void end(); + int begin(int channels, int sampleRate); + void end(); - virtual int available(); - virtual int read(void* buffer, size_t size); + virtual int available(); + virtual int read(void* buffer, size_t size); - void onReceive(void(*)(void)); + void onReceive(void(*)(void)); - //PORTENTA_H7 min -12 max 51 - //NANO 33 BLE SENSe min 0 max 80 - void setGain(int gain); - void setBufferSize(int bufferSize); - size_t getBufferSize(); + //PORTENTA_H7 min -12 max 51 + //NANO 33 BLE SENSe min 0 max 80 + //NICLA_VISION min 0 max 8 + void setGain(int gain); + void setBufferSize(int bufferSize); + size_t getBufferSize(); -// private: - void IrqHandler(bool halftranfer); + // private: + void IrqHandler(bool halftranfer); private: - int _dinPin; - int _clkPin; - int _pwrPin; + int _dinPin; + int _clkPin; + int _pwrPin; - int _channels; - int _samplerate; + int _channels; + int _samplerate; - int _gain; - int _init; + int _gain; + int _init; -// Hardware peripherals used - uint _dmaChannel; - PIO _pio; - int _smIdx; - int _pgmOffset; + int _cutSamples; - PDMDoubleBuffer _doubleBuffer; + // Hardware peripherals used + uint _dmaChannel; + PIO _pio; + int _smIdx; + int _pgmOffset; - void (*_onReceive)(void); + PDMDoubleBuffer _doubleBuffer; + + void (*_onReceive)(void); }; + #ifdef PIN_PDM_DIN extern PDMClass PDM; #endif -#endif diff --git a/libraries/PDM/src/rp2040/OpenPDMFilter.c b/libraries/PDM/src/rp2040/OpenPDMFilter.c index e2f409ac0..be932cd4b 100644 --- a/libraries/PDM/src/rp2040/OpenPDMFilter.c +++ b/libraries/PDM/src/rp2040/OpenPDMFilter.c @@ -1,30 +1,30 @@ /** ******************************************************************************* - * @file OpenPDMFilter.c - * @author CL - * @version V1.0.0 - * @date 9-September-2015 - * @brief Open PDM audio software decoding Library. - * This Library is used to decode and reconstruct the audio signal - * produced by ST MEMS microphone (MP45Dxxx, MP34Dxxx). + @file OpenPDMFilter.c + @author CL + @version V1.0.0 + @date 9-September-2015 + @brief Open PDM audio software decoding Library. + This Library is used to decode and reconstruct the audio signal + produced by ST MEMS microphone (MP45Dxxx, MP34Dxxx). ******************************************************************************* - * @attention - * - *

© COPYRIGHT 2018 STMicroelectronics

- * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + @attention + +

© COPYRIGHT 2018 STMicroelectronics

+ + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. ******************************************************************************* - */ +*/ /* Includes ------------------------------------------------------------------*/ @@ -48,266 +48,255 @@ int32_t lut[256][DECIMATION_MAX / 8][SINCN]; /* Functions -----------------------------------------------------------------*/ #ifdef USE_LUT -int32_t filter_table_mono_64(uint8_t *data, uint8_t sincn) -{ - return (int32_t) - lut[data[0]][0][sincn] + - lut[data[1]][1][sincn] + - lut[data[2]][2][sincn] + - lut[data[3]][3][sincn] + - lut[data[4]][4][sincn] + - lut[data[5]][5][sincn] + - lut[data[6]][6][sincn] + - lut[data[7]][7][sincn]; +int32_t filter_table_mono_64(uint8_t *data, uint8_t sincn) { + return (int32_t) + lut[data[0]][0][sincn] + + lut[data[1]][1][sincn] + + lut[data[2]][2][sincn] + + lut[data[3]][3][sincn] + + lut[data[4]][4][sincn] + + lut[data[5]][5][sincn] + + lut[data[6]][6][sincn] + + lut[data[7]][7][sincn]; } -int32_t filter_table_stereo_64(uint8_t *data, uint8_t sincn) -{ - return (int32_t) - lut[data[0]][0][sincn] + - lut[data[2]][1][sincn] + - lut[data[4]][2][sincn] + - lut[data[6]][3][sincn] + - lut[data[8]][4][sincn] + - lut[data[10]][5][sincn] + - lut[data[12]][6][sincn] + - lut[data[14]][7][sincn]; +int32_t filter_table_stereo_64(uint8_t *data, uint8_t sincn) { + return (int32_t) + lut[data[0]][0][sincn] + + lut[data[2]][1][sincn] + + lut[data[4]][2][sincn] + + lut[data[6]][3][sincn] + + lut[data[8]][4][sincn] + + lut[data[10]][5][sincn] + + lut[data[12]][6][sincn] + + lut[data[14]][7][sincn]; } -int32_t filter_table_mono_128(uint8_t *data, uint8_t sincn) -{ - return (int32_t) - lut[data[0]][0][sincn] + - lut[data[1]][1][sincn] + - lut[data[2]][2][sincn] + - lut[data[3]][3][sincn] + - lut[data[4]][4][sincn] + - lut[data[5]][5][sincn] + - lut[data[6]][6][sincn] + - lut[data[7]][7][sincn] + - lut[data[8]][8][sincn] + - lut[data[9]][9][sincn] + - lut[data[10]][10][sincn] + - lut[data[11]][11][sincn] + - lut[data[12]][12][sincn] + - lut[data[13]][13][sincn] + - lut[data[14]][14][sincn] + - lut[data[15]][15][sincn]; +int32_t filter_table_mono_128(uint8_t *data, uint8_t sincn) { + return (int32_t) + lut[data[0]][0][sincn] + + lut[data[1]][1][sincn] + + lut[data[2]][2][sincn] + + lut[data[3]][3][sincn] + + lut[data[4]][4][sincn] + + lut[data[5]][5][sincn] + + lut[data[6]][6][sincn] + + lut[data[7]][7][sincn] + + lut[data[8]][8][sincn] + + lut[data[9]][9][sincn] + + lut[data[10]][10][sincn] + + lut[data[11]][11][sincn] + + lut[data[12]][12][sincn] + + lut[data[13]][13][sincn] + + lut[data[14]][14][sincn] + + lut[data[15]][15][sincn]; } -int32_t filter_table_stereo_128(uint8_t *data, uint8_t sincn) -{ - return (int32_t) - lut[data[0]][0][sincn] + - lut[data[2]][1][sincn] + - lut[data[4]][2][sincn] + - lut[data[6]][3][sincn] + - lut[data[8]][4][sincn] + - lut[data[10]][5][sincn] + - lut[data[12]][6][sincn] + - lut[data[14]][7][sincn] + - lut[data[16]][8][sincn] + - lut[data[18]][9][sincn] + - lut[data[20]][10][sincn] + - lut[data[22]][11][sincn] + - lut[data[24]][12][sincn] + - lut[data[26]][13][sincn] + - lut[data[28]][14][sincn] + - lut[data[30]][15][sincn]; +int32_t filter_table_stereo_128(uint8_t *data, uint8_t sincn) { + return (int32_t) + lut[data[0]][0][sincn] + + lut[data[2]][1][sincn] + + lut[data[4]][2][sincn] + + lut[data[6]][3][sincn] + + lut[data[8]][4][sincn] + + lut[data[10]][5][sincn] + + lut[data[12]][6][sincn] + + lut[data[14]][7][sincn] + + lut[data[16]][8][sincn] + + lut[data[18]][9][sincn] + + lut[data[20]][10][sincn] + + lut[data[22]][11][sincn] + + lut[data[24]][12][sincn] + + lut[data[26]][13][sincn] + + lut[data[28]][14][sincn] + + lut[data[30]][15][sincn]; } -int32_t (* filter_tables_64[2]) (uint8_t *data, uint8_t sincn) = {filter_table_mono_64, filter_table_stereo_64}; -int32_t (* filter_tables_128[2]) (uint8_t *data, uint8_t sincn) = {filter_table_mono_128, filter_table_stereo_128}; +int32_t (* filter_tables_64[2])(uint8_t *data, uint8_t sincn) = {filter_table_mono_64, filter_table_stereo_64}; +int32_t (* filter_tables_128[2])(uint8_t *data, uint8_t sincn) = {filter_table_mono_128, filter_table_stereo_128}; #else -int32_t filter_table(uint8_t *data, uint8_t sincn, TPDMFilter_InitStruct *param) -{ - uint8_t c, i; - uint16_t data_index = 0; - uint32_t *coef_p = &coef[sincn][0]; - int32_t F = 0; - uint8_t decimation = param->Decimation; - uint8_t channels = param->In_MicChannels; - - for (i = 0; i < decimation; i += 8) { - c = data[data_index]; - F += ((c >> 7) ) * coef_p[i ] + - ((c >> 6) & 0x01) * coef_p[i + 1] + - ((c >> 5) & 0x01) * coef_p[i + 2] + - ((c >> 4) & 0x01) * coef_p[i + 3] + - ((c >> 3) & 0x01) * coef_p[i + 4] + - ((c >> 2) & 0x01) * coef_p[i + 5] + - ((c >> 1) & 0x01) * coef_p[i + 6] + - ((c ) & 0x01) * coef_p[i + 7]; - data_index += channels; - } - return F; +int32_t filter_table(uint8_t *data, uint8_t sincn, TPDMFilter_InitStruct *param) { + uint8_t c, i; + uint16_t data_index = 0; + uint32_t *coef_p = &coef[sincn][0]; + int32_t F = 0; + uint8_t decimation = param->Decimation; + uint8_t channels = param->In_MicChannels; + + for (i = 0; i < decimation; i += 8) { + c = data[data_index]; + F += ((c >> 7)) * coef_p[i ] + + ((c >> 6) & 0x01) * coef_p[i + 1] + + ((c >> 5) & 0x01) * coef_p[i + 2] + + ((c >> 4) & 0x01) * coef_p[i + 3] + + ((c >> 3) & 0x01) * coef_p[i + 4] + + ((c >> 2) & 0x01) * coef_p[i + 5] + + ((c >> 1) & 0x01) * coef_p[i + 6] + + ((c) & 0x01) * coef_p[i + 7]; + data_index += channels; + } + return F; } #endif void convolve(uint32_t Signal[/* SignalLen */], unsigned short SignalLen, uint32_t Kernel[/* KernelLen */], unsigned short KernelLen, - uint32_t Result[/* SignalLen + KernelLen - 1 */]) -{ - uint16_t n; - - for (n = 0; n < SignalLen + KernelLen - 1; n++) - { - unsigned short kmin, kmax, k; - - Result[n] = 0; - - kmin = (n >= KernelLen - 1) ? n - (KernelLen - 1) : 0; - kmax = (n < SignalLen - 1) ? n : SignalLen - 1; - - for (k = kmin; k <= kmax; k++) { - Result[n] += Signal[k] * Kernel[n - k]; + uint32_t Result[/* SignalLen + KernelLen - 1 */]) { + uint16_t n; + + for (n = 0; n < SignalLen + KernelLen - 1; n++) { + unsigned short kmin, kmax, k; + + Result[n] = 0; + + kmin = (n >= KernelLen - 1) ? n - (KernelLen - 1) : 0; + kmax = (n < SignalLen - 1) ? n : SignalLen - 1; + + for (k = kmin; k <= kmax; k++) { + Result[n] += Signal[k] * Kernel[n - k]; + } } - } } -void Open_PDM_Filter_Init(TPDMFilter_InitStruct *Param) -{ - uint16_t i, j; - int64_t sum = 0; - - uint8_t decimation = Param->Decimation; - - for (i = 0; i < SINCN; i++) { - Param->Coef[i] = 0; - Param->bit[i] = 0; - } - for (i = 0; i < decimation; i++) { - sinc1[i] = 1; - } - - Param->OldOut = Param->OldIn = Param->OldZ = 0; - Param->LP_ALFA = (Param->LP_HZ != 0 ? (uint16_t) (Param->LP_HZ * 256 / (Param->LP_HZ + Param->Fs / (2 * 3.14159))) : 0); - Param->HP_ALFA = (Param->HP_HZ != 0 ? (uint16_t) (Param->Fs * 256 / (2 * 3.14159 * Param->HP_HZ + Param->Fs)) : 0); - - Param->FilterLen = decimation * SINCN; - sinc[0] = 0; - sinc[decimation * SINCN - 1] = 0; - convolve(sinc1, decimation, sinc1, decimation, sinc2); - convolve(sinc2, decimation * 2 - 1, sinc1, decimation, &sinc[1]); - for(j = 0; j < SINCN; j++) { +void Open_PDM_Filter_Init(TPDMFilter_InitStruct *Param) { + uint16_t i, j; + int64_t sum = 0; + + uint8_t decimation = Param->Decimation; + + for (i = 0; i < SINCN; i++) { + Param->Coef[i] = 0; + Param->bit[i] = 0; + } for (i = 0; i < decimation; i++) { - coef[j][i] = sinc[j * decimation + i]; - sum += sinc[j * decimation + i]; + sinc1[i] = 1; + } + + Param->OldOut = Param->OldIn = Param->OldZ = 0; + Param->LP_ALFA = (Param->LP_HZ != 0 ? (uint16_t)(Param->LP_HZ * 256 / (Param->LP_HZ + Param->Fs / (2 * 3.14159))) : 0); + Param->HP_ALFA = (Param->HP_HZ != 0 ? (uint16_t)(Param->Fs * 256 / (2 * 3.14159 * Param->HP_HZ + Param->Fs)) : 0); + + Param->FilterLen = decimation * SINCN; + sinc[0] = 0; + sinc[decimation * SINCN - 1] = 0; + convolve(sinc1, decimation, sinc1, decimation, sinc2); + convolve(sinc2, decimation * 2 - 1, sinc1, decimation, &sinc[1]); + for (j = 0; j < SINCN; j++) { + for (i = 0; i < decimation; i++) { + coef[j][i] = sinc[j * decimation + i]; + sum += sinc[j * decimation + i]; + } } - } - sub_const = sum >> 1; - div_const = sub_const * Param->MaxVolume / 32768 / Param->filterGain; - div_const = (div_const == 0 ? 1 : div_const); + sub_const = sum >> 1; + div_const = sub_const * Param->MaxVolume / 32768 / Param->filterGain; + div_const = (div_const == 0 ? 1 : div_const); #ifdef USE_LUT - /* Look-Up Table. */ - uint16_t c, d, s; - for (s = 0; s < SINCN; s++) - { - uint32_t *coef_p = &coef[s][0]; - for (c = 0; c < 256; c++) - for (d = 0; d < decimation / 8; d++) - lut[c][d][s] = ((c >> 7) ) * coef_p[d * 8 ] + - ((c >> 6) & 0x01) * coef_p[d * 8 + 1] + - ((c >> 5) & 0x01) * coef_p[d * 8 + 2] + - ((c >> 4) & 0x01) * coef_p[d * 8 + 3] + - ((c >> 3) & 0x01) * coef_p[d * 8 + 4] + - ((c >> 2) & 0x01) * coef_p[d * 8 + 5] + - ((c >> 1) & 0x01) * coef_p[d * 8 + 6] + - ((c ) & 0x01) * coef_p[d * 8 + 7]; - } + /* Look-Up Table. */ + uint16_t c, d, s; + for (s = 0; s < SINCN; s++) { + uint32_t *coef_p = &coef[s][0]; + for (c = 0; c < 256; c++) + for (d = 0; d < decimation / 8; d++) + lut[c][d][s] = ((c >> 7)) * coef_p[d * 8 ] + + ((c >> 6) & 0x01) * coef_p[d * 8 + 1] + + ((c >> 5) & 0x01) * coef_p[d * 8 + 2] + + ((c >> 4) & 0x01) * coef_p[d * 8 + 3] + + ((c >> 3) & 0x01) * coef_p[d * 8 + 4] + + ((c >> 2) & 0x01) * coef_p[d * 8 + 5] + + ((c >> 1) & 0x01) * coef_p[d * 8 + 6] + + ((c) & 0x01) * coef_p[d * 8 + 7]; + } #endif } -void Open_PDM_Filter_64(uint8_t* data, int16_t* dataOut, uint16_t volume, TPDMFilter_InitStruct *Param) -{ - uint8_t i, data_out_index; - uint8_t channels = Param->In_MicChannels; - uint8_t data_inc = ((DECIMATION_MAX >> 4) * channels); - int64_t Z, Z0, Z1, Z2; - int64_t OldOut, OldIn, OldZ; +void Open_PDM_Filter_64(uint8_t* data, int16_t* dataOut, uint16_t volume, TPDMFilter_InitStruct *Param) { + uint8_t i, data_out_index; + uint8_t channels = Param->In_MicChannels; + uint8_t data_inc = ((DECIMATION_MAX >> 4) * channels); + int64_t Z, Z0, Z1, Z2; + int64_t OldOut, OldIn, OldZ; - OldOut = Param->OldOut; - OldIn = Param->OldIn; - OldZ = Param->OldZ; + OldOut = Param->OldOut; + OldIn = Param->OldIn; + OldZ = Param->OldZ; #ifdef USE_LUT - uint8_t j = channels - 1; + uint8_t j = channels - 1; #endif - for (i = 0, data_out_index = 0; i < Param->nSamples; i++, data_out_index += channels) { + for (i = 0, data_out_index = 0; i < Param->nSamples; i++, data_out_index += channels) { #ifdef USE_LUT - Z0 = filter_tables_64[j](data, 0); - Z1 = filter_tables_64[j](data, 1); - Z2 = filter_tables_64[j](data, 2); + Z0 = filter_tables_64[j](data, 0); + Z1 = filter_tables_64[j](data, 1); + Z2 = filter_tables_64[j](data, 2); #else - Z0 = filter_table(data, 0, Param); - Z1 = filter_table(data, 1, Param); - Z2 = filter_table(data, 2, Param); + Z0 = filter_table(data, 0, Param); + Z1 = filter_table(data, 1, Param); + Z2 = filter_table(data, 2, Param); #endif - Z = Param->Coef[1] + Z2 - sub_const; - Param->Coef[1] = Param->Coef[0] + Z1; - Param->Coef[0] = Z0; + Z = Param->Coef[1] + Z2 - sub_const; + Param->Coef[1] = Param->Coef[0] + Z1; + Param->Coef[0] = Z0; - OldOut = (Param->HP_ALFA * (OldOut + Z - OldIn)) >> 8; - OldIn = Z; - OldZ = ((256 - Param->LP_ALFA) * OldZ + Param->LP_ALFA * OldOut) >> 8; + OldOut = (Param->HP_ALFA * (OldOut + Z - OldIn)) >> 8; + OldIn = Z; + OldZ = ((256 - Param->LP_ALFA) * OldZ + Param->LP_ALFA * OldOut) >> 8; - Z = OldZ * volume; - Z = RoundDiv(Z, div_const); - Z = SaturaLH(Z, -32700, 32700); + Z = OldZ * volume; + Z = RoundDiv(Z, div_const); + Z = SaturaLH(Z, -32700, 32700); - dataOut[data_out_index] = Z; - data += data_inc; - } + dataOut[data_out_index] = Z; + data += data_inc; + } - Param->OldOut = OldOut; - Param->OldIn = OldIn; - Param->OldZ = OldZ; + Param->OldOut = OldOut; + Param->OldIn = OldIn; + Param->OldZ = OldZ; } -void Open_PDM_Filter_128(uint8_t* data, int16_t* dataOut, uint16_t volume, TPDMFilter_InitStruct *Param) -{ - uint8_t i, data_out_index; - uint8_t channels = Param->In_MicChannels; - uint8_t data_inc = ((DECIMATION_MAX >> 3) * channels); - int64_t Z, Z0, Z1, Z2; - int64_t OldOut, OldIn, OldZ; +void Open_PDM_Filter_128(uint8_t* data, int16_t* dataOut, uint16_t volume, TPDMFilter_InitStruct *Param) { + uint8_t i, data_out_index; + uint8_t channels = Param->In_MicChannels; + uint8_t data_inc = ((DECIMATION_MAX >> 3) * channels); + int64_t Z, Z0, Z1, Z2; + int64_t OldOut, OldIn, OldZ; - OldOut = Param->OldOut; - OldIn = Param->OldIn; - OldZ = Param->OldZ; + OldOut = Param->OldOut; + OldIn = Param->OldIn; + OldZ = Param->OldZ; #ifdef USE_LUT - uint8_t j = channels - 1; + uint8_t j = channels - 1; #endif - for (i = 0, data_out_index = 0; i < Param->nSamples; i++, data_out_index += channels) { + for (i = 0, data_out_index = 0; i < Param->nSamples; i++, data_out_index += channels) { #ifdef USE_LUT - Z0 = filter_tables_128[j](data, 0); - Z1 = filter_tables_128[j](data, 1); - Z2 = filter_tables_128[j](data, 2); + Z0 = filter_tables_128[j](data, 0); + Z1 = filter_tables_128[j](data, 1); + Z2 = filter_tables_128[j](data, 2); #else - Z0 = filter_table(data, 0, Param); - Z1 = filter_table(data, 1, Param); - Z2 = filter_table(data, 2, Param); + Z0 = filter_table(data, 0, Param); + Z1 = filter_table(data, 1, Param); + Z2 = filter_table(data, 2, Param); #endif - Z = Param->Coef[1] + Z2 - sub_const; - Param->Coef[1] = Param->Coef[0] + Z1; - Param->Coef[0] = Z0; + Z = Param->Coef[1] + Z2 - sub_const; + Param->Coef[1] = Param->Coef[0] + Z1; + Param->Coef[0] = Z0; - OldOut = (Param->HP_ALFA * (OldOut + Z - OldIn)) >> 8; - OldIn = Z; - OldZ = ((256 - Param->LP_ALFA) * OldZ + Param->LP_ALFA * OldOut) >> 8; + OldOut = (Param->HP_ALFA * (OldOut + Z - OldIn)) >> 8; + OldIn = Z; + OldZ = ((256 - Param->LP_ALFA) * OldZ + Param->LP_ALFA * OldOut) >> 8; - Z = OldZ * volume; - Z = RoundDiv(Z, div_const); - Z = SaturaLH(Z, -32700, 32700); + Z = OldZ * volume; + Z = RoundDiv(Z, div_const); + Z = SaturaLH(Z, -32700, 32700); - dataOut[data_out_index] = Z; - data += data_inc; - } + dataOut[data_out_index] = Z; + data += data_inc; + } - Param->OldOut = OldOut; - Param->OldIn = OldIn; - Param->OldZ = OldZ; + Param->OldOut = OldOut; + Param->OldIn = OldIn; + Param->OldZ = OldZ; } diff --git a/libraries/PDM/src/rp2040/OpenPDMFilter.h b/libraries/PDM/src/rp2040/OpenPDMFilter.h index d57ddf077..21f3e12d7 100644 --- a/libraries/PDM/src/rp2040/OpenPDMFilter.h +++ b/libraries/PDM/src/rp2040/OpenPDMFilter.h @@ -1,30 +1,30 @@ /** ******************************************************************************* - * @file OpenPDMFilter.h - * @author CL - * @version V1.0.0 - * @date 9-September-2015 - * @brief Header file for Open PDM audio software decoding Library. - * This Library is used to decode and reconstruct the audio signal - * produced by ST MEMS microphone (MP45Dxxx, MP34Dxxx). + @file OpenPDMFilter.h + @author CL + @version V1.0.0 + @date 9-September-2015 + @brief Header file for Open PDM audio software decoding Library. + This Library is used to decode and reconstruct the audio signal + produced by ST MEMS microphone (MP45Dxxx, MP34Dxxx). ******************************************************************************* - * @attention - * - *

© COPYRIGHT 2018 STMicroelectronics

- * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + @attention + +

© COPYRIGHT 2018 STMicroelectronics

+ + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. ******************************************************************************* - */ +*/ /* Define to prevent recursive inclusion -------------------------------------*/ @@ -33,7 +33,7 @@ #define __OPENPDMFILTER_H #ifdef __cplusplus - extern "C" { +extern "C" { #endif @@ -45,10 +45,10 @@ /* Definitions ---------------------------------------------------------------*/ /* - * Enable to use a Look-Up Table to improve performances while using more FLASH - * and RAM memory. - * Note: Without Look-Up Table up to stereo@16KHz configuration is supported. - */ + Enable to use a Look-Up Table to improve performances while using more FLASH + and RAM memory. + Note: Without Look-Up Table up to stereo@16KHz configuration is supported. +*/ #define USE_LUT #define SINCN 3 @@ -63,24 +63,24 @@ /* Types ---------------------------------------------------------------------*/ typedef struct { - /* Public */ - float LP_HZ; - float HP_HZ; - uint16_t Fs; - unsigned int nSamples; - uint8_t In_MicChannels; - uint8_t Out_MicChannels; - uint8_t Decimation; - uint8_t MaxVolume; - /* Private */ - uint32_t Coef[SINCN]; - uint16_t FilterLen; - int64_t OldOut, OldIn, OldZ; - uint16_t LP_ALFA; - uint16_t HP_ALFA; - uint16_t bit[5]; - uint16_t byte; - uint16_t filterGain; + /* Public */ + float LP_HZ; + float HP_HZ; + uint16_t Fs; + unsigned int nSamples; + uint8_t In_MicChannels; + uint8_t Out_MicChannels; + uint8_t Decimation; + uint8_t MaxVolume; + /* Private */ + uint32_t Coef[SINCN]; + uint16_t FilterLen; + int64_t OldOut, OldIn, OldZ; + uint16_t LP_ALFA; + uint16_t HP_ALFA; + uint16_t bit[5]; + uint16_t byte; + uint16_t filterGain; } TPDMFilter_InitStruct; diff --git a/libraries/PDM/src/rp2040/PDM.cpp b/libraries/PDM/src/rp2040/PDM.cpp index 273761328..a27d3f616 100644 --- a/libraries/PDM/src/rp2040/PDM.cpp +++ b/libraries/PDM/src/rp2040/PDM.cpp @@ -9,7 +9,7 @@ extern "C" { #include "hardware/dma.h" #include "hardware/clocks.h" } -#include "hardware/sync.h" +#include "hardware/sync.h" #include "pdm.pio.h" static PIOProgram _pdmPgm(&pdm_pio_program); @@ -18,9 +18,9 @@ static PIOProgram _pdmPgm(&pdm_pio_program); uint8_t rawBuffer0[RAW_BUFFER_SIZE]; uint8_t rawBuffer1[RAW_BUFFER_SIZE]; uint8_t* rawBuffer[2] = {rawBuffer0, rawBuffer1}; -volatile int rawBufferIndex = 0; +volatile int rawBufferIndex = 0; -int decimation = 64; +int decimation = 128; // final buffer is the one to be filled with PCM data int16_t* volatile finalBuffer; @@ -30,179 +30,203 @@ int16_t* volatile finalBuffer; TPDMFilter_InitStruct filter; extern "C" { - __attribute__((__used__)) void dmaHandler(void) - { - PDM.IrqHandler(true); - } + __attribute__((__used__)) void dmaHandler(void) { + PDM.IrqHandler(true); + } } PDMClass::PDMClass(int dinPin, int clkPin, int pwrPin) : - _dinPin(dinPin), - _clkPin(clkPin), - _pwrPin(pwrPin), - _onReceive(NULL), - _gain(-1), - _channels(-1), - _samplerate(-1), - _init(-1), - _dmaChannel(0), - _pio(nullptr), - _smIdx(-1), - _pgmOffset(-1) -{ + _dinPin(dinPin), + _clkPin(clkPin), + _pwrPin(pwrPin), + _onReceive(NULL), + _gain(-1), + _channels(-1), + _samplerate(-1), + _init(-1), + _cutSamples(100), + _dmaChannel(0), + _pio(nullptr), + _smIdx(-1), + _pgmOffset(-1) { } -PDMClass::~PDMClass() -{ +PDMClass::~PDMClass() { } -int PDMClass::begin(int channels, int sampleRate) -{ - //_channels = channels; // only one channel available - - // clear the final buffers - _doubleBuffer.reset(); - finalBuffer = (int16_t*)_doubleBuffer.data(); - int finalBufferLength = _doubleBuffer.availableForWrite() / sizeof(int16_t); - _doubleBuffer.swap(0); - - int rawBufferLength = RAW_BUFFER_SIZE / (decimation / 8); - // Saturate number of samples. Remaining bytes are dropped. - if (rawBufferLength > finalBufferLength) { - rawBufferLength = finalBufferLength; - } - - /* Initialize Open PDM library */ - filter.Fs = sampleRate; - filter.nSamples = rawBufferLength; - filter.LP_HZ = sampleRate/2; - filter.HP_HZ = 10; - filter.In_MicChannels = 1; - filter.Out_MicChannels = 1; - filter.Decimation = decimation; - if(_gain == -1) { - _gain = FILTER_GAIN; - } - filter.filterGain = _gain; - Open_PDM_Filter_Init(&filter); - - // Configure PIO state machine - float clkDiv = (float)clock_get_hz(clk_sys) / sampleRate / decimation / 2; - - if (!_pdmPgm.prepare(&_pio, &_smIdx, &_pgmOffset)) { - // ERROR, no free slots - return -1; - } - pdm_pio_program_init(_pio, _smIdx, _pgmOffset, _clkPin, _dinPin, clkDiv); - - // Wait for microphone - delay(100); - - // Configure DMA for transferring PIO rx buffer to raw buffers - _dmaChannel = dma_claim_unused_channel(false); - dma_channel_config c = dma_channel_get_default_config(_dmaChannel); - channel_config_set_read_increment(&c, false); - channel_config_set_write_increment(&c, true); - channel_config_set_dreq(&c, pio_get_dreq(_pio, _smIdx, false)); - channel_config_set_transfer_data_size(&c, DMA_SIZE_8); - - // Clear DMA interrupts - dma_hw->ints0 = 1u << _dmaChannel; - // Enable DMA interrupts - dma_channel_set_irq0_enabled(_dmaChannel, true); - // Share but allocate a high priority to the interrupt - irq_add_shared_handler(DMA_IRQ_0, dmaHandler, 0); - irq_set_enabled(DMA_IRQ_0, true); - - dma_channel_configure(_dmaChannel, &c, - rawBuffer[rawBufferIndex], // Destinatinon pointer - &_pio->rxf[_smIdx], // Source pointer - RAW_BUFFER_SIZE, // Number of transfers - true // Start immediately - ); - - _init = 1; - - return 1; +int PDMClass::begin(int channels, int sampleRate) { + + if (_init == 1) { + //ERROR: please call end first + return 0; + } + + //_channels = channels; // only one channel available + + // clear the final buffers + _doubleBuffer.reset(); + finalBuffer = (int16_t*)_doubleBuffer.data(); + int finalBufferLength = _doubleBuffer.availableForWrite() / sizeof(int16_t); + _doubleBuffer.swap(0); + + // The mic accepts an input clock from 1.2 to 3.25 Mhz + // Setup the decimation factor accordingly + if ((sampleRate * decimation * 2) > 3250000) { + decimation = 64; + } + + // Sanity check, abort if still over 3.25Mhz + if ((sampleRate * decimation * 2) > 3250000) { + //ERROR: Sample rate too high, the mic would glitch + return -1; + } + + int rawBufferLength = RAW_BUFFER_SIZE / (decimation / 8); + // Saturate number of samples. Remaining bytes are dropped. + if (rawBufferLength > finalBufferLength) { + rawBufferLength = finalBufferLength; + } + + /* Initialize Open PDM library */ + filter.Fs = sampleRate; + filter.MaxVolume = 1; + filter.nSamples = rawBufferLength; + filter.LP_HZ = sampleRate / 2; + filter.HP_HZ = 10; + filter.In_MicChannels = 1; + filter.Out_MicChannels = 1; + filter.Decimation = decimation; + if (_gain == -1) { + _gain = FILTER_GAIN; + } + filter.filterGain = _gain; + Open_PDM_Filter_Init(&filter); + + // Configure PIO state machine + float clkDiv = (float)clock_get_hz(clk_sys) / sampleRate / decimation / 2; + + if (!_pdmPgm.prepare(&_pio, &_smIdx, &_pgmOffset)) { + // ERROR, no free slots + return 0; + } + pdm_pio_program_init(_pio, _smIdx, _pgmOffset, _clkPin, _dinPin, clkDiv); + + // Wait for microphone + delay(100); + + // Configure DMA for transferring PIO rx buffer to raw buffers + _dmaChannel = dma_claim_unused_channel(false); + dma_channel_config c = dma_channel_get_default_config(_dmaChannel); + channel_config_set_read_increment(&c, false); + channel_config_set_write_increment(&c, true); + channel_config_set_dreq(&c, pio_get_dreq(_pio, _smIdx, false)); + channel_config_set_transfer_data_size(&c, DMA_SIZE_8); + + // Clear DMA interrupts + dma_hw->ints0 = 1u << _dmaChannel; + // Enable DMA interrupts + dma_channel_set_irq0_enabled(_dmaChannel, true); + // Share but allocate a high priority to the interrupt + irq_add_shared_handler(DMA_IRQ_0, dmaHandler, 0); + irq_set_enabled(DMA_IRQ_0, true); + + dma_channel_configure(_dmaChannel, &c, + rawBuffer[rawBufferIndex], // Destinatinon pointer + &_pio->rxf[_smIdx], // Source pointer + RAW_BUFFER_SIZE, // Number of transfers + true // Start immediately + ); + + _cutSamples = 100; + + _init = 1; + + return 1; } -void PDMClass::end() -{ - dma_channel_abort(_dmaChannel); - pinMode(_clkPin, INPUT); +void PDMClass::end() { + + if (_init != 1) { + return; + } + + dma_channel_set_irq0_enabled(_dmaChannel, false); + dma_channel_abort(_dmaChannel); + dma_channel_unclaim(_dmaChannel); + irq_remove_handler(DMA_IRQ_0, dmaHandler); + pio_sm_unclaim(_pio, _smIdx); + pinMode(_clkPin, INPUT); + rawBufferIndex = 0; + _pgmOffset = -1; + + _init = 0; } -int PDMClass::available() -{ - //NVIC_DisableIRQ(DMA_IRQ_0n); - //uint32_t interrupts = save_and_disable_interrupts(); - irq_set_enabled(DMA_IRQ_0, false); - size_t avail = _doubleBuffer.available(); - irq_set_enabled(DMA_IRQ_0, true); - //restore_interrupts(interrupts); - //NVIC_EnableIRQ(DMA_IRQ_0n); - return avail; +int PDMClass::available() { + //NVIC_DisableIRQ(DMA_IRQ_0n); + //uint32_t interrupts = save_and_disable_interrupts(); + irq_set_enabled(DMA_IRQ_0, false); + size_t avail = _doubleBuffer.available(); + irq_set_enabled(DMA_IRQ_0, true); + //restore_interrupts(interrupts); + //NVIC_EnableIRQ(DMA_IRQ_0n); + return avail; } -int PDMClass::read(void* buffer, size_t size) -{ - irq_set_enabled(DMA_IRQ_0, false); - int read = _doubleBuffer.read(buffer, size); - irq_set_enabled(DMA_IRQ_0, true); - return read; +int PDMClass::read(void* buffer, size_t size) { + irq_set_enabled(DMA_IRQ_0, false); + int read = _doubleBuffer.read(buffer, size); + irq_set_enabled(DMA_IRQ_0, true); + return read; } -void PDMClass::onReceive(void(*function)(void)) -{ - _onReceive = function; +void PDMClass::onReceive(void(*function)(void)) { + _onReceive = function; } -void PDMClass::setGain(int gain) -{ - _gain = gain; - if(_init == 1) { - filter.filterGain = _gain; - Open_PDM_Filter_Init(&filter); - } +void PDMClass::setGain(int gain) { + _gain = gain; + if (_init == 1) { + filter.filterGain = _gain; + Open_PDM_Filter_Init(&filter); + } } -void PDMClass::setBufferSize(int bufferSize) -{ - _doubleBuffer.setSize(bufferSize); +void PDMClass::setBufferSize(int bufferSize) { + _doubleBuffer.setSize(bufferSize); } -void PDMClass::IrqHandler(bool halftranfer) -{ - static int cutSamples = 100; - - // Clear the interrupt request. - dma_hw->ints0 = 1u << _dmaChannel; - // Restart dma pointing to the other buffer - int shadowIndex = rawBufferIndex ^ 1; - dma_channel_set_write_addr(_dmaChannel, rawBuffer[shadowIndex], true); - - if (_doubleBuffer.available()) { - // buffer overflow, stop - return end(); - } - - // fill final buffer with PCM samples - Open_PDM_Filter_64(rawBuffer[rawBufferIndex], finalBuffer, 1, &filter); - - if (cutSamples) { - memset(finalBuffer, 0, cutSamples); - cutSamples = 0; - } - - // swap final buffer and raw buffers' indexes - finalBuffer = (int16_t*)_doubleBuffer.data(); - _doubleBuffer.swap(filter.nSamples * sizeof(int16_t)); - rawBufferIndex = shadowIndex; - - if (_onReceive) { - _onReceive(); - } +void PDMClass::IrqHandler(bool halftranfer) { + + // Clear the interrupt request. + dma_hw->ints0 = 1u << _dmaChannel; + // Restart dma pointing to the other buffer + int shadowIndex = rawBufferIndex ^ 1; + dma_channel_set_write_addr(_dmaChannel, rawBuffer[shadowIndex], true); + + if (!_doubleBuffer.available()) { + // fill final buffer with PCM samples + if (filter.Decimation == 128) { + Open_PDM_Filter_128(rawBuffer[rawBufferIndex], finalBuffer, 1, &filter); + } else { + Open_PDM_Filter_64(rawBuffer[rawBufferIndex], finalBuffer, 1, &filter); + } + + if (_cutSamples) { + memset(finalBuffer, 0, _cutSamples); + _cutSamples = 0; + } + + // swap final buffer and raw buffers' indexes + finalBuffer = (int16_t*)_doubleBuffer.data(); + _doubleBuffer.swap(filter.nSamples * sizeof(int16_t)); + rawBufferIndex = shadowIndex; + } + + if (_onReceive) { + _onReceive(); + } } #ifdef PIN_PDM_DIN PDMClass PDM(PIN_PDM_DIN, PIN_PDM_CLK, -1); diff --git a/libraries/PDM/src/rp2040/pdm.pio.h b/libraries/PDM/src/rp2040/pdm.pio.h index 09c77a515..63d9a6139 100644 --- a/libraries/PDM/src/rp2040/pdm.pio.h +++ b/libraries/PDM/src/rp2040/pdm.pio.h @@ -14,10 +14,10 @@ #define pdm_pio_wrap 1 static const uint16_t pdm_pio_program_instructions[] = { - // .wrap_target - 0x9040, // 0: push iffull noblock side 1 - 0x4001, // 1: in pins, 1 side 0 - // .wrap + // .wrap_target + 0x9040, // 0: push iffull noblock side 1 + 0x4001, // 1: in pins, 1 side 0 + // .wrap }; #if !PICO_NO_HARDWARE @@ -36,21 +36,21 @@ static inline pio_sm_config pdm_pio_program_get_default_config(uint offset) { #include "hardware/gpio.h" static inline void pdm_pio_program_init(PIO pio, uint sm, uint offset, uint clkPin, uint dataPin, float clkDiv) { - pio_sm_config c = pdm_pio_program_get_default_config(offset); - sm_config_set_sideset(&c, 1, false, false); - //sm_config_set_in_shift(&c, false, true, 8); - sm_config_set_in_shift(&c, false, false, 8); - sm_config_set_in_pins(&c, dataPin); - sm_config_set_sideset_pins(&c, clkPin); - sm_config_set_clkdiv(&c, clkDiv); - sm_config_set_fifo_join(&c, PIO_FIFO_JOIN_RX); - pio_sm_set_consecutive_pindirs(pio, sm, dataPin, 1, false); - pio_sm_set_consecutive_pindirs(pio, sm, clkPin, 1, true); - pio_sm_set_pins_with_mask(pio, sm, 0, (1u << clkPin) ); - //pio_gpio_init(pio, dataPin); - pio_gpio_init(pio, clkPin); - pio_sm_init(pio, sm, offset, &c); - pio_sm_set_enabled(pio, sm, true); + pio_sm_config c = pdm_pio_program_get_default_config(offset); + sm_config_set_sideset(&c, 1, false, false); + //sm_config_set_in_shift(&c, false, true, 8); + sm_config_set_in_shift(&c, false, false, 8); + sm_config_set_in_pins(&c, dataPin); + sm_config_set_sideset_pins(&c, clkPin); + sm_config_set_clkdiv(&c, clkDiv); + sm_config_set_fifo_join(&c, PIO_FIFO_JOIN_RX); + pio_sm_set_consecutive_pindirs(pio, sm, dataPin, 1, false); + pio_sm_set_consecutive_pindirs(pio, sm, clkPin, 1, true); + pio_sm_set_pins_with_mask(pio, sm, 0, (1u << clkPin)); + //pio_gpio_init(pio, dataPin); + pio_gpio_init(pio, clkPin); + pio_sm_init(pio, sm, offset, &c); + pio_sm_set_enabled(pio, sm, true); } #endif diff --git a/libraries/PDM/src/utility/PDMDoubleBuffer.cpp b/libraries/PDM/src/utility/PDMDoubleBuffer.cpp index d3924c1f0..25a2cb04c 100644 --- a/libraries/PDM/src/utility/PDMDoubleBuffer.cpp +++ b/libraries/PDM/src/utility/PDMDoubleBuffer.cpp @@ -1,19 +1,19 @@ /* - Copyright (c) 2016 Arduino LLC. All right reserved. + Copyright (c) 2016 Arduino LLC. All right reserved. - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - See the GNU Lesser General Public License for more details. + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU Lesser General Public License for more details. - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include @@ -22,118 +22,106 @@ #include "PDMDoubleBuffer.h" PDMDoubleBuffer::PDMDoubleBuffer() : - _size(DEFAULT_PDM_BUFFER_SIZE) -{ - reset(); + _size(DEFAULT_PDM_BUFFER_SIZE) { + reset(); } -PDMDoubleBuffer::~PDMDoubleBuffer() -{ +PDMDoubleBuffer::~PDMDoubleBuffer() { } -void PDMDoubleBuffer::setSize(int size) -{ - _size = size; - reset(); +void PDMDoubleBuffer::setSize(int size) { + _size = size; + reset(); } -size_t PDMDoubleBuffer::getSize() -{ - return _size; +size_t PDMDoubleBuffer::getSize() { + return _size; } -void PDMDoubleBuffer::reset() -{ - _buffer[0] = (uint8_t*)realloc(_buffer[0], _size); - _buffer[1] = (uint8_t*)realloc(_buffer[1], _size); +void PDMDoubleBuffer::reset() { + _buffer[0] = (uint8_t*)realloc(_buffer[0], _size); + _buffer[1] = (uint8_t*)realloc(_buffer[1], _size); - memset(_buffer[0], 0x00, _size); - memset(_buffer[1], 0x00, _size); + memset(_buffer[0], 0x00, _size); + memset(_buffer[1], 0x00, _size); - _index = 0; - _length[0] = 0; - _length[1] = 0; - _readOffset[0] = 0; - _readOffset[1] = 0; + _index = 0; + _length[0] = 0; + _length[1] = 0; + _readOffset[0] = 0; + _readOffset[1] = 0; } -size_t PDMDoubleBuffer::availableForWrite() -{ - return (_size - (_length[_index] - _readOffset[_index])); +size_t PDMDoubleBuffer::availableForWrite() { + return (_size - (_length[_index] - _readOffset[_index])); } -size_t PDMDoubleBuffer::write(const void *buffer, size_t size) -{ - size_t space = availableForWrite(); +size_t PDMDoubleBuffer::write(const void *buffer, size_t size) { + size_t space = availableForWrite(); - if (size > space) { - size = space; - } + if (size > space) { + size = space; + } - if (size == 0) { - return 0; - } + if (size == 0) { + return 0; + } - memcpy(&_buffer[_index][_length[_index]], buffer, size); + memcpy(&_buffer[_index][_length[_index]], buffer, size); - _length[_index] += size; + _length[_index] += size; - return size; + return size; } -size_t PDMDoubleBuffer::read(void *buffer, size_t size) -{ - size_t avail = available(); +size_t PDMDoubleBuffer::read(void *buffer, size_t size) { + size_t avail = available(); - if (size > avail) { - size = avail; - } + if (size > avail) { + size = avail; + } - if (size == 0) { - return 0; - } + if (size == 0) { + return 0; + } - memcpy(buffer, &_buffer[_index][_readOffset[_index]], size); - _readOffset[_index] += size; + memcpy(buffer, &_buffer[_index][_readOffset[_index]], size); + _readOffset[_index] += size; - return size; + return size; } -size_t PDMDoubleBuffer::peek(void *buffer, size_t size) -{ - size_t avail = available(); +size_t PDMDoubleBuffer::peek(void *buffer, size_t size) { + size_t avail = available(); - if (size > avail) { - size = avail; - } + if (size > avail) { + size = avail; + } - if (size == 0) { - return 0; - } + if (size == 0) { + return 0; + } - memcpy(buffer, &_buffer[_index][_readOffset[_index]], size); + memcpy(buffer, &_buffer[_index][_readOffset[_index]], size); - return size; + return size; } -void* PDMDoubleBuffer::data() -{ - return (void*)_buffer[_index]; +void* PDMDoubleBuffer::data() { + return (void*)_buffer[_index]; } -size_t PDMDoubleBuffer::available() -{ - return _length[_index] - _readOffset[_index]; +size_t PDMDoubleBuffer::available() { + return _length[_index] - _readOffset[_index]; } -void PDMDoubleBuffer::swap(int length) -{ - if (_index == 0) { - _index = 1; - } else { - _index = 0; - } +void PDMDoubleBuffer::swap(int length) { + if (_index == 0) { + _index = 1; + } else { + _index = 0; + } - _length[_index] = length; - _readOffset[_index] = 0; + _length[_index] = length; + _readOffset[_index] = 0; } diff --git a/libraries/PDM/src/utility/PDMDoubleBuffer.h b/libraries/PDM/src/utility/PDMDoubleBuffer.h index 7eb8a614a..009665323 100644 --- a/libraries/PDM/src/utility/PDMDoubleBuffer.h +++ b/libraries/PDM/src/utility/PDMDoubleBuffer.h @@ -1,19 +1,19 @@ /* - Copyright (c) 2016 Arduino LLC. All right reserved. + Copyright (c) 2016 Arduino LLC. All right reserved. - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - See the GNU Lesser General Public License for more details. + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU Lesser General Public License for more details. - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef _PDM_DOUBLE_BUFFER_H_INCLUDED @@ -24,31 +24,30 @@ #define DEFAULT_PDM_BUFFER_SIZE 512 -class PDMDoubleBuffer -{ +class PDMDoubleBuffer { public: - PDMDoubleBuffer(); - virtual ~PDMDoubleBuffer(); + PDMDoubleBuffer(); + virtual ~PDMDoubleBuffer(); - void setSize(int size); - size_t getSize(); + void setSize(int size); + size_t getSize(); - void reset(); + void reset(); - size_t availableForWrite(); - size_t write(const void *buffer, size_t size); - size_t read(void *buffer, size_t size); - size_t peek(void *buffer, size_t size); - void* data(); - size_t available(); - void swap(int length = 0); + size_t availableForWrite(); + size_t write(const void *buffer, size_t size); + size_t read(void *buffer, size_t size); + size_t peek(void *buffer, size_t size); + void* data(); + size_t available(); + void swap(int length = 0); private: - uint8_t* _buffer[2] __attribute__((aligned (16))); - int _size; - volatile int _length[2]; - volatile int _readOffset[2]; - volatile int _index; + uint8_t* _buffer[2] __attribute__((aligned(16))); + int _size; + volatile int _length[2]; + volatile int _readOffset[2]; + volatile int _index; }; #endif diff --git a/libraries/PWMAudio/examples/PlayRaw/PlayRaw.ino b/libraries/PWMAudio/examples/PlayRaw/PlayRaw.ino new file mode 100644 index 000000000..a33550978 --- /dev/null +++ b/libraries/PWMAudio/examples/PlayRaw/PlayRaw.ino @@ -0,0 +1,37 @@ +/* + This example plays a raw, headerless, mono 16b, 44.1 sample using the PWMAudio library on GPIO 1. + + Released to the public domain by Earle F. Philhower, III +*/ + +#include +#include "wav.h" + +// The sample pointers +const int16_t *start = (const int16_t *)out_raw; +const int16_t *p = start; + +// Create the PWM audio device on GPIO 1. Hook amp/speaker between GPIO1 and convenient GND. +PWMAudio pwm(1); + +unsigned int count = 0; + +void cb() { + while (pwm.availableForWrite()) { + pwm.write(*p++); + count += 2; + if (count >= sizeof(out_raw)) { + count = 0; + p = start; + } + } +} + +void setup() { + pwm.onTransmit(cb); + pwm.begin(44100); +} + +void loop() { + /* noop, everything is done in the CB */ +} diff --git a/libraries/PWMAudio/examples/PlayRaw/wav.h b/libraries/PWMAudio/examples/PlayRaw/wav.h new file mode 100644 index 000000000..b34033fad --- /dev/null +++ b/libraries/PWMAudio/examples/PlayRaw/wav.h @@ -0,0 +1,15092 @@ +unsigned char out_raw[] = { + 0xbd, 0x1b, 0xd1, 0x1a, 0x41, 0x1b, 0x63, 0x1a, 0xdf, 0x19, 0xea, 0x19, + 0x18, 0x19, 0x50, 0x19, 0x2e, 0x1a, 0xdc, 0x19, 0x90, 0x1a, 0x8d, 0x1a, + 0x60, 0x19, 0x31, 0x19, 0x81, 0x17, 0x79, 0x16, 0xda, 0x16, 0x0b, 0x16, + 0xf1, 0x15, 0x94, 0x15, 0xa6, 0x13, 0xad, 0x12, 0x31, 0x12, 0xa6, 0x10, + 0x94, 0x10, 0xf6, 0x10, 0x17, 0x10, 0x2c, 0x10, 0xa3, 0x0f, 0x16, 0x0e, + 0x0e, 0x0d, 0xcc, 0x0b, 0x10, 0x0c, 0xf7, 0x0c, 0xa4, 0x0b, 0x7c, 0x0a, + 0x18, 0x0b, 0xb0, 0x0a, 0x97, 0x09, 0xbb, 0x08, 0x30, 0x07, 0xc0, 0x06, + 0xe9, 0x06, 0x8b, 0x06, 0x37, 0x06, 0xcf, 0x04, 0x75, 0x03, 0x40, 0x04, + 0x84, 0x04, 0xb6, 0x03, 0x9f, 0x02, 0xb9, 0x00, 0xe1, 0x00, 0x24, 0x02, + 0xe6, 0x01, 0x42, 0x01, 0x5f, 0x00, 0xa7, 0xff, 0xf5, 0x00, 0xaf, 0x02, + 0xf5, 0x01, 0x4d, 0x01, 0x56, 0x01, 0x7a, 0x01, 0x3e, 0x02, 0x07, 0x02, + 0x6e, 0x02, 0x1a, 0x03, 0x5e, 0x02, 0xae, 0x02, 0x31, 0x03, 0x82, 0x02, + 0x4e, 0x03, 0x61, 0x04, 0x19, 0x04, 0x82, 0x04, 0x01, 0x04, 0x0c, 0x03, + 0xd0, 0x04, 0x67, 0x07, 0xf2, 0x08, 0x62, 0x09, 0x04, 0x08, 0xbb, 0x07, + 0x70, 0x08, 0xc8, 0x07, 0x3d, 0x08, 0x64, 0x09, 0x6b, 0x0a, 0xd6, 0x0b, + 0x52, 0x0c, 0x14, 0x0c, 0xd7, 0x0b, 0xdf, 0x0b, 0x9a, 0x0c, 0x15, 0x0e, + 0x4c, 0x0f, 0xa1, 0x0f, 0xa9, 0x10, 0x76, 0x11, 0xa6, 0x11, 0x92, 0x11, + 0xa1, 0x10, 0xe2, 0x10, 0x2d, 0x12, 0xa0, 0x12, 0xc3, 0x12, 0x24, 0x12, + 0xbe, 0x11, 0x30, 0x13, 0x6d, 0x14, 0x1e, 0x14, 0x94, 0x13, 0xda, 0x11, + 0x5c, 0x11, 0x58, 0x12, 0x88, 0x12, 0x29, 0x14, 0xc9, 0x14, 0xc6, 0x13, + 0xa8, 0x14, 0x5d, 0x15, 0x4b, 0x14, 0x33, 0x13, 0x34, 0x11, 0x47, 0x10, + 0x63, 0x11, 0x93, 0x10, 0x6b, 0x0f, 0x24, 0x0f, 0x4e, 0x0f, 0x83, 0x10, + 0xbc, 0x10, 0x22, 0x10, 0x5d, 0x10, 0xe4, 0x10, 0xcf, 0x10, 0x91, 0x10, + 0xa8, 0x0f, 0xa3, 0x0d, 0x7e, 0x0c, 0xc9, 0x0c, 0x5f, 0x0d, 0x08, 0x0e, + 0x80, 0x0d, 0x55, 0x0c, 0xed, 0x0b, 0x43, 0x0b, 0x67, 0x0b, 0x80, 0x0c, + 0x9d, 0x0c, 0xb7, 0x0c, 0x2e, 0x0c, 0xdd, 0x09, 0xab, 0x08, 0x13, 0x08, + 0xbb, 0x07, 0xa6, 0x08, 0x04, 0x08, 0xd0, 0x07, 0xb5, 0x08, 0xaf, 0x07, + 0xed, 0x05, 0x9d, 0x04, 0x69, 0x03, 0xf6, 0x03, 0x5e, 0x05, 0x03, 0x05, + 0xeb, 0x03, 0x16, 0x02, 0x25, 0x00, 0xe4, 0xff, 0xde, 0xff, 0x08, 0xff, + 0x12, 0xff, 0x63, 0xff, 0xfb, 0xfe, 0xba, 0xfd, 0xab, 0xfa, 0x19, 0xf9, + 0x3d, 0xf9, 0x30, 0xfa, 0x1e, 0xfb, 0xd4, 0xf9, 0x82, 0xf7, 0x37, 0xf6, + 0xdf, 0xf5, 0x89, 0xf5, 0x05, 0xf6, 0xe8, 0xf4, 0x7c, 0xf2, 0x4a, 0xf2, + 0xf1, 0xf1, 0x8f, 0xf1, 0x50, 0xf1, 0x58, 0xf0, 0x35, 0xf1, 0x88, 0xf2, + 0x7e, 0xf1, 0xe2, 0xf0, 0x3c, 0xf0, 0x95, 0xee, 0xf2, 0xed, 0xfb, 0xec, + 0x9c, 0xec, 0xe8, 0xed, 0x64, 0xee, 0xb6, 0xed, 0x76, 0xec, 0x4c, 0xea, + 0xcf, 0xe9, 0xd6, 0xeb, 0x3a, 0xec, 0x86, 0xec, 0x1c, 0xec, 0x7c, 0xe9, + 0xab, 0xe8, 0x3e, 0xe9, 0x7c, 0xe9, 0xed, 0xe9, 0xad, 0xe9, 0x59, 0xe9, + 0x7c, 0xea, 0x2b, 0xeb, 0x60, 0xeb, 0x6f, 0xeb, 0xf1, 0xe9, 0x2d, 0xea, + 0x3d, 0xeb, 0x0b, 0xeb, 0x31, 0xeb, 0xc6, 0xea, 0xb3, 0xe9, 0xf0, 0xe9, + 0x7d, 0xea, 0x77, 0xea, 0x3e, 0xeb, 0xad, 0xea, 0xb9, 0xe9, 0x83, 0xea, + 0xea, 0xe9, 0xb5, 0xe9, 0xb4, 0xe9, 0x92, 0xe8, 0x94, 0xe8, 0x37, 0xe8, + 0x6c, 0xe7, 0x70, 0xe7, 0xcd, 0xe7, 0xba, 0xe7, 0x96, 0xe7, 0x4a, 0xe7, + 0x36, 0xe7, 0xf2, 0xe7, 0xad, 0xe7, 0x6c, 0xe7, 0x36, 0xe7, 0x2a, 0xe6, + 0x10, 0xe6, 0x68, 0xe5, 0x71, 0xe4, 0x1f, 0xe5, 0xdd, 0xe5, 0x09, 0xe6, + 0xa9, 0xe6, 0x69, 0xe6, 0x06, 0xe6, 0xe6, 0xe6, 0x6d, 0xe6, 0x60, 0xe5, + 0x5a, 0xe5, 0xca, 0xe5, 0x7c, 0xe6, 0x4e, 0xe7, 0x35, 0xe7, 0x1b, 0xe7, + 0x4b, 0xe8, 0xb3, 0xe8, 0xfc, 0xe9, 0x7d, 0xeb, 0xd3, 0xea, 0x8a, 0xea, + 0x57, 0xea, 0x84, 0xea, 0xfb, 0xeb, 0xb2, 0xeb, 0xd1, 0xe9, 0x12, 0xe9, + 0xb7, 0xe8, 0xf0, 0xe8, 0x9a, 0xea, 0x2c, 0xeb, 0x68, 0xeb, 0x26, 0xec, + 0x2d, 0xec, 0x1a, 0xec, 0xc3, 0xeb, 0xa8, 0xea, 0x20, 0xeb, 0x80, 0xec, + 0x06, 0xed, 0x22, 0xee, 0xea, 0xed, 0x24, 0xed, 0x44, 0xed, 0xf8, 0xec, + 0xae, 0xec, 0x8a, 0xec, 0xb6, 0xec, 0xf1, 0xec, 0xa1, 0xec, 0x17, 0xeb, + 0xb1, 0xea, 0x08, 0xec, 0x5b, 0xed, 0x86, 0xee, 0xd9, 0xed, 0x10, 0xed, + 0xe9, 0xed, 0xc7, 0xed, 0xfe, 0xec, 0x35, 0xec, 0x1f, 0xeb, 0x36, 0xeb, + 0xe3, 0xec, 0x80, 0xee, 0x26, 0xf0, 0x64, 0xf0, 0xd1, 0xef, 0xdf, 0xf0, + 0xa3, 0xf1, 0xdd, 0xf1, 0x1d, 0xf2, 0x51, 0xf1, 0x4e, 0xf0, 0x49, 0xf0, + 0x67, 0xef, 0x0b, 0xef, 0xcb, 0xf0, 0x48, 0xf2, 0xb0, 0xf3, 0x24, 0xf4, + 0x3b, 0xf2, 0xee, 0xf0, 0x87, 0xf0, 0x7e, 0xf0, 0x88, 0xf1, 0x45, 0xf2, + 0x1f, 0xf3, 0x4a, 0xf3, 0x00, 0xf2, 0x1b, 0xf2, 0x4c, 0xf3, 0x6a, 0xf4, + 0xc9, 0xf5, 0x3c, 0xf6, 0x84, 0xf5, 0x96, 0xf5, 0x38, 0xf6, 0x84, 0xf6, + 0x1e, 0xf7, 0x93, 0xf7, 0xe0, 0xf6, 0x05, 0xf6, 0x36, 0xf6, 0x2c, 0xf7, + 0xb6, 0xf8, 0x8e, 0xf9, 0xa9, 0xf9, 0x41, 0xfa, 0xdb, 0xfa, 0x41, 0xfb, + 0xfa, 0xfa, 0xc9, 0xfa, 0x4d, 0xfb, 0x14, 0xfc, 0x9b, 0xfc, 0x12, 0xfd, + 0x57, 0xfd, 0x40, 0xfd, 0xa6, 0xfe, 0x8d, 0xff, 0xdc, 0xff, 0x38, 0x00, + 0xf9, 0xff, 0x83, 0x01, 0xcd, 0x02, 0x37, 0x03, 0x14, 0x04, 0x51, 0x04, + 0x24, 0x05, 0x35, 0x06, 0x7b, 0x05, 0xf2, 0x03, 0x64, 0x04, 0x18, 0x06, + 0x83, 0x07, 0xd4, 0x08, 0xb9, 0x08, 0xab, 0x08, 0xf2, 0x09, 0xee, 0x09, + 0x2f, 0x0a, 0xbd, 0x0a, 0x72, 0x0a, 0xa2, 0x0b, 0x96, 0x0c, 0xe6, 0x0c, + 0xc5, 0x0d, 0x43, 0x0d, 0x09, 0x0c, 0x69, 0x0c, 0x7c, 0x0c, 0x81, 0x0c, + 0xf5, 0x0c, 0xc9, 0x0d, 0x43, 0x0f, 0x89, 0x0f, 0xed, 0x0e, 0xa1, 0x0e, + 0x61, 0x0f, 0xe0, 0x0f, 0xdf, 0x0f, 0x1c, 0x0f, 0xe3, 0x0d, 0x44, 0x0e, + 0x35, 0x0e, 0x07, 0x0e, 0x74, 0x0f, 0xe5, 0x10, 0x8f, 0x11, 0xe8, 0x11, + 0x29, 0x10, 0xe5, 0x0e, 0x66, 0x0f, 0x2e, 0x10, 0x36, 0x12, 0x56, 0x12, + 0x64, 0x11, 0x87, 0x11, 0x56, 0x12, 0xab, 0x13, 0x77, 0x15, 0xe0, 0x16, + 0x6f, 0x16, 0xbf, 0x16, 0xe4, 0x15, 0xb8, 0x15, 0x69, 0x17, 0xd9, 0x18, + 0xec, 0x1a, 0xa3, 0x1b, 0x9a, 0x1b, 0xad, 0x1b, 0xb1, 0x1b, 0x76, 0x1c, + 0x07, 0x1e, 0x04, 0x1f, 0xae, 0x1e, 0xe9, 0x1e, 0xee, 0x1e, 0xde, 0x1e, + 0x7f, 0x1f, 0x2a, 0x1f, 0x29, 0x1f, 0xbf, 0x1f, 0x77, 0x1f, 0x27, 0x1f, + 0x51, 0x1e, 0x29, 0x1d, 0xa3, 0x1c, 0xeb, 0x1d, 0x2a, 0x1f, 0x4e, 0x1f, + 0xbd, 0x1e, 0x73, 0x1c, 0x77, 0x1b, 0x79, 0x1a, 0x1e, 0x1a, 0xcf, 0x1a, + 0x1b, 0x1a, 0x21, 0x1a, 0xc6, 0x19, 0x4e, 0x18, 0x24, 0x17, 0x21, 0x16, + 0x75, 0x15, 0x6c, 0x15, 0xf4, 0x13, 0xb9, 0x12, 0x0f, 0x14, 0xf4, 0x14, + 0x27, 0x15, 0x99, 0x15, 0xa1, 0x14, 0xe5, 0x12, 0x12, 0x13, 0x07, 0x12, + 0x17, 0x11, 0x1a, 0x11, 0xf2, 0x0f, 0xae, 0x10, 0x48, 0x11, 0xea, 0x10, + 0xea, 0x0f, 0xca, 0x0e, 0xc4, 0x0e, 0x44, 0x0e, 0x9f, 0x0c, 0xf0, 0x0a, + 0x48, 0x0b, 0x5f, 0x0c, 0x8b, 0x0d, 0xdd, 0x0d, 0xb2, 0x0b, 0xda, 0x09, + 0xa0, 0x09, 0xe7, 0x09, 0x66, 0x0a, 0x47, 0x0a, 0x6c, 0x09, 0x84, 0x09, + 0x1f, 0x09, 0xf7, 0x07, 0x1c, 0x08, 0xc8, 0x07, 0xa7, 0x07, 0x8c, 0x08, + 0xc0, 0x07, 0x2f, 0x07, 0x2b, 0x07, 0xef, 0x05, 0x2f, 0x06, 0x64, 0x06, + 0x9b, 0x05, 0x18, 0x06, 0x5e, 0x06, 0xb9, 0x05, 0xb6, 0x04, 0xe3, 0x02, + 0x74, 0x02, 0x9b, 0x03, 0xc0, 0x03, 0x5e, 0x04, 0x4d, 0x05, 0x91, 0x05, + 0xe8, 0x06, 0x7a, 0x07, 0x3f, 0x06, 0x8c, 0x05, 0x4b, 0x05, 0xef, 0x04, + 0x93, 0x05, 0xec, 0x05, 0x6f, 0x05, 0x85, 0x05, 0x47, 0x04, 0xac, 0x03, + 0x1d, 0x05, 0x15, 0x06, 0xd0, 0x06, 0x0e, 0x07, 0xba, 0x06, 0x1c, 0x07, + 0xcc, 0x07, 0xf5, 0x08, 0x79, 0x0a, 0xf1, 0x0a, 0xf5, 0x0a, 0xb2, 0x0a, + 0xa6, 0x09, 0x19, 0x0a, 0xf5, 0x0b, 0xa8, 0x0c, 0x56, 0x0d, 0xf1, 0x0d, + 0xcd, 0x0d, 0x2e, 0x0e, 0xda, 0x0d, 0x08, 0x0d, 0x52, 0x0d, 0x61, 0x0d, + 0xa8, 0x0d, 0x0a, 0x0e, 0xcb, 0x0d, 0x23, 0x0e, 0x0e, 0x0e, 0x8d, 0x0d, + 0x5d, 0x0d, 0xa8, 0x0c, 0x96, 0x0b, 0x08, 0x0b, 0xf2, 0x0a, 0xad, 0x0a, + 0x91, 0x0b, 0xe1, 0x0c, 0xdd, 0x0c, 0x8c, 0x0d, 0x98, 0x0d, 0xfc, 0x0c, + 0x41, 0x0d, 0xa0, 0x0b, 0xb1, 0x0a, 0x87, 0x0b, 0xb4, 0x0b, 0x54, 0x0d, + 0x16, 0x0e, 0xbc, 0x0c, 0x2e, 0x0c, 0xc0, 0x0b, 0x03, 0x0b, 0xd6, 0x0a, + 0xa1, 0x0a, 0x75, 0x0a, 0x45, 0x0b, 0x10, 0x0b, 0x36, 0x09, 0xcb, 0x08, + 0x38, 0x09, 0x13, 0x09, 0x44, 0x09, 0x12, 0x09, 0x41, 0x09, 0xca, 0x08, + 0x57, 0x07, 0xc0, 0x07, 0xfb, 0x07, 0x99, 0x07, 0xf7, 0x07, 0x0b, 0x08, + 0x92, 0x07, 0x97, 0x07, 0x1b, 0x07, 0x34, 0x06, 0x15, 0x06, 0xfc, 0x04, + 0xef, 0x03, 0xb4, 0x03, 0xf9, 0x02, 0x76, 0x02, 0xd9, 0x01, 0xc8, 0x00, + 0x1c, 0x00, 0x0f, 0xff, 0x1e, 0xfd, 0x0e, 0xfc, 0x38, 0xfb, 0x8c, 0xfa, + 0x5e, 0xfa, 0xb7, 0xf8, 0x24, 0xf8, 0x55, 0xf8, 0x7e, 0xf7, 0x2c, 0xf7, + 0x98, 0xf6, 0x9f, 0xf5, 0x76, 0xf5, 0xd9, 0xf5, 0x65, 0xf5, 0xb2, 0xf5, + 0x74, 0xf6, 0xef, 0xf5, 0x78, 0xf6, 0xc5, 0xf6, 0x7d, 0xf6, 0xdd, 0xf6, + 0x88, 0xf6, 0x54, 0xf6, 0x74, 0xf6, 0x24, 0xf6, 0xbd, 0xf5, 0xf2, 0xf5, + 0x91, 0xf4, 0x7f, 0xf4, 0x0a, 0xf5, 0x57, 0xf4, 0x4a, 0xf5, 0x25, 0xf5, + 0xa0, 0xf4, 0x71, 0xf4, 0x35, 0xf3, 0x0e, 0xf2, 0x6a, 0xf1, 0x2f, 0xf1, + 0xff, 0xf0, 0xd6, 0xf1, 0x4b, 0xf1, 0x35, 0xf0, 0xd8, 0xef, 0xe6, 0xee, + 0x0d, 0xef, 0x49, 0xee, 0x9e, 0xec, 0x27, 0xec, 0x3e, 0xeb, 0x1b, 0xeb, + 0x85, 0xeb, 0xf2, 0xea, 0x97, 0xeb, 0x00, 0xec, 0xcb, 0xeb, 0x63, 0xeb, + 0xdf, 0xea, 0x87, 0xea, 0x68, 0xea, 0xea, 0xea, 0x75, 0xe9, 0x69, 0xe9, + 0x76, 0xe9, 0xbe, 0xe7, 0xbf, 0xe7, 0xf5, 0xe6, 0xa0, 0xe7, 0x0e, 0xe9, + 0x8a, 0xe9, 0x23, 0xea, 0xf8, 0xe9, 0x36, 0xea, 0x99, 0xea, 0x7a, 0xeb, + 0xbc, 0xeb, 0x25, 0xed, 0x3b, 0xef, 0x82, 0xee, 0x3c, 0xef, 0x85, 0xf0, + 0xbe, 0xf0, 0x5d, 0xf2, 0x90, 0xf2, 0xd0, 0xf1, 0x22, 0xf2, 0xef, 0xf1, + 0x1f, 0xf2, 0x7f, 0xf2, 0x0b, 0xf2, 0xda, 0xf2, 0xf7, 0xf3, 0xd5, 0xf2, + 0x47, 0xf2, 0x23, 0xf2, 0x50, 0xf1, 0xb5, 0xf1, 0xea, 0xf0, 0x64, 0xf0, + 0x68, 0xf0, 0xf0, 0xee, 0x48, 0xee, 0x38, 0xee, 0x59, 0xed, 0x73, 0xed, + 0x91, 0xee, 0x42, 0xee, 0xf4, 0xee, 0xf5, 0xef, 0xbc, 0xee, 0x3b, 0xee, + 0x7a, 0xee, 0xd2, 0xef, 0xf8, 0xf0, 0x7e, 0xf1, 0x83, 0xf1, 0x64, 0xf1, + 0xa2, 0xf2, 0x40, 0xf3, 0x17, 0xf3, 0x7d, 0xf1, 0xba, 0xef, 0xf1, 0xef, + 0xdf, 0xef, 0x6e, 0xf0, 0x46, 0xf1, 0x1d, 0xf1, 0x59, 0xf2, 0xbc, 0xf3, + 0xc2, 0xf3, 0xe2, 0xf4, 0xbe, 0xf3, 0x43, 0xf2, 0x4e, 0xf3, 0x7e, 0xf1, + 0x75, 0xef, 0x27, 0xee, 0x01, 0xed, 0x82, 0xee, 0x92, 0xf0, 0x10, 0xf2, + 0xe5, 0xf3, 0xe5, 0xf5, 0xe8, 0xf7, 0xab, 0xfa, 0x89, 0xfb, 0xe5, 0xf9, + 0xa1, 0xf8, 0x23, 0xf6, 0xc8, 0xf4, 0x28, 0xf5, 0x23, 0xf4, 0xe0, 0xf3, + 0xe2, 0xf2, 0xe9, 0xf2, 0x2c, 0xf5, 0xcd, 0xf5, 0xcc, 0xf4, 0xea, 0xf2, + 0x78, 0xf2, 0x46, 0xf1, 0xce, 0xf2, 0xf5, 0xf4, 0x0b, 0xf3, 0x13, 0xf4, + 0xaf, 0xf4, 0xcc, 0xf6, 0x2f, 0xf8, 0x31, 0xf5, 0x67, 0xf4, 0xb1, 0xf2, + 0xe9, 0xf1, 0x3f, 0xf2, 0xc2, 0xef, 0x57, 0xee, 0xdf, 0xef, 0x48, 0xf1, + 0x9e, 0xf2, 0xd9, 0xf4, 0x2e, 0xf6, 0x83, 0xf7, 0x52, 0xf9, 0x95, 0xfa, + 0x3f, 0xfb, 0xf8, 0xfb, 0x6c, 0xfb, 0x6f, 0xfa, 0x83, 0xf9, 0xce, 0xf8, + 0xa6, 0xfa, 0xdb, 0xfc, 0xb5, 0xfd, 0x88, 0xfd, 0xee, 0xfd, 0xd1, 0xfe, + 0xa6, 0xff, 0x49, 0x00, 0xdc, 0xfe, 0x99, 0xfd, 0x6d, 0xfd, 0xc7, 0xfc, + 0xc1, 0xfd, 0x3d, 0xfe, 0x33, 0xfe, 0x2a, 0x00, 0xef, 0xff, 0xc4, 0x00, + 0x12, 0x02, 0x15, 0x01, 0x8e, 0x02, 0xdd, 0x01, 0x85, 0x00, 0xcb, 0x01, + 0x9c, 0x02, 0x07, 0x04, 0x1d, 0x04, 0xc5, 0x03, 0x66, 0x07, 0x6e, 0x0b, + 0x49, 0x0d, 0x5c, 0x0f, 0x71, 0x10, 0x1c, 0x12, 0xf0, 0x14, 0x57, 0x16, + 0x6c, 0x17, 0xdb, 0x18, 0x1d, 0x1a, 0x41, 0x1c, 0xf4, 0x1d, 0x60, 0x1b, + 0x7f, 0x19, 0xae, 0x1d, 0xa2, 0x22, 0xb1, 0x22, 0xcd, 0x1e, 0x4b, 0x1a, + 0xa4, 0x19, 0x18, 0x18, 0x91, 0x11, 0xf5, 0x0f, 0x8e, 0x14, 0xfb, 0x1a, + 0xc8, 0x1b, 0x33, 0x12, 0xe3, 0x09, 0xf5, 0x0b, 0xe0, 0x13, 0xec, 0x17, + 0xb3, 0x12, 0xa6, 0x09, 0x24, 0x06, 0xef, 0x07, 0x60, 0x0d, 0xdd, 0x11, + 0x5f, 0x0d, 0x16, 0x08, 0x64, 0x08, 0x72, 0x05, 0xc4, 0x01, 0xe4, 0x03, + 0xe9, 0x0a, 0xf1, 0x12, 0xa9, 0x0b, 0x5e, 0xfd, 0x9b, 0xfb, 0xaa, 0x03, + 0xd2, 0x11, 0xb3, 0x19, 0x16, 0x15, 0xb7, 0x0c, 0x91, 0x02, 0xd9, 0xfd, + 0xa1, 0x08, 0xdd, 0x15, 0x4d, 0x19, 0x48, 0x18, 0x43, 0x1b, 0xa7, 0x21, + 0xf0, 0x1c, 0xc4, 0x0a, 0x45, 0xfe, 0x6d, 0x04, 0xd3, 0x12, 0xca, 0x13, + 0x6c, 0x03, 0x58, 0xfe, 0xc2, 0x0c, 0x6a, 0x18, 0x23, 0x16, 0xe2, 0x05, + 0x5e, 0xf7, 0x17, 0xf5, 0x39, 0xf7, 0x64, 0xfa, 0xb1, 0xf9, 0xed, 0xec, + 0xc6, 0xf0, 0xbd, 0x0f, 0xb0, 0x1c, 0x83, 0x05, 0x7d, 0xe7, 0x08, 0xdf, + 0xde, 0xea, 0xc7, 0xfa, 0xe3, 0xf8, 0x28, 0xed, 0x32, 0xef, 0x90, 0xf7, + 0xe8, 0xf2, 0xca, 0xd5, 0xc5, 0xbd, 0x11, 0xc9, 0x3c, 0xe1, 0x31, 0xe5, + 0xc2, 0xd2, 0x6d, 0xcc, 0x5b, 0xd7, 0x92, 0xd6, 0x99, 0xd6, 0x74, 0xd6, + 0xa0, 0xd5, 0x23, 0xdd, 0x82, 0xd7, 0x93, 0xbb, 0xc2, 0x98, 0xc1, 0x8a, + 0x7e, 0x8c, 0x55, 0xa1, 0xbf, 0xbf, 0xb8, 0xef, 0x47, 0x45, 0xad, 0x76, + 0x88, 0x76, 0x77, 0x66, 0x50, 0x32, 0x5c, 0xf0, 0xf7, 0xc3, 0x0a, 0xa6, + 0x73, 0xa9, 0x34, 0xc7, 0xc5, 0xe3, 0xc3, 0xfc, 0x1d, 0x07, 0xd7, 0x0e, + 0x25, 0x06, 0x5a, 0xeb, 0x7b, 0xe4, 0xca, 0xf5, 0xec, 0xfd, 0x3c, 0xf6, + 0x39, 0xea, 0x0e, 0xe1, 0x80, 0xeb, 0xee, 0xed, 0x31, 0xeb, 0x89, 0xee, + 0x38, 0xef, 0xdd, 0xf8, 0x74, 0x02, 0xeb, 0x04, 0x48, 0x05, 0xfa, 0x10, + 0xc3, 0x1c, 0x7a, 0x15, 0xcc, 0x0b, 0x71, 0x0b, 0x24, 0x09, 0x35, 0x09, + 0x3a, 0x10, 0xf5, 0x0f, 0x01, 0x08, 0x9c, 0x03, 0x9f, 0x09, 0x1a, 0x19, + 0xd1, 0x22, 0x02, 0x28, 0x15, 0x36, 0xb0, 0x3b, 0x3f, 0x2f, 0x5f, 0x20, + 0x47, 0x1f, 0xc2, 0x29, 0x87, 0x3f, 0x28, 0x4c, 0xfc, 0x3e, 0xbc, 0x32, + 0x09, 0x2d, 0x0f, 0x2e, 0x2b, 0x2e, 0x49, 0x3c, 0x05, 0x52, 0x5f, 0x58, + 0xf9, 0x5d, 0x06, 0x5d, 0xfd, 0x53, 0x74, 0x47, 0x44, 0x46, 0x88, 0x4d, + 0xed, 0x56, 0xed, 0x5b, 0xb0, 0x56, 0xc3, 0x50, 0x90, 0x49, 0xe8, 0x4c, + 0x11, 0x55, 0xad, 0x55, 0xf9, 0x4d, 0x9c, 0x4b, 0xce, 0x4f, 0x4b, 0x4e, + 0x19, 0x49, 0x4e, 0x49, 0x86, 0x54, 0xb9, 0x5a, 0x61, 0x54, 0x0a, 0x47, + 0x03, 0x42, 0xf1, 0x43, 0x53, 0x48, 0xd2, 0x52, 0xcb, 0x56, 0x88, 0x54, + 0x90, 0x4f, 0x30, 0x49, 0x44, 0x48, 0x0b, 0x49, 0xcd, 0x45, 0x02, 0x42, + 0xfb, 0x3c, 0xd6, 0x3c, 0x76, 0x47, 0x81, 0x54, 0x9c, 0x57, 0x15, 0x4d, + 0x9a, 0x3e, 0x69, 0x36, 0xbb, 0x3a, 0x21, 0x44, 0x5f, 0x48, 0x89, 0x48, + 0x68, 0x42, 0xf3, 0x35, 0x7d, 0x31, 0xf1, 0x34, 0x63, 0x3c, 0xf6, 0x41, + 0xaf, 0x3e, 0xcb, 0x37, 0x5c, 0x2d, 0x60, 0x28, 0xdc, 0x29, 0x34, 0x2c, + 0x60, 0x28, 0x8f, 0x20, 0xcc, 0x20, 0xe0, 0x24, 0xd8, 0x25, 0xa4, 0x1c, + 0x94, 0x14, 0x69, 0x16, 0xf3, 0x1a, 0x1a, 0x21, 0xf6, 0x22, 0xd5, 0x19, + 0x7a, 0x11, 0x5c, 0x11, 0x32, 0x13, 0xb3, 0x19, 0x66, 0x17, 0x88, 0x09, + 0x5d, 0xfe, 0xa9, 0xf4, 0x87, 0xeb, 0x1e, 0xe3, 0x2c, 0xe6, 0x89, 0xfd, + 0x47, 0x0d, 0xe3, 0x00, 0x64, 0xf2, 0x0a, 0xec, 0x68, 0xe5, 0x33, 0xe6, + 0x70, 0xe5, 0x91, 0xe0, 0xc4, 0xdf, 0xe3, 0xd5, 0x77, 0xc8, 0xef, 0xc2, + 0x34, 0xc6, 0x09, 0xcd, 0x25, 0xc6, 0x99, 0xc3, 0xdd, 0xd0, 0x7c, 0xdb, + 0x9d, 0xdc, 0x31, 0xce, 0xd1, 0xbf, 0x77, 0xc0, 0x1b, 0xc3, 0x91, 0xcb, + 0xfb, 0xd5, 0xbb, 0xcc, 0xb9, 0xb8, 0x3d, 0xae, 0xea, 0xb1, 0x23, 0xbb, + 0xa9, 0xbf, 0x18, 0xb6, 0xa1, 0xaa, 0xf5, 0xb3, 0x66, 0xc3, 0xc6, 0xbd, + 0x33, 0xa5, 0x84, 0x9b, 0xc0, 0xa4, 0xe0, 0xb2, 0x9f, 0xbd, 0xf5, 0xb4, + 0x59, 0xa8, 0x60, 0xa0, 0x3a, 0x9c, 0x5e, 0xa0, 0xac, 0xa2, 0x46, 0xa2, + 0xe5, 0xa2, 0x8d, 0xa4, 0x8b, 0xa6, 0xbf, 0xa3, 0x2e, 0x9f, 0x44, 0xa3, + 0xf1, 0xa7, 0xef, 0xa3, 0xf1, 0x9b, 0xf3, 0x9d, 0x32, 0xa4, 0x95, 0xa2, + 0x4b, 0xa1, 0x30, 0xa2, 0xda, 0xae, 0x81, 0xb6, 0x4b, 0xb0, 0xad, 0xb0, + 0x57, 0xb0, 0xf9, 0xb5, 0x43, 0xc0, 0x9d, 0xbd, 0xa8, 0xb3, 0x29, 0xad, + 0x4e, 0xab, 0x85, 0xac, 0xe9, 0xb1, 0xa9, 0xb6, 0x90, 0xb3, 0xb7, 0xab, + 0xe2, 0xaf, 0xa7, 0xba, 0xd3, 0xb6, 0x1e, 0xaf, 0xdf, 0xac, 0x88, 0xac, + 0xad, 0xb3, 0xe3, 0xbb, 0x8f, 0xbf, 0x3e, 0xc0, 0x8a, 0xba, 0x40, 0xb3, + 0x9c, 0xad, 0xeb, 0xa9, 0x18, 0xb3, 0xdd, 0xc3, 0x50, 0xc6, 0x16, 0xbe, + 0x5f, 0xba, 0xc0, 0xc3, 0x72, 0xd0, 0x87, 0xce, 0x7e, 0xc1, 0xc5, 0xbb, + 0x88, 0xc8, 0x9b, 0xd9, 0x6e, 0xe4, 0xea, 0xe0, 0x39, 0xd9, 0xb6, 0xe1, + 0x8a, 0xf2, 0x34, 0xfb, 0x34, 0xec, 0x72, 0xd6, 0x3b, 0xd3, 0x7f, 0xe5, + 0x2c, 0xf2, 0x08, 0xea, 0x14, 0xec, 0xa7, 0xf8, 0xd1, 0x03, 0x45, 0x0a, + 0xc7, 0x05, 0x9d, 0xfa, 0x66, 0xf2, 0x9c, 0xf4, 0xe5, 0xf9, 0xa2, 0x01, + 0x74, 0x0c, 0xb2, 0x1a, 0xcd, 0x2a, 0x18, 0x2c, 0x23, 0x29, 0x41, 0x32, + 0x20, 0x3a, 0x0d, 0x35, 0xb4, 0x26, 0xe9, 0x1f, 0x17, 0x28, 0xeb, 0x38, + 0xd1, 0x46, 0x7a, 0x4a, 0x87, 0x4d, 0x65, 0x52, 0x7f, 0x58, 0x07, 0x5a, + 0x32, 0x53, 0xed, 0x4c, 0xb5, 0x4d, 0x51, 0x53, 0x74, 0x51, 0x8b, 0x51, + 0x0b, 0x54, 0x1c, 0x52, 0xbd, 0x57, 0xaf, 0x5a, 0x6f, 0x58, 0xad, 0x5c, + 0x27, 0x61, 0xd9, 0x5e, 0x14, 0x59, 0x55, 0x57, 0xf1, 0x58, 0x86, 0x53, + 0x56, 0x4b, 0x87, 0x41, 0xee, 0x34, 0xa3, 0x3b, 0x86, 0x4d, 0x46, 0x53, + 0xae, 0x4e, 0x70, 0x49, 0x07, 0x4c, 0x55, 0x54, 0xd0, 0x5d, 0x3b, 0x5c, + 0xee, 0x4e, 0x38, 0x46, 0xcf, 0x4a, 0xe4, 0x55, 0x5d, 0x58, 0x68, 0x4f, + 0x20, 0x46, 0x6f, 0x49, 0x66, 0x50, 0x86, 0x53, 0xc4, 0x56, 0x34, 0x56, + 0x74, 0x54, 0x78, 0x51, 0x1c, 0x4a, 0x9f, 0x42, 0x2f, 0x40, 0x7c, 0x3e, + 0x6f, 0x3c, 0xa9, 0x3b, 0x81, 0x37, 0x4d, 0x35, 0x73, 0x36, 0xad, 0x3b, + 0xac, 0x3e, 0xb0, 0x32, 0xd8, 0x2f, 0x92, 0x38, 0x74, 0x38, 0xe3, 0x3c, + 0x7d, 0x3d, 0x98, 0x33, 0x02, 0x2a, 0xea, 0x1f, 0xab, 0x20, 0xc9, 0x2a, + 0x95, 0x2b, 0xe1, 0x1e, 0x60, 0x15, 0xe1, 0x13, 0x28, 0x1a, 0x4d, 0x2f, + 0xed, 0x34, 0x85, 0x23, 0xa8, 0x19, 0x1a, 0x1f, 0xb3, 0x2f, 0x9e, 0x36, + 0xff, 0x2d, 0x58, 0x22, 0xf7, 0x17, 0x0f, 0x15, 0xf3, 0x14, 0x9c, 0x1b, + 0x08, 0x1d, 0xf0, 0x12, 0x67, 0x14, 0xa9, 0x15, 0xf1, 0x0f, 0x86, 0x09, + 0x39, 0xfe, 0xd3, 0xf6, 0x68, 0xfa, 0xec, 0x01, 0x68, 0x03, 0x5a, 0xfe, + 0xb3, 0xfa, 0x36, 0xfc, 0x7e, 0xfc, 0xa6, 0xf4, 0x9a, 0xea, 0x53, 0xee, + 0x21, 0xf7, 0xd6, 0xf4, 0x51, 0xe7, 0xb0, 0xdc, 0xf3, 0xdf, 0xc8, 0xdf, + 0x6e, 0xd9, 0x80, 0xd5, 0x69, 0xdb, 0x52, 0xe4, 0x3a, 0xe1, 0x25, 0xd9, + 0xce, 0xd2, 0x87, 0xd4, 0x98, 0xd4, 0x3f, 0xce, 0x4b, 0xc9, 0x3e, 0xce, + 0xad, 0xd7, 0x69, 0xce, 0x0f, 0xc6, 0x85, 0xcc, 0x08, 0xd2, 0x79, 0xd5, + 0xe4, 0xd0, 0x68, 0xcd, 0xac, 0xcf, 0xd6, 0xc8, 0x20, 0xc5, 0xe7, 0xc6, + 0x93, 0xc6, 0xad, 0xcd, 0xe9, 0xd0, 0xce, 0xc8, 0x2c, 0xc7, 0x99, 0xd0, + 0x1a, 0xda, 0xd5, 0xdb, 0x41, 0xd5, 0xf5, 0xce, 0x36, 0xc9, 0xa6, 0xc6, + 0xc2, 0xca, 0xc4, 0xc5, 0x38, 0xbb, 0xf3, 0xba, 0xbd, 0xc0, 0x13, 0xc6, + 0x32, 0xc9, 0x35, 0xc8, 0x65, 0xc8, 0xa4, 0xc7, 0xca, 0xc0, 0x67, 0xbe, + 0xa0, 0xc1, 0x58, 0xc4, 0x8b, 0xc3, 0x3c, 0xbe, 0x08, 0xba, 0x39, 0xc0, + 0x65, 0xcb, 0x69, 0xcf, 0xa6, 0xcf, 0xba, 0xc6, 0xec, 0xbb, 0x85, 0xc0, + 0xad, 0xcb, 0x4e, 0xd7, 0x4f, 0xdb, 0xd6, 0xce, 0xab, 0xc5, 0xf0, 0xc4, + 0x80, 0xc6, 0xd2, 0xc9, 0x09, 0xc6, 0x56, 0xc9, 0x28, 0xd0, 0x1d, 0xce, + 0x92, 0xce, 0xb3, 0xcb, 0xb7, 0xca, 0xae, 0xd3, 0x6a, 0xdc, 0x72, 0xda, + 0x0c, 0xd2, 0x74, 0xd0, 0xa7, 0xd7, 0xda, 0xe0, 0x14, 0xdd, 0xb3, 0xd7, + 0xe1, 0xe4, 0xe6, 0xee, 0xf0, 0xed, 0xa0, 0xee, 0x07, 0xe8, 0xd6, 0xe1, + 0x3a, 0xe0, 0x20, 0xe1, 0xa9, 0xf4, 0xa9, 0x04, 0xb0, 0x05, 0xf0, 0x06, + 0x88, 0x06, 0x38, 0x08, 0x14, 0x08, 0x83, 0xfe, 0x8c, 0xf1, 0x85, 0xf0, + 0x66, 0xfc, 0xee, 0x07, 0x6f, 0x08, 0x84, 0x02, 0x3f, 0x02, 0x0c, 0x07, + 0x28, 0x11, 0x1b, 0x18, 0x1b, 0x18, 0xd0, 0x1a, 0x07, 0x21, 0xf6, 0x1c, + 0x02, 0x10, 0x9c, 0x0f, 0xf9, 0x0f, 0xd1, 0x08, 0xaa, 0x0d, 0xcc, 0x15, + 0xf8, 0x17, 0xe4, 0x18, 0xe3, 0x15, 0x6f, 0x19, 0x97, 0x23, 0x95, 0x2a, + 0xc5, 0x29, 0x30, 0x22, 0xf9, 0x1c, 0x61, 0x1c, 0x58, 0x23, 0x3b, 0x30, + 0xbf, 0x3e, 0xb3, 0x41, 0x55, 0x3b, 0x97, 0x38, 0x1e, 0x34, 0x95, 0x31, + 0x18, 0x36, 0x94, 0x3f, 0x25, 0x4b, 0xcb, 0x51, 0x84, 0x4a, 0xaa, 0x40, + 0x84, 0x42, 0x76, 0x4e, 0xe9, 0x57, 0xeb, 0x57, 0x1e, 0x56, 0xc0, 0x54, + 0xb5, 0x53, 0x00, 0x53, 0x3b, 0x58, 0x31, 0x5b, 0x5f, 0x56, 0x83, 0x4a, + 0x3c, 0x46, 0xde, 0x4f, 0xcf, 0x4d, 0xda, 0x49, 0x93, 0x4a, 0x1d, 0x46, + 0xf7, 0x46, 0x49, 0x4e, 0xd4, 0x48, 0xf6, 0x40, 0x54, 0x48, 0x11, 0x51, + 0x4e, 0x52, 0xc2, 0x4a, 0xad, 0x45, 0xa9, 0x45, 0x9b, 0x4b, 0x85, 0x57, + 0x97, 0x57, 0x35, 0x4c, 0x24, 0x4c, 0x2d, 0x51, 0x1f, 0x52, 0x51, 0x50, + 0x1d, 0x3f, 0x2c, 0x32, 0xab, 0x30, 0x7d, 0x37, 0x57, 0x3e, 0xf7, 0x32, + 0xe0, 0x28, 0x4b, 0x26, 0xf7, 0x23, 0x2f, 0x25, 0x99, 0x20, 0xad, 0x1b, + 0x32, 0x20, 0x4c, 0x1f, 0x98, 0x23, 0xfc, 0x25, 0x0f, 0x1d, 0x00, 0x18, + 0x6b, 0x16, 0x1e, 0x22, 0xc0, 0x2c, 0xc0, 0x23, 0x69, 0x19, 0x7b, 0x1a, + 0xcf, 0x1e, 0xf6, 0x26, 0x84, 0x25, 0xbf, 0x1d, 0x9a, 0x1f, 0x7c, 0x1b, + 0x77, 0x15, 0x07, 0x13, 0xb7, 0x18, 0xd7, 0x20, 0x75, 0x1a, 0xbe, 0x12, + 0xa8, 0x11, 0x2e, 0x0e, 0x03, 0x0c, 0xaf, 0x08, 0x82, 0x0b, 0x04, 0x14, + 0xa8, 0x13, 0xae, 0x0c, 0x7b, 0xf9, 0x7e, 0xf4, 0xe3, 0x01, 0x4c, 0x11, + 0x79, 0x1b, 0xf8, 0x0d, 0x31, 0xfb, 0xec, 0xf4, 0xf1, 0xfa, 0x22, 0x03, + 0x98, 0x04, 0x4b, 0x02, 0xab, 0x07, 0xa5, 0x08, 0xb9, 0x00, 0xb8, 0xfa, + 0x15, 0xf2, 0x71, 0xf0, 0x9e, 0xf1, 0x3a, 0xf2, 0x75, 0xec, 0xe0, 0xdf, + 0x0b, 0xd8, 0xef, 0xe0, 0xa7, 0xee, 0x5d, 0xea, 0xf1, 0xe2, 0x65, 0xdc, + 0x28, 0xd8, 0x90, 0xd5, 0x81, 0xd2, 0xb8, 0xcf, 0x6d, 0xd0, 0x9a, 0xd3, + 0x9d, 0xcd, 0xb0, 0xc8, 0xf5, 0xc7, 0x51, 0xca, 0x5b, 0xcc, 0x66, 0xcc, + 0xd8, 0xd1, 0x4a, 0xd5, 0x59, 0xd2, 0x74, 0xcb, 0x4a, 0xbe, 0xd2, 0xb3, + 0x5c, 0xb4, 0x21, 0xb9, 0xbc, 0xc0, 0x29, 0xc6, 0x92, 0xc6, 0xe7, 0xc6, + 0x33, 0xc4, 0xa8, 0xbd, 0xfe, 0xb7, 0x8e, 0xb7, 0x0d, 0xbe, 0x6c, 0xc1, + 0x81, 0xbd, 0xbc, 0xbc, 0x97, 0xc0, 0x5e, 0xc3, 0xd1, 0xc5, 0xd3, 0xcd, + 0x25, 0xce, 0x97, 0xc4, 0xcf, 0xbc, 0xc0, 0xba, 0x48, 0xc6, 0x9f, 0xce, + 0x01, 0xce, 0xa8, 0xce, 0xab, 0xc9, 0x90, 0xc8, 0xda, 0xd2, 0x76, 0xdb, + 0x6c, 0xde, 0xf9, 0xdb, 0x71, 0xd8, 0x98, 0xd1, 0x1a, 0xc9, 0x93, 0xcb, + 0xd2, 0xcf, 0xdb, 0xd3, 0x6b, 0xd1, 0xa8, 0xca, 0x8a, 0xce, 0x56, 0xcf, + 0x7a, 0xcf, 0x51, 0xd3, 0xc8, 0xd9, 0x62, 0xe2, 0x76, 0xe1, 0x9c, 0xd8, + 0xb1, 0xd2, 0x2a, 0xcf, 0x7e, 0xc9, 0x05, 0xc9, 0x0e, 0xca, 0xdf, 0xc6, + 0x96, 0xc4, 0x29, 0xc3, 0x62, 0xc2, 0x69, 0xc4, 0xd3, 0xc9, 0x62, 0xcb, + 0xf3, 0xc5, 0xbb, 0xbc, 0xe5, 0xb8, 0xc3, 0xc4, 0xdb, 0xd0, 0x71, 0xd2, + 0xab, 0xce, 0xba, 0xc6, 0x41, 0xcb, 0x8c, 0xda, 0xa7, 0xe4, 0x3b, 0xe4, + 0xb5, 0xd4, 0x69, 0xcb, 0x79, 0xd1, 0x98, 0xdb, 0x96, 0xe5, 0x0f, 0xea, + 0x8b, 0xe9, 0xc3, 0xe3, 0xfe, 0xe1, 0x16, 0xe9, 0x31, 0xf2, 0x74, 0xf9, + 0xba, 0xfb, 0x20, 0xfe, 0x2f, 0x01, 0x9d, 0x01, 0x1d, 0xff, 0x86, 0xff, + 0x32, 0x05, 0x82, 0x0a, 0x08, 0x09, 0xfc, 0x00, 0xc0, 0xfe, 0x7c, 0x03, + 0xb8, 0x0c, 0x40, 0x0e, 0x97, 0x02, 0xb9, 0xf7, 0x43, 0xf2, 0xaf, 0xf8, + 0x6e, 0x0a, 0x4a, 0x18, 0x43, 0x12, 0x0a, 0x02, 0xf0, 0xf8, 0x2e, 0xfd, + 0x4e, 0x08, 0x81, 0x05, 0xa7, 0xfa, 0xb8, 0xf4, 0x0d, 0xf0, 0x77, 0xf2, + 0x38, 0x02, 0xe4, 0x09, 0x7a, 0x08, 0xc3, 0xff, 0xb0, 0xf6, 0xdf, 0xff, + 0x3f, 0x05, 0x1f, 0x0d, 0x94, 0x11, 0x19, 0x0e, 0x0d, 0x0c, 0x85, 0x0d, + 0xaf, 0x1d, 0x81, 0x1d, 0xdf, 0x10, 0xac, 0x04, 0xb1, 0x01, 0xb6, 0x0b, + 0x2f, 0x11, 0x9f, 0x14, 0xd8, 0x1b, 0x14, 0x23, 0xc6, 0x23, 0xd7, 0x28, + 0xf3, 0x27, 0xff, 0x2c, 0x62, 0x34, 0x1f, 0x33, 0x41, 0x32, 0x4a, 0x29, + 0x76, 0x2b, 0xd4, 0x28, 0x9b, 0x28, 0x12, 0x33, 0x0d, 0x37, 0x64, 0x39, + 0xfa, 0x37, 0x9a, 0x38, 0x26, 0x39, 0x8e, 0x3f, 0xcc, 0x41, 0x85, 0x3e, + 0x3a, 0x36, 0x4f, 0x2f, 0xec, 0x33, 0x75, 0x34, 0x23, 0x35, 0x2f, 0x30, + 0x56, 0x2c, 0x96, 0x2c, 0x19, 0x2e, 0xbb, 0x33, 0x7d, 0x35, 0x2e, 0x36, + 0xa8, 0x30, 0x7b, 0x2d, 0x1e, 0x30, 0xa7, 0x31, 0xf9, 0x31, 0xe2, 0x31, + 0x11, 0x30, 0x42, 0x2c, 0xe2, 0x2a, 0xdb, 0x29, 0xfa, 0x31, 0x2e, 0x3a, + 0xa5, 0x35, 0xef, 0x2d, 0x4d, 0x2a, 0x7a, 0x30, 0x4d, 0x37, 0x85, 0x35, + 0x41, 0x35, 0x54, 0x39, 0x17, 0x35, 0xb8, 0x2f, 0x32, 0x31, 0x44, 0x33, + 0x48, 0x39, 0x4b, 0x3a, 0xd7, 0x37, 0x62, 0x39, 0x32, 0x35, 0xe8, 0x33, + 0xc7, 0x38, 0xd2, 0x3a, 0x98, 0x38, 0x22, 0x37, 0xb0, 0x37, 0x61, 0x31, + 0x6a, 0x2d, 0x63, 0x2f, 0x67, 0x31, 0x65, 0x31, 0xc2, 0x28, 0x6c, 0x25, + 0xb7, 0x2a, 0x87, 0x34, 0xfa, 0x3b, 0x8b, 0x3a, 0x13, 0x3e, 0xbe, 0x3a, + 0xe2, 0x2c, 0x6d, 0x23, 0xaa, 0x25, 0x12, 0x34, 0x8d, 0x3d, 0xe2, 0x3d, + 0x0e, 0x3c, 0x7a, 0x3c, 0x95, 0x3b, 0xa7, 0x39, 0x0b, 0x41, 0xb1, 0x45, + 0xbc, 0x40, 0x90, 0x40, 0x34, 0x43, 0xf2, 0x42, 0x8a, 0x3f, 0xbc, 0x3a, + 0x03, 0x3a, 0x73, 0x3b, 0x60, 0x3d, 0x75, 0x3c, 0x1f, 0x39, 0x53, 0x39, + 0x2a, 0x3d, 0x75, 0x40, 0x3e, 0x3f, 0x1e, 0x3d, 0x5a, 0x36, 0x4e, 0x2d, + 0x38, 0x2c, 0xb5, 0x2f, 0x84, 0x2d, 0x5f, 0x20, 0xf8, 0x11, 0x48, 0x0e, + 0xd5, 0x12, 0x21, 0x13, 0x3c, 0x0c, 0x93, 0x04, 0x55, 0x05, 0x67, 0x08, + 0xb1, 0xfa, 0x7c, 0xeb, 0xc1, 0xea, 0x08, 0xf2, 0xed, 0xf9, 0xe0, 0xf6, + 0xe6, 0xeb, 0xa9, 0xdd, 0x48, 0xd7, 0x45, 0xe2, 0x31, 0xe6, 0x07, 0xe0, + 0x2e, 0xe0, 0x24, 0xe8, 0x16, 0xee, 0xf6, 0xe0, 0x46, 0xd2, 0x3d, 0xcd, + 0xd1, 0xd5, 0x5f, 0xe7, 0x42, 0xe4, 0x38, 0xda, 0xce, 0xd1, 0xdf, 0xd2, + 0xad, 0xda, 0xf4, 0xd7, 0x59, 0xd9, 0x62, 0xdb, 0xee, 0xd8, 0x1a, 0xcf, + 0xa8, 0xc9, 0x34, 0xcf, 0xee, 0xd7, 0xfa, 0xe3, 0x4c, 0xe9, 0x47, 0xe4, + 0xa8, 0xdb, 0x1c, 0xdd, 0xfb, 0xe2, 0x90, 0xe7, 0x24, 0xe7, 0x82, 0xe4, + 0xdb, 0xe1, 0x19, 0xdc, 0x4c, 0xdf, 0xe1, 0xdf, 0x2b, 0xdd, 0x0f, 0xd7, + 0x8a, 0xcd, 0xf2, 0xc8, 0x3e, 0xc9, 0x85, 0xcd, 0x4e, 0xcb, 0xb6, 0xc7, + 0x82, 0xc3, 0xef, 0xc3, 0x56, 0xc9, 0x87, 0xc8, 0xde, 0xc6, 0x0d, 0xc6, + 0x04, 0xc4, 0x85, 0xc1, 0xf6, 0xc2, 0x83, 0xc2, 0xfd, 0xb9, 0x1a, 0xb6, + 0xb7, 0xbc, 0x9c, 0xc4, 0xf6, 0xc6, 0x35, 0xbf, 0x82, 0xb6, 0x7b, 0xb8, + 0x4b, 0xc0, 0x9e, 0xc4, 0x8e, 0xbf, 0xf5, 0xb7, 0xcc, 0xb6, 0x3f, 0xbb, + 0x27, 0xc0, 0xff, 0xc1, 0x97, 0xbf, 0x51, 0xbb, 0x6e, 0xb5, 0x91, 0xb1, + 0x89, 0xb3, 0x3a, 0xb7, 0x8a, 0xbb, 0xe4, 0xbb, 0xa0, 0xb8, 0x5e, 0xba, + 0x7b, 0xc2, 0xd7, 0xc5, 0x00, 0xbf, 0x65, 0xb9, 0xc9, 0xbd, 0x7b, 0xc0, + 0xf7, 0xbd, 0x8a, 0xc4, 0xa8, 0xc7, 0x68, 0xc6, 0x95, 0xc8, 0xe0, 0xc2, + 0xb9, 0xc1, 0x31, 0xc8, 0x8f, 0xca, 0xd0, 0xca, 0x40, 0xc6, 0x34, 0xc2, + 0xd4, 0xc3, 0x51, 0xc5, 0x30, 0xc9, 0xc2, 0xcc, 0xd4, 0xcd, 0x95, 0xce, + 0xff, 0xcf, 0x4e, 0xd1, 0xba, 0xd5, 0x69, 0xde, 0xbd, 0xdd, 0xb1, 0xd9, + 0x96, 0xd7, 0xdf, 0xd7, 0xce, 0xdf, 0x0d, 0xe8, 0x2b, 0xf4, 0x4c, 0xfc, + 0x07, 0xf8, 0x2f, 0xf4, 0x7a, 0xff, 0x89, 0x16, 0x46, 0x1f, 0xd6, 0x17, + 0x43, 0x0f, 0x13, 0x09, 0xcb, 0x0c, 0x27, 0x1c, 0x8d, 0x21, 0xfa, 0x1b, + 0xd5, 0x1a, 0x86, 0x18, 0x88, 0x1a, 0x11, 0x1a, 0x35, 0x17, 0xcc, 0x19, + 0x0f, 0x1c, 0x6e, 0x25, 0xe4, 0x22, 0x6e, 0x19, 0x3f, 0x18, 0x5b, 0x16, + 0x0f, 0x1a, 0x05, 0x15, 0x3d, 0x01, 0x1d, 0xf4, 0x35, 0xed, 0x39, 0xe9, + 0x42, 0xec, 0x8c, 0xe7, 0xa4, 0xe0, 0x16, 0xe0, 0x70, 0xe4, 0x6c, 0xea, + 0x9e, 0xe6, 0x19, 0xe8, 0xf1, 0xe9, 0x7d, 0xe9, 0x86, 0xf1, 0x59, 0xf4, + 0x5f, 0xf7, 0xda, 0xf8, 0xe5, 0xf4, 0x48, 0xf8, 0x1f, 0xff, 0xdb, 0x03, + 0x2f, 0x06, 0x07, 0x06, 0x31, 0x02, 0xc0, 0xff, 0x5d, 0xff, 0x85, 0xf9, + 0xfe, 0xf8, 0x9e, 0xfd, 0x96, 0x05, 0x90, 0x07, 0x45, 0x02, 0x5b, 0x06, + 0x6c, 0x09, 0xa5, 0x0f, 0x10, 0x0e, 0x3d, 0x0e, 0x0c, 0x1b, 0x90, 0x1d, + 0x58, 0x2a, 0x55, 0x2f, 0xd4, 0x2a, 0x09, 0x3a, 0xf1, 0x49, 0xdd, 0x55, + 0xb1, 0x59, 0xed, 0x57, 0x8b, 0x5d, 0xb9, 0x64, 0x21, 0x6b, 0xbf, 0x6c, + 0x19, 0x66, 0x31, 0x60, 0x17, 0x5f, 0xc6, 0x5f, 0xbb, 0x60, 0xcf, 0x5e, + 0x03, 0x5d, 0x55, 0x58, 0xb3, 0x4c, 0xe3, 0x47, 0x38, 0x4a, 0x99, 0x4d, + 0xb3, 0x4c, 0xc6, 0x44, 0xda, 0x3d, 0x70, 0x39, 0xdd, 0x39, 0x90, 0x3e, + 0xfc, 0x44, 0xcd, 0x44, 0xf6, 0x3b, 0x32, 0x39, 0xe6, 0x40, 0xaa, 0x43, + 0x88, 0x3a, 0xbc, 0x33, 0x59, 0x36, 0xdb, 0x45, 0x4b, 0x51, 0x0f, 0x4b, + 0x59, 0x41, 0x54, 0x3c, 0x2e, 0x41, 0xe9, 0x44, 0xa1, 0x41, 0x47, 0x3f, + 0x1f, 0x3f, 0x23, 0x3f, 0x61, 0x37, 0x4e, 0x2e, 0x6d, 0x32, 0xb6, 0x34, + 0x68, 0x2d, 0xf7, 0x2a, 0x03, 0x28, 0xf0, 0x23, 0xb1, 0x1d, 0xbe, 0x16, + 0xed, 0x1c, 0xfd, 0x24, 0x6c, 0x27, 0xc1, 0x26, 0x87, 0x23, 0x4a, 0x2a, + 0x24, 0x33, 0x50, 0x36, 0xb2, 0x39, 0xb3, 0x35, 0x84, 0x35, 0x99, 0x34, + 0xa5, 0x2f, 0xfd, 0x35, 0x81, 0x36, 0xc0, 0x36, 0x74, 0x3a, 0x3c, 0x3a, + 0xa8, 0x3f, 0x8f, 0x3a, 0xcf, 0x2f, 0xa5, 0x2d, 0xef, 0x2b, 0xc1, 0x2f, + 0x5a, 0x2f, 0x1c, 0x24, 0xe7, 0x1d, 0x4d, 0x1c, 0x35, 0x1f, 0x53, 0x27, + 0xdd, 0x2c, 0xdc, 0x2b, 0x00, 0x23, 0xaf, 0x21, 0x40, 0x1f, 0x76, 0x14, + 0xd0, 0x17, 0x7e, 0x1d, 0xd6, 0x22, 0x46, 0x26, 0xf3, 0x22, 0xe9, 0x1f, + 0x19, 0x1b, 0x90, 0x20, 0xcf, 0x24, 0x6a, 0x28, 0xeb, 0x32, 0x54, 0x31, + 0xbf, 0x22, 0x6c, 0x14, 0xcc, 0x11, 0x40, 0x12, 0x35, 0x11, 0xf0, 0x10, + 0xb3, 0x08, 0x30, 0xfb, 0x1b, 0xf2, 0x63, 0xee, 0x7f, 0xec, 0x2a, 0xe8, + 0x75, 0xe6, 0xd0, 0xe3, 0xeb, 0xd5, 0xdc, 0xc6, 0x4c, 0xc2, 0x54, 0xce, + 0xc6, 0xd8, 0x86, 0xda, 0xa0, 0xda, 0x49, 0xd6, 0xda, 0xda, 0xa9, 0xdf, + 0x80, 0xdb, 0x7b, 0xd5, 0x3a, 0xdb, 0x17, 0xf1, 0x76, 0xf5, 0x26, 0xe9, + 0xc9, 0xe5, 0x96, 0xe2, 0xd7, 0xe0, 0x03, 0xe3, 0x95, 0xe2, 0x83, 0xe8, + 0xf1, 0xee, 0xf5, 0xed, 0x49, 0xed, 0x3b, 0xe8, 0x8b, 0xe3, 0xba, 0xec, + 0x48, 0xf6, 0x36, 0xf4, 0x7b, 0xe5, 0x1d, 0xdc, 0x0b, 0xe1, 0x80, 0xe2, + 0xfc, 0xde, 0xb0, 0xd2, 0x16, 0xcd, 0xfa, 0xd2, 0x27, 0xdd, 0xd6, 0xe7, + 0xdc, 0xe3, 0x8f, 0xdd, 0x36, 0xd6, 0xb8, 0xd8, 0x5c, 0xdf, 0x4e, 0xdb, + 0x3b, 0xe1, 0x9e, 0xe4, 0x1a, 0xd7, 0x2e, 0xcd, 0xd7, 0xce, 0x1b, 0xd3, + 0x82, 0xd9, 0x43, 0xcc, 0xcd, 0xb9, 0xa5, 0xbf, 0x8c, 0xc4, 0x73, 0xc8, + 0xbe, 0xcc, 0x0a, 0xc8, 0x5b, 0xbe, 0xea, 0xb5, 0xde, 0xb7, 0xcb, 0xbd, + 0x4b, 0xbc, 0xe7, 0xb6, 0x21, 0xb6, 0x9b, 0xb8, 0x07, 0xbb, 0x38, 0xba, + 0xe9, 0xba, 0x49, 0xb8, 0x7e, 0xb5, 0xce, 0xbb, 0x93, 0xbe, 0x54, 0xc4, + 0xc2, 0xc5, 0x6c, 0xbc, 0x87, 0xbf, 0x0a, 0xc9, 0x1a, 0xce, 0x4c, 0xd3, + 0x28, 0xd3, 0x28, 0xd0, 0x21, 0xd0, 0x29, 0xcc, 0xb8, 0xd1, 0x2f, 0xe1, + 0x8f, 0xe4, 0xa4, 0xe0, 0xa6, 0xda, 0xdb, 0xd9, 0x9f, 0xdf, 0x46, 0xe2, + 0x0b, 0xde, 0x16, 0xd2, 0xdd, 0xcc, 0x80, 0xd1, 0x2f, 0xda, 0xac, 0xe2, + 0x5a, 0xdf, 0x10, 0xda, 0xd3, 0xd8, 0xe6, 0xd8, 0xe0, 0xe1, 0x71, 0xe8, + 0x22, 0xe9, 0x25, 0xe5, 0xbf, 0xde, 0xc9, 0xe5, 0x2a, 0xe8, 0xe2, 0xe4, + 0xc5, 0xe4, 0x15, 0xdb, 0x29, 0xde, 0xfb, 0xe7, 0xa5, 0xe7, 0xe5, 0xe7, + 0xb0, 0xe1, 0x98, 0xdb, 0x28, 0xd4, 0x86, 0xd0, 0x29, 0xd7, 0xb3, 0xd0, + 0xf3, 0xc7, 0x84, 0xc0, 0xc5, 0xbe, 0x8a, 0xc8, 0x78, 0xca, 0x55, 0xc9, + 0xc6, 0xc7, 0x58, 0xc7, 0xcc, 0xc5, 0xe5, 0xc3, 0x60, 0xc5, 0x7c, 0xc2, + 0x2d, 0xbc, 0x5d, 0xba, 0xd1, 0xca, 0xcd, 0xdc, 0xff, 0xe3, 0xfc, 0xe0, + 0x67, 0xd2, 0x04, 0xd2, 0xd6, 0xdf, 0x28, 0xe9, 0xa7, 0xe4, 0x37, 0xcd, + 0x46, 0xb9, 0xc2, 0xc0, 0x9a, 0xd2, 0x0e, 0xdb, 0x60, 0xd4, 0xa8, 0xc4, + 0x9b, 0xc1, 0x39, 0xc5, 0x50, 0xcb, 0x0d, 0xd4, 0xc6, 0xda, 0xa2, 0xdd, + 0x87, 0xd4, 0x6e, 0xd1, 0x06, 0xd7, 0xd4, 0xde, 0xc1, 0xeb, 0x68, 0xf0, + 0x48, 0xf3, 0x54, 0xfa, 0x61, 0x00, 0x76, 0x06, 0x7b, 0x01, 0xca, 0xff, + 0x34, 0x0a, 0x21, 0x0b, 0x43, 0x11, 0xea, 0x11, 0xc4, 0x09, 0x24, 0x10, + 0xc4, 0x13, 0xdd, 0x1e, 0x2c, 0x27, 0xb8, 0x21, 0xe0, 0x1b, 0x44, 0x0d, + 0x0b, 0x0b, 0x81, 0x11, 0x87, 0x13, 0xc1, 0x16, 0x43, 0x12, 0x21, 0x10, + 0x86, 0x16, 0xb2, 0x1f, 0x51, 0x2a, 0x69, 0x28, 0x25, 0x1a, 0x8c, 0x0f, + 0x59, 0x04, 0x69, 0xfe, 0x76, 0xfc, 0xb4, 0xf4, 0x52, 0xf5, 0x61, 0xf3, + 0x0c, 0xea, 0xd6, 0xdf, 0xfb, 0xd5, 0x41, 0xda, 0x09, 0xe1, 0xe4, 0xe6, + 0x7c, 0xf0, 0x39, 0xef, 0x0b, 0xe5, 0xe7, 0xe5, 0x4e, 0xea, 0xc2, 0xe6, + 0x06, 0xea, 0xa9, 0xec, 0x5c, 0xf4, 0xad, 0x05, 0x03, 0x0a, 0x7e, 0x06, + 0xf8, 0x01, 0x65, 0x01, 0x2e, 0x09, 0xc6, 0x0d, 0xda, 0x0e, 0x88, 0x13, + 0x46, 0x16, 0xca, 0x14, 0x0a, 0x17, 0x71, 0x1c, 0xb8, 0x1f, 0x86, 0x1f, + 0xc9, 0x1e, 0xb3, 0x1f, 0x1c, 0x20, 0xa4, 0x1d, 0xea, 0x16, 0x6b, 0x17, + 0x92, 0x22, 0x4d, 0x25, 0x50, 0x28, 0x43, 0x2f, 0x57, 0x32, 0x74, 0x3d, + 0xd8, 0x44, 0xeb, 0x46, 0x16, 0x51, 0xdc, 0x56, 0x31, 0x55, 0x53, 0x54, + 0x07, 0x50, 0xc1, 0x4d, 0xed, 0x4f, 0x55, 0x51, 0x1b, 0x51, 0xa2, 0x46, + 0xca, 0x39, 0xad, 0x30, 0x28, 0x2f, 0x01, 0x36, 0x00, 0x38, 0x20, 0x3a, + 0xe0, 0x38, 0xf2, 0x30, 0x97, 0x2c, 0xaa, 0x28, 0xa7, 0x27, 0x3f, 0x2c, + 0x1e, 0x2e, 0x4a, 0x28, 0x1f, 0x1b, 0xfc, 0x13, 0x73, 0x16, 0x8f, 0x1c, + 0x15, 0x25, 0xcd, 0x28, 0xcc, 0x27, 0x3a, 0x28, 0x19, 0x2d, 0xc8, 0x2f, + 0xfb, 0x31, 0xeb, 0x36, 0x73, 0x3a, 0x14, 0x3e, 0x70, 0x3f, 0xfa, 0x3d, + 0x88, 0x37, 0xbd, 0x34, 0x59, 0x38, 0xbf, 0x37, 0x91, 0x30, 0xf7, 0x2e, + 0xb0, 0x31, 0x78, 0x2a, 0xab, 0x2b, 0xa4, 0x2f, 0xe4, 0x25, 0xd6, 0x1a, + 0x30, 0x18, 0x5c, 0x1d, 0x4d, 0x1a, 0xcc, 0x1b, 0xcd, 0x28, 0xa2, 0x2f, + 0x51, 0x2f, 0xe3, 0x28, 0x1f, 0x2b, 0x4e, 0x36, 0xe0, 0x41, 0xbc, 0x49, + 0x4d, 0x40, 0xc9, 0x35, 0x7b, 0x37, 0x68, 0x44, 0xfb, 0x52, 0x1d, 0x57, + 0x3a, 0x5a, 0x0b, 0x55, 0x09, 0x4e, 0x84, 0x4f, 0x8a, 0x4e, 0x82, 0x4f, + 0x70, 0x48, 0xfd, 0x40, 0x95, 0x47, 0xcb, 0x44, 0xd2, 0x42, 0x56, 0x45, + 0xd5, 0x42, 0x39, 0x47, 0xad, 0x3f, 0xef, 0x37, 0xe1, 0x31, 0x89, 0x28, + 0x32, 0x30, 0xee, 0x32, 0x8b, 0x34, 0x25, 0x3a, 0xf5, 0x3d, 0xb9, 0x3c, + 0x24, 0x39, 0x57, 0x41, 0x6e, 0x42, 0x3e, 0x3d, 0x9a, 0x36, 0x60, 0x30, + 0x05, 0x2c, 0x28, 0x29, 0xc4, 0x2b, 0xde, 0x28, 0xf0, 0x1c, 0x45, 0x09, + 0x60, 0xfd, 0xa0, 0xf4, 0x6d, 0xe7, 0x82, 0xde, 0xaf, 0xd6, 0x10, 0xd4, + 0xdb, 0xd3, 0x76, 0xd5, 0x6c, 0xd4, 0x4f, 0xd0, 0xc6, 0xd1, 0xe2, 0xdc, + 0x04, 0xeb, 0xc1, 0xed, 0xdc, 0xe7, 0x02, 0xdf, 0x00, 0xdf, 0xcd, 0xe4, + 0x38, 0xe6, 0x64, 0xeb, 0x26, 0xef, 0xac, 0xef, 0x94, 0xf4, 0xc8, 0xf6, + 0xa2, 0xf1, 0x6c, 0xed, 0x41, 0xeb, 0x24, 0xf0, 0x36, 0xf7, 0xb0, 0xf3, + 0x0d, 0xf1, 0x10, 0xed, 0x97, 0xe3, 0x2f, 0xe2, 0x68, 0xe3, 0x1a, 0xe4, + 0xd1, 0xe1, 0x32, 0xd9, 0xa8, 0xda, 0x8d, 0xde, 0x41, 0xde, 0x70, 0xe4, + 0xe3, 0xeb, 0xcd, 0xef, 0x97, 0xed, 0xd8, 0xf4, 0x20, 0x06, 0xd7, 0x0f, + 0x1d, 0x15, 0x70, 0x17, 0xe9, 0x17, 0xbc, 0x1a, 0xdb, 0x1b, 0x13, 0x14, + 0xb0, 0x11, 0xf9, 0x15, 0x1e, 0x11, 0x25, 0x0b, 0x71, 0x01, 0x85, 0xf6, + 0x30, 0xf4, 0x96, 0xf0, 0xbf, 0xe7, 0x46, 0xde, 0xe1, 0xd8, 0x02, 0xda, + 0x01, 0xd8, 0xfd, 0xcf, 0x29, 0xcc, 0xae, 0xc9, 0x20, 0xcd, 0x20, 0xd2, + 0x8c, 0xce, 0x2e, 0xcb, 0x45, 0xc5, 0x5f, 0xca, 0x2c, 0xd9, 0x4e, 0xd8, + 0x92, 0xce, 0x1a, 0xc5, 0x64, 0xc6, 0xf5, 0xcf, 0x78, 0xce, 0x2b, 0xcd, + 0xd2, 0xcb, 0x49, 0xc5, 0xe2, 0xc6, 0x28, 0xc6, 0x23, 0xc3, 0x2b, 0xbe, + 0xea, 0xb0, 0x7b, 0xaa, 0xd8, 0xa5, 0x19, 0xa1, 0xa7, 0xa2, 0xfc, 0xa4, + 0xb0, 0xa7, 0x68, 0xa6, 0x75, 0xa2, 0x53, 0xa2, 0x5b, 0xa4, 0xa4, 0xaa, + 0x29, 0xb7, 0x15, 0xc1, 0x58, 0xc4, 0x58, 0xc3, 0x98, 0xc4, 0xf3, 0xcf, + 0x2c, 0xdc, 0x47, 0xea, 0xad, 0xf4, 0xac, 0xf3, 0xca, 0xf8, 0x8b, 0xfc, + 0xcb, 0xff, 0x83, 0xff, 0x58, 0xf7, 0x9b, 0xff, 0x4d, 0x03, 0xbb, 0x01, + 0x3f, 0x00, 0x5c, 0xf3, 0xcc, 0xf2, 0xa7, 0xf4, 0x87, 0xfa, 0x69, 0x01, + 0x2e, 0xf9, 0x5b, 0xf2, 0x1c, 0xe9, 0x52, 0xe6, 0xfb, 0xe7, 0xc1, 0xe7, + 0x0f, 0xf0, 0xfd, 0xf5, 0xe0, 0xf7, 0xba, 0xfc, 0x92, 0x05, 0x4a, 0x0c, + 0x13, 0x15, 0x53, 0x16, 0xb3, 0x0e, 0x21, 0x0d, 0x32, 0x0b, 0x66, 0x12, + 0x8a, 0x17, 0xfa, 0x16, 0x60, 0x14, 0xde, 0x07, 0x28, 0x04, 0xd0, 0x09, + 0x4f, 0x14, 0x30, 0x12, 0x4a, 0x00, 0x24, 0xee, 0x4b, 0xdd, 0x19, 0xd7, + 0x7f, 0xd8, 0x74, 0xda, 0xa7, 0xd6, 0x71, 0xd1, 0x6a, 0xc8, 0x17, 0xbe, + 0xbe, 0xc3, 0x3c, 0xd1, 0x13, 0xdd, 0x61, 0xde, 0xe8, 0xd8, 0x36, 0xd5, + 0xd3, 0xd9, 0xef, 0xed, 0x8d, 0xfb, 0x71, 0xf7, 0xef, 0xf2, 0x28, 0xf4, + 0x0b, 0xfc, 0xb4, 0x0a, 0x0a, 0x13, 0xaf, 0x15, 0x7a, 0x17, 0xa4, 0x13, + 0xbb, 0x10, 0xa6, 0x10, 0xa1, 0x14, 0x34, 0x1a, 0xf2, 0x11, 0x16, 0x06, + 0x8f, 0x04, 0xa2, 0x04, 0x5d, 0x02, 0xa6, 0xf8, 0xca, 0xed, 0x4d, 0xea, + 0x63, 0xe9, 0x63, 0xf0, 0xd4, 0xf6, 0xd6, 0xf0, 0x04, 0xec, 0x91, 0xe8, + 0xf6, 0xe7, 0xf1, 0xf2, 0x9a, 0xf9, 0xc1, 0x00, 0x32, 0x08, 0xf3, 0x09, + 0x03, 0x16, 0x63, 0x1c, 0x4d, 0x1b, 0xda, 0x1c, 0x57, 0x19, 0xfc, 0x17, + 0x2f, 0x16, 0xea, 0x12, 0x33, 0x10, 0xd3, 0x08, 0x8e, 0x09, 0x4f, 0x0e, + 0x3f, 0x0e, 0xca, 0x0e, 0x56, 0x0b, 0x3c, 0x0b, 0xbc, 0x0c, 0xf8, 0x09, + 0x4e, 0x09, 0x4e, 0x08, 0x02, 0x06, 0xf9, 0xff, 0xe6, 0xfb, 0x83, 0xfc, + 0xcb, 0x02, 0x13, 0x0e, 0x28, 0x11, 0x94, 0x11, 0x14, 0x0f, 0xac, 0x07, + 0xfa, 0x06, 0x55, 0x04, 0x99, 0xfc, 0x89, 0xf2, 0x2b, 0xe9, 0xfd, 0xee, + 0x21, 0xf8, 0xcf, 0xf9, 0xa5, 0xf5, 0xbb, 0xe9, 0x17, 0xe2, 0xc8, 0xe2, + 0x28, 0xe9, 0x63, 0xef, 0x35, 0xef, 0x95, 0xe8, 0x02, 0xe0, 0x48, 0xd9, + 0x1d, 0xd8, 0xd2, 0xe2, 0x06, 0xec, 0xbc, 0xf6, 0x1a, 0x01, 0x99, 0xfa, + 0xa6, 0xfa, 0x78, 0x00, 0x79, 0x03, 0xcb, 0x06, 0xb9, 0xfd, 0x4e, 0xff, + 0xaa, 0x06, 0xda, 0x08, 0x3c, 0x15, 0xd5, 0x14, 0x9b, 0x0f, 0x8d, 0x12, + 0x02, 0x16, 0x53, 0x1a, 0x5d, 0x17, 0x1b, 0x17, 0x9c, 0x17, 0x21, 0x13, + 0xd9, 0x16, 0x01, 0x20, 0x4c, 0x23, 0xb8, 0x23, 0xa6, 0x23, 0x05, 0x28, + 0x3a, 0x32, 0x29, 0x32, 0x87, 0x32, 0x3e, 0x35, 0x98, 0x31, 0x92, 0x33, + 0x76, 0x31, 0xef, 0x2b, 0xb8, 0x29, 0xbd, 0x2b, 0x63, 0x35, 0xa9, 0x38, + 0x5e, 0x3a, 0x85, 0x3e, 0x2a, 0x3d, 0x19, 0x39, 0x94, 0x35, 0x43, 0x3d, + 0x52, 0x4a, 0xd1, 0x4e, 0xb1, 0x48, 0x08, 0x3b, 0x20, 0x2e, 0x3e, 0x1e, + 0x99, 0x0e, 0xf5, 0x0e, 0xdb, 0x15, 0x6a, 0x0f, 0x8c, 0x01, 0x42, 0xf5, + 0xf9, 0xee, 0x96, 0xf4, 0xb7, 0xfd, 0x9f, 0x07, 0x6e, 0x0a, 0x5a, 0x05, + 0xd4, 0x09, 0xea, 0x09, 0x20, 0x03, 0xf5, 0x06, 0xce, 0x05, 0x0c, 0x02, + 0xd2, 0x0b, 0x6c, 0x14, 0x13, 0x1a, 0xe7, 0x22, 0x51, 0x29, 0xe3, 0x2e, + 0x75, 0x32, 0xe1, 0x30, 0xdc, 0x31, 0x2e, 0x37, 0xca, 0x3c, 0x80, 0x3d, + 0x88, 0x37, 0x46, 0x37, 0x26, 0x3a, 0x2d, 0x39, 0xcf, 0x32, 0xbe, 0x28, + 0x77, 0x28, 0x22, 0x2b, 0xfd, 0x2b, 0x92, 0x2f, 0xfe, 0x2b, 0xac, 0x2a, + 0x7c, 0x2f, 0xdc, 0x2b, 0x24, 0x2d, 0x3b, 0x38, 0xe8, 0x40, 0xce, 0x48, + 0x21, 0x49, 0x05, 0x45, 0x64, 0x48, 0xe3, 0x4f, 0xc6, 0x58, 0x86, 0x5d, + 0x61, 0x56, 0xd7, 0x4b, 0xdf, 0x49, 0x15, 0x4c, 0x44, 0x4e, 0xf0, 0x51, + 0x87, 0x51, 0xf5, 0x4e, 0x8d, 0x4c, 0xa0, 0x4a, 0x47, 0x4c, 0xd5, 0x46, + 0x4a, 0x3e, 0xbf, 0x3b, 0x97, 0x3f, 0x81, 0x46, 0x11, 0x40, 0x1e, 0x30, + 0x13, 0x22, 0xbe, 0x16, 0x78, 0x0f, 0xac, 0x0e, 0x01, 0x12, 0x60, 0x14, + 0x16, 0x16, 0x42, 0x11, 0x40, 0x09, 0x57, 0x06, 0x85, 0x0f, 0xe1, 0x21, + 0x3e, 0x29, 0x15, 0x29, 0x8a, 0x27, 0xbb, 0x1f, 0x20, 0x1b, 0x93, 0x1f, + 0xd5, 0x2c, 0x78, 0x30, 0x98, 0x24, 0x0c, 0x1f, 0xe8, 0x14, 0xa7, 0x0c, + 0x8c, 0x15, 0xcb, 0x1b, 0x53, 0x18, 0xf8, 0x08, 0x8e, 0xfc, 0x38, 0x00, + 0x1b, 0x07, 0x6a, 0x0d, 0xd1, 0x0f, 0x87, 0x13, 0x89, 0x17, 0x2d, 0x14, + 0xbc, 0x14, 0xd5, 0x13, 0xef, 0x15, 0x44, 0x22, 0xd0, 0x27, 0x0d, 0x2f, + 0xe2, 0x39, 0x2a, 0x40, 0x0d, 0x46, 0x24, 0x4e, 0x8d, 0x54, 0xb6, 0x53, + 0xac, 0x52, 0x4e, 0x53, 0x14, 0x55, 0x6d, 0x51, 0x7d, 0x4a, 0xda, 0x43, + 0xfc, 0x3b, 0xb5, 0x37, 0x97, 0x31, 0xb6, 0x2e, 0x53, 0x2b, 0x92, 0x26, + 0x6b, 0x23, 0xbb, 0x1b, 0x34, 0x17, 0xd6, 0x18, 0x6e, 0x22, 0xd7, 0x26, + 0xa1, 0x1e, 0x4f, 0x1c, 0xc1, 0x20, 0x99, 0x25, 0xd9, 0x2b, 0x69, 0x2a, + 0x30, 0x18, 0x33, 0xff, 0xc5, 0xed, 0x25, 0xe5, 0x9e, 0xe7, 0x15, 0xeb, + 0xa6, 0xdf, 0x5a, 0xcc, 0x3d, 0xb7, 0xd0, 0xb0, 0xe2, 0xb8, 0x4e, 0xbf, + 0x1c, 0xc4, 0x78, 0xba, 0x29, 0xa9, 0x57, 0xa2, 0x2d, 0xa1, 0xd7, 0xa2, + 0xda, 0xa9, 0xb3, 0xae, 0xa7, 0xae, 0xe6, 0xae, 0x52, 0xb0, 0x2b, 0xb8, + 0x07, 0xc2, 0x81, 0xc6, 0x6a, 0xca, 0x40, 0xd0, 0x30, 0xdb, 0xb8, 0xec, + 0x3b, 0xf8, 0x0a, 0xf7, 0x26, 0xf8, 0x57, 0xfe, 0xf3, 0x04, 0xe8, 0x06, + 0xfe, 0xfd, 0xd8, 0xf8, 0x8c, 0xfa, 0x59, 0xf5, 0x3b, 0xe9, 0xda, 0xdf, + 0x6c, 0xe4, 0x97, 0xeb, 0x46, 0xe8, 0x22, 0xe7, 0xd1, 0xe8, 0xc7, 0xee, + 0xfe, 0xf8, 0x99, 0xfa, 0xdb, 0xfa, 0xdc, 0xff, 0x68, 0x08, 0xe0, 0x0e, + 0x9c, 0x0d, 0x09, 0x0f, 0xde, 0x11, 0x3e, 0x13, 0xa4, 0x13, 0x24, 0x11, + 0x35, 0x13, 0x5c, 0x14, 0x14, 0x13, 0xd9, 0x12, 0x5d, 0x0f, 0x63, 0x0a, + 0x16, 0x02, 0x5c, 0xf9, 0x47, 0xf0, 0x75, 0xde, 0xc0, 0xca, 0x58, 0xbb, + 0x28, 0xaf, 0x11, 0xab, 0x4e, 0xa8, 0x86, 0xa2, 0x8b, 0xa0, 0xfc, 0x9f, + 0xcb, 0xa0, 0x07, 0xa0, 0x19, 0x9d, 0xf9, 0xa1, 0x51, 0xab, 0x0c, 0xb1, + 0x89, 0xad, 0x00, 0xa8, 0xb1, 0xab, 0x71, 0xb1, 0xcf, 0xba, 0x72, 0xbe, + 0x3d, 0xbc, 0x3a, 0xbf, 0x6f, 0xbb, 0x52, 0xbc, 0xbf, 0xbe, 0x5f, 0xbe, + 0xd7, 0xc1, 0xdd, 0xbb, 0x0b, 0xb8, 0x24, 0xb7, 0xc0, 0xb9, 0x09, 0xc4, + 0x3e, 0xc7, 0xb7, 0xc6, 0x90, 0xc5, 0x48, 0xc6, 0x39, 0xcb, 0x0b, 0xcd, + 0xde, 0xd0, 0x44, 0xda, 0x7a, 0xe4, 0x99, 0xec, 0xc9, 0xf1, 0xe5, 0xfc, + 0x7f, 0x0c, 0x0f, 0x16, 0x4f, 0x1d, 0x12, 0x25, 0x4d, 0x28, 0x78, 0x2a, + 0x85, 0x2b, 0x89, 0x28, 0x2a, 0x2a, 0x7e, 0x27, 0x1e, 0x21, 0xe9, 0x1b, + 0x90, 0x0f, 0x7e, 0x0a, 0x6c, 0x08, 0x96, 0x06, 0x4a, 0x08, 0xd8, 0x00, + 0xf1, 0xf7, 0x18, 0xf3, 0x44, 0xf4, 0x05, 0xfb, 0xf0, 0x02, 0x7d, 0x05, + 0x10, 0xfc, 0x1e, 0xf4, 0xd4, 0xf1, 0x2b, 0xee, 0x9b, 0xe7, 0xda, 0xdf, + 0x33, 0xd6, 0x4e, 0xc4, 0xec, 0xb4, 0x33, 0xaf, 0xa4, 0xae, 0xb3, 0xb2, + 0x89, 0xb2, 0x84, 0xab, 0x8e, 0xa1, 0x20, 0x9b, 0x62, 0x9d, 0xad, 0xa1, + 0x7f, 0xa7, 0x9c, 0xa9, 0xca, 0xa0, 0xb4, 0x9a, 0x28, 0xa1, 0xcd, 0xa8, + 0xe7, 0xa7, 0x5a, 0xa7, 0x83, 0xae, 0x85, 0xb6, 0x84, 0xbe, 0x1f, 0xcb, + 0x5e, 0xd3, 0x98, 0xd5, 0xce, 0xdb, 0x71, 0xe5, 0x19, 0xed, 0xa4, 0xf6, + 0x25, 0x00, 0x30, 0x00, 0x5a, 0xfe, 0xdb, 0xfb, 0xa7, 0xfb, 0xe5, 0xfe, + 0x52, 0xfd, 0xa8, 0xfe, 0x2b, 0x01, 0x93, 0xff, 0x0e, 0xfe, 0xc4, 0xff, + 0xd9, 0x02, 0x7e, 0x0a, 0xd9, 0x0f, 0x49, 0x0b, 0x04, 0x0f, 0x02, 0x17, + 0xe5, 0x19, 0x71, 0x22, 0x6c, 0x29, 0xdb, 0x2a, 0x49, 0x2f, 0xc7, 0x2c, + 0xbb, 0x26, 0x39, 0x28, 0x82, 0x29, 0x87, 0x2b, 0x29, 0x2b, 0x0d, 0x25, + 0x1b, 0x1d, 0xa2, 0x14, 0x3a, 0x0e, 0xb9, 0x0c, 0x1f, 0x05, 0x5c, 0xf1, + 0x8f, 0xdd, 0x82, 0xcf, 0x27, 0xca, 0x23, 0xc8, 0xd6, 0xc4, 0xeb, 0xbe, + 0x8c, 0xba, 0xb3, 0xb8, 0x96, 0xb2, 0x1f, 0xb0, 0x25, 0xb1, 0x47, 0xb7, + 0xe9, 0xc0, 0xad, 0xc2, 0x6f, 0xbf, 0xd2, 0xbb, 0x7b, 0xb8, 0xdb, 0xbc, + 0x17, 0xca, 0x08, 0xd3, 0x0d, 0xd6, 0x1f, 0xd6, 0xc9, 0xd3, 0xd6, 0xd4, + 0x03, 0xd9, 0x4a, 0xdd, 0xbf, 0xe1, 0xc8, 0xe0, 0x10, 0xe0, 0xb9, 0xe7, + 0x6d, 0xeb, 0x4d, 0xed, 0x09, 0xed, 0x6c, 0xeb, 0x31, 0xf5, 0xdb, 0xff, + 0x4b, 0x08, 0xa0, 0x0b, 0xbc, 0x07, 0x8d, 0x0a, 0x61, 0x10, 0xa3, 0x1b, + 0x2c, 0x2a, 0xa3, 0x35, 0x0a, 0x41, 0xf7, 0x44, 0xa4, 0x46, 0xa0, 0x48, + 0xdf, 0x4c, 0x50, 0x54, 0xeb, 0x56, 0xe3, 0x52, 0x98, 0x47, 0x09, 0x40, + 0xec, 0x3e, 0x97, 0x3c, 0xdf, 0x36, 0xfd, 0x2c, 0x1b, 0x27, 0x9d, 0x26, + 0x42, 0x20, 0x16, 0x17, 0xaf, 0x13, 0x54, 0x13, 0x14, 0x12, 0x46, 0x0c, + 0xe2, 0x05, 0x7b, 0x0a, 0x91, 0x13, 0x1f, 0x12, 0xce, 0x0c, 0x38, 0x0a, + 0x96, 0x0d, 0x1d, 0x11, 0xc7, 0x06, 0xfa, 0xfb, 0x8d, 0xf6, 0x59, 0xee, + 0x0e, 0xe3, 0xe6, 0xdd, 0x5e, 0xdf, 0x46, 0xdd, 0x7a, 0xd7, 0xa7, 0xcc, + 0x7e, 0xc3, 0x1e, 0xc3, 0xc5, 0xca, 0x47, 0xd7, 0xa5, 0xdb, 0xfc, 0xd5, + 0x24, 0xd6, 0x03, 0xd8, 0x55, 0xd7, 0x03, 0xe1, 0x13, 0xee, 0xfc, 0xfb, + 0x1d, 0x07, 0xbb, 0x08, 0x80, 0x0e, 0x6d, 0x1c, 0xf3, 0x2d, 0xa4, 0x3d, + 0xad, 0x43, 0x70, 0x47, 0xa6, 0x50, 0x6f, 0x59, 0xf1, 0x5f, 0x22, 0x61, + 0x4c, 0x5b, 0xb7, 0x58, 0xfc, 0x59, 0x7d, 0x5d, 0xa6, 0x60, 0x46, 0x5b, + 0xb3, 0x55, 0xc7, 0x4f, 0x8a, 0x4c, 0x8a, 0x52, 0x2a, 0x53, 0xb3, 0x52, + 0xa4, 0x51, 0xbd, 0x4e, 0x6b, 0x56, 0x21, 0x5f, 0xc9, 0x61, 0x82, 0x60, + 0xc8, 0x5d, 0x17, 0x5d, 0x15, 0x5d, 0xf8, 0x5d, 0x27, 0x5e, 0x70, 0x5b, + 0x64, 0x54, 0x58, 0x49, 0xb6, 0x41, 0x28, 0x43, 0xd6, 0x47, 0xdc, 0x40, + 0x45, 0x2e, 0x08, 0x1a, 0x2f, 0x0c, 0xce, 0x07, 0x00, 0x03, 0x89, 0xfc, + 0x31, 0xf9, 0x9d, 0xf3, 0x9c, 0xeb, 0xa8, 0xe6, 0x7b, 0xe1, 0x32, 0xe5, + 0x29, 0xf0, 0x20, 0xf1, 0xca, 0xf3, 0x5e, 0xf2, 0xde, 0xeb, 0x12, 0xee, + 0x6f, 0xef, 0xfe, 0xf6, 0xfe, 0x03, 0xd3, 0x08, 0xa8, 0x0f, 0xd8, 0x15, + 0xf3, 0x18, 0x90, 0x23, 0xb3, 0x26, 0x68, 0x25, 0x66, 0x27, 0x1b, 0x27, + 0xe2, 0x2b, 0xe5, 0x2b, 0xc6, 0x2b, 0x0b, 0x31, 0xec, 0x33, 0xbc, 0x39, + 0x89, 0x3e, 0xb1, 0x47, 0x54, 0x4c, 0x6c, 0x46, 0x3b, 0x48, 0xc2, 0x4b, + 0xb0, 0x52, 0xaf, 0x5a, 0xb8, 0x5d, 0x9e, 0x61, 0x06, 0x62, 0x47, 0x63, + 0x8b, 0x64, 0xa5, 0x64, 0xc3, 0x66, 0x9b, 0x6a, 0x12, 0x67, 0x81, 0x5d, + 0xeb, 0x55, 0xfa, 0x4d, 0x76, 0x4e, 0x64, 0x4c, 0x42, 0x45, 0x2f, 0x3e, + 0xbb, 0x32, 0xe2, 0x2f, 0xf0, 0x31, 0x4d, 0x31, 0x17, 0x30, 0xc4, 0x28, + 0xca, 0x21, 0x70, 0x22, 0x56, 0x1f, 0xbc, 0x1a, 0x1b, 0x13, 0xaa, 0x0f, + 0x4b, 0x19, 0xa4, 0x1f, 0x35, 0x20, 0x0f, 0x16, 0x7f, 0x08, 0xf9, 0xfb, + 0x88, 0xed, 0x54, 0xe6, 0x4f, 0xdf, 0x40, 0xda, 0x2f, 0xda, 0xc1, 0xd4, + 0xfc, 0xc6, 0x92, 0xbd, 0xdd, 0xbd, 0x61, 0xc5, 0x7e, 0xd4, 0x7a, 0xdf, + 0xcf, 0xde, 0xc0, 0xd6, 0xc8, 0xd0, 0x08, 0xd4, 0x8a, 0xdc, 0x18, 0xe7, + 0xee, 0xf5, 0xea, 0x03, 0x24, 0x10, 0xf9, 0x1a, 0x4e, 0x21, 0x87, 0x28, + 0xb7, 0x36, 0xc7, 0x48, 0x38, 0x52, 0x9a, 0x50, 0x85, 0x4f, 0xd9, 0x51, + 0x10, 0x52, 0x0c, 0x50, 0xc5, 0x4b, 0x7c, 0x4b, 0xb4, 0x4c, 0x63, 0x45, + 0x34, 0x3d, 0x98, 0x35, 0x6e, 0x34, 0x53, 0x37, 0xbb, 0x30, 0x73, 0x2b, + 0x98, 0x28, 0x26, 0x26, 0x71, 0x28, 0xfb, 0x29, 0x3b, 0x2d, 0x5e, 0x2e, + 0xea, 0x2b, 0x5b, 0x2f, 0x27, 0x33, 0x84, 0x33, 0xce, 0x33, 0xeb, 0x31, + 0x59, 0x30, 0x34, 0x2c, 0x28, 0x21, 0xe3, 0x18, 0xd2, 0x13, 0x58, 0x0b, + 0x69, 0x03, 0x39, 0xfa, 0x5e, 0xee, 0xcc, 0xe3, 0x79, 0xda, 0x1f, 0xd2, + 0xea, 0xc9, 0x8f, 0xc1, 0xc9, 0xbe, 0x4c, 0xbe, 0x12, 0xb8, 0xa3, 0xb6, + 0xd2, 0xb9, 0x94, 0xb8, 0xef, 0xb8, 0x65, 0xba, 0x77, 0xbc, 0x5b, 0xc2, + 0xa3, 0xc5, 0x0a, 0xc9, 0x49, 0xd4, 0x75, 0xdc, 0xb0, 0xe3, 0x59, 0xe8, + 0x3d, 0xe8, 0x33, 0xf3, 0x5a, 0xf6, 0xd4, 0xf1, 0x03, 0xf0, 0x59, 0xe8, + 0x1f, 0xe8, 0x8f, 0xec, 0xad, 0xf1, 0x3b, 0xf0, 0xc4, 0xe5, 0x44, 0xe5, + 0xc9, 0xe9, 0xe8, 0xf1, 0x13, 0xfd, 0xcc, 0xfe, 0x1c, 0xfd, 0x93, 0xf9, + 0xf5, 0xfa, 0x6f, 0x08, 0x7c, 0x16, 0xc9, 0x23, 0xf2, 0x2c, 0x82, 0x2d, + 0x8b, 0x2b, 0xb1, 0x30, 0xbe, 0x37, 0x3c, 0x3b, 0xc8, 0x41, 0xfd, 0x3f, + 0x99, 0x3b, 0x3c, 0x37, 0x75, 0x34, 0xab, 0x37, 0x9f, 0x2c, 0xa4, 0x21, + 0xb2, 0x1a, 0x7a, 0x10, 0x76, 0x0f, 0x03, 0x0d, 0xd6, 0x05, 0x98, 0x00, + 0xfb, 0xfb, 0xdf, 0xf7, 0xa4, 0xf4, 0x5c, 0xf8, 0xae, 0x00, 0x2e, 0x04, + 0x1f, 0x05, 0xc7, 0x02, 0x54, 0x00, 0x74, 0xfd, 0x87, 0xf8, 0x20, 0xf3, + 0x1f, 0xe1, 0x60, 0xd0, 0x48, 0xcb, 0x0e, 0xce, 0x57, 0xd4, 0xe4, 0xcc, + 0xe5, 0xbd, 0xae, 0xb2, 0x9d, 0xac, 0x35, 0xac, 0xdd, 0xb6, 0x60, 0xc1, + 0xbf, 0xb9, 0xf8, 0xaf, 0xa3, 0xac, 0xff, 0xac, 0xe6, 0xb2, 0x60, 0xb8, + 0xa9, 0xbd, 0xd0, 0xc3, 0x4c, 0xc6, 0x47, 0xcc, 0xe6, 0xd6, 0x66, 0xde, + 0x91, 0xe9, 0x1f, 0xf3, 0x89, 0xf3, 0x93, 0xf7, 0xca, 0x01, 0x17, 0x0b, + 0x2c, 0x0f, 0x31, 0x0a, 0xd9, 0x05, 0xc6, 0x07, 0xe0, 0x07, 0xfa, 0x04, + 0x90, 0xff, 0x87, 0xf9, 0xa7, 0xf6, 0xee, 0xf3, 0xe9, 0xf0, 0x76, 0xf5, + 0x7f, 0xf6, 0xea, 0xf3, 0xa0, 0xf6, 0x36, 0xf9, 0x70, 0x01, 0xbd, 0x04, + 0x9c, 0x09, 0xc3, 0x14, 0x1e, 0x15, 0x2c, 0x17, 0x69, 0x17, 0x13, 0x15, + 0xe5, 0x14, 0xfb, 0x11, 0x7f, 0x13, 0x9d, 0x14, 0xa5, 0x10, 0x57, 0x0a, + 0xcd, 0x01, 0xea, 0xf3, 0x7f, 0xe2, 0x84, 0xd9, 0xb0, 0xd5, 0x98, 0xcd, + 0x96, 0xc2, 0x32, 0xb5, 0xa8, 0xae, 0xc4, 0xae, 0x69, 0xaa, 0x15, 0xaa, + 0x52, 0xac, 0xcd, 0xa9, 0x0f, 0xac, 0x05, 0xaf, 0xde, 0xaa, 0x7b, 0xa7, + 0x59, 0xaa, 0xdf, 0xaa, 0xc8, 0xad, 0xce, 0xb3, 0x0d, 0xb5, 0xcd, 0xbc, + 0x19, 0xbc, 0x1a, 0xb8, 0x37, 0xc0, 0x91, 0xc0, 0x8b, 0xc5, 0xfa, 0xc9, + 0x39, 0xc6, 0xec, 0xc8, 0x05, 0xcb, 0xc7, 0xd0, 0xcd, 0xd4, 0x99, 0xd6, + 0x60, 0xdc, 0x09, 0xde, 0x41, 0xe5, 0xba, 0xeb, 0x47, 0xec, 0x91, 0xf0, + 0xe7, 0xf0, 0x8d, 0xf8, 0xeb, 0x04, 0x25, 0x08, 0xda, 0x0d, 0xec, 0x15, + 0xe4, 0x1f, 0xe3, 0x29, 0x87, 0x2c, 0x71, 0x2a, 0xca, 0x2a, 0x67, 0x2f, + 0x84, 0x34, 0xe8, 0x35, 0xea, 0x32, 0xe9, 0x2f, 0x19, 0x28, 0x73, 0x1e, + 0xf4, 0x1d, 0xd7, 0x21, 0xfb, 0x24, 0xdd, 0x24, 0xd6, 0x1d, 0x98, 0x18, + 0xf3, 0x1b, 0x51, 0x23, 0x85, 0x26, 0x6a, 0x21, 0x86, 0x1f, 0xe2, 0x1e, + 0xfd, 0x1b, 0xe8, 0x15, 0x5e, 0x05, 0xeb, 0xee, 0x9b, 0xd8, 0x8b, 0xcd, + 0xea, 0xc5, 0xa8, 0xbb, 0xe3, 0xb5, 0x26, 0xab, 0xf9, 0x9f, 0x38, 0x9d, + 0xa5, 0xa2, 0x9a, 0xa7, 0x30, 0xa2, 0xf9, 0xa0, 0x38, 0xa5, 0xf8, 0xa3, + 0x9f, 0xa5, 0xaa, 0xa8, 0x75, 0xa9, 0x1c, 0xad, 0x1e, 0xb2, 0x56, 0xbc, + 0x69, 0xc7, 0x65, 0xcd, 0xbb, 0xd9, 0xdc, 0xe6, 0x82, 0xee, 0x46, 0xf9, + 0xc3, 0x04, 0xa1, 0x0f, 0x3c, 0x1b, 0xf6, 0x23, 0x49, 0x25, 0x56, 0x20, + 0xc1, 0x1b, 0x24, 0x1a, 0x3f, 0x1b, 0x05, 0x1e, 0xaf, 0x18, 0x8e, 0x0e, + 0x3f, 0x10, 0xb9, 0x0f, 0x61, 0x0f, 0xbf, 0x15, 0x7b, 0x18, 0x68, 0x22, + 0x36, 0x27, 0xfd, 0x23, 0xcf, 0x2e, 0xe0, 0x42, 0xad, 0x52, 0xde, 0x5c, + 0x94, 0x5f, 0xce, 0x5c, 0xc8, 0x5a, 0xe6, 0x5b, 0x53, 0x5f, 0x3b, 0x5c, + 0x02, 0x54, 0x5c, 0x4c, 0x9d, 0x47, 0x86, 0x42, 0xd1, 0x37, 0x76, 0x2b, + 0xfe, 0x1e, 0x93, 0x12, 0x6e, 0x02, 0x6e, 0xf0, 0x7e, 0xe2, 0xce, 0xd9, + 0x0c, 0xd6, 0x4c, 0xd1, 0x50, 0xc6, 0x60, 0xbf, 0x89, 0xc0, 0x29, 0xc2, + 0x19, 0xc5, 0x34, 0xc3, 0x93, 0xc3, 0x1b, 0xc8, 0xdb, 0xc8, 0xee, 0xcd, + 0xc3, 0xd3, 0x7a, 0xd9, 0x93, 0xdf, 0x52, 0xe2, 0xb4, 0xe0, 0xe9, 0xe1, + 0x5a, 0xea, 0x5f, 0xf0, 0x7d, 0xf4, 0xf4, 0xf5, 0xe9, 0xf6, 0x5a, 0xf7, + 0x02, 0xf3, 0x60, 0xf3, 0x92, 0xf7, 0x6f, 0xfc, 0x41, 0x02, 0x0c, 0x05, + 0x1c, 0x09, 0x2c, 0x0f, 0xcd, 0x16, 0x8d, 0x1f, 0x7d, 0x27, 0xce, 0x2f, + 0xa9, 0x37, 0x70, 0x42, 0xb2, 0x4e, 0xb7, 0x58, 0x00, 0x62, 0xe9, 0x66, + 0x0a, 0x69, 0x1f, 0x6d, 0x42, 0x70, 0x52, 0x72, 0x6a, 0x74, 0x15, 0x74, + 0x6d, 0x72, 0x7b, 0x6f, 0x2e, 0x6c, 0xac, 0x69, 0xa2, 0x65, 0xa3, 0x61, + 0xba, 0x5d, 0x2f, 0x58, 0x99, 0x51, 0x30, 0x4e, 0xea, 0x4c, 0x6c, 0x4a, + 0x6b, 0x48, 0xcf, 0x43, 0xd6, 0x41, 0xf0, 0x41, 0x7a, 0x3e, 0xd3, 0x37, + 0xd9, 0x2b, 0x80, 0x20, 0x8f, 0x15, 0x76, 0x0c, 0x05, 0x06, 0xa2, 0xfe, + 0x82, 0xfa, 0x29, 0xf3, 0x62, 0xe8, 0x78, 0xe1, 0xd8, 0xdf, 0xaf, 0xe2, + 0x56, 0xe9, 0xaf, 0xec, 0xc3, 0xe5, 0x06, 0xe1, 0xa9, 0xdf, 0x92, 0xdb, + 0xd7, 0xdc, 0x61, 0xe0, 0xa0, 0xe6, 0xdb, 0xed, 0x7f, 0xed, 0x50, 0xf7, + 0xda, 0x07, 0x4d, 0x0e, 0xc1, 0x16, 0xe4, 0x1f, 0xe8, 0x2f, 0xb6, 0x45, + 0xd6, 0x4c, 0x3b, 0x4f, 0x38, 0x4d, 0x17, 0x47, 0x4e, 0x49, 0x1b, 0x49, + 0x59, 0x46, 0x00, 0x40, 0x0c, 0x35, 0x40, 0x33, 0xce, 0x30, 0x78, 0x2b, + 0x44, 0x2b, 0x26, 0x29, 0xf2, 0x28, 0xb8, 0x2c, 0xc4, 0x31, 0x30, 0x3a, + 0x65, 0x3d, 0x8a, 0x3b, 0x47, 0x3d, 0xa3, 0x3f, 0x57, 0x42, 0x86, 0x42, + 0x74, 0x3f, 0xf6, 0x40, 0x95, 0x42, 0x3f, 0x42, 0xfc, 0x3e, 0x6b, 0x3b, + 0xeb, 0x3d, 0x59, 0x3a, 0x34, 0x35, 0x82, 0x30, 0x7a, 0x29, 0xf7, 0x26, + 0x48, 0x1d, 0x4d, 0x12, 0x73, 0x07, 0x9e, 0xf9, 0xda, 0xf0, 0x44, 0xe8, + 0xc0, 0xe0, 0x00, 0xdd, 0x50, 0xda, 0x62, 0xd1, 0x8f, 0xcc, 0x1e, 0xd2, + 0x94, 0xd7, 0x94, 0xdd, 0xe4, 0xe1, 0x4d, 0xe2, 0x75, 0xe8, 0xa5, 0xf3, + 0xfb, 0xf7, 0x6f, 0xfe, 0x40, 0x06, 0x49, 0x0c, 0x02, 0x12, 0xfb, 0x0d, + 0x16, 0x11, 0x92, 0x1c, 0x0f, 0x20, 0xc7, 0x1f, 0x55, 0x20, 0x0a, 0x21, + 0x17, 0x26, 0x6e, 0x2d, 0x3a, 0x32, 0x3d, 0x33, 0xca, 0x2f, 0x9a, 0x31, + 0xfb, 0x32, 0x97, 0x31, 0x0f, 0x31, 0xe2, 0x2e, 0xc7, 0x2f, 0xee, 0x2f, + 0xac, 0x35, 0x09, 0x3f, 0xdc, 0x42, 0x20, 0x45, 0xb0, 0x46, 0x8f, 0x4b, + 0x15, 0x53, 0x6b, 0x56, 0xb3, 0x53, 0x64, 0x51, 0xb8, 0x50, 0x28, 0x4f, + 0xaa, 0x4c, 0x2e, 0x47, 0x2c, 0x42, 0x45, 0x3e, 0x8f, 0x3c, 0xdd, 0x38, + 0x1b, 0x30, 0x63, 0x28, 0x29, 0x26, 0x8b, 0x2b, 0x4f, 0x2d, 0x8b, 0x26, + 0x11, 0x1d, 0x70, 0x11, 0x29, 0x05, 0xb8, 0xfe, 0xeb, 0xf9, 0x09, 0xef, + 0xa4, 0xe4, 0xd2, 0xdd, 0xe2, 0xdc, 0x77, 0xd6, 0x9f, 0xca, 0x68, 0xc9, + 0x90, 0xc7, 0x38, 0xc6, 0xdc, 0xcf, 0x0d, 0xdb, 0xfe, 0xd8, 0xd6, 0xcd, + 0x31, 0xc7, 0x0d, 0xc5, 0x31, 0xc8, 0x87, 0xce, 0x73, 0xd1, 0xb7, 0xd2, + 0x2d, 0xd3, 0x75, 0xd3, 0x1a, 0xd6, 0x47, 0xdb, 0xf8, 0xe6, 0xbe, 0xf4, + 0x25, 0xfc, 0x82, 0xfe, 0x03, 0x02, 0xfe, 0x07, 0xaa, 0x10, 0x0e, 0x19, + 0xe8, 0x19, 0x8d, 0x1a, 0xf0, 0x1a, 0x4b, 0x1c, 0x5d, 0x22, 0x02, 0x24, + 0x02, 0x29, 0x97, 0x2f, 0x6b, 0x2a, 0x43, 0x26, 0x43, 0x26, 0x30, 0x28, + 0xa0, 0x32, 0x90, 0x35, 0x46, 0x37, 0xfd, 0x3b, 0x9b, 0x39, 0xfe, 0x3f, + 0x64, 0x47, 0x0f, 0x45, 0xae, 0x45, 0xb9, 0x45, 0xe6, 0x42, 0x4e, 0x43, + 0xfb, 0x3e, 0x9f, 0x3a, 0xbd, 0x38, 0xc2, 0x36, 0x31, 0x3a, 0xc6, 0x3d, + 0xd3, 0x3b, 0x97, 0x33, 0x00, 0x2f, 0x74, 0x2c, 0xf8, 0x27, 0xe3, 0x22, + 0x43, 0x1a, 0xac, 0x0e, 0x1d, 0xff, 0x88, 0xee, 0xf8, 0xe1, 0xf0, 0xd8, + 0xdd, 0xcb, 0x07, 0xc1, 0x47, 0xb8, 0x7e, 0xae, 0x55, 0xab, 0xb0, 0xab, + 0x7c, 0xb0, 0xc2, 0xb6, 0x6a, 0xb5, 0x1a, 0xb0, 0x00, 0xb0, 0x0b, 0xb5, + 0xcb, 0xb8, 0x96, 0xb7, 0x3a, 0xb7, 0xdb, 0xb8, 0x10, 0xba, 0x33, 0xbc, + 0x9b, 0xc0, 0xc4, 0xc8, 0xf0, 0xcc, 0xa6, 0xcf, 0x6f, 0xd1, 0x65, 0xd0, + 0xe0, 0xd4, 0xb5, 0xdb, 0x19, 0xe2, 0xd5, 0xea, 0xe7, 0xeb, 0xfc, 0xe5, + 0xc5, 0xe5, 0x59, 0xe7, 0xc8, 0xe8, 0x51, 0xee, 0xaf, 0xef, 0xe2, 0xee, + 0x22, 0xf7, 0x71, 0xfd, 0xcc, 0x00, 0x57, 0x05, 0x1c, 0x10, 0xd3, 0x1d, + 0x9c, 0x22, 0x78, 0x2c, 0x9c, 0x32, 0xe3, 0x39, 0x7c, 0x47, 0x0c, 0x4c, + 0x43, 0x4c, 0xc0, 0x4a, 0xed, 0x4a, 0x00, 0x4d, 0xed, 0x4d, 0x28, 0x48, + 0xd6, 0x43, 0x60, 0x3d, 0x17, 0x2f, 0x11, 0x20, 0xd7, 0x0d, 0xf5, 0xfd, + 0x15, 0xf0, 0xd1, 0xe6, 0xde, 0xe0, 0x7a, 0xd6, 0xe8, 0xc4, 0xac, 0xb3, + 0xad, 0xae, 0x8a, 0xb1, 0xc4, 0xb3, 0x0e, 0xb4, 0x50, 0xb4, 0x4d, 0xb3, + 0x26, 0xb0, 0x6e, 0xab, 0x92, 0xa8, 0xea, 0xa9, 0x0c, 0xaa, 0xde, 0xaa, + 0x19, 0xb5, 0x49, 0xb7, 0xb2, 0xb3, 0xd3, 0xb8, 0xb5, 0xb8, 0x9a, 0xb8, + 0x5e, 0xb9, 0x39, 0xba, 0xfd, 0xbe, 0xd3, 0xc0, 0x67, 0xbe, 0xb6, 0xbb, + 0xd2, 0xb7, 0x6c, 0xb3, 0xed, 0xb8, 0x05, 0xbf, 0x9b, 0xc4, 0x79, 0xc9, + 0x3e, 0xc6, 0xc6, 0xc9, 0xda, 0xce, 0x3d, 0xce, 0x84, 0xd6, 0x74, 0xdf, + 0xe6, 0xe3, 0x55, 0xee, 0x11, 0xf6, 0x11, 0x01, 0xbd, 0x0e, 0xe1, 0x12, + 0x53, 0x18, 0x5a, 0x20, 0x68, 0x23, 0xb1, 0x26, 0xcf, 0x26, 0x94, 0x1e, + 0xef, 0x1b, 0x65, 0x16, 0x20, 0x12, 0x4b, 0x14, 0x87, 0x0a, 0x12, 0x05, + 0x41, 0x06, 0xbf, 0x04, 0xab, 0x05, 0x2b, 0x03, 0x45, 0xfb, 0xc7, 0xf4, + 0x25, 0xec, 0x65, 0xe6, 0x21, 0xec, 0x01, 0xeb, 0xf0, 0xe4, 0x46, 0xdd, + 0x98, 0xcd, 0x2c, 0xc2, 0x5b, 0xbf, 0xaf, 0xc2, 0xc0, 0xc8, 0xe5, 0xc7, + 0xf0, 0xbc, 0xe4, 0xb7, 0xae, 0xbb, 0xaf, 0xbe, 0xc4, 0xc0, 0x6b, 0xc3, + 0xf5, 0xc5, 0x93, 0xc9, 0x06, 0xcd, 0x27, 0xca, 0x0b, 0xce, 0x54, 0xd7, + 0x17, 0xd7, 0xec, 0xd7, 0xc4, 0xdc, 0xf5, 0xdf, 0x8b, 0xe2, 0xfa, 0xe0, + 0xbd, 0xe3, 0x79, 0xee, 0xc6, 0xf2, 0xfd, 0xf5, 0x7c, 0xf8, 0x1e, 0xf8, + 0x05, 0xf7, 0xa7, 0xf1, 0xef, 0xef, 0xd1, 0xeb, 0xf2, 0xe7, 0x4b, 0xea, + 0x81, 0xea, 0xb6, 0xe6, 0xe1, 0xde, 0x11, 0xdb, 0x7d, 0xe1, 0xc2, 0xec, + 0x6f, 0xf7, 0x18, 0xfd, 0xd1, 0xfa, 0xef, 0xf8, 0xc6, 0xfa, 0xeb, 0xfd, + 0xb4, 0x09, 0xa2, 0x18, 0x09, 0x1f, 0x7b, 0x1b, 0xb1, 0x17, 0x8f, 0x1f, + 0xdc, 0x24, 0xed, 0x20, 0x2f, 0x1e, 0x74, 0x11, 0x61, 0xf8, 0xb3, 0xe5, + 0x5c, 0xdd, 0xe1, 0xd4, 0xfa, 0xcb, 0x63, 0xca, 0x71, 0xc8, 0x94, 0xb7, + 0xd5, 0xa9, 0x16, 0xae, 0x13, 0xb0, 0x5a, 0xb2, 0x31, 0xbc, 0x8d, 0xbf, + 0xd6, 0xb9, 0x10, 0xb3, 0x1c, 0xb4, 0x3c, 0xb9, 0x02, 0xbc, 0x81, 0xc3, + 0x0a, 0xcc, 0x7d, 0xce, 0xb6, 0xd3, 0x66, 0xdb, 0x77, 0xda, 0xf5, 0xd4, + 0x8f, 0xd8, 0xef, 0xe0, 0x89, 0xe6, 0x62, 0xe9, 0xa3, 0xe4, 0x4c, 0xdd, + 0x54, 0xd6, 0xeb, 0xd1, 0x29, 0xda, 0x7a, 0xe3, 0x98, 0xe3, 0x5a, 0xe2, + 0x82, 0xdb, 0xd1, 0xd5, 0xbd, 0xda, 0xbf, 0xe2, 0xd6, 0xed, 0xf8, 0xf4, + 0x32, 0xf7, 0x2a, 0xfe, 0x53, 0x04, 0xae, 0x0c, 0xd5, 0x1b, 0xbd, 0x1f, + 0xa0, 0x1a, 0x31, 0x1b, 0xd1, 0x1c, 0x59, 0x1e, 0xca, 0x1f, 0x1b, 0x1e, + 0xda, 0x16, 0x2f, 0x0e, 0xef, 0x0a, 0x10, 0x0b, 0x2c, 0x08, 0x94, 0x02, + 0xd6, 0xff, 0x75, 0xfc, 0x2e, 0xf7, 0x15, 0xf7, 0xa5, 0xf6, 0xd8, 0xef, + 0xf5, 0xec, 0xb8, 0xec, 0x1f, 0xee, 0x71, 0xf3, 0xb4, 0xf0, 0x64, 0xed, + 0xd5, 0xec, 0x5b, 0xe9, 0xde, 0xec, 0x01, 0xef, 0xed, 0xe9, 0x44, 0xeb, + 0xd8, 0xeb, 0x66, 0xe6, 0xf4, 0xe0, 0xdd, 0xd9, 0xee, 0xd8, 0xc6, 0xde, + 0x01, 0xe3, 0x17, 0xe2, 0xc7, 0xdb, 0xb1, 0xd2, 0x05, 0xce, 0xe1, 0xd7, + 0xb3, 0xe4, 0x10, 0xe7, 0x06, 0xea, 0x39, 0xe9, 0x40, 0xe7, 0x15, 0xf1, + 0x74, 0xf6, 0x60, 0xfe, 0x4f, 0x05, 0xf4, 0xfc, 0x06, 0xfe, 0xfa, 0xfe, + 0xf7, 0xfc, 0x90, 0x05, 0xaf, 0x05, 0xa1, 0x04, 0x4e, 0x07, 0xe2, 0x04, + 0xb6, 0x07, 0x30, 0x06, 0xda, 0x04, 0x09, 0x0e, 0xeb, 0x14, 0x99, 0x1d, + 0x7f, 0x20, 0x88, 0x1d, 0x02, 0x23, 0x6b, 0x2c, 0x12, 0x33, 0xaa, 0x36, + 0x3c, 0x42, 0x19, 0x50, 0x80, 0x56, 0xf1, 0x5c, 0x66, 0x62, 0xcb, 0x64, + 0xc7, 0x65, 0xdb, 0x64, 0xcd, 0x65, 0x9c, 0x60, 0x58, 0x4f, 0x05, 0x3e, + 0x2a, 0x2a, 0x93, 0x18, 0x62, 0x12, 0x2c, 0x0e, 0x60, 0xff, 0xb7, 0xe7, + 0xd7, 0xd7, 0xbd, 0xd3, 0x60, 0xd7, 0x88, 0xda, 0x68, 0xe0, 0x19, 0xe3, + 0x1c, 0xdb, 0xfc, 0xdb, 0xc3, 0xdc, 0x6c, 0xdd, 0x50, 0xea, 0x0f, 0xf2, + 0xa0, 0xf3, 0x9d, 0xf7, 0x61, 0xfe, 0xd5, 0x08, 0xfe, 0x11, 0xd0, 0x14, + 0x70, 0x12, 0x81, 0x15, 0xa2, 0x1a, 0x85, 0x1e, 0x98, 0x26, 0xe2, 0x20, + 0x26, 0x14, 0x52, 0x0e, 0x48, 0x09, 0x5e, 0x0b, 0x8f, 0x0d, 0xbf, 0x07, + 0xad, 0xfe, 0x1c, 0xf9, 0xf4, 0xfc, 0x00, 0x06, 0x3e, 0x0e, 0x27, 0x13, + 0xf2, 0x16, 0x47, 0x1d, 0xce, 0x28, 0x4e, 0x3b, 0xd2, 0x4b, 0x0a, 0x57, + 0xc9, 0x5d, 0x81, 0x60, 0xfa, 0x63, 0x72, 0x67, 0x61, 0x6a, 0xef, 0x68, + 0xfa, 0x65, 0x90, 0x62, 0x74, 0x61, 0xf3, 0x5b, 0x19, 0x51, 0x41, 0x4e, + 0xf0, 0x43, 0x1c, 0x3c, 0x46, 0x39, 0xa1, 0x2e, 0x7f, 0x2c, 0x3a, 0x28, + 0x0f, 0x1a, 0x62, 0x14, 0x9b, 0x14, 0x2d, 0x14, 0xdb, 0x16, 0x42, 0x11, + 0x71, 0x09, 0x95, 0x0b, 0xfa, 0x0d, 0xdb, 0x12, 0xfa, 0x18, 0xf1, 0x18, + 0x1a, 0x1c, 0x3f, 0x1c, 0xfb, 0x18, 0x23, 0x22, 0x0f, 0x2a, 0xb9, 0x2a, + 0x9a, 0x29, 0xeb, 0x20, 0x3f, 0x14, 0x39, 0x0a, 0x66, 0xff, 0xd2, 0x03, + 0x96, 0x10, 0xaa, 0x0a, 0xf7, 0x03, 0xa2, 0xf9, 0xdc, 0xee, 0xe3, 0xf1, + 0xc5, 0xfc, 0x23, 0x0c, 0xd9, 0x13, 0x84, 0x10, 0xe7, 0x0d, 0xb7, 0x12, + 0xab, 0x12, 0x2b, 0x15, 0x5c, 0x1d, 0xae, 0x1e, 0x61, 0x1e, 0xcc, 0x20, + 0x7f, 0x20, 0x03, 0x23, 0x11, 0x27, 0x81, 0x22, 0xa0, 0x21, 0xf2, 0x1c, + 0x44, 0x1c, 0x8a, 0x22, 0xae, 0x22, 0xf3, 0x29, 0x73, 0x2b, 0xc9, 0x27, + 0x2d, 0x29, 0x9b, 0x2a, 0xdb, 0x32, 0x42, 0x3b, 0x7f, 0x3d, 0xc7, 0x41, + 0xa0, 0x41, 0x8b, 0x3e, 0x46, 0x41, 0x5c, 0x41, 0x99, 0x37, 0x41, 0x2a, + 0x9e, 0x23, 0x7f, 0x20, 0x17, 0x1f, 0x30, 0x1b, 0x68, 0x11, 0x52, 0x05, + 0x05, 0xf8, 0xc2, 0xf1, 0xf8, 0xf9, 0x3f, 0x07, 0x14, 0x0c, 0xfe, 0x0d, + 0xd6, 0x0a, 0x6e, 0x01, 0xfd, 0xfe, 0x50, 0x05, 0xba, 0x0c, 0x67, 0x14, + 0x4c, 0x1b, 0x39, 0x1f, 0xef, 0x23, 0x0a, 0x28, 0x5e, 0x2b, 0xc2, 0x2a, + 0x54, 0x2f, 0xfa, 0x38, 0x86, 0x39, 0x60, 0x37, 0x86, 0x2e, 0x60, 0x23, + 0x74, 0x20, 0xef, 0x1b, 0x02, 0x16, 0x57, 0x0e, 0xc3, 0x04, 0xb5, 0xfb, + 0x1d, 0xf1, 0xa9, 0xe9, 0x0b, 0xe6, 0x00, 0xe6, 0xd3, 0xe3, 0xe1, 0xe0, + 0x9f, 0xe3, 0x79, 0xea, 0x3d, 0xf4, 0x68, 0xf8, 0x00, 0xf7, 0x37, 0xfa, + 0x44, 0x07, 0x8c, 0x15, 0xff, 0x21, 0xf0, 0x24, 0x78, 0x1c, 0xcf, 0x17, + 0xfc, 0x18, 0x2e, 0x23, 0x01, 0x2b, 0x3f, 0x2b, 0x57, 0x26, 0x49, 0x1b, + 0xaa, 0x13, 0x47, 0x11, 0x2a, 0x14, 0x23, 0x18, 0x3a, 0x12, 0xee, 0x03, + 0x95, 0xfe, 0xb9, 0xfe, 0x8b, 0x01, 0xb1, 0x06, 0x7f, 0x03, 0x4b, 0xff, + 0xa7, 0xfc, 0xf1, 0xfc, 0x13, 0x08, 0xc8, 0x15, 0x8d, 0x1c, 0x90, 0x22, + 0x61, 0x24, 0x5c, 0x26, 0xc7, 0x30, 0x04, 0x3c, 0x6f, 0x47, 0xc6, 0x50, + 0xa9, 0x54, 0xd1, 0x55, 0xab, 0x55, 0x73, 0x53, 0x23, 0x56, 0x39, 0x5a, + 0x0f, 0x59, 0xef, 0x51, 0x4c, 0x47, 0x5b, 0x40, 0x79, 0x35, 0xf1, 0x2e, + 0xf7, 0x30, 0xbc, 0x31, 0x4a, 0x2e, 0x89, 0x23, 0xdb, 0x18, 0x9c, 0x12, + 0x2c, 0x10, 0xf8, 0x14, 0x96, 0x18, 0x88, 0x13, 0xf0, 0x12, 0x96, 0x12, + 0xa7, 0x11, 0x56, 0x14, 0x03, 0x12, 0x91, 0x15, 0x1e, 0x17, 0x47, 0x14, + 0x94, 0x18, 0x7d, 0x17, 0x41, 0x12, 0xf3, 0x11, 0xd8, 0x14, 0x13, 0x14, + 0x2a, 0x11, 0x9c, 0x12, 0x90, 0x15, 0xb5, 0x1a, 0xd7, 0x22, 0xb7, 0x27, + 0xb1, 0x23, 0xe9, 0x1a, 0x01, 0x10, 0x4f, 0x02, 0x75, 0xfa, 0x96, 0xf8, + 0x92, 0xf4, 0xe4, 0xf1, 0x40, 0xf2, 0x2d, 0xf1, 0xe2, 0xeb, 0x39, 0xe2, + 0x2e, 0xe6, 0x10, 0xf7, 0x6a, 0x01, 0xad, 0x0c, 0x42, 0x17, 0x16, 0x14, + 0x23, 0x0f, 0xaf, 0x16, 0xdb, 0x20, 0xff, 0x23, 0x72, 0x29, 0x34, 0x32, + 0x1a, 0x32, 0x76, 0x30, 0xf1, 0x36, 0x6f, 0x3c, 0x81, 0x3d, 0x66, 0x3d, + 0x1d, 0x43, 0x74, 0x48, 0x7d, 0x4d, 0x88, 0x51, 0x30, 0x4b, 0x8d, 0x47, + 0xe0, 0x46, 0x1e, 0x47, 0x12, 0x49, 0xdc, 0x45, 0x50, 0x3f, 0xd4, 0x38, + 0xd0, 0x33, 0xf9, 0x2f, 0x8e, 0x2d, 0x42, 0x2b, 0x4a, 0x27, 0x7e, 0x21, + 0x06, 0x1f, 0x68, 0x22, 0x87, 0x25, 0x2a, 0x26, 0x0a, 0x27, 0xd6, 0x24, + 0xfa, 0x22, 0x21, 0x25, 0x48, 0x22, 0x43, 0x1e, 0x08, 0x1a, 0xa9, 0x10, + 0x21, 0x09, 0x00, 0x07, 0x14, 0x01, 0xd7, 0xf8, 0xeb, 0xf3, 0x9d, 0xeb, + 0x6c, 0xe6, 0x25, 0xe6, 0xc0, 0xe7, 0xa8, 0xe8, 0x10, 0xe0, 0x8c, 0xd4, + 0x5a, 0xd1, 0x05, 0xd3, 0x6e, 0xd8, 0xb8, 0xdc, 0x17, 0xd1, 0xbc, 0xc5, + 0x6d, 0xc6, 0x0e, 0xc8, 0x4c, 0xd2, 0xf2, 0xdd, 0x56, 0xe0, 0x46, 0xe0, + 0xab, 0xdb, 0x9d, 0xdd, 0x78, 0xed, 0x97, 0xff, 0x12, 0x13, 0x1e, 0x20, + 0x23, 0x1b, 0x9d, 0x16, 0x10, 0x1c, 0x1c, 0x21, 0xf3, 0x2b, 0x91, 0x2f, + 0xe6, 0x2a, 0xed, 0x29, 0x33, 0x26, 0x69, 0x27, 0x98, 0x29, 0x44, 0x2c, + 0xc4, 0x30, 0xff, 0x30, 0x57, 0x30, 0x58, 0x2d, 0xfb, 0x22, 0x74, 0x19, + 0x68, 0x14, 0xbe, 0x08, 0xe6, 0x02, 0x11, 0x00, 0x65, 0xfc, 0xb4, 0xfa, + 0x9d, 0xef, 0xb0, 0xe6, 0xb5, 0xe0, 0xdb, 0xdb, 0xa1, 0xdf, 0x8c, 0xe7, + 0x74, 0xe9, 0x00, 0xe3, 0x16, 0xdc, 0xed, 0xdc, 0xa2, 0xde, 0xbd, 0xdc, + 0x9c, 0xe2, 0xfa, 0xe4, 0x50, 0xdf, 0x06, 0xd7, 0xbc, 0xd0, 0x73, 0xd0, + 0xa6, 0xc6, 0xa4, 0xb5, 0x85, 0xa7, 0x0a, 0x9d, 0xdf, 0x98, 0x01, 0x98, + 0x50, 0x9a, 0xca, 0x9e, 0x1e, 0x9c, 0x18, 0x94, 0xe1, 0x8f, 0xf0, 0x91, + 0x35, 0x99, 0x8e, 0xa0, 0xf9, 0xa6, 0xf1, 0xb0, 0xe8, 0xb3, 0x61, 0xac, + 0xf1, 0xb1, 0x65, 0xc0, 0xe4, 0xcd, 0x8b, 0xdf, 0x36, 0xee, 0x70, 0xf7, + 0xb5, 0xfb, 0x9d, 0x05, 0xb4, 0x11, 0xe2, 0x18, 0xe2, 0x1c, 0x8c, 0x1c, + 0x11, 0x1f, 0x61, 0x1d, 0xcc, 0x1d, 0xfd, 0x1f, 0xb6, 0x1c, 0x21, 0x1e, + 0x28, 0x1a, 0x1c, 0x16, 0x03, 0x19, 0x8b, 0x19, 0x1a, 0x1c, 0xaf, 0x1d, + 0x19, 0x19, 0x6c, 0x15, 0xf2, 0x16, 0x2c, 0x18, 0x9d, 0x1a, 0x2b, 0x1d, + 0x53, 0x1a, 0x5b, 0x19, 0x84, 0x15, 0x5b, 0x10, 0x17, 0x0f, 0x71, 0x0b, + 0x12, 0x0c, 0x3c, 0x08, 0x08, 0xfb, 0xd2, 0xee, 0xcc, 0xe4, 0x0b, 0xdd, + 0x33, 0xd3, 0x6c, 0xcc, 0x9a, 0xc7, 0xc0, 0xbf, 0x55, 0xba, 0x91, 0xb4, + 0x12, 0xae, 0x64, 0xab, 0xe9, 0xaa, 0x08, 0xab, 0x81, 0xa9, 0xbf, 0xa4, + 0xdd, 0xa3, 0xa0, 0xa5, 0xb3, 0xa7, 0x64, 0xa9, 0x42, 0xa6, 0xf2, 0xa6, + 0xf4, 0xab, 0x85, 0xaf, 0xbc, 0xb6, 0x18, 0xbc, 0x16, 0xb8, 0xf1, 0xb6, + 0x77, 0xb7, 0xf6, 0xb7, 0xfc, 0xbf, 0xfa, 0xc5, 0xda, 0xc9, 0x56, 0xcc, + 0x39, 0xcb, 0x1a, 0xcf, 0xef, 0xd7, 0xa0, 0xdd, 0x9a, 0xe3, 0x37, 0xec, + 0xcd, 0xf6, 0x9f, 0x02, 0x88, 0x07, 0x7b, 0x08, 0x01, 0x08, 0xe3, 0x0b, + 0x2d, 0x13, 0x1f, 0x1b, 0x40, 0x26, 0xe3, 0x25, 0xab, 0x1b, 0xac, 0x16, + 0x2f, 0x1b, 0x9c, 0x26, 0x0d, 0x2f, 0xe1, 0x2d, 0xbc, 0x2b, 0x45, 0x24, + 0x72, 0x1a, 0x77, 0x17, 0xca, 0x0a, 0x1f, 0xfc, 0xf4, 0xef, 0xfd, 0xe6, + 0x3f, 0xea, 0xf4, 0xe8, 0x82, 0xe1, 0xcf, 0xdc, 0xe5, 0xd7, 0x89, 0xd6, + 0x03, 0xdc, 0xef, 0xe4, 0x50, 0xf2, 0xf4, 0xf7, 0x4f, 0xef, 0xc4, 0xe3, + 0xc5, 0xd2, 0x43, 0xc3, 0xdc, 0xb8, 0xff, 0xaf, 0xe3, 0xaa, 0x5d, 0xa2, + 0x4e, 0x9b, 0x45, 0x98, 0xe3, 0x92, 0x3f, 0x90, 0x9b, 0x90, 0xca, 0x91, + 0xd8, 0x94, 0x67, 0x99, 0x7f, 0x9d, 0x93, 0x9d, 0xca, 0x9b, 0xe8, 0x9a, + 0x33, 0x9d, 0x8d, 0xa2, 0x50, 0xa9, 0x75, 0xb1, 0xfc, 0xb8, 0x96, 0xbf, + 0xd9, 0xc6, 0x61, 0xcf, 0xfa, 0xd7, 0x5c, 0xe6, 0x9b, 0xf6, 0xe3, 0x00, + 0xb4, 0x07, 0x7c, 0x09, 0x59, 0x0a, 0x59, 0x0f, 0x89, 0x14, 0x32, 0x17, + 0xc5, 0x16, 0xb3, 0x0f, 0xbe, 0x06, 0x8e, 0x02, 0x5c, 0xfe, 0x15, 0xfd, + 0x72, 0xfe, 0x03, 0xfc, 0xb7, 0xfe, 0xf3, 0x04, 0x7d, 0x09, 0x99, 0x10, + 0x2f, 0x16, 0xbc, 0x1e, 0x1c, 0x28, 0x72, 0x28, 0xac, 0x26, 0x61, 0x27, + 0xb1, 0x23, 0x14, 0x1b, 0xe7, 0x16, 0x52, 0x0f, 0x8b, 0x05, 0x1f, 0xfc, + 0xe7, 0xef, 0xc2, 0xe9, 0x94, 0xe1, 0x1e, 0xd9, 0xa9, 0xd1, 0x15, 0xc9, + 0x78, 0xc4, 0x30, 0xbf, 0x92, 0xb7, 0x89, 0xb0, 0x5f, 0xb0, 0x67, 0xb1, + 0xa6, 0xaf, 0x5d, 0xab, 0xc5, 0xa4, 0x49, 0xa2, 0x56, 0xa1, 0x5b, 0xa3, + 0x0f, 0xa9, 0x89, 0xad, 0xbb, 0xaf, 0xf6, 0xb0, 0x4e, 0xb3, 0xd6, 0xb7, + 0xfc, 0xc2, 0x62, 0xcf, 0x6c, 0xd9, 0x0c, 0xe3, 0x3e, 0xe3, 0x17, 0xe1, + 0x9b, 0xe1, 0x07, 0xe2, 0x21, 0xe9, 0x61, 0xef, 0x6b, 0xf1, 0xd2, 0xfa, + 0x06, 0x0a, 0xf1, 0x10, 0x0f, 0x12, 0x77, 0x15, 0xfd, 0x1c, 0xd9, 0x29, + 0x8c, 0x32, 0x9d, 0x30, 0x14, 0x28, 0x0f, 0x1e, 0xe3, 0x16, 0x8b, 0x1c, + 0xb2, 0x21, 0xe8, 0x1b, 0xf1, 0x14, 0xaf, 0x0c, 0xc7, 0x12, 0x44, 0x18, + 0xe2, 0x17, 0x60, 0x25, 0xf9, 0x23, 0xc0, 0x1b, 0x28, 0x1f, 0xfc, 0x21, + 0x14, 0x2f, 0x2b, 0x3a, 0x44, 0x37, 0x09, 0x34, 0x2a, 0x2c, 0xba, 0x20, + 0xfa, 0x1e, 0x3d, 0x20, 0x80, 0x1d, 0x31, 0x1d, 0x37, 0x10, 0x62, 0xf6, + 0x57, 0xe3, 0xe4, 0xd4, 0x6f, 0xd1, 0x9f, 0xcf, 0x30, 0xc8, 0x4f, 0xca, + 0xc4, 0xc2, 0x87, 0xb1, 0x8a, 0xb1, 0xe3, 0xb4, 0xf5, 0xb1, 0x0e, 0xb5, + 0xb0, 0xbb, 0xfa, 0xc2, 0xa5, 0xc2, 0x8a, 0xbe, 0x00, 0xc2, 0x31, 0xc0, + 0xe4, 0xc4, 0x58, 0xd7, 0x5f, 0xe1, 0x9a, 0xe5, 0xf7, 0xe9, 0x3b, 0xed, + 0x22, 0xf2, 0xd1, 0xfb, 0x47, 0x08, 0xc4, 0x0e, 0xe6, 0x0e, 0x6d, 0x0d, + 0x10, 0x10, 0xe6, 0x11, 0xf7, 0x15, 0x56, 0x1e, 0x17, 0x21, 0x08, 0x27, + 0xc8, 0x2b, 0xaf, 0x2a, 0x6e, 0x2a, 0xda, 0x27, 0x29, 0x2a, 0x0d, 0x30, + 0xb9, 0x2f, 0xb8, 0x31, 0xe6, 0x36, 0x33, 0x39, 0x15, 0x3e, 0xfc, 0x40, + 0x74, 0x42, 0x3a, 0x44, 0x38, 0x45, 0x39, 0x48, 0x1a, 0x49, 0xd6, 0x47, + 0x43, 0x44, 0x2c, 0x3f, 0xa0, 0x35, 0x78, 0x2c, 0x4c, 0x29, 0x25, 0x23, + 0x51, 0x1c, 0x65, 0x18, 0xd2, 0x11, 0x44, 0x08, 0xe1, 0xfe, 0xc4, 0xf6, + 0x99, 0xf1, 0x81, 0xee, 0x4c, 0xeb, 0x17, 0xe7, 0xa3, 0xe1, 0x0c, 0xde, + 0x0c, 0xdd, 0x57, 0xdb, 0x5c, 0xd6, 0x00, 0xd2, 0xe1, 0xd1, 0x21, 0xd5, + 0x62, 0xd8, 0x88, 0xdb, 0xf6, 0xdc, 0x1f, 0xde, 0xe1, 0xe1, 0xb4, 0xe5, + 0xbe, 0xec, 0x2b, 0xf4, 0xd8, 0xfb, 0x6c, 0x02, 0x86, 0x03, 0x7f, 0x06, + 0x7f, 0x0a, 0xa9, 0x0f, 0x3e, 0x14, 0xf9, 0x13, 0x8b, 0x17, 0x0f, 0x1e, + 0xaf, 0x20, 0xa4, 0x25, 0xa5, 0x2b, 0x4d, 0x2d, 0x04, 0x30, 0xd6, 0x2e, + 0x5a, 0x2f, 0x9e, 0x34, 0xe3, 0x34, 0x28, 0x3a, 0x27, 0x42, 0x7c, 0x45, + 0xcb, 0x45, 0xa8, 0x44, 0x1b, 0x49, 0x89, 0x4e, 0xf7, 0x4e, 0x14, 0x53, + 0x0e, 0x57, 0x25, 0x54, 0x05, 0x53, 0xec, 0x4f, 0xb3, 0x49, 0xc6, 0x41, + 0x5c, 0x3c, 0x7b, 0x3d, 0x24, 0x3a, 0x76, 0x38, 0x50, 0x33, 0x3e, 0x28, + 0x6c, 0x28, 0x6a, 0x2e, 0x85, 0x33, 0x34, 0x31, 0xe9, 0x20, 0x71, 0x0a, + 0xe6, 0xf9, 0x7f, 0xf6, 0x64, 0xf9, 0x0e, 0xf0, 0x81, 0xdc, 0xbb, 0xcd, + 0x58, 0xbf, 0xd4, 0xb8, 0x14, 0xc8, 0x70, 0xd4, 0x19, 0xd4, 0x70, 0xdb, + 0x35, 0xdd, 0x44, 0xd4, 0x5b, 0xd4, 0x83, 0xdc, 0x0e, 0xe6, 0x25, 0xee, + 0x16, 0xf2, 0xe9, 0xf6, 0x38, 0xfb, 0x31, 0xf9, 0x88, 0xff, 0x1d, 0x06, + 0x60, 0x03, 0x4a, 0x09, 0x5c, 0x0e, 0xc0, 0x0f, 0xb0, 0x14, 0x5a, 0x13, + 0x1c, 0x0d, 0x81, 0x0d, 0x73, 0x12, 0xe8, 0x16, 0x8e, 0x23, 0x93, 0x29, + 0x82, 0x24, 0x82, 0x29, 0x7c, 0x29, 0x7f, 0x25, 0x80, 0x29, 0x62, 0x26, + 0x2d, 0x2a, 0x29, 0x32, 0x9a, 0x33, 0x59, 0x3d, 0xc1, 0x47, 0x19, 0x4d, + 0x5b, 0x52, 0x0b, 0x53, 0x44, 0x4d, 0xb6, 0x4e, 0xc5, 0x4c, 0xdb, 0x41, + 0x66, 0x3c, 0x2e, 0x2f, 0x71, 0x21, 0x83, 0x1a, 0x8b, 0x11, 0x21, 0x0c, + 0xad, 0x08, 0x2b, 0x03, 0xa7, 0xfe, 0x8d, 0xfa, 0xfb, 0xf6, 0xe0, 0xf3, + 0xda, 0xef, 0x4f, 0xf1, 0xa9, 0xf5, 0x34, 0xf6, 0x40, 0xf4, 0x72, 0xf4, + 0xee, 0xf2, 0xa6, 0xf1, 0x22, 0xf1, 0x4f, 0xee, 0x64, 0xf4, 0xff, 0xf5, + 0x35, 0xf3, 0xd0, 0xf5, 0xa8, 0xf8, 0x6a, 0xfb, 0x53, 0xff, 0xb4, 0x05, + 0x4a, 0x0a, 0xb2, 0x11, 0xf6, 0x17, 0x48, 0x1a, 0xa7, 0x13, 0x19, 0x0c, + 0xcc, 0x0f, 0x44, 0x16, 0x16, 0x21, 0x78, 0x24, 0x74, 0x21, 0x12, 0x23, + 0x4c, 0x2a, 0x1c, 0x35, 0xfb, 0x41, 0xeb, 0x4e, 0xf9, 0x52, 0xe3, 0x52, + 0xc2, 0x51, 0x94, 0x51, 0xc6, 0x53, 0x88, 0x57, 0x96, 0x59, 0x12, 0x56, + 0x95, 0x51, 0x94, 0x4f, 0xd7, 0x4c, 0x0a, 0x49, 0x26, 0x48, 0x41, 0x46, + 0x1b, 0x48, 0x5f, 0x48, 0xb2, 0x47, 0x2c, 0x4d, 0xb8, 0x4f, 0x2f, 0x55, + 0x4b, 0x5b, 0x44, 0x5a, 0xb8, 0x59, 0xb5, 0x5c, 0x09, 0x61, 0xc8, 0x66, + 0x70, 0x69, 0x8e, 0x68, 0xf3, 0x66, 0x34, 0x5b, 0x38, 0x44, 0x3e, 0x2f, + 0xeb, 0x22, 0x1b, 0x1c, 0x11, 0x14, 0x0a, 0x0b, 0x24, 0x03, 0x54, 0xef, + 0xdc, 0xd8, 0x20, 0xd8, 0xfe, 0xe4, 0x58, 0xef, 0xe8, 0xfd, 0xdb, 0x0d, + 0xa4, 0x08, 0x33, 0xf4, 0xe2, 0xe4, 0xae, 0xe2, 0x39, 0xe4, 0x89, 0xea, + 0x61, 0x00, 0x48, 0x0a, 0x85, 0x03, 0x63, 0x05, 0x5a, 0x0a, 0x6e, 0x0c, + 0x1d, 0x16, 0x6a, 0x25, 0x5f, 0x32, 0xe1, 0x36, 0xe6, 0x36, 0x4e, 0x34, + 0xdf, 0x28, 0x42, 0x26, 0x64, 0x27, 0xc4, 0x22, 0xf8, 0x22, 0x48, 0x1c, + 0x44, 0x14, 0xcf, 0x13, 0x38, 0x0f, 0xcc, 0x0c, 0x54, 0x10, 0xc5, 0x11, + 0x3a, 0x16, 0x7e, 0x19, 0x2c, 0x1e, 0xcc, 0x2a, 0x35, 0x33, 0x5b, 0x3d, + 0x6f, 0x45, 0x11, 0x46, 0x72, 0x44, 0x6c, 0x3e, 0xf3, 0x37, 0xa6, 0x33, + 0xbd, 0x33, 0xd8, 0x2c, 0xd9, 0x24, 0x60, 0x21, 0xcd, 0x18, 0x20, 0x16, + 0xeb, 0x14, 0x23, 0x11, 0x71, 0x0b, 0x18, 0x00, 0xf6, 0xf5, 0x53, 0xef, + 0xa4, 0xe9, 0x83, 0xe6, 0xf1, 0xe3, 0xaa, 0xdf, 0x10, 0xdd, 0xa5, 0xdb, + 0xec, 0xd9, 0x36, 0xd5, 0x42, 0xd6, 0x9a, 0xdd, 0x73, 0xe2, 0x82, 0xe9, + 0x1a, 0xf0, 0xdf, 0xf4, 0x0b, 0xf9, 0x93, 0xfe, 0x14, 0x05, 0xd6, 0x09, + 0x76, 0x0f, 0xc4, 0x15, 0xd2, 0x14, 0x72, 0x0c, 0x06, 0x0a, 0x9d, 0x0c, + 0x1b, 0x12, 0xf2, 0x15, 0xc0, 0x15, 0x0e, 0x12, 0x92, 0x0d, 0xaa, 0x10, + 0x50, 0x14, 0xcb, 0x17, 0x56, 0x1a, 0x8e, 0x19, 0x0a, 0x17, 0x3f, 0x13, + 0x75, 0x13, 0x27, 0x15, 0xef, 0x14, 0xc5, 0x14, 0x46, 0x13, 0xbe, 0x0e, + 0x67, 0x10, 0x90, 0x13, 0x1b, 0x13, 0x98, 0x15, 0x36, 0x17, 0xef, 0x1d, + 0x1c, 0x21, 0xcb, 0x18, 0x68, 0x15, 0x20, 0x12, 0x94, 0x10, 0x7e, 0x18, + 0x01, 0x16, 0xbb, 0x0b, 0xc8, 0x0b, 0x2b, 0x0e, 0x88, 0x13, 0xa7, 0x1e, + 0x01, 0x25, 0x65, 0x26, 0x06, 0x1f, 0xf9, 0x0d, 0x42, 0x02, 0xb2, 0xfb, + 0xc4, 0xf6, 0x55, 0xf5, 0xf9, 0xea, 0xe3, 0xe5, 0x4e, 0xea, 0xca, 0xda, + 0x1e, 0xcf, 0x93, 0xda, 0x3f, 0xe7, 0x2d, 0xee, 0x67, 0xf7, 0xba, 0x02, + 0xc4, 0xf7, 0xc5, 0xe6, 0xa3, 0xe9, 0x32, 0xed, 0xb6, 0xec, 0xef, 0xf1, + 0x3c, 0x00, 0xaa, 0x06, 0x5b, 0x04, 0xc9, 0x0c, 0x03, 0x18, 0xf0, 0x22, + 0x36, 0x2e, 0x3c, 0x32, 0x03, 0x2c, 0xba, 0x1e, 0xb2, 0x13, 0xb8, 0x0b, + 0x0c, 0x10, 0xfa, 0x18, 0x66, 0x0f, 0x6e, 0x06, 0x05, 0x05, 0x39, 0x01, + 0x72, 0x05, 0x5f, 0x0c, 0xbb, 0x0d, 0x42, 0x0e, 0x50, 0x16, 0x76, 0x1f, + 0x50, 0x1e, 0x2c, 0x1b, 0x8a, 0x1a, 0xb7, 0x1d, 0x86, 0x20, 0x7c, 0x1f, + 0x79, 0x21, 0x9b, 0x1e, 0xcd, 0x15, 0x14, 0x13, 0x3e, 0x0e, 0xb0, 0x0b, + 0xca, 0x0c, 0xab, 0x01, 0xde, 0xfc, 0x60, 0xfe, 0xde, 0xfc, 0xbd, 0xfc, + 0x97, 0xf9, 0xdd, 0xfa, 0x26, 0xf5, 0x93, 0xea, 0xa8, 0xe5, 0xcf, 0xe2, + 0xb7, 0xe2, 0x6a, 0xdf, 0xc0, 0xdf, 0xce, 0xe0, 0x9b, 0xe2, 0x9a, 0xea, + 0x5c, 0xea, 0xaa, 0xe8, 0xb2, 0xee, 0x0c, 0xf3, 0x43, 0xf8, 0x84, 0xfa, + 0x71, 0xfb, 0x24, 0x02, 0x84, 0x01, 0x53, 0x02, 0x0d, 0x0a, 0x49, 0x0e, + 0xf9, 0x11, 0xcd, 0x16, 0x0e, 0x1a, 0xf8, 0x17, 0x27, 0x17, 0xef, 0x1a, + 0x79, 0x21, 0xa7, 0x2a, 0xc4, 0x2c, 0x25, 0x2a, 0x26, 0x2d, 0x9c, 0x30, + 0x17, 0x30, 0xf4, 0x2c, 0x60, 0x2b, 0xe6, 0x2a, 0x02, 0x27, 0x12, 0x24, + 0xef, 0x20, 0x1f, 0x1d, 0x65, 0x1a, 0x10, 0x18, 0xff, 0x16, 0x9f, 0x14, + 0xfb, 0x0e, 0x9b, 0x09, 0x50, 0x09, 0x2c, 0x07, 0x17, 0x05, 0x4c, 0x05, + 0x7b, 0x00, 0x88, 0x00, 0xe9, 0x02, 0x7e, 0xfc, 0x18, 0xfa, 0x1d, 0xfe, + 0x5d, 0x00, 0xf3, 0x04, 0x09, 0x0a, 0xb9, 0x0f, 0x1e, 0x14, 0xcb, 0x13, + 0xe7, 0x19, 0x36, 0x21, 0x5d, 0x1b, 0x53, 0x0c, 0xb3, 0xf7, 0x62, 0xe7, + 0xaf, 0xe1, 0xc8, 0xda, 0x50, 0xd5, 0xe0, 0xd0, 0x46, 0xc5, 0x57, 0xb5, + 0xc6, 0xaa, 0x0f, 0xb5, 0x80, 0xcb, 0x61, 0xd4, 0x86, 0xd4, 0x01, 0xe4, + 0x13, 0xf1, 0xb4, 0xea, 0xbc, 0xef, 0x68, 0xff, 0xf4, 0x03, 0x2c, 0x09, + 0x6d, 0x1c, 0x70, 0x28, 0x07, 0x20, 0xdb, 0x26, 0x1a, 0x34, 0x80, 0x2e, + 0x98, 0x30, 0x88, 0x31, 0x62, 0x2a, 0x61, 0x26, 0xa2, 0x21, 0xd0, 0x1d, + 0x31, 0x13, 0xa0, 0x0a, 0x38, 0x05, 0xd5, 0xfe, 0x41, 0x03, 0xac, 0x08, + 0xb7, 0x05, 0x81, 0xf9, 0x57, 0xea, 0x9d, 0xe0, 0xc9, 0xdb, 0x1f, 0xdc, + 0xfb, 0xdb, 0x7d, 0xdc, 0xed, 0xde, 0x93, 0xdd, 0xff, 0xe2, 0x0d, 0xe8, + 0xc9, 0xe7, 0xf3, 0xec, 0x26, 0xeb, 0x09, 0xe6, 0x21, 0xe4, 0x84, 0xe8, + 0xdb, 0xe9, 0x38, 0xd8, 0x60, 0xc9, 0xc6, 0xbf, 0xb4, 0xb9, 0x01, 0xb8, + 0x5a, 0xb0, 0xf3, 0xae, 0xf5, 0xa8, 0xb0, 0x9a, 0x4c, 0xa0, 0xf4, 0xa6, + 0x66, 0xa3, 0x51, 0xa7, 0x40, 0xa5, 0x11, 0xa2, 0x6a, 0xa6, 0x94, 0xab, + 0x6a, 0xb2, 0x98, 0xb6, 0x9c, 0xb8, 0x61, 0xb7, 0x39, 0xba, 0x74, 0xc2, + 0x7e, 0xce, 0xfa, 0xe0, 0x74, 0xe9, 0xe9, 0xef, 0xf6, 0xf9, 0x15, 0xff, + 0x9c, 0x0a, 0xf9, 0x11, 0xa0, 0x14, 0x3b, 0x1a, 0x10, 0x14, 0xb2, 0x10, + 0x82, 0x11, 0xbe, 0x0d, 0x85, 0x14, 0x04, 0x15, 0xe6, 0x0b, 0x03, 0x0f, + 0x26, 0x15, 0x14, 0x0f, 0xf1, 0x0b, 0x60, 0x16, 0xda, 0x1a, 0x54, 0x18, + 0xd9, 0x14, 0xb1, 0x10, 0x5f, 0x12, 0x6d, 0x0f, 0x5b, 0x0b, 0xf1, 0x0b, + 0x65, 0x06, 0x4a, 0xff, 0x5a, 0xf9, 0x7a, 0xed, 0x1f, 0xe8, 0x65, 0xec, + 0x8b, 0xe9, 0xde, 0xe2, 0x36, 0xe1, 0xc4, 0xdd, 0xb3, 0xd4, 0x2f, 0xd1, + 0x01, 0xd3, 0x2f, 0xce, 0x25, 0xc9, 0xae, 0xcb, 0xdd, 0xd3, 0xfa, 0xd6, + 0x58, 0xd3, 0xb3, 0xd7, 0x00, 0xe0, 0x54, 0xdf, 0xf3, 0xd8, 0xb5, 0xcd, + 0xa5, 0xc1, 0x78, 0xb6, 0xb5, 0xa9, 0xa8, 0xa9, 0x07, 0xae, 0x75, 0xa9, + 0x03, 0xa6, 0x00, 0xa2, 0x49, 0x9c, 0x84, 0x9f, 0xe0, 0xa9, 0x32, 0xb1, + 0x75, 0xc1, 0x3f, 0xd3, 0xcf, 0xcf, 0x5e, 0xc9, 0xa5, 0xcb, 0xb0, 0xd1, + 0xa3, 0xe0, 0x33, 0xf2, 0xc2, 0x03, 0x62, 0x14, 0x49, 0x18, 0x45, 0x1d, + 0x05, 0x29, 0x68, 0x31, 0xc9, 0x3e, 0xfc, 0x4a, 0x02, 0x4c, 0x99, 0x4a, + 0xe5, 0x4c, 0x62, 0x49, 0xcc, 0x3f, 0xab, 0x38, 0x58, 0x2f, 0xe1, 0x24, + 0xbc, 0x17, 0xe3, 0x0b, 0x31, 0x05, 0xe3, 0xfa, 0xb9, 0xf1, 0xb7, 0xe9, + 0x31, 0xe3, 0x80, 0xe0, 0xf8, 0xe2, 0xce, 0xee, 0x6b, 0xf8, 0x18, 0xfe, + 0xdc, 0xff, 0xaf, 0xfa, 0x04, 0xfa, 0x3d, 0xf8, 0x7a, 0xf3, 0x03, 0xec, + 0x8e, 0xd5, 0x2b, 0xbf, 0xd3, 0xb6, 0x2d, 0xb2, 0x90, 0xaf, 0xca, 0xb4, + 0xf5, 0xb3, 0x73, 0xa7, 0x1c, 0xa3, 0x02, 0xa4, 0x9a, 0xa3, 0xe5, 0xa5, + 0x9c, 0xa8, 0xd8, 0xa7, 0x0c, 0xa1, 0xf8, 0x9f, 0x0c, 0xa3, 0x59, 0xa3, + 0xb9, 0xa3, 0x6a, 0xa4, 0x18, 0xab, 0xf8, 0xaf, 0xf8, 0xac, 0x58, 0xb4, + 0x27, 0xc2, 0x0f, 0xc6, 0xb2, 0xce, 0x55, 0xd8, 0x81, 0xda, 0x8d, 0xe4, + 0x6a, 0xf1, 0x89, 0xfb, 0x43, 0x06, 0xe4, 0x0b, 0x6b, 0x06, 0x6c, 0xfe, + 0x3f, 0xfb, 0xb0, 0xfc, 0xc8, 0x02, 0x07, 0x07, 0x78, 0x0c, 0x6a, 0x0e, + 0xa6, 0x0c, 0x22, 0x17, 0xff, 0x21, 0xbd, 0x24, 0x36, 0x28, 0x98, 0x28, + 0xe6, 0x26, 0xe3, 0x23, 0xf4, 0x1b, 0x96, 0x18, 0x11, 0x17, 0xcb, 0x0f, + 0x84, 0x0b, 0x44, 0x05, 0x78, 0xf9, 0x27, 0xf7, 0x6b, 0xfb, 0xcd, 0xf7, + 0xf7, 0xf4, 0x63, 0xf6, 0x75, 0xf2, 0xb0, 0xeb, 0x23, 0xe5, 0xa5, 0xe3, + 0x1e, 0xe5, 0xb2, 0xe3, 0x3a, 0xe3, 0x36, 0xe1, 0x6e, 0xdb, 0x30, 0xd7, + 0xbe, 0xd7, 0xaa, 0xd9, 0xa4, 0xdc, 0x4c, 0xe4, 0x10, 0xea, 0x51, 0xe6, + 0xc2, 0xde, 0x48, 0xd7, 0xfc, 0xc7, 0x13, 0xb9, 0x2f, 0xb6, 0x94, 0xb5, + 0x24, 0xb3, 0x5d, 0xb4, 0xd2, 0xb0, 0x8f, 0xa6, 0xd2, 0xa3, 0x0e, 0xac, + 0xb8, 0xb6, 0x52, 0xbf, 0xe1, 0xcd, 0x47, 0xdc, 0x8b, 0xdc, 0x1c, 0xdb, + 0xa0, 0xe5, 0x41, 0xef, 0xee, 0xee, 0x96, 0xfb, 0x33, 0x0f, 0x7d, 0x12, + 0x79, 0x17, 0x3d, 0x23, 0xf3, 0x29, 0xd0, 0x31, 0xe9, 0x3d, 0xc3, 0x46, + 0x15, 0x47, 0xa0, 0x45, 0xd3, 0x4a, 0x68, 0x48, 0xd5, 0x42, 0xbf, 0x4a, + 0x33, 0x4c, 0xb4, 0x46, 0xb8, 0x45, 0x38, 0x42, 0x82, 0x3e, 0x64, 0x3b, + 0xee, 0x38, 0xfa, 0x38, 0x27, 0x37, 0x9d, 0x2f, 0x69, 0x26, 0x6e, 0x22, + 0x01, 0x25, 0xd4, 0x26, 0xb9, 0x23, 0xe5, 0x1f, 0x83, 0x1b, 0xce, 0x13, + 0xdd, 0x0a, 0x8d, 0x05, 0x20, 0x01, 0x3e, 0xfc, 0xc1, 0xf4, 0x5f, 0xea, + 0x0d, 0xe8, 0x7f, 0xe8, 0xbf, 0xe3, 0x80, 0xdf, 0xc3, 0xdd, 0x46, 0xdb, + 0x27, 0xd7, 0xf6, 0xce, 0x95, 0xc5, 0x38, 0xc3, 0xbd, 0xc2, 0x29, 0xc4, + 0x07, 0xc8, 0x5d, 0xca, 0xe5, 0xcb, 0xf6, 0xca, 0x79, 0xcb, 0xdd, 0xce, + 0x21, 0xd1, 0x8e, 0xd6, 0xae, 0xe6, 0xa2, 0xf1, 0xbf, 0xf3, 0x0c, 0xfb, + 0xec, 0x00, 0xbe, 0x03, 0x42, 0x0a, 0xad, 0x16, 0x38, 0x1e, 0x4b, 0x1f, + 0xdd, 0x1e, 0x48, 0x19, 0x25, 0x1b, 0x79, 0x25, 0x23, 0x2f, 0x3f, 0x32, + 0x16, 0x30, 0x9d, 0x34, 0x87, 0x38, 0x12, 0x3f, 0x0e, 0x4c, 0x06, 0x4d, + 0xcb, 0x4c, 0xe2, 0x49, 0xc1, 0x3e, 0xd9, 0x43, 0xe9, 0x4d, 0xfe, 0x4e, + 0x15, 0x4c, 0x5d, 0x49, 0x61, 0x41, 0x7b, 0x38, 0xf6, 0x3a, 0x3a, 0x39, + 0x4f, 0x37, 0x4d, 0x33, 0x1b, 0x2a, 0x15, 0x2b, 0x30, 0x27, 0xb9, 0x1f, + 0x79, 0x1d, 0x4b, 0x14, 0x5d, 0x0b, 0xf7, 0x07, 0xa2, 0x05, 0x97, 0x05, + 0x81, 0x04, 0x70, 0x02, 0x07, 0x01, 0x5b, 0x00, 0x82, 0x01, 0xf6, 0x0c, + 0xb3, 0x19, 0xd1, 0x17, 0x8f, 0x12, 0x1f, 0x08, 0x59, 0xfb, 0x53, 0xf1, + 0x88, 0xe2, 0xd5, 0xd9, 0x37, 0xd3, 0x6b, 0xcb, 0x5d, 0xd2, 0x6d, 0xd8, + 0x81, 0xcc, 0x0c, 0xc5, 0x9c, 0xc9, 0x20, 0xd2, 0x06, 0xd9, 0x50, 0xe3, + 0x7f, 0xf1, 0x29, 0xed, 0x49, 0xe3, 0xf1, 0xe6, 0xa0, 0xed, 0xbf, 0xf3, + 0x03, 0x01, 0x26, 0x12, 0x0e, 0x18, 0x25, 0x1a, 0x92, 0x21, 0xb4, 0x2a, + 0xc9, 0x35, 0x55, 0x42, 0xea, 0x4e, 0x0b, 0x51, 0x2d, 0x4c, 0x7a, 0x4e, + 0xe6, 0x4b, 0x43, 0x45, 0xfc, 0x47, 0x08, 0x48, 0x2e, 0x40, 0x0e, 0x3a, + 0x45, 0x36, 0x3b, 0x2f, 0xf8, 0x2a, 0xe0, 0x2b, 0xe2, 0x2a, 0x01, 0x2f, + 0x0d, 0x38, 0xa8, 0x40, 0x6a, 0x45, 0x1f, 0x45, 0x9f, 0x4b, 0xbc, 0x4e, + 0xa5, 0x4b, 0x7b, 0x49, 0xa0, 0x3d, 0xcb, 0x33, 0x3c, 0x2f, 0xb5, 0x25, + 0xbc, 0x1c, 0xd3, 0x14, 0x3a, 0x08, 0xe6, 0xfb, 0xf8, 0xf6, 0xbf, 0xf4, + 0x00, 0xf6, 0x96, 0xf4, 0x26, 0xea, 0x7b, 0xe2, 0x3e, 0xe0, 0x44, 0xdf, + 0x9e, 0xe3, 0x99, 0xe8, 0xf7, 0xe5, 0xb1, 0xe5, 0x93, 0xe8, 0x38, 0xe9, + 0xa8, 0xee, 0xbd, 0xf2, 0x13, 0xee, 0x58, 0xe8, 0x3a, 0xe1, 0x42, 0xe0, + 0x1f, 0xee, 0x42, 0xf4, 0xe5, 0xee, 0x7f, 0xea, 0x27, 0xe9, 0xe2, 0xeb, + 0xcb, 0xee, 0x39, 0xf8, 0x11, 0x03, 0x36, 0x00, 0xa3, 0xfa, 0xbc, 0xff, + 0xb1, 0x04, 0x1d, 0x08, 0x4f, 0x11, 0xe2, 0x14, 0xfa, 0x12, 0xf5, 0x12, + 0x39, 0x1a, 0x7d, 0x26, 0xb9, 0x2d, 0x16, 0x32, 0xa9, 0x33, 0x3e, 0x2d, + 0x80, 0x26, 0xd2, 0x2b, 0x8b, 0x2f, 0xa3, 0x2b, 0x83, 0x2d, 0x00, 0x2c, + 0xf0, 0x26, 0xed, 0x25, 0xb9, 0x23, 0x52, 0x21, 0xc7, 0x1a, 0xbd, 0x13, + 0x54, 0x17, 0xd2, 0x17, 0xe5, 0x13, 0x45, 0x18, 0xe7, 0x17, 0xfa, 0x13, + 0xa6, 0x17, 0x75, 0x18, 0x2f, 0x1a, 0xbc, 0x1f, 0xbe, 0x1f, 0x9c, 0x24, + 0x43, 0x29, 0xd0, 0x23, 0xb5, 0x25, 0xc3, 0x2f, 0x47, 0x35, 0x37, 0x33, + 0x41, 0x27, 0x7a, 0x19, 0x7d, 0x0b, 0xbd, 0xf7, 0x10, 0xed, 0x1f, 0xec, + 0x3c, 0xe6, 0x61, 0xe4, 0x13, 0xe6, 0xd6, 0xd8, 0x13, 0xce, 0xee, 0xd8, + 0xa2, 0xe1, 0xfe, 0xe0, 0xdf, 0xe9, 0x67, 0xf8, 0x05, 0xfa, 0x1c, 0xf4, + 0xdf, 0xf5, 0xf9, 0xfa, 0x9f, 0x01, 0x94, 0x09, 0xa6, 0x10, 0x0a, 0x1b, + 0x9e, 0x22, 0xe9, 0x25, 0x07, 0x2a, 0x30, 0x27, 0xf0, 0x2a, 0xb2, 0x37, + 0xab, 0x38, 0xc5, 0x3b, 0x1e, 0x3d, 0x76, 0x32, 0x39, 0x2c, 0x9e, 0x2b, + 0x4a, 0x2a, 0xdb, 0x28, 0xce, 0x28, 0xaf, 0x23, 0xbc, 0x24, 0x4f, 0x27, + 0x51, 0x26, 0xea, 0x35, 0xb0, 0x3c, 0xaa, 0x3e, 0xd8, 0x48, 0x3d, 0x4a, + 0x3f, 0x54, 0x82, 0x5b, 0x27, 0x5a, 0x13, 0x5f, 0x23, 0x62, 0x09, 0x62, + 0x24, 0x5f, 0xec, 0x5d, 0xe6, 0x58, 0x7c, 0x55, 0xcf, 0x51, 0xa5, 0x3d, + 0x63, 0x2e, 0x0a, 0x28, 0xa0, 0x21, 0x6e, 0x1b, 0x88, 0x11, 0x83, 0x0b, + 0xe6, 0x04, 0x3f, 0xfe, 0xdd, 0xfe, 0x10, 0xff, 0x5d, 0x00, 0x72, 0x00, + 0xe2, 0xfa, 0x2f, 0xf7, 0x05, 0xf4, 0x1f, 0xf7, 0x52, 0xfe, 0x2f, 0xff, + 0xec, 0xfc, 0xe6, 0xfa, 0x38, 0xff, 0x9c, 0x03, 0x9c, 0x0a, 0x5c, 0x17, + 0x6f, 0x1f, 0x2e, 0x23, 0x33, 0x22, 0x0f, 0x22, 0x53, 0x20, 0xb7, 0x1d, + 0xd4, 0x18, 0x38, 0x07, 0x9f, 0xfa, 0x1f, 0xf9, 0xe7, 0xfa, 0xf7, 0xfd, + 0xa3, 0xfc, 0x7e, 0xfb, 0x93, 0xf9, 0xe1, 0xf7, 0xbb, 0x02, 0x14, 0x11, + 0xdc, 0x14, 0x3e, 0x1a, 0xf0, 0x22, 0x7d, 0x22, 0xf2, 0x1f, 0xd4, 0x26, + 0xd2, 0x2e, 0xaf, 0x2a, 0x95, 0x26, 0x9d, 0x22, 0xc0, 0x1d, 0xdf, 0x1e, + 0x64, 0x19, 0xf7, 0x18, 0xa9, 0x18, 0xc2, 0x12, 0xd0, 0x10, 0x54, 0x0d, + 0x38, 0x10, 0x07, 0x12, 0xdc, 0x0f, 0x31, 0x0d, 0xc6, 0x08, 0x50, 0x04, + 0xb2, 0x01, 0x4c, 0x03, 0x25, 0x01, 0xff, 0xfe, 0x85, 0x00, 0xd7, 0x04, + 0x3d, 0x0a, 0x17, 0x10, 0xac, 0x17, 0x64, 0x21, 0xe2, 0x23, 0x96, 0x1d, + 0x83, 0x1c, 0xad, 0x12, 0x9f, 0x04, 0x67, 0xfa, 0xf0, 0xec, 0x03, 0xe0, + 0x6d, 0xd0, 0x7d, 0xc8, 0x7a, 0xc4, 0xd1, 0xbb, 0x25, 0xb7, 0x35, 0xbe, + 0xa9, 0xc4, 0x84, 0xc3, 0x65, 0xd4, 0x41, 0xe1, 0x64, 0xd7, 0xa8, 0xd6, + 0x52, 0xde, 0x94, 0xe1, 0xf0, 0xe4, 0x60, 0xf1, 0xc9, 0xfd, 0x56, 0x00, + 0xd3, 0x02, 0x4b, 0x04, 0xb7, 0x05, 0x2b, 0x09, 0xe9, 0x0d, 0x26, 0x0d, + 0x1d, 0x06, 0x66, 0x05, 0xb1, 0x00, 0xf3, 0xf5, 0xc2, 0xed, 0xe5, 0xe9, + 0x08, 0xeb, 0x55, 0xe8, 0x85, 0xe7, 0xa4, 0xe8, 0x32, 0xe8, 0x8f, 0xee, + 0x78, 0xf3, 0x1c, 0xf2, 0x60, 0xf6, 0x7a, 0x01, 0x6d, 0x09, 0xda, 0x11, + 0x63, 0x1b, 0x79, 0x23, 0xa7, 0x2d, 0x15, 0x35, 0xfa, 0x3e, 0x08, 0x47, + 0x7d, 0x47, 0xbe, 0x45, 0x89, 0x3e, 0x27, 0x37, 0x3e, 0x2e, 0x3a, 0x26, + 0xb5, 0x22, 0xe9, 0x1c, 0x8f, 0x12, 0xf7, 0x01, 0x6c, 0xf6, 0xa6, 0xf4, + 0x05, 0xf5, 0xc8, 0xf5, 0x54, 0xf5, 0x11, 0xec, 0x4e, 0xe1, 0xaf, 0xe2, + 0x26, 0xe6, 0xcb, 0xe6, 0xd9, 0xe9, 0x06, 0xed, 0x5c, 0xea, 0x99, 0xea, + 0x96, 0xf2, 0x68, 0xf9, 0x65, 0xfe, 0x40, 0xfb, 0x1a, 0xf9, 0x8d, 0x02, + 0xb1, 0x08, 0xb7, 0x0a, 0xd4, 0x0a, 0xec, 0x08, 0xc4, 0x07, 0x74, 0x07, + 0x9a, 0x0c, 0xef, 0x10, 0xc2, 0x14, 0x46, 0x16, 0xf6, 0x12, 0x4f, 0x15, + 0xb6, 0x16, 0x5e, 0x1e, 0x00, 0x2a, 0x50, 0x2b, 0x42, 0x29, 0xcc, 0x25, + 0xec, 0x26, 0xf7, 0x24, 0x36, 0x22, 0x07, 0x27, 0x6b, 0x23, 0x90, 0x21, + 0x6e, 0x24, 0xb0, 0x1e, 0xcc, 0x1e, 0xe9, 0x22, 0x31, 0x20, 0x78, 0x23, + 0xb1, 0x2b, 0x72, 0x2c, 0x32, 0x27, 0x5d, 0x28, 0x1f, 0x26, 0x84, 0x1d, + 0x00, 0x23, 0xdc, 0x21, 0x61, 0x17, 0xb4, 0x18, 0xbd, 0x16, 0xbc, 0x12, + 0x2f, 0x15, 0x4f, 0x15, 0x80, 0x16, 0xf0, 0x18, 0xb1, 0x18, 0xb1, 0x1c, + 0x3f, 0x22, 0xf5, 0x25, 0xfa, 0x2c, 0x53, 0x34, 0xf7, 0x35, 0x4a, 0x31, + 0xdf, 0x27, 0xcc, 0x1c, 0x3e, 0x15, 0x57, 0x0b, 0x5b, 0xfd, 0xe4, 0xf2, + 0xe8, 0xeb, 0xd0, 0xeb, 0x0c, 0xe8, 0x64, 0xda, 0xb4, 0xd6, 0x76, 0xde, + 0x82, 0xea, 0xd6, 0xf7, 0x5d, 0x05, 0xaf, 0x12, 0x40, 0x0f, 0x22, 0x00, + 0x61, 0x02, 0x62, 0x0e, 0x5b, 0x0d, 0x10, 0x10, 0xca, 0x1d, 0x80, 0x19, + 0x7b, 0x11, 0xb8, 0x1c, 0x02, 0x22, 0x03, 0x27, 0x2a, 0x32, 0x10, 0x2e, + 0xf4, 0x26, 0x50, 0x26, 0x7c, 0x24, 0x10, 0x20, 0x23, 0x1a, 0x18, 0x12, + 0x96, 0x0a, 0xc0, 0x03, 0x1c, 0xfb, 0xaa, 0xfc, 0xee, 0xfb, 0xdc, 0xee, + 0x69, 0xe9, 0x26, 0xe8, 0xda, 0xe7, 0x23, 0xf1, 0x23, 0xf8, 0x2b, 0xf8, + 0x37, 0x02, 0xe8, 0x0d, 0x8b, 0x11, 0x47, 0x18, 0x4e, 0x1d, 0x28, 0x20, + 0x53, 0x22, 0x87, 0x1b, 0xde, 0x14, 0x70, 0x16, 0x70, 0x12, 0xdf, 0x07, + 0xbd, 0x00, 0x86, 0x00, 0x4e, 0x08, 0xde, 0x08, 0x74, 0xfe, 0xf8, 0xf4, + 0x43, 0xec, 0xb2, 0xe4, 0x48, 0xde, 0xd1, 0xdb, 0x4e, 0xda, 0xcd, 0xd2, + 0x9f, 0xcd, 0x1f, 0xc6, 0x9b, 0xbf, 0xb2, 0xc7, 0x26, 0xd0, 0x01, 0xd3, + 0x5c, 0xd5, 0xb0, 0xd6, 0xef, 0xd7, 0x20, 0xdb, 0xcc, 0xe4, 0x71, 0xec, + 0x1b, 0xf1, 0x0b, 0xf7, 0x4f, 0xf9, 0x74, 0xfc, 0x4b, 0xfd, 0x2c, 0xfb, + 0x77, 0xfe, 0xc7, 0x01, 0x2d, 0xfb, 0x9d, 0xf4, 0x59, 0xf6, 0xc0, 0xf3, + 0x70, 0xf2, 0x58, 0xf4, 0xaa, 0xf0, 0x89, 0xf2, 0x7a, 0xfd, 0x51, 0x07, + 0x8a, 0x0a, 0x9c, 0x09, 0x95, 0x0a, 0xec, 0x0d, 0x3f, 0x10, 0xf9, 0x1a, + 0x13, 0x24, 0x00, 0x18, 0xac, 0x07, 0x47, 0x01, 0xef, 0xff, 0x26, 0xfd, + 0xc4, 0xfb, 0xc0, 0xf9, 0x1f, 0xf1, 0xb4, 0xea, 0xf3, 0xea, 0x5e, 0xe9, + 0xd1, 0xe0, 0xb7, 0xda, 0xbd, 0xd7, 0x45, 0xdb, 0xa7, 0xe4, 0x41, 0xe8, + 0xc5, 0xe7, 0xd8, 0xdf, 0x0d, 0xd9, 0x1e, 0xdf, 0x72, 0xe6, 0x3f, 0xe8, + 0xe8, 0xe9, 0x3c, 0xea, 0x3b, 0xe8, 0x42, 0xee, 0x95, 0xfd, 0x1b, 0x02, + 0xa5, 0xfa, 0xc8, 0xf9, 0x3a, 0xf3, 0x4b, 0xe4, 0xe6, 0xd7, 0x46, 0xd2, + 0x75, 0xd0, 0x4b, 0xc0, 0xd9, 0xb5, 0xac, 0xb4, 0x18, 0xac, 0x97, 0xaf, + 0xb4, 0xbc, 0x5a, 0xc1, 0x69, 0xc1, 0xc2, 0xcc, 0x5c, 0xdf, 0x12, 0xe8, + 0xb8, 0xe7, 0xd2, 0xed, 0x8f, 0xf7, 0xc0, 0xf2, 0x78, 0xf4, 0x5b, 0x0a, + 0xa2, 0x14, 0x3f, 0x14, 0x27, 0x1b, 0x70, 0x1a, 0x4e, 0x18, 0x4b, 0x1d, + 0x23, 0x1b, 0x84, 0x14, 0xc9, 0x0c, 0x53, 0x08, 0xfd, 0x02, 0x4d, 0xf6, + 0x79, 0xee, 0x98, 0xea, 0xa2, 0xe5, 0x09, 0xe2, 0xe9, 0xe0, 0xc1, 0xe1, + 0x51, 0xe3, 0x64, 0xe5, 0xf2, 0xe3, 0x1c, 0xe1, 0xf1, 0xe1, 0x09, 0xe7, + 0x69, 0xf1, 0x0a, 0xf9, 0xd2, 0xfd, 0x15, 0x02, 0x08, 0x03, 0x26, 0x08, + 0xb9, 0x0d, 0xaf, 0x10, 0x27, 0x0e, 0xb5, 0x04, 0xfa, 0xff, 0x73, 0xfa, + 0x69, 0xf2, 0x92, 0xeb, 0x16, 0xe6, 0x7b, 0xe1, 0xc5, 0xdc, 0xaf, 0xdb, + 0xc8, 0xdb, 0xf4, 0xd9, 0x3b, 0xd2, 0xd0, 0xc8, 0x64, 0xc2, 0xcb, 0xc1, + 0xfd, 0xc8, 0x69, 0xce, 0x4c, 0xcc, 0xef, 0xc3, 0xea, 0xc0, 0x4d, 0xc4, + 0x9b, 0xc8, 0xa4, 0xd1, 0xe1, 0xd9, 0x89, 0xda, 0xf0, 0xd3, 0xbf, 0xd1, + 0xed, 0xd6, 0x93, 0xdd, 0x5e, 0xe4, 0x7d, 0xea, 0x42, 0xed, 0x88, 0xe7, + 0xb3, 0xe5, 0x4c, 0xec, 0x34, 0xeb, 0xec, 0xe6, 0x4a, 0xe8, 0x13, 0xe8, + 0x5c, 0xe6, 0x78, 0xe4, 0xc2, 0xe6, 0xdb, 0xea, 0xef, 0xe8, 0xa5, 0xec, + 0x6c, 0xf2, 0x89, 0xf9, 0x54, 0x02, 0x3d, 0x03, 0x59, 0x05, 0x2f, 0x06, + 0x08, 0x07, 0x01, 0x0e, 0x53, 0x14, 0xa7, 0x14, 0xc4, 0x0e, 0x2f, 0x10, + 0x22, 0x17, 0xd1, 0x1b, 0x14, 0x20, 0x0f, 0x1e, 0xee, 0x1b, 0xc8, 0x15, + 0x92, 0x06, 0xae, 0xfd, 0xed, 0xef, 0x1a, 0xe2, 0xbe, 0xe2, 0x01, 0xdc, + 0xa6, 0xd3, 0x52, 0xd0, 0x40, 0xce, 0x3e, 0xcf, 0x59, 0xc8, 0x0a, 0xcd, + 0x55, 0xd7, 0xf5, 0xd5, 0x59, 0xd7, 0x07, 0xdd, 0xbe, 0xe6, 0x28, 0xe6, + 0xf3, 0xeb, 0xc4, 0xfa, 0xe3, 0xfc, 0x0c, 0x05, 0x61, 0xff, 0xd9, 0xf0, + 0x9c, 0xe6, 0x3e, 0xd2, 0xd8, 0xc7, 0x87, 0xba, 0xb4, 0xae, 0x03, 0xb3, + 0x54, 0xae, 0x14, 0xa3, 0x0d, 0xa0, 0x33, 0xa8, 0x6a, 0xad, 0x0d, 0xb2, + 0x02, 0xc2, 0xb9, 0xcb, 0x5c, 0xd2, 0xad, 0xd5, 0x81, 0xd1, 0x9f, 0xd7, + 0xe1, 0xe0, 0x74, 0xee, 0xeb, 0xfd, 0x71, 0x00, 0xbd, 0x0a, 0x38, 0x14, + 0xb7, 0x15, 0xda, 0x22, 0x81, 0x29, 0xfe, 0x2a, 0x87, 0x2b, 0x65, 0x27, + 0xf9, 0x21, 0x89, 0x17, 0x10, 0x10, 0xd5, 0x01, 0xef, 0xf6, 0x97, 0xee, + 0xbe, 0xe6, 0x06, 0xe8, 0x92, 0xdd, 0xc5, 0xdc, 0xf5, 0xdd, 0x8e, 0xde, + 0xec, 0xe9, 0x81, 0xee, 0xbe, 0xf7, 0x48, 0xfd, 0x19, 0x05, 0xe7, 0x10, + 0xfe, 0x1d, 0x4e, 0x28, 0xa7, 0x27, 0x22, 0x2e, 0xf6, 0x2b, 0x5e, 0x27, + 0x05, 0x26, 0x91, 0x1d, 0xa0, 0x14, 0x7f, 0x07, 0xd3, 0xfd, 0x27, 0xf4, + 0x17, 0xec, 0x34, 0xe7, 0xa2, 0xe3, 0x6b, 0xe1, 0x6f, 0xda, 0x00, 0xd8, + 0xfc, 0xd1, 0x45, 0xc7, 0x56, 0xc5, 0xa0, 0xc9, 0xd8, 0xce, 0xd0, 0xce, + 0x8e, 0xce, 0x15, 0xcf, 0xf8, 0xcd, 0x6f, 0xd0, 0x1c, 0xda, 0xe2, 0xe7, + 0x5f, 0xec, 0xf8, 0xeb, 0xd9, 0xeb, 0x74, 0xea, 0x5e, 0xef, 0x5e, 0xf6, + 0xbe, 0xfe, 0xeb, 0xff, 0xf4, 0xf7, 0xf1, 0xf3, 0x05, 0xf2, 0xcc, 0xf5, + 0xf2, 0xf9, 0xc8, 0xfb, 0xba, 0xfb, 0x3c, 0xfb, 0x38, 0x04, 0x72, 0x0a, + 0xb2, 0x10, 0x68, 0x19, 0xaa, 0x1c, 0xe4, 0x22, 0xe4, 0x2a, 0xd4, 0x34, + 0xd1, 0x3f, 0x40, 0x43, 0x05, 0x42, 0xd8, 0x41, 0x8a, 0x47, 0x59, 0x53, + 0xb4, 0x57, 0x03, 0x54, 0x54, 0x4d, 0xa4, 0x48, 0x76, 0x4b, 0xed, 0x4c, + 0x08, 0x51, 0x16, 0x50, 0x75, 0x43, 0x37, 0x38, 0xdc, 0x2e, 0x70, 0x2e, + 0x2a, 0x34, 0xc7, 0x32, 0xd6, 0x2e, 0x6e, 0x2b, 0xc6, 0x20, 0xc5, 0x17, + 0x31, 0x19, 0xdf, 0x0f, 0x6d, 0xfe, 0x54, 0xfb, 0xf7, 0xf6, 0x3f, 0xee, + 0xb3, 0xee, 0x0d, 0xef, 0xe1, 0xf1, 0x81, 0xf1, 0x0a, 0xf4, 0x81, 0x00, + 0x6e, 0x00, 0xb6, 0x05, 0xb9, 0x0e, 0x5b, 0xfe, 0xfe, 0xe7, 0xa9, 0xdf, + 0xab, 0xd8, 0xb3, 0xca, 0x82, 0xc7, 0x3c, 0xcd, 0xfb, 0xca, 0xfe, 0xc3, + 0xb2, 0xbc, 0xe9, 0xc2, 0x2a, 0xcc, 0xa4, 0xcc, 0xc8, 0xda, 0x2d, 0xe9, + 0x28, 0xea, 0x68, 0xe5, 0xa1, 0xe8, 0x8b, 0xf4, 0x22, 0xf6, 0xdb, 0xfe, + 0x79, 0x0a, 0xeb, 0x0e, 0x12, 0x16, 0x39, 0x20, 0x4a, 0x2d, 0x82, 0x30, + 0xed, 0x37, 0x73, 0x42, 0xc3, 0x40, 0x08, 0x41, 0x65, 0x46, 0x38, 0x45, + 0xf6, 0x3d, 0x97, 0x3e, 0xac, 0x3b, 0xa1, 0x34, 0xc9, 0x2c, 0x2a, 0x22, + 0x72, 0x22, 0xeb, 0x1e, 0x2c, 0x1b, 0x3f, 0x19, 0xd8, 0x12, 0xf1, 0x18, + 0x54, 0x1f, 0xfc, 0x1e, 0x27, 0x22, 0xa4, 0x28, 0x32, 0x2d, 0xcf, 0x33, + 0x22, 0x39, 0x9c, 0x38, 0xa5, 0x3b, 0xb8, 0x35, 0x06, 0x2c, 0x84, 0x28, + 0x0f, 0x22, 0xe0, 0x18, 0x87, 0x0c, 0x63, 0x05, 0x82, 0x00, 0x68, 0xfb, + 0x99, 0xf4, 0xb6, 0xe7, 0x36, 0xe1, 0x71, 0xdd, 0x72, 0xd6, 0xde, 0xd0, + 0x60, 0xcb, 0xd6, 0xc8, 0x89, 0xca, 0x8d, 0xc9, 0xf3, 0xc6, 0xb4, 0xcb, + 0x4e, 0xcd, 0x09, 0xca, 0x8c, 0xcf, 0x00, 0xd6, 0x99, 0xda, 0xdb, 0xdf, + 0x15, 0xe1, 0x03, 0xe1, 0x04, 0xe5, 0xd9, 0xec, 0x54, 0xf6, 0xa8, 0xfc, + 0x46, 0xff, 0x06, 0x03, 0x1e, 0x02, 0xb2, 0x07, 0x0d, 0x11, 0xa1, 0x11, + 0xde, 0x13, 0x11, 0x14, 0xb6, 0x15, 0x1e, 0x18, 0xcf, 0x1d, 0xb2, 0x25, + 0x42, 0x29, 0x2f, 0x33, 0x18, 0x3a, 0xb7, 0x40, 0xcb, 0x46, 0x0f, 0x4b, + 0xe7, 0x4f, 0xb6, 0x4a, 0x6f, 0x4e, 0x49, 0x55, 0xbf, 0x4f, 0x7b, 0x51, + 0x4f, 0x54, 0xa4, 0x4e, 0xae, 0x45, 0x2a, 0x3c, 0x32, 0x3b, 0x61, 0x3a, + 0x7c, 0x32, 0x2c, 0x27, 0x7b, 0x1a, 0x6c, 0x15, 0x40, 0x13, 0x3e, 0x0e, + 0x65, 0x0b, 0xe9, 0x0b, 0x38, 0x0b, 0x88, 0x0a, 0xa3, 0x0b, 0x76, 0x0a, + 0x80, 0x07, 0xa3, 0x05, 0x52, 0x06, 0x8d, 0x04, 0xfa, 0x00, 0xac, 0xfe, + 0xc8, 0xf8, 0x13, 0xf0, 0x1a, 0xea, 0x6e, 0xe3, 0x59, 0xe1, 0x89, 0xed, + 0x48, 0xf6, 0xa1, 0xf1, 0xc7, 0xe6, 0x86, 0xd6, 0xca, 0xc9, 0xa4, 0xc2, + 0x82, 0xbc, 0xec, 0xc0, 0x73, 0xc7, 0x01, 0xc3, 0xeb, 0xc3, 0x56, 0xc0, + 0xdb, 0xbc, 0xd9, 0xcd, 0xbf, 0xd4, 0xfa, 0xdb, 0xe3, 0xf5, 0xc7, 0x07, + 0x94, 0x0c, 0xdc, 0x0d, 0x03, 0x11, 0x8d, 0x0d, 0x3e, 0x13, 0xb0, 0x22, + 0x2a, 0x28, 0x48, 0x32, 0x42, 0x39, 0x3f, 0x39, 0x3d, 0x37, 0x25, 0x37, + 0xba, 0x3f, 0xef, 0x3e, 0x73, 0x3c, 0x20, 0x3d, 0x2d, 0x38, 0x1f, 0x36, + 0x05, 0x32, 0x81, 0x2f, 0xa1, 0x30, 0xd3, 0x2c, 0x2b, 0x2a, 0xce, 0x28, + 0xbf, 0x28, 0x2a, 0x29, 0xfc, 0x2a, 0xb1, 0x2a, 0x2e, 0x25, 0x8e, 0x28, + 0xaa, 0x2c, 0xfb, 0x30, 0x0f, 0x34, 0x2a, 0x31, 0xb7, 0x36, 0x9f, 0x39, + 0x12, 0x36, 0x55, 0x36, 0xfc, 0x34, 0x22, 0x28, 0xa5, 0x21, 0x19, 0x21, + 0x66, 0x16, 0x9b, 0x11, 0xb5, 0x0a, 0x9e, 0x00, 0x71, 0xfc, 0xa3, 0xf6, + 0xda, 0xee, 0x2c, 0xe9, 0x6f, 0xe6, 0xe6, 0xe1, 0x07, 0xe0, 0x92, 0xdb, + 0x5d, 0xda, 0x90, 0xde, 0x83, 0xd7, 0x3f, 0xd1, 0xa1, 0xd7, 0x2e, 0xdf, + 0xb2, 0xdf, 0x9a, 0xde, 0xe3, 0xdf, 0x08, 0xe3, 0x3d, 0xe8, 0xb5, 0xec, + 0x04, 0xed, 0xb4, 0xf0, 0xa8, 0xfa, 0xf5, 0xff, 0xfc, 0x03, 0x53, 0x08, + 0x2d, 0x0b, 0x19, 0x10, 0x37, 0x12, 0x51, 0x14, 0xdc, 0x18, 0x98, 0x19, + 0xd5, 0x1b, 0x7a, 0x1c, 0x3e, 0x1a, 0xf3, 0x1d, 0x6b, 0x26, 0xea, 0x31, + 0x4d, 0x35, 0x46, 0x34, 0x48, 0x37, 0x27, 0x3a, 0x9c, 0x3f, 0x30, 0x43, + 0xde, 0x44, 0xa6, 0x42, 0x5b, 0x3b, 0xff, 0x34, 0xbb, 0x33, 0x7b, 0x35, + 0xb9, 0x37, 0x9f, 0x3a, 0xed, 0x2e, 0xab, 0x21, 0xc1, 0x21, 0x55, 0x1f, + 0x0f, 0x1d, 0x2a, 0x17, 0x1e, 0x10, 0x97, 0x10, 0xa5, 0x0a, 0x1c, 0x04, + 0x28, 0x03, 0x30, 0xfc, 0x64, 0xf6, 0x23, 0xfa, 0x05, 0xf9, 0x05, 0xf3, + 0x3f, 0xf3, 0xe9, 0xf6, 0x0b, 0xf8, 0x6e, 0xed, 0xdd, 0xea, 0x3d, 0xf5, + 0xc2, 0xf5, 0x7b, 0xf6, 0x34, 0xf5, 0xfb, 0xf3, 0x1d, 0xf8, 0x12, 0xf3, + 0xa8, 0xeb, 0xd2, 0xe6, 0x37, 0xe3, 0xe7, 0xdf, 0xa2, 0xd6, 0x63, 0xcb, + 0x57, 0xc1, 0x6f, 0xb2, 0x2a, 0xa9, 0xe5, 0xab, 0x23, 0xad, 0x66, 0xb6, + 0x82, 0xbf, 0x89, 0xb6, 0xc6, 0xb8, 0xb8, 0xc7, 0x37, 0xcf, 0x66, 0xdb, + 0x58, 0xec, 0x4c, 0xf5, 0x52, 0xee, 0x07, 0xe4, 0x99, 0xec, 0x72, 0xf2, + 0xdd, 0xed, 0xb7, 0xf7, 0x72, 0xfd, 0xb6, 0xf6, 0x76, 0xfa, 0xc0, 0xfc, + 0xcd, 0xfc, 0xa9, 0x04, 0x74, 0x08, 0x9b, 0x09, 0x39, 0x05, 0x7a, 0x02, + 0x71, 0x07, 0xf0, 0xff, 0x0d, 0xf9, 0xba, 0xfd, 0x44, 0xfb, 0x70, 0xf8, + 0xa4, 0xfc, 0x09, 0xfe, 0x98, 0x04, 0x6b, 0x0d, 0x6e, 0x0d, 0x19, 0x0e, + 0x40, 0x13, 0x4a, 0x1e, 0xcc, 0x27, 0x65, 0x28, 0xfe, 0x27, 0x0f, 0x24, + 0xf4, 0x20, 0x0c, 0x24, 0xad, 0x26, 0xfe, 0x27, 0x23, 0x20, 0xca, 0x10, + 0x66, 0x04, 0x1e, 0xfc, 0xea, 0xf8, 0x51, 0xf3, 0xd1, 0xe6, 0xca, 0xde, + 0x87, 0xdd, 0x06, 0xdd, 0x79, 0xde, 0x96, 0xdc, 0x27, 0xda, 0xac, 0xd9, + 0x17, 0xd4, 0xab, 0xd3, 0xca, 0xda, 0x88, 0xdf, 0x76, 0xdd, 0xf8, 0xd2, + 0xc1, 0xcc, 0x16, 0xd4, 0x04, 0xdd, 0xe8, 0xe3, 0x19, 0xe8, 0x66, 0xe3, + 0xe6, 0xe1, 0x7f, 0xe6, 0x2c, 0xea, 0xec, 0xf2, 0x8f, 0x00, 0x19, 0x05, + 0x4e, 0x05, 0x18, 0x08, 0xb1, 0x0a, 0x5e, 0x15, 0xd0, 0x1c, 0xbd, 0x1d, + 0x47, 0x1f, 0x5f, 0x21, 0x96, 0x2b, 0x77, 0x35, 0x9b, 0x34, 0x74, 0x36, + 0xcc, 0x3c, 0xf3, 0x3f, 0xf5, 0x48, 0x1a, 0x4e, 0x89, 0x4c, 0x84, 0x4c, + 0x69, 0x4e, 0xd9, 0x4c, 0x16, 0x45, 0x48, 0x48, 0x9a, 0x4a, 0xe8, 0x48, + 0x9c, 0x4a, 0x53, 0x46, 0xc3, 0x41, 0x68, 0x42, 0x26, 0x47, 0x8c, 0x42, + 0x79, 0x39, 0x24, 0x37, 0xaa, 0x35, 0x32, 0x34, 0x3d, 0x2f, 0xdc, 0x2c, + 0x46, 0x2f, 0x98, 0x2c, 0x1b, 0x2b, 0x1e, 0x27, 0xd2, 0x1b, 0xbf, 0x16, + 0x90, 0x14, 0xbb, 0x13, 0xb4, 0x15, 0xac, 0x15, 0x2f, 0x16, 0x2e, 0x14, + 0xdb, 0x0f, 0xae, 0x11, 0x0f, 0x11, 0xbf, 0x0e, 0x87, 0x13, 0xb4, 0x14, + 0x58, 0x1a, 0x06, 0x22, 0x2c, 0x23, 0xca, 0x24, 0xef, 0x24, 0xb3, 0x23, + 0x83, 0x16, 0xcd, 0x00, 0xd4, 0xf0, 0x45, 0xe6, 0x2f, 0xdb, 0x0f, 0xd5, + 0xa8, 0xdf, 0xa8, 0xe2, 0xd5, 0xd3, 0xe5, 0xca, 0x97, 0xc8, 0xa5, 0xd4, + 0x0e, 0xf0, 0x13, 0xfd, 0xc1, 0x04, 0xa8, 0x11, 0x05, 0x08, 0x07, 0xfa, + 0x6b, 0x06, 0x31, 0x0d, 0x0b, 0x06, 0x4e, 0x0c, 0x4e, 0x10, 0x14, 0x10, + 0x55, 0x19, 0x29, 0x17, 0x09, 0x0e, 0x90, 0x13, 0x64, 0x1a, 0x53, 0x1c, + 0x56, 0x25, 0x95, 0x2c, 0x15, 0x29, 0xb7, 0x22, 0x5d, 0x1a, 0xfd, 0x11, + 0xdd, 0x11, 0x32, 0x12, 0x00, 0x11, 0xd0, 0x13, 0x1a, 0x16, 0x09, 0x15, + 0xde, 0x13, 0x14, 0x17, 0x80, 0x1d, 0xee, 0x28, 0x58, 0x2b, 0x95, 0x26, + 0xa7, 0x2c, 0x81, 0x32, 0xab, 0x38, 0x9d, 0x3b, 0x5c, 0x32, 0x6e, 0x25, + 0x23, 0x1b, 0xbb, 0x0f, 0x80, 0x02, 0x03, 0xfc, 0xee, 0xef, 0x6c, 0xde, + 0xe9, 0xd1, 0x8a, 0xc6, 0x89, 0xc4, 0xdf, 0xc9, 0xdd, 0xca, 0xa3, 0xcb, + 0x1b, 0xd3, 0xe3, 0xd1, 0x7d, 0xc5, 0x05, 0xc2, 0x33, 0xc6, 0x25, 0xd1, + 0x0c, 0xd8, 0x9d, 0xd0, 0x21, 0xc7, 0x4c, 0xc6, 0xa8, 0xce, 0x38, 0xd6, + 0x78, 0xdc, 0xc2, 0xdd, 0x9b, 0xdc, 0x1f, 0xde, 0x83, 0xdb, 0x7a, 0xdd, + 0xc3, 0xe6, 0x64, 0xec, 0x4d, 0xeb, 0xfa, 0xed, 0xe2, 0xf3, 0xf4, 0xf3, + 0xbf, 0xf5, 0xbd, 0xf7, 0x25, 0xfa, 0x35, 0x02, 0xdd, 0x03, 0x9c, 0x00, + 0x30, 0x04, 0x36, 0x0c, 0x35, 0x16, 0x42, 0x1d, 0xdd, 0x1c, 0x01, 0x1e, + 0x70, 0x23, 0x6f, 0x29, 0x13, 0x30, 0xc4, 0x32, 0x7e, 0x31, 0x93, 0x29, + 0x9a, 0x20, 0x2b, 0x21, 0x0b, 0x22, 0xec, 0x21, 0x17, 0x1f, 0x7e, 0x19, + 0xf4, 0x16, 0x19, 0x13, 0x45, 0x0f, 0x4d, 0x0f, 0x7a, 0x0f, 0xed, 0x0a, + 0xbd, 0x06, 0x29, 0xff, 0x35, 0xf9, 0xe9, 0xf9, 0x44, 0xf4, 0x00, 0xf1, + 0xb1, 0xee, 0xaa, 0xee, 0x1e, 0xf0, 0x24, 0xe6, 0xc0, 0xe3, 0x45, 0xe8, + 0x4f, 0xe8, 0x3f, 0xee, 0x03, 0xf0, 0x66, 0xeb, 0xb4, 0xea, 0x80, 0xe9, + 0xa1, 0xec, 0x75, 0xf6, 0xdc, 0xfd, 0x8d, 0x00, 0xde, 0x01, 0xa8, 0x06, + 0x2f, 0x11, 0xa3, 0x19, 0x84, 0x22, 0x72, 0x2e, 0x97, 0x25, 0x29, 0x09, + 0x4d, 0xed, 0x38, 0xd8, 0xfd, 0xd2, 0x86, 0xd9, 0xe8, 0xd9, 0xfc, 0xd1, + 0x8f, 0xc8, 0x43, 0xbd, 0x18, 0xb6, 0x15, 0xc3, 0x28, 0xde, 0xe6, 0xea, + 0x90, 0xea, 0x42, 0xef, 0xfb, 0xf8, 0xaa, 0xf7, 0x45, 0xf2, 0x82, 0xfc, + 0xb2, 0xff, 0xa6, 0xfb, 0xf6, 0x01, 0x69, 0x0c, 0x30, 0x0f, 0xcd, 0x0a, + 0xf2, 0x0b, 0x92, 0x0a, 0xaa, 0x0c, 0xdb, 0x1b, 0x0b, 0x26, 0x2a, 0x1e, + 0x55, 0x11, 0xc9, 0x0d, 0xaf, 0x05, 0xcc, 0xfd, 0xd6, 0x02, 0x2d, 0xff, + 0xce, 0xf0, 0x1b, 0xea, 0x3d, 0xeb, 0x7e, 0xf2, 0xe7, 0xfb, 0xa8, 0x00, + 0xaf, 0xfe, 0x11, 0x02, 0x65, 0x07, 0x90, 0x01, 0x01, 0xfb, 0xff, 0xf8, + 0xa7, 0xff, 0xea, 0x03, 0xde, 0xfc, 0x73, 0xf4, 0x7f, 0xef, 0x83, 0xe7, + 0xce, 0xdc, 0xab, 0xd9, 0xa6, 0xd5, 0xe8, 0xd6, 0xc2, 0xd3, 0x6c, 0xc5, + 0x75, 0xc0, 0x19, 0xc0, 0x22, 0xc5, 0xfa, 0xca, 0xe3, 0xcb, 0xd3, 0xcb, + 0xd5, 0xc8, 0x55, 0xc8, 0x97, 0xcb, 0x46, 0xcf, 0x34, 0xd3, 0x7a, 0xd6, + 0x4b, 0xd5, 0xc6, 0xd3, 0xdf, 0xd7, 0x09, 0xe0, 0xf8, 0xe5, 0xaa, 0xe5, + 0xf3, 0xe4, 0x15, 0xe4, 0xae, 0xdf, 0xf7, 0xdb, 0x2b, 0xde, 0x80, 0xe3, + 0x69, 0xe6, 0x05, 0xec, 0x6c, 0xf0, 0x44, 0xf0, 0x76, 0xf3, 0x35, 0xf5, + 0x72, 0xf7, 0xd0, 0xf8, 0x6b, 0xf5, 0x32, 0xf8, 0x0e, 0xff, 0x4c, 0x04, + 0x8f, 0x05, 0xbb, 0x01, 0xc4, 0x01, 0x52, 0x07, 0xed, 0x0c, 0xd9, 0x0d, + 0xac, 0x0e, 0xe4, 0x14, 0x4a, 0x12, 0x7b, 0x08, 0x67, 0x06, 0xe9, 0x0a, + 0xcd, 0x0c, 0xc4, 0x07, 0x75, 0x01, 0x5c, 0xf7, 0x99, 0xf2, 0xf2, 0xf3, + 0x9e, 0xf0, 0xfb, 0xf1, 0xb4, 0xf5, 0xc7, 0xf7, 0x22, 0xf6, 0x7a, 0xf2, + 0x54, 0xf3, 0x97, 0xf1, 0x68, 0xe9, 0x7f, 0xe5, 0xe5, 0xe7, 0xdf, 0xe8, + 0x43, 0xef, 0xdc, 0xef, 0x0d, 0xeb, 0x30, 0xec, 0xac, 0xe7, 0xbd, 0xe8, + 0xc5, 0xec, 0x10, 0xec, 0x01, 0xf0, 0x6a, 0xf5, 0x5f, 0xf8, 0x0a, 0xf9, + 0x39, 0xff, 0x1e, 0x06, 0xd6, 0x0c, 0xe7, 0x13, 0x86, 0x1c, 0x91, 0x2f, + 0x7e, 0x38, 0x13, 0x38, 0x9d, 0x2e, 0xb3, 0x20, 0x7e, 0x20, 0x95, 0x16, + 0x6b, 0x07, 0xf4, 0xf5, 0xee, 0xdc, 0xd0, 0xcc, 0xbb, 0xc4, 0x7f, 0xc4, + 0x48, 0xd2, 0x20, 0xd9, 0xe9, 0xc1, 0x49, 0xb9, 0x74, 0xce, 0x65, 0xdd, + 0xf2, 0xe9, 0xf5, 0xfb, 0x97, 0x00, 0xc3, 0xf0, 0x8e, 0xec, 0xc4, 0xf3, + 0x15, 0xf6, 0x60, 0xf5, 0xba, 0xf5, 0xc5, 0xfb, 0xeb, 0xf6, 0x54, 0xf4, + 0xd3, 0x00, 0xe8, 0x06, 0x51, 0x00, 0xe1, 0x00, 0x1b, 0x0b, 0x81, 0x08, + 0x95, 0x08, 0x46, 0x0f, 0x45, 0x04, 0xf1, 0xf3, 0x7e, 0xf1, 0x1f, 0xf3, + 0x74, 0xee, 0x0c, 0xf0, 0x92, 0xf5, 0x05, 0xef, 0x5e, 0xea, 0x40, 0xf2, + 0x89, 0xf8, 0xb3, 0xfe, 0x35, 0x06, 0x5e, 0x03, 0xe2, 0x01, 0x63, 0x0a, + 0xdf, 0x10, 0xd9, 0x1b, 0x8a, 0x1f, 0x80, 0x13, 0xce, 0x11, 0xae, 0x0d, + 0x0f, 0x07, 0x96, 0x09, 0x2e, 0x00, 0xd5, 0xf5, 0x79, 0xf4, 0xdc, 0xf0, + 0x38, 0xf0, 0x7d, 0xf6, 0xfc, 0xf5, 0xea, 0xfa, 0xb4, 0x04, 0xb1, 0xfc, + 0x5f, 0xfd, 0xfb, 0x02, 0x28, 0xff, 0x4b, 0x02, 0xfe, 0x02, 0x4f, 0xfe, + 0x6a, 0xfd, 0x95, 0xff, 0x28, 0xfd, 0x32, 0xfc, 0x48, 0x00, 0x89, 0x01, + 0x05, 0x03, 0x87, 0x04, 0x92, 0x02, 0x3c, 0x00, 0x4d, 0xfd, 0x41, 0xfc, + 0xc9, 0x01, 0x37, 0x03, 0xd3, 0x00, 0xc4, 0x02, 0x58, 0x03, 0xce, 0xfe, + 0x85, 0xf8, 0x65, 0xf8, 0xf1, 0xfe, 0xa6, 0x08, 0x2a, 0x10, 0x63, 0x11, + 0x38, 0x0f, 0xc2, 0x12, 0x57, 0x1a, 0x87, 0x20, 0x51, 0x28, 0x4a, 0x2b, + 0x2c, 0x2e, 0x77, 0x34, 0xa5, 0x31, 0xfe, 0x25, 0x47, 0x1f, 0x1e, 0x1f, + 0x3d, 0x20, 0x5f, 0x26, 0x3b, 0x2a, 0xf6, 0x28, 0xa4, 0x27, 0x7d, 0x29, + 0xb3, 0x30, 0x85, 0x34, 0x55, 0x33, 0x48, 0x35, 0x3e, 0x32, 0x0e, 0x26, + 0xa5, 0x22, 0x58, 0x26, 0xec, 0x26, 0x66, 0x25, 0x1d, 0x1c, 0x4b, 0x11, + 0x37, 0x13, 0x65, 0x1a, 0xfa, 0x19, 0x4a, 0x17, 0x43, 0x16, 0xe0, 0x15, + 0x8d, 0x16, 0xbe, 0x13, 0x73, 0x0d, 0xa6, 0x0d, 0x03, 0x19, 0x8e, 0x20, + 0xa1, 0x1b, 0x77, 0x17, 0xa0, 0x1d, 0x6d, 0x25, 0x54, 0x2b, 0xe4, 0x2d, + 0xf6, 0x21, 0x85, 0x13, 0xf7, 0x0b, 0x37, 0x0b, 0xd2, 0x13, 0x57, 0x12, + 0xa9, 0x06, 0x12, 0xf9, 0xc3, 0xe4, 0xba, 0xd7, 0x8b, 0xd2, 0x3f, 0xcc, + 0xd2, 0xcd, 0x2d, 0xd7, 0xe2, 0xd8, 0xea, 0xcf, 0x76, 0xcc, 0xc0, 0xd8, + 0x54, 0xe2, 0x45, 0xe8, 0xe4, 0x02, 0x17, 0x0c, 0x5c, 0xfc, 0xa3, 0x04, + 0xea, 0x02, 0xfe, 0xf6, 0x1e, 0x01, 0x7b, 0x06, 0x51, 0x09, 0xbe, 0x15, + 0xc4, 0x1f, 0xe8, 0x1e, 0xaf, 0x1e, 0xbb, 0x24, 0xde, 0x2c, 0x2a, 0x2e, + 0x3d, 0x1f, 0xdf, 0x12, 0xd3, 0x0b, 0xe2, 0x01, 0xd9, 0xff, 0x85, 0xff, + 0xbc, 0xf7, 0x1b, 0xf4, 0x3b, 0xf6, 0x48, 0xf8, 0x51, 0xfa, 0x55, 0x01, + 0x95, 0x0c, 0xc1, 0x0b, 0x3e, 0x0b, 0x49, 0x12, 0x66, 0x16, 0xfe, 0x14, + 0x22, 0x11, 0xa5, 0x15, 0x7c, 0x17, 0x8e, 0x16, 0x32, 0x16, 0xe6, 0x14, + 0x7b, 0x12, 0x57, 0x0a, 0x21, 0x03, 0x1a, 0xfc, 0x88, 0xfb, 0x47, 0x03, + 0xa7, 0x02, 0xce, 0xf9, 0x89, 0xf8, 0x14, 0xf6, 0xdd, 0xf2, 0xfd, 0xfb, + 0xfd, 0xfd, 0x7a, 0xf7, 0x70, 0xf6, 0x79, 0xf4, 0x4a, 0xef, 0x45, 0xef, + 0x9f, 0xf3, 0x08, 0xf5, 0x8a, 0xf0, 0x4d, 0xe9, 0xaa, 0xea, 0xbc, 0xf1, + 0xe1, 0xf5, 0x1e, 0xfa, 0x6c, 0xf8, 0xcd, 0xed, 0xbf, 0xee, 0xce, 0xf4, + 0x05, 0xef, 0xe0, 0xed, 0x58, 0xf6, 0x2c, 0xfb, 0xe6, 0xf9, 0x7c, 0xf9, + 0x7d, 0xfb, 0x08, 0x03, 0xc4, 0x06, 0x17, 0x06, 0x29, 0x08, 0x0f, 0x06, + 0x35, 0x0e, 0x9f, 0x1b, 0xc6, 0x1b, 0x03, 0x1c, 0x3c, 0x22, 0x6e, 0x22, + 0xc4, 0x22, 0x5c, 0x2a, 0x9d, 0x2a, 0x19, 0x27, 0x15, 0x26, 0xb9, 0x22, + 0x4e, 0x28, 0xc3, 0x2e, 0xed, 0x2a, 0x08, 0x2d, 0xf6, 0x2d, 0xac, 0x26, + 0xce, 0x25, 0xeb, 0x27, 0xf6, 0x20, 0xa8, 0x1a, 0xb7, 0x1c, 0x79, 0x1d, + 0x20, 0x1c, 0xab, 0x13, 0xa2, 0x13, 0x60, 0x1c, 0xba, 0x18, 0xc7, 0x1a, + 0xde, 0x1f, 0x22, 0x18, 0x1a, 0x0c, 0xe1, 0x0c, 0x7f, 0x1a, 0x38, 0x20, + 0x30, 0x1f, 0xdc, 0x22, 0xa0, 0x21, 0x17, 0x17, 0xac, 0x16, 0x38, 0x22, + 0xa3, 0x2a, 0xb6, 0x2e, 0x5e, 0x2d, 0x16, 0x28, 0xb8, 0x21, 0xfb, 0x17, + 0x1a, 0x0c, 0x70, 0xff, 0x4a, 0x02, 0x70, 0x18, 0x16, 0x25, 0x80, 0x1d, + 0x29, 0x14, 0x42, 0x10, 0x5a, 0x01, 0x73, 0xf1, 0x8e, 0xf2, 0x09, 0xf7, + 0xf0, 0xf3, 0x2c, 0xed, 0xce, 0xeb, 0x29, 0xf0, 0xc4, 0xe9, 0x4b, 0xe1, + 0x55, 0xf3, 0xb2, 0x03, 0x04, 0x02, 0xc5, 0x14, 0x6f, 0x29, 0xe2, 0x22, + 0x3f, 0x1d, 0x42, 0x13, 0xed, 0x05, 0xdb, 0x05, 0x0c, 0xfe, 0xe5, 0x00, + 0xc2, 0x08, 0x5f, 0x01, 0xc8, 0xff, 0x73, 0x02, 0x13, 0xfd, 0x49, 0xf2, + 0x98, 0xf3, 0x7e, 0xf7, 0x4f, 0xf4, 0x4a, 0xf5, 0x4b, 0xfe, 0x7f, 0xf9, + 0xdd, 0xeb, 0x4f, 0xf1, 0xda, 0xf5, 0xe8, 0xf7, 0xb0, 0xfe, 0xe1, 0x02, + 0x51, 0xfe, 0x30, 0x01, 0x2c, 0x0b, 0x66, 0x09, 0x05, 0x0f, 0xbc, 0x10, + 0x32, 0x0f, 0x40, 0x11, 0x32, 0x11, 0x25, 0x15, 0x1a, 0x16, 0x82, 0x13, + 0x16, 0x10, 0xc1, 0x10, 0xb4, 0x0e, 0xe0, 0x0a, 0xb5, 0x09, 0x05, 0x05, + 0xa6, 0xfe, 0xdb, 0xf8, 0x0c, 0xf6, 0x6f, 0xf7, 0x98, 0xf9, 0x08, 0xf8, + 0xf8, 0xf6, 0x76, 0xf5, 0x11, 0xf1, 0x18, 0xf2, 0xa6, 0xf5, 0x81, 0xf1, + 0x10, 0xf2, 0x74, 0xf1, 0xb4, 0xeb, 0x35, 0xed, 0xfa, 0xeb, 0x96, 0xf0, + 0xfc, 0xf3, 0xd8, 0xf0, 0xcc, 0xed, 0x6f, 0xe9, 0x83, 0xe7, 0x0f, 0xe1, + 0x54, 0xdf, 0xa3, 0xe0, 0xff, 0xe2, 0x69, 0xe5, 0xd4, 0xe3, 0xea, 0xe2, + 0x4f, 0xe0, 0x65, 0xe1, 0x4b, 0xe2, 0xa4, 0xe5, 0x6a, 0xed, 0x6c, 0xef, + 0x00, 0xf0, 0x3c, 0xf0, 0x9d, 0xe9, 0xc5, 0xe7, 0xb6, 0xf1, 0x7b, 0xfc, + 0xa3, 0x02, 0x82, 0xff, 0xa1, 0xf4, 0x85, 0xec, 0x08, 0xf3, 0xa3, 0xfe, + 0x08, 0xff, 0xec, 0x02, 0x98, 0x09, 0xcf, 0x03, 0x62, 0xfd, 0x1a, 0xfc, + 0xac, 0x00, 0x35, 0x0d, 0x7a, 0x0e, 0x2d, 0x05, 0x65, 0xfd, 0x98, 0xf7, + 0x5d, 0xfd, 0xdc, 0x00, 0x79, 0xf8, 0x2b, 0xf6, 0xcf, 0xf6, 0x5c, 0xf6, + 0x8c, 0xf8, 0xb9, 0xf9, 0x90, 0xf8, 0xa7, 0xf8, 0x77, 0xfb, 0xa3, 0xff, + 0x1d, 0x0b, 0x6e, 0x11, 0x8d, 0x0d, 0x5e, 0x0b, 0x0f, 0x06, 0xc8, 0x04, + 0x93, 0x08, 0x2b, 0x09, 0xd5, 0x04, 0xee, 0xf2, 0xef, 0xd9, 0xd3, 0xd3, + 0xea, 0xda, 0xe0, 0xdd, 0xd6, 0xe6, 0xaf, 0xf0, 0x3e, 0xed, 0x04, 0xe8, + 0x43, 0xef, 0x95, 0xfb, 0xd6, 0x09, 0x13, 0x17, 0x6e, 0x1b, 0x63, 0x0d, + 0xe7, 0xf1, 0xbc, 0xe1, 0xb1, 0xd3, 0x93, 0xd2, 0xfb, 0xe1, 0x77, 0xe3, + 0x0b, 0xda, 0x7f, 0xcc, 0x0f, 0xca, 0x61, 0xd2, 0xda, 0xd7, 0x10, 0xea, + 0x5e, 0xfd, 0xf0, 0xf0, 0xde, 0xe0, 0x1d, 0xea, 0xbc, 0xe7, 0x17, 0xd4, + 0xff, 0xd9, 0xf4, 0xe7, 0xf0, 0xe0, 0xc6, 0xe6, 0xd4, 0xf7, 0x75, 0xfb, + 0x02, 0xfd, 0xa7, 0x0a, 0x87, 0x10, 0x1e, 0x0f, 0x1e, 0x26, 0xa2, 0x30, + 0x43, 0x2c, 0xd5, 0x2b, 0xdd, 0x21, 0xb3, 0x22, 0x70, 0x27, 0xa2, 0x25, + 0x6e, 0x25, 0x8b, 0x27, 0x37, 0x22, 0x83, 0x1e, 0x52, 0x20, 0xf2, 0x15, + 0x63, 0x1b, 0xef, 0x24, 0x74, 0x1d, 0x8f, 0x22, 0x66, 0x26, 0x7b, 0x24, + 0x68, 0x31, 0x98, 0x3a, 0x3b, 0x3d, 0x39, 0x46, 0x38, 0x42, 0x95, 0x37, + 0x9e, 0x37, 0x4d, 0x33, 0x75, 0x30, 0x12, 0x2e, 0xcd, 0x23, 0x06, 0x1f, + 0x51, 0x1a, 0x61, 0x12, 0xaa, 0x10, 0x06, 0x12, 0x2a, 0x0d, 0xd0, 0x06, + 0x2a, 0x00, 0xce, 0xf6, 0x8e, 0xf5, 0x39, 0xf3, 0x60, 0xef, 0x04, 0xf2, + 0xd4, 0xf3, 0xeb, 0xf0, 0xe8, 0xe7, 0xd3, 0xe6, 0xd5, 0xeb, 0xd8, 0xec, + 0x77, 0xef, 0xf3, 0xef, 0xb0, 0xf0, 0x54, 0xf6, 0x6e, 0xfb, 0xeb, 0xfd, + 0x2d, 0x02, 0xc9, 0x05, 0xdb, 0x03, 0x7e, 0x08, 0x56, 0x10, 0xd4, 0x0e, + 0x32, 0x10, 0xe7, 0x10, 0x8c, 0x09, 0xa9, 0x03, 0x64, 0x02, 0x1a, 0x03, + 0x5e, 0x05, 0x24, 0x0b, 0x10, 0x0b, 0x0a, 0x0e, 0xee, 0x1c, 0x4e, 0x26, + 0x17, 0x29, 0x2a, 0x26, 0xd3, 0x20, 0x5e, 0x25, 0xb7, 0x2a, 0x65, 0x2e, + 0xa9, 0x33, 0x5e, 0x2e, 0x57, 0x2d, 0x51, 0x32, 0x61, 0x29, 0xb6, 0x29, + 0x94, 0x2e, 0xe6, 0x24, 0xc2, 0x21, 0x54, 0x20, 0x9e, 0x1f, 0xc5, 0x24, + 0xe9, 0x1c, 0x61, 0x15, 0xaa, 0x16, 0xc5, 0x13, 0x0d, 0x18, 0xd6, 0x1e, + 0x72, 0x1e, 0xaf, 0x23, 0xb4, 0x1e, 0x27, 0x10, 0x7f, 0x0b, 0xbd, 0xfe, + 0x44, 0xf5, 0xd2, 0xf2, 0xff, 0xea, 0xd2, 0xe7, 0x1b, 0xdc, 0x25, 0xdc, + 0xca, 0xe9, 0x98, 0xdc, 0xdc, 0xd4, 0x0b, 0xea, 0xa8, 0xee, 0xab, 0xe3, + 0x87, 0xf6, 0x40, 0x15, 0x86, 0x12, 0x45, 0x10, 0xb2, 0x21, 0xd8, 0x1d, + 0x5a, 0x13, 0x11, 0x0b, 0x35, 0xf4, 0xf4, 0xdc, 0x2f, 0xca, 0xa9, 0xbb, + 0x54, 0xb6, 0xb8, 0xb4, 0xae, 0xac, 0x67, 0xa9, 0x8d, 0xa5, 0x2c, 0xa8, + 0x23, 0xbf, 0x4f, 0xc9, 0xa5, 0xd2, 0x07, 0xe6, 0xae, 0xde, 0x2b, 0xca, + 0x8a, 0xcb, 0xe0, 0xc8, 0x47, 0xc5, 0x38, 0xdd, 0xa8, 0xed, 0x31, 0xf0, + 0x21, 0xef, 0x7a, 0xf6, 0x1b, 0x0a, 0x6d, 0x13, 0xbe, 0x1d, 0x50, 0x2a, + 0x84, 0x2d, 0x92, 0x2c, 0x67, 0x2c, 0x90, 0x25, 0x43, 0x17, 0x21, 0x0c, + 0xe2, 0x06, 0xfb, 0xff, 0x72, 0xfb, 0xa8, 0xff, 0x9a, 0xfa, 0xcc, 0xf6, + 0xdd, 0xf8, 0xc2, 0xf1, 0xd8, 0xf1, 0x91, 0xfd, 0x96, 0x02, 0x7e, 0x07, + 0x51, 0x12, 0xf8, 0x12, 0xa5, 0x16, 0xcf, 0x1b, 0xef, 0x1a, 0x5f, 0x20, + 0x47, 0x1b, 0x5c, 0x0c, 0xf8, 0x04, 0x6b, 0xfb, 0x64, 0xed, 0xc9, 0xe3, + 0xa9, 0xd4, 0x64, 0xc8, 0x97, 0xc6, 0xdd, 0xc2, 0xb2, 0xc3, 0x21, 0xc9, + 0x09, 0xc9, 0xbb, 0xc3, 0x78, 0xc1, 0x6b, 0xbd, 0x31, 0xb9, 0x08, 0xbe, + 0x90, 0xc4, 0xda, 0xc9, 0x1e, 0xcb, 0x6b, 0xca, 0xe0, 0xce, 0x1f, 0xd8, + 0x4d, 0xe0, 0xcc, 0xe0, 0x1f, 0xe2, 0x14, 0xe6, 0x74, 0xe6, 0x92, 0xec, + 0x07, 0xf7, 0xa5, 0xf8, 0x98, 0xf7, 0x8d, 0xfd, 0xcc, 0xff, 0x6d, 0xfb, + 0x8b, 0xf7, 0xf6, 0xf1, 0x9a, 0xf2, 0x82, 0xf5, 0xe2, 0xf4, 0x64, 0xf8, + 0xa8, 0xf6, 0xea, 0xf5, 0xe2, 0xff, 0x7c, 0x0a, 0x9a, 0x17, 0x87, 0x23, + 0x26, 0x25, 0x4d, 0x25, 0x4b, 0x26, 0xe7, 0x24, 0xa6, 0x28, 0xff, 0x2f, + 0x82, 0x31, 0x28, 0x2c, 0xc2, 0x21, 0x5a, 0x1a, 0x60, 0x19, 0x4c, 0x1a, + 0xf1, 0x1c, 0xe9, 0x16, 0x48, 0x0a, 0xac, 0x04, 0x26, 0x04, 0x8e, 0x06, + 0x55, 0x09, 0x2f, 0x04, 0x97, 0xfa, 0xad, 0xf7, 0x65, 0xfc, 0x64, 0x00, + 0x0b, 0xfe, 0x05, 0xf9, 0xea, 0xea, 0x8c, 0xd3, 0xe0, 0xc9, 0x80, 0xd1, + 0x3e, 0xd8, 0xda, 0xdc, 0x38, 0xe0, 0x51, 0xd8, 0x57, 0xce, 0x57, 0xd2, + 0xa2, 0xdf, 0x00, 0xe3, 0xb0, 0xe2, 0x50, 0xed, 0xe0, 0xf4, 0xe7, 0xef, + 0x00, 0xf3, 0x06, 0xfb, 0x22, 0xf1, 0x7f, 0xed, 0x70, 0xf3, 0x21, 0xfb, + 0x4e, 0x00, 0xcc, 0xf8, 0x01, 0xf5, 0x16, 0xe8, 0xb9, 0xcc, 0xac, 0xbd, + 0x1d, 0xb7, 0x1d, 0xac, 0x9c, 0xac, 0x5d, 0xb1, 0x99, 0xb3, 0xd0, 0xb5, + 0x83, 0xb0, 0xf0, 0xb2, 0x35, 0xb7, 0x25, 0xbc, 0x8f, 0xcc, 0x7e, 0xe8, + 0x2e, 0xf9, 0xab, 0xf0, 0x25, 0xea, 0xcc, 0xeb, 0x6d, 0xea, 0xfb, 0xeb, + 0x23, 0x00, 0xed, 0x13, 0x7c, 0x15, 0xda, 0x11, 0x2f, 0x13, 0xaa, 0x15, + 0xfe, 0x13, 0x4e, 0x13, 0xf4, 0x13, 0x48, 0x10, 0xe7, 0x02, 0x1b, 0xff, + 0xd1, 0xf9, 0x90, 0xe5, 0x5a, 0xe0, 0xb7, 0xe0, 0xf2, 0xd6, 0x40, 0xd4, + 0xe6, 0xdb, 0xe2, 0xda, 0xd5, 0xd8, 0x2a, 0xdd, 0x90, 0xde, 0x7e, 0xe8, + 0xce, 0xf1, 0x90, 0xed, 0x8a, 0xeb, 0xad, 0xee, 0x48, 0xf4, 0xee, 0xf6, + 0xbc, 0xf2, 0x0b, 0xf0, 0xe8, 0xe9, 0x9d, 0xe5, 0x52, 0xe3, 0x68, 0xe1, + 0x9b, 0xdf, 0xb2, 0xd7, 0x5f, 0xd2, 0x5a, 0xc6, 0xfc, 0xbd, 0xf8, 0xbd, + 0x48, 0xb8, 0x03, 0xbb, 0x89, 0xc2, 0xb3, 0xc5, 0xc6, 0xc6, 0xf8, 0xc9, + 0xa0, 0xcb, 0x39, 0xd0, 0x83, 0xdd, 0x18, 0xe2, 0x7c, 0xe6, 0x9d, 0xeb, + 0x27, 0xe8, 0x21, 0xea, 0x44, 0xee, 0x9a, 0xf3, 0x64, 0xf7, 0xe7, 0xf9, + 0xd3, 0xfc, 0x92, 0xf5, 0x8f, 0xf4, 0x28, 0xf7, 0xba, 0xf6, 0xaa, 0x01, + 0x9c, 0x08, 0x54, 0x05, 0x76, 0xfe, 0x15, 0xfc, 0x2e, 0xff, 0x8c, 0x01, + 0xce, 0x07, 0x72, 0x07, 0x0e, 0x05, 0xe5, 0x02, 0xeb, 0xfd, 0x29, 0x02, + 0x53, 0x0d, 0x74, 0x18, 0xdf, 0x1b, 0xe3, 0x1d, 0xbf, 0x1d, 0x79, 0x17, + 0xe4, 0x15, 0x5c, 0x17, 0x6c, 0x1e, 0x3b, 0x24, 0x55, 0x1a, 0x09, 0x15, + 0xcc, 0x17, 0x3e, 0x10, 0xb0, 0x0f, 0xcb, 0x16, 0x3f, 0x1d, 0x3c, 0x1d, + 0x63, 0x16, 0x95, 0x11, 0xdb, 0x07, 0xcd, 0x01, 0xbf, 0xfb, 0x11, 0xee, + 0x26, 0xe4, 0x7f, 0xe8, 0xf8, 0xe8, 0x6a, 0xe4, 0x03, 0xec, 0x63, 0xe8, + 0x5e, 0xe5, 0xea, 0xee, 0x7c, 0xf7, 0x6a, 0xfb, 0x67, 0xfb, 0xda, 0x0a, + 0x4b, 0x10, 0xa5, 0x03, 0x9e, 0x0d, 0x12, 0x0e, 0xff, 0x08, 0xd4, 0x14, + 0x22, 0x0f, 0xf1, 0x06, 0x3c, 0x00, 0x03, 0x02, 0xe9, 0x0b, 0xbb, 0x09, + 0xae, 0x04, 0x6c, 0x0d, 0x94, 0x1b, 0x70, 0x18, 0x71, 0x20, 0x89, 0x29, + 0x67, 0x2a, 0xaa, 0x27, 0xd9, 0x10, 0x95, 0xfa, 0xed, 0xea, 0x55, 0xe2, + 0x05, 0xe6, 0x63, 0xee, 0xa8, 0xe9, 0xc3, 0xe4, 0xf7, 0xe9, 0xcb, 0xee, + 0x09, 0xf3, 0xa6, 0xff, 0x1b, 0x1d, 0x85, 0x29, 0x2c, 0x20, 0x78, 0x1c, + 0xda, 0x14, 0x2f, 0x05, 0x19, 0x02, 0x2f, 0x07, 0x59, 0x0c, 0xda, 0x0d, + 0x8f, 0x07, 0xbd, 0x08, 0x3a, 0x0d, 0x44, 0x0b, 0x5a, 0x07, 0xdd, 0x0b, + 0x90, 0x0c, 0x1d, 0x0a, 0x21, 0x0f, 0x49, 0x09, 0x56, 0xfe, 0xe3, 0xff, + 0xd2, 0x04, 0x62, 0x00, 0x3d, 0xfd, 0xb0, 0x01, 0xe0, 0x05, 0x27, 0x03, + 0xc5, 0x02, 0x4c, 0x02, 0x11, 0x00, 0x57, 0x03, 0xf3, 0xfb, 0x19, 0xf9, + 0xce, 0x02, 0xd1, 0x09, 0xf0, 0x0a, 0x40, 0x0d, 0x76, 0x12, 0x4a, 0x12, + 0x4a, 0x14, 0xdf, 0x0b, 0x20, 0xfd, 0xc7, 0xfb, 0xff, 0xff, 0xdb, 0x05, + 0x63, 0x06, 0x07, 0x01, 0xc4, 0xfa, 0xca, 0xf3, 0x6b, 0xf4, 0x6c, 0x01, + 0x6e, 0x0c, 0xc1, 0x0b, 0x30, 0x08, 0x20, 0x00, 0x9a, 0xff, 0xf8, 0x08, + 0x6c, 0x09, 0x6e, 0x0c, 0x8f, 0x09, 0x2c, 0xfe, 0x2e, 0xfd, 0xc3, 0xff, + 0xf0, 0x02, 0x09, 0x04, 0x2b, 0x00, 0x1e, 0xfa, 0xb8, 0xf7, 0xe3, 0xff, + 0x51, 0x07, 0xaf, 0x0b, 0x76, 0x16, 0x6e, 0x18, 0xa2, 0x11, 0x6e, 0x12, + 0xaa, 0x12, 0xb6, 0x12, 0x2c, 0x16, 0x06, 0x15, 0x74, 0x14, 0xf1, 0x0f, + 0xa0, 0x08, 0x10, 0x0e, 0x8c, 0x13, 0x1c, 0x19, 0x78, 0x1f, 0x48, 0x1d, + 0x02, 0x1f, 0xae, 0x2b, 0x8f, 0x39, 0x47, 0x38, 0x90, 0x30, 0x2c, 0x2e, + 0x29, 0x33, 0x38, 0x38, 0x9b, 0x38, 0x72, 0x3a, 0x89, 0x34, 0x25, 0x27, + 0x00, 0x15, 0x10, 0x03, 0xed, 0x00, 0x69, 0x0b, 0xc8, 0x11, 0x37, 0x0e, + 0x81, 0x04, 0x23, 0xfa, 0x70, 0xf4, 0xe5, 0x02, 0xc4, 0x13, 0xf5, 0x17, + 0xf6, 0x2c, 0x47, 0x2d, 0x17, 0x0d, 0x1b, 0x03, 0x3c, 0x09, 0x19, 0x08, + 0xc2, 0x0a, 0x32, 0x05, 0xcf, 0xf4, 0x32, 0xee, 0x25, 0xe6, 0x30, 0xed, + 0x2c, 0xfa, 0x3f, 0xf2, 0x82, 0xf0, 0x36, 0xf2, 0xca, 0xe8, 0x31, 0xf0, + 0x13, 0x02, 0x8d, 0x04, 0xd3, 0x0a, 0x2f, 0x13, 0x0f, 0x17, 0xa2, 0x1b, + 0x1d, 0x24, 0xce, 0x2f, 0x93, 0x34, 0x00, 0x30, 0xfc, 0x23, 0xcd, 0x15, + 0x62, 0x07, 0x82, 0xfa, 0x1c, 0xe7, 0xe0, 0xe3, 0x1d, 0xf1, 0xb6, 0xee, + 0x35, 0xe6, 0xcf, 0xdb, 0x04, 0xd7, 0x39, 0xe1, 0xa9, 0xee, 0x1b, 0xfd, + 0x52, 0x08, 0x60, 0xfe, 0x40, 0xf2, 0x40, 0xf0, 0x5e, 0xea, 0xf2, 0xe9, + 0xf1, 0xf3, 0x5a, 0xfb, 0x78, 0xf9, 0xc1, 0xfc, 0xfc, 0x09, 0xa4, 0x15, + 0xe8, 0x0f, 0x7e, 0x11, 0x8c, 0x20, 0x40, 0x1b, 0x7c, 0x14, 0xf0, 0x14, + 0x65, 0x08, 0x78, 0xf6, 0x9a, 0xf4, 0x86, 0xf0, 0x4f, 0xe7, 0x28, 0xe7, + 0x4d, 0xe6, 0x2f, 0xea, 0x90, 0xe9, 0x7f, 0xe6, 0x84, 0xe7, 0xd6, 0xe9, + 0xa8, 0xf0, 0xc3, 0xf7, 0x74, 0xfd, 0x1a, 0xfc, 0x13, 0x01, 0x8b, 0x0f, + 0x74, 0x1a, 0x6b, 0x25, 0xb3, 0x2c, 0xa9, 0x2c, 0xe0, 0x28, 0xe8, 0x27, + 0x66, 0x2a, 0x8a, 0x28, 0x87, 0x26, 0xf0, 0x1d, 0x7f, 0x0f, 0xd0, 0x09, + 0xec, 0x0b, 0x19, 0x0d, 0xb2, 0x0c, 0x64, 0x10, 0x4f, 0x0a, 0x94, 0x02, + 0x92, 0x04, 0x30, 0x0b, 0x3c, 0x12, 0x07, 0x0a, 0xb5, 0x02, 0xc4, 0x00, + 0xde, 0x02, 0x63, 0x14, 0x3b, 0x1b, 0xde, 0x17, 0x92, 0x17, 0x1f, 0x16, + 0xd5, 0x1a, 0x1c, 0x25, 0x53, 0x2c, 0x42, 0x2b, 0xf1, 0x27, 0x64, 0x24, + 0xec, 0x24, 0x5b, 0x27, 0xf2, 0x25, 0x74, 0x21, 0x44, 0x19, 0x61, 0x1b, + 0xff, 0x1a, 0x6b, 0x14, 0x5a, 0x11, 0xf2, 0x0c, 0xf9, 0x12, 0x33, 0x1a, + 0x58, 0x23, 0x4f, 0x33, 0xa9, 0x39, 0xbd, 0x3b, 0x4d, 0x3c, 0xf3, 0x33, + 0x9f, 0x2c, 0x1b, 0x27, 0xab, 0x1b, 0x9b, 0x13, 0x04, 0x15, 0x27, 0x18, + 0xfe, 0x15, 0x1a, 0x14, 0x95, 0x16, 0x9a, 0x18, 0x11, 0x23, 0x64, 0x26, + 0x08, 0x1e, 0xba, 0x2e, 0x5e, 0x34, 0x0f, 0x2a, 0x51, 0x2c, 0x42, 0x1b, + 0x61, 0x11, 0x1e, 0x1a, 0xc4, 0x13, 0xfd, 0x05, 0xa8, 0x06, 0x15, 0x00, + 0x95, 0xf2, 0x01, 0xf4, 0xe5, 0xef, 0xeb, 0xed, 0x5f, 0xee, 0x75, 0xeb, + 0xfd, 0xee, 0xb1, 0xfb, 0x5d, 0xff, 0xbf, 0xfc, 0x32, 0x02, 0x10, 0xf9, + 0x3e, 0xfa, 0x93, 0x03, 0x79, 0x05, 0x27, 0x16, 0x85, 0x1e, 0x93, 0x18, + 0x99, 0x18, 0xdf, 0x1f, 0x56, 0x37, 0xb1, 0x4a, 0x7a, 0x47, 0x22, 0x45, + 0x3d, 0x35, 0x46, 0x15, 0xb0, 0xff, 0xb0, 0xf7, 0x9c, 0xed, 0xc2, 0xe2, + 0x30, 0xe2, 0x96, 0xd6, 0x72, 0xc4, 0xb8, 0xc4, 0xd9, 0xcf, 0xa0, 0xd4, + 0xac, 0xdf, 0x23, 0xf5, 0x15, 0xff, 0x5c, 0xf3, 0x22, 0xe7, 0x46, 0xea, + 0x01, 0xe9, 0x53, 0xe6, 0x44, 0xf0, 0x6a, 0x05, 0x78, 0x0c, 0xb1, 0x08, + 0x77, 0x0d, 0x2b, 0x06, 0x92, 0xfb, 0x9a, 0x02, 0xfb, 0x0c, 0x7e, 0x07, + 0x96, 0x00, 0xc0, 0xf7, 0x7a, 0xe9, 0x15, 0xe0, 0xc1, 0xdc, 0x41, 0xe5, + 0xbc, 0xdf, 0xcb, 0xd4, 0xe5, 0xd5, 0xd6, 0xd0, 0xee, 0xd1, 0xf4, 0xdb, + 0xe4, 0xe2, 0x5d, 0xe8, 0xa3, 0xef, 0x41, 0xf7, 0x09, 0xfb, 0xdb, 0x01, + 0xed, 0x0c, 0x1d, 0x19, 0x37, 0x26, 0x9a, 0x2a, 0xa7, 0x2a, 0x6f, 0x2a, + 0xb2, 0x23, 0x19, 0x1f, 0x70, 0x1e, 0xe5, 0x17, 0xdf, 0x0c, 0x38, 0x00, + 0x48, 0xf5, 0xad, 0xf0, 0x82, 0xec, 0x74, 0xe9, 0x20, 0xeb, 0x80, 0xea, + 0xcb, 0xe4, 0x53, 0xe4, 0xf6, 0xe4, 0xf9, 0xea, 0x09, 0xf9, 0xca, 0xfb, + 0x8c, 0xfa, 0x4c, 0xf2, 0x3b, 0xec, 0xdb, 0xf4, 0x96, 0xfe, 0xbe, 0x04, + 0x10, 0x02, 0x4d, 0x01, 0x10, 0xfe, 0xdb, 0xfc, 0x34, 0x08, 0x5f, 0x0f, + 0x98, 0x14, 0x9a, 0x1e, 0x0b, 0x22, 0x42, 0x1e, 0x90, 0x1f, 0x96, 0x1c, + 0x17, 0x1f, 0x78, 0x26, 0x90, 0x28, 0x17, 0x2e, 0xdf, 0x20, 0x62, 0x13, + 0xbc, 0x0f, 0xe3, 0x07, 0x81, 0x0e, 0x98, 0x16, 0x3b, 0x17, 0x23, 0x17, + 0x0f, 0x1c, 0xcd, 0x25, 0x10, 0x2c, 0xb4, 0x33, 0x00, 0x38, 0xf3, 0x3b, + 0x95, 0x3f, 0x11, 0x48, 0x1c, 0x56, 0x6c, 0x50, 0x94, 0x4d, 0x85, 0x4b, + 0x9e, 0x37, 0xa3, 0x2e, 0x34, 0x2a, 0xa7, 0x26, 0x8f, 0x24, 0xc9, 0x17, + 0x2e, 0x0c, 0x5f, 0x03, 0x86, 0xf7, 0xe9, 0xf8, 0x15, 0x04, 0xa5, 0xfa, + 0xbd, 0xf4, 0x7f, 0xfe, 0x2b, 0xfa, 0xb1, 0xf8, 0x09, 0x02, 0xe7, 0x04, + 0x65, 0x05, 0x8e, 0x0d, 0x3e, 0x10, 0x65, 0x0c, 0xea, 0x17, 0x1a, 0x25, + 0xcb, 0x29, 0x0a, 0x2f, 0xf6, 0x2b, 0x33, 0x2d, 0xb7, 0x39, 0x10, 0x3d, + 0xc2, 0x40, 0x67, 0x4a, 0x85, 0x52, 0x3c, 0x53, 0x1f, 0x48, 0x82, 0x44, + 0xdc, 0x44, 0xe8, 0x3a, 0xab, 0x26, 0xdf, 0x14, 0x87, 0x0d, 0x09, 0xfc, + 0xc8, 0xef, 0x7b, 0xef, 0x07, 0xe8, 0xcb, 0xeb, 0x20, 0xed, 0x8a, 0xe9, + 0xcd, 0xff, 0xf7, 0x0c, 0xc1, 0x09, 0xc9, 0x21, 0xe7, 0x37, 0xd4, 0x2e, + 0xb9, 0x25, 0x4e, 0x1f, 0x0d, 0x11, 0xef, 0x0a, 0xb4, 0x10, 0x7f, 0x13, + 0xd6, 0x0b, 0x75, 0x08, 0x13, 0x0e, 0xe3, 0x0c, 0x39, 0x07, 0xe9, 0x0a, + 0xab, 0x11, 0x9b, 0x09, 0x39, 0x00, 0x8f, 0x00, 0x81, 0xf2, 0xb6, 0xe5, + 0xd2, 0xeb, 0xfc, 0xea, 0x26, 0xed, 0x85, 0xfb, 0x4a, 0x00, 0xd2, 0xfd, + 0xac, 0x02, 0x8a, 0x10, 0xdf, 0x12, 0x96, 0x10, 0xb1, 0x1d, 0xa4, 0x25, + 0xe2, 0x26, 0x17, 0x2a, 0xbd, 0x29, 0x05, 0x2a, 0xc8, 0x2a, 0xe8, 0x2c, + 0x65, 0x2e, 0x9c, 0x26, 0x8a, 0x20, 0x42, 0x1d, 0x61, 0x12, 0xe7, 0x0a, + 0xec, 0x05, 0xf6, 0x00, 0x31, 0xff, 0x7d, 0xfe, 0x52, 0xfd, 0x8d, 0xf7, + 0xee, 0xfa, 0xdf, 0xff, 0xa3, 0xfd, 0x81, 0xfe, 0x26, 0x01, 0x41, 0x06, + 0xf3, 0x08, 0x3f, 0x0b, 0x7e, 0x0a, 0x4e, 0x0a, 0x79, 0x0e, 0x0f, 0x0e, + 0x86, 0x10, 0x3f, 0x11, 0x6e, 0x0c, 0x78, 0x0e, 0x20, 0x10, 0x0f, 0x08, + 0xa8, 0x0f, 0xc8, 0x1a, 0xd9, 0x14, 0xe8, 0x10, 0x95, 0x07, 0x47, 0xfe, + 0x89, 0xf7, 0xa3, 0xea, 0x9d, 0xe2, 0x25, 0xe2, 0xf9, 0xd6, 0x7e, 0xc8, + 0x83, 0xcf, 0xb2, 0xd3, 0xc4, 0xd8, 0x78, 0xe9, 0x6d, 0xf8, 0x15, 0x00, + 0x03, 0x05, 0x49, 0x1a, 0x10, 0x22, 0x3e, 0x23, 0x37, 0x30, 0x6e, 0x28, + 0x0e, 0x1e, 0x93, 0x19, 0xd8, 0x15, 0x78, 0x1f, 0x94, 0x19, 0xf5, 0x09, + 0x82, 0x0c, 0x7f, 0x07, 0x05, 0xfb, 0x95, 0xf9, 0xac, 0xf2, 0x45, 0xe7, + 0xe6, 0xeb, 0x6e, 0xec, 0x98, 0xdf, 0xf2, 0xde, 0x3b, 0xe7, 0x96, 0xe5, + 0xd8, 0xdd, 0x86, 0xe3, 0xec, 0xeb, 0x49, 0xee, 0x6f, 0xed, 0x64, 0xec, + 0x6d, 0xf2, 0x29, 0xf8, 0xe2, 0x03, 0x95, 0x0a, 0x5c, 0x07, 0x93, 0x05, + 0xfb, 0x06, 0x56, 0x0b, 0x83, 0x0c, 0xa5, 0x0d, 0xaa, 0x0b, 0x6b, 0x07, + 0x74, 0x03, 0xbf, 0xfe, 0x1d, 0x00, 0x72, 0x0d, 0x11, 0x14, 0xeb, 0x0b, + 0x78, 0x07, 0xa6, 0x09, 0xe9, 0x09, 0x49, 0xfd, 0x45, 0xeb, 0x7d, 0xd9, + 0x9b, 0xc9, 0x37, 0xc2, 0xed, 0xc4, 0x95, 0xca, 0x2b, 0xc4, 0xac, 0xb9, + 0x74, 0xb8, 0xf2, 0xbb, 0x3c, 0xc4, 0x2d, 0xd8, 0x6c, 0xf3, 0xd6, 0x05, + 0xf3, 0xf6, 0x4e, 0xe5, 0x98, 0xe4, 0x2e, 0xd5, 0x8a, 0xcf, 0xb4, 0xe0, + 0xab, 0xec, 0xb0, 0xed, 0x2c, 0xed, 0xa7, 0xe5, 0x90, 0xe3, 0x0b, 0xea, + 0x80, 0xf7, 0x92, 0x0b, 0xec, 0x05, 0xe1, 0xff, 0xa9, 0x02, 0xe4, 0xfb, + 0x25, 0xf9, 0x07, 0xf9, 0x1e, 0xf4, 0x77, 0xee, 0xb1, 0xf1, 0x64, 0xf6, + 0x14, 0xf9, 0x78, 0xfc, 0xd9, 0xfc, 0x29, 0xf8, 0x64, 0xf6, 0xea, 0xf8, + 0x36, 0xfd, 0x74, 0x05, 0x74, 0x0a, 0x5a, 0x09, 0x1e, 0x08, 0x55, 0x0c, + 0xe5, 0x11, 0xc3, 0x16, 0x08, 0x16, 0xc6, 0x11, 0x33, 0x0b, 0x02, 0x04, + 0x85, 0xfc, 0xc8, 0xf6, 0xe1, 0xf7, 0x5b, 0xf2, 0x01, 0xed, 0xcd, 0xe0, + 0xfd, 0xd7, 0x6a, 0xe5, 0xa6, 0xed, 0xcb, 0xef, 0xc7, 0xf0, 0xf8, 0xe8, + 0x60, 0xea, 0x1f, 0xf4, 0x0a, 0xf4, 0xb4, 0xf9, 0x66, 0xfe, 0x95, 0xf6, + 0x09, 0xf5, 0x19, 0xf1, 0x66, 0xea, 0xb3, 0xf4, 0xd0, 0xf2, 0x54, 0xdc, + 0xc7, 0xcb, 0xab, 0xbc, 0xd1, 0xba, 0x75, 0xbe, 0x60, 0xc4, 0xad, 0xcd, + 0x3f, 0xcf, 0x28, 0xd2, 0xa3, 0xcd, 0xe8, 0xcb, 0x99, 0xd0, 0xb8, 0xd6, + 0x0f, 0xe0, 0xfb, 0xe2, 0xe6, 0xe4, 0x28, 0xeb, 0x5a, 0xe9, 0x9b, 0xe3, + 0x45, 0xea, 0x60, 0xef, 0x25, 0xf9, 0x0c, 0x0d, 0x9d, 0x11, 0x11, 0x11, + 0x9e, 0x0c, 0x9a, 0xfb, 0xd0, 0xfb, 0x22, 0xf3, 0xcc, 0xe6, 0xcd, 0xf2, + 0xd0, 0xeb, 0x7e, 0xe4, 0x97, 0xdf, 0xfc, 0xd6, 0x70, 0xd7, 0xe5, 0xd4, + 0x21, 0xd4, 0xae, 0xd7, 0x26, 0xe1, 0xcf, 0xda, 0xdd, 0xd5, 0xa2, 0xdb, + 0xfa, 0xdb, 0x29, 0xde, 0x39, 0xe1, 0x3f, 0xea, 0x9d, 0xea, 0xc2, 0xee, + 0x66, 0xfb, 0xdb, 0xf5, 0xfc, 0xed, 0xbb, 0xf1, 0x06, 0xef, 0x10, 0xe7, + 0x15, 0xe5, 0x71, 0xe0, 0xcc, 0xe1, 0xa5, 0xea, 0xf3, 0xeb, 0xb1, 0xe3, + 0xef, 0xde, 0x4e, 0xe6, 0x4c, 0xee, 0x49, 0xf8, 0x25, 0x0a, 0x4c, 0x13, + 0xb3, 0x0f, 0xc3, 0x0c, 0x70, 0x08, 0xbc, 0xf5, 0xdd, 0xd8, 0x5b, 0xcb, + 0x15, 0xc4, 0x4c, 0xb5, 0x2f, 0xaf, 0x95, 0xb1, 0x0e, 0xb3, 0xae, 0xa7, + 0xfe, 0x9f, 0x85, 0xae, 0xab, 0xbc, 0x5f, 0xc2, 0x8e, 0xd9, 0xe3, 0xec, + 0x79, 0xe0, 0x4a, 0xd9, 0xf9, 0xd3, 0xcf, 0xca, 0xc2, 0xcb, 0x6f, 0xd5, + 0x93, 0xea, 0x4c, 0xe9, 0x0c, 0xe1, 0xb1, 0xed, 0x0f, 0xf2, 0xb7, 0xf1, + 0xe3, 0xf9, 0xdb, 0x07, 0xf6, 0x12, 0xd6, 0x15, 0xce, 0x19, 0x94, 0x0f, + 0x39, 0xf9, 0x64, 0xf6, 0xee, 0xf4, 0x76, 0xe7, 0x84, 0xe8, 0x10, 0xf1, + 0x21, 0xef, 0x1d, 0xf1, 0x18, 0xf6, 0x43, 0xf4, 0x56, 0xfc, 0x0b, 0x08, + 0xad, 0x0c, 0xf7, 0x17, 0xfa, 0x21, 0xaa, 0x2a, 0xf0, 0x3a, 0x07, 0x3e, + 0xf7, 0x38, 0xbc, 0x39, 0xa6, 0x32, 0x3f, 0x32, 0x73, 0x35, 0xa0, 0x24, + 0x67, 0x18, 0x75, 0x11, 0x07, 0x03, 0x72, 0x01, 0xee, 0xff, 0x95, 0xf6, + 0x2b, 0xf8, 0xb8, 0xfa, 0x12, 0xfc, 0x62, 0xff, 0xb4, 0xfa, 0x4d, 0xf7, + 0xf4, 0xf2, 0xfc, 0xee, 0xf3, 0xf5, 0x61, 0xf2, 0x08, 0xe3, 0x7c, 0xd4, + 0x81, 0xc6, 0xb5, 0xc1, 0x04, 0xc7, 0xa2, 0xc7, 0x4f, 0xc3, 0x11, 0xc6, + 0xa4, 0xc4, 0xd0, 0xc9, 0x8b, 0xd6, 0x5f, 0xd8, 0xc3, 0xe9, 0x84, 0xfd, + 0xcd, 0xfe, 0x34, 0x03, 0x88, 0x05, 0x22, 0xff, 0xee, 0xfe, 0x37, 0x04, + 0x21, 0x02, 0xf4, 0xfd, 0x13, 0xfb, 0xa7, 0xf9, 0x7a, 0x01, 0xbf, 0x0c, + 0x74, 0x0f, 0x32, 0x13, 0x20, 0x1b, 0xb6, 0x1e, 0x12, 0x30, 0x52, 0x40, + 0xa4, 0x3e, 0xf6, 0x3b, 0x3d, 0x32, 0xa1, 0x2c, 0x87, 0x2b, 0xac, 0x24, + 0xf0, 0x22, 0x40, 0x1f, 0xfa, 0x18, 0x83, 0x1a, 0x81, 0x1a, 0xd0, 0x16, + 0x0f, 0x17, 0xee, 0x12, 0xc6, 0x18, 0x9e, 0x21, 0xfa, 0x15, 0xe6, 0x0f, + 0xc6, 0x13, 0x3c, 0x0e, 0x56, 0x05, 0x1e, 0x06, 0xa4, 0x04, 0xca, 0xf9, + 0xe3, 0xf0, 0x32, 0xf0, 0xff, 0xf2, 0x7b, 0xed, 0xcf, 0xeb, 0x4b, 0xeb, + 0xd7, 0xe5, 0x5e, 0xe9, 0x33, 0xf2, 0xed, 0xfc, 0xe3, 0xff, 0x74, 0xf9, + 0x33, 0xf6, 0xd1, 0xf9, 0xc8, 0x03, 0x44, 0x10, 0x39, 0x1b, 0xb6, 0x19, + 0xed, 0x0e, 0x9b, 0x02, 0xfe, 0xf5, 0x77, 0xee, 0xed, 0xde, 0x46, 0xcc, + 0xae, 0xc4, 0xc1, 0xc2, 0x7b, 0xc3, 0xed, 0xc3, 0x08, 0xc1, 0xce, 0xb8, + 0x73, 0xbd, 0x4c, 0xcd, 0x3c, 0xd3, 0xe5, 0xe1, 0x1f, 0xfb, 0xca, 0x01, + 0x8b, 0xf8, 0x97, 0xf8, 0xb0, 0xfe, 0x38, 0xf9, 0x2b, 0xf7, 0x7f, 0x09, + 0x80, 0x14, 0xca, 0x0d, 0x41, 0x17, 0x1c, 0x24, 0x3a, 0x1b, 0x7d, 0x1f, + 0xed, 0x2c, 0xb2, 0x26, 0xd9, 0x23, 0x4d, 0x29, 0x1e, 0x2b, 0x5f, 0x20, + 0xff, 0x12, 0xd4, 0x0c, 0xc4, 0x02, 0x07, 0x05, 0xf2, 0x08, 0xcf, 0x0b, + 0xcd, 0x14, 0x6a, 0x12, 0xec, 0x15, 0xa5, 0x16, 0xa4, 0x16, 0x78, 0x20, + 0x8e, 0x1f, 0x83, 0x1c, 0x2e, 0x20, 0xa5, 0x28, 0x18, 0x2b, 0x28, 0x2e, + 0xb2, 0x2f, 0xf3, 0x28, 0xe0, 0x2c, 0x3c, 0x2d, 0xc8, 0x29, 0xe6, 0x23, + 0xc6, 0x16, 0x59, 0x0a, 0x5d, 0x03, 0xfc, 0x07, 0xf0, 0x05, 0x21, 0xff, + 0x9f, 0xf4, 0x57, 0xe2, 0x18, 0xd9, 0xc8, 0xcd, 0x80, 0xc4, 0x21, 0xcb, + 0x3d, 0xc7, 0xec, 0xbd, 0x68, 0xc6, 0x5e, 0xc9, 0xca, 0xc6, 0x18, 0xcf, + 0x7c, 0xd2, 0xbc, 0xd0, 0x03, 0xdb, 0xc3, 0xe5, 0xf1, 0xe5, 0x94, 0xec, + 0x88, 0xf2, 0x17, 0xed, 0xbd, 0xf1, 0x50, 0xfb, 0x3d, 0xfa, 0x74, 0x00, + 0x37, 0x02, 0x2e, 0xfa, 0xef, 0xff, 0x92, 0x01, 0x1d, 0xf9, 0xd7, 0xfe, + 0x99, 0x06, 0xa5, 0x04, 0x54, 0x0b, 0x57, 0x0f, 0x4f, 0x12, 0xcf, 0x1c, + 0x0d, 0x21, 0x09, 0x2a, 0xad, 0x30, 0x79, 0x2f, 0x7c, 0x2b, 0x59, 0x22, + 0xfc, 0x22, 0x49, 0x24, 0x94, 0x1d, 0x8d, 0x1d, 0x39, 0x1c, 0x14, 0x14, + 0x86, 0x11, 0x8a, 0x0d, 0xe9, 0x08, 0x38, 0x0e, 0x28, 0x10, 0x92, 0x0b, + 0xd3, 0x03, 0x37, 0xfa, 0x01, 0xf4, 0x59, 0xeb, 0x09, 0xe9, 0xdd, 0xe9, + 0xe9, 0xe2, 0x08, 0xe1, 0x63, 0xe2, 0xc6, 0xe1, 0x9c, 0xe4, 0x8e, 0xe8, + 0x22, 0xea, 0x0f, 0xea, 0x0f, 0xec, 0x63, 0xf2, 0x28, 0xf5, 0x16, 0xf2, + 0x48, 0xec, 0x57, 0xec, 0xdd, 0xf0, 0xc3, 0xec, 0xc5, 0xf1, 0x79, 0xfc, + 0x54, 0x00, 0xe8, 0x09, 0x4a, 0x12, 0x4f, 0x15, 0xfa, 0x1a, 0xb9, 0x17, + 0x57, 0x10, 0x1a, 0x0f, 0xb3, 0xfb, 0x58, 0xe4, 0xd9, 0xd5, 0xc1, 0xcd, + 0xf1, 0xd8, 0x70, 0xdf, 0x36, 0xda, 0x9b, 0xdb, 0x2f, 0xdd, 0x2f, 0xda, + 0xb9, 0xe2, 0x9f, 0xf3, 0x7c, 0x0e, 0x17, 0x20, 0xda, 0x14, 0xec, 0x14, + 0x03, 0x16, 0x62, 0x08, 0x14, 0x10, 0x0c, 0x22, 0x72, 0x1b, 0x2a, 0x14, + 0xe2, 0x1b, 0x3d, 0x1d, 0xd6, 0x17, 0x24, 0x1d, 0xdf, 0x25, 0x08, 0x21, + 0xd5, 0x23, 0xec, 0x29, 0x75, 0x2c, 0xa0, 0x29, 0xcb, 0x23, 0xd9, 0x22, + 0xaf, 0x13, 0x61, 0x10, 0x4c, 0x13, 0xea, 0x11, 0xa3, 0x18, 0x77, 0x15, + 0x51, 0x0e, 0x34, 0x07, 0xa6, 0x07, 0xb4, 0x0f, 0x44, 0x19, 0x92, 0x1f, + 0xb5, 0x20, 0x74, 0x24, 0xce, 0x25, 0x8c, 0x2f, 0x56, 0x3b, 0x30, 0x40, + 0x57, 0x3f, 0x7f, 0x31, 0xa3, 0x29, 0xce, 0x1f, 0xa6, 0x0e, 0x16, 0x03, + 0xa0, 0xf3, 0x0e, 0xe3, 0xb6, 0xd6, 0x69, 0xd5, 0xc3, 0xd0, 0xb7, 0xc9, + 0x42, 0xd1, 0x92, 0xd2, 0x20, 0xd0, 0x32, 0xda, 0xb1, 0xdf, 0xd6, 0xd9, + 0xa2, 0xe8, 0xc2, 0xf2, 0xbc, 0xea, 0x41, 0xf3, 0x2a, 0xec, 0xf1, 0xe2, + 0x75, 0xee, 0x09, 0xe9, 0x04, 0xe2, 0x10, 0xf0, 0xb7, 0xef, 0x7b, 0xec, + 0x2a, 0xfc, 0x42, 0xf4, 0x08, 0xf3, 0xb1, 0x02, 0x03, 0xfb, 0xae, 0xff, + 0x3f, 0x0c, 0xfc, 0x0a, 0x0d, 0x14, 0x17, 0x1a, 0xa4, 0x15, 0x7a, 0x1b, + 0x95, 0x22, 0xaf, 0x20, 0xc5, 0x23, 0x4f, 0x2d, 0xdb, 0x33, 0xe7, 0x3a, + 0x81, 0x39, 0xd2, 0x3b, 0x38, 0x42, 0xe3, 0x3a, 0x42, 0x37, 0xeb, 0x2c, + 0x02, 0x25, 0x33, 0x24, 0x47, 0x1e, 0xaa, 0x16, 0xe0, 0x03, 0x75, 0xf7, + 0x9d, 0xf0, 0x49, 0xe9, 0xc8, 0xe6, 0xc0, 0xeb, 0xa7, 0xef, 0x0f, 0xed, + 0x37, 0xe4, 0x98, 0xd6, 0xf5, 0xdb, 0x7b, 0xde, 0xa8, 0xe1, 0x56, 0xe9, + 0x41, 0xdc, 0xa0, 0xda, 0x6b, 0xe3, 0xac, 0xdf, 0xbb, 0xde, 0xcf, 0xe3, + 0xa0, 0xde, 0x1b, 0xd9, 0xd2, 0xd9, 0xd7, 0xd9, 0xd1, 0xde, 0x61, 0xe1, + 0xa4, 0xdb, 0x38, 0xdf, 0xe9, 0xeb, 0x66, 0xf2, 0x04, 0x04, 0xb3, 0x0f, + 0xf8, 0x05, 0x5c, 0x06, 0x9a, 0x09, 0x5e, 0x06, 0x62, 0x02, 0x0e, 0xf7, + 0x71, 0xe7, 0xae, 0xd7, 0xad, 0xcc, 0x19, 0xd4, 0x68, 0xe0, 0x5c, 0xdd, + 0x32, 0xdd, 0xfe, 0xe4, 0xf8, 0xe4, 0xaa, 0xe7, 0x68, 0xfc, 0xdd, 0x17, + 0xa4, 0x1b, 0xfc, 0x13, 0x2a, 0x17, 0x4d, 0x0a, 0x0c, 0x03, 0x07, 0x0e, + 0xda, 0x11, 0xb7, 0x1c, 0xcd, 0x21, 0x81, 0x20, 0x96, 0x1c, 0x78, 0x12, + 0xd9, 0x20, 0x9f, 0x2b, 0x5e, 0x28, 0xc1, 0x2f, 0x7b, 0x26, 0x57, 0x18, + 0x23, 0x10, 0x05, 0x07, 0x02, 0x03, 0x8c, 0xf8, 0x54, 0xf5, 0xe1, 0xf1, + 0xfe, 0xeb, 0xb5, 0xf2, 0x07, 0xfa, 0x54, 0xf9, 0x3a, 0xf4, 0xb0, 0xfa, + 0x69, 0x00, 0x07, 0x0b, 0x28, 0x1b, 0xed, 0x23, 0xc6, 0x2f, 0x23, 0x2f, + 0x57, 0x32, 0xba, 0x39, 0x41, 0x30, 0x02, 0x26, 0x2d, 0x1b, 0x81, 0x0c, + 0xc8, 0x02, 0x43, 0xfb, 0x5b, 0xee, 0x83, 0xe9, 0x0c, 0xe6, 0x5d, 0xe3, + 0x40, 0xea, 0xd8, 0xe8, 0x04, 0xf1, 0x5a, 0x04, 0x5e, 0x0a, 0x3a, 0x09, + 0xc7, 0x0b, 0xd8, 0x0b, 0x70, 0x09, 0xbc, 0x15, 0x9e, 0x1e, 0xea, 0x1b, + 0xf0, 0x1f, 0xd4, 0x1b, 0x1e, 0x19, 0x49, 0x24, 0x98, 0x23, 0x77, 0x23, + 0x74, 0x2c, 0xb6, 0x2b, 0x53, 0x36, 0xbd, 0x45, 0xf3, 0x49, 0xd6, 0x51, + 0x6b, 0x50, 0x00, 0x4e, 0x24, 0x51, 0x43, 0x4d, 0xc1, 0x4d, 0xd6, 0x4a, + 0xda, 0x40, 0x73, 0x3f, 0x37, 0x42, 0xec, 0x46, 0x5c, 0x4d, 0xf5, 0x4a, + 0x41, 0x51, 0x6c, 0x59, 0x57, 0x55, 0x35, 0x5a, 0x04, 0x5a, 0xb5, 0x51, + 0x44, 0x47, 0x5f, 0x37, 0x1e, 0x2e, 0x97, 0x28, 0x53, 0x24, 0x34, 0x21, + 0xfd, 0x17, 0x5d, 0x0a, 0xc8, 0x07, 0x8b, 0x07, 0xc1, 0x06, 0x2f, 0x0e, + 0x3b, 0x0e, 0xec, 0x0a, 0x74, 0x09, 0x92, 0x03, 0x70, 0x03, 0x1c, 0x0f, + 0x51, 0x13, 0x77, 0x0d, 0x39, 0x05, 0xc6, 0xf8, 0x5b, 0xf9, 0x3c, 0xfd, + 0xc3, 0xfa, 0x31, 0x00, 0x59, 0xfc, 0x10, 0xf0, 0x5b, 0xf7, 0x35, 0x03, + 0x55, 0x04, 0x79, 0x08, 0xaa, 0x0e, 0xc1, 0x12, 0x10, 0x1b, 0x21, 0x2a, + 0xe0, 0x34, 0x49, 0x40, 0x4f, 0x4d, 0x1e, 0x4e, 0x85, 0x53, 0x21, 0x5a, + 0x7f, 0x4c, 0x9c, 0x37, 0xa9, 0x24, 0xdc, 0x11, 0x8f, 0x07, 0x65, 0x0d, + 0x02, 0x1c, 0x96, 0x19, 0xe5, 0x03, 0xf9, 0xf8, 0xfe, 0xf7, 0x69, 0xf6, + 0x7e, 0x02, 0x35, 0x21, 0x80, 0x34, 0x03, 0x20, 0xb3, 0x12, 0x49, 0x17, + 0x90, 0x07, 0xd1, 0x06, 0xdf, 0x15, 0x72, 0x1e, 0xc4, 0x23, 0x2d, 0x21, + 0x7d, 0x28, 0x3f, 0x2a, 0xc7, 0x28, 0x07, 0x34, 0x42, 0x2e, 0xb4, 0x2b, + 0x05, 0x32, 0xf6, 0x29, 0xb5, 0x21, 0xd9, 0x10, 0x6c, 0xff, 0x07, 0xf7, + 0x52, 0xea, 0x4b, 0xe4, 0x7f, 0xe5, 0x87, 0xe9, 0xc5, 0xef, 0x5c, 0xf1, + 0x7e, 0xf2, 0x7d, 0xf9, 0xd8, 0xfa, 0xe7, 0xfa, 0xfc, 0x03, 0xb5, 0x05, + 0x0b, 0x04, 0x21, 0xf9, 0xd4, 0xed, 0x74, 0xf6, 0xf4, 0xf4, 0x1e, 0xf5, + 0x90, 0x04, 0x86, 0xf9, 0x94, 0xe7, 0x01, 0xeb, 0xb1, 0xe3, 0xa0, 0xe2, + 0xbc, 0xf8, 0x3b, 0x01, 0xf3, 0xfa, 0x90, 0xf2, 0x69, 0xe9, 0x20, 0xe8, + 0x44, 0xf0, 0xe0, 0xf1, 0x1b, 0xef, 0x1c, 0xf1, 0x76, 0xe6, 0x69, 0xe4, + 0xe4, 0xf2, 0x29, 0xf2, 0x84, 0xf1, 0xb1, 0xf5, 0xda, 0xef, 0xb7, 0xf5, + 0xf2, 0x08, 0xf6, 0x0f, 0x67, 0x19, 0x47, 0x1e, 0xd2, 0x19, 0x2c, 0x24, + 0x3f, 0x25, 0x11, 0x2a, 0x51, 0x2f, 0x5d, 0x26, 0xa1, 0x28, 0x9c, 0x23, + 0x0a, 0x1e, 0x88, 0x1d, 0xd1, 0x1a, 0xf9, 0x18, 0xfe, 0x19, 0x15, 0x1e, + 0xf0, 0x20, 0x2a, 0x24, 0x8c, 0x1e, 0xcd, 0x20, 0x83, 0x21, 0x4e, 0x1e, + 0x0e, 0x23, 0xff, 0x1e, 0x42, 0x1b, 0x3e, 0x0f, 0xc0, 0x02, 0xc7, 0x01, + 0xe8, 0xfe, 0x2a, 0xfc, 0x6b, 0xf8, 0x62, 0xee, 0x3d, 0xe7, 0x36, 0xeb, + 0x79, 0xe8, 0xea, 0xe8, 0xfa, 0xf2, 0x88, 0xf3, 0xcb, 0xec, 0xf2, 0xde, + 0x2e, 0xd6, 0xb6, 0xdb, 0x34, 0xdf, 0x9f, 0xde, 0x3a, 0xdd, 0x44, 0xd4, + 0xf9, 0xc8, 0x18, 0xc8, 0xd5, 0xd0, 0x25, 0xd5, 0x57, 0xdb, 0x95, 0xe3, + 0xc2, 0xdd, 0xff, 0xe4, 0xab, 0xf4, 0xef, 0xf9, 0xe8, 0x06, 0x8c, 0x0a, + 0x51, 0x12, 0xb2, 0x2a, 0x5b, 0x34, 0xe2, 0x3f, 0x0b, 0x50, 0x9b, 0x4e, + 0x7e, 0x47, 0x27, 0x3e, 0x89, 0x33, 0xe0, 0x20, 0xb1, 0x01, 0xd0, 0xed, + 0xb6, 0xe4, 0x29, 0xe2, 0x54, 0xe0, 0xd4, 0xd6, 0x27, 0xd4, 0x5f, 0xd5, + 0x1c, 0xd4, 0x18, 0xdd, 0x75, 0xf4, 0x4f, 0x09, 0xe6, 0x10, 0xdd, 0x04, + 0x49, 0xfc, 0x59, 0x03, 0x80, 0xf8, 0xb3, 0xfa, 0xb7, 0x13, 0x2d, 0x15, + 0x5c, 0x12, 0x68, 0x22, 0x1b, 0x1d, 0x39, 0x08, 0xd5, 0x05, 0x70, 0x01, + 0xec, 0xfe, 0xf6, 0x08, 0x26, 0x12, 0x92, 0x07, 0x5d, 0xf3, 0xf1, 0xe0, + 0x61, 0xd4, 0x50, 0xd9, 0xaf, 0xd6, 0xc5, 0xdb, 0x18, 0xe1, 0x15, 0xd4, + 0x45, 0xc8, 0xce, 0xc2, 0xf7, 0xc5, 0x5c, 0xc6, 0xe2, 0xc8, 0x4e, 0xc2, + 0xad, 0xbf, 0x85, 0xc7, 0x32, 0xcf, 0x4e, 0xdf, 0xaa, 0xe0, 0xee, 0xe4, + 0x6f, 0xea, 0x58, 0xe3, 0xfd, 0xe9, 0x72, 0xfc, 0xf4, 0xff, 0x4d, 0xf5, + 0x93, 0xea, 0xc9, 0xcf, 0xa5, 0xc2, 0x98, 0xca, 0xbb, 0xc6, 0x6d, 0xcc, + 0x86, 0xd0, 0x28, 0xc2, 0x30, 0xc1, 0x42, 0xc5, 0xcb, 0xc1, 0x3a, 0xcb, + 0xdf, 0xd2, 0xe3, 0xd7, 0x2f, 0xdf, 0x7f, 0xe0, 0x5b, 0xeb, 0x54, 0xf0, + 0xb5, 0xf0, 0x46, 0xf9, 0xee, 0xfd, 0xf1, 0x03, 0xf5, 0x08, 0x18, 0x0c, + 0x89, 0x0d, 0xe0, 0x11, 0x9d, 0x16, 0x3b, 0x18, 0x44, 0x1f, 0xe3, 0x1f, + 0x5f, 0x1f, 0x33, 0x1d, 0x4c, 0x14, 0xd9, 0x0f, 0x56, 0x0a, 0xb8, 0x03, + 0x3c, 0x00, 0x2f, 0xfc, 0xc6, 0xf5, 0x88, 0xf3, 0xf4, 0xf9, 0xb2, 0xff, + 0x16, 0x00, 0x7f, 0x04, 0x8c, 0x07, 0xd8, 0x06, 0x20, 0xff, 0x1f, 0xef, + 0xa8, 0xeb, 0xba, 0xf2, 0xf3, 0xfc, 0x52, 0xfa, 0xa0, 0xed, 0xd4, 0xe4, + 0x1a, 0xd6, 0x75, 0xcb, 0x6a, 0xcd, 0x4d, 0xd6, 0x9e, 0xd6, 0x83, 0xcf, + 0x61, 0xc1, 0xa4, 0xb6, 0x87, 0xbf, 0xd6, 0xca, 0x64, 0xd5, 0xd1, 0xd8, + 0xd1, 0xd5, 0x3d, 0xd6, 0xaf, 0xd5, 0x7e, 0xd6, 0xe9, 0xdc, 0x8f, 0xe3, + 0x3c, 0xe7, 0x29, 0xec, 0x68, 0xf8, 0xca, 0x08, 0x3d, 0x13, 0xe0, 0x1f, + 0xbb, 0x23, 0x00, 0x2b, 0x0e, 0x41, 0x4f, 0x53, 0x7f, 0x6a, 0xf0, 0x6b, + 0xbd, 0x63, 0xd9, 0x59, 0x96, 0x38, 0x11, 0x2d, 0xe6, 0x22, 0xa3, 0x0c, + 0x52, 0x03, 0x9d, 0xf3, 0x4a, 0xe5, 0xbc, 0xdc, 0xd8, 0xdc, 0xfd, 0xe2, + 0x3f, 0xe6, 0x6c, 0xe8, 0xf4, 0xeb, 0x46, 0x02, 0xc0, 0x16, 0x44, 0x18, + 0x7a, 0x12, 0x77, 0x0f, 0xa5, 0x09, 0x05, 0x01, 0xb2, 0x0f, 0x21, 0x18, + 0x0f, 0x10, 0x2e, 0x12, 0x2e, 0x11, 0xca, 0x04, 0xb3, 0xfc, 0x83, 0x07, + 0x8f, 0x0a, 0xc8, 0x07, 0x9e, 0x11, 0xbd, 0x0c, 0xf6, 0x03, 0x06, 0x05, + 0x49, 0x03, 0xb3, 0x00, 0xa4, 0xf6, 0xbc, 0xe3, 0x60, 0xd5, 0x9e, 0xcd, + 0x59, 0xc4, 0x2b, 0xc8, 0xb3, 0xcd, 0x7d, 0xc5, 0xfb, 0xca, 0x87, 0xd0, + 0xaf, 0xce, 0xe8, 0xdb, 0x01, 0xf1, 0x4c, 0xfb, 0x91, 0x02, 0xf6, 0x15, + 0x95, 0x27, 0xd7, 0x28, 0x44, 0x26, 0xe2, 0x26, 0x96, 0x1a, 0xfb, 0x14, + 0x73, 0x10, 0xdc, 0x08, 0x3b, 0x07, 0xbf, 0xf2, 0xbc, 0xf0, 0x56, 0xf4, + 0x49, 0xe8, 0x9c, 0xed, 0x73, 0xf5, 0x60, 0xf7, 0xf0, 0xf8, 0x96, 0xfc, + 0x61, 0xff, 0xd4, 0x0a, 0xa8, 0x0e, 0xd2, 0x0b, 0xa3, 0x16, 0x16, 0x13, + 0x21, 0x14, 0x08, 0x18, 0x2e, 0x12, 0xf4, 0x14, 0x9a, 0x18, 0x1e, 0x1d, + 0x8f, 0x1d, 0x79, 0x24, 0xd3, 0x26, 0xe7, 0x23, 0x9d, 0x2a, 0x88, 0x28, + 0x8a, 0x28, 0xd6, 0x25, 0xbe, 0x1d, 0xb0, 0x16, 0x3d, 0x10, 0x26, 0x0c, + 0xbd, 0x03, 0x58, 0x01, 0x0f, 0xff, 0x37, 0xfe, 0x85, 0x02, 0x57, 0x06, + 0xb6, 0x0a, 0xc3, 0x0e, 0x1c, 0x16, 0x3b, 0x1e, 0xc6, 0x23, 0x29, 0x1c, + 0x13, 0x13, 0x2a, 0x11, 0x14, 0x09, 0x2e, 0x02, 0x4b, 0xfd, 0xad, 0xf3, + 0x11, 0xea, 0x97, 0xdf, 0xb2, 0xd2, 0x17, 0xcf, 0xcd, 0xd1, 0x7e, 0xd6, + 0x57, 0xdf, 0xae, 0xdc, 0x7c, 0xd7, 0xdc, 0xdd, 0x8c, 0xdf, 0x3b, 0xe0, + 0xed, 0xe8, 0xfa, 0xee, 0x35, 0xf5, 0x65, 0xfb, 0x1b, 0xfb, 0x5d, 0xff, + 0x62, 0x06, 0x4b, 0x0a, 0xc1, 0x12, 0xc1, 0x19, 0xb4, 0x24, 0xfb, 0x2d, + 0x2a, 0x30, 0x59, 0x37, 0xf8, 0x3e, 0xff, 0x52, 0x43, 0x5d, 0x8a, 0x56, + 0x93, 0x54, 0x94, 0x43, 0x96, 0x32, 0x4b, 0x26, 0x93, 0x13, 0xa1, 0x05, + 0xe4, 0xfa, 0x72, 0xec, 0xc1, 0xdf, 0x2b, 0xdf, 0x12, 0xde, 0x9a, 0xe1, + 0x3f, 0xed, 0x82, 0xf9, 0x74, 0x07, 0x3f, 0x16, 0x83, 0x2e, 0xaf, 0x29, + 0x50, 0x11, 0xa0, 0x13, 0x6c, 0x0e, 0x61, 0x00, 0xe9, 0x00, 0x9a, 0x0a, + 0x05, 0x09, 0x15, 0x07, 0x05, 0x10, 0xc2, 0x07, 0x10, 0x04, 0x04, 0x0d, + 0x21, 0x10, 0xd7, 0x0f, 0x6b, 0x14, 0xa1, 0x16, 0xf2, 0x05, 0x6e, 0xf5, + 0x97, 0xe1, 0xbf, 0xcb, 0xc1, 0xc0, 0xbb, 0xbf, 0xeb, 0xc8, 0x07, 0xc8, + 0xfd, 0xc2, 0x90, 0xc3, 0xab, 0xc0, 0x3a, 0xbf, 0x74, 0xcb, 0x8f, 0xd9, + 0x66, 0xe0, 0x45, 0xf7, 0xa6, 0x0a, 0xfb, 0x0b, 0x28, 0x15, 0x3a, 0x15, + 0xa0, 0x10, 0xb0, 0x19, 0xe2, 0x11, 0xf3, 0x0c, 0xfd, 0x0d, 0x65, 0xf5, + 0xd7, 0xf1, 0x7e, 0xf4, 0x45, 0xe2, 0xa9, 0xe3, 0xa6, 0xe5, 0xa7, 0xe2, + 0x05, 0xeb, 0xb8, 0xf2, 0x4a, 0xf4, 0xa9, 0xf5, 0x99, 0xfb, 0xbf, 0xfb, + 0xd7, 0xfa, 0xe0, 0xfb, 0x72, 0xfe, 0xfe, 0x01, 0xa4, 0x04, 0x56, 0x0a, + 0xc0, 0x09, 0x53, 0x0a, 0x81, 0x0e, 0x40, 0x0f, 0x38, 0x12, 0xd7, 0x17, + 0x41, 0x1a, 0x34, 0x19, 0xff, 0x15, 0x58, 0x0f, 0xb1, 0x10, 0x0f, 0x11, + 0x5c, 0x08, 0xfd, 0x03, 0x85, 0xff, 0x13, 0xf8, 0x99, 0xf7, 0xfa, 0xfa, + 0xa4, 0xf9, 0xa2, 0xfa, 0x80, 0xfa, 0xf6, 0xf8, 0x0e, 0x00, 0x41, 0x0e, + 0x56, 0x1a, 0x09, 0x1d, 0xf9, 0x20, 0x64, 0x22, 0xb2, 0x18, 0xd3, 0x0d, + 0xfe, 0x07, 0x90, 0x00, 0x64, 0xf6, 0xfb, 0xef, 0x64, 0xe4, 0xa0, 0xdc, + 0x99, 0xdc, 0x47, 0xd4, 0xc1, 0xd2, 0x7d, 0xd8, 0xe8, 0xda, 0xc1, 0xe3, + 0xdf, 0xe2, 0x76, 0xd9, 0x57, 0xdd, 0x3d, 0xe5, 0x91, 0xf0, 0x3f, 0xff, + 0x38, 0x09, 0x26, 0x0e, 0xc6, 0x0a, 0x30, 0x0d, 0x52, 0x19, 0x9c, 0x24, + 0xe2, 0x2f, 0x0d, 0x32, 0x98, 0x2b, 0xd6, 0x27, 0xac, 0x33, 0x8b, 0x46, + 0x17, 0x45, 0xc6, 0x3f, 0x5c, 0x3e, 0xc1, 0x3f, 0x79, 0x4f, 0x62, 0x54, + 0x91, 0x49, 0x9c, 0x3b, 0x64, 0x17, 0x48, 0xf3, 0x11, 0xf0, 0x52, 0xef, + 0x62, 0xef, 0xea, 0xf1, 0xc3, 0xe1, 0x3a, 0xd0, 0x36, 0xcd, 0x7f, 0xdf, + 0x6a, 0xf7, 0x03, 0x07, 0x2c, 0x17, 0xf6, 0x1e, 0x1d, 0x13, 0x13, 0x06, + 0x86, 0x0d, 0xaa, 0x0e, 0x6d, 0x06, 0xee, 0x0c, 0x2b, 0x13, 0xd5, 0x0c, + 0x20, 0x07, 0x6b, 0x0e, 0xd9, 0x11, 0x11, 0x11, 0x71, 0x10, 0x90, 0x04, + 0x8b, 0xfb, 0x98, 0xf3, 0x1c, 0xee, 0x96, 0xe3, 0x19, 0xce, 0x37, 0xc9, + 0xea, 0xc3, 0xef, 0xbc, 0x1c, 0xc5, 0x35, 0xc6, 0xf0, 0xbd, 0x1c, 0xc1, + 0xb0, 0xcc, 0x8e, 0xcc, 0x8e, 0xd2, 0xc7, 0xe6, 0x23, 0xea, 0x65, 0xef, + 0xb5, 0xfe, 0x03, 0xfc, 0x3f, 0x05, 0xd7, 0x10, 0x35, 0x11, 0x1d, 0x21, + 0x78, 0x18, 0x0a, 0x0a, 0x0c, 0x15, 0xd8, 0x0a, 0x7f, 0xfc, 0x76, 0xff, + 0x39, 0xf1, 0xf7, 0xe8, 0x73, 0xf0, 0xc4, 0xe8, 0x4a, 0xec, 0x12, 0xf0, + 0x4a, 0xed, 0x15, 0xf2, 0xdc, 0xee, 0x14, 0xf5, 0xf7, 0x00, 0x4d, 0x03, + 0xd2, 0xff, 0x55, 0x01, 0x73, 0x03, 0xd3, 0x03, 0x10, 0x0a, 0x71, 0x05, + 0x2f, 0x04, 0x8d, 0x09, 0x17, 0x09, 0xd9, 0x09, 0xa3, 0x06, 0x30, 0x00, + 0x4e, 0xfb, 0x6d, 0xfa, 0x49, 0xf9, 0x1c, 0xf9, 0x98, 0xf7, 0x2a, 0xf0, + 0x49, 0xee, 0x53, 0xea, 0xca, 0xe5, 0xfe, 0xe8, 0xf2, 0xe9, 0x1a, 0xea, + 0xaa, 0xea, 0xf7, 0xef, 0x0e, 0xf7, 0xbf, 0xf6, 0x73, 0xfb, 0x82, 0x01, + 0xfa, 0x04, 0x13, 0x0b, 0x44, 0x04, 0x43, 0xf9, 0x1a, 0xf5, 0x65, 0xef, + 0x39, 0xea, 0x75, 0xe3, 0x34, 0xda, 0x81, 0xd4, 0xbf, 0xd6, 0xfc, 0xce, + 0xe9, 0xc4, 0x23, 0xc7, 0x29, 0xc2, 0xd6, 0xc4, 0x40, 0xca, 0x91, 0xca, + 0x3b, 0xd6, 0x9d, 0xdd, 0xf7, 0xda, 0xfb, 0xd4, 0x21, 0xdc, 0x19, 0xed, + 0x47, 0xf6, 0xe5, 0x00, 0x57, 0x04, 0x46, 0xff, 0xbe, 0xff, 0x4b, 0x05, + 0xcd, 0x12, 0xd5, 0x1e, 0x99, 0x1f, 0x59, 0x22, 0xb3, 0x21, 0xb2, 0x1e, + 0xb1, 0x33, 0xff, 0x48, 0xa6, 0x48, 0x67, 0x44, 0x82, 0x39, 0x26, 0x28, + 0xa3, 0x10, 0xdb, 0xf6, 0xdf, 0xee, 0xa9, 0xe9, 0x89, 0xda, 0xd5, 0xd2, + 0x44, 0xce, 0x5a, 0xc2, 0x63, 0xbf, 0x25, 0xd0, 0x34, 0xd5, 0xe9, 0xdb, + 0xec, 0xff, 0xe1, 0x0e, 0x07, 0x06, 0x48, 0x02, 0x70, 0x04, 0x72, 0x02, + 0xbc, 0xf9, 0x54, 0x09, 0x6e, 0x19, 0xe5, 0x16, 0x04, 0x16, 0x1e, 0x19, + 0xd6, 0x0f, 0x4a, 0x03, 0x3f, 0x11, 0x88, 0x09, 0x27, 0xfa, 0x45, 0xfb, + 0x07, 0xe3, 0x37, 0xd5, 0x34, 0xcf, 0x7d, 0xcc, 0x68, 0xd6, 0x5e, 0xcd, + 0xb6, 0xc2, 0x03, 0xca, 0xe9, 0xcf, 0x51, 0xcf, 0xc9, 0xe7, 0x7b, 0xf4, + 0x6c, 0xee, 0x00, 0xff, 0x4a, 0xff, 0x57, 0x01, 0x7d, 0x10, 0x4e, 0x1b, + 0x7a, 0x29, 0x9a, 0x2f, 0x89, 0x35, 0x8e, 0x39, 0xfa, 0x3d, 0x96, 0x38, + 0xdb, 0x34, 0xda, 0x39, 0xdf, 0x28, 0x99, 0x22, 0x72, 0x25, 0x72, 0x1b, + 0x26, 0x1e, 0xbd, 0x1e, 0x4b, 0x19, 0x4b, 0x1d, 0x72, 0x1d, 0xb3, 0x1c, + 0x27, 0x22, 0xf0, 0x23, 0x40, 0x25, 0x4c, 0x29, 0xc0, 0x27, 0x9f, 0x28, + 0x5a, 0x2b, 0x9f, 0x29, 0xbe, 0x28, 0x86, 0x26, 0xba, 0x2a, 0x97, 0x31, + 0x1e, 0x33, 0x9c, 0x30, 0xb3, 0x2e, 0x39, 0x2e, 0xe5, 0x27, 0xb2, 0x22, + 0xa7, 0x20, 0xaf, 0x23, 0xf9, 0x23, 0xa0, 0x22, 0x9f, 0x23, 0xfa, 0x1a, + 0x9c, 0x15, 0xc9, 0x16, 0x9a, 0x19, 0xad, 0x1b, 0x01, 0x1d, 0xa6, 0x1e, + 0xfd, 0x1b, 0x42, 0x1d, 0x6e, 0x23, 0xb6, 0x29, 0x04, 0x28, 0x29, 0x25, + 0x21, 0x28, 0x39, 0x20, 0xe1, 0x19, 0xb5, 0x15, 0xbb, 0x09, 0x6d, 0x03, + 0x85, 0xff, 0xf9, 0x00, 0x16, 0x02, 0xc4, 0xfc, 0xc9, 0xf4, 0x63, 0xf2, + 0x85, 0xf7, 0x89, 0xf7, 0x74, 0x01, 0xd3, 0x0e, 0xe1, 0x0f, 0x38, 0x0c, + 0xf5, 0x06, 0xa6, 0x03, 0x2f, 0x08, 0xb9, 0x14, 0x08, 0x20, 0xad, 0x21, + 0x61, 0x1b, 0x70, 0x1b, 0xcf, 0x1a, 0x09, 0x1b, 0x05, 0x2c, 0xbd, 0x37, + 0xea, 0x30, 0xbe, 0x2f, 0x57, 0x37, 0x95, 0x43, 0x29, 0x4d, 0xd2, 0x4b, + 0x36, 0x57, 0x1d, 0x4f, 0xc5, 0x37, 0xa6, 0x31, 0xbf, 0x1f, 0xc5, 0x0d, + 0x1e, 0x00, 0x51, 0xf6, 0x06, 0xf0, 0x4c, 0xe4, 0x62, 0xdb, 0x85, 0xd8, + 0x6d, 0xde, 0x5a, 0xe2, 0x18, 0xe7, 0xef, 0xfd, 0x1a, 0x18, 0xae, 0x15, + 0x81, 0x10, 0x01, 0x1d, 0xf9, 0x0f, 0xfa, 0x00, 0xb7, 0x14, 0x19, 0x1f, + 0x3f, 0x17, 0x52, 0x16, 0x41, 0x12, 0x8a, 0x03, 0x06, 0xfe, 0x36, 0x06, + 0xe1, 0xfe, 0x25, 0xf0, 0x08, 0xed, 0x3e, 0xde, 0xea, 0xce, 0x1d, 0xd1, + 0x17, 0xd2, 0xfa, 0xd3, 0xf3, 0xce, 0xa9, 0xc3, 0x3e, 0xc7, 0x42, 0xcc, + 0xb8, 0xd9, 0xd2, 0xe8, 0xfa, 0xe1, 0xbc, 0xe2, 0x2a, 0xe7, 0xb8, 0xe2, + 0x15, 0xf4, 0xfb, 0x00, 0xa2, 0x05, 0xc7, 0x12, 0xa2, 0x0c, 0x34, 0x14, + 0xaa, 0x23, 0x79, 0x20, 0x9c, 0x21, 0x05, 0x21, 0x31, 0x1a, 0x14, 0x0f, + 0x7e, 0x05, 0x7f, 0x01, 0xa6, 0xff, 0x17, 0xfb, 0x81, 0xf9, 0xe3, 0xf5, + 0xa1, 0xf2, 0x37, 0xf9, 0x12, 0xfa, 0x85, 0xfd, 0xdd, 0x06, 0xef, 0x0b, + 0x1e, 0x0c, 0xd8, 0x0f, 0x2e, 0x11, 0x97, 0x10, 0x76, 0x15, 0xe2, 0x0f, + 0xd5, 0x0a, 0xc0, 0x0b, 0x1c, 0x0d, 0x66, 0x0b, 0x4f, 0x0c, 0x8d, 0x0d, + 0x1c, 0x05, 0x08, 0x05, 0x8a, 0x01, 0x81, 0xfe, 0xf4, 0x03, 0x80, 0x01, + 0x87, 0x01, 0xd5, 0x00, 0xa4, 0xfe, 0x58, 0xfc, 0xb4, 0xfa, 0xcb, 0x00, + 0x96, 0x01, 0x83, 0x02, 0x2f, 0x07, 0x95, 0x04, 0xe9, 0x02, 0xdf, 0x08, + 0xce, 0x0c, 0x4a, 0x0f, 0x48, 0x14, 0xea, 0x11, 0xd7, 0x10, 0xe6, 0x0f, + 0x35, 0x10, 0xa5, 0x15, 0xd0, 0x12, 0x30, 0x0d, 0x83, 0x01, 0xcc, 0xf3, + 0xac, 0xef, 0x53, 0xf5, 0x30, 0xf9, 0x44, 0xf7, 0xfd, 0xf3, 0x6f, 0xed, + 0xbb, 0xeb, 0xdc, 0xec, 0xb5, 0xf8, 0xd2, 0x07, 0x95, 0x0b, 0x23, 0x0a, + 0x7e, 0x02, 0xec, 0x05, 0x41, 0x13, 0xce, 0x12, 0xfd, 0x0a, 0x3b, 0x01, + 0xf5, 0xff, 0x54, 0x0a, 0x41, 0x0e, 0x11, 0x17, 0x1d, 0x1b, 0xb1, 0x12, + 0xd8, 0x12, 0x57, 0x23, 0x43, 0x33, 0xa7, 0x37, 0x0d, 0x34, 0xd0, 0x13, + 0x5b, 0xfb, 0xe0, 0xec, 0xf2, 0xd8, 0x4c, 0xe2, 0xfd, 0xe5, 0x66, 0xda, + 0x6d, 0xcb, 0x26, 0xb7, 0xbb, 0xb5, 0xfb, 0xc5, 0x7f, 0xd2, 0xfd, 0xe9, + 0xb0, 0x06, 0x05, 0x04, 0xc9, 0xfc, 0x7c, 0x04, 0xe1, 0x05, 0xde, 0x01, + 0x1c, 0x09, 0x69, 0x11, 0xe4, 0x0f, 0x83, 0x0e, 0x28, 0x0d, 0x5d, 0x04, + 0x2f, 0xef, 0x01, 0xe2, 0x2f, 0xe1, 0x57, 0xd8, 0xee, 0xd5, 0x61, 0xdc, + 0x03, 0xd7, 0x4f, 0xcd, 0x70, 0xc5, 0x9d, 0xbf, 0x40, 0xbf, 0x16, 0xc5, + 0x7d, 0xc5, 0x40, 0xcd, 0x38, 0xdc, 0xfa, 0xd5, 0x77, 0xda, 0x38, 0xd7, + 0xfc, 0xce, 0x4a, 0xde, 0x55, 0xe0, 0xa7, 0xe5, 0xcf, 0xf0, 0xb8, 0xee, + 0x7a, 0xee, 0x28, 0xfe, 0x2d, 0x00, 0xc7, 0xfc, 0xab, 0x01, 0xa6, 0xf5, + 0x76, 0xf2, 0xb2, 0xef, 0x6e, 0xea, 0xdc, 0xeb, 0xf2, 0xe7, 0xda, 0xdf, + 0xf2, 0xd7, 0x7b, 0xd5, 0xf2, 0xd4, 0x9f, 0xe0, 0x35, 0xe8, 0x05, 0xe9, + 0x65, 0xee, 0xe2, 0xec, 0xe4, 0xee, 0x7d, 0xf5, 0xce, 0xfa, 0xb5, 0xfe, + 0xf6, 0xfe, 0xe8, 0xfc, 0xe5, 0xf6, 0x9f, 0xf2, 0xf8, 0xf2, 0xc4, 0xf5, + 0xd9, 0xf5, 0x9b, 0xef, 0xc9, 0xed, 0x14, 0xed, 0x48, 0xed, 0x1f, 0xee, + 0x04, 0xf3, 0xa6, 0xf8, 0xed, 0xf4, 0x00, 0xf7, 0x1b, 0xf5, 0x21, 0xf2, + 0x07, 0xf9, 0x31, 0x02, 0xfa, 0x05, 0xcd, 0x06, 0x58, 0x09, 0x96, 0x05, + 0x2f, 0x08, 0x4c, 0x0d, 0xbf, 0x10, 0x34, 0x14, 0xeb, 0x13, 0xc7, 0x12, + 0x1f, 0x12, 0x40, 0x10, 0x3d, 0x12, 0xaf, 0x14, 0x41, 0x06, 0xfd, 0x02, + 0xb1, 0xfd, 0x50, 0xee, 0xc7, 0xef, 0xd5, 0xec, 0xb3, 0xe9, 0xbd, 0xe5, + 0x6b, 0xe5, 0x05, 0xf0, 0xc5, 0xee, 0x14, 0xed, 0x78, 0xf4, 0xa0, 0xf7, + 0x85, 0xfc, 0x3b, 0x02, 0x44, 0x07, 0x0b, 0x0c, 0xde, 0x0c, 0xad, 0x11, + 0x40, 0x0e, 0xf6, 0x0a, 0x6b, 0x14, 0x2c, 0x1b, 0x5f, 0x19, 0x75, 0x1a, + 0x8c, 0x22, 0x9a, 0x25, 0x8b, 0x29, 0xb4, 0x2d, 0xf6, 0x39, 0x0b, 0x43, + 0x5a, 0x30, 0x40, 0x11, 0x98, 0xf7, 0x28, 0xea, 0x0d, 0xe4, 0x3f, 0xe9, + 0x2d, 0xec, 0xe6, 0xe3, 0xbe, 0xcd, 0x81, 0xb4, 0x9f, 0xc0, 0x0d, 0xd4, + 0x46, 0xe1, 0x1f, 0x00, 0xd4, 0x16, 0xa8, 0x0c, 0x2b, 0x01, 0x94, 0x17, + 0xfd, 0x25, 0x44, 0x24, 0x3b, 0x2f, 0xd2, 0x34, 0x99, 0x28, 0x4a, 0x1e, + 0x3a, 0x22, 0xd3, 0x1a, 0x12, 0x0c, 0xfd, 0x01, 0x3c, 0xf7, 0xc0, 0xf1, + 0x49, 0xeb, 0x27, 0xed, 0x4a, 0xed, 0x90, 0xe2, 0xe8, 0xd7, 0x00, 0xcf, + 0xc4, 0xd3, 0x51, 0xd1, 0x33, 0xd4, 0x6d, 0xec, 0x6d, 0xe8, 0x73, 0xe6, + 0x9a, 0xf0, 0xce, 0xde, 0x79, 0xec, 0x98, 0xfe, 0x32, 0xf3, 0x59, 0x03, + 0xa2, 0x01, 0x1d, 0xfa, 0x4f, 0x11, 0xca, 0x18, 0x6a, 0x1e, 0xa0, 0x24, + 0xa6, 0x16, 0x11, 0x10, 0xb2, 0x12, 0x1d, 0x0a, 0xae, 0x09, 0xcf, 0x05, + 0x48, 0xf5, 0x3c, 0xed, 0x8a, 0xea, 0xee, 0xe9, 0x55, 0xec, 0x6f, 0xf5, + 0x66, 0xf4, 0xc4, 0xf5, 0x76, 0xfe, 0x48, 0x01, 0xf5, 0x0d, 0x5b, 0x12, + 0x1e, 0x16, 0xcf, 0x1a, 0x8f, 0x15, 0x8e, 0x15, 0x44, 0x15, 0x25, 0x12, + 0x75, 0x0b, 0x41, 0x0c, 0xf4, 0x0e, 0x39, 0x0c, 0x5a, 0x0d, 0x3d, 0x0a, + 0xd4, 0x09, 0x54, 0x06, 0xdb, 0x03, 0xe5, 0x0c, 0x9b, 0x0e, 0x0e, 0x0d, + 0xb6, 0x0b, 0xc6, 0x0a, 0x0e, 0x0c, 0x01, 0x0f, 0x29, 0x16, 0x12, 0x1c, + 0x7a, 0x21, 0x7f, 0x21, 0xee, 0x1f, 0x8e, 0x21, 0xb2, 0x29, 0xfe, 0x2f, + 0x45, 0x2c, 0x7e, 0x31, 0x29, 0x33, 0xb4, 0x2c, 0x43, 0x30, 0xaa, 0x2e, + 0x73, 0x29, 0xf9, 0x2b, 0xe7, 0x21, 0x73, 0x15, 0x48, 0x10, 0x24, 0x07, + 0xc0, 0x06, 0xcd, 0x02, 0x96, 0xff, 0x25, 0x03, 0xe9, 0xf9, 0x81, 0xf5, + 0x86, 0xf9, 0x16, 0xfc, 0xb7, 0x02, 0x9b, 0x05, 0x35, 0x06, 0x61, 0x06, + 0x69, 0x05, 0x5c, 0x0a, 0x59, 0x0a, 0x2f, 0x07, 0x1e, 0x0e, 0xe3, 0x1f, + 0x91, 0x2c, 0xdf, 0x25, 0x90, 0x22, 0x9c, 0x2e, 0x2a, 0x31, 0x0e, 0x32, + 0xe5, 0x43, 0x23, 0x3f, 0x28, 0x23, 0x51, 0x0b, 0x7e, 0xf4, 0x93, 0xe4, + 0xb0, 0xdd, 0xbb, 0xe5, 0xf0, 0xee, 0x8e, 0xe1, 0xa8, 0xc8, 0x40, 0xcb, + 0x6f, 0xd4, 0x83, 0xd1, 0x78, 0xed, 0x5f, 0x17, 0xdd, 0x21, 0x4c, 0x10, + 0xc3, 0x11, 0x38, 0x18, 0x9c, 0x14, 0x3b, 0x23, 0x13, 0x37, 0x93, 0x41, + 0xab, 0x38, 0x91, 0x36, 0x87, 0x30, 0xb4, 0x17, 0x86, 0x0d, 0xec, 0x08, + 0x88, 0xfe, 0xf0, 0xff, 0x6f, 0x00, 0x56, 0xee, 0x7b, 0xe5, 0xda, 0xd6, + 0x47, 0xd0, 0x46, 0xd8, 0xee, 0xd3, 0x7a, 0xd5, 0x78, 0xda, 0x6a, 0xe3, + 0x4b, 0xe4, 0x96, 0xe8, 0xfb, 0xe0, 0x8e, 0xde, 0x29, 0xf3, 0x80, 0xeb, + 0xb6, 0xf8, 0x4d, 0x08, 0x0c, 0xfa, 0xc0, 0xfa, 0xe6, 0x07, 0x71, 0x11, + 0x10, 0x13, 0xe0, 0x0f, 0x29, 0x04, 0xbb, 0x01, 0x9a, 0xf8, 0x67, 0xf2, + 0x95, 0xf9, 0xe2, 0xe8, 0x2c, 0xe1, 0xc0, 0xe0, 0xe3, 0xd7, 0xe9, 0xda, + 0xf5, 0xe2, 0x44, 0xe6, 0x74, 0xe5, 0x8f, 0xeb, 0xc2, 0xee, 0x57, 0xf3, + 0x81, 0xf9, 0x1d, 0xfc, 0x86, 0x05, 0xf5, 0x05, 0x9d, 0x04, 0xa6, 0x06, + 0xa6, 0x02, 0x9c, 0xfe, 0x24, 0x05, 0xaf, 0x07, 0x9a, 0x00, 0xcd, 0x03, + 0xa0, 0x03, 0x6b, 0x05, 0xde, 0x02, 0xde, 0x00, 0xc8, 0x0b, 0x1f, 0x0d, + 0x6d, 0x0b, 0xbd, 0x08, 0xb3, 0x05, 0x9f, 0x02, 0x64, 0x05, 0x92, 0x0a, + 0xb8, 0x12, 0xb1, 0x18, 0x57, 0x14, 0x86, 0x15, 0xde, 0x13, 0xef, 0x18, + 0x20, 0x20, 0x3d, 0x22, 0x6a, 0x22, 0x33, 0x21, 0x1e, 0x22, 0xd7, 0x21, + 0x62, 0x24, 0x8c, 0x1b, 0x82, 0x18, 0x3c, 0x16, 0x96, 0x09, 0xc5, 0x00, + 0x7f, 0xf7, 0x0e, 0xf3, 0x70, 0xf0, 0x69, 0xf5, 0x9d, 0xfc, 0x6f, 0xf8, + 0x31, 0xeb, 0x68, 0xed, 0x1a, 0xff, 0x8a, 0x08, 0x62, 0x0e, 0x5b, 0x09, + 0x50, 0x08, 0x24, 0x08, 0x1f, 0x07, 0xaf, 0x12, 0x81, 0x13, 0x44, 0x19, + 0x3e, 0x1a, 0xc8, 0x11, 0x29, 0x1c, 0x4d, 0x26, 0xbd, 0x2e, 0xef, 0x35, + 0xf1, 0x35, 0xae, 0x36, 0xe1, 0x2a, 0x0c, 0x0d, 0xbb, 0xfb, 0x77, 0xf2, + 0x0d, 0xe0, 0xf6, 0xdb, 0x74, 0xd8, 0x3d, 0xd8, 0xb7, 0xd2, 0x57, 0xc3, + 0x80, 0xcb, 0x70, 0xcd, 0x1a, 0xd3, 0xcf, 0xf7, 0x13, 0x19, 0xa2, 0x15, + 0x1d, 0x12, 0x7a, 0x1f, 0x48, 0x17, 0x88, 0x19, 0xb7, 0x2f, 0x79, 0x43, + 0x1f, 0x40, 0x3b, 0x38, 0xbf, 0x40, 0x55, 0x2d, 0xeb, 0x22, 0x6c, 0x22, + 0xaf, 0x0a, 0x3a, 0xfc, 0xf3, 0xf6, 0x18, 0xf1, 0xb7, 0xe1, 0x69, 0xdc, + 0x6e, 0xda, 0x2b, 0xc9, 0xbc, 0xc4, 0xde, 0xc4, 0x53, 0xc7, 0x37, 0xcb, + 0xde, 0xd2, 0x97, 0xe4, 0xf5, 0xe5, 0x34, 0xe2, 0x36, 0xe5, 0x30, 0xe6, + 0x5f, 0xee, 0xd9, 0xf8, 0x8f, 0x01, 0xef, 0x09, 0x92, 0x06, 0x4a, 0x0a, + 0x5c, 0x1a, 0x9a, 0x15, 0x43, 0x0a, 0xa4, 0x0b, 0x24, 0xfe, 0x1d, 0xea, + 0x75, 0xe8, 0x25, 0xe1, 0x40, 0xd8, 0x67, 0xd6, 0x4b, 0xd0, 0x34, 0xce, + 0x7b, 0xce, 0xa2, 0xd3, 0xa4, 0xda, 0x0b, 0xdf, 0x7d, 0xe1, 0xcf, 0xe8, + 0x21, 0xf1, 0x4b, 0xf5, 0xed, 0xff, 0x26, 0x04, 0x4f, 0x08, 0x7b, 0x0a, + 0x74, 0x07, 0x15, 0x0e, 0x89, 0x11, 0x5a, 0x16, 0x1a, 0x17, 0x64, 0x0f, + 0xf9, 0x0b, 0x4b, 0x09, 0xe3, 0x07, 0x5f, 0x04, 0x86, 0x06, 0x78, 0x06, + 0x9e, 0xfe, 0x7c, 0x00, 0xe6, 0xf7, 0xfb, 0xea, 0xbe, 0xe8, 0x58, 0xef, + 0xb1, 0xfa, 0x0f, 0xfe, 0xbe, 0x05, 0x9d, 0x08, 0x99, 0x08, 0xd0, 0x12, + 0x8c, 0x1a, 0x61, 0x1c, 0x4f, 0x1e, 0x70, 0x22, 0x8a, 0x1f, 0x64, 0x1b, + 0xc4, 0x1b, 0xb9, 0x19, 0x7b, 0x19, 0x02, 0x1a, 0x3a, 0x0f, 0xe4, 0x03, + 0x9f, 0xfa, 0x27, 0xec, 0xed, 0xe6, 0xb1, 0xe2, 0x6b, 0xe2, 0xb2, 0xe5, + 0x8a, 0xda, 0xca, 0xcf, 0x73, 0xd1, 0x6c, 0xd2, 0x6c, 0xd1, 0x62, 0xd9, + 0x68, 0xdc, 0x44, 0xdb, 0xb9, 0xdc, 0xf2, 0xda, 0x1c, 0xde, 0xfc, 0xe3, + 0x00, 0xf0, 0xb1, 0x00, 0xb9, 0x05, 0xa0, 0x05, 0xa7, 0x0e, 0x47, 0x1b, + 0x4a, 0x27, 0xf6, 0x24, 0x62, 0x14, 0x1c, 0xfe, 0xd8, 0xe0, 0xe4, 0xd4, + 0xa3, 0xc8, 0xc3, 0xbf, 0xa2, 0xc8, 0xd8, 0xc2, 0xf9, 0xb5, 0x34, 0xad, + 0xbb, 0xb1, 0xa6, 0xbf, 0xf0, 0xce, 0x6b, 0xe6, 0xac, 0xfc, 0xa7, 0xfa, + 0x31, 0xf2, 0x4f, 0xfc, 0x2c, 0xff, 0xe2, 0x07, 0x74, 0x1c, 0xa7, 0x29, + 0x33, 0x2c, 0x55, 0x30, 0xe9, 0x40, 0x13, 0x42, 0xc0, 0x39, 0xf8, 0x43, + 0xe9, 0x40, 0x89, 0x29, 0x62, 0x28, 0xf0, 0x15, 0xea, 0xf8, 0xb5, 0xef, + 0xba, 0xda, 0x53, 0xd6, 0xb2, 0xd6, 0x9a, 0xca, 0x99, 0xc8, 0x60, 0xca, + 0x7c, 0xc7, 0x84, 0xce, 0xdb, 0xe0, 0x45, 0xeb, 0xc3, 0xf2, 0x02, 0xf8, + 0xf9, 0xf6, 0xe8, 0xf5, 0x57, 0x03, 0xe1, 0x0d, 0x1b, 0x12, 0x54, 0x1d, + 0x06, 0x19, 0x77, 0x16, 0x52, 0x16, 0x9b, 0x0c, 0x5d, 0x0a, 0xd4, 0xff, + 0xa4, 0xf5, 0xac, 0xef, 0xd3, 0xe1, 0x4b, 0xe0, 0x81, 0xe2, 0x5a, 0xe4, + 0x0b, 0xe8, 0x5b, 0xea, 0x3e, 0xe9, 0xe6, 0xec, 0x96, 0xf5, 0x03, 0xf5, + 0xc7, 0xff, 0x86, 0x08, 0x4f, 0x0e, 0x5e, 0x17, 0x16, 0x1b, 0x63, 0x1b, + 0xac, 0x20, 0x8d, 0x2f, 0x59, 0x34, 0xed, 0x3f, 0x78, 0x3f, 0x4a, 0x38, + 0x7c, 0x39, 0xcf, 0x36, 0x42, 0x37, 0xc0, 0x31, 0xe0, 0x34, 0x99, 0x33, + 0xc1, 0x31, 0x3e, 0x31, 0x60, 0x2d, 0x1d, 0x29, 0x68, 0x1f, 0x32, 0x20, + 0xd3, 0x22, 0x6d, 0x29, 0xff, 0x2e, 0x46, 0x34, 0x5a, 0x37, 0x66, 0x39, + 0x6d, 0x43, 0xdd, 0x47, 0x52, 0x46, 0xc4, 0x43, 0xe8, 0x45, 0x67, 0x41, + 0x63, 0x3e, 0x50, 0x3f, 0x30, 0x34, 0xae, 0x2a, 0xba, 0x25, 0x0d, 0x20, + 0x72, 0x1b, 0x84, 0x14, 0x0a, 0x0a, 0x16, 0x01, 0x7d, 0xfc, 0xba, 0xfc, + 0x9d, 0xfd, 0x9f, 0xfa, 0x20, 0xf8, 0x97, 0xfc, 0xa3, 0xfc, 0x7e, 0xfa, + 0xc5, 0x03, 0x08, 0x0e, 0x56, 0x0f, 0x12, 0x09, 0xbe, 0x0b, 0x85, 0x15, + 0x0a, 0x1d, 0xe2, 0x22, 0x3a, 0x26, 0x06, 0x2a, 0x18, 0x2a, 0x19, 0x2d, + 0x7c, 0x30, 0x9b, 0x2c, 0x90, 0x1d, 0x2c, 0x08, 0x13, 0xfd, 0x2d, 0xe8, + 0x85, 0xd3, 0xce, 0xd6, 0x90, 0xd9, 0x37, 0xd1, 0xfc, 0xc0, 0xf9, 0xc4, + 0x91, 0xd6, 0x57, 0xd2, 0x9b, 0xdf, 0xba, 0x04, 0xec, 0x0c, 0xfe, 0x04, + 0x20, 0x10, 0xb8, 0x18, 0xae, 0x13, 0x38, 0x1b, 0xd4, 0x2c, 0xc7, 0x30, + 0x25, 0x35, 0xa0, 0x3e, 0x6f, 0x40, 0x71, 0x3b, 0xbb, 0x3a, 0x59, 0x4a, + 0x87, 0x47, 0x02, 0x41, 0x86, 0x3d, 0xc7, 0x22, 0x56, 0x09, 0x32, 0xf1, + 0x71, 0xe7, 0xaf, 0xdc, 0xaa, 0xca, 0x98, 0xc8, 0x81, 0xc3, 0x6c, 0xbe, + 0xe1, 0xc1, 0x8e, 0xc6, 0xa3, 0xc7, 0x9c, 0xd2, 0x68, 0xe3, 0x99, 0xef, + 0xf9, 0xf7, 0x13, 0xf8, 0x14, 0x01, 0xb0, 0x02, 0xa2, 0xff, 0xab, 0x11, + 0xd5, 0x16, 0xb6, 0x0b, 0xf9, 0x00, 0x99, 0xfc, 0x15, 0xf9, 0x8c, 0xe7, + 0xdc, 0xdf, 0x1e, 0xd4, 0xfd, 0xc4, 0xdd, 0xc5, 0x80, 0xc4, 0xde, 0xc5, + 0x46, 0xc9, 0x95, 0xcc, 0xa8, 0xce, 0x84, 0xcf, 0x26, 0xd3, 0x68, 0xda, + 0xff, 0xe2, 0xb6, 0xe5, 0x79, 0xeb, 0xa8, 0xf5, 0xfe, 0xfb, 0xab, 0x01, + 0x2e, 0x0d, 0xe9, 0x15, 0x53, 0x1c, 0xcd, 0x29, 0x69, 0x33, 0x89, 0x32, + 0x1e, 0x32, 0x14, 0x30, 0x6b, 0x29, 0xc6, 0x26, 0x3e, 0x25, 0x1f, 0x21, + 0x7b, 0x1d, 0x47, 0x17, 0x85, 0x0c, 0xce, 0x04, 0x40, 0xff, 0x13, 0x03, + 0x83, 0x09, 0x9e, 0x07, 0xf0, 0x09, 0xdf, 0x0d, 0xf0, 0x17, 0x86, 0x26, + 0xfd, 0x2f, 0x3d, 0x34, 0x4f, 0x37, 0x39, 0x34, 0xbf, 0x2f, 0xc0, 0x2e, + 0x93, 0x2a, 0x7f, 0x2d, 0x64, 0x24, 0x6e, 0x17, 0x04, 0x0f, 0x97, 0x02, + 0x53, 0x00, 0xff, 0xf6, 0x31, 0xeb, 0xe9, 0xe6, 0x95, 0xe2, 0x48, 0xdd, + 0xce, 0xd7, 0x67, 0xd3, 0x58, 0xd2, 0x78, 0xd3, 0xcf, 0xd5, 0xbe, 0xe0, + 0xc1, 0xe7, 0x33, 0xe9, 0x33, 0xe9, 0xa5, 0xe7, 0xf0, 0xf0, 0x95, 0x02, + 0x2c, 0x14, 0x3c, 0x1e, 0x74, 0x24, 0x96, 0x2a, 0x9f, 0x29, 0x1c, 0x2b, + 0x02, 0x29, 0x2f, 0x1b, 0x25, 0x09, 0xa6, 0xee, 0x9e, 0xdc, 0x31, 0xd2, + 0xbf, 0xc4, 0xc0, 0xc3, 0xe0, 0xbe, 0xfb, 0xac, 0x80, 0xa8, 0xda, 0xbc, + 0x85, 0xce, 0x1b, 0xc6, 0xf5, 0xd0, 0x88, 0xf2, 0x32, 0xee, 0xb0, 0xec, + 0xcc, 0x09, 0xd0, 0x07, 0xcd, 0xfd, 0x36, 0x13, 0xfa, 0x21, 0x43, 0x25, + 0x09, 0x31, 0x0f, 0x3c, 0x80, 0x3c, 0x13, 0x35, 0xd3, 0x38, 0xe4, 0x3a, + 0x4b, 0x36, 0x8c, 0x37, 0x26, 0x33, 0xd0, 0x27, 0xf0, 0x0d, 0xb2, 0xf8, + 0xb1, 0xe9, 0xbd, 0xd1, 0xfb, 0xc4, 0x3e, 0xbb, 0xeb, 0xb0, 0x19, 0xaf, + 0x37, 0xb2, 0xf4, 0xb6, 0xe0, 0xb7, 0xc5, 0xb5, 0x64, 0xbc, 0x1e, 0xc5, + 0xe4, 0xcf, 0x49, 0xe9, 0x49, 0xf9, 0x49, 0xf5, 0x16, 0xf6, 0x08, 0xfe, + 0xcd, 0xfa, 0x67, 0xf4, 0x4c, 0xef, 0x0e, 0xec, 0xa3, 0xdb, 0xa3, 0xc2, + 0x22, 0xc6, 0x39, 0xbc, 0x0e, 0xb1, 0x1f, 0xb6, 0x68, 0xaa, 0x81, 0xad, + 0xa9, 0xb1, 0x7d, 0xb1, 0xef, 0xb9, 0xf5, 0xbd, 0x2e, 0xbe, 0x29, 0xc3, + 0x4b, 0xcc, 0x6f, 0xc9, 0x8c, 0xd2, 0xe5, 0xdd, 0xed, 0xdd, 0x7f, 0xe9, + 0x65, 0xf5, 0xc2, 0xff, 0x3f, 0x0d, 0x53, 0x19, 0x8c, 0x1c, 0xdd, 0x20, + 0xab, 0x2a, 0xe8, 0x29, 0x7f, 0x29, 0x96, 0x2b, 0x33, 0x28, 0x1d, 0x22, + 0xd8, 0x1e, 0x90, 0x19, 0xca, 0x0d, 0xd8, 0x04, 0xd6, 0xfe, 0x75, 0x01, + 0x1e, 0x06, 0x9e, 0x09, 0x85, 0x0d, 0x77, 0x0f, 0xb8, 0x19, 0x9b, 0x25, + 0x5d, 0x2f, 0x50, 0x34, 0x21, 0x3d, 0x10, 0x3f, 0xe3, 0x32, 0x95, 0x33, + 0x91, 0x2f, 0xfe, 0x25, 0x92, 0x1d, 0x49, 0x0f, 0x2e, 0x04, 0xf7, 0xfa, + 0xf6, 0xee, 0xd7, 0xe2, 0xa8, 0xe1, 0xb1, 0xe1, 0x73, 0xdf, 0x82, 0xdb, + 0x42, 0xd4, 0x1d, 0xce, 0xa6, 0xc8, 0xd1, 0xcd, 0x2b, 0xd7, 0x4b, 0xda, + 0x0f, 0xd9, 0x64, 0xd7, 0x6a, 0xd6, 0x53, 0xd7, 0x81, 0xdf, 0xce, 0xef, + 0x9b, 0xfe, 0xf4, 0x06, 0xc4, 0x12, 0x57, 0x21, 0x5b, 0x2a, 0xfd, 0x2d, + 0x06, 0x29, 0xec, 0x14, 0x31, 0x00, 0x2e, 0xea, 0x3e, 0xd3, 0x23, 0xcc, + 0xe3, 0xca, 0x1d, 0xcb, 0x98, 0xbc, 0x1c, 0xad, 0x76, 0xbb, 0xdd, 0xcd, + 0x0a, 0xd0, 0x2e, 0xdd, 0x64, 0x01, 0x8f, 0x03, 0x93, 0xff, 0xac, 0x22, + 0xe6, 0x24, 0xfa, 0x19, 0xff, 0x2e, 0xb8, 0x33, 0x3f, 0x32, 0x45, 0x46, + 0x62, 0x4d, 0x0c, 0x49, 0xdb, 0x4e, 0x92, 0x50, 0x6f, 0x50, 0x92, 0x53, + 0xbb, 0x51, 0xab, 0x53, 0xd4, 0x56, 0x69, 0x44, 0xaa, 0x35, 0x75, 0x35, + 0xc0, 0x24, 0xad, 0x17, 0x01, 0x07, 0x0c, 0xe9, 0x07, 0xd7, 0x96, 0xd2, + 0xdb, 0xd3, 0x40, 0xd5, 0x58, 0xd9, 0xfe, 0xd4, 0xb7, 0xd8, 0xf4, 0xd8, + 0x4a, 0xdb, 0x50, 0xf8, 0x07, 0xf7, 0x8e, 0xfd, 0xa9, 0x1a, 0xab, 0x14, + 0x9a, 0x0b, 0x34, 0x09, 0xf3, 0xfd, 0xcd, 0xf3, 0xb5, 0xed, 0x0e, 0xe4, + 0x71, 0xd8, 0x9a, 0xcc, 0x34, 0xc5, 0x2e, 0xc9, 0x74, 0xc5, 0x1e, 0xc1, + 0x64, 0xc8, 0x39, 0xc8, 0x4c, 0xca, 0x78, 0xd4, 0x4c, 0xdb, 0x0b, 0xdd, + 0x14, 0xe0, 0x31, 0xe8, 0x48, 0xee, 0x11, 0xf4, 0x4d, 0xfa, 0x23, 0x08, + 0x43, 0x0e, 0xaa, 0x14, 0x42, 0x2e, 0x9e, 0x36, 0xdf, 0x38, 0x87, 0x45, + 0x61, 0x47, 0xcd, 0x3e, 0x5e, 0x47, 0xa2, 0x53, 0x9f, 0x4f, 0x1d, 0x50, + 0x28, 0x48, 0xf2, 0x3d, 0x31, 0x34, 0x65, 0x2c, 0x7f, 0x32, 0x7b, 0x2f, + 0x4b, 0x2b, 0x7f, 0x2d, 0x75, 0x2f, 0xde, 0x33, 0xde, 0x3b, 0x0c, 0x42, + 0x61, 0x42, 0xf9, 0x46, 0x10, 0x4b, 0xec, 0x48, 0x04, 0x49, 0xaa, 0x4c, + 0x9c, 0x46, 0xff, 0x35, 0x22, 0x32, 0xda, 0x2c, 0xc3, 0x1c, 0x88, 0x15, + 0xa6, 0x0a, 0x51, 0xfc, 0xb2, 0xf5, 0xe3, 0xf5, 0x91, 0xf1, 0x91, 0xe6, + 0x64, 0xe1, 0xa5, 0xe1, 0x03, 0xe0, 0x07, 0xdb, 0x0d, 0xe3, 0x57, 0xe8, + 0x94, 0xe2, 0x1e, 0xe1, 0xa0, 0xeb, 0xd1, 0xfd, 0x65, 0x01, 0x15, 0x0e, + 0x9e, 0x1e, 0x53, 0x20, 0x58, 0x29, 0xdc, 0x2e, 0xdd, 0x2f, 0x5d, 0x2c, + 0xb9, 0x1d, 0x00, 0x13, 0x5b, 0xfc, 0x2a, 0xde, 0x07, 0xd9, 0xd6, 0xdd, + 0x67, 0xdc, 0x17, 0xd3, 0xe2, 0xc8, 0xc7, 0xce, 0x4e, 0xd6, 0xe9, 0xd3, + 0x28, 0xe6, 0xb0, 0x07, 0x89, 0x06, 0xf1, 0xfd, 0xba, 0x12, 0xf3, 0x1a, + 0x13, 0x1c, 0x3c, 0x37, 0x90, 0x40, 0x7b, 0x3e, 0x4d, 0x4f, 0x09, 0x53, + 0xc3, 0x54, 0x8d, 0x58, 0xf9, 0x55, 0xe7, 0x57, 0xe1, 0x55, 0xb0, 0x51, + 0xfe, 0x51, 0xc9, 0x4e, 0xa1, 0x3b, 0x26, 0x2e, 0x9d, 0x2b, 0xc2, 0x22, + 0x10, 0x1e, 0xbf, 0x16, 0x3f, 0x09, 0xa1, 0x03, 0xe4, 0xfe, 0x0d, 0xf0, + 0x14, 0xe7, 0xb1, 0xe8, 0x4c, 0xe1, 0x79, 0xdf, 0xee, 0xe4, 0x82, 0xe1, + 0x27, 0xec, 0xa8, 0xf0, 0x30, 0xeb, 0x3d, 0xfa, 0x42, 0xfb, 0xcc, 0xef, + 0xf8, 0xf8, 0xe7, 0x06, 0xa7, 0xfa, 0x43, 0xee, 0xa1, 0xed, 0xac, 0xd2, + 0xe0, 0xc6, 0x85, 0xcf, 0x0d, 0xc7, 0x4f, 0xc4, 0x61, 0xc1, 0xa6, 0xba, + 0x33, 0xc3, 0xcd, 0xc1, 0xfc, 0xbc, 0x92, 0xca, 0x00, 0xca, 0x39, 0xcb, + 0x19, 0xd7, 0x06, 0xdd, 0xe3, 0xe2, 0xda, 0xe8, 0x79, 0xf5, 0xc4, 0xf7, + 0x2c, 0xff, 0xef, 0x11, 0x54, 0x1e, 0xba, 0x25, 0x8d, 0x2a, 0x21, 0x37, + 0x7f, 0x38, 0x58, 0x3a, 0x99, 0x45, 0xb8, 0x48, 0x8e, 0x45, 0xf9, 0x40, + 0x22, 0x40, 0x31, 0x39, 0x2c, 0x37, 0xac, 0x35, 0xa0, 0x31, 0x7e, 0x31, + 0xbf, 0x2a, 0xa6, 0x2b, 0xef, 0x30, 0x91, 0x37, 0x72, 0x3e, 0x8f, 0x3c, + 0x61, 0x3b, 0xe0, 0x3f, 0x92, 0x43, 0xa5, 0x3e, 0xd7, 0x37, 0x90, 0x30, + 0x03, 0x29, 0xf9, 0x22, 0xb3, 0x1b, 0x03, 0x13, 0x0f, 0x0b, 0xc5, 0x05, + 0x57, 0xf5, 0xd1, 0xe8, 0x5e, 0xef, 0x09, 0xf2, 0xbc, 0xe8, 0x40, 0xe0, + 0x1f, 0xde, 0xe8, 0xd9, 0x1c, 0xd5, 0xea, 0xd3, 0x4f, 0xd4, 0xec, 0xd1, + 0x61, 0xd1, 0x14, 0xd6, 0xb7, 0xd9, 0x79, 0xde, 0xa8, 0xe3, 0xe4, 0xef, + 0x01, 0x00, 0xe4, 0x0e, 0x3c, 0x1e, 0x4b, 0x24, 0x56, 0x21, 0x24, 0x16, + 0x29, 0x07, 0xe1, 0xf5, 0x0e, 0xe6, 0xc5, 0xdf, 0xfa, 0xdb, 0x2d, 0xd6, + 0xba, 0xcd, 0x32, 0xbf, 0x38, 0xc0, 0xe8, 0xd7, 0xb7, 0xd8, 0xee, 0xdd, + 0x50, 0x06, 0x7e, 0x10, 0x77, 0x00, 0xdc, 0x07, 0xd3, 0x18, 0xf4, 0x1b, + 0x03, 0x25, 0x03, 0x3b, 0xe5, 0x3f, 0xfb, 0x41, 0xf4, 0x4c, 0x68, 0x47, + 0x24, 0x48, 0x4f, 0x57, 0x45, 0x5a, 0x8b, 0x59, 0xd3, 0x4f, 0x2c, 0x46, + 0xf4, 0x4a, 0x61, 0x46, 0xdf, 0x3a, 0xf3, 0x37, 0xa3, 0x2f, 0x5d, 0x1b, + 0xa2, 0x15, 0xa9, 0x11, 0xe3, 0x09, 0x46, 0x10, 0x7f, 0x0b, 0x02, 0x03, + 0x2f, 0x05, 0xe8, 0x00, 0xad, 0xf7, 0x33, 0xf8, 0xe7, 0xf2, 0x0b, 0xec, + 0x8e, 0xf5, 0x23, 0xee, 0x8d, 0xef, 0x1f, 0xff, 0x41, 0xef, 0x34, 0xe2, + 0x37, 0xe7, 0x28, 0xe0, 0xdd, 0xd4, 0xa8, 0xdc, 0x79, 0xdc, 0xba, 0xcf, + 0x8f, 0xd3, 0x74, 0xcd, 0x58, 0xc1, 0x07, 0xc7, 0xf1, 0xc9, 0x4d, 0xc6, + 0x3a, 0xc9, 0x5e, 0xc5, 0x93, 0xc2, 0xc9, 0xcd, 0xee, 0xca, 0xfa, 0xc9, + 0x12, 0xd3, 0xed, 0xd4, 0xc9, 0xdb, 0x21, 0xe4, 0x2d, 0xef, 0x54, 0xf8, + 0xa3, 0x02, 0x36, 0x0e, 0x21, 0x0e, 0xd3, 0x15, 0x8e, 0x24, 0x7c, 0x29, + 0xb5, 0x2d, 0x94, 0x35, 0x34, 0x38, 0x8c, 0x37, 0x73, 0x38, 0x7c, 0x38, + 0x36, 0x37, 0x92, 0x36, 0x35, 0x37, 0xea, 0x38, 0x3a, 0x40, 0xfb, 0x3f, + 0xa4, 0x39, 0xf8, 0x40, 0x19, 0x45, 0x58, 0x43, 0x92, 0x41, 0x8e, 0x3b, + 0x62, 0x39, 0x8d, 0x37, 0x0b, 0x34, 0xd4, 0x2d, 0x0d, 0x28, 0x2c, 0x20, + 0x19, 0x14, 0x09, 0x0e, 0x96, 0x0b, 0xc9, 0x08, 0x6a, 0x01, 0x1e, 0xf8, + 0x99, 0xee, 0x26, 0xe9, 0x99, 0xe6, 0x1b, 0xdf, 0xad, 0xda, 0x68, 0xd2, + 0x68, 0xca, 0x49, 0xc8, 0x07, 0xc6, 0x95, 0xc4, 0x88, 0xc2, 0xd3, 0xc6, + 0x77, 0xc7, 0xc3, 0xca, 0x7a, 0xd8, 0x77, 0xdf, 0xd4, 0xe4, 0xf3, 0xe9, + 0x96, 0xf3, 0xe5, 0x01, 0xd3, 0x03, 0xd2, 0x03, 0x8c, 0xff, 0x4b, 0xee, + 0x9a, 0xdf, 0xf0, 0xcc, 0x78, 0xb9, 0x23, 0xb8, 0x29, 0xbc, 0x93, 0xbc, + 0x6c, 0xb6, 0x46, 0xae, 0xca, 0xbb, 0x5b, 0xc2, 0x4e, 0xba, 0xbb, 0xd8, + 0xd9, 0xf3, 0x13, 0xed, 0x8a, 0xf0, 0xfb, 0xf2, 0x2c, 0xee, 0xd8, 0xf1, + 0x72, 0x00, 0x82, 0x10, 0x69, 0x1b, 0x01, 0x27, 0x6a, 0x2f, 0xa1, 0x33, + 0x41, 0x37, 0x55, 0x43, 0xce, 0x4a, 0x65, 0x41, 0xeb, 0x39, 0xc3, 0x39, + 0xa3, 0x33, 0xaf, 0x26, 0xe6, 0x1b, 0x51, 0x12, 0x77, 0x05, 0xe4, 0xf9, + 0x0a, 0xf8, 0x2e, 0xf2, 0x91, 0xee, 0x5a, 0xee, 0x00, 0xe8, 0xfb, 0xef, + 0x37, 0xf5, 0x24, 0xf8, 0x83, 0xff, 0xb1, 0xfc, 0xf8, 0x01, 0xa5, 0x05, + 0xfe, 0xf7, 0x7a, 0xf5, 0x8e, 0xfa, 0x82, 0xee, 0x6e, 0xe5, 0x74, 0xe5, + 0x88, 0xe2, 0x79, 0xd9, 0xa2, 0xce, 0xc4, 0xcc, 0xb9, 0xc7, 0x1b, 0xc4, + 0xb1, 0xca, 0x46, 0xd0, 0xec, 0xd2, 0xc8, 0xd0, 0x05, 0xcf, 0xe3, 0xcc, + 0x77, 0xcb, 0x31, 0xd0, 0x75, 0xd4, 0xd1, 0xd9, 0x54, 0xd9, 0xb4, 0xdb, + 0x15, 0xe3, 0x19, 0xe2, 0x7a, 0xe5, 0x81, 0xf6, 0xe2, 0x00, 0xcc, 0x05, + 0xcd, 0x1b, 0x6f, 0x23, 0x0f, 0x2b, 0x0e, 0x3d, 0xd3, 0x3d, 0xcc, 0x3f, + 0xa8, 0x44, 0x32, 0x4b, 0xb0, 0x4e, 0xf3, 0x53, 0x71, 0x52, 0x57, 0x50, + 0xba, 0x51, 0xc6, 0x4a, 0xac, 0x4f, 0xb4, 0x57, 0x02, 0x5e, 0xbf, 0x5f, + 0x6a, 0x63, 0xa1, 0x63, 0xa1, 0x64, 0x9f, 0x67, 0x18, 0x60, 0xb8, 0x63, + 0x81, 0x5c, 0xad, 0x50, 0x30, 0x48, 0x07, 0x3d, 0x78, 0x37, 0x62, 0x2f, + 0x62, 0x2d, 0x7f, 0x26, 0x38, 0x1c, 0x4f, 0x19, 0x07, 0x17, 0xe6, 0x11, + 0xf6, 0x11, 0x05, 0x12, 0xb9, 0x0c, 0x19, 0x0b, 0x3e, 0x05, 0xa9, 0xfd, + 0xce, 0xf7, 0x0b, 0xf3, 0xb9, 0xf2, 0x3b, 0xf3, 0x6a, 0xf1, 0x26, 0xef, + 0x6f, 0xec, 0x39, 0xe7, 0x59, 0xea, 0x92, 0xf2, 0xea, 0xff, 0x87, 0x12, + 0x6d, 0x11, 0xa9, 0x0c, 0x02, 0x11, 0x86, 0x08, 0x7e, 0xf9, 0x5f, 0xfa, + 0x07, 0xfd, 0xdf, 0xe7, 0x17, 0xce, 0x67, 0xca, 0xde, 0xd9, 0x37, 0xd5, + 0x77, 0xc7, 0x1b, 0xd4, 0xea, 0xdf, 0xa8, 0xdf, 0x72, 0xe1, 0xa4, 0x02, + 0x74, 0x1d, 0x61, 0x15, 0xf7, 0x1e, 0x60, 0x22, 0xc1, 0x13, 0xc5, 0x1d, + 0x93, 0x30, 0x9a, 0x2c, 0xf0, 0x28, 0xea, 0x34, 0xed, 0x39, 0xff, 0x35, + 0x07, 0x35, 0xa9, 0x40, 0xe7, 0x47, 0xdb, 0x3f, 0x54, 0x42, 0xe8, 0x43, + 0xb0, 0x39, 0x00, 0x32, 0x6c, 0x29, 0xf5, 0x1d, 0x93, 0x0e, 0xfe, 0x0a, + 0x28, 0x09, 0x1c, 0x03, 0xe2, 0x06, 0xa5, 0xfe, 0xb9, 0xf6, 0xdf, 0xf7, + 0x27, 0xfc, 0xe2, 0x03, 0x9c, 0x07, 0x4b, 0x0c, 0xb9, 0x12, 0xb3, 0x0e, + 0x0c, 0x06, 0x73, 0x14, 0xc1, 0x1b, 0x9c, 0x0f, 0x8a, 0xff, 0xdd, 0xe6, + 0xcd, 0xd6, 0xfd, 0xc7, 0x04, 0xc7, 0x99, 0xc6, 0x88, 0xb7, 0xc7, 0xb9, + 0x0a, 0xb5, 0x2f, 0xb1, 0x3d, 0xbb, 0x90, 0xc0, 0xc1, 0xcc, 0xe8, 0xd3, + 0x16, 0xd2, 0x15, 0xd0, 0xab, 0xd5, 0xb7, 0xd7, 0xbc, 0xd4, 0x91, 0xdd, + 0xdf, 0xd8, 0xff, 0xd5, 0x08, 0xdc, 0xa0, 0xdd, 0x74, 0xe8, 0xdf, 0xf2, + 0xd2, 0xfc, 0x81, 0x03, 0x76, 0x0f, 0x9b, 0x16, 0xec, 0x13, 0x5e, 0x1e, + 0xe6, 0x24, 0x47, 0x29, 0x3e, 0x32, 0x4d, 0x36, 0x2e, 0x34, 0x29, 0x2e, + 0x3f, 0x2d, 0xfd, 0x2f, 0x58, 0x35, 0x49, 0x44, 0x8c, 0x4b, 0xd4, 0x44, + 0xf7, 0x49, 0x59, 0x53, 0xd6, 0x56, 0xfc, 0x55, 0x23, 0x52, 0x3a, 0x50, + 0x68, 0x4a, 0xd1, 0x3e, 0x42, 0x32, 0xdf, 0x2b, 0x73, 0x1f, 0x7d, 0x13, + 0x4c, 0x0d, 0xcf, 0x02, 0xce, 0xfb, 0x09, 0xf7, 0x8e, 0xf6, 0x7b, 0xf4, + 0xbe, 0xf0, 0xca, 0xee, 0xc7, 0xeb, 0x84, 0xea, 0xdc, 0xe6, 0x29, 0xe3, + 0x4d, 0xe4, 0xd5, 0xe4, 0x73, 0xdf, 0x53, 0xdf, 0x21, 0xe3, 0xca, 0xe2, + 0xaf, 0xe5, 0x86, 0xe8, 0xcd, 0xee, 0x9f, 0xf9, 0x54, 0xfe, 0xa6, 0x03, + 0xd3, 0x11, 0x7d, 0x16, 0xb8, 0x09, 0xa6, 0x03, 0x15, 0xf6, 0xa4, 0xd7, + 0x43, 0xc7, 0xc4, 0xba, 0x3d, 0xad, 0x4f, 0xb2, 0x5d, 0xbb, 0xab, 0xb6, + 0x91, 0xb5, 0x57, 0xbc, 0x32, 0xc3, 0x1c, 0xc9, 0x8d, 0xd3, 0xc4, 0xf4, + 0xaf, 0x0b, 0x00, 0x0b, 0x84, 0x0b, 0x8a, 0x0d, 0x7e, 0x09, 0xe0, 0x05, + 0x5c, 0x16, 0xed, 0x22, 0x07, 0x27, 0xc8, 0x2b, 0x40, 0x2a, 0x81, 0x24, + 0x58, 0x23, 0xf6, 0x2e, 0x68, 0x2c, 0x21, 0x28, 0x75, 0x28, 0x55, 0x21, + 0x29, 0x16, 0x96, 0x06, 0xff, 0x0a, 0x32, 0x06, 0x59, 0xf6, 0x6a, 0xf0, + 0x22, 0xe4, 0x42, 0xe3, 0x09, 0xe2, 0x1d, 0xe1, 0xe4, 0xe8, 0xc9, 0xea, + 0x8d, 0xeb, 0x84, 0xee, 0xaa, 0xf3, 0x22, 0xf9, 0x62, 0x06, 0x22, 0x07, + 0x4c, 0x08, 0xcd, 0x15, 0x9b, 0x14, 0x11, 0x0f, 0x15, 0x00, 0xfa, 0xf6, + 0x6f, 0xee, 0x98, 0xde, 0xc5, 0xd4, 0xf8, 0xbd, 0x77, 0xaf, 0xdb, 0xa9, + 0xbb, 0xa3, 0x2c, 0xa6, 0xb3, 0xab, 0x2b, 0xaf, 0x07, 0xab, 0x1b, 0xab, + 0x61, 0xab, 0x7a, 0xad, 0x78, 0xbd, 0x18, 0xc9, 0xc6, 0xcc, 0xb6, 0xce, + 0x94, 0xcb, 0x65, 0xc9, 0xc0, 0xcf, 0x69, 0xd7, 0x0f, 0xdd, 0x58, 0xeb, + 0xfe, 0xeb, 0x55, 0xe9, 0xa5, 0xfa, 0x95, 0xf5, 0xeb, 0xf4, 0xfb, 0x05, + 0x9d, 0x05, 0x7e, 0x09, 0x31, 0x0c, 0xde, 0x15, 0xda, 0x1a, 0x81, 0x15, + 0xe1, 0x1c, 0xb8, 0x1c, 0x8a, 0x23, 0x3d, 0x25, 0x5b, 0x25, 0xcb, 0x25, + 0xbe, 0x25, 0x98, 0x34, 0xc3, 0x2e, 0xb6, 0x2b, 0x83, 0x2b, 0xd0, 0x29, + 0x3f, 0x27, 0x7c, 0x1d, 0xdc, 0x19, 0xec, 0x12, 0x03, 0x0d, 0xca, 0xfd, + 0xdd, 0xff, 0x46, 0x01, 0x63, 0xf9, 0x8f, 0xf4, 0x6f, 0xe4, 0x02, 0xe0, + 0x5c, 0xe0, 0xe6, 0xeb, 0x5a, 0xea, 0x32, 0xe3, 0x4f, 0xe1, 0x0d, 0xda, + 0x3b, 0xdb, 0xdc, 0xd8, 0x61, 0xe4, 0xdd, 0xec, 0x2d, 0xf2, 0x90, 0xf0, + 0x6a, 0xe4, 0xb3, 0xe7, 0xdc, 0xe8, 0x5e, 0xea, 0xcb, 0xef, 0x1c, 0xf6, + 0x5a, 0xf9, 0xd6, 0xf7, 0xe8, 0xf2, 0x2c, 0xee, 0x41, 0xe6, 0x7c, 0xd6, + 0xdc, 0xce, 0xa3, 0xc2, 0xcf, 0xb5, 0xb8, 0xb6, 0x67, 0xb8, 0x24, 0xb5, + 0xc2, 0xac, 0x64, 0xaf, 0xae, 0xc0, 0x08, 0xcb, 0xe5, 0xd4, 0xef, 0xed, + 0x1e, 0xfe, 0x95, 0xfd, 0xc0, 0xff, 0xcf, 0x06, 0xca, 0x0e, 0x68, 0x12, + 0x1d, 0x1f, 0x92, 0x29, 0x3b, 0x22, 0x30, 0x24, 0xb4, 0x2a, 0x15, 0x2c, + 0x24, 0x2e, 0x61, 0x2f, 0x05, 0x2b, 0x65, 0x20, 0x78, 0x18, 0xb9, 0x1d, + 0xec, 0x1c, 0xb8, 0x10, 0x60, 0x12, 0x1d, 0x05, 0x37, 0xf8, 0x64, 0xfb, + 0x00, 0xfb, 0x5f, 0x03, 0x48, 0x01, 0x91, 0xfd, 0xc0, 0xfe, 0xd2, 0xfd, + 0x2c, 0xff, 0x3d, 0x05, 0x61, 0x0f, 0x89, 0x10, 0xb0, 0x11, 0x7e, 0x10, + 0x2f, 0x0f, 0x5d, 0x18, 0x01, 0x26, 0x8c, 0x26, 0x83, 0x1d, 0xe8, 0x17, + 0x86, 0x0b, 0xbb, 0x02, 0x17, 0xfe, 0x8f, 0xf4, 0x3b, 0xeb, 0x76, 0xe1, + 0x12, 0xd4, 0x0e, 0xc9, 0x3f, 0xc6, 0xa6, 0xc3, 0x43, 0xc5, 0xe0, 0xc7, + 0x36, 0xc7, 0xc4, 0xcc, 0xa7, 0xce, 0x80, 0xd0, 0x5e, 0xd8, 0xb5, 0xd9, + 0xbe, 0xe1, 0x66, 0xf3, 0x47, 0xfb, 0x5d, 0xfd, 0x36, 0x02, 0xe9, 0x03, + 0x13, 0x08, 0xa8, 0x0d, 0xe7, 0x11, 0xc3, 0x18, 0x8c, 0x16, 0x06, 0x12, + 0x80, 0x16, 0x08, 0x1e, 0x52, 0x19, 0x26, 0x1d, 0x92, 0x25, 0x7e, 0x1a, + 0xd1, 0x1e, 0x90, 0x23, 0x8d, 0x29, 0x7a, 0x33, 0xa6, 0x35, 0x39, 0x36, + 0xe6, 0x30, 0xf3, 0x3a, 0xda, 0x42, 0x11, 0x47, 0x1f, 0x40, 0x05, 0x3c, + 0x4c, 0x40, 0xe7, 0x32, 0x7f, 0x30, 0xdb, 0x2e, 0x49, 0x30, 0x13, 0x2b, + 0x86, 0x21, 0x9d, 0x1b, 0xb2, 0x13, 0xc2, 0x14, 0x38, 0x0d, 0x5e, 0x0d, + 0xec, 0x08, 0x41, 0x03, 0xaf, 0x03, 0xe8, 0xfb, 0x29, 0xf9, 0x8b, 0xf9, + 0x53, 0x00, 0x70, 0x02, 0xa8, 0x01, 0x43, 0xff, 0x68, 0x06, 0xb8, 0x13, + 0x45, 0x12, 0x60, 0x14, 0xbe, 0x1d, 0xd7, 0x22, 0x2e, 0x1e, 0x02, 0x29, + 0xf1, 0x31, 0x43, 0x29, 0x30, 0x2c, 0x20, 0x26, 0x03, 0x1a, 0xcb, 0x08, + 0x32, 0xf4, 0x69, 0xeb, 0xf5, 0xd8, 0x6c, 0xc6, 0x86, 0xc5, 0xec, 0xcc, + 0xb7, 0xc9, 0xff, 0xc1, 0xb0, 0xc5, 0xf2, 0xc8, 0x06, 0xc9, 0x9e, 0xd2, + 0x06, 0xf0, 0xfb, 0x06, 0xc0, 0x05, 0x2f, 0x09, 0x9d, 0x0e, 0xc1, 0x07, + 0x25, 0x10, 0x3e, 0x25, 0x89, 0x2b, 0xb3, 0x2e, 0xff, 0x35, 0x31, 0x38, + 0xb3, 0x30, 0x93, 0x2e, 0x14, 0x35, 0xf8, 0x2f, 0xfb, 0x23, 0xcf, 0x1f, + 0xac, 0x1f, 0x3b, 0x14, 0x46, 0x0d, 0xbb, 0x0a, 0xe8, 0x00, 0x1a, 0xfd, + 0x08, 0xf6, 0x06, 0xf4, 0x2c, 0xfa, 0xd2, 0xff, 0xc4, 0x07, 0x66, 0x07, + 0x49, 0x04, 0x14, 0x0a, 0x84, 0x10, 0xc8, 0x13, 0x0f, 0x1e, 0xac, 0x24, + 0xf8, 0x27, 0x7c, 0x2d, 0x0f, 0x2c, 0x97, 0x32, 0x43, 0x32, 0x37, 0x27, + 0x80, 0x26, 0xe9, 0x1b, 0xce, 0x0d, 0x01, 0x0b, 0xe4, 0x00, 0x33, 0xf4, + 0x39, 0xf3, 0x39, 0xee, 0x9d, 0xe8, 0xff, 0xeb, 0x60, 0xe4, 0xb6, 0xdc, + 0x55, 0xdb, 0x48, 0xd5, 0x72, 0xd6, 0x55, 0xd9, 0x45, 0xd6, 0xf8, 0xd7, + 0x94, 0xe0, 0x9a, 0xe4, 0xf7, 0xe7, 0xc0, 0xf2, 0xd1, 0xf5, 0x06, 0xfc, + 0xa9, 0x0d, 0x02, 0x14, 0xf3, 0x1a, 0xa5, 0x23, 0x4c, 0x18, 0x95, 0x10, + 0x28, 0x15, 0xae, 0x12, 0xc2, 0x17, 0xef, 0x18, 0x03, 0x0f, 0xfe, 0x0f, + 0xe1, 0x00, 0x36, 0xf4, 0x04, 0xfc, 0x47, 0xf2, 0xfd, 0xf1, 0xa5, 0xff, + 0xaf, 0xfc, 0x02, 0xff, 0xe4, 0x07, 0x53, 0x0f, 0x04, 0x17, 0x83, 0x15, + 0xd9, 0x19, 0xc7, 0x21, 0x7f, 0x1f, 0xaa, 0x1b, 0x72, 0x1b, 0x30, 0x1c, + 0x50, 0x17, 0x14, 0x19, 0x32, 0x1c, 0x6e, 0x16, 0x3d, 0x17, 0xa9, 0x15, + 0x6a, 0x0e, 0x3d, 0x10, 0xa0, 0x12, 0x48, 0x11, 0xfe, 0x0b, 0x15, 0x00, + 0x78, 0xfc, 0xda, 0xfe, 0x52, 0xfb, 0x1e, 0xfe, 0xbd, 0x07, 0x25, 0x08, + 0xb4, 0x09, 0xbc, 0x0b, 0xd4, 0x0a, 0x0a, 0x14, 0x90, 0x1c, 0x0f, 0x23, + 0x85, 0x26, 0x3e, 0x29, 0x1f, 0x30, 0x46, 0x31, 0x4e, 0x2e, 0x2f, 0x2a, + 0x06, 0x20, 0xfb, 0x09, 0x75, 0xf9, 0x48, 0xf6, 0x03, 0xe5, 0x53, 0xcc, + 0x98, 0xc8, 0x2e, 0xc5, 0xf2, 0xb4, 0x9c, 0xb2, 0x50, 0xbd, 0xce, 0xc2, + 0x3c, 0xc8, 0xd7, 0xd2, 0x33, 0xdf, 0x5e, 0xe9, 0x52, 0xea, 0x72, 0xf0, + 0xe4, 0xf9, 0x75, 0xfe, 0xe8, 0x09, 0x32, 0x13, 0x7e, 0x14, 0x4f, 0x15, + 0x73, 0x1a, 0xca, 0x1e, 0xd8, 0x1b, 0x7f, 0x1c, 0x31, 0x24, 0x57, 0x20, + 0x9a, 0x1a, 0x86, 0x1b, 0x71, 0x19, 0xf6, 0x10, 0xb8, 0x04, 0x5e, 0x02, + 0xfb, 0xfa, 0xab, 0xf7, 0xc5, 0xf8, 0x9f, 0xf5, 0x5d, 0xfa, 0x26, 0xf9, + 0x77, 0xfc, 0xfc, 0x02, 0x27, 0x0e, 0x49, 0x1c, 0x61, 0x25, 0x64, 0x2c, + 0x68, 0x2e, 0xf9, 0x37, 0xc6, 0x3b, 0xa6, 0x3b, 0x59, 0x40, 0x9f, 0x43, + 0xfd, 0x3f, 0x90, 0x32, 0xa7, 0x29, 0x2b, 0x1f, 0xeb, 0x16, 0x2f, 0x10, + 0x40, 0x03, 0x50, 0xfd, 0x66, 0xf8, 0xf7, 0xf2, 0x27, 0xee, 0x60, 0xeb, + 0x4c, 0xf3, 0x21, 0xfc, 0xfc, 0xfe, 0x8c, 0xfc, 0x5a, 0xf6, 0xd8, 0xe8, + 0x5d, 0xe1, 0xea, 0xe3, 0xa1, 0xe3, 0x17, 0xeb, 0xd1, 0xee, 0xfa, 0xed, + 0x25, 0xf1, 0x9c, 0xf2, 0x13, 0xfc, 0xc9, 0x08, 0x4b, 0x0b, 0xba, 0x11, + 0x56, 0x1d, 0x40, 0x13, 0xb0, 0x14, 0x3a, 0x1a, 0xd3, 0x05, 0xe6, 0x02, + 0xb5, 0xfc, 0x30, 0xef, 0xa1, 0xef, 0x5d, 0xe3, 0xb5, 0xde, 0xc1, 0xe7, + 0x95, 0xe0, 0x80, 0xdd, 0xf0, 0xe6, 0x6d, 0xec, 0xa6, 0xf6, 0x24, 0x04, + 0x5a, 0x0c, 0xd0, 0x0e, 0x04, 0x17, 0x11, 0x19, 0xd2, 0x10, 0xfc, 0x11, + 0xe0, 0x0f, 0x8d, 0x15, 0x0f, 0x16, 0x70, 0x08, 0x20, 0x0e, 0xfa, 0x14, + 0x64, 0x13, 0x1f, 0x18, 0x17, 0x18, 0x98, 0x12, 0x64, 0x17, 0xd9, 0x19, + 0xb8, 0x16, 0x37, 0x14, 0x19, 0x10, 0x88, 0x0f, 0xe3, 0x06, 0xee, 0x03, + 0x93, 0x08, 0x68, 0x0a, 0xdc, 0x0c, 0x30, 0x0a, 0x7b, 0x0a, 0xb0, 0x0d, + 0x1c, 0x16, 0xb7, 0x1d, 0x25, 0x23, 0xee, 0x29, 0x75, 0x2d, 0x59, 0x33, + 0x0e, 0x35, 0xb4, 0x33, 0xcc, 0x2a, 0xad, 0x1a, 0x69, 0x06, 0x39, 0xea, + 0x2d, 0xcf, 0x18, 0xba, 0xad, 0xb2, 0xa1, 0xb2, 0xb4, 0xad, 0xed, 0xa6, + 0x1a, 0xa3, 0xed, 0xa5, 0x20, 0xb2, 0xc3, 0xb9, 0xad, 0xbf, 0x4b, 0xd7, + 0x17, 0xdd, 0x16, 0xcc, 0x0b, 0xca, 0x6a, 0xcd, 0x61, 0xd0, 0xf6, 0xd9, + 0x0d, 0xe4, 0x33, 0xe7, 0x74, 0xe4, 0xb4, 0xe9, 0xbc, 0xed, 0x6a, 0xea, + 0x93, 0xf5, 0x70, 0xfe, 0x81, 0xf3, 0x60, 0xef, 0x8b, 0xf2, 0x8a, 0xf2, + 0x18, 0xf1, 0x9c, 0xe6, 0x05, 0xda, 0xbb, 0xd6, 0x51, 0xd5, 0xbf, 0xd4, + 0x8e, 0xdb, 0x81, 0xdb, 0x7a, 0xdb, 0x22, 0xe5, 0xff, 0xe7, 0xff, 0xf2, + 0xd3, 0x05, 0xc8, 0x11, 0xd3, 0x1d, 0x20, 0x2a, 0x10, 0x34, 0x78, 0x39, + 0x35, 0x3e, 0x99, 0x41, 0xae, 0x42, 0xbd, 0x38, 0x64, 0x2c, 0x9d, 0x27, + 0x28, 0x18, 0x6a, 0x0d, 0xaf, 0x07, 0xf3, 0xf9, 0x5e, 0xf3, 0x1e, 0xf3, + 0xd3, 0xf4, 0x92, 0xf4, 0x74, 0xf0, 0xfe, 0xf1, 0x91, 0xf3, 0x59, 0xf8, + 0x9a, 0x07, 0xff, 0x0c, 0x37, 0x0d, 0xe2, 0x06, 0xea, 0xfb, 0xcf, 0xfd, + 0xd8, 0xfc, 0xc6, 0xfd, 0x26, 0xfb, 0x16, 0xf8, 0x58, 0xfe, 0x1c, 0xfd, + 0x99, 0x01, 0xb8, 0x01, 0xf9, 0xf8, 0x76, 0xfc, 0x0e, 0xf9, 0x70, 0xf8, + 0x10, 0x04, 0x55, 0xf9, 0xda, 0xee, 0x49, 0xeb, 0xbf, 0xdd, 0xc8, 0xdd, + 0xd4, 0xe0, 0xbb, 0xe3, 0xad, 0xe7, 0x4d, 0xe6, 0x1d, 0xe9, 0x65, 0xed, + 0xa3, 0xf2, 0x55, 0xfe, 0x7e, 0x0f, 0xb5, 0x18, 0x33, 0x1f, 0x18, 0x26, + 0xf6, 0x2b, 0xe7, 0x31, 0x92, 0x39, 0xba, 0x42, 0x9e, 0x3d, 0xd3, 0x41, + 0x86, 0x45, 0x51, 0x3e, 0xa9, 0x43, 0xa3, 0x42, 0x5e, 0x40, 0xa1, 0x3c, + 0xad, 0x35, 0xbd, 0x39, 0x8c, 0x3d, 0x64, 0x3b, 0x31, 0x3b, 0x8b, 0x3d, + 0x66, 0x3e, 0xae, 0x44, 0xf2, 0x46, 0x93, 0x43, 0xa3, 0x44, 0x14, 0x43, + 0x94, 0x3e, 0x02, 0x3d, 0xa9, 0x3a, 0xad, 0x35, 0x6a, 0x35, 0xae, 0x3b, + 0x92, 0x44, 0x17, 0x42, 0xc7, 0x3d, 0x9f, 0x41, 0x59, 0x40, 0xc1, 0x3d, + 0x2b, 0x39, 0xed, 0x2e, 0x0c, 0x19, 0x3a, 0x01, 0xda, 0xec, 0xd4, 0xd1, + 0xb9, 0xc5, 0xa9, 0xcc, 0x9d, 0xca, 0x8f, 0xbf, 0x3d, 0xbb, 0xb7, 0xbe, + 0x4a, 0xc9, 0x06, 0xcb, 0xa3, 0xd7, 0xf9, 0xef, 0x76, 0xeb, 0xef, 0xe6, + 0xc0, 0xec, 0x66, 0xeb, 0x52, 0xe6, 0x7a, 0xed, 0x72, 0xf6, 0xf0, 0xf1, + 0xcf, 0xfa, 0x96, 0x02, 0xd9, 0x02, 0x79, 0x02, 0x00, 0x05, 0x13, 0x09, + 0xd9, 0x02, 0x00, 0x05, 0xb5, 0x08, 0x28, 0x0a, 0x6c, 0x04, 0xc7, 0x01, + 0x21, 0x07, 0xaf, 0xfc, 0x11, 0xfa, 0x7e, 0xff, 0xe7, 0x03, 0xb1, 0x04, + 0x58, 0x05, 0x66, 0x10, 0x12, 0x15, 0xd7, 0x1c, 0x85, 0x29, 0x52, 0x2f, + 0x52, 0x34, 0x4a, 0x3b, 0x6c, 0x45, 0xc0, 0x4b, 0xb1, 0x48, 0x75, 0x4e, + 0x99, 0x51, 0xec, 0x3e, 0x2f, 0x34, 0x47, 0x2b, 0x6c, 0x19, 0x26, 0x14, + 0xd9, 0x10, 0x45, 0x04, 0xf6, 0xf9, 0x98, 0xf0, 0x43, 0xee, 0xd8, 0xf6, + 0x9f, 0xfa, 0x01, 0x02, 0x68, 0x07, 0xb8, 0x06, 0xc1, 0x05, 0xdc, 0x09, + 0x3b, 0x12, 0x12, 0x0c, 0x2c, 0x0c, 0x99, 0x0c, 0x17, 0x03, 0x55, 0xfd, + 0x02, 0xf1, 0xc9, 0xdf, 0xff, 0xd2, 0x83, 0xce, 0xc0, 0xd2, 0x2a, 0xe0, + 0xc4, 0xe2, 0xda, 0xd7, 0xc1, 0xcf, 0x46, 0xca, 0x45, 0xc9, 0x91, 0xd0, + 0x79, 0xde, 0xa3, 0xde, 0xdd, 0xd7, 0x93, 0xd3, 0x5f, 0xc9, 0x86, 0xcb, + 0x1b, 0xd5, 0xea, 0xdb, 0xa3, 0xe1, 0x34, 0xe0, 0xa0, 0xea, 0xc3, 0xf9, + 0x7e, 0xfe, 0x3d, 0x0d, 0x6c, 0x1e, 0x03, 0x22, 0x41, 0x22, 0xd0, 0x27, + 0xea, 0x2f, 0x53, 0x35, 0xbd, 0x35, 0xbb, 0x38, 0x29, 0x35, 0xf4, 0x24, + 0x81, 0x20, 0x23, 0x24, 0x89, 0x23, 0xf6, 0x22, 0xca, 0x27, 0xd0, 0x2a, + 0x99, 0x2b, 0xde, 0x31, 0x3d, 0x35, 0xcc, 0x36, 0xe3, 0x36, 0x2c, 0x38, + 0x45, 0x3b, 0x63, 0x3a, 0xcf, 0x35, 0xbb, 0x35, 0xc9, 0x2f, 0x0f, 0x1e, + 0xf1, 0x19, 0x56, 0x1a, 0x3a, 0x18, 0xe0, 0x18, 0x61, 0x1b, 0x0d, 0x1e, + 0xfd, 0x18, 0x03, 0x14, 0xa5, 0x15, 0x45, 0x15, 0xd0, 0x0d, 0xfe, 0x0a, + 0x09, 0x00, 0xbd, 0xe9, 0x9c, 0xd5, 0xc5, 0xc2, 0xf4, 0xb3, 0x97, 0xa8, + 0xb5, 0xab, 0x40, 0xb0, 0xb7, 0xa4, 0x1e, 0xa2, 0x0f, 0xb2, 0x60, 0xb7, + 0x7e, 0xb7, 0x4b, 0xca, 0x2b, 0xd6, 0xa9, 0xd1, 0x6c, 0xd4, 0x26, 0xdf, + 0x80, 0xdc, 0xa9, 0xd8, 0x65, 0xde, 0xf5, 0xd9, 0xd3, 0xd3, 0xcd, 0xd5, + 0xe0, 0xde, 0x4c, 0xe4, 0xaa, 0xe1, 0x2d, 0xe8, 0x73, 0xed, 0xb4, 0xea, + 0x35, 0xf3, 0x0f, 0xfd, 0xfa, 0xfd, 0x09, 0x00, 0x86, 0x03, 0xe0, 0x03, + 0xa7, 0xfe, 0x1b, 0xfb, 0xe5, 0xfb, 0xee, 0xfe, 0x9c, 0xfd, 0x14, 0x00, + 0x7f, 0x07, 0xea, 0x06, 0xfe, 0x10, 0x1c, 0x1a, 0x5e, 0x1a, 0x8a, 0x1f, + 0xcd, 0x29, 0x14, 0x36, 0xf3, 0x3a, 0xd7, 0x3c, 0x57, 0x38, 0xd9, 0x32, + 0x2c, 0x23, 0x14, 0x1b, 0xfc, 0x1e, 0x83, 0x08, 0x92, 0x02, 0xaf, 0xfd, + 0x54, 0xe9, 0xb0, 0xe8, 0x1b, 0xe5, 0x00, 0xe4, 0xd4, 0xe6, 0xed, 0xe7, + 0xf4, 0xea, 0x2b, 0xf0, 0xb5, 0xf2, 0x98, 0xed, 0xf5, 0xee, 0xfc, 0xe9, + 0xd7, 0xde, 0x22, 0xde, 0x60, 0xdc, 0xbe, 0xd4, 0x7a, 0xd3, 0x6e, 0xc8, + 0x7b, 0xaf, 0xcd, 0xa8, 0xce, 0xa8, 0x84, 0xab, 0xd2, 0xb5, 0x3b, 0xb8, + 0xe1, 0xb8, 0xcd, 0xb2, 0x94, 0xac, 0x3f, 0xb4, 0xc8, 0xb9, 0xba, 0xbc, + 0x89, 0xcb, 0x43, 0xcc, 0x05, 0xc1, 0x23, 0xc8, 0x8c, 0xc7, 0x0b, 0xce, + 0xbe, 0xde, 0x11, 0xde, 0x39, 0xe7, 0xa7, 0xf3, 0x6f, 0xfc, 0x29, 0x0d, + 0x5b, 0x14, 0x03, 0x12, 0x45, 0x1b, 0xfd, 0x20, 0xc7, 0x1a, 0x44, 0x22, + 0x06, 0x29, 0xd8, 0x22, 0x3f, 0x22, 0x4d, 0x25, 0xdc, 0x20, 0xb8, 0x24, + 0x03, 0x26, 0xa7, 0x1c, 0x1b, 0x21, 0xb0, 0x21, 0x61, 0x27, 0x60, 0x33, + 0x5d, 0x33, 0x3d, 0x34, 0x14, 0x30, 0x03, 0x26, 0x5a, 0x1f, 0x4a, 0x21, + 0x4d, 0x1e, 0x62, 0x19, 0x26, 0x16, 0xaf, 0x04, 0x20, 0xf9, 0x9b, 0xf7, + 0x0c, 0xf3, 0x42, 0xf4, 0x75, 0xf6, 0x7a, 0xf1, 0x70, 0xef, 0x2c, 0xec, + 0xba, 0xe8, 0x98, 0xec, 0xf4, 0xee, 0x81, 0xf1, 0x77, 0xee, 0x27, 0xdc, + 0xf8, 0xc8, 0xcf, 0xc9, 0xf6, 0xc4, 0x52, 0xb2, 0x2d, 0xaf, 0xd3, 0xae, + 0xd1, 0xab, 0xbc, 0xaa, 0x59, 0xa9, 0x8c, 0xad, 0xc5, 0xb8, 0x2c, 0xbd, + 0x0e, 0xbd, 0x0f, 0xcf, 0x9e, 0xda, 0x36, 0xd7, 0xc8, 0xdb, 0x35, 0xde, + 0xaf, 0xd9, 0xc4, 0xdd, 0xfc, 0xe4, 0x08, 0xe3, 0xf2, 0xe3, 0xa8, 0xea, + 0x04, 0xf4, 0xa5, 0xfb, 0xdc, 0x03, 0x59, 0x13, 0xae, 0x18, 0xec, 0x18, + 0xad, 0x21, 0xcc, 0x28, 0x53, 0x2a, 0x66, 0x29, 0xaa, 0x29, 0x58, 0x25, + 0x29, 0x1c, 0x38, 0x17, 0x4e, 0x14, 0x64, 0x18, 0xb2, 0x1d, 0xac, 0x1c, + 0xae, 0x21, 0x52, 0x1f, 0x1c, 0x20, 0x49, 0x26, 0x8c, 0x24, 0xfa, 0x2d, + 0x88, 0x30, 0xed, 0x30, 0x33, 0x31, 0xcf, 0x30, 0x41, 0x3a, 0xd1, 0x35, + 0x3c, 0x32, 0xba, 0x31, 0xd3, 0x29, 0xf4, 0x1e, 0xd2, 0x1a, 0xc2, 0x0f, + 0xc5, 0xfe, 0x78, 0xfe, 0xe2, 0xf8, 0xfd, 0xf8, 0x92, 0xf6, 0x5b, 0xef, + 0xb0, 0xea, 0xa2, 0xe0, 0x0a, 0xe7, 0x34, 0xee, 0x9d, 0xec, 0x4b, 0xe6, + 0x37, 0xdf, 0xc5, 0xdb, 0xaa, 0xe0, 0xc3, 0xe4, 0x66, 0xe5, 0xa7, 0xe2, + 0xb9, 0xcd, 0x2a, 0xc7, 0x3c, 0xc7, 0xca, 0xc5, 0x08, 0xd0, 0xac, 0xd4, + 0x84, 0xd5, 0x59, 0xd5, 0xbe, 0xd5, 0x35, 0xd7, 0x41, 0xe0, 0xc7, 0xe9, + 0x90, 0xf3, 0xc7, 0xfd, 0x4d, 0xfe, 0xa7, 0x00, 0x0b, 0x06, 0x23, 0x09, + 0xf7, 0x06, 0x4b, 0x0f, 0x3c, 0x19, 0xf3, 0x1b, 0x52, 0x2c, 0xcd, 0x32, + 0xb5, 0x2f, 0xe2, 0x2f, 0x10, 0x2e, 0x0f, 0x35, 0x56, 0x3d, 0xc9, 0x3e, + 0xaa, 0x3e, 0x78, 0x3e, 0x64, 0x39, 0x8a, 0x38, 0xb2, 0x37, 0x8f, 0x32, + 0xcc, 0x31, 0x30, 0x2a, 0xaa, 0x28, 0x4d, 0x30, 0x4f, 0x35, 0x86, 0x39, + 0xeb, 0x3a, 0xa4, 0x38, 0x41, 0x35, 0xec, 0x32, 0xc9, 0x2c, 0x9c, 0x31, + 0x13, 0x38, 0xe9, 0x2d, 0xfc, 0x1d, 0x3d, 0x0b, 0x0a, 0x04, 0x08, 0x06, + 0x03, 0x01, 0xba, 0xf8, 0xc9, 0xf4, 0xeb, 0xf6, 0x7b, 0xf7, 0xc6, 0xf8, + 0xda, 0xfa, 0xd4, 0xf5, 0x2e, 0xf9, 0x3c, 0x02, 0x38, 0xfe, 0x52, 0xfa, + 0x86, 0xf1, 0xed, 0xe1, 0x2b, 0xdd, 0x2c, 0xd6, 0xd1, 0xc5, 0xb6, 0xb9, + 0x53, 0xba, 0x02, 0xc0, 0x4e, 0xc2, 0xbc, 0xc2, 0x35, 0xc6, 0xd9, 0xcc, + 0xf1, 0xce, 0x21, 0xe0, 0x5c, 0xf2, 0xa2, 0xe6, 0x3a, 0xe5, 0x1a, 0xf4, + 0x74, 0xf5, 0xa3, 0xf2, 0xb7, 0xf6, 0x6e, 0xf6, 0x7a, 0xf6, 0x38, 0x04, + 0x10, 0x0e, 0xf6, 0x10, 0x87, 0x19, 0x24, 0x31, 0xea, 0x45, 0xec, 0x44, + 0x62, 0x41, 0x90, 0x42, 0x16, 0x44, 0x8d, 0x41, 0xea, 0x41, 0x49, 0x48, + 0xd9, 0x49, 0x42, 0x4b, 0xa2, 0x4f, 0xe7, 0x4c, 0x31, 0x45, 0xff, 0x3d, + 0xbd, 0x35, 0x8c, 0x32, 0x9c, 0x32, 0x83, 0x36, 0xb1, 0x37, 0x7a, 0x36, + 0x24, 0x3d, 0xac, 0x45, 0x9e, 0x4c, 0xe6, 0x46, 0x53, 0x44, 0xaa, 0x42, + 0x9c, 0x33, 0x72, 0x34, 0x2b, 0x2b, 0xff, 0x12, 0x4c, 0x09, 0x37, 0xfc, + 0x26, 0xf2, 0x87, 0xed, 0xd1, 0xe2, 0x64, 0xd7, 0xba, 0xcd, 0x69, 0xca, + 0xda, 0xce, 0x04, 0xd1, 0x16, 0xd2, 0x22, 0xd3, 0xd8, 0xcc, 0xda, 0xc9, + 0xc0, 0xcc, 0xce, 0xd8, 0x9c, 0xe8, 0x72, 0xe7, 0xa9, 0xde, 0x84, 0xd2, + 0x69, 0xbf, 0x06, 0xb6, 0x41, 0xb6, 0xa9, 0xb8, 0x92, 0xc3, 0xb9, 0xc8, + 0xaa, 0xcc, 0x52, 0xd6, 0x6a, 0xdd, 0x8d, 0xee, 0xaa, 0xff, 0x2b, 0x08, + 0xc2, 0x06, 0xb2, 0x02, 0x3f, 0x0a, 0x5a, 0x0a, 0x85, 0x08, 0x76, 0x11, + 0xe1, 0x11, 0x6d, 0x18, 0x10, 0x2d, 0xdc, 0x3d, 0x65, 0x4d, 0xe7, 0x53, + 0xf0, 0x5b, 0x2e, 0x6b, 0x13, 0x6e, 0xa7, 0x6e, 0x20, 0x71, 0xc5, 0x69, + 0x33, 0x62, 0xbb, 0x57, 0xcb, 0x45, 0x8c, 0x3d, 0x93, 0x34, 0x86, 0x25, + 0xd0, 0x12, 0xb9, 0xfd, 0x78, 0xf3, 0xf0, 0xf3, 0x97, 0xf4, 0xd4, 0xf4, + 0x09, 0x00, 0xc6, 0x02, 0x9d, 0xff, 0xd5, 0x01, 0x6e, 0xfb, 0xba, 0xf3, + 0x0c, 0xf1, 0x24, 0xed, 0xec, 0xe1, 0x65, 0xd4, 0x4b, 0xc7, 0x62, 0xc1, + 0xe4, 0xc0, 0x6a, 0xc3, 0x60, 0xcc, 0x38, 0xd7, 0x2a, 0xe2, 0x7b, 0xf0, + 0xe4, 0x00, 0x22, 0x05, 0x94, 0x08, 0x1b, 0x00, 0xf2, 0xef, 0x49, 0xef, + 0xa1, 0xe9, 0xb7, 0xe7, 0xb1, 0xe7, 0xa8, 0xe0, 0xa6, 0xdf, 0xaa, 0xe0, + 0x50, 0xe0, 0x0f, 0xe8, 0xca, 0xf0, 0xaa, 0xe9, 0x97, 0xe1, 0xf5, 0xee, + 0x90, 0x05, 0x71, 0x09, 0x5f, 0x14, 0xfe, 0x30, 0x6f, 0x36, 0xa1, 0x2b, + 0x35, 0x2d, 0x80, 0x35, 0xa1, 0x2f, 0x6b, 0x2e, 0x85, 0x42, 0x6d, 0x51, + 0xae, 0x59, 0x0f, 0x5f, 0x46, 0x59, 0x3c, 0x59, 0x1d, 0x64, 0x26, 0x6b, + 0x8a, 0x62, 0xb1, 0x4b, 0x51, 0x3d, 0x91, 0x32, 0xf6, 0x17, 0x75, 0xf7, + 0x4b, 0xe0, 0x67, 0xdd, 0x38, 0xe6, 0x8a, 0xea, 0x29, 0xed, 0x6f, 0xf1, + 0xb2, 0xfb, 0x49, 0x06, 0x84, 0x04, 0x78, 0xff, 0xdc, 0xfc, 0xcf, 0xf8, + 0x74, 0xf7, 0x4e, 0xf5, 0x44, 0xf8, 0x03, 0x06, 0xd3, 0x06, 0xab, 0x01, + 0x1c, 0xfc, 0x29, 0xf7, 0x6a, 0x08, 0xfb, 0x0f, 0x27, 0x05, 0x9a, 0xf5, + 0x0f, 0xed, 0xf6, 0xf2, 0x2c, 0xec, 0xb3, 0xe6, 0x95, 0xe1, 0xc0, 0xe1, + 0x4c, 0xf1, 0x30, 0xf5, 0x9d, 0xf1, 0xe1, 0xf6, 0xc2, 0xfa, 0x64, 0xf3, + 0xff, 0xed, 0xda, 0xeb, 0x32, 0x00, 0x11, 0x17, 0xbb, 0x1b, 0x87, 0x26, + 0x2d, 0x29, 0xf5, 0x25, 0xf1, 0x14, 0x76, 0x03, 0x7b, 0xfd, 0x56, 0xf1, + 0x60, 0xe7, 0xbd, 0xe5, 0x98, 0xf1, 0x92, 0xf9, 0x61, 0x04, 0xd2, 0x12, + 0x19, 0x18, 0xfd, 0x22, 0xca, 0x2d, 0x44, 0x37, 0xd3, 0x3e, 0xd5, 0x45, + 0xfd, 0x41, 0xdc, 0x2b, 0xc3, 0x22, 0xf7, 0x15, 0xa4, 0xf7, 0xc7, 0xf4, + 0x60, 0x07, 0xf3, 0x1d, 0x0b, 0x34, 0x91, 0x35, 0x64, 0x3a, 0xa7, 0x42, + 0x04, 0x42, 0xf5, 0x4f, 0x2f, 0x4e, 0xe6, 0x31, 0xf8, 0x20, 0xf0, 0x15, + 0x00, 0x0c, 0x07, 0x06, 0x01, 0x05, 0x86, 0x12, 0x9d, 0x1b, 0x43, 0x0f, + 0x5f, 0x0a, 0xf5, 0x10, 0xad, 0x09, 0x37, 0xf6, 0x8e, 0xe0, 0x6a, 0xd4, + 0x78, 0xc3, 0xc7, 0xb5, 0xe0, 0xbf, 0xdc, 0xc3, 0x80, 0xc0, 0x71, 0xcd, + 0x40, 0xda, 0xbb, 0xd3, 0x1e, 0xc8, 0xe2, 0xc1, 0xe5, 0xcb, 0x62, 0xcc, + 0x14, 0xb6, 0xf9, 0xb7, 0x25, 0xca, 0x66, 0xde, 0xe9, 0xf7, 0xd5, 0x07, + 0xdc, 0x06, 0xd6, 0xf9, 0xa5, 0xe3, 0xfd, 0xdf, 0xbc, 0xfb, 0x34, 0xfa, + 0x94, 0xe9, 0x86, 0xe5, 0x9a, 0xd1, 0x2a, 0xc2, 0x29, 0xc1, 0x12, 0xc7, + 0x9c, 0xce, 0x39, 0xd7, 0x8b, 0xe0, 0xb5, 0xe8, 0x00, 0xf5, 0xad, 0x05, + 0x5e, 0x2d, 0x5d, 0x45, 0xcd, 0x25, 0x43, 0x0a, 0x23, 0x05, 0x6e, 0xf3, + 0xa5, 0xec, 0xae, 0x18, 0xee, 0x53, 0xd6, 0x6f, 0x14, 0x75, 0x05, 0x61, + 0xbc, 0x3a, 0x75, 0x30, 0x8c, 0x36, 0x87, 0x24, 0x93, 0x11, 0x34, 0x0e, + 0x88, 0x08, 0x26, 0x09, 0xfa, 0x13, 0x8d, 0x0f, 0x54, 0x00, 0xa5, 0x05, + 0xd0, 0x17, 0x0a, 0xfc, 0xd6, 0xb7, 0x08, 0x9d, 0x07, 0xa2, 0x14, 0xb0, + 0xf9, 0xd1, 0x3c, 0xec, 0xbb, 0x06, 0xda, 0x1c, 0x47, 0x0e, 0xc2, 0xef, + 0x55, 0xe9, 0x8c, 0xfa, 0xfb, 0xff, 0x48, 0xe8, 0x8d, 0xe3, 0xe0, 0x02, + 0x81, 0x0f, 0x57, 0x1c, 0xae, 0x30, 0x93, 0x23, 0x9d, 0x0c, 0x26, 0xf6, + 0x59, 0xf2, 0xea, 0x0c, 0x0b, 0x27, 0x96, 0x2e, 0x92, 0x1e, 0x49, 0x2c, + 0x93, 0x47, 0x1f, 0x39, 0x3d, 0x2e, 0xb9, 0x29, 0x6d, 0x1a, 0x9a, 0x0e, + 0x63, 0x12, 0x3f, 0x1f, 0xe8, 0x25, 0x01, 0x2e, 0xcf, 0x38, 0x14, 0x43, + 0xc4, 0x39, 0x43, 0x2f, 0xea, 0x42, 0x86, 0x55, 0x8a, 0x50, 0x5f, 0x4a, + 0x2c, 0x55, 0x45, 0x4c, 0x3f, 0x1f, 0x8b, 0xf9, 0x73, 0x02, 0x3a, 0x20, + 0xd2, 0x18, 0x41, 0x07, 0xb3, 0x10, 0x2b, 0x18, 0xa4, 0x15, 0x31, 0x0f, + 0xff, 0x07, 0xcd, 0x20, 0x4d, 0x3a, 0x38, 0x31, 0x15, 0x16, 0x92, 0xe8, + 0x37, 0xd9, 0xd2, 0xd6, 0x20, 0xc5, 0xb1, 0xd4, 0x6e, 0xe5, 0x8f, 0xde, + 0xc4, 0xe1, 0xf5, 0x0b, 0x40, 0x49, 0xd0, 0x5d, 0x65, 0x2e, 0xb6, 0xeb, + 0x11, 0xd9, 0xf5, 0xf7, 0xa4, 0x1c, 0x35, 0x0a, 0xa1, 0xd6, 0xe5, 0xd0, + 0x41, 0xee, 0xef, 0xea, 0x68, 0xc8, 0x47, 0xca, 0x1e, 0xea, 0x4c, 0x01, + 0xc0, 0x13, 0x7c, 0x10, 0x86, 0x0b, 0xec, 0x17, 0x25, 0x16, 0xae, 0x13, + 0xde, 0x04, 0xdf, 0xe9, 0x5d, 0xe4, 0x1d, 0xec, 0xbc, 0xfe, 0xa1, 0x0b, + 0x75, 0x05, 0xde, 0xff, 0x94, 0x0f, 0xc2, 0x28, 0x22, 0x38, 0xe7, 0x3a, + 0x40, 0x3f, 0x28, 0x49, 0x63, 0x46, 0x1f, 0x3f, 0xe8, 0x2d, 0x87, 0x14, + 0x1f, 0x06, 0x3b, 0x02, 0x19, 0x04, 0x2a, 0x13, 0x1a, 0x1f, 0x45, 0x1b, + 0xd4, 0x1f, 0x4a, 0x27, 0xa7, 0x36, 0x6f, 0x40, 0x10, 0x38, 0x5b, 0x37, + 0xde, 0x36, 0x71, 0x29, 0x8e, 0x23, 0xa8, 0x3a, 0x2c, 0x49, 0x8b, 0x34, + 0xa0, 0x18, 0x73, 0x0c, 0xef, 0x04, 0x12, 0x05, 0x2d, 0x2e, 0x84, 0x5a, + 0x7e, 0x5c, 0xe3, 0x5a, 0x76, 0x50, 0x56, 0x20, 0x41, 0xfa, 0x1b, 0xf0, + 0xc5, 0xeb, 0x29, 0xe0, 0x69, 0xc6, 0x61, 0xb2, 0x1f, 0xb6, 0xc0, 0xba, + 0x95, 0xb9, 0x2d, 0xbe, 0xd6, 0xbe, 0x7d, 0xc9, 0x5c, 0xd7, 0xac, 0xda, + 0xdc, 0xd8, 0xb0, 0xe6, 0x43, 0x0a, 0xe0, 0x15, 0xe4, 0x08, 0x1d, 0x08, + 0xe9, 0x06, 0xde, 0xec, 0x6e, 0xdb, 0xa7, 0xda, 0x00, 0xe8, 0x7e, 0xfd, + 0xfe, 0xf3, 0x1f, 0xd8, 0x2b, 0xc9, 0xbe, 0xde, 0x32, 0xf7, 0x89, 0xf7, + 0x66, 0x02, 0x83, 0x1d, 0x84, 0x2e, 0xd1, 0x2a, 0xdb, 0x2e, 0xd0, 0x37, + 0x83, 0x2d, 0x9a, 0x1d, 0xe2, 0x20, 0xf7, 0x1d, 0x3d, 0x1a, 0x52, 0x2d, + 0xd6, 0x34, 0xfe, 0x38, 0x2a, 0x2a, 0x49, 0x10, 0xc1, 0x16, 0x49, 0x11, + 0xc8, 0x02, 0x6a, 0x19, 0xcb, 0x40, 0x64, 0x5a, 0x04, 0x60, 0x10, 0x49, + 0x3b, 0x2d, 0xae, 0x19, 0x40, 0x17, 0xe4, 0x3d, 0x74, 0x41, 0xcf, 0x0f, + 0x23, 0xee, 0xc8, 0xe3, 0x53, 0xe9, 0x23, 0xf5, 0x25, 0xf9, 0xff, 0xe1, + 0xc0, 0xcb, 0xa2, 0xc8, 0x34, 0xc9, 0xfc, 0xd0, 0x14, 0xc5, 0x53, 0xc6, + 0x9f, 0xeb, 0x27, 0x04, 0x8a, 0x07, 0x71, 0xfd, 0x99, 0xe8, 0xcb, 0xe3, + 0x7d, 0xdf, 0xcc, 0xba, 0x1d, 0xaf, 0xe3, 0xbf, 0x5e, 0xd8, 0x9a, 0xf2, + 0x11, 0xe1, 0xe2, 0xd4, 0xc7, 0xe2, 0xe2, 0xed, 0x29, 0xf6, 0x53, 0xec, + 0x21, 0xda, 0x8b, 0xdf, 0x89, 0xfe, 0x47, 0x1d, 0x6f, 0x2b, 0xf4, 0x18, + 0x22, 0x18, 0x4c, 0x39, 0x13, 0x3e, 0x73, 0x2e, 0xbb, 0x17, 0xc1, 0x0e, + 0xfb, 0x18, 0xbf, 0x10, 0x4e, 0x0b, 0x56, 0x1a, 0x48, 0x35, 0x22, 0x5b, + 0xf4, 0x64, 0x80, 0x4d, 0x81, 0x3d, 0x1f, 0x44, 0xab, 0x4b, 0xe4, 0x32, + 0x27, 0x19, 0x4e, 0x0c, 0xed, 0xef, 0xa6, 0xdb, 0x84, 0xe3, 0xc0, 0xe6, + 0x8c, 0xd5, 0x64, 0xcb, 0xfc, 0xca, 0x76, 0xce, 0x7b, 0xd2, 0x28, 0xe0, + 0x96, 0x03, 0xa7, 0x04, 0x62, 0xca, 0x82, 0xa5, 0x6c, 0xb2, 0x8e, 0xc0, + 0x18, 0xcb, 0xae, 0xd0, 0x1d, 0xd1, 0x3c, 0xd8, 0x83, 0xd5, 0xfb, 0xc8, + 0x3d, 0xc7, 0x97, 0xc9, 0x7a, 0xcc, 0xe0, 0xd4, 0xd4, 0xc1, 0x69, 0x9e, + 0x6b, 0x94, 0xe8, 0xa2, 0xea, 0xaa, 0xce, 0x9d, 0x1b, 0x97, 0x6f, 0x9d, + 0xc6, 0xad, 0xe5, 0xbb, 0x6b, 0xc1, 0xae, 0xc7, 0xa0, 0xbd, 0x75, 0xa8, + 0x79, 0xab, 0x2e, 0xc5, 0xb2, 0xe1, 0xf8, 0xfc, 0x66, 0x07, 0x98, 0x0d, + 0x43, 0x1d, 0x1f, 0x2b, 0x29, 0x46, 0xc6, 0x5a, 0x0d, 0x49, 0x84, 0x29, + 0x6a, 0x09, 0xfc, 0xf2, 0x12, 0xfe, 0x42, 0x05, 0x74, 0xf0, 0xa0, 0xdf, + 0x63, 0xe7, 0xa2, 0xf8, 0x6f, 0xfb, 0xac, 0xfa, 0x8d, 0x0d, 0x08, 0x32, + 0x17, 0x3d, 0x66, 0x22, 0x4f, 0x0f, 0xd9, 0x12, 0xe4, 0x04, 0x54, 0xf4, + 0x7a, 0xf9, 0xad, 0xf2, 0xa8, 0xff, 0xd5, 0x1b, 0x81, 0x1c, 0x22, 0xfe, + 0x52, 0xe3, 0x57, 0xfa, 0x29, 0x10, 0xa3, 0xfe, 0x11, 0xcd, 0x6e, 0xbc, + 0xbb, 0xe1, 0x72, 0xe7, 0x55, 0xe2, 0x1f, 0xf8, 0x08, 0x02, 0x8d, 0xed, + 0xd3, 0xdb, 0x8b, 0xd4, 0x2e, 0xca, 0xce, 0xc9, 0x49, 0xc2, 0x57, 0xbc, + 0xfb, 0xc1, 0xce, 0xc1, 0x59, 0xd0, 0x72, 0xe1, 0xc1, 0xd7, 0xff, 0xd1, + 0xa1, 0xe8, 0xf2, 0xf8, 0xf9, 0xe7, 0xfc, 0xce, 0x86, 0xc4, 0xcd, 0xcd, + 0xda, 0xcc, 0x5e, 0xb4, 0xda, 0xa5, 0xa0, 0x9f, 0x60, 0xb0, 0x1d, 0xdc, + 0xeb, 0x07, 0xaa, 0x19, 0x66, 0xfa, 0xa2, 0xca, 0xd2, 0xb6, 0xf5, 0xcc, + 0xb4, 0xdc, 0x01, 0xca, 0xfa, 0xbb, 0xa2, 0xcf, 0x44, 0xf2, 0x15, 0xf0, + 0xd6, 0xd4, 0xa1, 0xc9, 0x30, 0xe8, 0x8f, 0x0b, 0xf8, 0x05, 0x76, 0x06, + 0x53, 0x01, 0xb3, 0xe8, 0x1c, 0xf7, 0xe3, 0x1e, 0x3e, 0x3a, 0xb4, 0x3c, + 0x88, 0x28, 0xcd, 0x2c, 0xff, 0x46, 0xb7, 0x48, 0x9e, 0x46, 0xa0, 0x55, + 0xd4, 0x5d, 0x6d, 0x55, 0x10, 0x4c, 0x05, 0x41, 0xe6, 0x35, 0x0c, 0x2b, + 0x4d, 0x01, 0xd4, 0xe0, 0x5a, 0xee, 0x3d, 0x0e, 0xd7, 0x1e, 0xcd, 0xf9, + 0x08, 0xe2, 0x7c, 0xf4, 0x30, 0xf6, 0xac, 0xe7, 0x54, 0xdc, 0x3c, 0xe6, + 0x5c, 0xe7, 0xf4, 0xd4, 0x93, 0xd3, 0x3f, 0xd8, 0x7b, 0xd8, 0x15, 0xe0, + 0x5e, 0xdf, 0xd9, 0xcf, 0x1b, 0xc0, 0x9a, 0xbc, 0x19, 0xc6, 0x73, 0xbc, + 0x1d, 0xb4, 0xc7, 0xca, 0x70, 0xed, 0x5e, 0xf7, 0x58, 0xdb, 0xa3, 0xcc, + 0x93, 0xcd, 0xa2, 0xdc, 0x46, 0x06, 0x06, 0x14, 0x0b, 0xf7, 0xc6, 0xfd, + 0xc7, 0x36, 0x4b, 0x5a, 0xc6, 0x4a, 0xdc, 0x24, 0xa9, 0x13, 0xa2, 0x16, + 0x84, 0x2f, 0xf8, 0x2b, 0x70, 0x03, 0x8a, 0x1a, 0x12, 0x56, 0x37, 0x72, + 0xc6, 0x73, 0xf9, 0x70, 0x50, 0x69, 0x8b, 0x61, 0x5d, 0x63, 0x03, 0x61, + 0x11, 0x53, 0xbb, 0x2e, 0x82, 0x11, 0xf3, 0x17, 0xa4, 0x35, 0x41, 0x40, + 0xc2, 0x37, 0x18, 0x35, 0x68, 0x30, 0x17, 0x32, 0x72, 0x2a, 0xed, 0x21, + 0x66, 0x24, 0x67, 0x31, 0xa0, 0x36, 0xc3, 0x1c, 0x36, 0x10, 0x38, 0x0a, + 0x77, 0xf5, 0xcb, 0xe0, 0x72, 0xd5, 0x4b, 0xd9, 0x00, 0xda, 0x8f, 0xc9, + 0x3f, 0xc8, 0x08, 0xdf, 0xae, 0xdd, 0x47, 0xd8, 0x45, 0xe6, 0xe1, 0xdc, + 0xee, 0xc9, 0x46, 0xcc, 0x43, 0xc2, 0x6a, 0xaa, 0x90, 0xa5, 0x86, 0xc3, + 0x25, 0xeb, 0x0f, 0xec, 0x09, 0xdd, 0xa7, 0xd4, 0x21, 0xd0, 0x94, 0xbf, + 0x49, 0xba, 0x53, 0xda, 0x83, 0xec, 0x59, 0xec, 0xd5, 0xf1, 0xbd, 0x12, + 0x5f, 0x33, 0xb6, 0x3f, 0x97, 0x39, 0x4d, 0x16, 0xb7, 0xfe, 0xfd, 0xf0, + 0x05, 0xeb, 0xa3, 0xee, 0x54, 0xfe, 0x81, 0x1b, 0x3e, 0x3b, 0xe5, 0x53, + 0xc6, 0x52, 0x9d, 0x46, 0x7e, 0x25, 0x66, 0x14, 0xc4, 0x1f, 0x1f, 0x20, + 0xe3, 0x1b, 0x15, 0x1a, 0x8e, 0x20, 0x04, 0x21, 0x2a, 0x21, 0x48, 0x17, + 0x84, 0x15, 0x9c, 0x31, 0xb4, 0x3c, 0x48, 0x3e, 0xfe, 0x41, 0xbc, 0x3d, + 0x76, 0x44, 0x40, 0x4d, 0x27, 0x3f, 0xe6, 0x31, 0xd4, 0x34, 0xf2, 0x46, + 0x4e, 0x56, 0xd5, 0x40, 0xcf, 0x27, 0x2e, 0x2a, 0xc0, 0x42, 0x49, 0x4e, + 0xf3, 0x45, 0xf1, 0x45, 0x29, 0x24, 0xf3, 0xf3, 0x95, 0xf3, 0x40, 0xfc, + 0xd5, 0xf9, 0x87, 0xfc, 0x2f, 0xee, 0x5a, 0xd7, 0x69, 0xc8, 0x34, 0xc0, + 0xfb, 0xd3, 0x4a, 0xe8, 0x69, 0xe6, 0x29, 0xe8, 0x1a, 0xdd, 0xca, 0xc4, + 0x57, 0xc2, 0xdc, 0xd4, 0x5e, 0xe1, 0xc4, 0xd0, 0xfa, 0xb6, 0x93, 0xb7, + 0x36, 0xc5, 0x61, 0xd0, 0x0c, 0xde, 0xe1, 0xdd, 0x0f, 0xd4, 0xca, 0xda, + 0xae, 0xe8, 0xab, 0xed, 0xef, 0xe9, 0x0e, 0xe9, 0xce, 0xee, 0xeb, 0xf6, + 0x77, 0x01, 0xfd, 0xf9, 0x04, 0xef, 0xde, 0x0a, 0x08, 0x23, 0xb9, 0x0c, + 0x8a, 0xee, 0xd4, 0xe3, 0x05, 0xf1, 0x1b, 0x02, 0x72, 0x06, 0xc7, 0x16, + 0xd8, 0x2f, 0x5a, 0x3b, 0x60, 0x3f, 0x9b, 0x49, 0x56, 0x55, 0x01, 0x63, + 0xa1, 0x70, 0x8e, 0x74, 0x52, 0x6f, 0x1b, 0x60, 0xf7, 0x53, 0x07, 0x4f, + 0x45, 0x39, 0x4b, 0x18, 0x43, 0x21, 0xb5, 0x47, 0x38, 0x5a, 0xfd, 0x43, + 0xde, 0x0a, 0x2e, 0xf3, 0x42, 0xf9, 0x0f, 0xfd, 0xe5, 0x04, 0xf1, 0x04, + 0x26, 0x01, 0x33, 0xf0, 0xde, 0xd8, 0x0b, 0xd6, 0x5b, 0xed, 0x98, 0xf3, + 0xcb, 0xdb, 0x25, 0xc9, 0x5a, 0xb1, 0xcc, 0xab, 0x4c, 0xc2, 0xc3, 0xdb, + 0x7e, 0xf8, 0xa2, 0xe3, 0x03, 0xae, 0x9d, 0xa8, 0xe5, 0xb7, 0x45, 0xc5, + 0x45, 0xd1, 0x59, 0xcd, 0xe8, 0xc9, 0xfd, 0xc6, 0x32, 0xc5, 0x6d, 0xc9, + 0x4e, 0xd6, 0xdb, 0xdb, 0x9b, 0xcf, 0xbe, 0xcc, 0x15, 0xdf, 0x2c, 0x03, + 0x13, 0x11, 0xe0, 0xfe, 0x8f, 0x09, 0x58, 0x32, 0xe8, 0x39, 0x43, 0x29, + 0x5d, 0x2b, 0x17, 0x3e, 0x10, 0x58, 0x5d, 0x64, 0x04, 0x65, 0x2f, 0x59, + 0x21, 0x47, 0x8a, 0x46, 0xec, 0x54, 0xe5, 0x66, 0x3c, 0x69, 0xa1, 0x56, + 0x8b, 0x37, 0x33, 0x3f, 0x7a, 0x63, 0x5a, 0x6e, 0x24, 0x5a, 0x88, 0x2a, + 0x4a, 0x16, 0xb4, 0x24, 0x37, 0x36, 0xd1, 0x37, 0x9a, 0x20, 0x84, 0x0b, + 0x8d, 0x0d, 0xc0, 0x24, 0x49, 0x2e, 0x86, 0x1b, 0xb3, 0x0f, 0xa4, 0x26, + 0xfb, 0x3c, 0x66, 0x2f, 0x48, 0x0f, 0x7d, 0x0e, 0x19, 0x25, 0xeb, 0x15, + 0x3d, 0xf1, 0xdf, 0xd4, 0x27, 0xd3, 0x9f, 0xe7, 0x34, 0xea, 0xc6, 0xe4, + 0x7d, 0xea, 0xf0, 0xf3, 0xd1, 0xed, 0x41, 0xc8, 0x72, 0xa7, 0x01, 0xa4, + 0xc1, 0xb0, 0x72, 0xbc, 0x00, 0xb6, 0xf1, 0xb2, 0x26, 0xb8, 0x08, 0xc0, + 0x31, 0xc3, 0x11, 0xbe, 0x48, 0xbf, 0x4e, 0xcd, 0x00, 0xec, 0x3d, 0x08, + 0xf7, 0x15, 0xa1, 0xfd, 0x94, 0xdd, 0x04, 0xf0, 0x6e, 0x1e, 0xcb, 0x2f, + 0xc6, 0x2c, 0x24, 0x43, 0x58, 0x46, 0x1a, 0x2f, 0xcc, 0x19, 0x04, 0x20, + 0xc5, 0x4b, 0x70, 0x6b, 0x76, 0x6d, 0x04, 0x40, 0x6a, 0x0e, 0x63, 0x0b, + 0x40, 0x13, 0x5d, 0x1c, 0x31, 0x1c, 0xfd, 0x14, 0xd0, 0x2e, 0x88, 0x42, + 0x74, 0x2f, 0x3b, 0x1c, 0x62, 0x1e, 0x2f, 0x34, 0x51, 0x46, 0x82, 0x4b, + 0xcb, 0x3a, 0x7e, 0x2d, 0x4b, 0x38, 0xe4, 0x42, 0x4f, 0x4a, 0xc7, 0x4c, + 0x6b, 0x53, 0xfd, 0x4b, 0x6e, 0x39, 0x6d, 0x2e, 0x63, 0x23, 0x47, 0x1d, + 0xd4, 0x14, 0x11, 0x0b, 0x7c, 0x0c, 0xb4, 0x0e, 0x14, 0xfc, 0x45, 0xf0, + 0xca, 0xf0, 0x3c, 0xe6, 0xa1, 0xd2, 0xdf, 0xc8, 0x26, 0xd4, 0x31, 0xd8, + 0xc3, 0xdd, 0x62, 0xd3, 0xef, 0xba, 0xfb, 0xc9, 0xc0, 0xdc, 0x66, 0xda, + 0x35, 0xea, 0x72, 0xf4, 0xbb, 0xde, 0xcb, 0xdf, 0xc6, 0xeb, 0x3b, 0xed, + 0x40, 0xe7, 0x69, 0xc9, 0x18, 0xba, 0x12, 0xbd, 0x85, 0xbe, 0xde, 0xbc, + 0x81, 0xb9, 0xcd, 0xb2, 0xe4, 0xa1, 0x8e, 0xa8, 0xf7, 0xc4, 0x7e, 0xe3, + 0xd2, 0xf0, 0x86, 0xc7, 0xec, 0xa2, 0xc5, 0xb4, 0x9d, 0xd5, 0xf1, 0xe8, + 0x8f, 0xe6, 0x3b, 0xef, 0xc8, 0x11, 0x2d, 0x15, 0x2f, 0x00, 0x20, 0x08, + 0x30, 0x23, 0xf8, 0x43, 0x61, 0x52, 0xde, 0x4f, 0xe4, 0x41, 0x7e, 0x11, + 0xf1, 0xfe, 0x52, 0x2c, 0xc2, 0x48, 0x12, 0x27, 0x67, 0x0a, 0x4e, 0x10, + 0x01, 0x30, 0xd4, 0x4d, 0x44, 0x38, 0xd7, 0x2a, 0xa2, 0x29, 0x34, 0x26, + 0xa8, 0x36, 0xa0, 0x41, 0x9f, 0x46, 0x1c, 0x3d, 0xe2, 0x29, 0x61, 0x14, + 0x8a, 0x0d, 0x5f, 0x25, 0x87, 0x3f, 0xda, 0x51, 0xa2, 0x50, 0x40, 0x21, + 0xd3, 0xeb, 0x6f, 0xe6, 0x8a, 0xf6, 0xc2, 0xef, 0x7b, 0xd9, 0xa5, 0xdc, + 0xec, 0xe9, 0x7a, 0xe6, 0xbd, 0xdd, 0x15, 0xd6, 0x4e, 0xd4, 0x7f, 0xcc, + 0x09, 0xc1, 0x4d, 0xc2, 0x57, 0xc3, 0x3f, 0xb1, 0x30, 0xa1, 0x2d, 0xa4, + 0x78, 0xad, 0x7a, 0xb6, 0x27, 0xb0, 0x1f, 0xa9, 0x65, 0xbd, 0x1b, 0xd4, + 0x9e, 0xdd, 0x45, 0xee, 0x05, 0x09, 0x49, 0x1a, 0x1e, 0x24, 0xe2, 0x30, + 0xba, 0x31, 0x3d, 0x2e, 0x96, 0x31, 0x12, 0x32, 0x71, 0x2d, 0x92, 0x33, + 0x49, 0x45, 0x25, 0x4e, 0x5f, 0x55, 0x1c, 0x55, 0x24, 0x52, 0xd0, 0x5b, + 0xfd, 0x68, 0xfc, 0x6e, 0xc4, 0x66, 0xcb, 0x60, 0x4b, 0x61, 0xa0, 0x64, + 0x5e, 0x69, 0x1f, 0x5d, 0x8f, 0x4c, 0x5c, 0x52, 0x94, 0x5f, 0xa7, 0x66, + 0xc4, 0x5f, 0x8d, 0x4a, 0x9f, 0x43, 0x21, 0x49, 0x6a, 0x44, 0x39, 0x47, + 0x5d, 0x5d, 0xb7, 0x61, 0x6c, 0x5e, 0xa2, 0x4c, 0x1d, 0x28, 0xba, 0x22, + 0x65, 0x2b, 0x91, 0x25, 0x37, 0xfa, 0xf9, 0xde, 0x33, 0xed, 0x79, 0xd9, + 0x56, 0xc2, 0x11, 0xc3, 0xd9, 0xbb, 0x94, 0xbc, 0xf0, 0xc1, 0x0b, 0xb3, + 0x4a, 0xb0, 0xa9, 0xb8, 0x76, 0xc6, 0xe3, 0xdb, 0xa7, 0xdb, 0xd1, 0xd5, + 0x05, 0xd6, 0xe2, 0xe2, 0xf8, 0xe8, 0x38, 0xeb, 0xfc, 0xeb, 0xed, 0xe0, + 0x6a, 0xe9, 0xc8, 0xeb, 0xba, 0xe3, 0xee, 0xe0, 0xc7, 0xdd, 0xfa, 0xe5, + 0x59, 0xf1, 0x1c, 0xe5, 0xb6, 0xe2, 0x03, 0x07, 0x43, 0x1a, 0x6f, 0x0d, + 0x4e, 0x03, 0xca, 0x08, 0x9f, 0x0e, 0x50, 0x17, 0xb0, 0x17, 0x63, 0x15, + 0x5a, 0x28, 0x52, 0x2d, 0xea, 0x29, 0x76, 0x2e, 0x6a, 0x3a, 0xa3, 0x4a, + 0x4a, 0x4b, 0x70, 0x4e, 0x9d, 0x56, 0xf7, 0x53, 0xdb, 0x59, 0x35, 0x59, + 0x4c, 0x4a, 0xea, 0x47, 0x0a, 0x44, 0x3c, 0x3b, 0x4e, 0x35, 0x77, 0x30, + 0x07, 0x26, 0xde, 0x22, 0x88, 0x32, 0xe5, 0x3c, 0xcc, 0x3c, 0xe8, 0x30, + 0xf1, 0x1d, 0xd9, 0x1a, 0xc2, 0x21, 0xc0, 0x24, 0x4b, 0x33, 0xed, 0x3e, + 0xe5, 0x34, 0x7c, 0x1d, 0x8a, 0x09, 0x07, 0x0d, 0x78, 0x17, 0xf0, 0x0f, + 0x6b, 0xf8, 0x14, 0xeb, 0xb3, 0xfa, 0x12, 0x1a, 0xd6, 0x1b, 0x07, 0x06, + 0xd8, 0x04, 0x29, 0x0a, 0x2c, 0xfd, 0xaa, 0xed, 0x59, 0xea, 0x64, 0xe8, + 0xca, 0xf5, 0x4b, 0xf4, 0x0b, 0xdb, 0xd2, 0xd3, 0xe2, 0xd9, 0xe9, 0xe6, + 0x60, 0xe6, 0x1d, 0xd7, 0x02, 0xcc, 0x49, 0xc7, 0x37, 0xd1, 0x65, 0xe5, + 0x35, 0xe0, 0x54, 0xc6, 0xb0, 0xbe, 0x29, 0xc6, 0xe1, 0xd0, 0x31, 0xf0, + 0xeb, 0x0d, 0x3f, 0xff, 0xe1, 0xfa, 0xcf, 0x13, 0xd7, 0x18, 0xa8, 0x0b, + 0x64, 0x18, 0x4c, 0x27, 0x71, 0x13, 0x91, 0x20, 0x38, 0x45, 0xe7, 0x41, + 0x21, 0x27, 0x60, 0x29, 0x76, 0x37, 0xa5, 0x37, 0x2a, 0x3f, 0x6f, 0x4a, + 0xa6, 0x5c, 0x94, 0x53, 0xde, 0x2e, 0xcf, 0x20, 0x51, 0x36, 0x42, 0x57, + 0xe7, 0x63, 0x51, 0x53, 0xe9, 0x36, 0x71, 0x30, 0xde, 0x3d, 0x0f, 0x4b, + 0x9b, 0x46, 0xe8, 0x41, 0xbf, 0x4c, 0xed, 0x4d, 0xc0, 0x44, 0x22, 0x48, + 0x59, 0x52, 0x7e, 0x53, 0x64, 0x3e, 0x61, 0x0d, 0x2a, 0xf2, 0xc6, 0xf3, + 0x09, 0xea, 0x05, 0xd8, 0xb2, 0xd7, 0xb1, 0xd0, 0xb6, 0xb2, 0x71, 0xb3, + 0xb7, 0xc0, 0xe3, 0xbe, 0xa0, 0xc8, 0x30, 0xd4, 0x16, 0xdd, 0x91, 0xeb, + 0x3e, 0xe3, 0xfd, 0xcf, 0x90, 0xce, 0x7d, 0xd3, 0xb9, 0xe1, 0xc5, 0xeb, + 0xa8, 0xe1, 0x89, 0xc5, 0xba, 0xb8, 0x5b, 0xbc, 0x47, 0xc5, 0x31, 0xdf, + 0xf1, 0xea, 0xe9, 0xf4, 0x5e, 0x03, 0x7c, 0x02, 0x51, 0x07, 0x03, 0x1d, + 0x83, 0x23, 0x26, 0x21, 0xa0, 0x1e, 0xc2, 0x06, 0x2b, 0x02, 0x1f, 0x12, + 0xbb, 0x21, 0x78, 0x2c, 0x1e, 0x2f, 0xa1, 0x2e, 0x9f, 0x31, 0x89, 0x3d, + 0xcb, 0x41, 0xe2, 0x49, 0xb1, 0x4e, 0x9d, 0x4e, 0x09, 0x54, 0x6f, 0x5a, + 0x55, 0x67, 0xb2, 0x62, 0x25, 0x45, 0x1f, 0x27, 0x16, 0x11, 0xa4, 0x08, + 0xe2, 0x22, 0x42, 0x44, 0x0e, 0x33, 0xa7, 0x07, 0xdc, 0xfc, 0x0a, 0x03, + 0x76, 0x04, 0xbf, 0xfe, 0x61, 0xe8, 0x95, 0xda, 0xe4, 0xdc, 0x64, 0xe3, + 0x0f, 0xed, 0xf0, 0xe1, 0x7d, 0xbe, 0xd1, 0xac, 0xe6, 0xb2, 0x2b, 0xca, + 0x57, 0xde, 0x10, 0xd2, 0xdc, 0xc5, 0xf2, 0xc6, 0xa4, 0xc9, 0x1c, 0xc6, + 0xd6, 0xc3, 0xc2, 0xcc, 0x84, 0xcd, 0xb3, 0xbe, 0x65, 0xb9, 0xf7, 0xc8, + 0x7a, 0xc5, 0xf5, 0xb5, 0x5c, 0xbd, 0x0c, 0xce, 0x00, 0xd8, 0x4a, 0xd1, + 0x70, 0xc5, 0x6c, 0xe0, 0x0d, 0x03, 0x0d, 0xfd, 0x03, 0xf0, 0xbf, 0xe2, + 0xc4, 0xd4, 0x2e, 0xd4, 0xe3, 0xe3, 0xdd, 0xeb, 0x32, 0xd4, 0xb1, 0xc7, + 0x8a, 0xd0, 0xe9, 0xdb, 0x3e, 0xe6, 0xe4, 0xf4, 0x0e, 0x0c, 0xb8, 0x0e, + 0xd5, 0x14, 0xf1, 0x20, 0x16, 0x08, 0x4b, 0x03, 0x9e, 0x26, 0x97, 0x34, + 0xbf, 0x29, 0xc8, 0x26, 0x75, 0x28, 0x29, 0x16, 0x5d, 0x03, 0x69, 0x12, + 0xda, 0x2c, 0x23, 0x2a, 0x9b, 0x2a, 0xc7, 0x38, 0xfb, 0x23, 0x91, 0x07, + 0x6e, 0x00, 0x9f, 0x06, 0xd1, 0x15, 0xca, 0x11, 0x8a, 0x04, 0xf1, 0xfc, + 0x8f, 0xf7, 0xce, 0x01, 0x6e, 0x0f, 0x9a, 0x1a, 0x1c, 0x23, 0x3b, 0x10, + 0xe2, 0xe6, 0xe9, 0xdb, 0xaa, 0xf1, 0xaa, 0x01, 0x9f, 0x06, 0x27, 0xf5, + 0x26, 0xe2, 0x1c, 0xdb, 0x10, 0xd2, 0x58, 0xcc, 0xb7, 0xc4, 0x24, 0xc4, + 0x62, 0xcc, 0xb3, 0xcb, 0x00, 0xbc, 0x2d, 0xb6, 0xa0, 0xc8, 0x75, 0xd1, + 0x24, 0xc5, 0x50, 0xbb, 0x39, 0xbb, 0x17, 0xba, 0x1c, 0xb8, 0xe7, 0xb5, + 0x72, 0xb1, 0xd7, 0xb5, 0x12, 0xc7, 0x5e, 0xd2, 0x1b, 0xc4, 0xd1, 0xb4, + 0x81, 0xc1, 0xaa, 0xdd, 0x62, 0xe7, 0x39, 0xda, 0xf3, 0xde, 0xf6, 0xdb, + 0x5e, 0xc6, 0x44, 0xc5, 0x9f, 0xc3, 0x8b, 0xcf, 0x6d, 0xe7, 0xc1, 0xe6, + 0x15, 0xde, 0x97, 0xdc, 0x88, 0xe9, 0x87, 0x02, 0x66, 0x15, 0x99, 0x14, + 0x41, 0x0c, 0x29, 0x12, 0x63, 0x1b, 0x24, 0x1e, 0x7b, 0x23, 0x35, 0x25, + 0x0e, 0x23, 0xa3, 0x2f, 0x93, 0x4a, 0x1d, 0x55, 0xe5, 0x3a, 0xe1, 0x19, + 0xca, 0x23, 0x11, 0x4b, 0x15, 0x51, 0xd8, 0x38, 0xbe, 0x27, 0x29, 0x22, + 0xf4, 0x1d, 0x13, 0x0c, 0x29, 0x06, 0x2f, 0x22, 0x00, 0x2e, 0x1c, 0x22, + 0x56, 0x12, 0xfc, 0xf2, 0xb3, 0xe9, 0xb8, 0xeb, 0xd8, 0xd9, 0xd0, 0xd7, + 0x8c, 0xe0, 0x8d, 0xe4, 0xff, 0xee, 0x5c, 0xf6, 0x23, 0xee, 0x59, 0xdc, + 0x6f, 0xdb, 0x65, 0xf9, 0x91, 0x0b, 0xce, 0xff, 0x35, 0xf8, 0xbb, 0x02, + 0xd6, 0x14, 0x76, 0x24, 0xcb, 0x28, 0x1f, 0x19, 0xfd, 0x17, 0xf3, 0x32, + 0x71, 0x41, 0xa3, 0x36, 0x20, 0x33, 0x49, 0x3f, 0x08, 0x38, 0x51, 0x2b, + 0x2c, 0x22, 0x7b, 0x13, 0xe4, 0x0b, 0x75, 0x04, 0x2b, 0x03, 0x48, 0x0b, + 0xea, 0x08, 0x05, 0xf7, 0xd2, 0xeb, 0x0a, 0xfb, 0xe6, 0x18, 0xb5, 0x2b, + 0xa4, 0x38, 0x5b, 0x40, 0x38, 0x3d, 0x30, 0x46, 0xe2, 0x47, 0x4c, 0x32, + 0xf0, 0x26, 0x24, 0x3a, 0xa5, 0x52, 0x59, 0x58, 0xd8, 0x4f, 0x96, 0x3d, + 0x02, 0x2d, 0x0c, 0x1c, 0x5b, 0x1c, 0x12, 0x2b, 0x94, 0x29, 0xe2, 0x1e, + 0xc7, 0x0c, 0x28, 0x03, 0xd6, 0x16, 0xb8, 0x2d, 0xa8, 0x1a, 0x5a, 0xf0, + 0xa5, 0xe4, 0xf9, 0xf8, 0x40, 0x09, 0x20, 0x08, 0xeb, 0x03, 0xc6, 0xfa, + 0x7f, 0xe5, 0xef, 0xcd, 0x18, 0xd6, 0x8c, 0xe0, 0x2b, 0xd6, 0xd1, 0xd7, + 0xed, 0xd3, 0x5f, 0xd8, 0x82, 0xe9, 0x93, 0xf0, 0x47, 0xef, 0x3f, 0xe9, + 0x3c, 0xfc, 0xce, 0x0b, 0x6a, 0xf9, 0x85, 0xe3, 0x6d, 0xd0, 0xf2, 0xd5, + 0x1f, 0xe6, 0x8c, 0xd7, 0x47, 0xcd, 0xd0, 0xd1, 0x01, 0xd3, 0xf9, 0xde, + 0x2b, 0xec, 0x3f, 0xe9, 0x73, 0xe2, 0x25, 0xe2, 0xf3, 0xf2, 0xe8, 0x0c, + 0x6d, 0x04, 0xe1, 0xea, 0x01, 0xfb, 0x01, 0x11, 0x76, 0x04, 0xb5, 0xff, + 0xbb, 0x04, 0xdd, 0x14, 0x99, 0x28, 0xbd, 0x18, 0x66, 0x0d, 0x63, 0x0d, + 0x0a, 0x0c, 0x75, 0x1d, 0xd1, 0x24, 0x19, 0x18, 0xd7, 0x1e, 0x96, 0x3f, + 0xe9, 0x3e, 0xcd, 0x1d, 0x32, 0x0f, 0x5d, 0x1a, 0xc6, 0x39, 0x0f, 0x4c, + 0x91, 0x39, 0xdd, 0x1b, 0xff, 0x16, 0xe6, 0x29, 0xcc, 0x43, 0xa4, 0x4d, + 0xbb, 0x3c, 0x0c, 0x39, 0x37, 0x41, 0x61, 0x47, 0xe9, 0x4a, 0x52, 0x46, + 0x1c, 0x36, 0x4c, 0x1a, 0x23, 0x11, 0x46, 0x20, 0x19, 0x33, 0x4b, 0x1e, + 0xb6, 0xee, 0xe1, 0xe1, 0x4e, 0xf3, 0x52, 0xfd, 0x61, 0xfb, 0xe0, 0xfb, + 0xe4, 0xed, 0xf6, 0xe3, 0xb3, 0xe8, 0x97, 0xf1, 0xd6, 0xfa, 0xe0, 0xef, + 0xa8, 0xe3, 0x2e, 0xdd, 0xce, 0xd9, 0x3e, 0xe2, 0x77, 0xf0, 0xcc, 0xfa, + 0x0e, 0x02, 0xae, 0x09, 0x59, 0x06, 0x8b, 0x00, 0x08, 0x0b, 0xb6, 0x18, + 0x3e, 0x16, 0x05, 0x14, 0x78, 0x25, 0x25, 0x37, 0x05, 0x31, 0x8f, 0x24, + 0xa6, 0x1d, 0x1e, 0x08, 0xa2, 0xee, 0xdd, 0xe9, 0xa5, 0xe9, 0x94, 0xdc, + 0x47, 0xc7, 0x17, 0xc9, 0xd7, 0xec, 0x67, 0xf1, 0x56, 0xde, 0xee, 0xdf, + 0xb0, 0xe1, 0xdd, 0xf1, 0xbb, 0x0c, 0x87, 0x1f, 0x64, 0x2c, 0x13, 0x27, + 0xf8, 0x30, 0x3a, 0x4b, 0x11, 0x3c, 0xd1, 0x28, 0x38, 0x2e, 0x7d, 0x2f, + 0x31, 0x3a, 0xd1, 0x41, 0x79, 0x2f, 0x5e, 0x1a, 0x83, 0x25, 0xa7, 0x33, + 0xe8, 0x26, 0xc0, 0x16, 0x35, 0x14, 0x64, 0x22, 0x93, 0x1a, 0x8d, 0x04, + 0x66, 0x04, 0xe3, 0x0e, 0x5d, 0x16, 0xf0, 0x02, 0xac, 0xd6, 0x90, 0xbc, + 0x1c, 0xc3, 0xac, 0xd5, 0x0d, 0xdf, 0x6e, 0xc8, 0xe7, 0xbe, 0x03, 0xe0, + 0x0d, 0xf9, 0x40, 0xf2, 0x17, 0xe1, 0x2b, 0xe6, 0x0a, 0xf8, 0xe9, 0x14, + 0x48, 0x19, 0x1d, 0xf8, 0xe3, 0xe3, 0xf9, 0xe5, 0x15, 0xfd, 0x86, 0xfd, + 0xc9, 0xf0, 0x15, 0xec, 0xe6, 0xda, 0x89, 0xe3, 0xdd, 0xea, 0x48, 0xcc, + 0x1a, 0xc5, 0x5f, 0xe5, 0x15, 0xf9, 0x89, 0xf9, 0x6a, 0xfa, 0x51, 0xfe, + 0x48, 0x13, 0xcf, 0x2b, 0xbf, 0x1d, 0x81, 0x0f, 0x4c, 0x18, 0xb6, 0x20, + 0x00, 0x32, 0x4d, 0x2b, 0xb6, 0x10, 0x09, 0x10, 0x10, 0x26, 0x9e, 0x30, + 0x61, 0x23, 0x52, 0x16, 0xda, 0x11, 0xda, 0x18, 0x1a, 0x1f, 0xea, 0x13, + 0x19, 0x05, 0x5e, 0x06, 0xc5, 0x0e, 0x94, 0x0b, 0x32, 0x02, 0x15, 0x02, + 0x6d, 0xfe, 0x40, 0xee, 0x58, 0xe6, 0x4b, 0xe2, 0xfa, 0xe5, 0xa1, 0xfa, + 0x64, 0x07, 0x88, 0xfe, 0x6c, 0xfb, 0xd3, 0x06, 0x59, 0x03, 0xbf, 0xf2, + 0x4e, 0xf1, 0xa2, 0xfe, 0x97, 0x00, 0x91, 0xfa, 0x7b, 0xe9, 0x36, 0xdb, + 0x54, 0xf4, 0x8a, 0x0e, 0x94, 0x04, 0x0b, 0xeb, 0x94, 0xdf, 0x75, 0xe0, + 0xb1, 0xdc, 0xc3, 0xe0, 0x3a, 0xef, 0x0f, 0xec, 0xf5, 0xe1, 0xa1, 0xf0, + 0xb1, 0x04, 0xb0, 0x0e, 0x3e, 0x17, 0x4e, 0x1e, 0xaf, 0x2a, 0x81, 0x37, + 0xa9, 0x37, 0x78, 0x2d, 0xe6, 0x26, 0x1d, 0x31, 0xe8, 0x3a, 0xcf, 0x3b, + 0x9a, 0x40, 0x63, 0x4e, 0xd8, 0x5d, 0x1f, 0x56, 0xec, 0x44, 0x02, 0x44, + 0x58, 0x51, 0x41, 0x62, 0xcc, 0x64, 0x52, 0x4b, 0xb7, 0x1e, 0x9a, 0x01, + 0x94, 0x01, 0xaa, 0x02, 0x6b, 0xf1, 0xa5, 0xe7, 0x8d, 0xe5, 0x89, 0xd6, + 0xaa, 0xc6, 0x42, 0xc8, 0xfe, 0xd4, 0x9b, 0xd8, 0x2b, 0xed, 0x9d, 0x10, + 0xa8, 0x1e, 0x3d, 0x13, 0x9a, 0x05, 0xfe, 0x03, 0x0b, 0xf9, 0x90, 0xf2, + 0x75, 0x01, 0x89, 0x1a, 0x5b, 0x28, 0x61, 0x24, 0x82, 0x13, 0x1f, 0x02, + 0x84, 0x1a, 0xa7, 0x38, 0x40, 0x2d, 0xb8, 0x23, 0xb8, 0x28, 0xaa, 0x23, + 0xe6, 0x20, 0x14, 0x1b, 0x24, 0x09, 0x85, 0xf4, 0x7e, 0xd7, 0x42, 0xca, + 0x7d, 0xd7, 0x4a, 0xdb, 0x4a, 0xcc, 0xb0, 0xc6, 0x2b, 0xcd, 0xd3, 0xcd, + 0xfb, 0xd0, 0x19, 0xe9, 0x0b, 0x16, 0xfe, 0x2d, 0x60, 0x1e, 0xaa, 0x03, + 0x6b, 0xe8, 0x1b, 0xe6, 0x4c, 0xf9, 0xf7, 0xec, 0xf7, 0xd7, 0xd1, 0xc9, + 0x98, 0xb5, 0xc7, 0xba, 0x43, 0xc4, 0x54, 0xc0, 0x7b, 0xba, 0xec, 0xab, + 0x26, 0xa7, 0x37, 0xb6, 0x41, 0xc0, 0xca, 0xbc, 0x87, 0xba, 0xb0, 0xc4, + 0x53, 0xdf, 0x8e, 0xe7, 0x11, 0xd1, 0x77, 0xc7, 0x86, 0xce, 0xcb, 0xd0, + 0xef, 0xd0, 0xdc, 0xcf, 0x96, 0xcd, 0xd3, 0xda, 0x14, 0xed, 0x91, 0xfc, + 0x4d, 0x11, 0xe3, 0x10, 0x60, 0x0c, 0x13, 0x15, 0xf7, 0x16, 0x1c, 0x19, + 0xb7, 0x16, 0xce, 0x13, 0x94, 0x1c, 0x35, 0x22, 0x5f, 0x09, 0x39, 0xe8, + 0x6a, 0xf0, 0x70, 0x0e, 0x7c, 0x1c, 0x30, 0x0b, 0x81, 0xf0, 0xd7, 0xf0, + 0xa0, 0x0b, 0x30, 0x21, 0x97, 0x18, 0x0f, 0x00, 0xfe, 0xf1, 0x4d, 0xfd, + 0x81, 0x07, 0x1e, 0xfa, 0x0f, 0xe0, 0x31, 0xd5, 0xc7, 0xeb, 0x92, 0x0b, + 0xe4, 0x14, 0x99, 0xfc, 0xcb, 0xe2, 0x32, 0xd7, 0x9f, 0xd1, 0x77, 0xd1, + 0x63, 0xd0, 0x03, 0xd6, 0xba, 0xd9, 0x80, 0xd8, 0xee, 0xdd, 0xb6, 0xe0, + 0xf7, 0xd9, 0x2d, 0xdb, 0x22, 0xf6, 0x0a, 0x1d, 0x6d, 0x2d, 0xda, 0x1c, + 0x43, 0x0c, 0x5d, 0x15, 0xdd, 0x2b, 0x4a, 0x3f, 0x75, 0x48, 0x49, 0x47, + 0xaf, 0x49, 0xe2, 0x4e, 0xae, 0x4b, 0x8c, 0x4c, 0xcc, 0x59, 0xf9, 0x66, + 0x5f, 0x6d, 0xb6, 0x69, 0x79, 0x63, 0x40, 0x67, 0x5a, 0x6f, 0xfb, 0x6d, + 0x20, 0x5d, 0xe1, 0x52, 0x69, 0x49, 0xf9, 0x31, 0x5a, 0x25, 0x2b, 0x24, + 0x73, 0x21, 0x18, 0x14, 0xb1, 0x07, 0xe1, 0x0c, 0x55, 0x0a, 0xde, 0x06, + 0x29, 0x1c, 0x94, 0x25, 0xee, 0x21, 0xa1, 0x23, 0xcd, 0x18, 0x82, 0x03, + 0x77, 0xfc, 0xec, 0x15, 0xa9, 0x0c, 0xe3, 0xe5, 0xf3, 0xe7, 0x46, 0xef, + 0x09, 0xe5, 0xe0, 0xeb, 0xb7, 0x0b, 0xd9, 0x04, 0x0a, 0xe6, 0xcb, 0xd6, + 0x84, 0xc6, 0x83, 0xc9, 0x80, 0xd6, 0x2e, 0xdb, 0xf4, 0xd2, 0x85, 0xcb, + 0x15, 0xd1, 0xcc, 0xd5, 0x0c, 0xd5, 0x38, 0xda, 0x84, 0xe7, 0x46, 0xfc, + 0xe8, 0x06, 0xcb, 0xf6, 0x8d, 0xf7, 0x5c, 0xf7, 0x73, 0xfe, 0x9a, 0x22, + 0xd2, 0x27, 0xc6, 0x1e, 0x48, 0x25, 0x71, 0x30, 0x55, 0x27, 0x17, 0x18, + 0xe1, 0x15, 0xff, 0x17, 0xea, 0x25, 0xe6, 0x1d, 0x47, 0x10, 0x2a, 0x12, + 0x37, 0x05, 0x5b, 0x04, 0x80, 0x0a, 0xd8, 0x02, 0xc6, 0x0b, 0xc2, 0x09, + 0x8e, 0xfd, 0xc3, 0x0a, 0x96, 0x09, 0xbd, 0xff, 0x02, 0xf8, 0x34, 0xf0, + 0x6d, 0xfc, 0xc0, 0xff, 0x44, 0xf4, 0x09, 0xf7, 0xd8, 0x01, 0xab, 0xf8, + 0xc6, 0xf1, 0x10, 0xef, 0x3f, 0xde, 0x31, 0xe6, 0xaf, 0xfa, 0xf0, 0x04, + 0x3c, 0x01, 0x37, 0xe6, 0x51, 0xd7, 0x52, 0xe6, 0x63, 0x08, 0xb1, 0x19, + 0x34, 0xfe, 0x99, 0xe7, 0xd7, 0xf3, 0x0f, 0xfb, 0xa9, 0xf4, 0x91, 0xf8, + 0x52, 0xfd, 0xa5, 0xfa, 0x8d, 0xf5, 0xa3, 0xef, 0xcd, 0xf8, 0x6d, 0x05, + 0x19, 0x0b, 0xd4, 0x16, 0xdb, 0x17, 0x04, 0x11, 0xdf, 0x1b, 0x4e, 0x28, + 0x9a, 0x23, 0xae, 0x14, 0x40, 0x08, 0xba, 0x0d, 0x24, 0x15, 0xb2, 0x06, + 0x1d, 0xfc, 0xc9, 0x0c, 0xcb, 0x0f, 0x5b, 0x00, 0x18, 0x0b, 0xa3, 0x1c, + 0x5c, 0x23, 0x6b, 0x2c, 0x8f, 0x36, 0xd6, 0x2f, 0x47, 0x23, 0x6c, 0x1f, + 0x0f, 0x1c, 0xa8, 0x2d, 0x20, 0x36, 0x9d, 0x26, 0xc7, 0x12, 0xaa, 0xfd, + 0xbd, 0x01, 0xe0, 0x22, 0xed, 0x3c, 0xb0, 0x31, 0x48, 0x2c, 0xe8, 0x3b, + 0xc6, 0x3c, 0x95, 0x33, 0xaf, 0x30, 0xdf, 0x33, 0x91, 0x37, 0xf3, 0x34, + 0x56, 0x30, 0xac, 0x33, 0xbf, 0x1a, 0x0e, 0xf7, 0x8e, 0xf0, 0x1a, 0xff, + 0x5f, 0x11, 0x9b, 0xfc, 0xa4, 0xde, 0xa9, 0xf3, 0x9f, 0x12, 0x23, 0x0d, + 0x2a, 0x18, 0x3e, 0x39, 0x19, 0x3d, 0x27, 0x33, 0xf2, 0x2b, 0xdb, 0x23, + 0x3f, 0x17, 0x66, 0x0d, 0xf2, 0x08, 0x0f, 0x04, 0x07, 0x06, 0x3c, 0x14, + 0x11, 0x0d, 0x84, 0xe5, 0x55, 0xe0, 0x3d, 0xec, 0x1a, 0xe2, 0x94, 0xe6, + 0xbd, 0xed, 0xe9, 0xea, 0xc5, 0xdd, 0x47, 0xcf, 0x2c, 0xd9, 0xb3, 0xe0, + 0x13, 0xdb, 0xeb, 0xde, 0x41, 0xea, 0xf5, 0xdf, 0xe4, 0xd8, 0x8a, 0xf7, + 0x2b, 0x03, 0x20, 0xfd, 0x74, 0xf4, 0x04, 0xe3, 0xea, 0xee, 0xb6, 0x01, + 0x08, 0xff, 0xe5, 0xf0, 0xba, 0xec, 0xe4, 0xf8, 0x75, 0x0f, 0xc1, 0x14, + 0xfd, 0xfd, 0x1e, 0x05, 0x54, 0x14, 0x19, 0x14, 0x10, 0x15, 0x0f, 0x0c, + 0xb0, 0x0f, 0x8a, 0x1f, 0x2b, 0x1b, 0x46, 0x0b, 0x78, 0x0b, 0xc1, 0x04, + 0x93, 0x0a, 0xdc, 0x15, 0x61, 0x02, 0x0e, 0x06, 0x3c, 0x20, 0x31, 0x1f, + 0x8d, 0x05, 0x04, 0x03, 0xfb, 0x0b, 0x39, 0x08, 0x68, 0xf8, 0x47, 0xe0, + 0x1e, 0xe0, 0x64, 0xec, 0xc1, 0xf7, 0x73, 0xf4, 0x06, 0xe3, 0x88, 0xc9, + 0xa4, 0xb8, 0xb7, 0xc7, 0x43, 0xdc, 0x32, 0xdd, 0xc9, 0xd0, 0x69, 0xd4, + 0x0a, 0xd7, 0x4e, 0xd2, 0x4a, 0xcb, 0xe2, 0xbf, 0x33, 0xbf, 0x90, 0xbf, + 0xd0, 0xb7, 0x3b, 0xa9, 0xec, 0xaa, 0x92, 0xb8, 0xfa, 0xbd, 0x34, 0xb7, + 0xce, 0xad, 0x62, 0xb6, 0x85, 0xc7, 0xaf, 0xca, 0xbf, 0xc1, 0x16, 0xbe, + 0x22, 0xc3, 0x59, 0xbf, 0x0f, 0xb5, 0xad, 0xbb, 0x84, 0xc4, 0xcf, 0xd0, + 0xcf, 0xe0, 0x20, 0xe1, 0x36, 0xe1, 0x36, 0xe7, 0x09, 0xe4, 0x19, 0xe1, + 0xbc, 0xe8, 0xe8, 0xef, 0x5b, 0xfc, 0x2c, 0x07, 0x3b, 0x18, 0x96, 0x28, + 0x86, 0x31, 0x35, 0x3e, 0xfc, 0x37, 0x37, 0x2d, 0x80, 0x1d, 0x7b, 0x05, + 0x6e, 0xff, 0x0f, 0x0f, 0x80, 0x24, 0x10, 0x24, 0xcf, 0x0e, 0x45, 0x0f, + 0x88, 0x1d, 0xf4, 0x26, 0x89, 0x40, 0xc3, 0x54, 0xee, 0x52, 0x5b, 0x2f, + 0xa1, 0x06, 0xff, 0xff, 0xc1, 0xff, 0xce, 0xf3, 0x45, 0xee, 0x98, 0xee, + 0x17, 0xd8, 0x2b, 0xc7, 0xbc, 0xd1, 0xee, 0xe6, 0xb3, 0xec, 0x4b, 0xe5, + 0x9b, 0xfc, 0xba, 0x16, 0x36, 0x10, 0xe2, 0x18, 0xc1, 0x31, 0xdf, 0x18, + 0x66, 0xf7, 0x3f, 0x06, 0x17, 0x1d, 0xd4, 0x17, 0x1f, 0x04, 0xfc, 0xfc, + 0x4a, 0xf0, 0xaf, 0xd6, 0xab, 0xdc, 0x38, 0xe6, 0x65, 0xd4, 0xb1, 0xd4, + 0x6b, 0xcb, 0x97, 0xbc, 0x9f, 0xc7, 0xff, 0xcf, 0xa5, 0xd9, 0x1a, 0xe3, + 0x2c, 0xdf, 0xdf, 0xd3, 0xd4, 0xda, 0x6d, 0xdf, 0xaf, 0xca, 0xe8, 0xbc, + 0x9f, 0xb3, 0x8d, 0xb2, 0x51, 0xc2, 0x33, 0xc4, 0x49, 0xc0, 0x45, 0xca, + 0x2b, 0xd9, 0x5d, 0xe3, 0x0c, 0xe6, 0xb9, 0xf3, 0x1f, 0x0a, 0xcd, 0x17, + 0xae, 0x0f, 0x31, 0xfa, 0x79, 0xe9, 0x4c, 0xe5, 0x75, 0xe0, 0x47, 0xd2, + 0xf0, 0xd5, 0x6b, 0xd1, 0x81, 0xc7, 0x9a, 0xd1, 0x29, 0xde, 0xd7, 0xe5, + 0x05, 0xe9, 0x77, 0xf1, 0xb0, 0xf8, 0xa5, 0xfb, 0x2a, 0xf5, 0x85, 0xf4, + 0xea, 0xff, 0x40, 0x0c, 0x64, 0x14, 0x6a, 0x0b, 0x45, 0x02, 0x26, 0xfc, + 0xd2, 0xfb, 0x23, 0xfe, 0x5f, 0xfe, 0xe7, 0x01, 0x53, 0x02, 0x21, 0xfc, + 0x50, 0xf0, 0xb0, 0xf4, 0x4f, 0x07, 0x5d, 0x15, 0x0f, 0x11, 0xb7, 0x04, + 0x7a, 0xff, 0x97, 0xfd, 0x75, 0xf9, 0x3f, 0xdc, 0x4b, 0xc3, 0xf3, 0xc8, + 0x27, 0xd6, 0x84, 0xd7, 0x4b, 0xcc, 0xd1, 0xd2, 0x86, 0xe1, 0xfa, 0xe6, + 0x6f, 0xe8, 0xf2, 0xe0, 0xfc, 0xe1, 0x6c, 0x04, 0x22, 0x1d, 0xfc, 0x08, + 0xf1, 0xee, 0xbc, 0xe0, 0x69, 0xe4, 0x28, 0xed, 0xaf, 0xff, 0xb5, 0x11, + 0x12, 0x0b, 0xa4, 0x0c, 0x2a, 0x18, 0x4a, 0x29, 0x79, 0x2e, 0xa6, 0x2b, + 0x8b, 0x2a, 0x32, 0x2c, 0xcf, 0x3b, 0x06, 0x40, 0x49, 0x47, 0x58, 0x4a, + 0x88, 0x3f, 0x0a, 0x3e, 0xd5, 0x40, 0x5b, 0x47, 0xd1, 0x4d, 0xcb, 0x4e, + 0x43, 0x4d, 0x3b, 0x51, 0xf8, 0x5a, 0xa4, 0x58, 0x00, 0x50, 0x01, 0x59, + 0x3d, 0x69, 0x98, 0x6c, 0x74, 0x61, 0xd6, 0x59, 0x0f, 0x5c, 0x06, 0x4f, + 0x03, 0x2c, 0xa3, 0x16, 0xc4, 0x0e, 0x78, 0xf8, 0xf8, 0xf1, 0x3a, 0xf8, + 0x97, 0xe7, 0x08, 0xd6, 0xe5, 0xe4, 0x08, 0xf0, 0xe8, 0xe8, 0x48, 0xfb, + 0x75, 0x16, 0x06, 0x12, 0x72, 0xf5, 0xb1, 0xf3, 0x58, 0x02, 0xdd, 0xfd, + 0xdc, 0xf2, 0x95, 0xe6, 0x9a, 0xdb, 0x46, 0xe2, 0x84, 0xf1, 0xcd, 0xe2, + 0x62, 0xd5, 0x3c, 0xd8, 0x25, 0xd8, 0xd7, 0xe7, 0xd2, 0xfa, 0xdd, 0xf9, + 0x44, 0xf4, 0xad, 0xfd, 0xd0, 0x07, 0x7d, 0x10, 0xe5, 0x10, 0xa7, 0x01, + 0x5d, 0xf2, 0xb6, 0xeb, 0x5e, 0xf0, 0x75, 0xf9, 0x83, 0xf6, 0x30, 0xe0, + 0xf3, 0xd1, 0x0c, 0xdc, 0xa4, 0xeb, 0x45, 0xf2, 0x35, 0x00, 0x6f, 0x14, + 0x47, 0x15, 0x8a, 0x12, 0x15, 0x12, 0x3d, 0x12, 0xbf, 0x24, 0xfb, 0x39, + 0x01, 0x3e, 0xd9, 0x20, 0xd9, 0xf1, 0x82, 0xef, 0x3a, 0x10, 0x0d, 0x1d, + 0x6e, 0x0f, 0x52, 0x02, 0x1e, 0x01, 0xf4, 0x0c, 0x7e, 0x1f, 0x6e, 0x1f, + 0xaf, 0x1d, 0xde, 0x1c, 0x62, 0x18, 0x5d, 0x1c, 0xb9, 0x17, 0x17, 0x12, + 0x6f, 0x0d, 0x10, 0x0c, 0x59, 0x18, 0xa1, 0x17, 0xd4, 0x03, 0x42, 0x04, + 0x72, 0x1c, 0x4f, 0x26, 0x67, 0x25, 0x90, 0x20, 0x4f, 0x18, 0x48, 0x24, + 0x20, 0x31, 0x77, 0x30, 0x1b, 0x2e, 0x68, 0x27, 0x3b, 0x22, 0xd5, 0x19, + 0x1d, 0x16, 0x90, 0x16, 0xeb, 0x05, 0x9c, 0xf1, 0x5e, 0xec, 0x3d, 0xf1, + 0xad, 0xf9, 0x9f, 0x00, 0x96, 0x06, 0xbb, 0x0d, 0x69, 0x03, 0x8c, 0xfc, + 0x8f, 0xff, 0x85, 0xef, 0x0d, 0xe7, 0x6c, 0xeb, 0x8f, 0xea, 0xd6, 0xe9, + 0x45, 0xf2, 0x2b, 0x01, 0xdf, 0x06, 0xb0, 0x05, 0xff, 0xf8, 0xf1, 0xe2, + 0x5b, 0xdf, 0x85, 0xf0, 0x6c, 0x01, 0x6b, 0x02, 0x5c, 0xfe, 0x4f, 0x00, + 0xdf, 0xfb, 0x16, 0xf7, 0x35, 0xf2, 0xd5, 0xea, 0xc0, 0xf2, 0xdc, 0x07, + 0x0f, 0x11, 0x8d, 0xf7, 0x71, 0xe4, 0xdb, 0x00, 0x92, 0x14, 0x67, 0x17, + 0x2a, 0x2a, 0x9b, 0x29, 0x67, 0x24, 0xba, 0x3e, 0x77, 0x59, 0x0d, 0x5a, + 0x13, 0x52, 0x21, 0x49, 0x0c, 0x45, 0x83, 0x4c, 0x9b, 0x38, 0x03, 0x1d, + 0x4f, 0x09, 0x85, 0xec, 0xcf, 0xe7, 0x59, 0xf5, 0xef, 0xf4, 0xd7, 0xe9, + 0x9a, 0xf4, 0x74, 0xfb, 0xd2, 0xf7, 0xf0, 0x0c, 0xba, 0x1a, 0xaa, 0x13, + 0x64, 0x11, 0xc6, 0x1e, 0x0d, 0x0c, 0x79, 0xe3, 0x4d, 0xe6, 0x4d, 0xfb, + 0x67, 0xfb, 0x0c, 0xec, 0x47, 0xea, 0xff, 0xf1, 0x6a, 0xed, 0xa2, 0xd8, + 0xb4, 0xc8, 0x59, 0xd5, 0x08, 0xee, 0x87, 0x02, 0x7a, 0x0a, 0x3c, 0x00, + 0xc7, 0xf1, 0x47, 0xed, 0x94, 0xea, 0xce, 0xf8, 0xe6, 0x10, 0x38, 0x0b, + 0x94, 0xfe, 0xfd, 0xfa, 0x83, 0xf9, 0xf2, 0xf6, 0xfb, 0xec, 0xf1, 0xeb, + 0xe3, 0xfd, 0x37, 0x15, 0x72, 0x21, 0xb1, 0x2b, 0xcc, 0x38, 0xa9, 0x38, + 0x79, 0x30, 0x37, 0x25, 0x0c, 0x1b, 0xd8, 0x1d, 0x89, 0x12, 0x9b, 0xf7, + 0xb4, 0xf4, 0x8e, 0xfa, 0x91, 0xf7, 0x51, 0xea, 0xbd, 0xd8, 0xef, 0xe2, + 0xd5, 0xef, 0x65, 0xf0, 0x72, 0xef, 0x68, 0xe8, 0x1c, 0xf0, 0x65, 0xf8, + 0xd1, 0xf5, 0x28, 0xee, 0xa0, 0xeb, 0x4c, 0xf9, 0x3f, 0xfd, 0x41, 0xea, + 0xfd, 0xd7, 0xb0, 0xd5, 0xae, 0xd4, 0x87, 0xdd, 0xfc, 0xe5, 0x23, 0xdd, + 0x1b, 0xdb, 0x86, 0xe4, 0xb8, 0xeb, 0x8b, 0xe6, 0xc4, 0xd9, 0xef, 0xcc, + 0xca, 0xd4, 0xf5, 0xed, 0x31, 0xed, 0xaa, 0xd0, 0x3e, 0xbf, 0xfa, 0xcc, + 0x91, 0xe4, 0xe5, 0xe7, 0x3c, 0xd5, 0x5c, 0xc7, 0x7c, 0xd7, 0xd2, 0xf8, + 0x02, 0x05, 0x60, 0x05, 0x9e, 0x07, 0x1c, 0x14, 0xac, 0x22, 0x26, 0x15, + 0x01, 0x17, 0x72, 0x26, 0x0d, 0x2b, 0xf2, 0x2e, 0x09, 0x28, 0xcc, 0x2a, + 0x26, 0x36, 0x95, 0x37, 0x5f, 0x31, 0x31, 0x27, 0x1f, 0x2a, 0xfb, 0x39, + 0x88, 0x36, 0x64, 0x2d, 0x23, 0x34, 0x35, 0x3f, 0x27, 0x3d, 0x0b, 0x26, + 0x03, 0x23, 0x08, 0x2e, 0x8d, 0x30, 0x94, 0x34, 0xa6, 0x27, 0x27, 0x24, + 0xcd, 0x31, 0x28, 0x28, 0x05, 0x21, 0xa5, 0x20, 0x47, 0x27, 0x9c, 0x41, + 0xab, 0x38, 0x90, 0x2f, 0x6a, 0x44, 0x49, 0x49, 0x1c, 0x4a, 0xb0, 0x45, + 0x53, 0x39, 0x02, 0x24, 0xab, 0x05, 0x23, 0xf3, 0xac, 0xe8, 0xb6, 0xe1, + 0x73, 0xe2, 0x4d, 0xda, 0x79, 0xcb, 0x6d, 0xcd, 0x13, 0xd8, 0x5d, 0xde, + 0x14, 0xec, 0x8e, 0x19, 0x31, 0x3b, 0x66, 0x2c, 0x7e, 0x20, 0xd3, 0x21, + 0x96, 0x16, 0x45, 0x05, 0x7b, 0x00, 0xf2, 0x02, 0xee, 0x01, 0x8d, 0x01, + 0x43, 0x04, 0x27, 0xfb, 0xd9, 0xf5, 0x23, 0x04, 0x8a, 0x04, 0x7e, 0x02, + 0x27, 0x08, 0x56, 0x14, 0x10, 0x16, 0x6a, 0x08, 0xa7, 0x10, 0xd9, 0x0c, + 0x71, 0xf8, 0xc5, 0xf6, 0xdc, 0x00, 0xad, 0x04, 0x4f, 0xf1, 0x19, 0xdb, + 0xe2, 0xe0, 0xed, 0xed, 0x0f, 0xf0, 0x2e, 0xf0, 0x3e, 0xf5, 0xec, 0x11, + 0x00, 0x2c, 0x6b, 0x30, 0xe8, 0x2b, 0xf2, 0x27, 0x02, 0x29, 0xfa, 0x24, + 0x54, 0x2d, 0x86, 0x34, 0x03, 0x26, 0xb8, 0x07, 0xe7, 0xec, 0x9c, 0xf0, + 0xc3, 0xfd, 0xff, 0xfa, 0x89, 0xe8, 0x99, 0xd6, 0xec, 0xd9, 0x91, 0xe5, + 0x99, 0xd9, 0xfa, 0xc9, 0x9e, 0xd4, 0xe8, 0xdd, 0xcb, 0xde, 0xf6, 0xe0, + 0xf3, 0xd9, 0xa8, 0xdc, 0xf6, 0xe4, 0x03, 0xdc, 0x96, 0xda, 0x78, 0xde, + 0xda, 0xdf, 0xbc, 0xeb, 0x1c, 0xef, 0xd8, 0xe8, 0xf5, 0xe1, 0x18, 0xdd, + 0x59, 0xe8, 0x9e, 0xf6, 0xfc, 0xfb, 0x05, 0xfd, 0x02, 0xf7, 0xe3, 0xe7, + 0xa8, 0xd7, 0xf1, 0xd6, 0x85, 0xd8, 0x47, 0xcf, 0xdc, 0xc6, 0xa8, 0xbd, + 0x87, 0xb3, 0xb3, 0xb5, 0x9e, 0xc3, 0xcb, 0xcf, 0x8c, 0xd4, 0x19, 0xd2, + 0x90, 0xda, 0x0f, 0xef, 0x5a, 0x01, 0x72, 0x07, 0xdb, 0xfb, 0x28, 0xf4, + 0x9b, 0xf5, 0xfb, 0xfb, 0x36, 0xfe, 0x5b, 0xfc, 0x92, 0x05, 0xa6, 0x11, + 0x3b, 0x10, 0x5f, 0x0b, 0x88, 0x1c, 0x2a, 0x29, 0xa1, 0x24, 0xd3, 0x23, + 0x79, 0x1f, 0x41, 0x1c, 0x6f, 0x15, 0x38, 0x10, 0x8d, 0x20, 0x21, 0x3a, + 0xca, 0x3e, 0x9d, 0x28, 0x10, 0x18, 0x0d, 0x1f, 0xc5, 0x39, 0x00, 0x3d, + 0xc2, 0x26, 0x31, 0x25, 0x44, 0x34, 0xb8, 0x4d, 0xb3, 0x53, 0x24, 0x4d, + 0x45, 0x4e, 0x5d, 0x4c, 0xb7, 0x52, 0x0a, 0x4c, 0x6a, 0x31, 0xc7, 0x09, + 0xc4, 0xe7, 0x62, 0xd5, 0x5d, 0xca, 0x83, 0xd7, 0xca, 0xe0, 0xf6, 0xc5, + 0x2a, 0xb5, 0xc0, 0xc4, 0x93, 0xce, 0x36, 0xd2, 0xed, 0xd6, 0x11, 0xde, + 0x3a, 0xd8, 0xcc, 0xcc, 0xf9, 0xe2, 0xef, 0xe7, 0x8f, 0xc6, 0x6d, 0xb8, + 0xf6, 0xbc, 0x93, 0xbf, 0x3b, 0xd2, 0x51, 0xe4, 0xa8, 0xe0, 0x7d, 0xdf, + 0x65, 0xe9, 0xc6, 0xe6, 0x8e, 0xdc, 0x08, 0xe7, 0x27, 0xff, 0xf3, 0x14, + 0x85, 0x06, 0x6a, 0xee, 0x3c, 0xf6, 0xac, 0x00, 0xf1, 0x10, 0x11, 0x13, + 0x4f, 0xff, 0x81, 0xfe, 0x33, 0x09, 0xbb, 0x18, 0xf2, 0x2d, 0x9a, 0x30, + 0xe3, 0x30, 0x7e, 0x33, 0x22, 0x34, 0xc2, 0x47, 0x27, 0x5a, 0x93, 0x64, + 0x14, 0x6b, 0x69, 0x6d, 0xa8, 0x67, 0xc9, 0x60, 0x9b, 0x61, 0x03, 0x5c, + 0x6a, 0x4e, 0xde, 0x30, 0xac, 0x1e, 0x94, 0x21, 0x69, 0x19, 0xae, 0x06, + 0xc4, 0xf6, 0xca, 0xf9, 0x3c, 0x0c, 0x7d, 0x12, 0x61, 0x0c, 0xed, 0x07, + 0xc8, 0xff, 0x46, 0x03, 0x6e, 0x11, 0xd2, 0x0c, 0x46, 0xfa, 0xbe, 0xf7, + 0x0d, 0x00, 0x2f, 0x06, 0x35, 0x0c, 0xf4, 0xff, 0x13, 0xf3, 0xe2, 0xef, + 0x12, 0xef, 0x0b, 0xf7, 0x2e, 0xf6, 0x2d, 0xea, 0x2e, 0xdf, 0x7a, 0xdf, + 0xa2, 0xe9, 0x0f, 0xf6, 0x0f, 0xff, 0x3a, 0xf3, 0x4b, 0xda, 0x22, 0xd2, + 0x9d, 0xd7, 0x90, 0xe0, 0xa5, 0xec, 0xd2, 0xf0, 0x62, 0xf3, 0xc4, 0xfa, + 0x06, 0x05, 0xbd, 0x0e, 0xdd, 0x14, 0x87, 0x28, 0x7b, 0x43, 0x43, 0x51, + 0x7a, 0x54, 0x34, 0x4d, 0xcd, 0x3d, 0x9b, 0x2f, 0x41, 0x2c, 0xd4, 0x37, + 0xf1, 0x40, 0x25, 0x3a, 0x2c, 0x30, 0x59, 0x29, 0x3a, 0x24, 0xc5, 0x22, + 0xe3, 0x29, 0x1c, 0x2e, 0x84, 0x21, 0xab, 0x1d, 0xdf, 0x23, 0x5a, 0x2e, + 0xb8, 0x2c, 0x9d, 0x1d, 0x1c, 0x27, 0x2b, 0x30, 0x3c, 0x35, 0x3b, 0x32, + 0x6e, 0x1e, 0xc0, 0x22, 0xd4, 0x3a, 0x66, 0x46, 0x05, 0x43, 0xe8, 0x47, + 0x0a, 0x47, 0x01, 0x35, 0x1c, 0x2b, 0xc2, 0x3d, 0xae, 0x4b, 0x67, 0x33, + 0xaa, 0x1e, 0x61, 0x1a, 0x96, 0x02, 0xed, 0xd8, 0x98, 0xca, 0x02, 0xd4, + 0xfd, 0xd9, 0x10, 0xd2, 0xcf, 0xc4, 0xaa, 0xce, 0x20, 0xd3, 0x18, 0xc9, + 0x23, 0xda, 0x66, 0xfc, 0xec, 0xfd, 0x70, 0xf0, 0xa3, 0xf3, 0xef, 0xf1, + 0x45, 0xe8, 0x32, 0xe5, 0x9c, 0xe9, 0x9c, 0xdf, 0xc6, 0xd7, 0x31, 0xdf, + 0x73, 0xd4, 0x18, 0xd3, 0xa6, 0xec, 0xf7, 0xeb, 0xd2, 0xdb, 0x14, 0xdb, + 0x71, 0xd9, 0xe8, 0xdd, 0xc7, 0xe8, 0xa2, 0xf8, 0x86, 0x00, 0x06, 0xf0, + 0x73, 0xd9, 0x57, 0xcf, 0xb5, 0xdf, 0x4e, 0xf3, 0xb3, 0xf3, 0xde, 0xed, + 0x9d, 0xf8, 0x51, 0x0f, 0x96, 0x10, 0x2b, 0x09, 0x03, 0x07, 0x4d, 0x17, + 0x83, 0x3c, 0xca, 0x48, 0x95, 0x4f, 0x64, 0x5d, 0x96, 0x5c, 0x09, 0x5e, + 0x5e, 0x57, 0xab, 0x48, 0x97, 0x38, 0x56, 0x2f, 0xbf, 0x32, 0xb4, 0x2f, + 0xc0, 0x19, 0xa5, 0x00, 0x96, 0x00, 0xf9, 0x02, 0xb5, 0x05, 0xc5, 0x01, + 0x15, 0xee, 0x56, 0xec, 0xbd, 0xf6, 0x7a, 0xff, 0x36, 0xfb, 0xba, 0xee, + 0xd5, 0xea, 0xf4, 0xf1, 0x69, 0xf0, 0xce, 0xe7, 0x56, 0xe8, 0x14, 0xe8, + 0x63, 0xf0, 0x04, 0xf8, 0xea, 0xf5, 0xff, 0xed, 0x7b, 0xea, 0xed, 0xe7, + 0xcf, 0xe7, 0x14, 0xf1, 0xf3, 0xf1, 0x59, 0xf7, 0xc7, 0xf4, 0x13, 0xe5, + 0x14, 0xd2, 0x96, 0xc6, 0x28, 0xcd, 0x6a, 0xd1, 0xba, 0xcd, 0x1b, 0xba, + 0xd2, 0xa8, 0x57, 0xaa, 0xda, 0xaf, 0x17, 0xae, 0xe6, 0xaf, 0x4d, 0xbc, + 0x86, 0xd2, 0x01, 0xe3, 0xd3, 0xdf, 0xe2, 0xe5, 0x1d, 0xe8, 0xae, 0xea, + 0x41, 0xed, 0xce, 0xe7, 0xc9, 0xf9, 0xe6, 0x05, 0xba, 0x04, 0x23, 0x05, + 0x2c, 0xfc, 0x67, 0xf7, 0xf7, 0x0b, 0x8b, 0x26, 0x14, 0x2b, 0xa6, 0x1f, + 0xed, 0x15, 0xb1, 0x11, 0x30, 0x0d, 0x9c, 0x11, 0x88, 0x11, 0xf2, 0x0b, + 0xb4, 0x0d, 0xc3, 0x11, 0x49, 0x17, 0xe5, 0x1a, 0x69, 0x22, 0x81, 0x2c, + 0xda, 0x2d, 0x2d, 0x2f, 0x93, 0x43, 0xa4, 0x53, 0x09, 0x58, 0x38, 0x4f, + 0xbb, 0x3f, 0x42, 0x41, 0x61, 0x36, 0xec, 0x21, 0x47, 0x09, 0x5e, 0xfb, + 0xb1, 0xf2, 0x79, 0xe1, 0x0a, 0xdb, 0x82, 0xca, 0x4f, 0xd0, 0x86, 0xe3, + 0x7d, 0xd8, 0xf4, 0xce, 0x13, 0xe1, 0xf7, 0xec, 0x32, 0xf2, 0x5f, 0x08, + 0x04, 0xff, 0xbe, 0xe2, 0xc1, 0xd6, 0x37, 0xde, 0x27, 0xe8, 0x70, 0xdf, + 0x7c, 0xcf, 0x70, 0xc8, 0x1a, 0xd0, 0xef, 0xd2, 0xc6, 0xd6, 0xc4, 0xde, + 0x14, 0xeb, 0x0c, 0xea, 0xe9, 0xe2, 0xb4, 0xdc, 0xf5, 0xcf, 0x68, 0xd9, + 0x5f, 0xde, 0x14, 0xe4, 0x72, 0xdb, 0x50, 0xc3, 0xcc, 0xbe, 0x4e, 0xc0, + 0xf7, 0xd4, 0x07, 0xdd, 0xea, 0xce, 0xda, 0xcf, 0x26, 0xdc, 0xd9, 0xe5, + 0xef, 0xe8, 0x66, 0xeb, 0xec, 0xfd, 0xbf, 0x0b, 0x6c, 0x0e, 0xec, 0x21, + 0x0b, 0x2c, 0x4d, 0x2d, 0x84, 0x28, 0xe2, 0x1b, 0xd5, 0x14, 0xae, 0x16, + 0x66, 0x16, 0xb3, 0x05, 0x77, 0xfc, 0x67, 0xf1, 0xd5, 0xee, 0x31, 0xf6, + 0x63, 0xf6, 0x61, 0xfd, 0x92, 0xfb, 0x96, 0xeb, 0xb3, 0xde, 0xbd, 0xe7, + 0xa9, 0xed, 0xb2, 0xde, 0x01, 0xcd, 0xe7, 0xc6, 0x7c, 0xd5, 0x13, 0xe3, + 0x9c, 0xde, 0xd9, 0xd0, 0x6f, 0xc8, 0xd4, 0xcf, 0x3f, 0xe3, 0x93, 0xea, + 0x90, 0xe7, 0x71, 0xe3, 0xe9, 0xdf, 0x79, 0xe3, 0x85, 0xe4, 0x1b, 0xe8, + 0x92, 0xe7, 0x68, 0xe6, 0x6f, 0xef, 0xee, 0xea, 0xaa, 0xd9, 0xff, 0xd5, + 0xa9, 0xe3, 0x36, 0xf1, 0x85, 0xf5, 0x43, 0xf4, 0x42, 0xf2, 0x8d, 0xee, + 0x82, 0xed, 0xed, 0xf6, 0xdd, 0x08, 0x0c, 0x0f, 0x95, 0x0c, 0xdf, 0x1c, + 0x15, 0x32, 0x22, 0x33, 0xda, 0x20, 0x66, 0x0a, 0x4e, 0x02, 0x00, 0x15, + 0x68, 0x26, 0x29, 0x19, 0x60, 0x02, 0x5c, 0xf7, 0x9d, 0x02, 0x38, 0x16, + 0xa4, 0x22, 0x7a, 0x25, 0x29, 0x1e, 0x89, 0x21, 0x28, 0x24, 0x01, 0x1e, + 0x2f, 0x1f, 0x3c, 0x23, 0xb0, 0x2c, 0xd0, 0x2d, 0xfc, 0x26, 0x89, 0x2a, + 0x79, 0x31, 0x86, 0x32, 0xba, 0x34, 0x3e, 0x47, 0x62, 0x50, 0x73, 0x50, + 0x8e, 0x5a, 0xcc, 0x5c, 0xa1, 0x54, 0x49, 0x43, 0x41, 0x23, 0xb1, 0xf3, + 0x36, 0xd2, 0xac, 0xd1, 0xe4, 0xe2, 0x9e, 0xde, 0x97, 0xc1, 0xdb, 0xc4, + 0xdf, 0xe0, 0x61, 0xe0, 0xff, 0xc9, 0xb6, 0xda, 0x0a, 0xfc, 0x11, 0xfd, + 0x30, 0x05, 0xed, 0x13, 0xa6, 0x07, 0xb4, 0xf9, 0x70, 0x05, 0x08, 0x0a, + 0x77, 0xfd, 0x26, 0xf7, 0x34, 0xfb, 0xb7, 0xfb, 0x1c, 0xe8, 0x09, 0xdb, + 0x88, 0xe2, 0xea, 0xe4, 0x3d, 0xe6, 0xe2, 0xf4, 0x41, 0xef, 0x6f, 0xda, + 0xe9, 0xe2, 0x64, 0xf4, 0xed, 0xf2, 0xda, 0xee, 0xaf, 0xf0, 0xcb, 0xe7, + 0xb1, 0xe8, 0xc1, 0xe9, 0xb2, 0xdf, 0x57, 0xf0, 0xf7, 0xf8, 0xd8, 0xf8, + 0x3b, 0x06, 0x3f, 0x05, 0x25, 0x15, 0x38, 0x33, 0xe1, 0x39, 0xff, 0x3c, + 0x54, 0x3e, 0x11, 0x3e, 0x3b, 0x45, 0x8e, 0x48, 0x12, 0x3c, 0x04, 0x20, + 0xfe, 0x15, 0x94, 0x18, 0xc6, 0x0c, 0x17, 0x03, 0x7a, 0x05, 0xd8, 0x07, + 0xab, 0x02, 0x45, 0x09, 0x06, 0x10, 0x1f, 0x0e, 0x29, 0x12, 0xa3, 0x0b, + 0x16, 0x0b, 0xd8, 0x16, 0x9c, 0x16, 0x4b, 0x11, 0x6c, 0x0a, 0x40, 0xfb, + 0xc6, 0xf4, 0x4f, 0x01, 0x56, 0x09, 0x46, 0x06, 0x89, 0x01, 0x6c, 0xff, + 0x1d, 0x0a, 0xe8, 0x11, 0xf1, 0x04, 0x09, 0xf9, 0xb3, 0xfb, 0xea, 0x05, + 0xb2, 0x07, 0x7a, 0xfa, 0xae, 0xf4, 0x61, 0x00, 0x83, 0x0c, 0x11, 0x06, + 0x2b, 0xf1, 0x0b, 0xe1, 0xb1, 0xe7, 0x2e, 0xf8, 0xad, 0xfc, 0x0b, 0x04, + 0xe2, 0x09, 0x17, 0x0c, 0x3e, 0x13, 0xcb, 0x13, 0x86, 0x17, 0x21, 0x1b, + 0xca, 0x1a, 0xb1, 0x2b, 0x7d, 0x3a, 0x82, 0x31, 0xa9, 0x1e, 0xd0, 0x0e, + 0x20, 0x0f, 0x99, 0x1e, 0x88, 0x32, 0xcf, 0x37, 0xe0, 0x27, 0x37, 0x23, + 0x18, 0x28, 0xb8, 0x26, 0x32, 0x28, 0xe7, 0x2a, 0x24, 0x24, 0x47, 0x1d, + 0x5f, 0x2c, 0x25, 0x33, 0x9a, 0x25, 0x32, 0x1a, 0x87, 0x0d, 0xf5, 0x0d, + 0x79, 0x12, 0xab, 0x0d, 0xd5, 0x0f, 0xd9, 0x11, 0x28, 0x17, 0x19, 0x2b, + 0xdc, 0x30, 0xde, 0x2f, 0xfe, 0x3a, 0xf7, 0x28, 0x11, 0x0b, 0xc9, 0xfb, + 0xbd, 0xf2, 0x5e, 0xf0, 0x5b, 0xe0, 0xd9, 0xdb, 0x22, 0xda, 0x4a, 0xc0, + 0x3e, 0xbe, 0x3e, 0xd8, 0xd3, 0xe0, 0x77, 0xd0, 0x3d, 0xd6, 0x38, 0xf2, + 0x60, 0xf8, 0x15, 0xff, 0x4a, 0x0d, 0xea, 0x02, 0x45, 0xfb, 0x1d, 0x09, + 0x5a, 0x20, 0xaf, 0x30, 0x5f, 0x1a, 0xdf, 0x0a, 0xdf, 0x08, 0x3b, 0xfd, + 0x39, 0x05, 0x39, 0xf7, 0x6d, 0xdd, 0xbd, 0xe6, 0x40, 0xff, 0x49, 0x09, + 0xa8, 0xfb, 0xc2, 0xf5, 0x1a, 0xfc, 0xa5, 0xf8, 0x67, 0xfc, 0x18, 0x0b, + 0x5c, 0x08, 0x0f, 0x01, 0x9a, 0x00, 0x5b, 0xff, 0xa1, 0xfd, 0x90, 0xfa, + 0x2e, 0x01, 0x9b, 0x0f, 0x7d, 0x10, 0xb8, 0x14, 0xf7, 0x26, 0x56, 0x22, + 0x4f, 0x21, 0x4c, 0x27, 0xe5, 0x22, 0x6b, 0x25, 0x21, 0x31, 0xa5, 0x46, + 0xa1, 0x3a, 0x9c, 0x1c, 0xb2, 0x0d, 0xb2, 0x07, 0x19, 0xfe, 0x6d, 0xed, + 0x23, 0xe8, 0xeb, 0xea, 0x6b, 0xfa, 0x03, 0xf6, 0x97, 0xe8, 0x0e, 0xeb, + 0xff, 0xf4, 0x4e, 0x08, 0xa3, 0x08, 0x21, 0x00, 0x51, 0xfa, 0x00, 0x02, + 0xc5, 0x14, 0x89, 0x13, 0xdc, 0xff, 0xa2, 0xef, 0x13, 0xf0, 0x04, 0xf8, + 0xc5, 0xf0, 0xd7, 0xe1, 0x55, 0xde, 0xbc, 0xd9, 0xb4, 0xe0, 0xc6, 0xe6, + 0xa3, 0xdd, 0x9c, 0xdc, 0xdc, 0xe6, 0x7d, 0xf4, 0xf0, 0xf2, 0x58, 0xe6, + 0x7c, 0xdd, 0xb5, 0xe1, 0x28, 0xe8, 0xd7, 0xeb, 0x08, 0xed, 0x9b, 0xe9, + 0xf0, 0xec, 0x78, 0xf7, 0x3c, 0x05, 0xb8, 0x00, 0x5d, 0xfb, 0x00, 0x01, + 0xb1, 0x03, 0x45, 0x07, 0x7f, 0x0b, 0xeb, 0x11, 0x1b, 0x15, 0x0d, 0x1a, + 0x38, 0x1d, 0xd9, 0x22, 0xda, 0x1d, 0xb9, 0x0f, 0x37, 0x0c, 0x6c, 0x08, + 0xaf, 0x0f, 0x2a, 0x10, 0x3d, 0x08, 0x22, 0x11, 0xc5, 0x22, 0x7f, 0x28, + 0x33, 0x1c, 0x04, 0x17, 0x98, 0x21, 0x23, 0x37, 0x1a, 0x49, 0x9c, 0x4a, + 0x20, 0x44, 0x71, 0x3b, 0x42, 0x38, 0x25, 0x3d, 0xd7, 0x46, 0xf4, 0x56, + 0x9f, 0x61, 0xa3, 0x62, 0x2f, 0x5f, 0x21, 0x4f, 0x9b, 0x37, 0xb4, 0x2c, + 0x22, 0x26, 0xd3, 0x0d, 0x04, 0xf4, 0xce, 0xeb, 0x03, 0xed, 0x09, 0xd7, + 0x05, 0xb4, 0xad, 0xb5, 0x86, 0xcc, 0x2b, 0xcf, 0x70, 0xc8, 0x12, 0xd9, + 0xaf, 0xe2, 0xfb, 0xe5, 0xd2, 0xfa, 0xe3, 0xfa, 0xd5, 0xe4, 0x28, 0xdb, + 0xe4, 0xed, 0x12, 0x05, 0x4a, 0x06, 0xcf, 0x04, 0xff, 0x1e, 0xb3, 0x24, + 0xd4, 0x11, 0x65, 0x17, 0x53, 0x0c, 0x49, 0xfd, 0x62, 0x08, 0xdb, 0x0c, + 0xd5, 0xee, 0x24, 0xd7, 0xce, 0xe1, 0xec, 0xe3, 0xe7, 0xe0, 0xc0, 0xdd, + 0xbc, 0xdd, 0xe2, 0xd7, 0xaa, 0xd3, 0x5e, 0xe5, 0xdd, 0xf1, 0x1b, 0xfa, + 0x8e, 0xfc, 0xd6, 0xf8, 0xae, 0xf9, 0x06, 0x00, 0x67, 0x0c, 0x9a, 0x18, + 0x5e, 0x1d, 0x8e, 0x22, 0x18, 0x30, 0x0d, 0x2d, 0x28, 0x24, 0x58, 0x30, + 0xc2, 0x2b, 0x0b, 0x0e, 0x9a, 0x08, 0x29, 0x05, 0x97, 0xf5, 0x86, 0xf6, + 0x2d, 0xf2, 0x67, 0xe7, 0x27, 0xde, 0x99, 0xe0, 0xfb, 0xed, 0xdf, 0xf3, + 0xa5, 0xee, 0xdb, 0xe1, 0x33, 0xdf, 0x0d, 0xe2, 0x1e, 0xe7, 0xb9, 0xe7, + 0x31, 0xeb, 0xc3, 0xf2, 0x57, 0xf1, 0x54, 0xf4, 0xe3, 0xf1, 0xd8, 0xf3, + 0x14, 0xff, 0x81, 0x04, 0xa7, 0xfd, 0xc3, 0xee, 0x64, 0xeb, 0x71, 0xf5, + 0xa4, 0x04, 0x54, 0x02, 0x26, 0xf1, 0xf1, 0xe9, 0x42, 0xe6, 0x1b, 0xdd, + 0xa1, 0xd5, 0xb2, 0xd4, 0xcb, 0xdd, 0x79, 0xe1, 0xf3, 0xd9, 0x83, 0xdd, + 0x33, 0xe5, 0xce, 0xea, 0x23, 0xed, 0x1a, 0xec, 0x84, 0xf0, 0x73, 0xf5, + 0x49, 0xfd, 0x5c, 0x05, 0x4f, 0x06, 0x41, 0x0c, 0xec, 0x10, 0xba, 0x05, + 0xc3, 0xf7, 0x17, 0xf6, 0x53, 0x05, 0x93, 0x0e, 0x89, 0x0e, 0x1c, 0x09, + 0x91, 0xfe, 0x39, 0x0b, 0x2f, 0x1b, 0xa0, 0x1b, 0x07, 0x0e, 0x19, 0xf4, + 0x08, 0xf3, 0x15, 0x07, 0x06, 0x13, 0xc2, 0x19, 0xf6, 0x15, 0xed, 0x14, + 0x94, 0x1b, 0x4f, 0x1c, 0xf4, 0x23, 0x9c, 0x27, 0xd3, 0x2c, 0xda, 0x32, + 0x3f, 0x38, 0xe1, 0x4c, 0xe6, 0x4a, 0x45, 0x3e, 0x83, 0x46, 0xff, 0x3e, + 0x03, 0x24, 0x76, 0x0d, 0xd1, 0xfb, 0xd6, 0xf7, 0xff, 0xf7, 0x38, 0xf4, + 0x76, 0xeb, 0x65, 0xd2, 0xc8, 0xcb, 0x08, 0xe1, 0x90, 0xe7, 0x42, 0xed, + 0x68, 0x0a, 0xe6, 0x0a, 0xd5, 0xf2, 0xfc, 0x01, 0x24, 0x1a, 0xe9, 0x0d, + 0xea, 0x02, 0x4d, 0x0e, 0x7d, 0x0f, 0x70, 0x0d, 0x38, 0x11, 0x3c, 0x04, + 0x9c, 0xfc, 0x33, 0x17, 0xcf, 0x22, 0xa1, 0x0e, 0x7f, 0x00, 0x6b, 0x01, + 0xc3, 0x16, 0xf4, 0x0e, 0x56, 0xf3, 0x82, 0xe5, 0x2d, 0xc6, 0x20, 0xb6, + 0xcf, 0xc1, 0x1b, 0xd5, 0xae, 0xdf, 0x54, 0xe1, 0xbc, 0xd8, 0xc5, 0xd2, + 0x7c, 0xe3, 0x69, 0xf3, 0x79, 0x10, 0xe1, 0x1a, 0x50, 0x17, 0xaa, 0x19, + 0x51, 0x0c, 0x1e, 0x1a, 0x87, 0x29, 0x8a, 0x33, 0x40, 0x33, 0x4a, 0x1d, + 0x69, 0x11, 0xbc, 0x04, 0x4d, 0x03, 0xf0, 0x0a, 0x7a, 0x0e, 0xda, 0xff, + 0xe2, 0xef, 0x2e, 0xf0, 0x71, 0xeb, 0x14, 0xf1, 0xfb, 0xf5, 0x87, 0xf0, + 0xb0, 0xfa, 0x6c, 0x0b, 0x34, 0x08, 0x7d, 0x05, 0x75, 0x02, 0xdb, 0xfa, + 0xca, 0xff, 0xa6, 0xff, 0x84, 0x07, 0x25, 0x13, 0x16, 0x1e, 0xe2, 0x26, + 0xc4, 0x20, 0x7a, 0x11, 0x53, 0x03, 0xaa, 0x11, 0x30, 0x26, 0x44, 0x2e, + 0xec, 0x1c, 0x4e, 0x05, 0xde, 0x09, 0xff, 0x04, 0x05, 0x07, 0x40, 0x10, + 0x79, 0xfd, 0xcc, 0xed, 0x5e, 0xf7, 0xfe, 0xfe, 0xeb, 0xf4, 0x24, 0xf1, + 0x0a, 0xf6, 0x78, 0xfc, 0x69, 0x01, 0xbf, 0x01, 0x87, 0x07, 0xee, 0x09, + 0xdb, 0x06, 0xbb, 0x08, 0x6d, 0x04, 0x10, 0xf8, 0x50, 0xfc, 0x82, 0x08, + 0xa9, 0xff, 0xfa, 0xf3, 0x67, 0xed, 0x79, 0xeb, 0x51, 0xf8, 0x6d, 0xfd, + 0x7a, 0xf4, 0x53, 0xe7, 0x80, 0xe6, 0xde, 0xf7, 0x2a, 0x05, 0xfa, 0x06, + 0x14, 0xfe, 0x28, 0xf4, 0x97, 0xf8, 0xb4, 0x0a, 0xcd, 0x0e, 0x26, 0x0e, + 0x17, 0x1e, 0x1a, 0x22, 0x9e, 0x18, 0x12, 0x17, 0xde, 0x23, 0x11, 0x33, + 0x80, 0x42, 0xba, 0x46, 0x5c, 0x3c, 0x1e, 0x34, 0xaa, 0x25, 0xf1, 0x1c, + 0x2c, 0x14, 0x3d, 0x04, 0xcc, 0xf5, 0xf0, 0xe5, 0x46, 0xda, 0x76, 0xd0, + 0xe7, 0xc8, 0x04, 0xc1, 0x66, 0xcb, 0x94, 0xe2, 0x8b, 0xdf, 0x68, 0xd6, + 0x46, 0xe2, 0xf8, 0xf0, 0x4b, 0xf7, 0x86, 0xfa, 0x0f, 0x00, 0x80, 0xfd, + 0x91, 0xf4, 0xd3, 0x01, 0xc1, 0x0b, 0x27, 0x0b, 0x9a, 0x16, 0x91, 0x1e, + 0xf2, 0x23, 0x0e, 0x20, 0x49, 0x22, 0x0e, 0x30, 0xac, 0x2a, 0x7d, 0x23, + 0xfc, 0x27, 0xd6, 0x2d, 0x86, 0x26, 0x41, 0x1b, 0x20, 0x17, 0x99, 0x05, + 0x0b, 0xf8, 0xe9, 0xe8, 0x97, 0xcb, 0xf5, 0xbc, 0x06, 0xc3, 0xa0, 0xcb, + 0x00, 0xcb, 0xf8, 0xcb, 0xf2, 0xc6, 0x2a, 0xd2, 0x14, 0xe3, 0x32, 0xe5, + 0x5f, 0x00, 0x43, 0x0e, 0xc5, 0x05, 0xa4, 0x04, 0x26, 0x03, 0x17, 0xff, + 0xa4, 0xf9, 0x07, 0xf8, 0x2b, 0xf8, 0x23, 0xf6, 0xd9, 0xf0, 0xe4, 0xdf, + 0xee, 0xcc, 0x00, 0xd2, 0xd7, 0xd2, 0xd8, 0xda, 0xae, 0xe7, 0xf3, 0xdc, + 0x0c, 0xe1, 0x13, 0xe2, 0x84, 0xd8, 0x15, 0xe0, 0x86, 0xec, 0x7b, 0xe3, + 0x16, 0xe1, 0x47, 0xe8, 0x43, 0xe3, 0x93, 0xe7, 0x26, 0xf1, 0xe2, 0xfe, + 0x69, 0xff, 0x0b, 0x07, 0x36, 0x18, 0x1b, 0x1c, 0x4e, 0x22, 0xd0, 0x25, + 0xec, 0x26, 0xfe, 0x26, 0x47, 0x31, 0x44, 0x2f, 0x3f, 0x23, 0x76, 0x23, + 0xbb, 0x1d, 0x46, 0x11, 0xbd, 0x10, 0xc3, 0x1b, 0x69, 0x13, 0x4b, 0x09, + 0x97, 0x08, 0xf8, 0x05, 0x17, 0x0c, 0x05, 0x17, 0x3c, 0x1d, 0x60, 0x15, + 0xb6, 0x0a, 0x17, 0x14, 0x55, 0x1a, 0x8f, 0x0f, 0x5a, 0x0c, 0xe1, 0x00, + 0x94, 0xf7, 0x5d, 0xfb, 0x9c, 0xf6, 0x36, 0xf8, 0x17, 0xfa, 0x43, 0xf9, + 0x27, 0xf3, 0xbc, 0xdc, 0x75, 0xdb, 0x1d, 0xe8, 0x2b, 0xe3, 0x23, 0xde, + 0x62, 0xda, 0xd0, 0xdc, 0xfd, 0xe5, 0xc2, 0xea, 0x3f, 0xed, 0x11, 0xf1, + 0x4c, 0xfa, 0xdb, 0x06, 0xbf, 0x0b, 0xb2, 0x08, 0x5d, 0x11, 0xca, 0x21, + 0x38, 0x35, 0x8d, 0x3a, 0x00, 0x31, 0x8c, 0x35, 0x47, 0x3b, 0x15, 0x35, + 0x1c, 0x24, 0xac, 0x0d, 0x58, 0xed, 0x99, 0xd5, 0x34, 0xd9, 0xb5, 0xe4, + 0x03, 0xdd, 0x23, 0xc1, 0xd1, 0xc0, 0x36, 0xd5, 0xc5, 0xd7, 0xe5, 0xda, + 0x6b, 0xf7, 0xe5, 0x04, 0xbe, 0xf1, 0x3b, 0xfc, 0x83, 0x0f, 0xc7, 0x05, + 0x6f, 0x0b, 0xc0, 0x20, 0x24, 0x1f, 0x60, 0x18, 0x4b, 0x29, 0xa8, 0x39, + 0xf8, 0x37, 0xac, 0x2d, 0x05, 0x30, 0x24, 0x31, 0x9f, 0x25, 0xef, 0x32, + 0x19, 0x38, 0x2d, 0x2b, 0xba, 0x1b, 0x68, 0x09, 0xfb, 0x0f, 0x66, 0x0e, + 0x45, 0x10, 0xcd, 0x1a, 0x33, 0x11, 0x20, 0x10, 0x31, 0x0f, 0x56, 0x03, + 0xb6, 0xfe, 0x2e, 0xfd, 0x08, 0xf3, 0x8a, 0xf6, 0xda, 0x06, 0x06, 0x12, + 0x01, 0x1c, 0x4b, 0x10, 0xa6, 0x07, 0xf7, 0x14, 0x42, 0x14, 0xc7, 0x13, + 0xf7, 0x17, 0x61, 0x12, 0x29, 0xfb, 0x83, 0xea, 0x31, 0xf0, 0x25, 0xd3, + 0x08, 0xc4, 0x39, 0xcc, 0xb4, 0xba, 0x65, 0xbd, 0x08, 0xbd, 0x02, 0xbd, + 0x70, 0xc8, 0xc9, 0xbe, 0xc7, 0xbc, 0x32, 0xc8, 0xc5, 0xcf, 0x16, 0xd4, + 0x06, 0xe0, 0x4a, 0xe5, 0x14, 0xd8, 0x84, 0xde, 0xd8, 0xec, 0xc6, 0xf4, + 0x0d, 0x03, 0x35, 0x05, 0xb5, 0x00, 0x68, 0xfc, 0xbb, 0xfc, 0x70, 0xfd, + 0x49, 0x03, 0xcb, 0x0d, 0xe4, 0x15, 0xf8, 0x1d, 0xec, 0x1c, 0xbc, 0x24, + 0x49, 0x1f, 0xe9, 0x15, 0x5c, 0x1f, 0xd1, 0x1e, 0x70, 0x14, 0x12, 0x0e, + 0x67, 0x0e, 0xeb, 0x0d, 0xc9, 0x17, 0x89, 0x21, 0xf4, 0x2e, 0x20, 0x3b, + 0xcd, 0x3c, 0x72, 0x43, 0xe4, 0x42, 0xb1, 0x3e, 0x65, 0x3a, 0xf6, 0x34, + 0x8e, 0x2b, 0x0c, 0x2c, 0x1e, 0x31, 0x7d, 0x2c, 0x55, 0x1b, 0x18, 0x06, + 0xb5, 0xff, 0x18, 0xf7, 0xeb, 0xf5, 0x3a, 0xee, 0x7b, 0xe2, 0xbf, 0xe6, + 0x65, 0xe6, 0x13, 0xdf, 0xbc, 0xd3, 0x6b, 0xd2, 0x55, 0xdf, 0x2a, 0xef, + 0xd8, 0xf4, 0xcd, 0xf3, 0xc0, 0xef, 0x02, 0xf4, 0x3e, 0x08, 0x8d, 0x15, + 0xa9, 0x17, 0x99, 0x18, 0xa0, 0x24, 0x74, 0x2e, 0x6b, 0x25, 0x27, 0x16, + 0x54, 0x0a, 0x04, 0xf3, 0xb8, 0xdc, 0xf4, 0xda, 0x6e, 0xdf, 0x7c, 0xdb, + 0xd6, 0xbe, 0xcb, 0xa3, 0x3a, 0xab, 0x22, 0xc0, 0xc0, 0xc2, 0xbe, 0xd1, + 0xa7, 0xe7, 0xbe, 0xdd, 0x29, 0xd2, 0x1a, 0xd5, 0xec, 0xf1, 0x27, 0x03, + 0x3b, 0x0d, 0xe1, 0x2a, 0x41, 0x27, 0x47, 0x1c, 0xa1, 0x24, 0xa5, 0x30, + 0xba, 0x3b, 0x19, 0x44, 0xe4, 0x46, 0x61, 0x3c, 0x8b, 0x31, 0x4f, 0x37, + 0xee, 0x3d, 0x8f, 0x34, 0x9c, 0x2e, 0x3c, 0x29, 0xfd, 0x1b, 0x83, 0x0d, + 0x7f, 0x07, 0x6a, 0x09, 0x9c, 0x08, 0x51, 0x04, 0xb1, 0x05, 0x31, 0x08, + 0xb7, 0x04, 0x03, 0x10, 0x93, 0x14, 0x03, 0x1c, 0x70, 0x23, 0x26, 0x11, + 0xa9, 0x11, 0x3c, 0x10, 0x9e, 0x0d, 0xef, 0x13, 0x1c, 0x0d, 0x5c, 0x10, + 0x73, 0x18, 0xfc, 0x14, 0x2a, 0xfc, 0x7a, 0xf0, 0xc2, 0xf1, 0xb0, 0xe8, + 0x54, 0xf6, 0x32, 0xfc, 0x0b, 0xee, 0x08, 0xe3, 0xae, 0xdd, 0xc0, 0xd7, + 0x19, 0xd1, 0x54, 0xd3, 0xcc, 0xc7, 0x0f, 0xcb, 0xac, 0xcc, 0x39, 0xba, + 0xe7, 0xbf, 0x97, 0xc0, 0x90, 0xbf, 0xdb, 0xc9, 0x52, 0xd0, 0x96, 0xd7, + 0x2c, 0xe7, 0x82, 0xf3, 0x50, 0xf8, 0x6b, 0xfc, 0x45, 0xed, 0xf8, 0xe6, + 0x61, 0xeb, 0x8b, 0xf1, 0x1f, 0x01, 0x20, 0xfb, 0xea, 0xf4, 0xff, 0xfe, + 0x65, 0x0a, 0xc4, 0x17, 0xee, 0x24, 0x5d, 0x26, 0x32, 0x25, 0x95, 0x2e, + 0x0e, 0x31, 0xba, 0x2f, 0xa1, 0x2b, 0x20, 0x29, 0xf7, 0x2c, 0x3d, 0x30, + 0x53, 0x37, 0x67, 0x37, 0x3d, 0x2b, 0xa8, 0x1f, 0x58, 0x29, 0x80, 0x36, + 0xe1, 0x35, 0x6f, 0x36, 0x68, 0x3a, 0x27, 0x3d, 0xb3, 0x33, 0xad, 0x2a, + 0x27, 0x2f, 0x65, 0x38, 0x09, 0x34, 0x02, 0x28, 0x6e, 0x16, 0x75, 0x04, + 0xcc, 0x00, 0xdc, 0xf4, 0x53, 0xf0, 0x79, 0xf2, 0xd8, 0xf3, 0x6f, 0xf8, + 0xe5, 0xf1, 0x1a, 0xf0, 0x78, 0xf2, 0x78, 0xf5, 0xfe, 0xfe, 0x6f, 0x09, + 0xf9, 0x0d, 0xef, 0x12, 0x70, 0x12, 0x5a, 0x11, 0x02, 0x0d, 0xc5, 0xf6, + 0x5b, 0xe7, 0x90, 0xdc, 0x21, 0xdb, 0xe1, 0xd8, 0x12, 0xcb, 0x71, 0xc9, + 0xc1, 0xc4, 0x73, 0xb8, 0xa0, 0xb6, 0xf1, 0xc2, 0x59, 0xc6, 0x17, 0xc0, + 0x3f, 0xca, 0x15, 0xd3, 0x19, 0xcc, 0x31, 0xd4, 0x6c, 0xe5, 0x85, 0xe2, + 0xf1, 0xe2, 0x85, 0xea, 0x26, 0xf4, 0x49, 0x00, 0x96, 0x09, 0x2b, 0x21, + 0x03, 0x2d, 0x31, 0x2d, 0x68, 0x31, 0x7c, 0x2f, 0x10, 0x32, 0x2b, 0x32, + 0x78, 0x37, 0xe0, 0x39, 0xdc, 0x2d, 0x98, 0x28, 0x7f, 0x27, 0xf3, 0x1f, + 0x31, 0x1b, 0x81, 0x1a, 0x04, 0x16, 0xb8, 0x0f, 0xc1, 0x06, 0x25, 0x0a, + 0x4d, 0x1c, 0x23, 0x2f, 0x71, 0x2e, 0xca, 0x26, 0x37, 0x26, 0x3a, 0x20, + 0x7f, 0x2d, 0xb4, 0x31, 0x7b, 0x2f, 0xc7, 0x3b, 0x85, 0x38, 0xe2, 0x2c, + 0x2b, 0x24, 0xf4, 0x19, 0x02, 0x03, 0x6d, 0xf1, 0x6c, 0xe0, 0x73, 0xd4, + 0xfa, 0xd5, 0xe5, 0xd0, 0x03, 0xd5, 0x61, 0xd5, 0x9f, 0xc9, 0x69, 0xc4, + 0xf0, 0xca, 0x2a, 0xda, 0x45, 0xe2, 0xd4, 0xdd, 0x54, 0xd9, 0xfb, 0xd1, + 0xca, 0xd1, 0x09, 0xde, 0xb5, 0xdd, 0xbb, 0xd6, 0xde, 0xd9, 0xd1, 0xe2, + 0x1a, 0xe2, 0x07, 0xe7, 0x7d, 0xf4, 0xba, 0xf5, 0x32, 0xf6, 0x46, 0xf1, + 0xd8, 0xe7, 0xde, 0xe9, 0x5f, 0xe8, 0xf2, 0xea, 0x0d, 0xf4, 0x61, 0xee, + 0x8b, 0xee, 0x6b, 0xe8, 0x82, 0xe1, 0x08, 0xf4, 0x08, 0x06, 0xfd, 0x08, + 0xbf, 0x04, 0x63, 0x0d, 0x78, 0x16, 0xcb, 0x25, 0x67, 0x37, 0xbb, 0x3a, + 0xd5, 0x3a, 0xa5, 0x35, 0x4e, 0x36, 0x8c, 0x37, 0xcc, 0x3c, 0x94, 0x43, + 0xc9, 0x45, 0x91, 0x3d, 0x41, 0x2e, 0x3b, 0x25, 0x13, 0x1c, 0x51, 0x1c, + 0xf1, 0x20, 0x77, 0x28, 0xb9, 0x24, 0x77, 0x1c, 0xca, 0x19, 0x2e, 0x16, + 0xda, 0x18, 0xcf, 0x17, 0x9b, 0x1b, 0xdb, 0x18, 0xee, 0x0e, 0x75, 0x0b, + 0x03, 0x0c, 0x11, 0x07, 0x99, 0x03, 0x0f, 0x0d, 0x39, 0x0c, 0x47, 0x0a, + 0xf4, 0x15, 0xfc, 0x24, 0xdc, 0x1b, 0xce, 0x0d, 0x9b, 0x0d, 0x57, 0x00, + 0xd8, 0xf1, 0x18, 0xea, 0xf8, 0xdf, 0x5d, 0xcd, 0x7d, 0xbe, 0x41, 0xc0, + 0xd9, 0xc8, 0x6b, 0xba, 0xad, 0xa8, 0xdf, 0xb7, 0xba, 0xbf, 0x9f, 0xba, + 0x71, 0xcb, 0x02, 0xe1, 0x94, 0xe0, 0xd4, 0xe3, 0x70, 0xee, 0xb6, 0xf0, + 0xff, 0xe4, 0xbe, 0xe0, 0x7b, 0xfa, 0xba, 0x06, 0x56, 0x09, 0xbe, 0x0d, + 0x3e, 0x0a, 0x22, 0x05, 0xcf, 0x0d, 0x8f, 0x1e, 0x04, 0x19, 0x7d, 0x19, + 0x1a, 0x21, 0x60, 0x2b, 0x80, 0x27, 0xc7, 0x13, 0xf9, 0x1d, 0x95, 0x1d, + 0x4c, 0x12, 0xb1, 0x15, 0xa7, 0x10, 0xfb, 0x0f, 0xff, 0x17, 0x5b, 0x16, + 0x0c, 0x0e, 0x0b, 0x10, 0x18, 0x1a, 0x86, 0x27, 0xe9, 0x2b, 0xc7, 0x2c, + 0x44, 0x3c, 0xba, 0x3c, 0xda, 0x30, 0x76, 0x34, 0x89, 0x40, 0xd7, 0x3c, + 0xed, 0x30, 0xcd, 0x35, 0x0d, 0x2b, 0x77, 0x1f, 0x93, 0x1f, 0x15, 0x07, + 0x4e, 0xef, 0x47, 0xdb, 0x73, 0xce, 0x66, 0xce, 0x58, 0xc9, 0x07, 0xc8, + 0xee, 0xc8, 0xa6, 0xcc, 0xb0, 0xce, 0x6f, 0xcb, 0xd6, 0xc8, 0xca, 0xcc, + 0x08, 0xd3, 0xf7, 0xe1, 0xf7, 0xf0, 0xf1, 0xe2, 0xe7, 0xd7, 0xa0, 0xd3, + 0x4a, 0xcf, 0x96, 0xda, 0x4e, 0xe7, 0x92, 0xee, 0x72, 0xef, 0xc9, 0xe9, + 0x71, 0xe5, 0x18, 0xec, 0x90, 0xf2, 0xa2, 0x03, 0x22, 0x12, 0xea, 0x0a, + 0x9a, 0x07, 0x01, 0x01, 0x6d, 0xfb, 0x1c, 0x04, 0x38, 0x10, 0x00, 0x0c, + 0xf3, 0x06, 0x4b, 0x08, 0xd7, 0x01, 0xad, 0x07, 0xb6, 0x13, 0x6b, 0x1b, + 0x0c, 0x1d, 0xaf, 0x19, 0xd1, 0x22, 0xa6, 0x34, 0x85, 0x38, 0x38, 0x33, + 0xda, 0x2b, 0x41, 0x23, 0x91, 0x24, 0xe0, 0x2e, 0xe3, 0x38, 0xd5, 0x30, + 0xd2, 0x1b, 0x81, 0x08, 0xea, 0x05, 0x5f, 0x0f, 0x5b, 0x19, 0x33, 0x20, + 0xde, 0x16, 0x68, 0x0b, 0x45, 0x05, 0x42, 0x0e, 0xf1, 0x1a, 0x11, 0x1b, + 0x24, 0x1a, 0x24, 0x1a, 0xbe, 0x15, 0xfa, 0x0c, 0xea, 0x0f, 0x68, 0x17, + 0x5d, 0x1d, 0x72, 0x1e, 0xde, 0x18, 0x13, 0x19, 0xed, 0x1b, 0x30, 0x12, + 0x4f, 0x02, 0xe4, 0xfa, 0x0b, 0xe9, 0x38, 0xcd, 0xf3, 0xbe, 0xad, 0xc7, + 0x9a, 0xc9, 0x21, 0xbb, 0xb5, 0xb3, 0xfb, 0xaa, 0xee, 0xaa, 0xb4, 0xb7, + 0x97, 0xc2, 0x9f, 0xd2, 0x30, 0xe1, 0x33, 0xe0, 0xf4, 0xe1, 0x90, 0xec, + 0xac, 0xf4, 0x16, 0xfd, 0x60, 0x02, 0x82, 0xfd, 0x43, 0xf6, 0x1b, 0x05, + 0x5d, 0x16, 0x3f, 0x0e, 0xa2, 0x09, 0x81, 0x11, 0x78, 0x12, 0xc4, 0x10, + 0xe2, 0x0a, 0xbb, 0x0d, 0xe2, 0x1b, 0xfa, 0x19, 0x53, 0x15, 0x18, 0x0e, + 0xb9, 0x06, 0x33, 0x08, 0x96, 0x06, 0xdd, 0x00, 0x64, 0xff, 0x90, 0x08, + 0x0c, 0x0e, 0x1d, 0x15, 0x02, 0x1d, 0x11, 0x23, 0x0a, 0x27, 0x3e, 0x28, + 0xe9, 0x2a, 0x6f, 0x2b, 0x13, 0x2e, 0xd7, 0x2b, 0x28, 0x32, 0x57, 0x3a, + 0xcd, 0x39, 0x14, 0x30, 0x97, 0x24, 0x98, 0x1c, 0xf0, 0x10, 0xfc, 0x0e, + 0xdf, 0xff, 0x40, 0xf8, 0xb2, 0xf8, 0xf8, 0xea, 0x6d, 0xe6, 0xb1, 0xe5, + 0x67, 0xe4, 0xd7, 0xd7, 0x72, 0xcf, 0x3f, 0xc9, 0xd5, 0xc7, 0xdb, 0xcf, + 0xa4, 0xcc, 0xa7, 0xd3, 0x41, 0xd5, 0x9f, 0xcb, 0x4f, 0xc7, 0x17, 0xc9, + 0xdd, 0xda, 0x7f, 0xec, 0xbf, 0xf2, 0xe0, 0xf5, 0x38, 0xf0, 0x38, 0xe7, + 0x6a, 0xe4, 0x18, 0xdf, 0xda, 0xde, 0x70, 0xe3, 0x6d, 0xea, 0xa5, 0xf2, + 0x1b, 0xf4, 0xd3, 0xf3, 0xb1, 0xed, 0x3f, 0xf1, 0x03, 0x04, 0x83, 0x0f, + 0x38, 0x16, 0x61, 0x19, 0xdf, 0x1a, 0x82, 0x23, 0x9a, 0x31, 0x57, 0x3a, + 0xcd, 0x37, 0xf5, 0x35, 0xd9, 0x34, 0x13, 0x34, 0x05, 0x2a, 0xe4, 0x1a, + 0x3f, 0x20, 0xb5, 0x26, 0xa6, 0x24, 0x2b, 0x22, 0x65, 0x1f, 0xa8, 0x1e, + 0x55, 0x20, 0x6a, 0x2a, 0xc6, 0x2f, 0xb6, 0x21, 0x0a, 0x15, 0xb2, 0x14, + 0x86, 0x0b, 0xa9, 0xfe, 0xaa, 0xfa, 0x0b, 0x01, 0xa7, 0x03, 0xe4, 0xfc, + 0xde, 0xff, 0xb1, 0x0c, 0xd7, 0x1e, 0x4e, 0x22, 0x4c, 0x21, 0xfb, 0x23, + 0x6f, 0x23, 0xbb, 0x26, 0xc7, 0x2a, 0x44, 0x34, 0xd4, 0x32, 0x5f, 0x2b, + 0x8e, 0x17, 0xb2, 0xfb, 0x24, 0xea, 0x23, 0xdb, 0xd0, 0xd3, 0xf8, 0xc1, + 0xbd, 0xb8, 0xb8, 0xc2, 0xf8, 0xbe, 0xd1, 0xaf, 0x55, 0xab, 0x20, 0xb2, + 0x97, 0xb0, 0xa9, 0xb4, 0x97, 0xd0, 0x31, 0xe7, 0x2c, 0xe2, 0x84, 0xe5, + 0x80, 0xf1, 0x67, 0xe7, 0x20, 0xe9, 0x07, 0x04, 0xc4, 0x0d, 0xde, 0x0d, + 0x33, 0x1c, 0xae, 0x20, 0x07, 0x16, 0xe6, 0x16, 0xa3, 0x26, 0x92, 0x26, + 0x6d, 0x1e, 0x38, 0x1e, 0x06, 0x1a, 0xaa, 0x10, 0xae, 0x01, 0xae, 0x03, + 0xae, 0x0e, 0x8b, 0x05, 0xfe, 0xfb, 0x55, 0xfa, 0xa1, 0xf9, 0xe8, 0x01, + 0xb3, 0x07, 0x9b, 0x0a, 0x6a, 0x10, 0xb0, 0x14, 0xb0, 0x1f, 0x47, 0x1f, + 0xe8, 0x1f, 0x32, 0x30, 0x83, 0x34, 0x32, 0x33, 0xe4, 0x34, 0x04, 0x3b, + 0xf7, 0x3a, 0xb5, 0x27, 0xea, 0x1f, 0x64, 0x20, 0x31, 0x10, 0x69, 0x07, + 0x7e, 0x00, 0xa0, 0xed, 0x0f, 0xe9, 0xf2, 0xec, 0x3b, 0xe7, 0x91, 0xde, + 0x66, 0xd5, 0x9c, 0xd7, 0x31, 0xe5, 0xa6, 0xe7, 0x9d, 0xe6, 0x9f, 0xea, + 0xab, 0xe6, 0xc5, 0xe2, 0x75, 0xe9, 0x39, 0xea, 0xa4, 0xe1, 0x27, 0xd5, + 0x7e, 0xcb, 0x94, 0xcc, 0x42, 0xd4, 0x65, 0xe5, 0x1d, 0xed, 0x14, 0xe1, + 0x50, 0xd3, 0x61, 0xd3, 0xe6, 0xdd, 0x56, 0xe8, 0x71, 0xf8, 0x07, 0xf9, + 0x8a, 0xec, 0x49, 0xef, 0xe3, 0xf7, 0x41, 0xfa, 0x2c, 0xfa, 0xef, 0xfb, + 0xed, 0xfa, 0x87, 0x03, 0x55, 0x12, 0xd3, 0x19, 0x20, 0x1c, 0x1c, 0x14, + 0xc6, 0x22, 0x50, 0x38, 0x07, 0x36, 0x6e, 0x44, 0xfd, 0x4a, 0x2a, 0x46, + 0x35, 0x4e, 0xa8, 0x44, 0xce, 0x35, 0x06, 0x32, 0x3c, 0x29, 0x56, 0x1c, + 0x3e, 0x0f, 0x20, 0x06, 0xa2, 0x0d, 0xc6, 0x0e, 0x8f, 0x05, 0x70, 0x04, + 0x3a, 0x02, 0x72, 0x02, 0xc3, 0x0b, 0x16, 0x16, 0x24, 0x14, 0xd1, 0x16, + 0xf5, 0x14, 0x5d, 0x09, 0x9a, 0x07, 0x33, 0x08, 0xb5, 0x0c, 0x4d, 0x08, + 0x8e, 0x07, 0x7e, 0x0c, 0xf4, 0x10, 0xba, 0x1c, 0x65, 0x2e, 0x50, 0x3b, + 0x0d, 0x2e, 0x19, 0x24, 0x31, 0x15, 0xc0, 0x03, 0x04, 0xfd, 0x29, 0xeb, + 0xc3, 0xdc, 0x96, 0xcd, 0x33, 0xbe, 0xfa, 0xae, 0xe1, 0xa7, 0xce, 0xaf, + 0x4c, 0xb6, 0x8c, 0xb4, 0xaa, 0xb4, 0xce, 0xcd, 0x2c, 0xde, 0x1b, 0xd6, + 0x9f, 0xdd, 0x43, 0xe4, 0xd2, 0xdd, 0xc3, 0xe7, 0xb2, 0xf7, 0x39, 0xff, + 0x89, 0x04, 0x16, 0x12, 0x6a, 0x1a, 0x75, 0x0f, 0x4f, 0x0d, 0x5f, 0x16, + 0xc3, 0x23, 0x9b, 0x24, 0x38, 0x1c, 0x71, 0x23, 0x5d, 0x28, 0x2b, 0x24, + 0x63, 0x1c, 0x7a, 0x13, 0xaf, 0x0c, 0x8a, 0x0a, 0x4f, 0x09, 0x67, 0x09, + 0xa4, 0x04, 0x80, 0xf7, 0xbd, 0xf5, 0x40, 0xfc, 0x44, 0x0a, 0x12, 0x16, + 0x47, 0x14, 0xd7, 0x10, 0x54, 0x11, 0xf5, 0x1d, 0x18, 0x2c, 0x0b, 0x37, + 0xae, 0x3d, 0x69, 0x35, 0xf9, 0x2d, 0xa2, 0x2a, 0x09, 0x29, 0xbc, 0x1d, + 0xc6, 0x0d, 0x18, 0x08, 0x3a, 0xf7, 0x87, 0xe5, 0x75, 0xdb, 0xbf, 0xdc, + 0x2f, 0xde, 0xe7, 0xdb, 0x12, 0xe1, 0xf8, 0xdb, 0x83, 0xdb, 0x02, 0xde, + 0xf3, 0xe7, 0x47, 0xed, 0xef, 0xe0, 0xc3, 0xdc, 0xb8, 0xe2, 0x84, 0xeb, + 0x62, 0xec, 0xd9, 0xef, 0x53, 0xea, 0x9f, 0xe8, 0x3e, 0xf4, 0x65, 0xf3, + 0xb6, 0xea, 0xf4, 0xde, 0xa7, 0xdd, 0x66, 0xe2, 0x11, 0xe0, 0xe1, 0xdc, + 0xea, 0xe6, 0x29, 0xe2, 0x22, 0xe1, 0x80, 0xf0, 0x00, 0xe9, 0x9b, 0xf4, + 0x92, 0x05, 0xd0, 0x05, 0x47, 0x01, 0xc6, 0x01, 0xda, 0x08, 0x9c, 0x0c, + 0xb1, 0x1a, 0x8b, 0x1a, 0x4e, 0x22, 0x84, 0x2f, 0xec, 0x30, 0x66, 0x35, + 0xdb, 0x2f, 0xa8, 0x2b, 0x4a, 0x34, 0x1b, 0x47, 0xd4, 0x46, 0x65, 0x42, + 0xde, 0x3d, 0xa7, 0x31, 0xbb, 0x35, 0xec, 0x2c, 0xbb, 0x22, 0xc7, 0x1b, + 0xf6, 0x0a, 0x92, 0x00, 0x65, 0xfa, 0x5c, 0xf7, 0xaf, 0xf4, 0xb8, 0xf8, + 0xdb, 0xfe, 0xdd, 0x05, 0x47, 0x0b, 0xf4, 0x0e, 0x40, 0x1d, 0x46, 0x20, + 0xc9, 0x18, 0x86, 0x12, 0xd8, 0x0e, 0x8c, 0x16, 0x3d, 0x21, 0xe4, 0x26, + 0xf4, 0x20, 0x45, 0x1d, 0x5f, 0x1d, 0x66, 0x17, 0xbe, 0x11, 0x6a, 0x04, + 0xe1, 0xf1, 0xd1, 0xde, 0x1a, 0xce, 0xa8, 0xc8, 0xda, 0xca, 0x69, 0xbf, + 0xc7, 0xab, 0xe7, 0xab, 0x12, 0xb8, 0x05, 0xba, 0xe8, 0xb7, 0x17, 0xd0, + 0x14, 0xdf, 0x4f, 0xd4, 0x34, 0xe0, 0x8a, 0xe7, 0x58, 0xe0, 0x69, 0xe8, + 0x52, 0xf9, 0x33, 0x02, 0xb9, 0x01, 0x3c, 0x09, 0x14, 0x09, 0xca, 0x06, + 0x16, 0x16, 0xed, 0x21, 0x5b, 0x1c, 0x8c, 0x13, 0xef, 0x16, 0xb8, 0x1a, + 0x6d, 0x1e, 0xcf, 0x1a, 0xcc, 0x14, 0x6a, 0x10, 0x88, 0x04, 0x93, 0x0a, + 0x56, 0x13, 0xcd, 0x13, 0x32, 0x0d, 0x18, 0xff, 0x9e, 0xfc, 0x75, 0x03, + 0x9e, 0x0b, 0xf7, 0x11, 0x1a, 0x17, 0x89, 0x10, 0xdb, 0x16, 0x50, 0x24, + 0x75, 0x27, 0xd0, 0x35, 0x5b, 0x41, 0xa8, 0x3a, 0xec, 0x27, 0xd2, 0x29, + 0x47, 0x26, 0xfc, 0x16, 0x72, 0x0f, 0xbc, 0xfa, 0x64, 0xf1, 0x5a, 0xe6, + 0xe1, 0xd7, 0xd4, 0xd8, 0x79, 0xdb, 0x7e, 0xd8, 0x39, 0xda, 0x48, 0xe1, + 0x9d, 0xda, 0xe7, 0xd9, 0x06, 0xe3, 0xdf, 0xe6, 0x89, 0xe2, 0x06, 0xe4, + 0x37, 0xe8, 0x76, 0xe7, 0x21, 0xec, 0x6b, 0xe7, 0x09, 0xe7, 0x54, 0xee, + 0x99, 0xfa, 0x61, 0x00, 0x6c, 0xf8, 0xbe, 0xf6, 0x79, 0xf5, 0xd7, 0xfa, + 0x0d, 0xf8, 0x22, 0xf5, 0xde, 0xf5, 0xd7, 0xed, 0xaf, 0xe9, 0x30, 0xe1, + 0x51, 0xda, 0xa4, 0xde, 0x0c, 0xf0, 0x53, 0xf4, 0x2e, 0xf0, 0x31, 0xf1, + 0xd7, 0xf3, 0xde, 0x03, 0xf1, 0x14, 0x19, 0x2c, 0x21, 0x35, 0xb7, 0x31, + 0x75, 0x29, 0x7e, 0x22, 0x30, 0x2f, 0x42, 0x32, 0x73, 0x35, 0x0e, 0x35, + 0x78, 0x2a, 0x76, 0x2c, 0x14, 0x32, 0xc5, 0x2d, 0xd1, 0x2e, 0xb6, 0x2d, + 0xa6, 0x1f, 0xfe, 0x1d, 0x4e, 0x1c, 0xa2, 0x1c, 0xaa, 0x1b, 0xc8, 0x0f, + 0xba, 0x02, 0xc9, 0xf9, 0x00, 0x00, 0xfb, 0x00, 0x0d, 0xfd, 0xef, 0xfb, + 0xd6, 0xfe, 0x86, 0x04, 0x4b, 0x07, 0x0c, 0x14, 0x34, 0x1f, 0xbd, 0x20, + 0xdf, 0x21, 0xc3, 0x1e, 0x78, 0x1e, 0xbe, 0x28, 0xfb, 0x27, 0xa5, 0x1b, + 0x3e, 0x11, 0x30, 0x02, 0x06, 0xec, 0x97, 0xdc, 0x5b, 0xd2, 0x9c, 0xc8, + 0xb1, 0xd0, 0x59, 0xd1, 0x45, 0xbf, 0x62, 0xb4, 0xdc, 0xba, 0x95, 0xc4, + 0x94, 0xc1, 0x1f, 0xd1, 0x43, 0xe5, 0xc7, 0xdb, 0x88, 0xd9, 0x6b, 0xe9, + 0x72, 0xe6, 0x9e, 0xe1, 0x60, 0xf3, 0x24, 0xf9, 0xca, 0xf3, 0x6d, 0x01, + 0xfb, 0x13, 0x67, 0x11, 0xbd, 0x0a, 0x75, 0x10, 0x37, 0x10, 0x4c, 0x0d, + 0x5a, 0x10, 0x52, 0x13, 0x8a, 0x1a, 0x0e, 0x1c, 0x2c, 0x0c, 0x2b, 0x02, + 0x78, 0x00, 0xe3, 0xf8, 0x2f, 0xff, 0xbb, 0x0c, 0x02, 0x0f, 0xee, 0x0f, + 0x2c, 0x0a, 0xec, 0x05, 0xda, 0x0f, 0x29, 0x14, 0xe4, 0x17, 0xea, 0x1d, + 0x4b, 0x19, 0x39, 0x1d, 0x4f, 0x1f, 0x5c, 0x18, 0x17, 0x25, 0xae, 0x2d, + 0xfd, 0x23, 0xc9, 0x1f, 0x95, 0x1c, 0xad, 0x12, 0x7e, 0x09, 0xbd, 0x03, + 0x5f, 0xf4, 0x44, 0xe7, 0x87, 0xe8, 0xb4, 0xe7, 0xa6, 0xe7, 0xbf, 0xdd, + 0x7c, 0xd2, 0x1a, 0xda, 0x8e, 0xdd, 0x82, 0xde, 0xd7, 0xe4, 0xa6, 0xea, + 0x10, 0xea, 0xc8, 0xe6, 0x82, 0xeb, 0x00, 0xe9, 0x33, 0xe9, 0x72, 0xf1, + 0x21, 0xf2, 0x5c, 0xed, 0xe5, 0xe3, 0x50, 0xe7, 0x81, 0xef, 0x20, 0xf1, + 0x9f, 0xf5, 0x4e, 0xf7, 0x8a, 0xf8, 0x47, 0xf9, 0x6b, 0x02, 0xee, 0x07, + 0xa3, 0x01, 0x0d, 0x02, 0x10, 0x0e, 0x7e, 0x11, 0xb3, 0xfd, 0x6d, 0xf6, + 0xb8, 0xed, 0x50, 0xe7, 0x3c, 0xf8, 0x82, 0xfa, 0x2f, 0x01, 0x26, 0x0a, + 0x07, 0xff, 0xd1, 0x00, 0x75, 0x12, 0xaf, 0x1b, 0xea, 0x2f, 0x67, 0x3d, + 0x27, 0x36, 0x68, 0x3d, 0x87, 0x39, 0x44, 0x2d, 0x66, 0x27, 0xfe, 0x29, + 0x5a, 0x2e, 0xc0, 0x20, 0xec, 0x13, 0x3d, 0x13, 0x21, 0x1a, 0x87, 0x15, + 0x85, 0x10, 0xa8, 0x0e, 0xec, 0x08, 0xa1, 0x03, 0xdb, 0x04, 0x81, 0x05, + 0xfc, 0xff, 0x63, 0x0d, 0xca, 0x09, 0xb0, 0x05, 0x96, 0x04, 0x00, 0xf3, + 0xb4, 0xfd, 0x0f, 0x06, 0xcf, 0x0c, 0xa7, 0x1b, 0xad, 0x21, 0xfd, 0x24, + 0x94, 0x25, 0xdb, 0x26, 0xd9, 0x26, 0x06, 0x1e, 0xf5, 0x07, 0xae, 0xfa, + 0x8a, 0xee, 0x78, 0xe0, 0x13, 0xd9, 0xcf, 0xcf, 0xaa, 0xcc, 0xaf, 0xc3, + 0x72, 0xb2, 0xfc, 0xb5, 0x8b, 0xca, 0x90, 0xc7, 0x51, 0xcd, 0x5c, 0xe8, + 0x3c, 0xe3, 0x54, 0xd7, 0xc5, 0xe7, 0x08, 0xf2, 0xd5, 0xe7, 0x88, 0xf6, + 0x5c, 0x07, 0x0c, 0xff, 0xc1, 0x09, 0x40, 0x1d, 0xbc, 0x11, 0x3c, 0xff, + 0xb9, 0x08, 0xe3, 0x0c, 0xeb, 0x06, 0xa9, 0x09, 0x5f, 0x0b, 0x40, 0x0b, + 0xbb, 0x0b, 0x06, 0x0a, 0x2e, 0x04, 0x93, 0xff, 0x16, 0xf7, 0x5d, 0xfc, + 0x01, 0xfe, 0x7d, 0xf9, 0xef, 0x02, 0xc5, 0xfa, 0x64, 0xf6, 0xe0, 0xff, + 0xe0, 0x06, 0x26, 0x11, 0x34, 0x16, 0x16, 0x10, 0x65, 0x16, 0x37, 0x22, + 0x64, 0x1f, 0x14, 0x2e, 0x46, 0x37, 0x28, 0x25, 0x54, 0x19, 0x88, 0x16, + 0xf6, 0x0e, 0xcf, 0x08, 0x6f, 0x00, 0xc0, 0xee, 0x2e, 0xe5, 0x15, 0xe4, + 0x52, 0xe1, 0x54, 0xde, 0x90, 0xde, 0xfa, 0xda, 0xc6, 0xe0, 0x60, 0xe7, + 0x4d, 0xe2, 0xb7, 0xe5, 0xb1, 0xe7, 0x01, 0xec, 0xb8, 0xef, 0x4a, 0xf8, + 0xd5, 0x02, 0x85, 0xf8, 0x85, 0xf1, 0x27, 0xee, 0x02, 0xe7, 0xc2, 0xe8, + 0x63, 0xee, 0xdb, 0xf3, 0xae, 0xfb, 0x4d, 0x01, 0x5f, 0x02, 0x37, 0xfa, + 0x8b, 0xf0, 0xf0, 0xf2, 0x97, 0xfd, 0xf2, 0x0b, 0x9c, 0x11, 0x27, 0x0f, + 0xa0, 0x05, 0x1d, 0xf9, 0x04, 0x01, 0x10, 0x10, 0x69, 0x15, 0x0c, 0x1f, + 0x53, 0x1e, 0xd1, 0x0a, 0xdf, 0x03, 0xaa, 0x08, 0x6b, 0x0e, 0x91, 0x17, + 0x71, 0x1a, 0x98, 0x22, 0x51, 0x21, 0x2a, 0x13, 0xd7, 0x1d, 0x0c, 0x23, + 0x05, 0x24, 0xf0, 0x2d, 0xfa, 0x24, 0x71, 0x19, 0x4a, 0x11, 0x0f, 0x13, + 0xe2, 0x0f, 0xba, 0x0d, 0x7c, 0x16, 0x88, 0x0e, 0x8c, 0x0b, 0x7d, 0x0b, + 0xee, 0x07, 0xee, 0xff, 0xa6, 0xf7, 0xe7, 0xfc, 0x0a, 0x02, 0xe3, 0x00, + 0xa0, 0xfc, 0x88, 0xfc, 0x2f, 0xf2, 0xe0, 0xf0, 0xc4, 0xfe, 0x6c, 0x04, + 0x29, 0x10, 0x26, 0x17, 0xd2, 0x13, 0xae, 0x13, 0x9e, 0x17, 0x1d, 0x1a, + 0xc3, 0x23, 0x20, 0x1e, 0xb3, 0x02, 0xb4, 0xf5, 0x2b, 0xe7, 0x6b, 0xdb, + 0x4e, 0xdb, 0xdf, 0xe1, 0xba, 0xe0, 0xe4, 0xc7, 0x4b, 0xbe, 0x67, 0xc8, + 0x77, 0xd1, 0xb3, 0xd5, 0x84, 0xe0, 0x4a, 0xf4, 0x07, 0xef, 0xb4, 0xe8, + 0x40, 0x01, 0x8f, 0x05, 0x28, 0xf8, 0xdb, 0xff, 0x94, 0x03, 0x53, 0x00, + 0x17, 0x06, 0x08, 0x11, 0xbc, 0x0d, 0x47, 0x03, 0x55, 0x0c, 0x4e, 0x18, + 0x63, 0x18, 0x51, 0x0d, 0x43, 0x07, 0x3f, 0x0d, 0x81, 0x04, 0x53, 0xf8, + 0xa0, 0xfc, 0xbd, 0xf8, 0x90, 0xf2, 0xde, 0xf4, 0x4a, 0xf1, 0x66, 0xec, + 0xc0, 0xf2, 0x25, 0xfd, 0xc0, 0xfb, 0x1b, 0x01, 0x60, 0xff, 0x9b, 0xf8, + 0x61, 0x03, 0x53, 0x09, 0xd8, 0x13, 0x28, 0x15, 0x8e, 0x13, 0xbd, 0x20, + 0x72, 0x1f, 0x79, 0x14, 0x39, 0x0f, 0x4a, 0x0d, 0x1a, 0x05, 0xc7, 0xfe, + 0x8f, 0xf9, 0x2a, 0xec, 0x54, 0xdf, 0x90, 0xd9, 0x3a, 0xdb, 0x95, 0xd7, + 0xbc, 0xd8, 0x70, 0xdf, 0xe9, 0xde, 0x3b, 0xe0, 0xcb, 0xe1, 0x04, 0xe9, + 0x1c, 0xf0, 0x05, 0xf8, 0x5e, 0xfa, 0x4c, 0xf6, 0x7f, 0x01, 0xed, 0xfc, + 0x4f, 0xfa, 0x52, 0x03, 0xcd, 0xff, 0x01, 0xfd, 0x54, 0xfa, 0x9f, 0xfe, + 0xb8, 0xfe, 0x4f, 0xfe, 0x2d, 0x02, 0xa3, 0xfe, 0x64, 0xfb, 0xbc, 0xfc, + 0x77, 0xff, 0x08, 0x03, 0xec, 0x05, 0xdb, 0x06, 0x2d, 0x0b, 0x22, 0x0a, + 0x2d, 0x10, 0xec, 0x0e, 0x77, 0x0c, 0x43, 0x18, 0x43, 0x1e, 0x8e, 0x29, + 0x5f, 0x2a, 0x0a, 0x35, 0xb6, 0x43, 0x84, 0x3f, 0xe3, 0x39, 0x34, 0x26, + 0x15, 0x18, 0xd8, 0x1b, 0xe6, 0x1e, 0x32, 0x20, 0x53, 0x20, 0x05, 0x0c, + 0x98, 0xfa, 0xc6, 0xfd, 0x2c, 0x04, 0x51, 0x0a, 0x2f, 0x0f, 0x86, 0x15, + 0x93, 0x0c, 0x73, 0x00, 0xc0, 0xf9, 0xa2, 0xf8, 0xe9, 0xf7, 0x40, 0xef, + 0x88, 0xf7, 0xb0, 0xf9, 0x0d, 0xe8, 0xe1, 0xe1, 0x42, 0xeb, 0xd0, 0xee, + 0x96, 0xfb, 0xf8, 0x09, 0xce, 0xfb, 0xce, 0xf5, 0xfc, 0xf9, 0xbf, 0xf8, + 0x96, 0x06, 0x0d, 0x16, 0xba, 0x18, 0xea, 0x1f, 0x60, 0x19, 0x35, 0x0d, + 0x73, 0x11, 0x1d, 0x05, 0x6c, 0xf8, 0xd3, 0xf3, 0x45, 0xe5, 0x6e, 0xd3, + 0xdf, 0xd0, 0xde, 0xdd, 0xa3, 0xd8, 0x05, 0xcb, 0x7b, 0xcd, 0x32, 0xd7, + 0x1f, 0xd9, 0x7d, 0xee, 0x39, 0x10, 0x6b, 0x0f, 0x85, 0x06, 0x69, 0x0d, + 0x44, 0x0e, 0xd1, 0x03, 0x27, 0x0d, 0x0f, 0x1d, 0x8e, 0x11, 0xc3, 0x08, + 0xfe, 0x0c, 0xa8, 0x09, 0xe9, 0x0a, 0x72, 0x12, 0x17, 0x13, 0x0d, 0x0e, + 0xa3, 0x03, 0x08, 0x03, 0xf7, 0x03, 0x23, 0x02, 0xe7, 0xfd, 0xbf, 0xf7, + 0xa0, 0xf7, 0x11, 0xed, 0x84, 0xed, 0x78, 0xf2, 0x25, 0xf4, 0xfb, 0xf6, + 0xd0, 0xf3, 0x75, 0xf0, 0x2d, 0xe7, 0x80, 0xe8, 0xc6, 0xf0, 0x1d, 0xfa, + 0x2d, 0xfa, 0x28, 0xff, 0x0f, 0x09, 0x80, 0x02, 0xd3, 0x0a, 0xdf, 0x14, + 0x18, 0x10, 0xfa, 0x03, 0x5d, 0x00, 0xd7, 0xfe, 0x0d, 0xf4, 0xda, 0xf0, + 0xd2, 0xe8, 0x57, 0xda, 0xb1, 0xd3, 0x32, 0xda, 0x62, 0xe1, 0xe9, 0xdb, + 0x49, 0xd4, 0x0b, 0xdf, 0x57, 0xeb, 0x5f, 0xeb, 0x53, 0xf0, 0x95, 0xf4, + 0x89, 0xf9, 0xf2, 0xff, 0xe1, 0x05, 0xbc, 0x09, 0x8b, 0x03, 0x06, 0xff, + 0xac, 0x07, 0x79, 0x06, 0x58, 0xfd, 0x22, 0x02, 0x6d, 0x04, 0x9a, 0x0c, + 0xdc, 0x12, 0x5e, 0x08, 0x06, 0x03, 0x5b, 0xfe, 0xf9, 0x05, 0x13, 0x13, + 0x7f, 0x09, 0x8c, 0x06, 0xf2, 0x07, 0xd2, 0x05, 0x3e, 0x0d, 0x0b, 0x12, + 0x03, 0x15, 0x6f, 0x0f, 0xf5, 0x11, 0x42, 0x1d, 0x4b, 0x27, 0x6a, 0x39, + 0x8f, 0x4d, 0x3e, 0x57, 0x71, 0x54, 0xfb, 0x58, 0xe9, 0x4c, 0x30, 0x3d, + 0xdb, 0x32, 0x37, 0x26, 0xa8, 0x26, 0xac, 0x18, 0xa3, 0x07, 0x98, 0xf9, + 0xae, 0xf9, 0x59, 0xf7, 0x66, 0xea, 0x9d, 0xee, 0x75, 0xe7, 0x13, 0xe3, + 0x6d, 0xe6, 0x70, 0xeb, 0x4f, 0xf0, 0x0a, 0xe9, 0x44, 0xe3, 0x2a, 0xe2, + 0xf4, 0xe5, 0x63, 0xe9, 0xb1, 0xf1, 0xef, 0xf2, 0x7e, 0xe7, 0xba, 0xe7, + 0x01, 0xf2, 0xf3, 0xf9, 0x70, 0xf6, 0x98, 0xf3, 0xbb, 0xf8, 0x9d, 0xfa, + 0x7a, 0x02, 0xb2, 0x12, 0x2a, 0x23, 0xaa, 0x27, 0x4c, 0x24, 0x81, 0x21, + 0xd5, 0x13, 0x85, 0x07, 0xb9, 0xf7, 0xd7, 0xe6, 0x6f, 0xd9, 0xd6, 0xcb, + 0x91, 0xd1, 0x40, 0xd5, 0x9e, 0xd0, 0x5b, 0xd4, 0x12, 0xe7, 0xd6, 0xf2, + 0xbe, 0xf8, 0x58, 0x19, 0x4a, 0x35, 0xc0, 0x36, 0x4d, 0x28, 0xf6, 0x26, + 0x27, 0x22, 0xdf, 0x0f, 0x3d, 0x18, 0x72, 0x21, 0x26, 0x13, 0xe0, 0x02, + 0x97, 0x04, 0x42, 0x09, 0xc7, 0x03, 0xf6, 0x01, 0xd4, 0x07, 0x14, 0xfe, + 0xfc, 0xf2, 0x6f, 0xfc, 0xdf, 0x03, 0x70, 0x00, 0x5e, 0xf4, 0xba, 0xf4, + 0x9e, 0xec, 0xb2, 0xe2, 0x5a, 0xe6, 0xe9, 0xe9, 0x48, 0xed, 0xc7, 0xe3, + 0x71, 0xe6, 0x28, 0xdf, 0xb1, 0xdc, 0xbd, 0xe8, 0xee, 0xe8, 0x02, 0xf0, + 0x83, 0xf2, 0x3c, 0xfa, 0x39, 0xfa, 0x6b, 0xf4, 0xa2, 0x00, 0x49, 0x0c, + 0x3c, 0x06, 0xa3, 0xfc, 0xd7, 0xfa, 0xb6, 0xf2, 0x75, 0xe1, 0xab, 0xd6, + 0xaf, 0xd9, 0x2f, 0xd3, 0xa3, 0xd1, 0x0e, 0xda, 0x6d, 0xdd, 0x66, 0xe3, + 0xe5, 0xe8, 0x23, 0xf1, 0xfb, 0xf7, 0xe2, 0xf5, 0x63, 0xfe, 0x42, 0x10, + 0xa0, 0x14, 0x6c, 0x1b, 0xdd, 0x1b, 0x3a, 0x15, 0x81, 0x11, 0x6b, 0x0c, + 0xc5, 0x15, 0xc8, 0x18, 0x69, 0x0e, 0xc4, 0x08, 0x75, 0x04, 0xc0, 0x00, + 0x79, 0x06, 0xb6, 0x0e, 0xbd, 0x12, 0xfd, 0x0e, 0xa5, 0x0c, 0x70, 0x0e, + 0x93, 0x09, 0xda, 0x0c, 0xde, 0x15, 0x64, 0x1b, 0xb8, 0x1a, 0xd8, 0x1a, + 0xcf, 0x1b, 0x8e, 0x1b, 0x7b, 0x21, 0x6f, 0x31, 0xd5, 0x3e, 0xa1, 0x3a, + 0x4e, 0x3a, 0x90, 0x3e, 0xe7, 0x48, 0xe2, 0x4f, 0x18, 0x4c, 0x94, 0x44, + 0x7c, 0x33, 0x57, 0x26, 0x8f, 0x20, 0x1c, 0x14, 0xed, 0xf9, 0x4c, 0xe5, + 0xa5, 0xdb, 0xcc, 0xd5, 0x3d, 0xcc, 0x26, 0xcc, 0xca, 0xce, 0xbc, 0xca, + 0x8d, 0xd6, 0x02, 0xd9, 0x25, 0xdf, 0x8a, 0xe5, 0x9b, 0xdd, 0x8f, 0xe8, + 0xb9, 0xf5, 0xb4, 0xf8, 0x2b, 0x05, 0x2f, 0x02, 0xf1, 0xf3, 0x98, 0xf5, + 0x08, 0xf0, 0x92, 0xf5, 0x53, 0xfb, 0x71, 0x02, 0x6f, 0x02, 0x42, 0xf6, + 0xce, 0x02, 0x2e, 0x06, 0x9b, 0x14, 0x9c, 0x1f, 0xfc, 0x20, 0xff, 0x25, + 0x1b, 0x1e, 0x36, 0x19, 0xa3, 0x0a, 0xd9, 0x01, 0x22, 0xfc, 0x4d, 0xf0, + 0xd3, 0xdf, 0x88, 0xe4, 0xd6, 0xed, 0x46, 0xeb, 0x18, 0xf2, 0x21, 0xf4, + 0xdb, 0x05, 0xeb, 0x0d, 0x9d, 0x19, 0x22, 0x32, 0xec, 0x3c, 0x5b, 0x30, + 0x82, 0x1e, 0xf3, 0x23, 0xca, 0x13, 0x89, 0x0c, 0x89, 0x07, 0x89, 0xfa, + 0xc6, 0xf5, 0x72, 0xee, 0x10, 0xf7, 0x17, 0xea, 0x4e, 0xe3, 0x37, 0xeb, + 0xb2, 0xe5, 0x3b, 0xe8, 0xfd, 0xec, 0x85, 0xf4, 0x7d, 0xf9, 0xec, 0xf2, + 0x10, 0xf0, 0x11, 0xf3, 0xba, 0xf1, 0x23, 0xee, 0x1c, 0xea, 0x00, 0xe9, + 0xe9, 0xe5, 0x90, 0xe2, 0xf1, 0xdc, 0xb6, 0xd7, 0xd4, 0xda, 0xae, 0xde, + 0x48, 0xe6, 0xe4, 0xe7, 0x56, 0xe9, 0x91, 0xf1, 0x49, 0xf8, 0x21, 0xfb, + 0x59, 0xfd, 0x8e, 0xfd, 0xfa, 0xf7, 0x48, 0xfa, 0xdd, 0xf8, 0xc9, 0xeb, + 0x61, 0xe1, 0xc7, 0xdc, 0xfb, 0xe0, 0x79, 0xeb, 0x77, 0xee, 0x55, 0xf2, + 0x6d, 0xf7, 0xe8, 0xfd, 0xdd, 0x0d, 0xbc, 0x17, 0x03, 0x22, 0x2d, 0x24, + 0xee, 0x24, 0xa6, 0x24, 0xa4, 0x17, 0xb2, 0x16, 0x23, 0x16, 0x1f, 0x11, + 0x0b, 0x08, 0x5c, 0xff, 0xd7, 0xfd, 0x5a, 0x01, 0xf2, 0x07, 0x0c, 0x0b, + 0xd7, 0x0b, 0x65, 0x0c, 0x49, 0x11, 0x46, 0x13, 0x84, 0x1d, 0x53, 0x28, + 0xe5, 0x2f, 0xc8, 0x30, 0x98, 0x29, 0x33, 0x2b, 0x02, 0x26, 0xa4, 0x25, + 0x90, 0x22, 0x02, 0x24, 0xc9, 0x27, 0x91, 0x1d, 0x26, 0x1a, 0x06, 0x16, + 0x95, 0x15, 0xa6, 0x17, 0xd3, 0x1a, 0x20, 0x16, 0x69, 0x12, 0x8d, 0x0e, + 0x72, 0x02, 0x7e, 0xfe, 0xa6, 0xf4, 0xf8, 0xf4, 0xaf, 0xfe, 0x18, 0xff, + 0x98, 0xf6, 0x65, 0xe7, 0x1f, 0xd1, 0x3c, 0xc7, 0x07, 0xcb, 0xde, 0xd1, + 0x17, 0xe3, 0x04, 0xe4, 0xda, 0xe5, 0xd0, 0xe4, 0x4a, 0xe0, 0x15, 0xea, + 0x78, 0xf3, 0x01, 0x06, 0x84, 0x10, 0x0f, 0x08, 0x7b, 0xfc, 0xcc, 0xfb, + 0x12, 0xf6, 0x8b, 0xf0, 0x9b, 0xf6, 0x3a, 0xf5, 0xaf, 0xeb, 0x07, 0xf1, + 0xb5, 0x04, 0xf0, 0x0a, 0x58, 0x0e, 0xee, 0x11, 0x66, 0x25, 0xaf, 0x31, + 0x08, 0x36, 0xcc, 0x48, 0xe9, 0x46, 0x87, 0x3c, 0x08, 0x36, 0x8d, 0x2e, + 0xc0, 0x18, 0x04, 0x10, 0xd5, 0x06, 0x85, 0xf7, 0x05, 0xf9, 0xbb, 0xea, + 0x86, 0xe3, 0x20, 0xea, 0xbd, 0xfd, 0xe0, 0xfd, 0x89, 0xfc, 0x6f, 0x11, + 0x2b, 0x12, 0xda, 0x09, 0xdf, 0x04, 0x52, 0x09, 0xdf, 0xf5, 0x1d, 0xe9, + 0x00, 0xf1, 0x65, 0xe4, 0xab, 0xd6, 0xfa, 0xe0, 0x91, 0xea, 0x24, 0xd8, + 0xf5, 0xdb, 0x83, 0xe9, 0x5f, 0xec, 0xf9, 0xea, 0xd3, 0xe9, 0x0f, 0xf1, + 0x16, 0xf5, 0xd2, 0xfb, 0x39, 0xf2, 0x36, 0xe9, 0xc7, 0xe4, 0xdc, 0xdd, + 0xc0, 0xdf, 0x03, 0xe0, 0x3f, 0xdd, 0x60, 0xd4, 0x79, 0xce, 0x39, 0xd1, + 0xf1, 0xd5, 0x61, 0xdd, 0xf7, 0xe7, 0x4c, 0xef, 0xf5, 0xf6, 0x3c, 0xf7, + 0x3e, 0xf8, 0x2f, 0x04, 0x8d, 0x0c, 0xf7, 0x0d, 0xec, 0x0f, 0xa2, 0x14, + 0xa8, 0x0e, 0xda, 0x09, 0x98, 0x04, 0xa1, 0x04, 0x1a, 0x0b, 0xf5, 0x08, + 0x45, 0x0d, 0xcd, 0x0d, 0xf9, 0x09, 0x36, 0x0f, 0x2c, 0x1b, 0x23, 0x21, + 0x44, 0x24, 0x4f, 0x1c, 0xfc, 0x12, 0xaa, 0x1c, 0xbd, 0x17, 0x85, 0x15, + 0x41, 0x19, 0x70, 0x12, 0x42, 0x0f, 0x84, 0x07, 0x44, 0x0b, 0xb0, 0x14, + 0x07, 0x19, 0x09, 0x23, 0x64, 0x25, 0x73, 0x23, 0x05, 0x25, 0x04, 0x29, + 0x5b, 0x25, 0xea, 0x21, 0xd1, 0x26, 0xc5, 0x17, 0x09, 0x0c, 0xe1, 0x07, + 0x85, 0xfb, 0xe5, 0xf5, 0xcb, 0xed, 0xcf, 0xe7, 0x4d, 0xe8, 0xeb, 0xe7, + 0xa6, 0xe3, 0x46, 0xe5, 0xee, 0xea, 0x65, 0xf2, 0x57, 0xf9, 0xdb, 0xf5, + 0xd1, 0xee, 0xae, 0xe9, 0x63, 0xf1, 0x16, 0xfb, 0x48, 0x07, 0xf6, 0x0b, + 0xc5, 0x0c, 0x3d, 0x11, 0x53, 0x06, 0x82, 0x03, 0x07, 0x00, 0x2f, 0xfe, + 0x1f, 0xfb, 0xd3, 0xec, 0x8d, 0xe8, 0x0e, 0xe6, 0x24, 0xe3, 0x30, 0xeb, + 0xde, 0xf1, 0x4e, 0xe7, 0x1d, 0xe9, 0xac, 0xee, 0x70, 0xf2, 0xfc, 0x00, + 0x48, 0x08, 0xab, 0x0e, 0x92, 0x15, 0x1c, 0x18, 0x52, 0x15, 0x82, 0x1c, + 0xcf, 0x20, 0xca, 0x21, 0x15, 0x32, 0xbe, 0x36, 0x27, 0x34, 0x1c, 0x3d, + 0x7c, 0x3f, 0x0a, 0x3d, 0x70, 0x49, 0x0c, 0x4f, 0x6d, 0x4e, 0x87, 0x4c, + 0xce, 0x39, 0x8a, 0x21, 0xa0, 0x0c, 0xdc, 0xfa, 0x71, 0xeb, 0x7a, 0xdc, + 0xe5, 0xce, 0x66, 0xd0, 0x63, 0xcc, 0xc2, 0xbe, 0x43, 0xca, 0x55, 0xd7, + 0x14, 0xd4, 0x01, 0xde, 0x8d, 0xf3, 0x4c, 0xfd, 0x70, 0xf5, 0xea, 0xf2, + 0x4e, 0xfb, 0x61, 0xe7, 0xa4, 0xde, 0x32, 0xee, 0x61, 0xe6, 0x00, 0xe3, + 0x26, 0xe8, 0xe7, 0xe1, 0x18, 0xd4, 0x0d, 0xd9, 0x13, 0xea, 0xce, 0xe5, + 0x6c, 0xdd, 0x0c, 0xd8, 0xdb, 0xda, 0xb2, 0xe8, 0xd6, 0xe7, 0x5f, 0xde, + 0x25, 0xdb, 0xbc, 0xdd, 0xde, 0xe1, 0xbc, 0xdf, 0x7b, 0xe2, 0x60, 0xe2, + 0xcd, 0xe4, 0xda, 0xf1, 0x25, 0xf7, 0xee, 0xf9, 0x82, 0x01, 0x25, 0x11, + 0x4b, 0x17, 0x54, 0x21, 0x91, 0x34, 0x21, 0x33, 0x89, 0x33, 0x0d, 0x38, + 0xf4, 0x36, 0xd1, 0x36, 0x03, 0x36, 0x5e, 0x31, 0xa0, 0x20, 0xfc, 0x10, + 0x62, 0x0d, 0xf4, 0x0c, 0x46, 0x0c, 0xaa, 0x0b, 0x91, 0x0b, 0x86, 0x09, + 0xd7, 0x10, 0xf8, 0x21, 0x41, 0x25, 0x77, 0x27, 0xe3, 0x26, 0xa6, 0x25, + 0x7d, 0x2c, 0x27, 0x24, 0x1e, 0x27, 0x9b, 0x2c, 0x7f, 0x1b, 0x29, 0x13, + 0x68, 0x0d, 0x6e, 0x00, 0x81, 0xfc, 0x18, 0xf5, 0x32, 0xed, 0x16, 0xf3, + 0x18, 0xe8, 0x3d, 0xdd, 0xb1, 0xdf, 0x8f, 0xd7, 0x4b, 0xe0, 0x4f, 0xe6, + 0x0e, 0xdc, 0xf0, 0xdc, 0x58, 0xd5, 0x36, 0xcf, 0x8b, 0xd7, 0x8a, 0xd7, + 0x81, 0xd3, 0xda, 0xd5, 0x87, 0xdb, 0x23, 0xe3, 0x92, 0xea, 0x6a, 0xef, + 0xb5, 0xf9, 0x5f, 0x0a, 0x0d, 0x13, 0x1f, 0x1b, 0x94, 0x23, 0x58, 0x2d, + 0x44, 0x36, 0xf9, 0x27, 0xbb, 0x16, 0xd4, 0x17, 0x77, 0x1a, 0x97, 0x24, + 0x8f, 0x32, 0xa4, 0x1b, 0x0c, 0xfc, 0x39, 0xf3, 0x0e, 0xef, 0x92, 0xfa, + 0xbd, 0x06, 0x59, 0x07, 0x94, 0x08, 0x2f, 0x0a, 0x4e, 0x0b, 0x6a, 0x15, + 0x72, 0x22, 0x7d, 0x26, 0x9a, 0x30, 0x9b, 0x35, 0x63, 0x35, 0x54, 0x34, + 0x7f, 0x2a, 0xc8, 0x20, 0xb3, 0x29, 0xfb, 0x2d, 0x62, 0x17, 0xe9, 0x1b, + 0x97, 0x23, 0x6e, 0x18, 0xad, 0x1a, 0x88, 0x20, 0xcd, 0x24, 0x3f, 0x1d, + 0x5b, 0x12, 0xf2, 0x14, 0xa4, 0x1e, 0xf6, 0x11, 0xd4, 0xff, 0xbe, 0xf0, + 0x57, 0xd2, 0x7a, 0xc5, 0x59, 0xc1, 0xce, 0xbb, 0xdf, 0xbe, 0xf0, 0xbf, + 0x84, 0xb7, 0xf0, 0xb9, 0x35, 0xc6, 0x14, 0xcb, 0x34, 0xd9, 0x90, 0xe6, + 0x60, 0xee, 0x42, 0xe4, 0xd9, 0xe1, 0x8a, 0xf7, 0xf2, 0xef, 0x79, 0xdf, + 0x60, 0xe5, 0x12, 0xec, 0x26, 0xe1, 0x54, 0xe5, 0x6e, 0xf2, 0x85, 0xe2, + 0xeb, 0xdd, 0x0c, 0xe6, 0x31, 0xe8, 0x74, 0xed, 0x29, 0xef, 0x5e, 0xef, + 0xe3, 0xf5, 0x37, 0xff, 0xed, 0x00, 0x0f, 0x00, 0x29, 0x04, 0x5a, 0x09, + 0x54, 0x0b, 0xaa, 0x11, 0x47, 0x16, 0x07, 0x10, 0x45, 0x0f, 0xec, 0x12, + 0x40, 0x14, 0xb7, 0x16, 0xb5, 0x19, 0xfd, 0x22, 0x7b, 0x2f, 0xc5, 0x33, + 0xce, 0x38, 0xc8, 0x3c, 0x7c, 0x39, 0xce, 0x3f, 0xa8, 0x3e, 0x7e, 0x36, + 0xa8, 0x35, 0x60, 0x2e, 0xef, 0x2b, 0x19, 0x25, 0x80, 0x15, 0x18, 0x07, + 0xab, 0x01, 0xe2, 0x09, 0x48, 0x04, 0xf4, 0xf5, 0xdb, 0xef, 0x1b, 0xf5, + 0xc8, 0x02, 0xd8, 0x02, 0x00, 0xf6, 0xeb, 0xf1, 0x75, 0xef, 0x6e, 0xe8, + 0xa9, 0xe8, 0xec, 0xe7, 0xd4, 0xec, 0xb0, 0xe8, 0x57, 0xd3, 0x67, 0xc1, + 0x2a, 0xba, 0x30, 0xd0, 0xc4, 0xe5, 0x8c, 0xdf, 0x63, 0xd0, 0x84, 0xcc, + 0x36, 0xda, 0x45, 0xe8, 0xe2, 0xe4, 0x62, 0xe6, 0x92, 0xfc, 0x72, 0xfc, + 0xce, 0xf0, 0xba, 0xe6, 0xfe, 0xdd, 0x17, 0xe8, 0x88, 0xeb, 0x43, 0xed, + 0x31, 0xf6, 0x74, 0x04, 0x4a, 0x0a, 0x3a, 0x03, 0xbc, 0x0c, 0xee, 0x23, + 0xe1, 0x35, 0x71, 0x39, 0xeb, 0x3c, 0x6a, 0x46, 0x7e, 0x47, 0x38, 0x3b, + 0xbd, 0x2e, 0xf4, 0x31, 0x82, 0x46, 0x37, 0x58, 0x69, 0x44, 0x25, 0x1d, + 0xf0, 0x06, 0x44, 0x09, 0xb8, 0x1f, 0xbc, 0x26, 0x58, 0x19, 0x17, 0x16, + 0xf6, 0x0e, 0x0b, 0x14, 0xab, 0x2e, 0x0b, 0x28, 0x9e, 0x1d, 0xae, 0x23, + 0x43, 0x1b, 0x62, 0x1a, 0x86, 0x15, 0x8f, 0x08, 0x51, 0x0e, 0x7a, 0x14, + 0x7f, 0x01, 0xab, 0xe9, 0xf4, 0xe9, 0x36, 0xf9, 0xa6, 0x12, 0x10, 0x0f, + 0x25, 0xeb, 0xe8, 0xeb, 0xbe, 0xec, 0xba, 0xe4, 0xad, 0xff, 0x8f, 0x0c, + 0xd7, 0x02, 0xa3, 0xf5, 0x29, 0xeb, 0x4f, 0xe5, 0x24, 0xcc, 0x40, 0xaf, + 0xfc, 0xa7, 0xef, 0xb4, 0x9e, 0xc7, 0xa1, 0xc6, 0xd9, 0xb0, 0x9f, 0xae, + 0x09, 0xcb, 0x43, 0xe5, 0x46, 0xeb, 0xf6, 0xe4, 0xd9, 0xe9, 0x34, 0xf8, + 0xcf, 0x00, 0x83, 0x06, 0x6f, 0xfe, 0xd5, 0xe3, 0xa1, 0xee, 0x68, 0x18, + 0xdc, 0x10, 0xe6, 0xe6, 0x77, 0xda, 0x68, 0xf0, 0xd4, 0x04, 0x63, 0x14, + 0x05, 0x12, 0xd0, 0x09, 0x63, 0x1a, 0x91, 0x25, 0xf2, 0x1f, 0xdf, 0x09, + 0x8d, 0x00, 0xe3, 0x15, 0x22, 0x34, 0xc6, 0x39, 0x17, 0x26, 0x3e, 0x24, + 0x81, 0x1d, 0x5a, 0x15, 0xca, 0x1e, 0x89, 0x24, 0xb2, 0x2b, 0x1c, 0x2f, + 0xa7, 0x2f, 0x1f, 0x35, 0x88, 0x2d, 0xe2, 0x24, 0xa7, 0x22, 0xb8, 0x1a, + 0xf2, 0x1c, 0x5a, 0x21, 0x39, 0x1c, 0xc8, 0x01, 0xfb, 0xe3, 0xa3, 0xea, + 0x49, 0xfd, 0xb4, 0xfc, 0x52, 0xec, 0xad, 0xd7, 0x6e, 0xc8, 0x57, 0xcc, + 0x39, 0xd8, 0xd8, 0xdb, 0x7a, 0xdc, 0x71, 0xe4, 0xfb, 0xe4, 0x5a, 0xd8, + 0xbd, 0xe1, 0x57, 0xf3, 0xb5, 0xf4, 0x02, 0xe6, 0x73, 0xdb, 0xff, 0xeb, + 0xf8, 0xf2, 0xf3, 0xe4, 0x37, 0xe6, 0x37, 0xe8, 0xf2, 0xe6, 0xd5, 0xef, + 0x7d, 0xeb, 0x24, 0xe1, 0x70, 0xd4, 0x77, 0xe2, 0x64, 0xf7, 0xe5, 0xe7, + 0xb4, 0xed, 0xd2, 0xfa, 0x68, 0xfc, 0xd6, 0x0a, 0xa9, 0x15, 0x07, 0x10, + 0x92, 0x05, 0x8c, 0x00, 0x4e, 0x08, 0x26, 0x1b, 0x43, 0x1a, 0x9a, 0x1d, + 0xa2, 0x31, 0xcc, 0x37, 0x02, 0x2f, 0x21, 0x2b, 0x48, 0x32, 0xda, 0x43, + 0x36, 0x5b, 0x6a, 0x5c, 0x88, 0x57, 0xe7, 0x4a, 0x01, 0x3c, 0x06, 0x2f, + 0x6f, 0x1e, 0x38, 0x26, 0xd5, 0x1c, 0x6a, 0x07, 0x64, 0x05, 0xbd, 0x01, + 0x21, 0xf3, 0x2b, 0xee, 0x28, 0xf2, 0x41, 0xef, 0x27, 0xfe, 0xe4, 0x01, + 0xc6, 0xf9, 0x5b, 0xfc, 0x51, 0xf9, 0x51, 0xf7, 0xbc, 0x04, 0xdb, 0x0e, + 0x84, 0xf9, 0x2f, 0xf6, 0x63, 0xf5, 0x95, 0xda, 0xbb, 0xd2, 0x2d, 0xd4, + 0xd4, 0xe2, 0xe6, 0xf0, 0xda, 0xde, 0x80, 0xd1, 0x64, 0xd7, 0x30, 0xd0, + 0x11, 0xd3, 0xd2, 0xed, 0xc7, 0xf6, 0x52, 0xfe, 0x87, 0x11, 0x25, 0x1b, + 0x0b, 0x1a, 0x3b, 0x07, 0xe1, 0xe8, 0x85, 0xdd, 0xe2, 0xe4, 0x99, 0xe7, + 0x16, 0xed, 0x51, 0xf0, 0xc8, 0xe3, 0xc8, 0xd6, 0xf1, 0xd5, 0x1a, 0xe6, + 0x1c, 0xfe, 0x83, 0x0c, 0xa4, 0x1a, 0x71, 0x2d, 0x9a, 0x24, 0x34, 0x13, + 0xdd, 0x1b, 0x6d, 0x25, 0xf9, 0x30, 0x4e, 0x44, 0x7c, 0x46, 0xe6, 0x2e, + 0x14, 0x0b, 0x6d, 0xfd, 0xbd, 0x0f, 0x68, 0x13, 0xcc, 0x05, 0x4b, 0x11, + 0xd3, 0x27, 0x76, 0x3a, 0x26, 0x44, 0xf5, 0x2f, 0x27, 0x0f, 0x61, 0xf8, + 0x07, 0xf5, 0x9b, 0x04, 0x4a, 0x0b, 0x7a, 0xed, 0xf9, 0xc1, 0x78, 0xb7, + 0x10, 0xc5, 0xd4, 0xd6, 0x76, 0xe3, 0x6b, 0xe3, 0x1b, 0xe7, 0x8f, 0xef, + 0x6f, 0xf2, 0xa5, 0xeb, 0x28, 0xe7, 0xa4, 0xe7, 0x45, 0xe0, 0x55, 0xdf, + 0x33, 0xf0, 0x55, 0xfb, 0x62, 0xf6, 0x18, 0xef, 0x3e, 0xe6, 0x77, 0xe4, + 0xe0, 0xeb, 0x84, 0xf6, 0x5d, 0xfb, 0x85, 0xf1, 0x60, 0xf3, 0xfd, 0xf9, + 0x53, 0xf1, 0x4e, 0xee, 0xa7, 0xf3, 0xba, 0xfd, 0xa6, 0x06, 0x1e, 0x04, + 0xb8, 0x01, 0x32, 0xfb, 0x72, 0xf8, 0x2b, 0x09, 0xff, 0x1a, 0x62, 0x13, + 0x1e, 0xfe, 0x25, 0x0a, 0x29, 0x29, 0x2c, 0x3f, 0xc8, 0x37, 0x75, 0x16, + 0x2b, 0x08, 0xa6, 0x16, 0x1a, 0x2f, 0x4d, 0x1e, 0xb7, 0xff, 0xb6, 0xff, + 0xc8, 0x0e, 0xb2, 0x22, 0xc9, 0x24, 0xc2, 0x17, 0x68, 0x0c, 0x9a, 0x0d, + 0xbd, 0x0a, 0x2a, 0x15, 0x42, 0x21, 0x97, 0x1f, 0x78, 0x25, 0xf0, 0x18, + 0x0f, 0x13, 0x3e, 0x10, 0x1c, 0x13, 0x26, 0x20, 0x97, 0x20, 0xfe, 0x18, + 0x50, 0x10, 0x6a, 0x1b, 0xf3, 0x1c, 0x87, 0x0d, 0x8c, 0xf8, 0xa0, 0xf2, + 0xe3, 0xf5, 0xc1, 0xea, 0x82, 0xdf, 0x91, 0xd7, 0xd2, 0xda, 0xd1, 0xd8, + 0x40, 0xdb, 0x59, 0xd9, 0xea, 0xd2, 0x1d, 0xdd, 0xce, 0xe8, 0x97, 0xf3, + 0x8d, 0x00, 0x56, 0x11, 0x9e, 0x0a, 0xd5, 0xfb, 0x87, 0xf5, 0xb5, 0xe9, + 0x5d, 0xe3, 0x4b, 0xe2, 0x55, 0xe4, 0x74, 0xf1, 0x6b, 0xfd, 0xd9, 0xfe, + 0x00, 0x0c, 0xc3, 0x15, 0xb6, 0x17, 0x7a, 0x1f, 0x01, 0x1b, 0xef, 0x0e, + 0xe9, 0x15, 0x19, 0x25, 0xff, 0x26, 0xc8, 0x28, 0x5c, 0x39, 0xb8, 0x51, + 0xe6, 0x53, 0xd0, 0x39, 0x5d, 0x16, 0x5c, 0xf8, 0x89, 0xe7, 0x9e, 0xee, + 0x89, 0xf9, 0x1b, 0xf8, 0x33, 0xfa, 0x20, 0xfd, 0x21, 0x0d, 0x74, 0x17, + 0x48, 0xfd, 0x24, 0xdb, 0xcd, 0xef, 0x09, 0x1b, 0x9f, 0x17, 0xc2, 0x05, + 0x9e, 0xfe, 0xf5, 0xf2, 0x62, 0xeb, 0xb2, 0x04, 0xa3, 0x0f, 0xcd, 0xfc, + 0xbc, 0xf7, 0xe5, 0xf7, 0x11, 0xf2, 0x19, 0xe5, 0xc3, 0xe3, 0xff, 0xe2, + 0x6f, 0xe0, 0x42, 0xe9, 0x0e, 0xf4, 0xa5, 0xf5, 0x58, 0xdd, 0xd7, 0xc3, + 0x4a, 0xcb, 0x73, 0xdc, 0x81, 0xd7, 0xad, 0xd6, 0x58, 0xdf, 0x24, 0xe1, + 0x1c, 0xeb, 0x08, 0xf3, 0x61, 0xf2, 0x28, 0xe5, 0x61, 0xc9, 0x8d, 0xd2, + 0x8e, 0xf8, 0xd7, 0x0d, 0xce, 0x20, 0xe6, 0x2e, 0xc0, 0x3a, 0xbb, 0x4b, + 0x76, 0x54, 0xc8, 0x4d, 0x3f, 0x48, 0x07, 0x46, 0x33, 0x3b, 0x2a, 0x31, + 0xc7, 0x25, 0xd8, 0x27, 0x6f, 0x24, 0x1a, 0x14, 0xec, 0x14, 0xc8, 0x16, + 0x8d, 0x14, 0x15, 0x21, 0xc0, 0x30, 0x15, 0x27, 0x5e, 0x1f, 0x44, 0x27, + 0xf6, 0x30, 0x63, 0x38, 0x8c, 0x33, 0x08, 0x23, 0xb4, 0x10, 0xa9, 0x09, + 0x1c, 0x0c, 0x2f, 0x1b, 0x67, 0x13, 0xa9, 0xff, 0xf4, 0x01, 0x68, 0xf8, + 0xd9, 0xef, 0xde, 0xec, 0xda, 0xea, 0x04, 0xe9, 0xdf, 0xe2, 0xf9, 0xdc, + 0xd5, 0xd2, 0xeb, 0xca, 0x7d, 0xc1, 0x22, 0xca, 0xbb, 0xdc, 0xa8, 0xdb, + 0xe7, 0xd2, 0xe8, 0xcd, 0x7e, 0xd5, 0x4d, 0xe2, 0xf3, 0xdb, 0xff, 0xcc, + 0xf4, 0xd2, 0xcc, 0xdd, 0x90, 0xe6, 0x5a, 0xf1, 0x55, 0xe7, 0xe9, 0xd1, + 0x46, 0xc1, 0xd9, 0xb6, 0x21, 0xc4, 0xfa, 0xd3, 0x7c, 0xcc, 0x60, 0xc4, + 0x20, 0xbf, 0x97, 0xba, 0x7e, 0xca, 0xad, 0xe5, 0xd1, 0xe9, 0x44, 0xed, + 0xc7, 0xf8, 0xeb, 0xf5, 0x0f, 0x02, 0x9d, 0x03, 0xfe, 0xec, 0x02, 0xeb, + 0x7a, 0xeb, 0xa8, 0xe1, 0x57, 0xf0, 0x8a, 0x01, 0x6e, 0xf4, 0xe1, 0xfe, + 0x44, 0x17, 0xdc, 0x12, 0x4c, 0x0c, 0xb4, 0xfe, 0xf3, 0x03, 0x9d, 0x23, + 0x66, 0x23, 0xb1, 0x21, 0xb9, 0x30, 0x79, 0x32, 0x7e, 0x3e, 0x24, 0x4a, + 0xc1, 0x48, 0x82, 0x4b, 0x1a, 0x4b, 0xcc, 0x4e, 0x7c, 0x5d, 0x62, 0x5f, + 0x24, 0x49, 0xb5, 0x2a, 0x44, 0x0f, 0xa5, 0xfe, 0x36, 0xe9, 0x9d, 0xd0, + 0x97, 0xdd, 0x20, 0xfe, 0x24, 0xfe, 0xd9, 0xdb, 0x7b, 0xc6, 0xc9, 0xcf, + 0x29, 0xdb, 0x01, 0xde, 0xbc, 0xee, 0x9e, 0x05, 0x3d, 0xf9, 0x50, 0xea, + 0x33, 0xf3, 0xcc, 0xed, 0xf8, 0xeb, 0x07, 0x04, 0xca, 0x09, 0xc1, 0xfe, + 0x2a, 0x04, 0x22, 0x13, 0x37, 0x1e, 0xee, 0x0c, 0xad, 0xfa, 0x48, 0xfc, + 0xe2, 0xfd, 0xad, 0x08, 0xe5, 0x14, 0xc5, 0x22, 0x6a, 0x2b, 0x2b, 0x28, + 0xf8, 0x2a, 0x78, 0x31, 0xa7, 0x2d, 0x4e, 0x26, 0x09, 0x2c, 0x8f, 0x2f, + 0x21, 0x29, 0xea, 0x23, 0x86, 0x2a, 0x4b, 0x3e, 0xc5, 0x50, 0x38, 0x57, + 0x7e, 0x56, 0x90, 0x5e, 0x7e, 0x68, 0xa5, 0x6a, 0x40, 0x6e, 0x06, 0x6b, + 0x41, 0x5b, 0x32, 0x4b, 0x5c, 0x44, 0xce, 0x44, 0x9b, 0x36, 0xa9, 0x24, + 0x50, 0x1e, 0x0b, 0x0e, 0x5b, 0xfa, 0x31, 0xf6, 0x5e, 0x00, 0x37, 0x0b, + 0x9d, 0x06, 0xf7, 0xf5, 0xc5, 0xf5, 0x49, 0x01, 0x86, 0x07, 0xb0, 0x08, + 0xc0, 0xfb, 0x76, 0xf2, 0x94, 0xec, 0xe2, 0xe6, 0x30, 0xe7, 0x19, 0xdd, + 0x78, 0xd9, 0xc9, 0xde, 0x7f, 0xe4, 0x33, 0xeb, 0x47, 0xe2, 0xae, 0xd7, + 0xc3, 0xd3, 0x3b, 0xd2, 0xe0, 0xcd, 0xe4, 0xc7, 0x0e, 0xcf, 0x62, 0xc7, + 0x19, 0xc0, 0x19, 0xc7, 0x46, 0xc7, 0x90, 0xc7, 0x1f, 0xbf, 0x0e, 0xc6, + 0xd4, 0xdb, 0x72, 0xe6, 0xa6, 0xe3, 0x82, 0xe1, 0x9f, 0xe9, 0x16, 0xf0, + 0x62, 0xf6, 0xce, 0xeb, 0x65, 0xde, 0xde, 0xe2, 0xf8, 0xf8, 0x4b, 0x0b, + 0x01, 0x04, 0x1d, 0xfd, 0x74, 0xf7, 0xfb, 0xf4, 0xa5, 0x01, 0x82, 0x0b, + 0x8e, 0x09, 0x52, 0x1b, 0x16, 0x2e, 0x0d, 0x1d, 0x2d, 0x0f, 0xbd, 0x0e, + 0x4b, 0x0e, 0xfd, 0x12, 0x0f, 0x15, 0xf4, 0x0f, 0xa6, 0x11, 0x5a, 0x13, + 0xda, 0x15, 0x8d, 0x1f, 0x6e, 0x1a, 0x10, 0x14, 0xf1, 0x15, 0x1d, 0x12, + 0x2c, 0x14, 0xfc, 0x0e, 0x27, 0xff, 0xbc, 0x07, 0x31, 0x03, 0xc9, 0xea, + 0xa4, 0xe8, 0xe3, 0xe2, 0x74, 0xd9, 0xea, 0xdf, 0xf8, 0xe9, 0xe2, 0xec, + 0xb6, 0xf4, 0xa3, 0xfa, 0x64, 0xfb, 0xd2, 0x00, 0x2c, 0x05, 0xde, 0x0c, + 0x69, 0x09, 0x8e, 0xf7, 0x9e, 0xe3, 0xa5, 0xcd, 0x71, 0xbd, 0x7d, 0xc2, + 0x88, 0xce, 0xe9, 0xd1, 0x31, 0xc9, 0xd6, 0xbc, 0x65, 0xcc, 0x14, 0xd4, + 0xb8, 0xc9, 0x80, 0xdb, 0xea, 0xf7, 0xa6, 0xf7, 0x9a, 0xef, 0x3f, 0xfa, + 0x7f, 0xf9, 0xbd, 0xf0, 0x3c, 0x06, 0x4e, 0x23, 0xea, 0x1d, 0xd3, 0x14, + 0x53, 0x19, 0x6e, 0x16, 0xe6, 0x11, 0xfd, 0x19, 0x05, 0x2a, 0xcb, 0x2c, + 0x77, 0x34, 0xc2, 0x3c, 0x17, 0x36, 0x9d, 0x2d, 0x33, 0x29, 0x07, 0x34, + 0x07, 0x44, 0xb9, 0x4c, 0xac, 0x46, 0x02, 0x37, 0xc1, 0x30, 0x70, 0x32, + 0x98, 0x37, 0xb8, 0x36, 0xa6, 0x2e, 0x44, 0x31, 0x5a, 0x3b, 0xca, 0x3f, + 0xeb, 0x3e, 0xd5, 0x3f, 0x57, 0x38, 0x26, 0x25, 0x29, 0x26, 0xa2, 0x34, + 0x24, 0x34, 0x61, 0x22, 0x37, 0x12, 0x17, 0x05, 0xf4, 0xf4, 0x30, 0xf2, + 0x6a, 0xee, 0xee, 0xe5, 0x6a, 0xdc, 0x84, 0xd4, 0x7a, 0xce, 0x8b, 0xc2, + 0xa8, 0xca, 0x3b, 0xd5, 0x81, 0xce, 0xb1, 0xd0, 0xf3, 0xd7, 0x4b, 0xde, + 0x09, 0xdd, 0xf8, 0xd2, 0xe9, 0xda, 0xed, 0xe6, 0xa9, 0xe0, 0x6b, 0xd7, + 0x7a, 0xd2, 0x1c, 0xcc, 0x24, 0xd7, 0x48, 0xee, 0x87, 0xeb, 0x2d, 0xe5, + 0x02, 0xe5, 0xbc, 0xe8, 0xb8, 0xf6, 0xd7, 0xf5, 0xc0, 0xf3, 0xca, 0xfb, + 0xe7, 0xfe, 0xe2, 0x05, 0x10, 0x17, 0xe4, 0x1c, 0xc2, 0x1f, 0x34, 0x26, + 0x78, 0x21, 0x73, 0x1d, 0xea, 0x1a, 0x19, 0x12, 0xc9, 0x04, 0xe8, 0x0b, + 0x7d, 0x21, 0xb6, 0x2b, 0xeb, 0x29, 0x95, 0x28, 0x30, 0x2e, 0x6c, 0x27, + 0xf6, 0x2a, 0xf4, 0x34, 0x5c, 0x31, 0x4e, 0x29, 0x85, 0x12, 0xf6, 0x01, + 0x1b, 0x00, 0x49, 0xfd, 0x1a, 0xfc, 0x8a, 0xf2, 0x06, 0xe3, 0x5c, 0xe2, + 0xa5, 0xe1, 0xe0, 0xdb, 0xa8, 0xd8, 0x6f, 0xd5, 0x41, 0xd4, 0xab, 0xd8, + 0xf0, 0xe2, 0x45, 0xe2, 0xf0, 0xe3, 0xd4, 0xe7, 0xde, 0xe8, 0x15, 0xeb, + 0xd8, 0xe9, 0xdb, 0xf0, 0x24, 0xee, 0x49, 0xe5, 0x60, 0xe2, 0xe2, 0xeb, + 0xcb, 0xfb, 0x62, 0xfd, 0x3e, 0xf6, 0x02, 0xed, 0xd9, 0xee, 0xaf, 0xf6, + 0xdd, 0x02, 0x8d, 0x18, 0x27, 0x34, 0x6d, 0x3f, 0xcc, 0x35, 0x9c, 0x28, + 0x0c, 0x0d, 0xb0, 0xfd, 0x4a, 0xfc, 0xf1, 0xf7, 0x50, 0xf0, 0x14, 0xe3, + 0xa1, 0xe0, 0x23, 0xe0, 0xf0, 0xde, 0x2b, 0xe6, 0xc3, 0xfb, 0x04, 0x11, + 0x8e, 0x1c, 0x05, 0x32, 0x92, 0x3a, 0xd1, 0x2b, 0x88, 0x28, 0x09, 0x2d, + 0x78, 0x2c, 0x5f, 0x2e, 0xfb, 0x2c, 0xa9, 0x28, 0x35, 0x1f, 0x4e, 0x17, + 0x09, 0x0f, 0xca, 0x05, 0x38, 0x0c, 0x7c, 0x12, 0x61, 0x14, 0xe2, 0x0f, + 0xbf, 0x0c, 0x4f, 0x0b, 0x4e, 0x05, 0x16, 0x09, 0xb6, 0x01, 0x71, 0xf3, + 0xd2, 0xeb, 0xaf, 0xeb, 0xcf, 0xf4, 0x8c, 0xf7, 0x1c, 0xef, 0x4b, 0xe2, + 0x20, 0xe6, 0x7a, 0xf7, 0x37, 0x03, 0x9c, 0x06, 0xca, 0xfe, 0x84, 0xf7, + 0x7c, 0x01, 0x58, 0x10, 0x5b, 0x1a, 0x99, 0x18, 0xc6, 0x07, 0xab, 0xf8, + 0xda, 0xec, 0xaa, 0xee, 0x0a, 0xf6, 0xa3, 0xee, 0xba, 0xe3, 0xa9, 0xdb, + 0x55, 0xd3, 0x61, 0xcb, 0x31, 0xcc, 0xc4, 0xd7, 0xd6, 0xe7, 0xec, 0xec, + 0x2c, 0xe9, 0x43, 0xee, 0x36, 0xf8, 0xd8, 0x08, 0x46, 0x17, 0xab, 0x15, + 0x1b, 0x0a, 0x1b, 0x01, 0x26, 0x0f, 0x42, 0x1d, 0x8b, 0x1e, 0xf5, 0x21, + 0x31, 0x16, 0x35, 0x0e, 0xba, 0x14, 0x7b, 0x1d, 0x86, 0x1e, 0x8a, 0x16, + 0xf4, 0x12, 0xca, 0x14, 0x30, 0x1f, 0x1d, 0x23, 0x80, 0x35, 0xf4, 0x3b, + 0x7e, 0x1f, 0x31, 0x0f, 0xfc, 0xf8, 0x44, 0xee, 0xb9, 0xf3, 0xda, 0xe7, + 0x42, 0xdd, 0x52, 0xdc, 0xd0, 0xd5, 0x52, 0xda, 0x28, 0xea, 0x0c, 0xeb, + 0xe5, 0xec, 0x64, 0xf1, 0xe3, 0xfd, 0x59, 0x06, 0xfc, 0xf9, 0xf7, 0xef, + 0xbc, 0xf1, 0x5a, 0xec, 0xcf, 0xda, 0xb2, 0xdb, 0x24, 0xdd, 0x54, 0xe0, + 0xd2, 0xe2, 0x83, 0xd9, 0xb4, 0xdd, 0xda, 0xdc, 0xd6, 0xe0, 0x9a, 0xea, + 0x23, 0xe6, 0xa5, 0xe5, 0xfe, 0xe5, 0x91, 0xda, 0xd0, 0xdd, 0x73, 0xef, + 0xab, 0xf9, 0xff, 0x02, 0x9a, 0x02, 0x99, 0xfe, 0x61, 0x03, 0x7f, 0x11, + 0x90, 0x1f, 0x94, 0x28, 0x5f, 0x2c, 0xd3, 0x2c, 0x36, 0x37, 0x33, 0x3a, + 0x2f, 0x40, 0x56, 0x47, 0xc1, 0x3f, 0x50, 0x42, 0x55, 0x4e, 0x15, 0x5a, + 0xe9, 0x5b, 0xa3, 0x59, 0xbf, 0x5f, 0x13, 0x5a, 0xda, 0x42, 0xd4, 0x36, + 0x1d, 0x31, 0xe9, 0x22, 0x8a, 0x1e, 0x5a, 0x18, 0x37, 0x06, 0xeb, 0xf7, + 0x1b, 0xef, 0xe7, 0xe9, 0x0e, 0xed, 0xaa, 0xf5, 0x74, 0xf9, 0x11, 0x02, + 0x43, 0x10, 0xa5, 0x0a, 0x4f, 0xfd, 0xd4, 0x07, 0x5d, 0x10, 0xfb, 0xfd, + 0x4f, 0xf4, 0xb9, 0xf6, 0x39, 0xe6, 0x7b, 0xda, 0xb0, 0xe7, 0x14, 0xf0, + 0x5c, 0xe2, 0xa4, 0xdb, 0xec, 0xe3, 0x7c, 0xda, 0x81, 0xd5, 0xe3, 0xe4, + 0xbc, 0xe5, 0xbf, 0xdb, 0x75, 0xd4, 0x9f, 0xcd, 0x2f, 0xd3, 0xb2, 0xdf, + 0x5f, 0xd9, 0xb8, 0xd2, 0x3d, 0xe2, 0xff, 0xea, 0xbf, 0xe6, 0x00, 0xe5, + 0x49, 0xeb, 0xe0, 0xfb, 0xbb, 0x07, 0x89, 0x0d, 0xc6, 0x16, 0x40, 0x21, + 0x8e, 0x21, 0xf2, 0x17, 0x0b, 0x17, 0xd0, 0x1a, 0x82, 0x16, 0x54, 0x14, + 0x33, 0x1c, 0x46, 0x18, 0x6a, 0x0f, 0x2f, 0x10, 0x88, 0x0d, 0xa8, 0x0e, + 0x43, 0x08, 0x88, 0xff, 0x4b, 0x01, 0x83, 0xff, 0xa5, 0x07, 0x16, 0x19, + 0x22, 0x1e, 0x37, 0x19, 0x42, 0x1b, 0x3d, 0x23, 0x4f, 0x28, 0x04, 0x29, + 0x80, 0x27, 0xf1, 0x1b, 0x01, 0x07, 0x53, 0x06, 0x95, 0x0a, 0x39, 0xfd, + 0xe2, 0xf2, 0xec, 0xf5, 0x31, 0xfb, 0xa6, 0xf7, 0xf7, 0xf1, 0x58, 0xe6, + 0x2f, 0xd8, 0x1b, 0xcb, 0xd3, 0xc2, 0x9c, 0xc1, 0x49, 0xb5, 0x11, 0xb1, + 0x3f, 0xb8, 0x2b, 0xb5, 0x79, 0xb4, 0x29, 0xc3, 0xc7, 0xc1, 0x08, 0xc0, + 0xd6, 0xd1, 0xf0, 0xc8, 0x91, 0xce, 0x78, 0xdf, 0x05, 0xe5, 0x93, 0xf7, + 0x52, 0xf3, 0x18, 0xee, 0x51, 0xec, 0x61, 0xe2, 0x71, 0xf0, 0x68, 0x04, + 0x79, 0x07, 0xae, 0x03, 0xdf, 0x03, 0x68, 0x04, 0xab, 0x03, 0xf4, 0x12, + 0x78, 0x16, 0xef, 0x18, 0x59, 0x33, 0xfb, 0x2f, 0xd8, 0x30, 0x3f, 0x34, + 0x79, 0x2f, 0xb2, 0x39, 0xa5, 0x39, 0x1e, 0x48, 0x2d, 0x4d, 0x7e, 0x50, + 0x34, 0x5a, 0xdd, 0x58, 0xc9, 0x57, 0x06, 0x4c, 0x68, 0x4b, 0xd2, 0x48, + 0xe1, 0x4b, 0xbe, 0x5b, 0xbb, 0x56, 0xc0, 0x4b, 0x96, 0x41, 0xb9, 0x34, + 0x03, 0x36, 0x4f, 0x35, 0xbb, 0x2b, 0xfe, 0x2d, 0xfb, 0x30, 0x06, 0x2f, + 0x9a, 0x2e, 0xd4, 0x30, 0x39, 0x22, 0x07, 0x08, 0xce, 0x01, 0x53, 0x04, + 0xb0, 0xf5, 0xec, 0xd9, 0xb3, 0xcd, 0xe3, 0xc7, 0x2f, 0xc2, 0xb3, 0xc4, + 0xc0, 0xc1, 0x1f, 0xc1, 0x78, 0xca, 0x44, 0xcc, 0x42, 0xcd, 0x38, 0xdd, + 0xff, 0xde, 0x18, 0xd6, 0xb1, 0xdf, 0xdb, 0xe2, 0xd7, 0xd1, 0xc8, 0xd3, + 0x05, 0xe5, 0x9e, 0xdb, 0xfd, 0xd1, 0xfe, 0xe0, 0x42, 0xec, 0xc7, 0xe5, + 0xa7, 0xe0, 0xc1, 0xe9, 0xa6, 0xf5, 0x1f, 0xfc, 0x40, 0xfa, 0x6d, 0xfb, + 0xb6, 0x06, 0x30, 0x0f, 0x2f, 0x0e, 0x76, 0x0a, 0x24, 0x0f, 0xcc, 0x15, + 0xc8, 0x24, 0x54, 0x31, 0x21, 0x28, 0x84, 0x19, 0x7d, 0x0c, 0xd1, 0x0f, + 0x14, 0x24, 0xe5, 0x38, 0xec, 0x39, 0x67, 0x2d, 0x02, 0x34, 0xa7, 0x39, + 0x33, 0x40, 0x92, 0x4c, 0xfb, 0x47, 0x06, 0x41, 0xdd, 0x3a, 0x9e, 0x2d, + 0x51, 0x1b, 0x25, 0x0d, 0x1e, 0x10, 0x89, 0x13, 0x3c, 0x06, 0xeb, 0xf1, + 0x88, 0xf0, 0xaf, 0xfa, 0x0d, 0xf2, 0x2a, 0xed, 0xb2, 0xeb, 0x30, 0xe6, + 0x8f, 0xea, 0xe0, 0xef, 0xb2, 0xfa, 0x33, 0xfa, 0xe9, 0xec, 0x65, 0xe7, + 0x52, 0xe9, 0x7e, 0xe8, 0x1c, 0xe7, 0xfa, 0xe2, 0x62, 0xd0, 0xc4, 0xc8, + 0x41, 0xc2, 0x28, 0xb8, 0xde, 0xb5, 0x4f, 0xae, 0x13, 0xb3, 0xe5, 0xbc, + 0xf4, 0xb9, 0x22, 0xb5, 0xd4, 0xaf, 0x9a, 0xac, 0x5a, 0xbd, 0xb3, 0xca, + 0x4f, 0xc4, 0x5e, 0xcc, 0x2e, 0xd9, 0xd3, 0xdd, 0xca, 0xe9, 0x62, 0xf0, + 0x34, 0xec, 0xee, 0xf2, 0xe1, 0xfe, 0xe4, 0x0a, 0x24, 0x21, 0xb3, 0x2d, + 0x76, 0x2f, 0x20, 0x34, 0x09, 0x2d, 0xf5, 0x28, 0x75, 0x31, 0xac, 0x32, + 0xea, 0x39, 0xc2, 0x3b, 0x5d, 0x32, 0x10, 0x32, 0x26, 0x3c, 0x37, 0x4d, + 0x41, 0x51, 0x03, 0x4a, 0xa6, 0x3e, 0x2b, 0x39, 0x89, 0x3b, 0xd1, 0x3b, + 0xb5, 0x3a, 0xe9, 0x38, 0x4a, 0x3f, 0xe0, 0x3d, 0xc6, 0x36, 0x44, 0x37, + 0x42, 0x3a, 0xc1, 0x36, 0x59, 0x35, 0x93, 0x38, 0x4a, 0x2c, 0x9f, 0x23, + 0x9b, 0x1d, 0x9c, 0x16, 0x99, 0x0f, 0x61, 0x06, 0x8a, 0x03, 0x0c, 0xfe, + 0x63, 0xfe, 0xed, 0x02, 0x53, 0x08, 0x2a, 0x05, 0xfa, 0x00, 0xd1, 0x02, + 0xc9, 0xfb, 0xe6, 0xf4, 0xf6, 0xe6, 0x17, 0xda, 0xbd, 0xd1, 0x0c, 0xc7, + 0xae, 0xbe, 0x2e, 0xbb, 0xe2, 0xbe, 0x0b, 0xb9, 0x75, 0xb6, 0x5c, 0xc3, + 0xa9, 0xc8, 0x92, 0xc6, 0x6f, 0xd9, 0x83, 0xf7, 0x1a, 0xf4, 0x62, 0xe1, + 0xb0, 0xe7, 0xe5, 0xf3, 0x21, 0xf5, 0xc5, 0xfe, 0x48, 0x0f, 0x23, 0x0f, + 0xbd, 0x0b, 0xd1, 0x15, 0x14, 0x16, 0x85, 0x0f, 0x0a, 0x17, 0x5f, 0x1f, + 0xc4, 0x1b, 0x02, 0x1d, 0x2a, 0x30, 0xa5, 0x3d, 0x0a, 0x3c, 0xa6, 0x3a, + 0x9f, 0x3d, 0x96, 0x3d, 0xf9, 0x30, 0x77, 0x26, 0x90, 0x2a, 0x41, 0x28, + 0x39, 0x19, 0x98, 0x0d, 0x36, 0x05, 0x82, 0x05, 0x2a, 0x11, 0xf7, 0x16, + 0xbc, 0x16, 0xf8, 0x16, 0x2f, 0x17, 0xcc, 0x15, 0x18, 0x10, 0xf5, 0x11, + 0x3e, 0x18, 0x0e, 0x0d, 0x04, 0xfe, 0xc6, 0xf8, 0x1f, 0xed, 0x09, 0xdd, + 0xc6, 0xd5, 0x30, 0xd0, 0x49, 0xcb, 0x15, 0xcc, 0x7c, 0xcd, 0x56, 0xd1, + 0xd4, 0xd1, 0x47, 0xd0, 0xe9, 0xd3, 0xe2, 0xd7, 0xd9, 0xda, 0xa4, 0xd6, + 0xb2, 0xd3, 0x8c, 0xda, 0xce, 0xda, 0x7f, 0xd3, 0x5f, 0xd3, 0x7b, 0xd3, + 0xf9, 0xcd, 0x29, 0xca, 0xb1, 0xc2, 0x3e, 0xbc, 0xd2, 0xc3, 0x8b, 0xcc, + 0x14, 0xce, 0x42, 0xd5, 0x05, 0xdd, 0x58, 0xe3, 0x1e, 0xec, 0x76, 0xf3, + 0x3a, 0x03, 0x03, 0x14, 0x01, 0x1a, 0xdf, 0x24, 0x47, 0x2c, 0x80, 0x24, + 0x31, 0x22, 0xec, 0x23, 0x55, 0x20, 0xbc, 0x23, 0xb7, 0x33, 0x0f, 0x34, + 0xd2, 0x27, 0x3d, 0x2d, 0x46, 0x2f, 0x12, 0x3b, 0x2d, 0x46, 0xb0, 0x3a, + 0x8e, 0x3f, 0xe5, 0x41, 0x83, 0x3f, 0xdf, 0x3f, 0x0b, 0x32, 0x48, 0x29, + 0x10, 0x2c, 0x94, 0x2d, 0x30, 0x27, 0x8d, 0x22, 0x75, 0x1a, 0xd4, 0x13, + 0xf1, 0x12, 0x9a, 0x16, 0x91, 0x22, 0x00, 0x23, 0x5b, 0x1f, 0x55, 0x1a, + 0x79, 0x13, 0xaa, 0x0f, 0x51, 0x0b, 0xe5, 0x0b, 0x3b, 0x0f, 0xb2, 0x0b, + 0xcb, 0xff, 0x7d, 0xfc, 0x8f, 0xfa, 0x34, 0xf8, 0x28, 0xf5, 0x7a, 0xee, + 0x78, 0xf0, 0xe9, 0xf5, 0xbb, 0xf8, 0xd5, 0xf9, 0x72, 0x02, 0xea, 0x06, + 0xaf, 0x07, 0xa7, 0x13, 0x5a, 0x22, 0x88, 0x26, 0xe9, 0x1b, 0x52, 0x0d, + 0x8f, 0xf9, 0x39, 0xe1, 0xbf, 0xd7, 0xee, 0xdd, 0xfe, 0xd8, 0xaa, 0xd2, + 0x89, 0xd2, 0x83, 0xd0, 0x2a, 0xd8, 0xf7, 0xdf, 0xa8, 0xe6, 0x43, 0xf7, + 0x17, 0x0e, 0x58, 0x16, 0xef, 0x14, 0x63, 0x19, 0x59, 0x19, 0xc8, 0x15, + 0x7c, 0x1d, 0x77, 0x2c, 0x00, 0x25, 0x31, 0x14, 0xe9, 0x13, 0x18, 0x13, + 0x16, 0x0a, 0xee, 0x0a, 0x22, 0x14, 0x4e, 0x0c, 0x4f, 0x05, 0x22, 0x08, + 0x8e, 0x01, 0xaf, 0xfa, 0x0e, 0xf3, 0x5c, 0xf0, 0x26, 0xef, 0x5e, 0xe7, + 0xde, 0xdc, 0x0a, 0xd5, 0xc1, 0xde, 0x88, 0xe1, 0x1c, 0xe2, 0x4d, 0xe2, + 0xe7, 0xdb, 0x6c, 0xe3, 0xb1, 0xed, 0xdb, 0xf6, 0xe2, 0xf9, 0x51, 0x03, + 0xee, 0x04, 0x11, 0x02, 0x6d, 0x0b, 0x87, 0x14, 0x49, 0x1d, 0x19, 0x12, + 0x77, 0x0e, 0x7a, 0xff, 0xf7, 0xe0, 0xed, 0xdf, 0xe1, 0xe1, 0x72, 0xe0, + 0xf5, 0xe2, 0xd3, 0xe3, 0xaa, 0xde, 0x04, 0xde, 0x97, 0xe0, 0xc5, 0xe4, + 0x83, 0xf2, 0xec, 0xfc, 0x6f, 0xf8, 0x86, 0xed, 0xcb, 0xec, 0x10, 0xe5, + 0xe6, 0xe1, 0x3c, 0xee, 0xbe, 0xf4, 0x4d, 0xf8, 0x54, 0xef, 0xa6, 0xe1, + 0x3b, 0xe7, 0x9f, 0xf5, 0xc7, 0xff, 0xd7, 0x0e, 0x64, 0x1a, 0xf6, 0x16, + 0x42, 0x17, 0x8d, 0x0f, 0x41, 0x06, 0xaf, 0x0a, 0x6a, 0x03, 0x7e, 0x00, + 0x22, 0x03, 0xc4, 0xfe, 0x98, 0x01, 0xc7, 0x01, 0x57, 0xfc, 0xf1, 0xfb, + 0x45, 0x02, 0x4e, 0x08, 0x71, 0x0f, 0x76, 0x0f, 0xda, 0x07, 0xe3, 0x16, + 0xbc, 0x2a, 0x4e, 0x2e, 0x42, 0x2b, 0x63, 0x22, 0xad, 0x25, 0xa7, 0x25, + 0x05, 0x19, 0xba, 0x0f, 0x9c, 0x08, 0x4d, 0x0a, 0xcc, 0x0a, 0x3b, 0x0e, + 0xb0, 0x0c, 0x6f, 0x03, 0xe4, 0x02, 0xe8, 0xff, 0xd9, 0x01, 0x0a, 0x07, + 0xce, 0x0d, 0x19, 0x11, 0x66, 0x05, 0x2d, 0xfc, 0x2c, 0xf9, 0x7c, 0xf9, + 0x63, 0x02, 0xc6, 0x03, 0x53, 0x01, 0x92, 0x0a, 0xed, 0x0a, 0x89, 0x05, + 0x79, 0x08, 0xb2, 0x0d, 0xbc, 0x0e, 0xae, 0x10, 0x89, 0x18, 0xf0, 0x1e, + 0x42, 0x25, 0x53, 0x2a, 0x98, 0x2b, 0xeb, 0x2c, 0x63, 0x35, 0x7c, 0x37, + 0xd8, 0x32, 0x82, 0x26, 0x19, 0x09, 0xef, 0xf9, 0x8b, 0xf6, 0xf8, 0xeb, + 0xa5, 0xe1, 0xd6, 0xe1, 0x67, 0xe6, 0xfd, 0xdb, 0xdb, 0xca, 0x63, 0xd1, + 0x7b, 0xe5, 0x38, 0xe6, 0x75, 0xee, 0x13, 0x04, 0xae, 0xfb, 0xf8, 0xe5, + 0xf8, 0xeb, 0xab, 0xef, 0x7d, 0xe1, 0x59, 0xe9, 0x3c, 0xfa, 0x8e, 0xf2, + 0xcb, 0xe4, 0xa1, 0xee, 0x60, 0xf1, 0x39, 0xe4, 0xde, 0xe6, 0xbe, 0xe4, + 0xe3, 0xdb, 0x34, 0xdb, 0x1d, 0xdc, 0x3c, 0xdd, 0xd7, 0xdc, 0x96, 0xde, + 0x2e, 0xe6, 0x41, 0xf0, 0xd4, 0xef, 0xb5, 0xe5, 0x47, 0xe6, 0x59, 0xe6, + 0x61, 0xe3, 0x2f, 0xf0, 0xef, 0xf4, 0xb0, 0xf4, 0x89, 0x05, 0x99, 0x14, + 0x69, 0x1d, 0xcb, 0x2d, 0x60, 0x3a, 0x03, 0x3d, 0xd3, 0x3c, 0xc2, 0x3f, + 0xcf, 0x48, 0x93, 0x3f, 0xfe, 0x34, 0x63, 0x36, 0x87, 0x2a, 0x09, 0x1f, + 0x5c, 0x18, 0x91, 0x0d, 0x27, 0x02, 0xf2, 0xfb, 0xe5, 0xfa, 0x31, 0xfc, + 0xf9, 0xf5, 0x60, 0xec, 0xc2, 0xea, 0xe1, 0xe6, 0x4a, 0xe4, 0x4b, 0xeb, + 0x48, 0xf6, 0xc4, 0xf4, 0x15, 0xf0, 0x11, 0xf5, 0x50, 0xf6, 0xbd, 0xf5, + 0x65, 0xfb, 0xbf, 0x01, 0xa6, 0x04, 0xa9, 0x00, 0xf5, 0xff, 0xc0, 0x06, + 0x76, 0xfb, 0x20, 0xef, 0x43, 0xe6, 0x70, 0xe0, 0xc1, 0xe4, 0xd1, 0xde, + 0x92, 0xdd, 0x25, 0xe0, 0xed, 0xe2, 0xe7, 0xe4, 0x0e, 0xe3, 0x3a, 0xe0, + 0x23, 0xec, 0x65, 0xf8, 0x88, 0xf1, 0x66, 0x00, 0x24, 0x07, 0xd4, 0x01, + 0xdf, 0x0d, 0xd6, 0x1e, 0x59, 0x2e, 0x58, 0x32, 0xd0, 0x38, 0x93, 0x3c, + 0xb3, 0x3a, 0xaa, 0x39, 0x77, 0x3c, 0xef, 0x43, 0x31, 0x46, 0x26, 0x40, + 0x9c, 0x39, 0x23, 0x39, 0x29, 0x33, 0x70, 0x2c, 0x62, 0x27, 0xf1, 0x1f, + 0x49, 0x15, 0x8a, 0x0d, 0x03, 0x12, 0x81, 0x12, 0xd6, 0x0e, 0xe9, 0x12, + 0x10, 0x19, 0xad, 0x1e, 0x47, 0x21, 0x44, 0x1e, 0xa7, 0x1f, 0x6a, 0x22, + 0xb9, 0x20, 0x21, 0x1d, 0x9f, 0x17, 0x2c, 0x1c, 0xf2, 0x26, 0x2a, 0x28, + 0x88, 0x27, 0x5a, 0x24, 0xd5, 0x1a, 0x51, 0x16, 0x55, 0x15, 0xb8, 0x15, + 0x20, 0x16, 0x37, 0x10, 0x67, 0x02, 0xdf, 0xe8, 0x7b, 0xca, 0x71, 0xb8, + 0xc3, 0xb2, 0x88, 0xb6, 0xcb, 0xbd, 0xa5, 0xb9, 0x93, 0xb1, 0xb4, 0xa7, + 0x8d, 0xa5, 0x40, 0xb4, 0x53, 0xc0, 0x58, 0xc9, 0x9f, 0xd7, 0xaf, 0xdf, + 0xfe, 0xd0, 0xde, 0xc9, 0x40, 0xda, 0xf4, 0xda, 0x03, 0xd7, 0x1d, 0xe7, + 0x12, 0xf0, 0x21, 0xe9, 0xc7, 0xe9, 0x58, 0xec, 0xb8, 0xe5, 0x00, 0xdd, + 0x7d, 0xde, 0x38, 0xe1, 0xaf, 0xd9, 0x69, 0xe4, 0xf1, 0xf5, 0xdb, 0xfe, + 0x72, 0x04, 0x50, 0x03, 0xdd, 0x0a, 0x7c, 0x15, 0x74, 0x1d, 0xc6, 0x23, + 0x80, 0x2c, 0xdd, 0x2e, 0xcb, 0x2b, 0xd7, 0x32, 0x6b, 0x31, 0x10, 0x2c, + 0x79, 0x2f, 0xb6, 0x36, 0x1e, 0x38, 0xc6, 0x46, 0x4c, 0x51, 0xa3, 0x3c, + 0xf5, 0x3b, 0xb0, 0x41, 0x9a, 0x3d, 0x08, 0x3b, 0xef, 0x30, 0x46, 0x25, + 0x5c, 0x17, 0x87, 0x0e, 0x0e, 0x05, 0xbc, 0xf4, 0xbe, 0xdb, 0xbc, 0xcd, + 0x3f, 0xc9, 0xe3, 0xbe, 0x48, 0xc5, 0x54, 0xce, 0xd9, 0xd7, 0xbf, 0xe4, + 0xfb, 0xe0, 0x22, 0xde, 0xca, 0xe6, 0x28, 0xea, 0xe4, 0xf4, 0x94, 0x03, + 0x81, 0xf9, 0xf7, 0xe9, 0x87, 0xe4, 0x47, 0xe6, 0xa1, 0xe6, 0xe1, 0xdf, + 0x00, 0xdc, 0x19, 0xd8, 0x93, 0xd5, 0x54, 0xd8, 0x76, 0xde, 0x6b, 0xdd, + 0xee, 0xde, 0x37, 0xe7, 0x03, 0xeb, 0xa9, 0xf5, 0x7a, 0xfc, 0x33, 0xfc, + 0x05, 0x03, 0x32, 0x0d, 0xe8, 0x10, 0x90, 0x15, 0x2e, 0x1e, 0xa7, 0x23, + 0xc2, 0x2a, 0xe1, 0x2f, 0x61, 0x3c, 0x7e, 0x48, 0x93, 0x4e, 0xb7, 0x51, + 0xc4, 0x4f, 0x9f, 0x57, 0x3d, 0x5d, 0xf7, 0x62, 0x2b, 0x65, 0x05, 0x5e, + 0x3e, 0x58, 0x40, 0x50, 0x14, 0x46, 0x85, 0x37, 0xfe, 0x31, 0xc9, 0x31, + 0xdc, 0x2e, 0x4b, 0x2a, 0xa9, 0x24, 0xc7, 0x21, 0xba, 0x1f, 0x15, 0x27, + 0xa1, 0x29, 0xf8, 0x25, 0x35, 0x2d, 0x3f, 0x33, 0x70, 0x2c, 0xa5, 0x1e, + 0xa8, 0x17, 0x4d, 0x13, 0x5f, 0x08, 0x6b, 0xfd, 0x04, 0xf0, 0x7d, 0xe1, + 0x03, 0xdf, 0x9f, 0xe1, 0x04, 0xdd, 0x17, 0xe0, 0x2e, 0xe7, 0xc7, 0xe1, + 0xc7, 0xde, 0xf5, 0xdd, 0x72, 0xdc, 0x75, 0xd1, 0xbd, 0xb9, 0x38, 0xb0, + 0x0f, 0xab, 0xde, 0xa1, 0x02, 0xa3, 0x09, 0xa7, 0x81, 0xa4, 0xf6, 0xa0, + 0x1e, 0xa2, 0x3c, 0xb4, 0x3e, 0xc5, 0x6d, 0xc9, 0xd6, 0xe2, 0x19, 0xf1, + 0x8d, 0xe0, 0x04, 0xdd, 0x05, 0xeb, 0xa7, 0xee, 0xdc, 0xe9, 0x2c, 0xf4, + 0x1d, 0xf9, 0x01, 0xec, 0x86, 0xe7, 0xe8, 0xfb, 0x0b, 0x0d, 0xf8, 0x09, + 0x05, 0x12, 0x14, 0x21, 0x3d, 0x20, 0x5e, 0x22, 0x62, 0x31, 0x28, 0x3a, + 0x0c, 0x3d, 0xe0, 0x3f, 0x29, 0x3b, 0x74, 0x37, 0x14, 0x38, 0xb6, 0x38, + 0xe0, 0x40, 0x45, 0x3b, 0x28, 0x34, 0x8d, 0x40, 0x42, 0x3d, 0x7e, 0x36, + 0xe8, 0x36, 0xe3, 0x2f, 0xb7, 0x24, 0x9e, 0x23, 0x22, 0x2d, 0x7d, 0x25, + 0x7a, 0x1e, 0x47, 0x23, 0x51, 0x1b, 0x74, 0x0a, 0x84, 0x05, 0xf9, 0x00, + 0x19, 0xea, 0x5d, 0xd6, 0xb7, 0xd0, 0xff, 0xc7, 0x4d, 0xbd, 0x89, 0xc0, + 0xd0, 0xc1, 0x8e, 0xc0, 0x32, 0xbf, 0x18, 0xb9, 0xb4, 0xc7, 0xea, 0xd3, + 0xa7, 0xd6, 0x76, 0xe4, 0xb4, 0xe3, 0xa9, 0xd9, 0xff, 0xdd, 0x05, 0xde, + 0x99, 0xd8, 0x77, 0xe2, 0xf9, 0xe1, 0xc2, 0xd6, 0x62, 0xd7, 0xa3, 0xda, + 0x0a, 0xe1, 0x20, 0xea, 0xab, 0xec, 0x55, 0xee, 0x6a, 0xf7, 0xd6, 0xf9, + 0x26, 0x02, 0xc6, 0x11, 0x31, 0x19, 0x95, 0x29, 0x36, 0x34, 0x0a, 0x39, + 0xd4, 0x42, 0x48, 0x46, 0xbb, 0x47, 0x78, 0x49, 0x3d, 0x4a, 0x20, 0x4c, + 0xe6, 0x4f, 0x7f, 0x54, 0x61, 0x5f, 0xc8, 0x63, 0xb0, 0x5f, 0x8f, 0x60, + 0xc8, 0x60, 0xe2, 0x61, 0xc2, 0x65, 0x67, 0x62, 0x11, 0x55, 0x03, 0x4e, + 0x28, 0x4a, 0xd5, 0x42, 0xc9, 0x3d, 0x9e, 0x36, 0x65, 0x2d, 0xa4, 0x22, + 0x2b, 0x1e, 0x32, 0x1c, 0xc1, 0x0f, 0x2c, 0x07, 0x38, 0x09, 0x02, 0x06, + 0x59, 0xfc, 0x9d, 0xf8, 0x14, 0xf7, 0x85, 0xea, 0x55, 0xde, 0xae, 0xdc, + 0x27, 0xda, 0xc3, 0xd7, 0x3d, 0xd5, 0x7d, 0xcb, 0xb6, 0xc2, 0xea, 0xc3, + 0x0a, 0xc8, 0x58, 0xc7, 0xd6, 0xc7, 0x7d, 0xd0, 0x14, 0xd7, 0x50, 0xd7, + 0xc4, 0xda, 0xbe, 0xd8, 0x02, 0xd5, 0x1e, 0xd3, 0x6c, 0xce, 0x0b, 0xc6, + 0xd3, 0xb5, 0x9f, 0xb1, 0xb7, 0xb0, 0x66, 0xa9, 0xa8, 0xab, 0xa8, 0xae, + 0x75, 0xba, 0xe0, 0xcf, 0x8c, 0xdb, 0x88, 0xe9, 0x9a, 0x00, 0x7a, 0x07, + 0x40, 0x05, 0x40, 0x15, 0x72, 0x24, 0xdb, 0x1c, 0xac, 0x15, 0x0a, 0x23, + 0x06, 0x2a, 0x09, 0x28, 0x9b, 0x34, 0x1d, 0x41, 0xeb, 0x3b, 0xf6, 0x34, + 0x08, 0x42, 0xaf, 0x47, 0xdc, 0x43, 0x0d, 0x4f, 0xe3, 0x4e, 0x2c, 0x46, + 0x36, 0x48, 0xed, 0x47, 0x74, 0x43, 0xb1, 0x3d, 0xb9, 0x2e, 0x21, 0x27, + 0x0f, 0x28, 0x76, 0x18, 0xb0, 0x0f, 0x20, 0x0e, 0x8d, 0x04, 0x78, 0x06, + 0x7b, 0x04, 0x97, 0xfd, 0xb7, 0x04, 0xe0, 0x0d, 0x32, 0x0b, 0x4e, 0x00, + 0x31, 0xfc, 0x19, 0xf1, 0x81, 0xe0, 0xa4, 0xdd, 0xe5, 0xd8, 0x17, 0xcd, + 0x39, 0xc0, 0x8c, 0xbe, 0x50, 0xc1, 0xb8, 0xc1, 0xb3, 0xc5, 0xf0, 0xc3, + 0xfe, 0xc6, 0x07, 0xcd, 0x49, 0xd3, 0xf0, 0xd7, 0x57, 0xd4, 0x08, 0xcc, + 0xd2, 0xd2, 0x6b, 0xdf, 0xed, 0xd9, 0x42, 0xe4, 0x69, 0xe8, 0x8c, 0xe2, + 0x9e, 0xe4, 0xe7, 0xe1, 0x81, 0xea, 0xcc, 0xed, 0xcc, 0xf3, 0x3c, 0x01, + 0x51, 0x0e, 0x1b, 0x12, 0xd4, 0x13, 0x9b, 0x21, 0xf6, 0x24, 0x1f, 0x2d, + 0x37, 0x36, 0x09, 0x3d, 0x6d, 0x43, 0xe6, 0x42, 0x57, 0x43, 0x30, 0x44, + 0xae, 0x48, 0x1d, 0x4b, 0x49, 0x4e, 0x0c, 0x4c, 0xc5, 0x4f, 0xe2, 0x56, + 0x71, 0x54, 0xfa, 0x56, 0xcb, 0x54, 0xf2, 0x50, 0x7b, 0x4f, 0x4e, 0x4e, + 0xc2, 0x4a, 0xc2, 0x49, 0x1b, 0x47, 0xff, 0x32, 0x76, 0x1c, 0x5a, 0x0e, + 0xb4, 0x0a, 0xba, 0x09, 0xd6, 0x06, 0x71, 0x00, 0xe2, 0xf1, 0x4c, 0xe3, + 0xe6, 0xdc, 0x84, 0xe2, 0x5c, 0xe5, 0x23, 0xe2, 0x3d, 0xdc, 0x9d, 0xce, + 0x15, 0xc6, 0x5e, 0xc9, 0xd3, 0xcd, 0x8b, 0xc8, 0xb4, 0xbe, 0x30, 0xc0, + 0x26, 0xc7, 0x3c, 0xc5, 0x23, 0xc0, 0x35, 0xbf, 0xf5, 0xc3, 0xb9, 0xd0, + 0xdd, 0xe0, 0x84, 0xec, 0x68, 0xf7, 0x1c, 0xfe, 0xa9, 0xfd, 0x3d, 0xfc, + 0x8e, 0xfc, 0x4a, 0x03, 0x57, 0xfa, 0x83, 0xe5, 0xd7, 0xdf, 0x00, 0xd8, + 0x51, 0xcf, 0x88, 0xce, 0xf8, 0xd4, 0x68, 0xdf, 0x0d, 0xe2, 0xcc, 0xef, + 0xf2, 0xfc, 0x80, 0xff, 0xbd, 0x1a, 0x9e, 0x3b, 0x62, 0x42, 0xf8, 0x3b, + 0x6a, 0x3d, 0x2d, 0x36, 0x11, 0x22, 0x4b, 0x27, 0xe6, 0x2e, 0x9d, 0x2e, + 0x11, 0x3d, 0x4e, 0x41, 0x7c, 0x34, 0xd8, 0x2c, 0xef, 0x29, 0x65, 0x25, + 0x18, 0x2a, 0xbd, 0x25, 0x4e, 0x18, 0xab, 0x0e, 0x3f, 0x00, 0x02, 0x03, + 0x0b, 0x09, 0x5b, 0xff, 0xe2, 0xf7, 0x6c, 0xf5, 0x62, 0xf5, 0x4f, 0xf6, + 0xad, 0xf1, 0x16, 0xf0, 0x5f, 0xf1, 0x2c, 0xe8, 0x86, 0xef, 0x13, 0xf7, + 0xe0, 0xe7, 0xeb, 0xe8, 0xfd, 0xed, 0x4f, 0xe0, 0x9a, 0xdc, 0x91, 0xe9, + 0x85, 0xe7, 0xf9, 0xdb, 0x16, 0xd9, 0x39, 0xd9, 0x6f, 0xdb, 0x71, 0xd6, + 0x63, 0xd2, 0x0b, 0xd9, 0xf1, 0xd4, 0xd5, 0xcf, 0x1b, 0xe1, 0xd6, 0xe3, + 0xa9, 0xdd, 0xaf, 0xeb, 0x24, 0xee, 0xa3, 0xee, 0x19, 0xf2, 0x4b, 0xf7, + 0xcb, 0x05, 0x91, 0x0c, 0x8c, 0x10, 0xfb, 0x0d, 0x06, 0x11, 0xc8, 0x17, + 0xc7, 0x1b, 0xa9, 0x20, 0x68, 0x1b, 0x45, 0x25, 0x20, 0x30, 0xcd, 0x32, + 0x80, 0x33, 0xea, 0x2a, 0x9b, 0x29, 0x5b, 0x2c, 0x10, 0x35, 0xd3, 0x3e, + 0xc8, 0x47, 0x85, 0x4a, 0xab, 0x47, 0xc1, 0x4a, 0xa7, 0x46, 0x69, 0x44, + 0x08, 0x45, 0x81, 0x45, 0x08, 0x48, 0xef, 0x45, 0x47, 0x3e, 0xb6, 0x38, + 0x62, 0x31, 0x02, 0x23, 0x77, 0x20, 0x7b, 0x19, 0x75, 0x09, 0x96, 0x02, + 0x76, 0xf9, 0x97, 0xea, 0x15, 0xe3, 0x58, 0xe5, 0xcf, 0xe8, 0x55, 0xea, + 0xe3, 0xe6, 0xa2, 0xe0, 0x77, 0xda, 0xef, 0xd8, 0x92, 0xd7, 0x6d, 0xd7, + 0x1a, 0xdb, 0x94, 0xd8, 0x84, 0xdc, 0x2c, 0xdc, 0xe2, 0xd0, 0x50, 0xce, + 0x94, 0xd2, 0xae, 0xdb, 0x8e, 0xde, 0x1c, 0xda, 0x68, 0xdb, 0x30, 0xde, + 0x52, 0xdd, 0x9f, 0xdd, 0x80, 0xe2, 0x81, 0xe8, 0xf3, 0xf3, 0x91, 0x00, + 0x4d, 0x0a, 0x27, 0x0e, 0xbd, 0x09, 0x34, 0x12, 0x4b, 0x1b, 0xe7, 0x19, + 0x92, 0x11, 0x29, 0x00, 0xab, 0xf5, 0x3f, 0xe9, 0x8c, 0xe3, 0x3f, 0xee, + 0xdd, 0xf1, 0xae, 0xe6, 0xbf, 0xe2, 0x77, 0xf2, 0x01, 0xf5, 0x33, 0xfa, + 0x51, 0x1d, 0x3e, 0x30, 0xe4, 0x20, 0x69, 0x1b, 0x7d, 0x2b, 0xc5, 0x29, + 0x0b, 0x27, 0x8c, 0x2f, 0xf8, 0x2a, 0x6a, 0x23, 0x3b, 0x17, 0x33, 0x15, + 0x88, 0x14, 0x74, 0x10, 0x0e, 0x17, 0xa2, 0x0d, 0x6a, 0x0b, 0xfc, 0x09, + 0xe7, 0x05, 0x2c, 0x0b, 0xe1, 0x03, 0xc7, 0x05, 0xb9, 0x06, 0x2c, 0xfc, + 0x6d, 0xf1, 0x87, 0xf0, 0x5a, 0xf2, 0x96, 0xeb, 0xbc, 0xef, 0xa5, 0xec, + 0x7e, 0xe7, 0x1b, 0xed, 0x2d, 0xf1, 0x4f, 0xf1, 0xcb, 0xe5, 0xd5, 0xe6, + 0xc7, 0xef, 0x6a, 0xe9, 0x22, 0xee, 0x2e, 0xf9, 0xeb, 0xf8, 0xb5, 0xf3, + 0x94, 0xeb, 0xf6, 0xe4, 0xe9, 0xdd, 0x26, 0xdf, 0xd9, 0xeb, 0x88, 0xf7, + 0x65, 0xf2, 0x8c, 0xe7, 0x34, 0xe6, 0x68, 0xe6, 0xd7, 0xf4, 0x44, 0xfd, + 0x9c, 0x00, 0x30, 0x09, 0xc8, 0x0c, 0xd0, 0x15, 0xa6, 0x12, 0xc0, 0x14, + 0x66, 0x20, 0x3a, 0x24, 0x58, 0x26, 0x65, 0x20, 0xa4, 0x21, 0xd9, 0x28, + 0x0a, 0x2e, 0x4e, 0x38, 0xcd, 0x3a, 0x8e, 0x3a, 0x9a, 0x3b, 0x80, 0x34, + 0xcd, 0x32, 0x2d, 0x33, 0x2b, 0x36, 0x9f, 0x3c, 0x8c, 0x3b, 0xb5, 0x3a, + 0xfd, 0x37, 0x78, 0x30, 0xfe, 0x28, 0x6a, 0x24, 0xfb, 0x1c, 0x6d, 0x16, + 0xc9, 0x0d, 0x62, 0x06, 0x28, 0x07, 0x93, 0xff, 0x62, 0xf5, 0x67, 0xee, + 0x88, 0xed, 0xa1, 0xe8, 0xc2, 0xe0, 0x77, 0xe0, 0xa9, 0xd6, 0x98, 0xca, + 0x0e, 0xcb, 0x74, 0xd0, 0x4a, 0xcf, 0xb4, 0xcc, 0x66, 0xc8, 0x62, 0xc3, + 0x9a, 0xc4, 0xb5, 0xcb, 0x86, 0xd2, 0x02, 0xd3, 0x57, 0xd2, 0x28, 0xd3, + 0xfe, 0xd2, 0xbf, 0xcd, 0xc1, 0xd3, 0xe8, 0xdd, 0xa9, 0xd6, 0x02, 0xcf, + 0xbf, 0xd4, 0x3a, 0xdd, 0x28, 0xe1, 0xd1, 0xe8, 0x30, 0xee, 0x4b, 0xf5, + 0x30, 0xff, 0xb4, 0x05, 0x1c, 0x0f, 0x13, 0x1f, 0x03, 0x2c, 0xde, 0x34, + 0x0e, 0x40, 0x09, 0x36, 0x0c, 0x24, 0x92, 0x1b, 0xa1, 0x14, 0x3f, 0x0a, + 0x59, 0xf9, 0xcf, 0xf3, 0xf3, 0xf2, 0xa5, 0xe8, 0x76, 0xe0, 0x72, 0xe8, + 0x8f, 0xee, 0xb7, 0xf2, 0x42, 0x0a, 0x0a, 0x21, 0x1f, 0x22, 0xc1, 0x1b, + 0x33, 0x24, 0x21, 0x2a, 0x3c, 0x1c, 0xb3, 0x15, 0x38, 0x1d, 0x7b, 0x19, + 0x51, 0x13, 0xed, 0x11, 0x85, 0x0e, 0x8a, 0x04, 0x2a, 0xfe, 0xb0, 0x09, + 0xc9, 0x0a, 0x54, 0x03, 0x87, 0x01, 0x65, 0x07, 0x2d, 0x03, 0x87, 0xf8, + 0x10, 0x04, 0x91, 0x03, 0x79, 0xf6, 0x06, 0xf5, 0xe5, 0xf6, 0xbc, 0xf1, + 0x25, 0xf2, 0xb8, 0xee, 0xb7, 0xe9, 0x10, 0xf4, 0x74, 0xf4, 0x9d, 0xf4, + 0x3c, 0xed, 0x3a, 0xef, 0x99, 0xf6, 0xb6, 0xee, 0x9f, 0xfb, 0xce, 0x03, + 0xfa, 0x01, 0xb6, 0x05, 0xa8, 0x06, 0x74, 0x00, 0x05, 0x06, 0xe7, 0x0f, + 0xaa, 0x09, 0xe8, 0x0c, 0x05, 0x06, 0xd2, 0xf8, 0x5b, 0xfa, 0x71, 0xfc, + 0x86, 0xff, 0xee, 0x08, 0xe4, 0x0c, 0xa5, 0x07, 0xf2, 0x09, 0x08, 0x08, + 0xa8, 0x0d, 0x73, 0x1e, 0x7d, 0x1e, 0x2b, 0x1e, 0xfc, 0x26, 0xf8, 0x28, + 0xa3, 0x29, 0xe3, 0x2a, 0x5c, 0x29, 0xb9, 0x32, 0x00, 0x3b, 0x66, 0x3b, + 0x2b, 0x3a, 0x8c, 0x33, 0x6a, 0x2c, 0xe6, 0x29, 0xa4, 0x2c, 0x64, 0x2d, + 0x04, 0x2a, 0xbc, 0x1c, 0x1b, 0x12, 0x07, 0x14, 0x3b, 0x0f, 0x9e, 0x08, + 0x61, 0x03, 0xc1, 0xfc, 0xe7, 0xfa, 0x5d, 0xfc, 0xda, 0xfb, 0x28, 0xf6, + 0x33, 0xf1, 0x15, 0xec, 0x3d, 0xea, 0x3c, 0xe7, 0x6d, 0xdd, 0xa2, 0xdc, + 0x1e, 0xde, 0x39, 0xdd, 0x5f, 0xe2, 0xda, 0xe4, 0x4d, 0xde, 0xce, 0xdc, + 0x18, 0xe3, 0xf1, 0xe1, 0xb6, 0xe1, 0x9b, 0xe0, 0xb1, 0xe0, 0x9e, 0xe0, + 0x94, 0xd3, 0x59, 0xd0, 0x74, 0xd3, 0x22, 0xd3, 0x1a, 0xd8, 0x1c, 0xde, + 0x0b, 0xe1, 0x01, 0xe1, 0x6d, 0xe6, 0xa0, 0xf5, 0x16, 0x02, 0xbd, 0x02, + 0xcc, 0x09, 0x01, 0x14, 0x43, 0x15, 0x83, 0x1a, 0xb5, 0x23, 0x5a, 0x31, + 0x23, 0x3e, 0x87, 0x41, 0xa1, 0x3c, 0x9a, 0x30, 0xee, 0x1d, 0xa4, 0x0c, + 0x5c, 0x02, 0x8d, 0xf2, 0x9b, 0xe1, 0x7b, 0xdc, 0xb6, 0xd9, 0xdf, 0xca, + 0x6f, 0xc4, 0x82, 0xd3, 0x26, 0xd9, 0x22, 0xd7, 0xed, 0xe2, 0x13, 0xf5, + 0xb9, 0xf4, 0xf8, 0xf6, 0xfe, 0x0c, 0xf7, 0x09, 0xf1, 0x00, 0xbb, 0x06, + 0x2d, 0x0b, 0xcc, 0x0e, 0x86, 0x11, 0x19, 0x1e, 0x50, 0x15, 0x5d, 0x03, + 0xe8, 0x05, 0x62, 0xfe, 0x92, 0xf8, 0x34, 0xff, 0xc2, 0x07, 0xf7, 0x04, + 0x94, 0xf6, 0x29, 0xf3, 0xf7, 0xfb, 0xcf, 0xf9, 0xe3, 0xf1, 0x2f, 0xfb, + 0xe1, 0xf9, 0xbb, 0xf2, 0xae, 0xf3, 0x17, 0xf3, 0x1a, 0xf6, 0x45, 0xf8, + 0x95, 0x01, 0xeb, 0x04, 0xf2, 0xfd, 0x58, 0xf8, 0x2a, 0xf9, 0x46, 0x01, + 0xa2, 0x0f, 0x14, 0x21, 0x68, 0x24, 0x54, 0x21, 0xb2, 0x1a, 0xd2, 0x19, + 0x9d, 0x18, 0xf7, 0x12, 0x37, 0x18, 0xc9, 0x13, 0x1b, 0x08, 0x2e, 0x00, + 0xd5, 0xfb, 0x51, 0xf5, 0x75, 0xf2, 0x9d, 0xf5, 0x0a, 0xfb, 0x16, 0x00, + 0x73, 0xfa, 0x7e, 0x03, 0x1c, 0x14, 0x37, 0x1a, 0x7d, 0x1f, 0x89, 0x27, + 0x22, 0x2a, 0xbe, 0x2d, 0x2f, 0x37, 0x15, 0x37, 0xc0, 0x3e, 0x96, 0x3e, + 0xbf, 0x36, 0xe5, 0x31, 0x07, 0x26, 0x08, 0x1e, 0xee, 0x10, 0x2c, 0x0b, + 0xbd, 0x09, 0xdd, 0x0a, 0xa3, 0x09, 0x3a, 0x01, 0x27, 0xfa, 0xdd, 0xec, + 0x1c, 0xed, 0xc9, 0xf2, 0xc6, 0xfb, 0x54, 0xff, 0x3a, 0xf8, 0xbd, 0xf0, + 0xa6, 0xe1, 0x77, 0xde, 0xfb, 0xda, 0x67, 0xe0, 0x8a, 0xea, 0xd8, 0xe8, + 0xe2, 0xeb, 0x9d, 0xed, 0x7c, 0xf3, 0x8b, 0xf3, 0x06, 0xfb, 0x62, 0x03, + 0x8a, 0xfb, 0xd9, 0xf7, 0xc8, 0xf7, 0x59, 0xf6, 0xe7, 0xe6, 0x18, 0xe0, + 0x74, 0xdf, 0x8f, 0xd4, 0xda, 0xd4, 0xef, 0xd6, 0x8b, 0xda, 0x49, 0xe0, + 0xaf, 0xe3, 0x40, 0xe9, 0x74, 0xf0, 0xec, 0xf8, 0x1f, 0x00, 0xf8, 0x06, + 0xd3, 0x10, 0x97, 0x1c, 0xa4, 0x26, 0x00, 0x2d, 0x27, 0x34, 0xbc, 0x3a, + 0x45, 0x34, 0x3c, 0x35, 0x55, 0x3c, 0x24, 0x2e, 0xc0, 0x1d, 0x22, 0x0e, + 0x15, 0xfa, 0x7c, 0xec, 0x0c, 0xdb, 0x3a, 0xcf, 0x34, 0xd0, 0x5c, 0xc7, + 0x75, 0xbd, 0x98, 0xb7, 0xfe, 0xb7, 0xb3, 0xc4, 0xd9, 0xc3, 0x5f, 0xcb, + 0xb0, 0xea, 0x7b, 0xe9, 0x28, 0xe2, 0xb9, 0xfc, 0xb9, 0x03, 0xdd, 0x02, + 0x21, 0x0e, 0xf7, 0x1c, 0xd2, 0x25, 0x6f, 0x1b, 0xc6, 0x24, 0x62, 0x21, + 0x9e, 0x0b, 0xc1, 0x0d, 0xb8, 0x0e, 0x9d, 0x0a, 0x0a, 0x07, 0x1b, 0x05, + 0x1c, 0x08, 0x6f, 0x03, 0x71, 0xfc, 0xe4, 0x05, 0xcd, 0x05, 0x6b, 0x03, + 0x61, 0x08, 0x35, 0x04, 0x2e, 0x0b, 0x17, 0x06, 0x32, 0xff, 0x50, 0x07, + 0xde, 0x08, 0xb5, 0x0e, 0xcb, 0x12, 0xc7, 0x0b, 0xc4, 0x0f, 0x35, 0x19, + 0x83, 0x0f, 0x9b, 0x1a, 0x77, 0x2f, 0x76, 0x23, 0x68, 0x1b, 0x3d, 0x1d, + 0xbd, 0x16, 0xf4, 0x11, 0xe2, 0x0e, 0xbe, 0x0d, 0xef, 0x0e, 0x8e, 0xff, + 0xd0, 0xf0, 0x08, 0xf3, 0xc8, 0xe4, 0xd8, 0xdf, 0x3c, 0xf8, 0x03, 0xf3, + 0x8f, 0xe8, 0x9f, 0xf2, 0x0d, 0xf4, 0xe2, 0x02, 0xeb, 0x0d, 0x6b, 0x0c, + 0x6b, 0x17, 0x11, 0x1f, 0xd2, 0x20, 0xbc, 0x25, 0x16, 0x24, 0xaf, 0x22, + 0x6d, 0x26, 0xa9, 0x1e, 0x60, 0x10, 0x94, 0x07, 0x2d, 0x06, 0x85, 0x00, + 0x1f, 0xfd, 0x18, 0xfb, 0x7d, 0xf2, 0x88, 0xf5, 0x1d, 0xf2, 0xa8, 0xed, + 0x8e, 0xf4, 0x0d, 0xf7, 0x9b, 0xfb, 0x22, 0xfc, 0xa7, 0xf6, 0x1c, 0xf9, + 0xbe, 0xf6, 0x86, 0xee, 0x9d, 0xf2, 0xde, 0xf6, 0x71, 0xfc, 0xa1, 0xfe, + 0xd2, 0xf8, 0x2b, 0xfd, 0x86, 0x01, 0x36, 0x07, 0xf7, 0x09, 0x8f, 0x03, + 0xcd, 0xff, 0xdc, 0xf5, 0xd1, 0xf3, 0x2b, 0xfc, 0xff, 0xf5, 0x5e, 0xea, + 0xd1, 0xdf, 0x25, 0xd9, 0x2b, 0xda, 0x8c, 0xdb, 0x9e, 0xe1, 0x8c, 0xe5, + 0x39, 0xdf, 0xe0, 0xd9, 0x81, 0xdc, 0x0b, 0xe3, 0x41, 0xf1, 0x56, 0x03, + 0x08, 0x0b, 0x2e, 0x0a, 0x07, 0x12, 0x41, 0x29, 0xec, 0x39, 0xd3, 0x3f, + 0x45, 0x48, 0xde, 0x46, 0xd6, 0x3e, 0x7f, 0x3b, 0xa4, 0x34, 0x00, 0x27, + 0x3f, 0x0f, 0x20, 0xfb, 0x7f, 0xe8, 0x7f, 0xd1, 0x58, 0xce, 0xe2, 0xcb, + 0x46, 0xbd, 0x05, 0xb3, 0xb5, 0xb1, 0xb5, 0xb8, 0x80, 0xbc, 0x7a, 0xc6, + 0xf3, 0xe1, 0x41, 0xf2, 0x4b, 0xee, 0x85, 0xf3, 0xc0, 0xfa, 0x7f, 0xf9, + 0xdb, 0xff, 0xb8, 0x12, 0x4a, 0x24, 0x88, 0x25, 0x69, 0x28, 0xad, 0x2d, + 0x57, 0x24, 0xd1, 0x25, 0x65, 0x2b, 0x19, 0x1d, 0x13, 0x16, 0xa0, 0x0f, + 0xe9, 0x0d, 0x17, 0x14, 0x0d, 0x07, 0x0d, 0x05, 0x9e, 0x07, 0x71, 0x03, + 0x05, 0x07, 0x01, 0x09, 0xe2, 0x07, 0x58, 0x06, 0x0b, 0x0d, 0x61, 0x11, + 0x65, 0x1b, 0x45, 0x24, 0x37, 0x1c, 0x6f, 0x1a, 0x45, 0x17, 0xc0, 0x1e, + 0xdd, 0x2f, 0x07, 0x25, 0x6a, 0x21, 0xc0, 0x2b, 0x53, 0x1c, 0x9e, 0x15, + 0x66, 0x19, 0xff, 0x0f, 0xcb, 0x10, 0x0a, 0x0c, 0xe2, 0x01, 0x64, 0x02, + 0xe4, 0xf5, 0x06, 0xe6, 0xb9, 0xe4, 0x3e, 0xdf, 0x49, 0xdc, 0x99, 0xe4, + 0xc3, 0xe6, 0xcd, 0xe4, 0xf0, 0xe8, 0x0c, 0xf6, 0x72, 0xfd, 0xa9, 0x03, + 0x81, 0x0a, 0xf7, 0x0d, 0x95, 0x1a, 0x4a, 0x16, 0xab, 0x17, 0xbf, 0x22, + 0x46, 0x15, 0x99, 0x0f, 0x25, 0x07, 0xdd, 0xf7, 0x95, 0xf3, 0x3b, 0xf3, + 0x35, 0xf4, 0xf7, 0xed, 0xea, 0xe4, 0x65, 0xdc, 0x02, 0xe4, 0x88, 0xee, + 0x59, 0xf2, 0x83, 0xfa, 0x7e, 0xf2, 0xa9, 0xef, 0xfa, 0xf2, 0xee, 0xf4, + 0x9f, 0xfd, 0x46, 0xfd, 0x00, 0xfa, 0x48, 0xf7, 0xdc, 0xf9, 0x38, 0xfc, + 0xe6, 0x03, 0xd1, 0x0b, 0x06, 0x07, 0xa2, 0x09, 0x91, 0x07, 0x45, 0x05, + 0x72, 0x06, 0x4c, 0x01, 0xe0, 0xfe, 0xdf, 0xf9, 0x91, 0xf9, 0xb6, 0xf6, + 0xe3, 0xed, 0x6a, 0xec, 0x4f, 0xe6, 0xa0, 0xdf, 0xdd, 0xdf, 0xe4, 0xe0, + 0x21, 0xdf, 0x7f, 0xdf, 0x5b, 0xe7, 0x10, 0xe7, 0x19, 0xeb, 0x2d, 0xf7, + 0xe4, 0xff, 0x71, 0x0b, 0x94, 0x0f, 0x54, 0x18, 0x5b, 0x2a, 0xdc, 0x33, + 0x25, 0x33, 0x63, 0x38, 0x22, 0x36, 0x14, 0x27, 0x8b, 0x21, 0x1c, 0x0d, + 0x83, 0xf7, 0x0b, 0xe7, 0x77, 0xd7, 0x35, 0xcf, 0x02, 0xb9, 0x4d, 0xb8, + 0xa1, 0xb8, 0xd4, 0xa3, 0x72, 0xb0, 0x77, 0xc3, 0xc3, 0xbb, 0x92, 0xc1, + 0x25, 0xdb, 0x17, 0xe7, 0x86, 0xe6, 0x87, 0xf5, 0x0a, 0x0a, 0x0f, 0x05, + 0x27, 0x10, 0xa3, 0x2c, 0xbc, 0x27, 0xc2, 0x2a, 0xed, 0x39, 0x90, 0x40, + 0xce, 0x45, 0x90, 0x3c, 0x24, 0x3b, 0xe8, 0x3b, 0xc1, 0x35, 0xe7, 0x33, + 0x11, 0x30, 0x77, 0x2e, 0xa1, 0x23, 0x44, 0x1f, 0x16, 0x23, 0x98, 0x19, + 0x3b, 0x17, 0x70, 0x21, 0xcc, 0x27, 0xb2, 0x22, 0x81, 0x1f, 0x7e, 0x1e, + 0x44, 0x22, 0x11, 0x2c, 0xad, 0x2b, 0x71, 0x29, 0xea, 0x22, 0xbc, 0x21, + 0xc9, 0x1a, 0xef, 0x0e, 0xab, 0x1e, 0x17, 0x21, 0xcb, 0x17, 0x28, 0x16, + 0xf2, 0x0e, 0xd3, 0x06, 0xb3, 0xf4, 0xdf, 0xef, 0x65, 0xf2, 0x05, 0xe3, + 0x08, 0xdb, 0x15, 0xd9, 0xa6, 0xd2, 0xa0, 0xd1, 0x08, 0xd8, 0xa1, 0xe2, + 0x9f, 0xe4, 0x6f, 0xe2, 0x7e, 0xee, 0x96, 0xfb, 0x09, 0xfb, 0x39, 0xfb, + 0x42, 0x05, 0x20, 0x04, 0xa9, 0xfc, 0x56, 0x01, 0x59, 0x05, 0xf1, 0x04, + 0xcb, 0x00, 0x6a, 0xfe, 0x75, 0xf4, 0x87, 0xe6, 0xe3, 0xe5, 0xf4, 0xe3, + 0x62, 0xe7, 0x2c, 0xe8, 0xb6, 0xe7, 0xe7, 0xee, 0xc3, 0xe9, 0x96, 0xe9, + 0xfc, 0xe9, 0x23, 0xed, 0x14, 0xfa, 0x81, 0xf8, 0xf7, 0xf9, 0xb4, 0x02, + 0xf9, 0x07, 0xac, 0x09, 0x3f, 0x0f, 0xfb, 0x16, 0xb9, 0x14, 0xff, 0x1c, + 0xca, 0x29, 0xe2, 0x30, 0xfa, 0x33, 0xb4, 0x32, 0x63, 0x29, 0x26, 0x15, + 0x36, 0x10, 0xad, 0x0c, 0x44, 0x06, 0xd6, 0x05, 0x1e, 0x02, 0x04, 0xfa, + 0x54, 0xec, 0x20, 0xee, 0xeb, 0xeb, 0x5a, 0xe4, 0x36, 0xea, 0x51, 0xe9, + 0x8e, 0xe6, 0x65, 0xe0, 0x19, 0xe3, 0xa7, 0xed, 0x9f, 0xf0, 0xd9, 0xf7, + 0xce, 0xf6, 0x93, 0xf2, 0xd6, 0xf8, 0x58, 0x0a, 0x14, 0x1c, 0x4c, 0x22, + 0x03, 0x26, 0xb5, 0x25, 0x7d, 0x24, 0x46, 0x16, 0x43, 0x05, 0x49, 0x00, + 0xc7, 0xf0, 0x96, 0xd7, 0x45, 0xc1, 0x87, 0xb7, 0x4c, 0xb2, 0x28, 0xae, + 0xe3, 0xaa, 0xcb, 0xa3, 0x52, 0xa4, 0x09, 0xac, 0x12, 0xb6, 0x8c, 0xc3, + 0x96, 0xd7, 0x68, 0xde, 0x2f, 0xde, 0xb4, 0xf1, 0x31, 0xfe, 0x17, 0x00, + 0xf3, 0x0d, 0xe8, 0x1c, 0x4e, 0x22, 0x8d, 0x26, 0x7d, 0x33, 0x0e, 0x37, + 0xb1, 0x35, 0xb1, 0x42, 0x74, 0x43, 0x5f, 0x3e, 0x98, 0x3a, 0xe8, 0x34, + 0xa7, 0x39, 0x52, 0x33, 0x22, 0x2d, 0x45, 0x30, 0xf9, 0x2e, 0xf1, 0x2a, + 0x74, 0x26, 0xbf, 0x2b, 0x68, 0x2e, 0x3e, 0x29, 0x0b, 0x28, 0xa6, 0x2b, + 0x85, 0x34, 0xbf, 0x3c, 0x8a, 0x48, 0x69, 0x4d, 0x73, 0x4b, 0x3a, 0x4d, + 0x80, 0x43, 0xab, 0x3f, 0x27, 0x3d, 0xcb, 0x34, 0xb6, 0x28, 0x46, 0x18, + 0x99, 0x10, 0x40, 0xfa, 0x17, 0xee, 0xcf, 0xed, 0xf3, 0xdf, 0x3b, 0xd4, + 0xad, 0xd2, 0x2f, 0xd5, 0x8b, 0xd2, 0xa4, 0xdb, 0xcc, 0xd9, 0xf7, 0xd4, + 0x2b, 0xd9, 0x77, 0xd4, 0x96, 0xdd, 0x28, 0xe2, 0x04, 0xe0, 0xac, 0xe5, + 0xf3, 0xe8, 0xcb, 0xeb, 0x38, 0xf2, 0x1b, 0xfc, 0x88, 0x04, 0x60, 0x07, + 0xa7, 0x06, 0x67, 0x03, 0xa0, 0xfc, 0xe0, 0xf5, 0xb7, 0xee, 0x72, 0xef, + 0x9b, 0xed, 0x08, 0xe2, 0x81, 0xde, 0x80, 0xe3, 0x54, 0xeb, 0xf4, 0xef, + 0xd2, 0xf3, 0xb0, 0xf9, 0x56, 0xfb, 0x37, 0x01, 0xdb, 0x0d, 0xd1, 0x0f, + 0xa9, 0x13, 0xa3, 0x24, 0x3f, 0x2c, 0xfd, 0x2c, 0x4f, 0x32, 0x3b, 0x34, + 0x3e, 0x33, 0x05, 0x32, 0x25, 0x32, 0x60, 0x30, 0x10, 0x1f, 0xdc, 0x12, + 0x12, 0x10, 0x61, 0x08, 0xa2, 0x08, 0xa0, 0x0a, 0xd8, 0x07, 0xd6, 0xfd, + 0x2e, 0xf5, 0x3f, 0xf8, 0x24, 0xf5, 0x94, 0xea, 0x36, 0xe7, 0xb7, 0xe2, + 0x28, 0xdb, 0xc0, 0xd9, 0xe9, 0xd9, 0x3b, 0xe0, 0xa2, 0xe7, 0xd0, 0xec, + 0xca, 0xf0, 0x9c, 0xf2, 0x58, 0xf2, 0x36, 0xf8, 0xdf, 0x0e, 0xf7, 0x17, + 0xe1, 0x12, 0x95, 0x14, 0xe6, 0x14, 0x9a, 0x02, 0x78, 0xe8, 0x69, 0xdc, + 0xcb, 0xc9, 0x9b, 0xb9, 0xe0, 0xb4, 0xf6, 0xb3, 0x6b, 0xb2, 0x75, 0xac, + 0xfd, 0xab, 0x3f, 0xa9, 0x70, 0xac, 0x55, 0xaf, 0xf4, 0xb7, 0x05, 0xd2, + 0x75, 0xe0, 0xd1, 0xe0, 0xed, 0xe6, 0x89, 0xf7, 0x85, 0xf4, 0x2c, 0xf5, + 0x08, 0x14, 0x2e, 0x22, 0x72, 0x25, 0x12, 0x31, 0xc2, 0x36, 0x67, 0x35, + 0x7e, 0x3b, 0xe9, 0x47, 0x90, 0x47, 0x55, 0x46, 0x94, 0x49, 0xb7, 0x45, + 0xf8, 0x40, 0x7e, 0x3d, 0x04, 0x3a, 0x41, 0x36, 0x74, 0x2f, 0x8b, 0x2e, + 0xc1, 0x33, 0xa4, 0x31, 0x94, 0x33, 0x36, 0x37, 0xdd, 0x32, 0xc6, 0x39, + 0xae, 0x41, 0x61, 0x42, 0xa0, 0x47, 0x8a, 0x4d, 0xf1, 0x54, 0x44, 0x55, + 0x88, 0x49, 0x45, 0x47, 0x72, 0x47, 0xb9, 0x31, 0xde, 0x20, 0x2a, 0x16, + 0xb4, 0xff, 0x08, 0xf6, 0x51, 0xf2, 0x04, 0xe7, 0xfc, 0xda, 0x86, 0xce, + 0x54, 0xc4, 0xe8, 0xc6, 0x03, 0xd0, 0x1a, 0xd4, 0xec, 0xd6, 0x65, 0xd1, + 0x88, 0xd1, 0xa4, 0xd1, 0xc6, 0xd1, 0x0d, 0xde, 0x20, 0xdc, 0x7d, 0xe1, + 0xf4, 0xe9, 0x6f, 0xea, 0xd3, 0xf3, 0xbb, 0xf3, 0x53, 0xfc, 0xe7, 0x03, + 0xbd, 0x04, 0x5a, 0x14, 0x18, 0x14, 0x28, 0x0b, 0x3c, 0x08, 0x01, 0x03, + 0x16, 0xfd, 0x3a, 0xf3, 0x8a, 0xed, 0x54, 0xe4, 0x1e, 0xdc, 0xd9, 0xdb, + 0xa8, 0xd7, 0x85, 0xde, 0x35, 0xeb, 0x9c, 0xf9, 0x5c, 0x0c, 0x90, 0x11, + 0x04, 0x14, 0xa3, 0x17, 0x81, 0x20, 0x5f, 0x2e, 0x24, 0x33, 0x63, 0x37, + 0xf1, 0x37, 0x26, 0x30, 0x81, 0x27, 0xab, 0x26, 0x8a, 0x23, 0xfa, 0x1e, + 0xc4, 0x21, 0xf9, 0x18, 0xb6, 0x10, 0x44, 0x0f, 0x5f, 0x09, 0xba, 0xfa, + 0x91, 0xf3, 0xf9, 0xfb, 0xa1, 0xf3, 0x6d, 0xf0, 0x9c, 0xf7, 0xb1, 0xef, + 0x41, 0xe1, 0x08, 0xd6, 0x9f, 0xdc, 0xb3, 0xe3, 0x7c, 0xe3, 0xcd, 0xec, + 0x93, 0xf1, 0x17, 0xeb, 0xb5, 0xf1, 0xb2, 0x03, 0xeb, 0x07, 0xc6, 0x0b, + 0x8b, 0x1d, 0x39, 0x29, 0x57, 0x16, 0xdf, 0xfa, 0x1a, 0xf3, 0x0a, 0xe3, + 0xe5, 0xc6, 0xc5, 0xbb, 0x0f, 0xba, 0x72, 0xba, 0x86, 0xbc, 0x88, 0xae, + 0x0a, 0xae, 0x19, 0xbe, 0xab, 0xb8, 0xd5, 0xc2, 0xa1, 0xe2, 0xcd, 0xee, + 0xa7, 0xe3, 0x43, 0xe3, 0xf6, 0xf8, 0xf8, 0xef, 0x4f, 0xe8, 0x2f, 0x08, + 0xf9, 0x0e, 0x82, 0x0f, 0x14, 0x29, 0xa4, 0x34, 0x28, 0x32, 0xfc, 0x2f, + 0x3d, 0x3e, 0xe5, 0x4a, 0xa8, 0x3f, 0x94, 0x37, 0x76, 0x3a, 0x4a, 0x39, + 0x22, 0x30, 0x45, 0x31, 0x82, 0x2c, 0xb2, 0x20, 0x65, 0x1f, 0x4e, 0x16, + 0x05, 0x18, 0xd7, 0x18, 0x49, 0x17, 0xc0, 0x22, 0xb1, 0x2a, 0xd6, 0x34, + 0xa3, 0x39, 0xfe, 0x38, 0x8e, 0x3b, 0x37, 0x52, 0x95, 0x61, 0x86, 0x57, + 0x1c, 0x5e, 0xf7, 0x5e, 0xb4, 0x4f, 0x33, 0x42, 0x82, 0x39, 0x95, 0x2a, + 0x24, 0x14, 0x31, 0x04, 0x68, 0xeb, 0x44, 0xd6, 0xdd, 0xc6, 0x34, 0xc0, + 0xf6, 0xc8, 0x36, 0xc5, 0x57, 0xbb, 0x0c, 0xbd, 0xd2, 0xc3, 0xbd, 0xc3, + 0x78, 0xd0, 0xea, 0xdd, 0x4b, 0xd7, 0xc9, 0xd5, 0xa5, 0xd2, 0x11, 0xd7, + 0xf3, 0xd9, 0xfb, 0xd5, 0x1b, 0xe6, 0x72, 0xe9, 0x51, 0xe5, 0xb5, 0xed, + 0xdc, 0xef, 0x62, 0xef, 0x44, 0xf3, 0x19, 0xfc, 0x6c, 0x02, 0x41, 0x04, + 0x50, 0x07, 0x01, 0x0d, 0xc0, 0x12, 0x2e, 0x1b, 0xee, 0x23, 0x02, 0x26, + 0x7c, 0x23, 0x7b, 0x24, 0x0d, 0x29, 0x02, 0x27, 0x85, 0x2a, 0x10, 0x30, + 0x56, 0x2b, 0x4d, 0x28, 0xbd, 0x2b, 0xf2, 0x2d, 0x80, 0x2f, 0x05, 0x32, + 0xec, 0x27, 0x88, 0x1d, 0x6c, 0x18, 0x6e, 0x16, 0x28, 0x19, 0x68, 0x14, + 0x58, 0x0b, 0x8d, 0xf9, 0x6e, 0xed, 0xaa, 0xee, 0xbf, 0xf4, 0x66, 0xfb, + 0xde, 0xf6, 0xd9, 0xed, 0x05, 0xe2, 0xb5, 0xe0, 0x55, 0xea, 0x56, 0xec, + 0xf8, 0xf0, 0xe8, 0xf1, 0x78, 0xed, 0xe3, 0xec, 0x0a, 0xe4, 0x80, 0xe2, + 0x36, 0xe6, 0x0f, 0xe6, 0xc5, 0xf0, 0x70, 0xf6, 0xe1, 0xf5, 0x41, 0xf4, + 0x48, 0xed, 0x70, 0xe4, 0x78, 0xdf, 0xca, 0xd6, 0xbe, 0xc4, 0x84, 0xba, + 0xa5, 0xb5, 0xd6, 0xb2, 0x0c, 0xb5, 0x3a, 0xb7, 0x28, 0xad, 0x10, 0xae, + 0x5c, 0xc1, 0x36, 0xc1, 0x6a, 0xc4, 0x1c, 0xe0, 0x27, 0xf6, 0x55, 0xf7, + 0x09, 0x01, 0xc2, 0x0f, 0x16, 0x0d, 0x87, 0x09, 0x89, 0x14, 0x27, 0x25, + 0xaa, 0x24, 0x9b, 0x28, 0x36, 0x2c, 0xc5, 0x1e, 0x77, 0x18, 0x7c, 0x22, + 0x93, 0x30, 0x75, 0x38, 0x21, 0x3e, 0x4a, 0x41, 0xa0, 0x44, 0x9b, 0x3d, + 0xba, 0x42, 0x58, 0x4e, 0x02, 0x46, 0xd0, 0x40, 0x75, 0x38, 0x2f, 0x35, + 0x23, 0x33, 0xa1, 0x31, 0x75, 0x38, 0xaf, 0x35, 0x03, 0x32, 0xfe, 0x31, + 0x63, 0x35, 0x36, 0x3c, 0xa1, 0x48, 0x90, 0x4e, 0x26, 0x45, 0xc7, 0x42, + 0xb6, 0x4a, 0xe6, 0x47, 0x1e, 0x40, 0x4c, 0x3c, 0x13, 0x31, 0x4c, 0x22, + 0x5e, 0x12, 0x94, 0x01, 0x1a, 0xee, 0xcf, 0xdc, 0x8e, 0xce, 0x8b, 0xc5, + 0x78, 0xc4, 0xc7, 0xbd, 0x7f, 0xc2, 0xd6, 0xc5, 0x45, 0xba, 0x94, 0xbd, + 0x66, 0xc8, 0xe2, 0xcc, 0x0e, 0xd3, 0x78, 0xd9, 0x89, 0xdb, 0xa2, 0xda, + 0xb2, 0xd3, 0x3a, 0xd1, 0x86, 0xdb, 0x2f, 0xe1, 0x1a, 0xdf, 0x20, 0xe5, + 0xdb, 0xe7, 0xf0, 0xe4, 0xf4, 0xea, 0x9c, 0xed, 0x95, 0xed, 0x18, 0xf3, + 0xeb, 0xf4, 0xbe, 0xf3, 0xe8, 0xf8, 0xd3, 0xf8, 0x32, 0xfb, 0xcb, 0x0a, + 0x5c, 0x14, 0xc0, 0x1f, 0xa2, 0x22, 0xfa, 0x1f, 0x7d, 0x2a, 0xaa, 0x33, + 0xc0, 0x40, 0x99, 0x4f, 0x06, 0x59, 0x04, 0x60, 0xb8, 0x61, 0xf5, 0x5c, + 0xaf, 0x5b, 0xbe, 0x5d, 0x18, 0x53, 0xdf, 0x42, 0x48, 0x37, 0xaf, 0x29, + 0x08, 0x19, 0x37, 0x08, 0x8e, 0xf8, 0x03, 0xee, 0x23, 0xe4, 0x43, 0xd9, + 0xc9, 0xd7, 0x57, 0xdf, 0x20, 0xe4, 0xf9, 0xe1, 0xac, 0xdc, 0xec, 0xd9, + 0x4d, 0xdf, 0x9e, 0xe9, 0xf6, 0xf0, 0x16, 0xf1, 0x5e, 0xed, 0xef, 0xe6, + 0x4e, 0xe2, 0xf9, 0xe2, 0x86, 0xf0, 0xec, 0x01, 0xb7, 0xfe, 0xb2, 0xf8, + 0xee, 0xee, 0xe7, 0xdf, 0xac, 0xd6, 0x0a, 0xc5, 0xf2, 0xb6, 0x63, 0xae, + 0xe4, 0xa5, 0xa0, 0xa5, 0x07, 0xa7, 0x95, 0xa2, 0x05, 0xa3, 0x08, 0xac, + 0xc0, 0xb0, 0x1a, 0xb8, 0xa3, 0xcd, 0xa4, 0xe3, 0xcc, 0xf0, 0x2d, 0xfe, + 0x6d, 0x0a, 0xb2, 0x0e, 0xae, 0x0e, 0xc5, 0x25, 0x63, 0x41, 0x75, 0x47, + 0x2a, 0x50, 0x94, 0x4d, 0xc1, 0x47, 0x4f, 0x46, 0xa3, 0x42, 0xa2, 0x44, + 0x34, 0x3e, 0x34, 0x3a, 0x7a, 0x3c, 0x69, 0x3c, 0x9c, 0x36, 0xec, 0x36, + 0x7f, 0x3c, 0x84, 0x36, 0x21, 0x32, 0x63, 0x35, 0xe6, 0x37, 0x6d, 0x33, + 0x21, 0x31, 0xa5, 0x2e, 0x69, 0x2e, 0x55, 0x33, 0x2b, 0x30, 0xb4, 0x31, + 0xae, 0x39, 0x97, 0x44, 0xf8, 0x4d, 0xdd, 0x4e, 0xd6, 0x4d, 0x53, 0x50, + 0x6d, 0x4b, 0x54, 0x3b, 0x03, 0x34, 0x3a, 0x25, 0x00, 0x13, 0xe1, 0x0a, + 0x0a, 0x00, 0x22, 0xf9, 0x27, 0xe9, 0xcd, 0xd8, 0xf8, 0xd3, 0x49, 0xce, + 0x41, 0xcc, 0x2b, 0xca, 0xc5, 0xc4, 0x89, 0xbe, 0xb4, 0xbb, 0xd0, 0xb9, + 0xb0, 0xbc, 0x61, 0xc2, 0xeb, 0xbf, 0xf0, 0xc2, 0x7a, 0xc8, 0x60, 0xcd, + 0xd2, 0xd4, 0xb8, 0xd9, 0x90, 0xe0, 0x58, 0xe1, 0xae, 0xdf, 0x98, 0xe1, + 0xf8, 0xe6, 0x74, 0xf3, 0xaa, 0xf3, 0x9c, 0xef, 0x91, 0xed, 0xf7, 0xe6, + 0x06, 0xed, 0xf6, 0xf0, 0xbd, 0xf5, 0x86, 0xfa, 0xa9, 0xf8, 0xd9, 0x01, + 0x1c, 0x05, 0xed, 0x06, 0xdf, 0x10, 0xca, 0x1b, 0x30, 0x20, 0x6e, 0x23, + 0x0c, 0x2d, 0xc4, 0x33, 0xeb, 0x3f, 0xb7, 0x41, 0x45, 0x3a, 0xc4, 0x37, + 0x7b, 0x39, 0x23, 0x42, 0x72, 0x45, 0x30, 0x42, 0x52, 0x3a, 0xf8, 0x36, + 0xd8, 0x36, 0xd2, 0x35, 0x46, 0x33, 0xb2, 0x2c, 0x09, 0x26, 0x0f, 0x1d, + 0x0e, 0x16, 0x24, 0x11, 0xe5, 0x09, 0x0f, 0xfd, 0xc0, 0xf6, 0xb7, 0xf5, + 0x28, 0xf1, 0xea, 0xe9, 0x81, 0xe3, 0x73, 0xea, 0xd0, 0xef, 0x90, 0xf0, + 0x6d, 0xf2, 0x4b, 0xf5, 0x11, 0xf4, 0x7b, 0xf3, 0xa9, 0xf9, 0xd4, 0xf0, + 0x10, 0xe0, 0x42, 0xcd, 0x2d, 0xc2, 0x17, 0xb7, 0x49, 0xab, 0x56, 0xaf, + 0x02, 0xac, 0xf6, 0xa4, 0x6c, 0x9d, 0xae, 0x9c, 0x9f, 0xa7, 0xba, 0xaf, + 0x45, 0xb8, 0xaf, 0xcd, 0x06, 0xe0, 0xc9, 0xdd, 0x7b, 0xe3, 0x02, 0xef, + 0x9a, 0xef, 0x21, 0xea, 0x17, 0xf5, 0xff, 0x05, 0x74, 0x07, 0x47, 0x14, + 0x1e, 0x26, 0x86, 0x2b, 0xfd, 0x28, 0x36, 0x2d, 0x81, 0x37, 0x41, 0x40, + 0xf6, 0x44, 0xb4, 0x49, 0x13, 0x4a, 0xa9, 0x3e, 0x45, 0x41, 0x1e, 0x45, + 0xcf, 0x49, 0xdb, 0x4d, 0xfc, 0x45, 0x38, 0x44, 0x3e, 0x41, 0x1d, 0x43, + 0xf8, 0x4b, 0x91, 0x51, 0x85, 0x50, 0xa9, 0x50, 0x2f, 0x47, 0xeb, 0x3b, + 0x4c, 0x46, 0xd3, 0x4a, 0x05, 0x4e, 0x49, 0x4e, 0x2f, 0x48, 0x61, 0x45, + 0x86, 0x39, 0xbc, 0x35, 0xd0, 0x36, 0xb2, 0x2c, 0x51, 0x21, 0x43, 0x15, + 0xca, 0x08, 0xa2, 0xfb, 0x79, 0xf1, 0x32, 0xf0, 0x3d, 0xed, 0x77, 0xee, + 0xe4, 0xeb, 0x4b, 0xdc, 0xe6, 0xd5, 0x51, 0xd7, 0xca, 0xd4, 0xb3, 0xcd, + 0x3e, 0xc7, 0x14, 0xc4, 0xec, 0xc0, 0x48, 0xbe, 0x5c, 0xc5, 0xb2, 0xc5, + 0xbb, 0xbc, 0x03, 0xc2, 0x53, 0xc0, 0x30, 0xc6, 0xe4, 0xd7, 0x3b, 0xd9, + 0x16, 0xe2, 0x72, 0xe6, 0xd4, 0xdc, 0xa0, 0xde, 0xdb, 0xdf, 0x81, 0xda, + 0xd5, 0xe1, 0x86, 0xea, 0xdd, 0xe3, 0x15, 0xe7, 0xec, 0xf5, 0x3c, 0xfa, + 0x33, 0xff, 0x9f, 0x07, 0x6f, 0x0c, 0xc3, 0x14, 0x42, 0x19, 0x0b, 0x18, + 0x24, 0x20, 0xed, 0x27, 0xc6, 0x28, 0x8f, 0x2b, 0x5f, 0x21, 0xb3, 0x19, + 0xca, 0x21, 0x93, 0x1e, 0xcc, 0x1d, 0xaa, 0x28, 0xc0, 0x2b, 0x3f, 0x2a, + 0xe3, 0x25, 0x66, 0x1f, 0x02, 0x22, 0xf9, 0x26, 0x0e, 0x2d, 0x5e, 0x33, + 0x33, 0x2b, 0x81, 0x23, 0x53, 0x20, 0x7d, 0x17, 0x5b, 0x0e, 0xd9, 0x10, + 0xbe, 0x19, 0x81, 0x13, 0x0c, 0x0c, 0xde, 0x0c, 0x54, 0x11, 0x57, 0x19, + 0x16, 0x1f, 0x77, 0x22, 0x0d, 0x21, 0x3a, 0x1a, 0x8a, 0x0f, 0xbe, 0xff, + 0x55, 0xea, 0x00, 0xd8, 0xe0, 0xbf, 0x3f, 0xa8, 0xc6, 0x9f, 0xfa, 0x99, + 0xce, 0x9e, 0x0c, 0xa4, 0xbd, 0xa2, 0xb1, 0xa7, 0x8d, 0xa9, 0x20, 0xa2, + 0x07, 0xa7, 0x15, 0xc3, 0x00, 0xd4, 0x18, 0xd6, 0x8f, 0xdd, 0x8d, 0xe0, + 0x08, 0xd6, 0x2b, 0xd6, 0xec, 0xeb, 0xb2, 0xfb, 0xd6, 0xff, 0x71, 0x08, + 0xa1, 0x11, 0x97, 0x13, 0x45, 0x21, 0x36, 0x30, 0xd1, 0x33, 0xcb, 0x32, + 0x0e, 0x2d, 0xd1, 0x2e, 0x41, 0x30, 0x1b, 0x32, 0x7a, 0x36, 0x71, 0x33, + 0x90, 0x2b, 0x7c, 0x28, 0xa5, 0x2c, 0x63, 0x31, 0x80, 0x37, 0x94, 0x3b, + 0xb2, 0x3d, 0x34, 0x41, 0x2f, 0x47, 0x54, 0x4e, 0xd5, 0x59, 0x91, 0x60, + 0x38, 0x61, 0x16, 0x61, 0x8a, 0x58, 0x0b, 0x59, 0x7a, 0x58, 0x7a, 0x51, + 0x74, 0x4c, 0xba, 0x41, 0x14, 0x36, 0x30, 0x25, 0x4f, 0x18, 0xdb, 0x15, + 0xc4, 0x0d, 0x38, 0x04, 0x98, 0x05, 0xc3, 0xfe, 0x74, 0xf4, 0x5a, 0xf0, + 0xac, 0xe7, 0xc7, 0xe1, 0x46, 0xe1, 0x67, 0xe5, 0xbd, 0xe5, 0x3b, 0xe4, + 0xbc, 0xdf, 0xfd, 0xdf, 0xe9, 0xe3, 0xdd, 0xda, 0x89, 0xd6, 0x96, 0xd3, + 0xfe, 0xca, 0x04, 0xc2, 0x6d, 0xc0, 0xcb, 0xc2, 0x38, 0xc2, 0x39, 0xc2, + 0x29, 0xc7, 0xaa, 0xca, 0xd7, 0xc4, 0xc3, 0xd0, 0x20, 0xd8, 0xd5, 0xd6, + 0xcf, 0xe2, 0x0d, 0xe4, 0x97, 0xe0, 0x0e, 0xe0, 0x4f, 0xe8, 0x5c, 0xea, + 0xae, 0xe9, 0xee, 0xf6, 0xef, 0xfe, 0x0b, 0x08, 0x76, 0x0a, 0x2a, 0x12, + 0x2a, 0x21, 0x9c, 0x21, 0x01, 0x2b, 0x44, 0x32, 0xc5, 0x2c, 0xf1, 0x28, + 0x55, 0x29, 0xfe, 0x29, 0x11, 0x24, 0x8c, 0x22, 0x42, 0x21, 0xd9, 0x1e, + 0x72, 0x1c, 0x9e, 0x17, 0xfb, 0x17, 0xeb, 0x16, 0x44, 0x19, 0x57, 0x22, + 0xd3, 0x23, 0xde, 0x1b, 0xda, 0x1b, 0x37, 0x20, 0x3f, 0x20, 0x91, 0x21, + 0x59, 0x1d, 0x19, 0x1a, 0x33, 0x1b, 0x5a, 0x16, 0xe2, 0x11, 0x34, 0x17, + 0x1a, 0x1b, 0x01, 0x19, 0x4d, 0x1a, 0x7c, 0x1e, 0x47, 0x17, 0x32, 0x00, + 0x04, 0xf1, 0x64, 0xe3, 0x34, 0xd6, 0x7c, 0xd5, 0x49, 0xd3, 0x1f, 0xd0, + 0xf4, 0xc9, 0x06, 0xbc, 0x79, 0xb3, 0x91, 0xba, 0xa4, 0xb9, 0x8a, 0xb6, + 0xdb, 0xc8, 0x34, 0xd3, 0xe4, 0xd0, 0x12, 0xd0, 0x94, 0xd4, 0x38, 0xd4, + 0xed, 0xc8, 0x69, 0xcc, 0x92, 0xd7, 0x03, 0xda, 0xde, 0xe4, 0x59, 0xf2, + 0xfe, 0xf0, 0x47, 0xeb, 0xac, 0xe7, 0xfb, 0xef, 0xa3, 0xfa, 0x7b, 0xff, + 0xd0, 0x0c, 0xa7, 0x10, 0x12, 0x0b, 0x83, 0x0a, 0xee, 0x17, 0xd2, 0x29, + 0xea, 0x31, 0x15, 0x38, 0xac, 0x3b, 0xcb, 0x3e, 0x28, 0x40, 0x21, 0x46, + 0xfd, 0x44, 0x46, 0x42, 0x77, 0x42, 0xb5, 0x3b, 0xef, 0x42, 0xb2, 0x48, + 0x42, 0x53, 0x3d, 0x54, 0xaa, 0x47, 0xe3, 0x50, 0x54, 0x57, 0x24, 0x56, + 0x23, 0x58, 0x0a, 0x57, 0xa6, 0x47, 0x9e, 0x36, 0x69, 0x2e, 0xb3, 0x26, + 0x1f, 0x1e, 0x31, 0x15, 0x29, 0x11, 0xa3, 0x06, 0x81, 0xfe, 0x21, 0xfa, + 0x13, 0xfc, 0x27, 0x05, 0x28, 0x04, 0xc1, 0x03, 0xf2, 0xfc, 0x42, 0xf0, + 0xa1, 0xed, 0x50, 0xf1, 0x3e, 0xf1, 0x50, 0xef, 0xf6, 0xea, 0xb1, 0xe3, + 0x9e, 0xdf, 0x28, 0xd7, 0x58, 0xd8, 0x4c, 0xd6, 0x6d, 0xca, 0xcb, 0xc9, + 0x8d, 0xc3, 0x31, 0xc1, 0x92, 0xc6, 0x8c, 0xc8, 0xe1, 0xcd, 0xa7, 0xd1, + 0xd6, 0xd3, 0xbd, 0xd5, 0x04, 0xd8, 0x28, 0xdc, 0x02, 0xe6, 0xa6, 0xeb, + 0xbd, 0xec, 0xb9, 0xf4, 0xc2, 0xf7, 0x92, 0xf7, 0x66, 0xfa, 0x1e, 0xfe, + 0xb5, 0xfe, 0x81, 0x07, 0xcb, 0x0e, 0x19, 0x04, 0x69, 0x05, 0x15, 0xfe, + 0x37, 0xf3, 0xbe, 0xfb, 0x1d, 0xfb, 0xbd, 0xfd, 0xb5, 0x01, 0xc4, 0x02, + 0x33, 0x05, 0xa6, 0x07, 0x4c, 0x0d, 0x6f, 0x09, 0xcb, 0x0b, 0xc8, 0x11, + 0x94, 0x0f, 0x7b, 0x11, 0xaf, 0x11, 0xfb, 0x15, 0x51, 0x22, 0x05, 0x26, + 0x80, 0x27, 0x5d, 0x2d, 0x9c, 0x2a, 0x4e, 0x29, 0xd8, 0x2d, 0x57, 0x2a, + 0x51, 0x28, 0xaf, 0x2d, 0x99, 0x2c, 0x7d, 0x22, 0x27, 0x1b, 0xdf, 0x10, + 0xf0, 0xfb, 0x27, 0xe8, 0x93, 0xdb, 0xa3, 0xd4, 0x14, 0xce, 0x63, 0xcc, + 0x52, 0xce, 0x97, 0xc5, 0x00, 0xbb, 0x59, 0xbd, 0x95, 0xc9, 0xe8, 0xd0, + 0xd6, 0xdb, 0x88, 0xf3, 0x74, 0xfa, 0x7e, 0xf1, 0xe6, 0xf2, 0xb5, 0xf8, + 0x1c, 0xf3, 0x6e, 0xf0, 0x03, 0xf9, 0x9e, 0xf7, 0x98, 0xf0, 0xba, 0xef, + 0x1c, 0xeb, 0x48, 0xe8, 0xf3, 0xea, 0xe7, 0xe5, 0xdb, 0xe2, 0xa1, 0xe1, + 0x81, 0xd9, 0x12, 0xdb, 0x24, 0xe6, 0x53, 0xeb, 0x6e, 0xef, 0xb6, 0xf8, + 0x80, 0xfa, 0x12, 0x02, 0x6a, 0x13, 0xbc, 0x23, 0x3a, 0x31, 0xbc, 0x35, + 0x44, 0x38, 0xe3, 0x31, 0xbe, 0x32, 0xeb, 0x39, 0xeb, 0x40, 0xaa, 0x4d, + 0x04, 0x4a, 0x38, 0x48, 0x6f, 0x46, 0x4a, 0x4a, 0x33, 0x54, 0xc4, 0x49, + 0x7c, 0x41, 0x9e, 0x3c, 0xec, 0x33, 0xe4, 0x2a, 0xd9, 0x23, 0xf7, 0x1c, + 0x8d, 0x11, 0x8f, 0x09, 0x9c, 0x07, 0xf7, 0x06, 0xee, 0x03, 0x82, 0x05, + 0xb8, 0x0b, 0x92, 0x13, 0x61, 0x13, 0x2c, 0x11, 0xf7, 0x17, 0xf8, 0x12, + 0xbd, 0x0b, 0x29, 0x0c, 0x80, 0x0b, 0x79, 0x0b, 0xcf, 0x07, 0x6e, 0xfe, + 0xf6, 0xf0, 0x2f, 0xe8, 0xbd, 0xe7, 0xdb, 0xeb, 0x7b, 0xec, 0x99, 0xea, + 0x05, 0xea, 0x59, 0xe3, 0x1e, 0xdb, 0xf4, 0xd7, 0x2e, 0xd6, 0x55, 0xcc, + 0x16, 0xc0, 0x1a, 0xc4, 0x68, 0xca, 0x15, 0xc5, 0x32, 0xcf, 0x31, 0xdb, + 0x33, 0xda, 0xf1, 0xdf, 0x9f, 0xe0, 0x66, 0xeb, 0xf9, 0xfd, 0x3e, 0x0b, + 0xd4, 0x15, 0x3a, 0x11, 0xc6, 0x07, 0xe6, 0xff, 0x80, 0xfe, 0xb3, 0xf8, + 0x6b, 0xf4, 0x1e, 0xf9, 0xa6, 0xf5, 0x04, 0xee, 0x42, 0xee, 0xc6, 0xf3, + 0xfa, 0xf1, 0x71, 0xf7, 0x38, 0xf9, 0x27, 0xf9, 0x60, 0x00, 0x6a, 0xff, + 0x2f, 0x04, 0xfb, 0x06, 0x86, 0x08, 0x32, 0x10, 0x2d, 0x19, 0xca, 0x1d, + 0x85, 0x25, 0x7a, 0x2f, 0xba, 0x2e, 0xfe, 0x34, 0xba, 0x38, 0xd3, 0x3a, + 0x02, 0x3f, 0x72, 0x3e, 0x3b, 0x41, 0xbb, 0x41, 0xb6, 0x40, 0x4d, 0x37, + 0x69, 0x29, 0x04, 0x18, 0xf2, 0x01, 0xbd, 0xed, 0x09, 0xd7, 0x62, 0xc7, + 0x49, 0xc3, 0x5d, 0xc4, 0x48, 0xc0, 0x71, 0xbd, 0xd9, 0xc2, 0xe9, 0xc7, + 0x92, 0xcb, 0xad, 0xda, 0xa3, 0xf1, 0xe4, 0xf9, 0x67, 0x01, 0x15, 0x02, + 0x3d, 0xf5, 0xf6, 0xf1, 0xc3, 0xf3, 0x34, 0xf7, 0xb6, 0xf8, 0x02, 0xf4, + 0x8c, 0xf1, 0x83, 0xf4, 0xb1, 0xf3, 0xdc, 0xf9, 0xcd, 0x01, 0x54, 0xff, + 0x88, 0xfc, 0xe9, 0xf0, 0xa2, 0xf4, 0xb2, 0x01, 0x42, 0x05, 0xef, 0x11, + 0x6f, 0x10, 0x71, 0x04, 0xc6, 0x00, 0x11, 0x01, 0xc1, 0x09, 0xac, 0x0d, + 0xae, 0x0a, 0x82, 0x0a, 0xeb, 0x07, 0x6f, 0x0a, 0x8c, 0x16, 0x8c, 0x1f, + 0xaf, 0x28, 0x01, 0x3b, 0x3d, 0x44, 0xea, 0x42, 0xd5, 0x3f, 0x71, 0x38, + 0xb5, 0x39, 0x39, 0x39, 0xfd, 0x36, 0x5c, 0x2d, 0x15, 0x18, 0x7f, 0x0d, + 0x7c, 0x05, 0xfb, 0x06, 0xf6, 0x09, 0xfb, 0x07, 0x98, 0x0b, 0xac, 0x0a, + 0x90, 0x11, 0xca, 0x18, 0x77, 0x13, 0x2d, 0x11, 0x38, 0x0d, 0xae, 0x07, + 0xe3, 0x09, 0xd9, 0x0c, 0xab, 0x13, 0x25, 0x11, 0x94, 0x01, 0x87, 0xf9, + 0x1c, 0xf2, 0xc7, 0xee, 0x7b, 0xf4, 0xe8, 0xf6, 0xc2, 0xf4, 0x02, 0xf3, + 0x22, 0xf2, 0xf2, 0xf2, 0xb4, 0xed, 0x10, 0xe8, 0x77, 0xf0, 0xd2, 0xee, + 0x01, 0xeb, 0x92, 0xf4, 0x5d, 0xf2, 0x9b, 0xf0, 0x1d, 0xf0, 0xc0, 0xe5, + 0x2a, 0xe8, 0x9b, 0xeb, 0xdc, 0xe8, 0x50, 0xf4, 0x55, 0xf6, 0xf8, 0xec, + 0xe7, 0xef, 0x7e, 0xe9, 0x7e, 0xe9, 0x38, 0xfc, 0xad, 0xfd, 0xc9, 0xfa, + 0xf2, 0xf4, 0xcf, 0xe7, 0x52, 0xe3, 0x7d, 0xdf, 0x5a, 0xe0, 0xed, 0xe0, + 0x57, 0xe9, 0xb0, 0xed, 0xc4, 0xe5, 0xc1, 0xf1, 0xc4, 0xf1, 0x03, 0xef, + 0x4e, 0xf9, 0x3b, 0xf3, 0x64, 0xf3, 0x3f, 0xfa, 0x56, 0xfa, 0x73, 0x01, + 0xe7, 0x0a, 0x02, 0x0a, 0x2b, 0x10, 0x43, 0x16, 0x02, 0x13, 0xf4, 0x17, + 0x7f, 0x1b, 0xe2, 0x21, 0x88, 0x29, 0x6a, 0x2c, 0xdb, 0x2f, 0xdf, 0x34, + 0xa6, 0x32, 0x8d, 0x2d, 0xd4, 0x21, 0x35, 0x06, 0xe2, 0xfb, 0xeb, 0xec, + 0x9f, 0xd7, 0x38, 0xd5, 0xd9, 0xd7, 0x53, 0xd6, 0x8e, 0xc5, 0x0d, 0xc2, + 0x50, 0xcb, 0xec, 0xcb, 0x84, 0xd6, 0xec, 0xf6, 0x28, 0xfe, 0x7f, 0xf1, + 0x07, 0x02, 0xd6, 0x01, 0x6a, 0xf1, 0x6a, 0xf4, 0xe7, 0xfe, 0x1b, 0x04, + 0xa1, 0x02, 0x44, 0x02, 0x3a, 0x02, 0x38, 0x00, 0x6f, 0xff, 0x8c, 0xfb, + 0x66, 0xf6, 0x0f, 0xfc, 0x0d, 0xf8, 0xbc, 0xf9, 0x0c, 0x05, 0xd0, 0xfd, + 0xba, 0xff, 0xa7, 0x05, 0x82, 0x03, 0x0a, 0x07, 0xb5, 0x11, 0xfa, 0x1a, + 0x5e, 0x26, 0x41, 0x37, 0x91, 0x37, 0xfa, 0x33, 0x24, 0x32, 0xbb, 0x2a, + 0x04, 0x30, 0xbf, 0x3a, 0x7d, 0x41, 0x38, 0x41, 0x3d, 0x3b, 0x35, 0x38, + 0xe1, 0x33, 0x7c, 0x2b, 0x8e, 0x1b, 0x0a, 0x13, 0x74, 0x0c, 0x80, 0xfd, + 0xbc, 0xfa, 0xe3, 0xf3, 0xd1, 0xe5, 0x71, 0xe3, 0xa9, 0xeb, 0xa5, 0xf1, + 0x24, 0xf2, 0xb3, 0xf2, 0x70, 0xf2, 0xe7, 0xf6, 0x6c, 0xf5, 0xba, 0xf7, + 0xec, 0x06, 0x14, 0x12, 0x85, 0x18, 0x81, 0x1b, 0x29, 0x1b, 0xf1, 0x17, + 0xbd, 0x11, 0x53, 0x0b, 0xd3, 0x04, 0xf6, 0xf9, 0xd3, 0xf9, 0x43, 0xfc, + 0xbc, 0xf1, 0x61, 0xe6, 0x82, 0xdb, 0xf0, 0xde, 0x22, 0xe4, 0x32, 0xe7, + 0xc5, 0xf5, 0xb0, 0xf7, 0x0a, 0xf2, 0x21, 0xf2, 0x55, 0xef, 0x8b, 0xf5, + 0xdd, 0x05, 0xc8, 0x0e, 0xaa, 0x17, 0xa4, 0x1a, 0x70, 0x14, 0x5a, 0x16, + 0x6a, 0x1b, 0x6b, 0x1b, 0xfe, 0x14, 0x0a, 0x09, 0x76, 0xff, 0x84, 0xf7, + 0x3f, 0xed, 0x9a, 0xed, 0xb1, 0xe6, 0xae, 0xd9, 0xa9, 0xde, 0x92, 0xe0, + 0x03, 0xe5, 0x55, 0xec, 0x55, 0xe7, 0x76, 0xe5, 0xcc, 0xe6, 0x94, 0xdd, + 0xa0, 0xdd, 0x5e, 0xe2, 0xe0, 0xde, 0xd0, 0xeb, 0x3b, 0xf5, 0x9d, 0xf8, + 0xeb, 0x04, 0x3d, 0x11, 0x86, 0x16, 0x35, 0x1a, 0x58, 0x24, 0x3a, 0x26, + 0x4b, 0x20, 0x2f, 0x16, 0xf8, 0x13, 0x90, 0x10, 0xe1, 0x0c, 0x29, 0x16, + 0xf4, 0x1b, 0x2b, 0x1a, 0x32, 0x10, 0x46, 0x0f, 0xed, 0x01, 0xa0, 0xec, + 0x2a, 0xed, 0xc2, 0xe3, 0xaa, 0xce, 0x2e, 0xc6, 0x96, 0xcb, 0x0b, 0xc9, + 0xd6, 0xc5, 0x42, 0xce, 0x94, 0xdb, 0x00, 0xdd, 0xaf, 0xdb, 0xdd, 0xfe, + 0x52, 0x18, 0x93, 0x13, 0x21, 0x1a, 0x79, 0x22, 0x2a, 0x1c, 0x11, 0x11, + 0xc8, 0x1a, 0x34, 0x26, 0x18, 0x19, 0xb1, 0x14, 0x4e, 0x19, 0x89, 0x0d, + 0x37, 0x04, 0x41, 0x0a, 0x79, 0x0d, 0x30, 0x05, 0x17, 0xfc, 0x61, 0xf9, + 0x90, 0xfa, 0xa6, 0xfb, 0x03, 0xfd, 0x6a, 0xff, 0xcd, 0xfc, 0xd0, 0xf9, + 0xd2, 0xfe, 0x90, 0x04, 0x12, 0x09, 0xcd, 0x0a, 0xf6, 0x08, 0x93, 0x08, + 0xad, 0x08, 0xb0, 0x0f, 0x6f, 0x15, 0x99, 0x1f, 0x8f, 0x30, 0x51, 0x32, + 0xab, 0x30, 0xeb, 0x34, 0x3d, 0x3e, 0x1b, 0x3d, 0x55, 0x31, 0xea, 0x2e, + 0x8c, 0x26, 0x79, 0x1a, 0x45, 0x16, 0xab, 0x14, 0xae, 0x0b, 0xbb, 0xfe, + 0xd9, 0xfa, 0x35, 0xfc, 0x01, 0xf4, 0x99, 0xeb, 0xbb, 0xf3, 0x9b, 0xf1, + 0x06, 0xea, 0x42, 0xed, 0x65, 0xf0, 0x06, 0xf8, 0x69, 0xfd, 0x54, 0x02, + 0xd2, 0x05, 0x68, 0xfd, 0xeb, 0xf2, 0x24, 0xf7, 0x14, 0x02, 0x48, 0x07, + 0x84, 0x08, 0x6c, 0x00, 0x94, 0xf6, 0xab, 0xed, 0xad, 0xf0, 0x4b, 0xf8, + 0xcd, 0xf3, 0xab, 0xf5, 0x1b, 0xf1, 0x92, 0xe7, 0x90, 0xe2, 0xed, 0xe4, + 0x7d, 0xf1, 0x09, 0xf5, 0x4d, 0xf9, 0xf8, 0xfa, 0x7b, 0xf9, 0x88, 0xf9, + 0xc9, 0xfb, 0x82, 0x0b, 0xae, 0x14, 0x12, 0x15, 0xce, 0x19, 0xf9, 0x1c, + 0xc6, 0x1a, 0x75, 0x1b, 0x2d, 0x1d, 0x61, 0x19, 0x9c, 0x10, 0x23, 0x08, + 0xb6, 0x00, 0x74, 0xf6, 0x25, 0xf2, 0xa4, 0xe9, 0xd3, 0xe2, 0xff, 0xe4, + 0xa7, 0xe7, 0xe0, 0xe7, 0x0b, 0xe5, 0xf1, 0xe8, 0x43, 0xed, 0x69, 0xf7, + 0x8e, 0xf6, 0xe8, 0xf0, 0xdf, 0xf8, 0xe6, 0xf5, 0xee, 0xf5, 0x36, 0xf6, + 0x7a, 0xf4, 0x29, 0xfe, 0x90, 0x02, 0xa8, 0xfe, 0x0f, 0x00, 0xdd, 0x00, + 0x93, 0xfd, 0x79, 0x02, 0x14, 0x09, 0xce, 0x0e, 0x05, 0x19, 0xe6, 0x1d, + 0x4a, 0x18, 0xa6, 0x0d, 0x38, 0xfb, 0xa9, 0xe6, 0xed, 0xd4, 0x21, 0xc7, + 0xf0, 0xc3, 0xb7, 0xcc, 0xe9, 0xce, 0x17, 0xc5, 0xee, 0xcc, 0x00, 0xd8, + 0x98, 0xdc, 0xce, 0xe2, 0xc2, 0xf4, 0x1c, 0x12, 0xd8, 0x1a, 0xce, 0x20, + 0x11, 0x29, 0x1a, 0x1d, 0x9c, 0x07, 0x37, 0x08, 0xa5, 0x0d, 0x1c, 0x07, + 0xa6, 0x08, 0x19, 0x0c, 0x47, 0x08, 0x84, 0xfb, 0x8b, 0xfe, 0x71, 0x03, + 0xa0, 0x01, 0x7e, 0x07, 0xbd, 0x06, 0x3a, 0x07, 0x5d, 0x07, 0x73, 0x07, + 0x65, 0x0b, 0x9c, 0x11, 0x1e, 0x14, 0xef, 0x13, 0xec, 0x11, 0x0f, 0x0f, + 0x29, 0x0d, 0x37, 0x08, 0x93, 0x09, 0x4b, 0x0b, 0xb0, 0x0f, 0xe9, 0x13, + 0x8d, 0x12, 0xb9, 0x12, 0x62, 0x1a, 0xcb, 0x1c, 0x24, 0x19, 0xd0, 0x1d, + 0x1d, 0x17, 0x04, 0x13, 0xc2, 0x10, 0xa0, 0x0a, 0xbd, 0x05, 0x9e, 0xf7, + 0xaf, 0xf4, 0x5b, 0xf5, 0x0d, 0xf6, 0xbe, 0xfa, 0xea, 0x01, 0xc0, 0x0b, + 0xf1, 0x0b, 0x30, 0x0c, 0xba, 0x10, 0xf1, 0x17, 0x5e, 0x1b, 0xd9, 0x14, + 0x65, 0x0f, 0x96, 0x05, 0x19, 0xff, 0x7a, 0x01, 0x9e, 0xfb, 0x5f, 0xf3, + 0x6d, 0xec, 0x03, 0xe1, 0x57, 0xd7, 0x2e, 0xdb, 0x7c, 0xe4, 0xc3, 0xec, + 0x33, 0xef, 0x05, 0xea, 0x18, 0xed, 0x9d, 0xeb, 0x65, 0xee, 0xc6, 0xf5, + 0x15, 0xf5, 0x84, 0xfa, 0xa3, 0xf7, 0xb7, 0xf0, 0x99, 0xeb, 0x0d, 0xef, + 0x8c, 0x02, 0x1a, 0x0c, 0xe5, 0x0a, 0xea, 0x0a, 0xf3, 0x10, 0x9a, 0x18, + 0x35, 0x19, 0xd8, 0x1c, 0x38, 0x1f, 0x90, 0x19, 0xdd, 0x11, 0x20, 0x10, + 0x8e, 0x15, 0x97, 0x17, 0xb4, 0x17, 0x6a, 0x10, 0xaa, 0x06, 0x55, 0x00, + 0x90, 0xfc, 0x4c, 0x00, 0x08, 0xf8, 0x44, 0xea, 0x5f, 0xe8, 0xf9, 0xee, + 0x7f, 0xee, 0x4b, 0xf1, 0x22, 0x02, 0x9d, 0x06, 0x90, 0x05, 0x57, 0x05, + 0x0a, 0x05, 0xfb, 0x10, 0x17, 0x18, 0xde, 0x0f, 0x96, 0x0e, 0x1f, 0x0d, + 0x25, 0x00, 0xc9, 0xfd, 0x66, 0x04, 0x29, 0x06, 0x71, 0x04, 0x98, 0x08, + 0xb7, 0x07, 0xca, 0x05, 0xa2, 0x0c, 0x1d, 0x0b, 0x53, 0x07, 0x7f, 0x00, + 0x57, 0xf1, 0xa2, 0xe2, 0x46, 0xd6, 0x24, 0xcb, 0x80, 0xc8, 0xb3, 0xd0, + 0xb8, 0xd0, 0xd9, 0xc9, 0x05, 0xc8, 0xe4, 0xd0, 0x25, 0xdf, 0x5f, 0xe3, + 0xd3, 0xf5, 0x61, 0x13, 0x99, 0x17, 0xb5, 0x16, 0xdf, 0x20, 0x46, 0x1a, + 0xce, 0x0a, 0x46, 0x0e, 0x4b, 0x12, 0x6f, 0x0e, 0x74, 0x11, 0xf2, 0x17, + 0x1b, 0x0e, 0xc9, 0x00, 0x22, 0xfe, 0x0e, 0xf7, 0x0b, 0xf7, 0x7a, 0xf5, + 0xda, 0xf9, 0x3f, 0x04, 0x20, 0x09, 0x7b, 0x12, 0x5b, 0x1d, 0x5e, 0x27, + 0x3c, 0x1c, 0x3a, 0x1a, 0x40, 0x1e, 0xeb, 0x18, 0xdc, 0x17, 0x9e, 0x15, + 0xf7, 0x1b, 0x40, 0x16, 0xc4, 0x14, 0xd2, 0x15, 0x2a, 0x0d, 0xc0, 0x0b, + 0xab, 0x0b, 0x76, 0x0b, 0x92, 0x06, 0xbf, 0x01, 0x41, 0xff, 0x9c, 0xf8, + 0x14, 0xef, 0xb2, 0xed, 0x1b, 0xe8, 0x41, 0xe1, 0x60, 0xe1, 0x84, 0xe5, + 0xaf, 0xe5, 0x44, 0xdb, 0xc5, 0xde, 0xf1, 0xe2, 0x8d, 0xe5, 0x58, 0xf0, + 0xec, 0xfd, 0x87, 0x09, 0x1b, 0x10, 0xdb, 0x14, 0x54, 0x16, 0x2b, 0x17, + 0x48, 0x13, 0xc7, 0x1a, 0x4c, 0x1b, 0x47, 0x0d, 0x5e, 0x0a, 0x2f, 0x08, + 0x52, 0x01, 0x44, 0xfe, 0x91, 0x04, 0x00, 0x05, 0xf1, 0xfd, 0xdf, 0xf2, + 0x32, 0xeb, 0x48, 0xe7, 0x62, 0xdf, 0x1f, 0xe6, 0x39, 0xea, 0xcb, 0xe6, + 0x13, 0xe8, 0x33, 0xe5, 0xeb, 0xe5, 0x51, 0xea, 0x9a, 0xf6, 0x02, 0x04, + 0xd7, 0x04, 0x68, 0x00, 0x7b, 0xfa, 0xdf, 0xfa, 0xe7, 0x01, 0x2b, 0x0a, + 0xcf, 0x12, 0x15, 0x1c, 0x6b, 0x20, 0xfd, 0x1a, 0xcb, 0x18, 0x15, 0x1d, + 0x88, 0x1f, 0x8f, 0x1b, 0x71, 0x15, 0x48, 0x10, 0x4a, 0x0b, 0xda, 0x0b, + 0x91, 0x0d, 0x5a, 0x0a, 0xe7, 0x05, 0xf1, 0x00, 0x55, 0x04, 0xc8, 0x0c, + 0xa0, 0x00, 0xd2, 0xee, 0xef, 0xe9, 0xc6, 0xe8, 0xed, 0xec, 0x97, 0xef, + 0xfc, 0xf3, 0x5d, 0xff, 0x3f, 0xfc, 0xa7, 0xee, 0x31, 0xf2, 0x93, 0xfe, + 0x04, 0x02, 0x64, 0x08, 0x3b, 0x0e, 0xb1, 0x0a, 0x06, 0x09, 0xc2, 0x0a, + 0xb6, 0x11, 0x98, 0x1d, 0x25, 0x2b, 0xa9, 0x28, 0x7e, 0x19, 0x3b, 0x08, + 0xda, 0xe6, 0xc5, 0xd2, 0x64, 0xd3, 0x3c, 0xd1, 0x14, 0xca, 0x96, 0xc9, + 0x6e, 0xca, 0x69, 0xc5, 0x34, 0xc8, 0x0c, 0xdb, 0x14, 0xf0, 0x89, 0xf1, + 0x26, 0x04, 0x8b, 0x16, 0x39, 0x16, 0x6a, 0x1b, 0xdd, 0x1a, 0x17, 0x15, + 0x19, 0x0c, 0xb8, 0x17, 0x52, 0x18, 0x24, 0x14, 0x4d, 0x22, 0x82, 0x19, + 0xa1, 0x07, 0x3a, 0x02, 0x5f, 0x02, 0xb7, 0x01, 0x2b, 0x0e, 0x3c, 0x0b, + 0x5d, 0x07, 0x83, 0x0c, 0xc6, 0x00, 0x66, 0x02, 0x54, 0x04, 0x6b, 0x03, + 0xc2, 0x05, 0xb7, 0x08, 0xf6, 0x09, 0xc9, 0x0c, 0x12, 0x11, 0x35, 0x19, + 0x42, 0x24, 0xe0, 0x1b, 0x61, 0x1d, 0x06, 0x1f, 0xca, 0x1f, 0x1d, 0x29, + 0x38, 0x26, 0xab, 0x24, 0x4e, 0x1d, 0xf9, 0x11, 0x6f, 0x0c, 0x2c, 0x01, + 0xb9, 0xef, 0x6d, 0xea, 0xc1, 0xe4, 0x6a, 0xda, 0xff, 0xd7, 0x4c, 0xd1, + 0xe9, 0xcb, 0x2f, 0xce, 0x04, 0xd6, 0x30, 0xdb, 0x1a, 0xda, 0xf8, 0xdb, + 0x61, 0xe5, 0xf5, 0xed, 0x61, 0xf2, 0xf7, 0xf9, 0xe1, 0x06, 0x45, 0x0d, + 0xac, 0x0a, 0xa5, 0x0d, 0x0d, 0x0e, 0x25, 0x0a, 0x15, 0x08, 0x19, 0x0b, + 0x9a, 0x0b, 0x19, 0x0c, 0x51, 0x0e, 0x44, 0x03, 0xba, 0x00, 0x6d, 0x07, + 0xe1, 0x05, 0xce, 0x00, 0xd9, 0x05, 0x96, 0x08, 0xc8, 0x04, 0x59, 0x03, + 0xcc, 0xfc, 0xbd, 0xfa, 0x5a, 0xf5, 0xb8, 0xf2, 0xcb, 0xf5, 0xf0, 0xf6, + 0xba, 0xf5, 0xc5, 0xf5, 0xce, 0xfa, 0x39, 0xfc, 0x55, 0x04, 0xed, 0x08, + 0x1d, 0x0e, 0x20, 0x0e, 0xaf, 0x02, 0x10, 0x06, 0xae, 0x13, 0x7b, 0x16, + 0x6c, 0x0b, 0x9f, 0x05, 0x10, 0xfb, 0x52, 0xf5, 0x82, 0xf9, 0x6f, 0xff, + 0x24, 0x0e, 0x67, 0x0b, 0xb0, 0x09, 0x3d, 0x10, 0x22, 0x12, 0xfb, 0x1a, + 0x36, 0x22, 0xfc, 0x23, 0x46, 0x23, 0x16, 0x1e, 0x52, 0x17, 0x6a, 0x1c, + 0xcf, 0x11, 0x7f, 0xfb, 0x72, 0xf8, 0xa9, 0xed, 0x8b, 0xe6, 0x34, 0xeb, + 0x65, 0xee, 0xbe, 0xf0, 0x4a, 0xee, 0x68, 0xf3, 0x39, 0x07, 0x69, 0x1d, + 0x6f, 0x2a, 0x6a, 0x38, 0x5f, 0x39, 0x8d, 0x26, 0xab, 0x16, 0x78, 0x12, + 0xfe, 0x07, 0xca, 0xec, 0x33, 0xdb, 0x54, 0xcf, 0xa7, 0xca, 0xb6, 0xd2, + 0x59, 0xd2, 0x95, 0xcd, 0x19, 0xd0, 0xe1, 0xd7, 0xfd, 0xde, 0x47, 0xed, + 0xa7, 0x06, 0x0d, 0x12, 0xe8, 0x0a, 0x42, 0x09, 0x28, 0x03, 0x65, 0xf3, + 0x1d, 0xed, 0x56, 0xfd, 0xfc, 0x06, 0xfb, 0x01, 0x95, 0x0b, 0x89, 0x0f, + 0xe0, 0x0c, 0x75, 0x0b, 0x07, 0x12, 0x75, 0x16, 0x8d, 0x14, 0xd7, 0x10, + 0x66, 0x0c, 0xfe, 0x1a, 0xb2, 0x1a, 0xb7, 0x17, 0xbb, 0x14, 0x0f, 0x07, + 0x74, 0xfc, 0xd8, 0xf6, 0xae, 0xfd, 0x7e, 0xf7, 0x90, 0xf4, 0xb9, 0xf2, + 0x7c, 0xef, 0x4e, 0xf5, 0x9b, 0xff, 0x55, 0x0c, 0x85, 0x0e, 0x27, 0x16, + 0x7b, 0x1a, 0xa2, 0x19, 0xd6, 0x1d, 0xaf, 0x20, 0x7a, 0x1a, 0x37, 0x12, + 0xd1, 0x06, 0x22, 0xfa, 0x50, 0xf3, 0x86, 0xe6, 0x1d, 0xe7, 0x32, 0xe3, + 0xbd, 0xd5, 0x84, 0xd5, 0x46, 0xda, 0x8b, 0xe2, 0x04, 0xe7, 0xe8, 0xe6, + 0x8d, 0xe8, 0x1f, 0xe8, 0x75, 0xe3, 0x0e, 0xeb, 0xbd, 0xf1, 0x4e, 0xf6, + 0xc4, 0xfd, 0x51, 0xf6, 0x61, 0xf1, 0x1f, 0xee, 0x27, 0xef, 0x90, 0xf9, + 0xa1, 0xfa, 0xbe, 0xfa, 0xfa, 0x01, 0xbf, 0xfd, 0x73, 0xf8, 0x9c, 0xfe, + 0x29, 0xfe, 0x65, 0xfb, 0x3d, 0xf4, 0x13, 0xee, 0xfc, 0xf2, 0xb1, 0xf7, + 0xf1, 0x01, 0x31, 0x09, 0x1b, 0x04, 0xee, 0x08, 0xcd, 0x0f, 0x2a, 0x14, + 0x9e, 0x1e, 0xe7, 0x1e, 0xb6, 0x21, 0xe2, 0x2a, 0x66, 0x2a, 0x99, 0x2b, + 0x0c, 0x34, 0x53, 0x28, 0x3b, 0x19, 0x30, 0x15, 0x89, 0x05, 0x56, 0x03, + 0x65, 0x03, 0xe9, 0x07, 0x26, 0x09, 0x76, 0xf2, 0x17, 0xec, 0xe1, 0xef, + 0x78, 0xf6, 0x2d, 0x02, 0x53, 0x0b, 0x1b, 0x08, 0xd3, 0xff, 0xf2, 0xfb, + 0x68, 0xff, 0xee, 0x0f, 0x5d, 0x1e, 0x76, 0x28, 0x3f, 0x26, 0xe5, 0x24, + 0x11, 0x1f, 0x2e, 0x14, 0xb1, 0x16, 0xdd, 0x18, 0x93, 0x19, 0x10, 0x0d, + 0xfa, 0xfe, 0x9c, 0xf3, 0xec, 0xe6, 0x58, 0xe6, 0x70, 0xed, 0xaf, 0xf2, + 0x3d, 0xf5, 0x28, 0x02, 0xdb, 0x10, 0x46, 0x14, 0x92, 0x15, 0x8c, 0x19, + 0x46, 0x0d, 0x8c, 0xf6, 0xa1, 0xe7, 0x65, 0xdd, 0x7b, 0xd6, 0x9f, 0xce, + 0xdb, 0xd3, 0xf5, 0xdc, 0x86, 0xd2, 0xb0, 0xd8, 0x86, 0xee, 0x26, 0xe5, + 0xd9, 0xe0, 0x9e, 0xf9, 0x4b, 0x08, 0xb1, 0xfa, 0x9f, 0xfc, 0x73, 0x11, + 0x52, 0xf7, 0xc5, 0xe1, 0xc6, 0xed, 0xd0, 0xef, 0x0a, 0xed, 0xeb, 0xf5, + 0xbe, 0x07, 0x1c, 0x07, 0xc8, 0x02, 0xb8, 0x03, 0x7c, 0x0b, 0x50, 0x13, + 0xdc, 0x19, 0x63, 0x22, 0x5e, 0x23, 0x08, 0x2a, 0xb1, 0x23, 0x3d, 0x21, + 0x2a, 0x25, 0x98, 0x1b, 0xa9, 0x11, 0x40, 0x0b, 0x8b, 0x03, 0x28, 0xf7, + 0xae, 0xf7, 0x5c, 0xf8, 0x3e, 0xf8, 0x11, 0xfa, 0x56, 0xfb, 0x4e, 0xff, + 0x98, 0x06, 0x93, 0x10, 0xe2, 0x09, 0x3f, 0x07, 0x5b, 0x08, 0xe5, 0x08, + 0xaf, 0x0b, 0x6c, 0x09, 0x9a, 0x09, 0x37, 0x02, 0x77, 0xf8, 0x7c, 0xf1, + 0xcb, 0xee, 0xbd, 0xe9, 0x72, 0xe4, 0x83, 0xe6, 0x00, 0xe8, 0xb8, 0xea, + 0x89, 0xec, 0xb0, 0xee, 0xf6, 0xf2, 0x85, 0xf6, 0xb8, 0xf5, 0x71, 0xf1, + 0x43, 0xf1, 0x08, 0xf5, 0x75, 0xf7, 0xfc, 0xf4, 0x4f, 0xe9, 0x45, 0xdf, + 0x84, 0xdd, 0x7d, 0xdc, 0xaf, 0xdf, 0x51, 0xe4, 0x17, 0xe8, 0x1e, 0xe9, + 0x46, 0xec, 0x12, 0xf3, 0x68, 0xf6, 0xa5, 0xf5, 0x77, 0xf6, 0x62, 0x00, + 0x1a, 0x02, 0x96, 0x04, 0x53, 0x0c, 0xc5, 0x0b, 0x36, 0x0f, 0x7a, 0x10, + 0x59, 0x19, 0xbb, 0x26, 0x0e, 0x2f, 0x27, 0x3a, 0xbf, 0x37, 0x2d, 0x2e, + 0xe0, 0x22, 0x5b, 0x1b, 0xc7, 0x22, 0x88, 0x25, 0x37, 0x21, 0x09, 0x20, + 0x6c, 0x15, 0x3c, 0x06, 0xff, 0x00, 0x28, 0xfe, 0x36, 0x08, 0xd8, 0x10, + 0xaa, 0x09, 0x91, 0x04, 0xc5, 0xfd, 0x15, 0xfb, 0x63, 0xff, 0x5f, 0x0e, + 0x8f, 0x1a, 0xd2, 0x13, 0xe3, 0x08, 0x9f, 0x0a, 0x70, 0x0f, 0xfc, 0x08, + 0x8b, 0x16, 0x14, 0x1e, 0x25, 0x13, 0x6b, 0x12, 0x95, 0x10, 0x03, 0x10, + 0x07, 0x0a, 0x5f, 0x0c, 0x4b, 0x16, 0xbb, 0x16, 0xef, 0x11, 0x44, 0x11, + 0xfe, 0x11, 0x5f, 0x04, 0x74, 0xfa, 0x39, 0xfe, 0xe3, 0x05, 0x97, 0x08, + 0x04, 0x0f, 0x0c, 0x09, 0x41, 0xf8, 0xfd, 0xec, 0xbd, 0xd8, 0x53, 0xd5, + 0x98, 0xda, 0x13, 0xe3, 0x03, 0xf1, 0x3a, 0xf2, 0x8a, 0xe0, 0x9a, 0xce, + 0xc8, 0xd7, 0x1d, 0xe2, 0x88, 0xe8, 0x9a, 0xf2, 0x21, 0x02, 0xbc, 0xf3, + 0x80, 0xdf, 0xed, 0xea, 0x85, 0xe4, 0x19, 0xe9, 0xa8, 0xf0, 0xf2, 0xf1, + 0xe6, 0xee, 0x1c, 0xe3, 0xc9, 0xf0, 0x65, 0xf1, 0x94, 0xeb, 0x54, 0xf3, + 0xfc, 0xf2, 0xa1, 0xf2, 0xeb, 0xfe, 0xb7, 0x00, 0x5a, 0xfe, 0xf9, 0x09, + 0xa9, 0x07, 0x79, 0x0a, 0x67, 0x14, 0xec, 0x15, 0x97, 0x15, 0xea, 0x0d, + 0x07, 0x07, 0x31, 0x07, 0xca, 0x04, 0x8e, 0x03, 0xdc, 0x06, 0x3a, 0x01, + 0xcf, 0x01, 0x82, 0x04, 0x6d, 0x03, 0x4d, 0x06, 0x7b, 0x0b, 0x39, 0x13, + 0x04, 0x12, 0xc1, 0x0f, 0xfc, 0x09, 0x0c, 0x05, 0x22, 0x06, 0x9e, 0x03, + 0x65, 0xfe, 0x31, 0xfa, 0x59, 0xfe, 0xf7, 0xfd, 0x1e, 0xf9, 0x7a, 0xf3, + 0x0e, 0xee, 0x18, 0xe9, 0x06, 0xe2, 0xcf, 0xe1, 0x79, 0xe5, 0xfb, 0xee, + 0xcc, 0xf5, 0x74, 0xf5, 0x28, 0xf1, 0x60, 0xea, 0x76, 0xe9, 0xd9, 0xe5, + 0x84, 0xde, 0xa8, 0xd8, 0xcc, 0xd8, 0xbe, 0xd7, 0xe4, 0xd4, 0x4b, 0xdb, + 0x4c, 0xe0, 0xd4, 0xe6, 0x1d, 0xf3, 0xc5, 0xfa, 0x8d, 0xf9, 0x50, 0xf9, + 0x75, 0xfd, 0x93, 0xfe, 0xb3, 0x02, 0x1e, 0x0c, 0x18, 0x13, 0xe0, 0x10, + 0xb5, 0x12, 0x11, 0x1c, 0x6f, 0x23, 0x93, 0x28, 0xc9, 0x29, 0x55, 0x2f, + 0x4d, 0x2f, 0x26, 0x27, 0x11, 0x2d, 0x91, 0x37, 0x19, 0x3a, 0xe4, 0x36, + 0x6c, 0x2a, 0x27, 0x23, 0x0d, 0x21, 0xc0, 0x1d, 0x40, 0x22, 0xa7, 0x1e, + 0x59, 0x19, 0xba, 0x15, 0x2f, 0x0b, 0xb8, 0x07, 0xfa, 0x0e, 0x2d, 0x16, + 0x52, 0x12, 0xbd, 0x0a, 0x24, 0x03, 0xe6, 0x03, 0xd6, 0x03, 0xfd, 0x0f, + 0xd2, 0x25, 0xae, 0x1d, 0x12, 0x19, 0x2b, 0x0f, 0x74, 0x01, 0xd9, 0x0a, + 0x93, 0x11, 0x47, 0x17, 0xe9, 0x15, 0xc7, 0x08, 0x30, 0x05, 0x5c, 0x09, + 0xe2, 0x0b, 0xb6, 0x23, 0x8b, 0x2a, 0xc3, 0x1a, 0x4d, 0x17, 0x06, 0x0b, + 0x5f, 0x11, 0xdc, 0x1f, 0x6d, 0x1e, 0xe8, 0x0c, 0x31, 0xf6, 0x6c, 0xe7, + 0xe8, 0xce, 0xf1, 0xc8, 0xf2, 0xd1, 0xf7, 0xc3, 0x2d, 0xbb, 0x48, 0xca, + 0x1e, 0xcb, 0xb7, 0xce, 0xea, 0xd8, 0x47, 0xdf, 0x4b, 0xf0, 0x6d, 0xe3, + 0xa8, 0xe6, 0x1e, 0x04, 0x6a, 0xfc, 0xe1, 0xf7, 0x1d, 0xf7, 0x2d, 0xf3, + 0x92, 0xf0, 0xf1, 0xe5, 0x70, 0xfa, 0x51, 0xfc, 0xf9, 0xeb, 0x07, 0xf7, + 0x80, 0xf1, 0xd1, 0xed, 0x66, 0xef, 0x27, 0xea, 0xc8, 0xed, 0x9f, 0xee, + 0x5a, 0xe4, 0xb1, 0xef, 0xd9, 0xff, 0xf9, 0xf8, 0xc3, 0x00, 0x29, 0xfc, + 0x82, 0xf9, 0x8d, 0x00, 0xe8, 0x01, 0x4f, 0x0a, 0xea, 0x0d, 0xc0, 0x0f, + 0x98, 0x0e, 0x7b, 0x15, 0x6d, 0x0f, 0x73, 0x10, 0x3d, 0x16, 0x6a, 0x15, + 0xab, 0x1d, 0x5b, 0x1d, 0xb6, 0x23, 0xcf, 0x1e, 0xd0, 0x21, 0xc3, 0x1d, + 0xea, 0x0d, 0xaf, 0x0f, 0x7b, 0x07, 0x93, 0x01, 0x66, 0xfa, 0x03, 0xf6, + 0xa2, 0xf2, 0x90, 0xeb, 0x9a, 0xea, 0x89, 0xf2, 0xd3, 0xf8, 0x41, 0xf5, + 0x90, 0xf7, 0x76, 0xf2, 0x9f, 0xf0, 0x30, 0xf1, 0xb2, 0xec, 0x22, 0xec, + 0x70, 0xe4, 0x9f, 0xe3, 0x5d, 0xe5, 0x48, 0xdb, 0x5e, 0xd7, 0x9d, 0xda, + 0x1e, 0xd8, 0xfc, 0xd6, 0x44, 0xdc, 0xfe, 0xe0, 0xa8, 0xe2, 0xc1, 0xe5, + 0x7f, 0xe2, 0xfe, 0xe0, 0x43, 0xe5, 0x1c, 0xe9, 0xb6, 0xf7, 0xbc, 0xfd, + 0x3e, 0x04, 0x86, 0x14, 0x6d, 0x1a, 0xd5, 0x21, 0xcf, 0x2b, 0x89, 0x35, + 0x7d, 0x3a, 0xd2, 0x3a, 0xfd, 0x3b, 0xc5, 0x3a, 0x17, 0x3b, 0xec, 0x3b, + 0xb8, 0x36, 0x7c, 0x2a, 0x16, 0x26, 0x6e, 0x28, 0x00, 0x24, 0xf0, 0x1f, + 0xd7, 0x13, 0xe2, 0x03, 0x53, 0x03, 0x81, 0x04, 0xf6, 0x0e, 0x54, 0x1e, + 0xd0, 0x14, 0x03, 0x08, 0x22, 0x08, 0x57, 0x05, 0x37, 0x08, 0x98, 0x14, + 0x5d, 0x1b, 0x34, 0x20, 0x6c, 0x19, 0x8d, 0x12, 0x0c, 0x0e, 0xe8, 0x03, + 0x20, 0x17, 0x8e, 0x21, 0x54, 0x1d, 0x45, 0x22, 0xda, 0x18, 0x1a, 0x11, + 0xb6, 0x05, 0x5a, 0x02, 0xa6, 0x0a, 0xf4, 0x01, 0x4c, 0xfd, 0x9f, 0x04, + 0xa5, 0xfe, 0xff, 0xfe, 0xae, 0x10, 0x64, 0x17, 0xc3, 0x20, 0xef, 0x26, + 0xa4, 0x28, 0x51, 0x2d, 0x56, 0x24, 0x39, 0x1c, 0xc6, 0x05, 0xad, 0xe5, + 0xfe, 0xd4, 0xe5, 0xc7, 0x6a, 0xc3, 0x6d, 0xc2, 0x2a, 0xc9, 0x6e, 0xd3, + 0x05, 0xc2, 0xab, 0xba, 0x0a, 0xd0, 0x0b, 0xd9, 0x9f, 0xe1, 0xf5, 0xf8, + 0x8f, 0x03, 0x7b, 0xf8, 0xad, 0xf4, 0x01, 0xfc, 0xe9, 0xeb, 0x0f, 0xda, + 0x20, 0xe7, 0x37, 0xe7, 0xb2, 0xd7, 0x3d, 0xd9, 0x34, 0xdd, 0xb0, 0xe0, + 0x0f, 0xe5, 0x90, 0xe9, 0x1c, 0xf0, 0x12, 0xf4, 0x90, 0xf5, 0xd7, 0xf7, + 0xc3, 0xfc, 0xc9, 0xff, 0x31, 0xfc, 0x90, 0xf3, 0x9c, 0xf6, 0x48, 0xf5, + 0x24, 0xed, 0x22, 0xef, 0xad, 0xf0, 0xee, 0xf9, 0xb1, 0x07, 0x2a, 0x16, + 0x7e, 0x1c, 0x21, 0x1d, 0xa6, 0x21, 0x36, 0x22, 0xcc, 0x2a, 0xe9, 0x2f, + 0x22, 0x2f, 0xb9, 0x2b, 0x46, 0x24, 0x0b, 0x20, 0xa9, 0x15, 0x2d, 0x0a, + 0x9b, 0x06, 0xe9, 0x03, 0xb7, 0xfb, 0xc1, 0xf9, 0xd6, 0xff, 0x46, 0x03, + 0xde, 0xff, 0x2f, 0xfc, 0x03, 0xfa, 0xf8, 0xf2, 0x06, 0xf4, 0xb7, 0xfb, + 0x8d, 0xff, 0x4d, 0xfc, 0x8b, 0xf8, 0xa0, 0xf6, 0xdc, 0xee, 0x16, 0xe6, + 0xaf, 0xe5, 0xdc, 0xea, 0x37, 0xe6, 0x40, 0xe1, 0x58, 0xe5, 0x53, 0xe5, + 0x47, 0xdf, 0xb1, 0xde, 0x55, 0xe1, 0x3e, 0xe3, 0xdc, 0xe7, 0xdc, 0xec, + 0x3a, 0xec, 0x44, 0xe8, 0x5e, 0xf2, 0x90, 0xfc, 0xa8, 0x05, 0x67, 0x10, + 0x27, 0x17, 0x11, 0x20, 0x36, 0x21, 0x5f, 0x2a, 0x02, 0x30, 0x1f, 0x2d, + 0xbe, 0x2f, 0xa6, 0x26, 0x0f, 0x1a, 0xa1, 0x14, 0x50, 0x12, 0x04, 0x17, + 0x45, 0x1a, 0x35, 0x10, 0x79, 0x11, 0xbe, 0x16, 0xe8, 0x0f, 0x55, 0x0f, + 0x2f, 0x13, 0x47, 0x19, 0x18, 0x1f, 0x5f, 0x1d, 0x0d, 0x1a, 0x08, 0x16, + 0x62, 0x0f, 0xc4, 0x0f, 0xb3, 0x11, 0xa7, 0x17, 0x0b, 0x1d, 0x89, 0x1e, + 0x53, 0x1b, 0x9a, 0x0f, 0x8f, 0x17, 0x99, 0x1e, 0x0f, 0x1c, 0xb9, 0x1b, + 0x9c, 0x18, 0x94, 0x16, 0x91, 0x10, 0xe9, 0x01, 0xae, 0xf1, 0xa2, 0xf2, + 0xa0, 0xec, 0xd4, 0xf1, 0xdb, 0xff, 0xef, 0xff, 0x71, 0x0c, 0xc1, 0x0d, + 0xe3, 0x10, 0x4c, 0x19, 0x6b, 0x1d, 0x5b, 0x2f, 0x2a, 0x37, 0x8b, 0x33, + 0x8e, 0x3c, 0x78, 0x39, 0x9e, 0x2a, 0xa2, 0x26, 0xf8, 0x0d, 0x32, 0xf8, + 0x0f, 0xe7, 0xad, 0xc7, 0x1b, 0xc4, 0xa4, 0xc5, 0x78, 0xbd, 0x16, 0xbf, + 0xa1, 0xc4, 0x6e, 0xcc, 0xa2, 0xcb, 0x54, 0xcb, 0x1f, 0xd7, 0x1a, 0xde, + 0x10, 0xe0, 0x4c, 0xe7, 0x11, 0xec, 0x28, 0xe2, 0x33, 0xda, 0x8f, 0xdb, + 0x65, 0xe0, 0xf8, 0xdd, 0xe5, 0xde, 0xf1, 0xee, 0x68, 0xe4, 0xb2, 0xdd, + 0x8c, 0xe2, 0x33, 0xdb, 0xe2, 0xe1, 0x6a, 0xe8, 0x74, 0xf2, 0x32, 0xfc, + 0x8d, 0xfe, 0xc5, 0xf7, 0xcf, 0xee, 0xd9, 0xef, 0xec, 0xf4, 0xa9, 0xfc, + 0x4e, 0xfc, 0x31, 0x03, 0xd9, 0x03, 0xfc, 0x00, 0x5b, 0x0a, 0x64, 0x13, + 0x11, 0x20, 0x86, 0x22, 0x33, 0x2b, 0xc5, 0x38, 0x22, 0x3f, 0x23, 0x44, + 0x4b, 0x45, 0xad, 0x49, 0x8e, 0x46, 0x12, 0x40, 0x68, 0x37, 0x63, 0x2e, + 0x3c, 0x1d, 0x4d, 0x01, 0xcb, 0xf5, 0x26, 0xed, 0x1d, 0xe8, 0x5d, 0xe7, + 0x92, 0xe3, 0xcf, 0xe7, 0xaf, 0xe7, 0x12, 0xe8, 0xe4, 0xef, 0x11, 0xf8, + 0xbb, 0xf8, 0xc5, 0xf6, 0xe8, 0xf7, 0x74, 0xf6, 0x66, 0xf9, 0x4d, 0xfd, + 0x43, 0xfb, 0xa6, 0xf2, 0xef, 0xec, 0x03, 0xec, 0xdb, 0xe7, 0xdc, 0xec, + 0x3d, 0xf6, 0xa7, 0xf6, 0xf5, 0xf4, 0x78, 0xf6, 0x4a, 0xf9, 0x46, 0x00, + 0xff, 0x02, 0xe8, 0xfd, 0x3a, 0xff, 0x5a, 0xfd, 0x26, 0xfb, 0xe4, 0xfb, + 0x84, 0xf2, 0x1f, 0xe8, 0xec, 0xe4, 0x1b, 0xeb, 0x31, 0xef, 0x9d, 0xf4, + 0x92, 0xfb, 0x8c, 0xf5, 0xbd, 0xf4, 0xf4, 0xff, 0xfc, 0x12, 0xfd, 0x24, + 0x59, 0x26, 0x7f, 0x1c, 0x75, 0x16, 0x2e, 0x12, 0x85, 0x0e, 0xf9, 0x18, + 0x7a, 0x21, 0x1f, 0x1c, 0x7d, 0x17, 0xe0, 0x19, 0x4e, 0x1c, 0x81, 0x23, + 0x6a, 0x2e, 0x2c, 0x2c, 0x3b, 0x28, 0x87, 0x26, 0x14, 0x26, 0xe0, 0x25, + 0x24, 0x1e, 0x99, 0x1e, 0x05, 0x1f, 0x29, 0x14, 0x13, 0x11, 0x47, 0x12, + 0x0b, 0x10, 0xd1, 0x0e, 0x93, 0x0f, 0x5e, 0x10, 0xc8, 0x06, 0x23, 0x0a, + 0xc4, 0x15, 0x97, 0x0c, 0x23, 0x0a, 0x95, 0x0e, 0x0f, 0x10, 0x22, 0x16, + 0x90, 0x1a, 0xac, 0x1e, 0x72, 0x26, 0x97, 0x28, 0x33, 0x26, 0xaa, 0x26, + 0xca, 0x21, 0xae, 0x26, 0x9c, 0x2a, 0xf6, 0x19, 0x6b, 0x01, 0xa2, 0xeb, + 0x2d, 0xe4, 0xe0, 0xdb, 0x88, 0xcf, 0x29, 0xc7, 0xef, 0xb9, 0xd1, 0xa7, + 0x9a, 0xa0, 0xaa, 0xa7, 0x79, 0xae, 0x09, 0xbc, 0xea, 0xc8, 0xd6, 0xc9, + 0x0d, 0xca, 0xd7, 0xce, 0x90, 0xd7, 0xad, 0xe2, 0xb7, 0xea, 0x86, 0xef, + 0x84, 0xf1, 0x21, 0xe8, 0x6c, 0xe3, 0x9a, 0xe6, 0x8b, 0xe6, 0x6d, 0xe7, + 0x98, 0xe1, 0x2d, 0xe8, 0x2c, 0xf7, 0x4c, 0xf0, 0xef, 0xed, 0x63, 0xf3, + 0xa6, 0xf0, 0xaf, 0xf3, 0x93, 0xf5, 0xc1, 0xf7, 0x19, 0xfb, 0x2a, 0xfb, + 0x24, 0x09, 0x2f, 0x0f, 0x26, 0x0e, 0x02, 0x1b, 0x26, 0x22, 0xb0, 0x2e, + 0x1a, 0x3a, 0x0e, 0x3e, 0xa6, 0x4b, 0xb8, 0x52, 0x65, 0x55, 0x18, 0x59, + 0xff, 0x57, 0x7b, 0x56, 0x40, 0x55, 0xe8, 0x48, 0x40, 0x38, 0x55, 0x2c, + 0xe2, 0x19, 0xdf, 0x09, 0xf3, 0xfc, 0xcf, 0xf1, 0xeb, 0xe6, 0x0f, 0xdd, + 0x18, 0xda, 0xec, 0xda, 0xd8, 0xe2, 0xa9, 0xeb, 0x7e, 0xf3, 0xcf, 0xf7, + 0x14, 0xfc, 0xf4, 0xff, 0xfe, 0x02, 0x85, 0x07, 0x7e, 0x0e, 0xfe, 0x17, + 0x2a, 0x13, 0xf7, 0x0b, 0x70, 0x07, 0xda, 0x02, 0x57, 0xff, 0x1c, 0xf7, + 0x35, 0xf1, 0x50, 0xec, 0x9a, 0xe6, 0x08, 0xe1, 0x4d, 0xdb, 0x0b, 0xd3, + 0x9f, 0xd0, 0x1b, 0xce, 0x30, 0xc9, 0x0d, 0xcd, 0x5e, 0xcd, 0xfd, 0xcf, + 0x7c, 0xd7, 0x71, 0xd9, 0xa3, 0xdc, 0x26, 0xe3, 0x19, 0xf0, 0x76, 0x00, + 0x82, 0xff, 0xaf, 0xfb, 0x64, 0x04, 0x21, 0x0d, 0x5c, 0x18, 0xb6, 0x1f, + 0xec, 0x22, 0x3f, 0x24, 0x31, 0x26, 0xf3, 0x30, 0x8a, 0x35, 0x41, 0x2e, + 0x18, 0x2a, 0x5a, 0x26, 0xfe, 0x1b, 0x60, 0x16, 0x5e, 0x16, 0x51, 0x19, + 0x3c, 0x1b, 0xec, 0x17, 0xeb, 0x16, 0x54, 0x14, 0x7d, 0x16, 0xb1, 0x23, + 0x26, 0x23, 0x92, 0x22, 0x51, 0x2b, 0x12, 0x22, 0xa5, 0x23, 0xe2, 0x25, + 0xde, 0x20, 0x31, 0x2d, 0x0e, 0x27, 0xd0, 0x23, 0x64, 0x21, 0xe6, 0x10, + 0x91, 0x17, 0x65, 0x12, 0x08, 0x05, 0xe7, 0x09, 0xec, 0x03, 0x09, 0x00, + 0x23, 0xff, 0x5a, 0xf5, 0x31, 0xf9, 0xcf, 0xf9, 0x92, 0xf8, 0x88, 0x03, + 0x4c, 0x02, 0x84, 0x01, 0xda, 0xfe, 0x5f, 0xf4, 0xfb, 0xf2, 0x8d, 0xe6, + 0x5e, 0xd7, 0x22, 0xd6, 0x23, 0xce, 0xff, 0xca, 0x7c, 0xd0, 0x26, 0xd0, + 0x06, 0xc4, 0x3c, 0xac, 0xdd, 0xb2, 0x64, 0xc0, 0x2a, 0xb6, 0x8c, 0xc1, + 0x97, 0xd6, 0xed, 0xd7, 0x96, 0xd3, 0xc8, 0xd7, 0x03, 0xdf, 0xc3, 0xe9, + 0x7a, 0xf2, 0xbb, 0x00, 0xa5, 0x08, 0x09, 0xf9, 0x16, 0x00, 0xc4, 0x08, + 0x33, 0x03, 0xfc, 0x06, 0x68, 0x08, 0x11, 0x09, 0xf0, 0x06, 0x83, 0x08, + 0x19, 0x0e, 0xcb, 0x14, 0x73, 0x1a, 0x37, 0x1b, 0x92, 0x20, 0x48, 0x28, + 0x3f, 0x2b, 0x31, 0x30, 0x76, 0x36, 0x5e, 0x39, 0x39, 0x3b, 0xbe, 0x32, + 0xf9, 0x2d, 0x97, 0x2f, 0x56, 0x29, 0xd2, 0x28, 0x61, 0x2a, 0x28, 0x2a, + 0xe0, 0x30, 0x0a, 0x33, 0x64, 0x31, 0x6d, 0x31, 0x12, 0x2f, 0xb2, 0x29, + 0x85, 0x1e, 0xce, 0x17, 0x52, 0x0b, 0x68, 0x01, 0x06, 0xff, 0x23, 0xf5, + 0xcf, 0xf0, 0x3e, 0xed, 0x2c, 0xf4, 0xbf, 0xf6, 0x8e, 0xf4, 0x90, 0xf9, + 0x70, 0xf9, 0x9b, 0x01, 0x15, 0x04, 0x12, 0xfe, 0xf3, 0xf0, 0xd0, 0xea, + 0x73, 0xea, 0xb6, 0xe2, 0xc6, 0xdc, 0xd0, 0xce, 0xfc, 0xca, 0x56, 0xc7, + 0x17, 0xc1, 0xeb, 0xc8, 0x2c, 0xd0, 0x63, 0xd1, 0x97, 0xcd, 0xec, 0xcb, + 0x30, 0xca, 0x8d, 0xcc, 0x1a, 0xd5, 0x43, 0xdc, 0xb7, 0xde, 0x5c, 0xe1, + 0xf4, 0xe8, 0x58, 0xf0, 0x5d, 0xfc, 0x11, 0x06, 0xc0, 0x0a, 0x7d, 0x0d, + 0xd9, 0x0a, 0x62, 0x11, 0xc8, 0x1f, 0xaf, 0x23, 0x38, 0x25, 0x74, 0x29, + 0x1b, 0x25, 0x65, 0x26, 0xb8, 0x33, 0x2a, 0x3a, 0xcc, 0x38, 0x41, 0x30, + 0x53, 0x24, 0xbb, 0x20, 0xa1, 0x20, 0x98, 0x23, 0x69, 0x26, 0xde, 0x23, + 0x86, 0x22, 0x1d, 0x1e, 0x04, 0x1c, 0x9a, 0x24, 0x54, 0x2d, 0xdd, 0x2c, + 0x54, 0x28, 0x1c, 0x23, 0x00, 0x1e, 0x4c, 0x1c, 0xd7, 0x1a, 0xbf, 0x1e, + 0x71, 0x1b, 0x85, 0x0e, 0x0a, 0x04, 0xdc, 0xfa, 0xdd, 0xfb, 0xe8, 0xfe, + 0x64, 0x01, 0x63, 0xf5, 0x8a, 0xe0, 0x37, 0xda, 0xb9, 0xd6, 0x62, 0xdc, + 0x0b, 0xe2, 0xb0, 0xe0, 0x9f, 0xe3, 0x9e, 0xe5, 0xdf, 0xe2, 0xe6, 0xec, + 0xe5, 0xfb, 0x1f, 0x01, 0x61, 0x09, 0xc6, 0x07, 0xef, 0x08, 0xd0, 0x03, + 0xd6, 0xfa, 0x7e, 0xff, 0x7c, 0xf3, 0xce, 0xe1, 0xb7, 0xd0, 0xd8, 0xca, + 0x75, 0xcf, 0xd0, 0xd0, 0x52, 0xd0, 0x89, 0xc2, 0xea, 0xb7, 0x21, 0xb7, + 0x2b, 0xb9, 0x64, 0xc6, 0xd4, 0xe0, 0xf9, 0xf2, 0xeb, 0xf5, 0xcb, 0xf9, + 0x75, 0xfc, 0x14, 0xff, 0x0a, 0x07, 0x5a, 0x12, 0x05, 0x23, 0x31, 0x2c, + 0xd1, 0x2c, 0x0e, 0x2e, 0x2a, 0x26, 0x47, 0x22, 0xe9, 0x17, 0x85, 0x0f, + 0x8a, 0x19, 0x5f, 0x22, 0x93, 0x4a, 0x6e, 0x6c, 0x46, 0x6a, 0xbc, 0x65, + 0x9d, 0x48, 0x61, 0x18, 0x5b, 0x02, 0xc2, 0x1a, 0xe4, 0x16, 0xfb, 0xea, + 0x68, 0xcd, 0xa6, 0xb9, 0x46, 0xe7, 0x74, 0x31, 0x4d, 0x22, 0xcc, 0xff, + 0xaa, 0x20, 0x56, 0x50, 0xd8, 0x66, 0x6b, 0x44, 0x8e, 0x1f, 0xe7, 0x37, + 0x0d, 0x3b, 0xd1, 0x1b, 0xc3, 0x00, 0xf0, 0xfb, 0xd4, 0xec, 0x84, 0xcf, + 0xf1, 0xe3, 0x40, 0xff, 0x54, 0xf4, 0xa1, 0xd5, 0xaa, 0xd0, 0xf3, 0xde, + 0x4c, 0xe0, 0xca, 0xe5, 0x9a, 0xd9, 0x77, 0xc5, 0x8e, 0xcf, 0xb3, 0xd3, + 0x4b, 0xc9, 0xc2, 0xce, 0xbc, 0xd0, 0x20, 0xcd, 0x20, 0xd9, 0x0b, 0xfc, + 0x4e, 0x22, 0x0d, 0x38, 0x6b, 0x38, 0x97, 0x1f, 0x2e, 0xff, 0xf8, 0xeb, + 0xa9, 0xe3, 0x26, 0xd1, 0x82, 0xc8, 0x0d, 0xd1, 0x85, 0xe2, 0x04, 0xfa, + 0x61, 0x05, 0x59, 0x0b, 0x55, 0x12, 0x21, 0x0f, 0x67, 0x00, 0x59, 0x03, + 0xbb, 0xfc, 0xb3, 0xe7, 0x22, 0xf0, 0xa5, 0x09, 0xb9, 0x27, 0xfa, 0x3a, + 0xfe, 0x2e, 0x34, 0x18, 0xc9, 0x22, 0x71, 0x40, 0xf7, 0x55, 0x6d, 0x61, + 0xf2, 0x59, 0x9a, 0x3f, 0xff, 0x26, 0x17, 0x31, 0xda, 0x46, 0x51, 0x48, + 0x1b, 0x4e, 0x79, 0x41, 0xb7, 0x05, 0xd0, 0xe4, 0x8f, 0xdc, 0x4c, 0xc3, + 0x2c, 0xc0, 0x7c, 0xce, 0xc0, 0xe1, 0xfa, 0xf3, 0xfd, 0xf4, 0x25, 0xf8, + 0xb3, 0xff, 0x4b, 0x06, 0x5c, 0x0e, 0xf9, 0x01, 0xaf, 0xf2, 0x64, 0xe8, + 0x63, 0xde, 0xc9, 0xe8, 0x92, 0xed, 0x07, 0xe2, 0x55, 0xdd, 0xb0, 0xe0, + 0x78, 0xe2, 0x3e, 0xe4, 0xe9, 0xe1, 0xe6, 0xe1, 0x34, 0xd8, 0xb3, 0xd0, + 0x84, 0xe7, 0xf0, 0xf9, 0x49, 0x0b, 0x03, 0x1b, 0x87, 0x24, 0xdf, 0x20, + 0xb5, 0x15, 0xc8, 0x1c, 0x84, 0x10, 0xcb, 0x04, 0x5a, 0x01, 0x4d, 0xed, + 0x6c, 0xed, 0x12, 0xf8, 0x0c, 0x02, 0x65, 0x13, 0x28, 0x0c, 0xc3, 0xfa, + 0x0d, 0xfb, 0xed, 0x01, 0x30, 0x04, 0x75, 0xfe, 0x03, 0x00, 0xb5, 0x00, + 0x62, 0xfc, 0x9e, 0xf9, 0xcf, 0xe5, 0x96, 0xd3, 0x49, 0xe0, 0x52, 0xf5, + 0x09, 0x06, 0xf7, 0x0c, 0x95, 0x16, 0xc6, 0x32, 0xe5, 0x2d, 0x2c, 0x18, + 0x6d, 0x16, 0xff, 0x20, 0x06, 0x2d, 0x01, 0x24, 0xf9, 0x23, 0xf5, 0x25, + 0x1b, 0x18, 0x02, 0x13, 0x84, 0x19, 0x9f, 0x21, 0xda, 0x20, 0x9d, 0x15, + 0xde, 0x00, 0xb8, 0xec, 0xea, 0xdd, 0x7d, 0xd8, 0x15, 0xde, 0xb6, 0xe6, + 0x4c, 0xed, 0x8d, 0xeb, 0xee, 0xe2, 0x36, 0xe5, 0x1b, 0xef, 0x4c, 0xec, + 0xb1, 0xec, 0xd6, 0xee, 0x5b, 0xee, 0x89, 0xea, 0x1e, 0xdc, 0xb4, 0xc6, + 0xe5, 0x9e, 0x60, 0x88, 0x4f, 0x8b, 0x85, 0x95, 0xd8, 0xaa, 0xf9, 0xc9, + 0x73, 0x1c, 0xe8, 0x69, 0x67, 0x74, 0xcc, 0x66, 0x41, 0x26, 0x19, 0xc6, + 0x14, 0x96, 0x44, 0x90, 0x86, 0xa2, 0xec, 0xc2, 0x4b, 0xe0, 0xe5, 0xf7, + 0x1f, 0x03, 0xab, 0x06, 0x44, 0x07, 0x2e, 0xf5, 0x3a, 0xe0, 0x9d, 0xe0, + 0x29, 0xe7, 0x15, 0xf0, 0x41, 0xfd, 0x39, 0x04, 0xbd, 0x0a, 0x8c, 0x0c, + 0x26, 0x09, 0x67, 0x0a, 0x08, 0x0a, 0x8a, 0x0c, 0x05, 0x10, 0x64, 0x0c, + 0x24, 0x0b, 0x6e, 0x0e, 0x60, 0x10, 0xc8, 0x10, 0x80, 0x18, 0x47, 0x25, + 0xd7, 0x2b, 0xa6, 0x29, 0x27, 0x20, 0x1f, 0x19, 0xb5, 0x12, 0xb8, 0x0d, + 0x98, 0x12, 0xaa, 0x17, 0xbc, 0x19, 0x15, 0x11, 0x84, 0x05, 0xa5, 0x07, + 0x59, 0x09, 0x0c, 0x06, 0x0d, 0x00, 0x25, 0x01, 0x00, 0x0d, 0x36, 0x14, + 0x1f, 0x14, 0x1a, 0x11, 0x5a, 0x0f, 0x7a, 0x0b, 0x85, 0x04, 0x44, 0x01, + 0x47, 0x0a, 0xb6, 0x1a, 0xcf, 0x23, 0xa7, 0x1f, 0xe2, 0x1a, 0xfe, 0x23, + 0x56, 0x2d, 0xff, 0x2c, 0xfd, 0x22, 0x5d, 0x18, 0x37, 0x1f, 0x96, 0x33, + 0x17, 0x3c, 0x5f, 0x3e, 0xe4, 0x48, 0x84, 0x52, 0xdc, 0x56, 0x93, 0x3e, + 0x07, 0x28, 0xd1, 0x2f, 0x03, 0x3d, 0xe3, 0x55, 0x88, 0x6b, 0x03, 0x74, + 0x32, 0x75, 0x5e, 0x74, 0xc1, 0x70, 0xb7, 0x64, 0x53, 0x63, 0x37, 0x6e, + 0x79, 0x6b, 0x91, 0x52, 0x15, 0x45, 0x89, 0x4a, 0x18, 0x4c, 0xd6, 0x4c, + 0xde, 0x5d, 0x15, 0x64, 0x68, 0x44, 0x13, 0x25, 0x80, 0x13, 0x10, 0x19, + 0x21, 0x2d, 0x53, 0x3a, 0x5e, 0x4e, 0x99, 0x4f, 0x36, 0x4a, 0x77, 0x5a, + 0xda, 0x54, 0x73, 0x2e, 0x1b, 0x16, 0x07, 0x1c, 0x74, 0x2f, 0xd7, 0x34, + 0x37, 0x21, 0xc0, 0x0d, 0x70, 0xf8, 0xdd, 0xef, 0x07, 0xf8, 0x68, 0xf2, + 0x80, 0xf1, 0x20, 0xf3, 0xd6, 0xea, 0x09, 0xe3, 0xe5, 0xe1, 0xaa, 0xe3, + 0x92, 0xde, 0x6a, 0xdb, 0x68, 0xdd, 0x89, 0xea, 0x24, 0xfb, 0xc4, 0xfb, + 0xcc, 0xf9, 0xcc, 0xfd, 0xf9, 0x03, 0x81, 0x17, 0x59, 0x22, 0x31, 0x0c, + 0x21, 0xff, 0xae, 0x08, 0xbe, 0x0d, 0xae, 0x0e, 0xc6, 0x14, 0x2e, 0x19, + 0x1b, 0x15, 0x58, 0x1c, 0x49, 0x23, 0x61, 0x1c, 0xa4, 0x10, 0x40, 0x05, + 0x40, 0x04, 0x4a, 0xf8, 0xdb, 0xe6, 0x55, 0xdd, 0xc0, 0xd8, 0x31, 0xd1, + 0x14, 0xc1, 0x1d, 0xc4, 0x79, 0xd3, 0x40, 0xec, 0x63, 0x0d, 0x58, 0x1c, + 0xa4, 0x16, 0x6f, 0x0b, 0x0a, 0xf8, 0x8a, 0xd6, 0x2b, 0xcc, 0x1f, 0xe1, + 0x82, 0xef, 0xea, 0xe7, 0xc5, 0xd4, 0xd4, 0xbf, 0x31, 0xb5, 0x4c, 0xb3, + 0x94, 0xae, 0xe7, 0xae, 0x80, 0xb3, 0x25, 0xb1, 0x96, 0xa7, 0xf0, 0xa2, + 0xc4, 0xa0, 0x22, 0x9f, 0x1b, 0x9f, 0xc9, 0x9c, 0xbe, 0x9b, 0x00, 0x9f, + 0x12, 0xa1, 0x55, 0x9d, 0xeb, 0x9d, 0x1f, 0xa5, 0x03, 0xb7, 0x70, 0xc2, + 0xb6, 0xbb, 0x0f, 0xb8, 0x31, 0xba, 0xbd, 0xb5, 0xf0, 0xb1, 0x27, 0xbf, + 0xee, 0xc7, 0x13, 0xc6, 0xb0, 0xc3, 0x16, 0xc1, 0xec, 0xc0, 0x7d, 0xbb, + 0x4f, 0xb8, 0x7d, 0xbc, 0x61, 0xbb, 0xe4, 0xba, 0xfe, 0xc0, 0x1c, 0xc3, + 0x13, 0xc2, 0x32, 0xb9, 0x06, 0xb3, 0x9b, 0xbc, 0x3b, 0xd3, 0x89, 0xe8, + 0x5d, 0xe6, 0xd4, 0xda, 0x3e, 0xd3, 0x52, 0xd5, 0xc9, 0xdd, 0x57, 0xdb, + 0x8c, 0xd4, 0xb5, 0xdf, 0xc6, 0xf2, 0xb7, 0x00, 0x28, 0x10, 0x09, 0x06, + 0x21, 0xf1, 0x32, 0xed, 0x17, 0xeb, 0x08, 0xe8, 0xd4, 0xd4, 0x1f, 0xc7, + 0xd6, 0xe0, 0xd0, 0xf6, 0x2a, 0xf5, 0xc0, 0xf7, 0x8e, 0x11, 0xe3, 0x41, + 0x95, 0x55, 0x1e, 0x38, 0x33, 0x14, 0x6f, 0xfc, 0x87, 0xf0, 0xf0, 0xec, + 0x79, 0xdd, 0x9a, 0xc4, 0x1a, 0xc0, 0x8e, 0xd7, 0xd2, 0xdf, 0x8c, 0xc3, + 0xc6, 0xb3, 0xdc, 0xae, 0x7a, 0x9b, 0xc8, 0x98, 0xbb, 0xae, 0xbf, 0xc6, + 0x17, 0xc5, 0xca, 0xa8, 0xb9, 0xa1, 0x72, 0xa7, 0x9e, 0xa9, 0x66, 0xc5, + 0xe2, 0xdb, 0x20, 0xe6, 0x9d, 0xed, 0xa6, 0xe8, 0x98, 0xe6, 0x90, 0xe9, + 0x6d, 0xf9, 0x28, 0x0b, 0x25, 0x0c, 0x60, 0x08, 0x6d, 0x0f, 0x91, 0x0f, + 0x7e, 0x0a, 0x9a, 0x18, 0x6c, 0x22, 0x9b, 0x14, 0x6a, 0x06, 0xf4, 0x1b, + 0x56, 0x47, 0x7d, 0x5f, 0x52, 0x4f, 0x45, 0x26, 0x68, 0x1f, 0x4c, 0x50, + 0xf7, 0x77, 0x47, 0x79, 0xf0, 0x73, 0xeb, 0x6a, 0xab, 0x6c, 0x03, 0x70, + 0x2b, 0x6f, 0xe0, 0x6e, 0xb9, 0x6c, 0xad, 0x6a, 0x07, 0x69, 0x24, 0x73, + 0xb8, 0x73, 0x55, 0x75, 0x87, 0x71, 0xf0, 0x6a, 0x11, 0x62, 0x53, 0x4b, + 0xbf, 0x3e, 0xfc, 0x2b, 0x31, 0x24, 0xb9, 0x1a, 0x9d, 0x16, 0x9d, 0x28, + 0x5a, 0x34, 0x3c, 0x38, 0x49, 0x29, 0xe2, 0x1b, 0xd6, 0x17, 0xa3, 0x0e, + 0xf3, 0xf7, 0x8e, 0xf4, 0x2e, 0x01, 0xb6, 0xfb, 0x80, 0x05, 0x9e, 0x18, + 0x34, 0x11, 0x00, 0xf9, 0xa3, 0xf2, 0x27, 0xf7, 0xa4, 0xfe, 0x80, 0x06, + 0x89, 0xfe, 0xab, 0xfa, 0xec, 0x03, 0xd2, 0x00, 0x36, 0xf2, 0x13, 0xed, + 0xc6, 0xeb, 0x4e, 0xfa, 0x73, 0x0d, 0x3e, 0x0e, 0xbf, 0x11, 0x7e, 0x16, + 0x68, 0x0e, 0xfb, 0x0d, 0x4f, 0x29, 0xca, 0x48, 0x56, 0x53, 0x51, 0x5c, + 0x7d, 0x6b, 0x5e, 0x76, 0xe5, 0x64, 0xbb, 0x27, 0xa1, 0x24, 0x07, 0x5d, + 0x0b, 0x6b, 0x56, 0x4c, 0x3e, 0x1a, 0xdd, 0x16, 0x07, 0x43, 0x80, 0x65, + 0xdf, 0x4f, 0xd1, 0x2f, 0x9f, 0x4e, 0x94, 0x52, 0xc7, 0x2f, 0xeb, 0x2c, + 0xa5, 0x49, 0x66, 0x71, 0x9b, 0x6d, 0x39, 0x28, 0x9a, 0xf8, 0x55, 0x05, + 0xc6, 0x1d, 0x04, 0x34, 0xd6, 0x34, 0x0e, 0x3b, 0x19, 0x4d, 0x29, 0x55, + 0xb2, 0x6d, 0xd2, 0x64, 0x54, 0x3a, 0xb9, 0x16, 0x5e, 0xfa, 0xde, 0x09, + 0x2b, 0x12, 0x8f, 0xf3, 0x73, 0xe2, 0xa3, 0xdc, 0x36, 0xde, 0x0b, 0xe3, + 0x02, 0xe4, 0xac, 0xe9, 0xb0, 0xf3, 0x4f, 0x09, 0x26, 0x22, 0xe2, 0x14, + 0x7b, 0xf8, 0xb0, 0xda, 0x5c, 0xb2, 0x55, 0xb4, 0xfb, 0xba, 0xb8, 0xb5, + 0x62, 0xbb, 0x0c, 0xb7, 0xf4, 0xb8, 0x53, 0xb2, 0x6b, 0xa8, 0x38, 0xa6, + 0x19, 0x99, 0x17, 0x9e, 0x40, 0xb7, 0x85, 0xba, 0xf6, 0xd5, 0x70, 0xed, + 0xfc, 0xb7, 0x38, 0x9a, 0xe6, 0xa7, 0x7e, 0xb3, 0x62, 0xba, 0xb6, 0xc8, + 0xcf, 0xf5, 0x06, 0x15, 0xe3, 0x15, 0x9d, 0xfc, 0x77, 0xd7, 0x4c, 0xc6, + 0xb6, 0xba, 0xc0, 0xa7, 0xab, 0xac, 0xd0, 0xc0, 0xb6, 0xd0, 0x8d, 0xe1, + 0xa3, 0xe6, 0x8b, 0x08, 0xa7, 0x1a, 0xf7, 0xe0, 0x18, 0xb6, 0x95, 0xbe, + 0x7b, 0xd0, 0x04, 0xe6, 0x4c, 0xf7, 0xd9, 0xed, 0xec, 0xe7, 0xa3, 0xea, + 0xeb, 0xdf, 0x8f, 0xe4, 0xb6, 0xf4, 0x11, 0x00, 0xd8, 0x05, 0xb3, 0xee, + 0xc4, 0xce, 0x2a, 0xcc, 0x8b, 0xd7, 0x35, 0xcf, 0x0f, 0xbc, 0x06, 0xba, + 0xe5, 0xbf, 0xf1, 0xcf, 0xe9, 0xd0, 0xfb, 0xb5, 0xdb, 0xa8, 0x2d, 0xb1, + 0x85, 0xbf, 0x7d, 0xbb, 0xa1, 0xb1, 0x5a, 0xa5, 0x4d, 0x9d, 0xf5, 0xb5, + 0xe7, 0xcc, 0xf3, 0xc6, 0xb3, 0xb2, 0xef, 0xa9, 0x3f, 0xb7, 0x07, 0xc9, + 0xf6, 0xd6, 0x8c, 0xdd, 0xb9, 0xd2, 0xd1, 0xd1, 0x5d, 0xea, 0x88, 0x09, + 0xac, 0x19, 0xab, 0xfc, 0x78, 0xcd, 0x60, 0xc2, 0xed, 0xdb, 0xb8, 0xec, + 0xe4, 0xe4, 0x71, 0xe3, 0xf3, 0xed, 0x93, 0xfd, 0x35, 0x1a, 0xa7, 0x27, + 0x22, 0x19, 0xaf, 0x1c, 0xc2, 0x2a, 0x3e, 0x21, 0x8d, 0x19, 0x24, 0x3a, + 0xdc, 0x66, 0xd1, 0x74, 0xd4, 0x74, 0xbc, 0x75, 0x11, 0x78, 0xc0, 0x77, + 0xa7, 0x73, 0x05, 0x73, 0x6e, 0x76, 0x9b, 0x76, 0x5e, 0x6b, 0x3b, 0x66, + 0x42, 0x69, 0xd0, 0x67, 0xc4, 0x63, 0x27, 0x61, 0x7f, 0x61, 0x16, 0x58, + 0x72, 0x59, 0xaf, 0x60, 0xbd, 0x53, 0xdf, 0x4e, 0x99, 0x51, 0xce, 0x53, + 0x88, 0x58, 0xe1, 0x50, 0x6b, 0x38, 0xc6, 0x26, 0xe6, 0x22, 0x7d, 0x21, + 0x75, 0x2c, 0xe4, 0x40, 0x19, 0x4d, 0xd4, 0x41, 0xda, 0x38, 0x46, 0x36, + 0x22, 0x2a, 0x31, 0x1f, 0x25, 0x16, 0x23, 0x11, 0xf6, 0x07, 0x1f, 0x15, + 0x86, 0x37, 0x4c, 0x47, 0xe3, 0x45, 0x9d, 0x48, 0xc6, 0x58, 0x62, 0x5a, + 0x8c, 0x4c, 0xb0, 0x3f, 0x77, 0x35, 0xdb, 0x2f, 0x42, 0x1f, 0x96, 0x0c, + 0x7b, 0x13, 0x57, 0x27, 0x76, 0x30, 0x38, 0x30, 0xdc, 0x20, 0x6c, 0x0c, + 0x76, 0x10, 0xdd, 0x0d, 0x9f, 0x0a, 0x3a, 0x2c, 0x47, 0x43, 0x99, 0x46, + 0xa2, 0x39, 0xbf, 0x20, 0xa5, 0x37, 0x17, 0x57, 0x33, 0x44, 0xa0, 0x37, + 0x80, 0x3e, 0x2e, 0x45, 0xa0, 0x58, 0x03, 0x5b, 0xf3, 0x48, 0x4f, 0x41, + 0x08, 0x40, 0xf9, 0x36, 0x74, 0x33, 0x4d, 0x2a, 0x57, 0x21, 0x37, 0x2c, + 0xb0, 0x29, 0x33, 0x23, 0xb1, 0x1d, 0x8b, 0x16, 0xf8, 0x11, 0x79, 0x03, + 0x8e, 0xef, 0xba, 0xf4, 0x0c, 0x10, 0x7f, 0x0c, 0xce, 0x04, 0x70, 0x06, + 0xaa, 0x01, 0x2f, 0x00, 0xa4, 0xff, 0xc7, 0x0b, 0x8d, 0x2a, 0x90, 0x40, + 0x3d, 0x39, 0x43, 0x2c, 0x10, 0x10, 0x22, 0xeb, 0xc4, 0xdc, 0xae, 0xec, + 0xbf, 0x00, 0x51, 0xff, 0xc8, 0x04, 0x50, 0x07, 0x9a, 0xf8, 0x3d, 0xe1, + 0x6f, 0xc5, 0x66, 0xbc, 0xa7, 0xcb, 0xae, 0xc8, 0x8c, 0xbb, 0x0f, 0xd0, + 0xd1, 0xe5, 0x95, 0xe9, 0xa5, 0xf2, 0xd7, 0xfe, 0xb1, 0xfe, 0xff, 0x03, + 0x91, 0x06, 0xdd, 0xfb, 0xcc, 0xf9, 0xc6, 0xfd, 0xfd, 0xfd, 0x2c, 0xea, + 0x35, 0xd2, 0x56, 0xc6, 0x29, 0xc3, 0x62, 0xc9, 0x3d, 0xd0, 0xce, 0xd1, + 0xe3, 0xdd, 0x42, 0xfc, 0xec, 0x15, 0x55, 0x15, 0x32, 0xfa, 0x7e, 0xee, + 0xa5, 0xe5, 0xa9, 0xc8, 0x8c, 0xb7, 0x24, 0xbd, 0x63, 0xcc, 0x32, 0xd4, + 0xc3, 0xde, 0xe5, 0xe0, 0x0c, 0xdf, 0xef, 0xed, 0x0e, 0x02, 0x01, 0x0b, + 0x07, 0xff, 0xc6, 0xe8, 0x79, 0xd5, 0xd4, 0xca, 0xf8, 0xc7, 0xb4, 0xd2, + 0x09, 0xd6, 0x43, 0xc9, 0xaa, 0xc2, 0xa9, 0xbe, 0x28, 0xb2, 0x0c, 0xb0, + 0x18, 0xc5, 0xe3, 0xca, 0xec, 0xc2, 0x47, 0xba, 0xfa, 0xb1, 0x4f, 0xaf, + 0x3f, 0xac, 0x7d, 0xaf, 0x56, 0xbd, 0x67, 0xdb, 0x61, 0xf2, 0x43, 0xf1, + 0xf2, 0xdb, 0x11, 0xc5, 0x78, 0xbb, 0x0c, 0xb7, 0x85, 0xbf, 0x37, 0xc5, + 0x37, 0xbf, 0xb3, 0xb6, 0x46, 0xab, 0x8e, 0xaa, 0x75, 0xbb, 0xbb, 0xcd, + 0x37, 0xd5, 0x55, 0xd4, 0xfb, 0xd8, 0x1e, 0xe9, 0x4a, 0xef, 0x4a, 0xe6, + 0x83, 0xde, 0xa5, 0xec, 0x31, 0xfa, 0xd0, 0xed, 0x48, 0xf1, 0xb0, 0x07, + 0x78, 0xff, 0x95, 0xd4, 0xdc, 0xbe, 0x5e, 0xc4, 0x64, 0xc2, 0xc8, 0xb9, + 0xef, 0xa7, 0xab, 0x9a, 0x33, 0x95, 0x46, 0x98, 0xf7, 0xa0, 0x37, 0x9b, + 0xce, 0x98, 0x48, 0xac, 0x8a, 0xc1, 0x26, 0xc9, 0x5a, 0xda, 0xbb, 0xdd, + 0x22, 0xcc, 0x72, 0xcc, 0xc8, 0xd2, 0x76, 0xc9, 0x1b, 0xbb, 0x25, 0xc8, + 0x6f, 0xd9, 0xef, 0xda, 0xec, 0xcd, 0xe1, 0xb5, 0x4c, 0xb3, 0xda, 0xbf, + 0xc5, 0xd1, 0x4b, 0xe7, 0xdf, 0xed, 0x2d, 0xe1, 0x8c, 0xd9, 0x9e, 0xd9, + 0xa5, 0xdc, 0x59, 0xe1, 0xfe, 0xdf, 0xfe, 0xdb, 0xc4, 0xd2, 0xdf, 0xd1, + 0xcf, 0xe1, 0xc9, 0x09, 0x7a, 0x29, 0x20, 0x29, 0xaf, 0x2a, 0x51, 0x34, + 0xa0, 0x3c, 0x23, 0x2e, 0x31, 0x12, 0x94, 0x0c, 0x52, 0x1b, 0x54, 0x22, + 0x3a, 0x26, 0xb8, 0x31, 0x3b, 0x37, 0xb1, 0x3c, 0x91, 0x3f, 0x78, 0x44, + 0xb0, 0x49, 0x94, 0x3c, 0x19, 0x20, 0x26, 0x00, 0xd9, 0xf1, 0x15, 0xf8, + 0x1b, 0x00, 0x82, 0x0b, 0xae, 0x19, 0xe4, 0x1f, 0x96, 0x2d, 0x84, 0x45, + 0xa1, 0x50, 0x36, 0x53, 0x2a, 0x57, 0x0a, 0x58, 0xef, 0x59, 0xb1, 0x53, + 0xb9, 0x40, 0xa8, 0x2c, 0x00, 0x1e, 0x0c, 0x11, 0x25, 0x07, 0xc7, 0x0b, + 0xfd, 0x12, 0x28, 0x0a, 0xf0, 0xf3, 0x06, 0xec, 0xab, 0xfa, 0x47, 0x10, + 0x41, 0x23, 0xf7, 0x27, 0xd5, 0x1e, 0xf3, 0x0f, 0x1b, 0x07, 0x92, 0x07, + 0xb4, 0x12, 0x89, 0x1c, 0x25, 0x26, 0x24, 0x34, 0x93, 0x2e, 0x4e, 0x2c, + 0xa9, 0x3a, 0xf3, 0x48, 0x6c, 0x50, 0x1e, 0x4e, 0x40, 0x4b, 0x56, 0x4a, + 0xca, 0x51, 0x2f, 0x61, 0x85, 0x6f, 0x95, 0x76, 0xbf, 0x76, 0x8e, 0x75, + 0x1e, 0x6e, 0xa7, 0x57, 0xa0, 0x3e, 0x9a, 0x34, 0x56, 0x32, 0x35, 0x38, + 0x1b, 0x4a, 0xe9, 0x5f, 0x30, 0x71, 0xfe, 0x72, 0x51, 0x68, 0x38, 0x64, + 0x59, 0x6b, 0xd7, 0x6f, 0x01, 0x6a, 0x32, 0x59, 0xea, 0x4e, 0x6a, 0x4e, + 0x1a, 0x4c, 0x38, 0x52, 0x31, 0x4f, 0xe1, 0x37, 0xe4, 0x2d, 0x97, 0x3c, + 0x1e, 0x4b, 0x72, 0x4d, 0xc8, 0x42, 0x55, 0x32, 0xf7, 0x28, 0x5c, 0x25, + 0x2a, 0x30, 0xfa, 0x3b, 0x10, 0x2f, 0xb7, 0x1a, 0xf1, 0x16, 0xf4, 0x21, + 0xe7, 0x31, 0x0a, 0x40, 0x98, 0x37, 0xcf, 0x07, 0xda, 0xd5, 0xf4, 0xcb, + 0x84, 0xce, 0xe4, 0xd1, 0x9a, 0xdb, 0x51, 0xd8, 0x3d, 0xce, 0x7a, 0xc9, + 0x3a, 0xca, 0xd1, 0xcd, 0xef, 0xd8, 0xde, 0xe7, 0x43, 0xf4, 0xe0, 0xf8, + 0xd0, 0xf9, 0x7c, 0x04, 0xa7, 0x00, 0xd0, 0xec, 0x10, 0xec, 0xb7, 0xfc, + 0x92, 0x05, 0xbf, 0x11, 0x11, 0x20, 0xb7, 0x14, 0x31, 0x04, 0xf2, 0xff, + 0xa9, 0x01, 0x9e, 0x06, 0x32, 0x0e, 0x90, 0x16, 0xea, 0x14, 0xf0, 0x0c, + 0x58, 0x08, 0x80, 0x0f, 0x4e, 0x21, 0x67, 0x32, 0x3a, 0x38, 0x0e, 0x32, + 0xa9, 0x33, 0x83, 0x36, 0xfd, 0x25, 0x02, 0x0d, 0x3e, 0x01, 0x03, 0x05, + 0x9f, 0x0c, 0x97, 0x12, 0x3b, 0x14, 0xc5, 0x15, 0xe9, 0x13, 0xa8, 0x10, + 0x38, 0x17, 0x7b, 0x1a, 0xc0, 0x17, 0x30, 0x1c, 0xb6, 0x1c, 0xe3, 0x03, + 0xd0, 0xe7, 0x53, 0xda, 0x92, 0xc6, 0x81, 0xb7, 0x37, 0xb7, 0xaa, 0xbf, + 0x71, 0xc8, 0x6b, 0xc2, 0xd0, 0xaf, 0x8d, 0xa0, 0x11, 0xa6, 0x00, 0xb8, + 0x79, 0xbe, 0x4f, 0xb6, 0x72, 0xb5, 0x3d, 0xba, 0x50, 0xbb, 0x1d, 0xbb, + 0xed, 0xad, 0xcf, 0xa6, 0x73, 0xa8, 0x16, 0xa9, 0xfa, 0xae, 0xdf, 0xac, + 0x47, 0xa9, 0x5d, 0xb4, 0x69, 0xc9, 0xe1, 0xd7, 0xb4, 0xd2, 0x40, 0xc2, + 0xa2, 0xbf, 0x81, 0xbe, 0xd5, 0xb4, 0x3c, 0xb5, 0x7f, 0xb7, 0xda, 0xb5, + 0x73, 0xbd, 0x38, 0xce, 0x0c, 0xe0, 0x4e, 0xf8, 0x25, 0x01, 0xc1, 0xff, + 0xf7, 0x0c, 0xeb, 0x1b, 0xda, 0x29, 0x6f, 0x35, 0x70, 0x44, 0x82, 0x47, + 0x98, 0x1b, 0x3f, 0xd6, 0x86, 0xbb, 0x1e, 0xb1, 0x06, 0xa0, 0x5d, 0xd2, + 0xaa, 0x25, 0x1d, 0x4a, 0xef, 0x59, 0xc6, 0x5a, 0x08, 0x32, 0xc6, 0x23, + 0x35, 0x2e, 0x5e, 0x24, 0x19, 0x0e, 0x7b, 0xf9, 0x48, 0xfa, 0x8c, 0xe7, + 0x84, 0xe4, 0xbc, 0xe5, 0xcf, 0xca, 0xc3, 0xca, 0x3e, 0xca, 0x45, 0xc0, + 0x5b, 0xbc, 0xeb, 0xb7, 0x70, 0xc4, 0x3f, 0xf0, 0x7a, 0xfa, 0xe0, 0xe0, + 0x33, 0xd5, 0x28, 0xc5, 0x11, 0xad, 0xfd, 0xa2, 0x3f, 0xd5, 0x2a, 0x19, + 0x47, 0x21, 0x19, 0xdf, 0x9e, 0xb3, 0xd5, 0xdf, 0x02, 0x08, 0xe5, 0x12, + 0x64, 0xf6, 0x65, 0xbc, 0xf9, 0xa4, 0xc8, 0xc9, 0x13, 0xde, 0x79, 0xa9, + 0x38, 0x8c, 0x71, 0x8e, 0x2e, 0x9e, 0xa2, 0xc7, 0x07, 0xcb, 0x3a, 0xad, + 0x24, 0x9c, 0x76, 0xa8, 0xf2, 0xd6, 0x21, 0xf6, 0x4b, 0xfb, 0x1f, 0x01, + 0x14, 0xff, 0x5e, 0x05, 0xc0, 0xff, 0x2c, 0xf0, 0x5b, 0xff, 0x62, 0x1f, + 0x5e, 0x39, 0x83, 0x27, 0x61, 0x04, 0x8f, 0x11, 0xdc, 0x25, 0x30, 0x1c, + 0x09, 0x16, 0x7f, 0x0d, 0x84, 0x03, 0x3a, 0x17, 0x01, 0x34, 0xbc, 0x3b, + 0x70, 0x25, 0x7c, 0x02, 0xd7, 0x04, 0xa8, 0x28, 0xa4, 0x48, 0x53, 0x69, + 0xd7, 0x72, 0x9f, 0x4d, 0x4b, 0x1b, 0xf4, 0x0b, 0x92, 0x1a, 0x7d, 0x25, + 0x7c, 0x37, 0x9d, 0x3f, 0x32, 0x2d, 0x75, 0x16, 0xcd, 0x13, 0x53, 0x1d, + 0x85, 0x29, 0xf1, 0x41, 0x9c, 0x47, 0x47, 0x37, 0x2b, 0x22, 0x2a, 0x0d, + 0x5b, 0xee, 0x89, 0xd4, 0x5e, 0xd8, 0x88, 0xd5, 0xfe, 0xc5, 0x8c, 0xcc, + 0x64, 0xeb, 0x32, 0x06, 0x20, 0x11, 0xdc, 0x00, 0x19, 0xf5, 0xeb, 0xf7, + 0x56, 0xe2, 0x0e, 0xd7, 0x86, 0xe0, 0x08, 0xef, 0x15, 0x01, 0x62, 0x15, + 0x22, 0x16, 0xa6, 0xfc, 0xdb, 0xf5, 0x93, 0x03, 0x90, 0x17, 0xb0, 0x20, + 0x76, 0x19, 0xd3, 0x1a, 0x22, 0x24, 0xf9, 0x24, 0x90, 0x25, 0x20, 0x2d, + 0x18, 0x38, 0xad, 0x46, 0xcc, 0x38, 0x1c, 0x21, 0x89, 0x38, 0xb4, 0x57, + 0x27, 0x54, 0xb4, 0x52, 0xc5, 0x61, 0x7f, 0x6d, 0x1b, 0x6e, 0xb7, 0x5f, + 0x61, 0x59, 0xbf, 0x64, 0x1c, 0x6e, 0xfa, 0x6f, 0x7f, 0x6a, 0x76, 0x61, + 0xea, 0x58, 0x3f, 0x52, 0x79, 0x4a, 0x36, 0x4a, 0x0f, 0x52, 0x67, 0x56, + 0xc3, 0x54, 0x33, 0x4b, 0xca, 0x41, 0x61, 0x2c, 0x22, 0x10, 0x6a, 0xfe, + 0x77, 0xfc, 0x74, 0x0e, 0xe3, 0x15, 0xf7, 0x0f, 0x72, 0x08, 0xd1, 0x08, + 0x3c, 0x0e, 0x14, 0x07, 0x0a, 0xfd, 0x4c, 0xfa, 0x3a, 0x04, 0xae, 0x07, + 0xe5, 0x06, 0x57, 0x06, 0x93, 0xfb, 0xb5, 0x09, 0x46, 0x28, 0xb9, 0x33, + 0x09, 0x3d, 0x29, 0x3a, 0x1a, 0x2a, 0x3f, 0x34, 0x11, 0x43, 0xa1, 0x47, + 0x65, 0x4c, 0x47, 0x4b, 0x37, 0x51, 0x8a, 0x58, 0x15, 0x54, 0x7d, 0x54, + 0x28, 0x5c, 0xf5, 0x63, 0x84, 0x6c, 0x01, 0x60, 0x5e, 0x51, 0x56, 0x4a, + 0x6d, 0x33, 0xce, 0x22, 0x05, 0x15, 0x25, 0x05, 0x3d, 0xfe, 0xa8, 0xfa, + 0xb0, 0xf7, 0xcc, 0xfa, 0x1c, 0x07, 0xe9, 0x12, 0xe5, 0x26, 0x4f, 0x3c, + 0xf1, 0x46, 0xf8, 0x48, 0x04, 0x33, 0x38, 0x16, 0x81, 0x11, 0x7a, 0x14, + 0xf8, 0x11, 0x2e, 0x18, 0x0c, 0x18, 0x92, 0x0c, 0x37, 0x13, 0xd1, 0x14, + 0xfa, 0x03, 0x4f, 0xfc, 0x4c, 0xf5, 0xc8, 0xed, 0x1e, 0xe8, 0x4e, 0xe6, + 0x64, 0xef, 0xd9, 0xf2, 0x45, 0xf6, 0x7e, 0xfd, 0x37, 0xec, 0x96, 0xd9, + 0x02, 0xe1, 0x58, 0xe6, 0x84, 0xec, 0x2c, 0xeb, 0xa8, 0xe6, 0xaa, 0xf0, + 0xb5, 0xed, 0xe8, 0xed, 0x6f, 0xf3, 0x83, 0xf4, 0x10, 0xfb, 0xd8, 0x0c, + 0xcb, 0x23, 0x09, 0x29, 0x4f, 0x29, 0x50, 0x2a, 0xc0, 0x22, 0x38, 0x0e, + 0x0c, 0xfd, 0xbb, 0xf9, 0x9a, 0xf9, 0x04, 0xf8, 0xab, 0xf1, 0x61, 0xec, + 0xcd, 0xe7, 0xbe, 0xe9, 0x56, 0xe4, 0x37, 0xe5, 0x0c, 0xf3, 0x7a, 0xfa, + 0x20, 0xfd, 0xfd, 0xea, 0x80, 0xe3, 0x52, 0xf1, 0xc8, 0xff, 0xfa, 0x0b, + 0xc4, 0x0e, 0xa0, 0x06, 0xbd, 0xfe, 0xb7, 0x0c, 0x4d, 0x1a, 0xa9, 0x09, + 0x7e, 0xe7, 0xe9, 0xd6, 0xb0, 0xd8, 0x7a, 0xe9, 0xc4, 0xf6, 0x18, 0xee, + 0x40, 0xe8, 0xcb, 0xe2, 0xdb, 0xe0, 0xfa, 0xdd, 0x7b, 0xd5, 0xe8, 0xd4, + 0x1d, 0xde, 0xbe, 0xe0, 0x79, 0xdd, 0xba, 0xe6, 0xb6, 0xec, 0x9b, 0xe9, + 0x7a, 0xe2, 0xf8, 0xdc, 0x74, 0xdd, 0x77, 0xe5, 0x76, 0xee, 0xca, 0xf7, + 0xd8, 0x02, 0x6d, 0x01, 0x77, 0xf7, 0x9c, 0xef, 0xb1, 0xf0, 0x53, 0xeb, + 0x20, 0xd8, 0xcb, 0xcd, 0x03, 0xcf, 0x2a, 0xcb, 0x66, 0xd1, 0x18, 0xdf, + 0x20, 0xdc, 0x79, 0xce, 0xf6, 0xb7, 0x67, 0xb1, 0xa1, 0xb5, 0x5f, 0xb8, + 0xf3, 0xc5, 0x78, 0xc9, 0x14, 0xc0, 0xce, 0xbb, 0x80, 0xbd, 0x35, 0xbb, + 0x3e, 0xc2, 0x28, 0xd1, 0x8b, 0xd5, 0x81, 0xd3, 0xb8, 0xd0, 0x12, 0xd2, + 0x64, 0xd0, 0xbf, 0xcf, 0x93, 0xe0, 0x6f, 0xe7, 0xb3, 0xe7, 0x0d, 0xf6, + 0x29, 0xfb, 0xeb, 0xfd, 0xf7, 0xf1, 0x40, 0xdf, 0x4d, 0xe7, 0x91, 0xed, + 0x34, 0xee, 0xf5, 0xf6, 0xc8, 0xf3, 0x8d, 0xdf, 0x54, 0xda, 0xb1, 0xda, + 0x21, 0xc6, 0x32, 0xba, 0x76, 0xb7, 0x83, 0xb3, 0xf5, 0xb7, 0xcb, 0xaf, + 0xa0, 0xa9, 0x9a, 0xb7, 0x05, 0xbc, 0xe9, 0xad, 0xf6, 0xa0, 0xd1, 0xaa, + 0xec, 0xb9, 0x4e, 0xb5, 0x96, 0xb0, 0xa5, 0xb7, 0x70, 0xb8, 0x72, 0xb4, + 0x97, 0xae, 0x5f, 0xad, 0x3f, 0xb4, 0xbc, 0xb0, 0x32, 0xb9, 0x50, 0xc1, + 0xcc, 0xb7, 0xa4, 0xab, 0x66, 0xa2, 0x1b, 0xa8, 0xab, 0xac, 0xbb, 0xb2, + 0x27, 0xbc, 0xbb, 0xc0, 0xe0, 0xd0, 0x21, 0xec, 0x0a, 0xf6, 0x30, 0xe8, + 0x39, 0xe0, 0x77, 0xe2, 0x15, 0xe6, 0xf7, 0xe8, 0x04, 0xe3, 0x0d, 0xe4, + 0xd9, 0xf8, 0x92, 0x06, 0x49, 0x08, 0x4d, 0x08, 0xda, 0x0d, 0x77, 0x1a, + 0xf1, 0x20, 0x8f, 0x23, 0xec, 0x25, 0x27, 0x28, 0x65, 0x25, 0x96, 0x24, + 0xf9, 0x23, 0xc5, 0x1d, 0x6c, 0x14, 0x5b, 0x08, 0x61, 0x04, 0xd3, 0x03, + 0x54, 0x06, 0xe2, 0x0a, 0xe5, 0x01, 0xf6, 0xfa, 0x8f, 0x04, 0xc3, 0x05, + 0xc6, 0x03, 0x8b, 0x03, 0xb5, 0xf6, 0xff, 0xe3, 0x2a, 0xd6, 0x24, 0xd6, + 0xfb, 0xda, 0xb7, 0xde, 0xe9, 0xd6, 0x50, 0xd7, 0x5b, 0xe8, 0x6b, 0xe7, + 0x9a, 0xe2, 0x17, 0xe8, 0x9e, 0xe8, 0x98, 0xde, 0xf6, 0xd8, 0xd2, 0xdd, + 0x68, 0xe5, 0xba, 0xeb, 0x7b, 0xf5, 0xbb, 0x00, 0x1c, 0x03, 0x58, 0x05, + 0x95, 0x0a, 0xab, 0x0d, 0x6a, 0x07, 0x41, 0x01, 0x83, 0x0a, 0x40, 0x1c, + 0xbd, 0x28, 0xf1, 0x30, 0xc7, 0x40, 0x6c, 0x4d, 0x3d, 0x4a, 0x8f, 0x44, + 0xf7, 0x3c, 0xe8, 0x2e, 0xe8, 0x2c, 0x16, 0x3a, 0x7c, 0x4d, 0xe9, 0x50, + 0xc1, 0x41, 0x35, 0x3d, 0x54, 0x40, 0xb1, 0x3f, 0x6c, 0x40, 0xd5, 0x49, + 0xbd, 0x4e, 0x74, 0x4c, 0x1f, 0x4c, 0x6f, 0x4f, 0x95, 0x50, 0x68, 0x45, + 0xf8, 0x46, 0xce, 0x4e, 0xaf, 0x42, 0x27, 0x3e, 0x9a, 0x49, 0x4a, 0x48, + 0xd5, 0x44, 0xab, 0x45, 0x62, 0x41, 0x9f, 0x49, 0x33, 0x52, 0xfe, 0x58, + 0xf4, 0x63, 0x46, 0x66, 0x7d, 0x65, 0xb5, 0x65, 0x69, 0x66, 0x42, 0x62, + 0x0d, 0x61, 0x55, 0x5c, 0x9c, 0x45, 0x19, 0x31, 0x09, 0x2e, 0x12, 0x35, + 0x53, 0x3f, 0x1f, 0x42, 0x2e, 0x30, 0x9f, 0x17, 0xd6, 0xfd, 0x6d, 0xf4, + 0x87, 0xfa, 0x1f, 0xf4, 0x3f, 0xf8, 0x67, 0xfd, 0x83, 0xf1, 0x3e, 0xe4, + 0x19, 0xe1, 0xb6, 0xe5, 0xc2, 0xea, 0x05, 0xf3, 0x2e, 0xf9, 0x45, 0x02, + 0x7b, 0x0b, 0x38, 0x13, 0xc3, 0x1b, 0xc5, 0x1c, 0xc3, 0x1a, 0xbb, 0x1e, + 0xba, 0x21, 0xc9, 0x25, 0x20, 0x2e, 0xed, 0x2a, 0x86, 0x29, 0x36, 0x28, + 0x42, 0x2d, 0xac, 0x36, 0x73, 0x29, 0x03, 0x23, 0x4b, 0x29, 0x13, 0x30, + 0x56, 0x38, 0x87, 0x3c, 0x24, 0x37, 0x09, 0x22, 0x99, 0x0f, 0x00, 0x0a, + 0x4b, 0x21, 0xde, 0x55, 0x19, 0x76, 0xb6, 0x77, 0x5b, 0x5e, 0x6e, 0x35, + 0xac, 0x25, 0xed, 0x32, 0x2d, 0x50, 0xc7, 0x52, 0x51, 0x36, 0x19, 0x25, + 0x95, 0x27, 0x66, 0x47, 0xf9, 0x5f, 0xef, 0x51, 0x9a, 0x37, 0xbc, 0x2a, + 0x64, 0x21, 0x13, 0x11, 0x54, 0x0e, 0x08, 0x0c, 0x27, 0x13, 0xa5, 0x17, + 0xc4, 0xf7, 0x02, 0xe7, 0xae, 0xe1, 0xc2, 0xcf, 0xa7, 0xcc, 0x29, 0xcb, + 0xff, 0xca, 0x0d, 0xd4, 0x4f, 0xd4, 0xcc, 0xd1, 0x31, 0xdf, 0x2a, 0xfa, + 0xf5, 0xff, 0xb0, 0xe5, 0xc8, 0xe0, 0x87, 0xe7, 0x1a, 0xd6, 0x67, 0xd4, + 0x32, 0xd9, 0xc4, 0xd3, 0x02, 0xd6, 0xca, 0xec, 0x16, 0x11, 0xb2, 0x1d, + 0x4d, 0x20, 0x6d, 0x27, 0x31, 0x16, 0x4e, 0xf3, 0x89, 0xed, 0xc8, 0xf5, + 0xd7, 0xfb, 0x59, 0x0f, 0x61, 0x19, 0xa0, 0x0f, 0x8e, 0xeb, 0xdc, 0xdc, + 0x5f, 0xff, 0x05, 0x2b, 0xcc, 0x41, 0xbb, 0x41, 0xb7, 0x3a, 0x06, 0x11, + 0x25, 0xf8, 0xe1, 0x0c, 0x24, 0x14, 0xc8, 0x20, 0x78, 0x3b, 0x69, 0x3e, + 0xf9, 0x2f, 0x41, 0x24, 0xf8, 0x18, 0x71, 0x25, 0x08, 0x35, 0xee, 0x3e, + 0x77, 0x43, 0xb7, 0x12, 0x03, 0xe1, 0xe3, 0xe2, 0x2b, 0xf9, 0x5d, 0x01, + 0x75, 0xfa, 0x7c, 0xef, 0xda, 0xe9, 0xd0, 0xec, 0x78, 0xde, 0x54, 0xd2, + 0x18, 0xdc, 0x2e, 0xda, 0xb4, 0xc6, 0x61, 0xc1, 0xd6, 0xc8, 0x08, 0xc1, + 0x10, 0xb8, 0xfb, 0xbb, 0x3d, 0xb6, 0x39, 0xb3, 0xf7, 0xd0, 0x89, 0xdc, + 0x88, 0xbb, 0x6a, 0xb3, 0xfe, 0xc5, 0xac, 0xd3, 0xb5, 0xd8, 0xb2, 0xd0, + 0xa8, 0xcf, 0x13, 0xc7, 0xb4, 0xb1, 0x7e, 0xa0, 0x07, 0x92, 0xa8, 0x8a, + 0xda, 0x99, 0x52, 0xb0, 0xc0, 0xac, 0x36, 0xad, 0xd3, 0xab, 0x27, 0xb1, + 0x17, 0xca, 0x99, 0xc5, 0xd4, 0xaf, 0xa4, 0x9e, 0x3c, 0xa4, 0xed, 0xbe, + 0xa8, 0xcf, 0x1e, 0xd1, 0x64, 0xdf, 0xd6, 0x03, 0xd4, 0x13, 0x9c, 0xfe, + 0xea, 0xee, 0xaf, 0xfb, 0x2b, 0x00, 0x84, 0xf5, 0xe5, 0xfb, 0x7d, 0x13, + 0x4b, 0x12, 0x33, 0xec, 0x86, 0xc2, 0x8c, 0xc4, 0x55, 0xe5, 0x3a, 0xf1, + 0x81, 0xe8, 0x88, 0xd8, 0xa2, 0xe6, 0xd7, 0x07, 0xce, 0x21, 0x81, 0x26, + 0xbf, 0x19, 0x5c, 0x13, 0x78, 0xf1, 0xfd, 0xc8, 0xef, 0xbc, 0x4b, 0xc8, + 0xa0, 0xdb, 0x29, 0xef, 0xbc, 0xee, 0x11, 0xd8, 0xfb, 0xd0, 0x34, 0xc9, + 0xec, 0xc6, 0xed, 0xdc, 0x1a, 0xef, 0xb6, 0xf0, 0xf7, 0xec, 0x98, 0xdb, + 0x98, 0xce, 0x29, 0xc8, 0x5f, 0xab, 0xfd, 0x9f, 0x59, 0xac, 0x7f, 0xa7, + 0xa9, 0x9b, 0xca, 0xab, 0xc5, 0xc2, 0x89, 0xbb, 0x57, 0xa4, 0x3e, 0xa8, + 0x86, 0xce, 0xea, 0xe3, 0x58, 0xdf, 0x3a, 0xd9, 0x29, 0xd5, 0x15, 0xda, + 0xc3, 0xe7, 0xf8, 0xea, 0x3b, 0xe0, 0x54, 0xdb, 0xef, 0xd8, 0x79, 0xd4, + 0x61, 0xd9, 0x29, 0xe2, 0x90, 0xfa, 0x8a, 0x0b, 0xd1, 0x05, 0xb2, 0x14, + 0x86, 0x20, 0xf7, 0x2b, 0x74, 0x3c, 0x6b, 0x28, 0xc4, 0x03, 0x60, 0xfa, + 0x6d, 0x01, 0x74, 0x02, 0xde, 0x15, 0x8c, 0x23, 0xcd, 0x23, 0xc7, 0x1f, + 0x13, 0x19, 0x03, 0x22, 0xc4, 0x0f, 0x5a, 0xf8, 0xc7, 0xfd, 0x69, 0x10, + 0xc5, 0x3c, 0x11, 0x59, 0xdd, 0x49, 0x78, 0x36, 0x5a, 0x29, 0x0e, 0x1d, + 0x17, 0x11, 0x64, 0x0b, 0xad, 0x08, 0xbd, 0xfc, 0x5a, 0xfe, 0xbe, 0x0b, + 0x2e, 0xfd, 0x09, 0xe4, 0x5d, 0xea, 0x1f, 0xec, 0xdf, 0xdb, 0x9c, 0xdb, + 0x36, 0xda, 0x06, 0xda, 0x6b, 0xe5, 0xfc, 0xe1, 0xbf, 0xd9, 0x92, 0xe3, + 0x3e, 0xdc, 0x93, 0xc3, 0x1c, 0xcb, 0x50, 0xe6, 0xf3, 0xfa, 0xad, 0x12, + 0xda, 0x1d, 0xcb, 0x13, 0x97, 0x0c, 0xfb, 0x03, 0x39, 0xfb, 0x74, 0x01, + 0x58, 0x11, 0x26, 0x16, 0x26, 0x0e, 0xae, 0xfc, 0x24, 0xea, 0x18, 0xea, + 0x04, 0xe0, 0x3e, 0xd3, 0xfa, 0xcf, 0xc3, 0xc7, 0x43, 0xcf, 0xaf, 0xe6, + 0x43, 0xee, 0xac, 0xde, 0x48, 0xe2, 0x48, 0xef, 0x50, 0xf6, 0x16, 0x07, + 0xce, 0x14, 0x5a, 0x19, 0x34, 0x05, 0xc3, 0xe7, 0x1c, 0xe7, 0xe5, 0xf8, + 0xbc, 0x17, 0xe5, 0x3f, 0x15, 0x3c, 0xeb, 0x18, 0x46, 0x08, 0x43, 0x19, + 0x67, 0x34, 0x99, 0x2c, 0x7d, 0x33, 0x6b, 0x36, 0x8d, 0x0d, 0xa1, 0xf4, + 0x29, 0xf2, 0x61, 0xfa, 0x0a, 0x0b, 0x23, 0x17, 0xb0, 0x14, 0x99, 0x16, + 0x43, 0x1d, 0x67, 0x21, 0xe5, 0x1e, 0xbd, 0x12, 0xe5, 0x19, 0x71, 0x11, + 0x35, 0x09, 0x4f, 0x26, 0x36, 0x26, 0xfa, 0x0d, 0xb3, 0x11, 0x84, 0x22, + 0x0e, 0x29, 0x03, 0x30, 0x48, 0x3d, 0xca, 0x39, 0xe0, 0x22, 0xfa, 0x15, + 0x23, 0x0a, 0x1e, 0xf6, 0x5d, 0xf3, 0x48, 0xf2, 0x7f, 0xee, 0x24, 0xf9, + 0x0f, 0x08, 0x16, 0x1a, 0x5c, 0x1c, 0x92, 0x0c, 0xcb, 0x0a, 0xcc, 0x16, + 0xd5, 0x0d, 0x6e, 0xf6, 0xdf, 0xff, 0x63, 0x1d, 0xb4, 0x3c, 0xb0, 0x53, + 0x41, 0x58, 0x71, 0x5b, 0x9d, 0x59, 0x30, 0x54, 0xce, 0x4e, 0x2a, 0x45, + 0x96, 0x3f, 0xb1, 0x4a, 0x6c, 0x4f, 0x22, 0x4a, 0x6b, 0x52, 0xd6, 0x5b, + 0x28, 0x65, 0x6a, 0x6b, 0xa3, 0x6a, 0xc4, 0x67, 0xb2, 0x65, 0x77, 0x66, + 0x70, 0x66, 0x91, 0x53, 0x7b, 0x43, 0xe7, 0x58, 0x8b, 0x6a, 0x2b, 0x70, + 0xaf, 0x74, 0xf7, 0x70, 0x40, 0x5c, 0x02, 0x36, 0x75, 0x26, 0xb9, 0x34, + 0xd9, 0x45, 0xd9, 0x47, 0x1d, 0x42, 0xd2, 0x37, 0xb3, 0x37, 0xdc, 0x40, + 0xe7, 0x22, 0xe8, 0x00, 0xc0, 0x12, 0x0f, 0x2c, 0x49, 0x2f, 0x19, 0x32, + 0x20, 0x2c, 0x7b, 0x22, 0xc3, 0x20, 0x7d, 0x1c, 0xdc, 0x1b, 0x67, 0x24, + 0xbb, 0x27, 0x80, 0x20, 0x37, 0x1d, 0xf9, 0x19, 0x1a, 0x1d, 0x24, 0x22, + 0xae, 0x1d, 0xeb, 0x1e, 0x40, 0x2d, 0x8f, 0x47, 0x97, 0x56, 0xbc, 0x5f, + 0x7d, 0x5c, 0xdc, 0x2c, 0x72, 0x01, 0xa1, 0x03, 0xd7, 0x21, 0xaf, 0x4b, + 0x72, 0x68, 0x60, 0x65, 0x16, 0x47, 0xbd, 0x2a, 0x67, 0x37, 0x2e, 0x4c, + 0x43, 0x51, 0xff, 0x57, 0xfe, 0x4c, 0x50, 0x36, 0x25, 0x33, 0x09, 0x3f, + 0xad, 0x2f, 0xfd, 0x13, 0xc8, 0x0b, 0x40, 0x0e, 0x92, 0x15, 0xea, 0x08, + 0x2e, 0xf4, 0xb3, 0xea, 0x87, 0xea, 0x85, 0xfa, 0xa1, 0x0b, 0xa9, 0x15, + 0xb4, 0x1d, 0x29, 0x18, 0x60, 0x10, 0xfa, 0x06, 0x63, 0xff, 0x90, 0x10, + 0x55, 0x14, 0x47, 0x1c, 0x55, 0x30, 0x15, 0x20, 0xf8, 0x07, 0xef, 0x06, + 0x31, 0x0f, 0x7d, 0x0e, 0xb4, 0x10, 0xfb, 0x18, 0x29, 0x22, 0x68, 0x23, + 0xc9, 0x15, 0xd2, 0x09, 0x03, 0x0e, 0xdf, 0x16, 0x64, 0x0e, 0x24, 0xfe, + 0x56, 0xe9, 0xb0, 0xde, 0x1e, 0xe7, 0x0b, 0xec, 0x2a, 0xe3, 0x61, 0xe1, + 0x68, 0xec, 0x39, 0xf3, 0xde, 0xfd, 0xa0, 0xfd, 0x73, 0xf4, 0x9d, 0xfd, + 0x57, 0x19, 0xf6, 0x2e, 0x6e, 0x32, 0x81, 0x2f, 0x40, 0x2a, 0x9c, 0x1e, + 0x0c, 0x0b, 0x37, 0x00, 0x8b, 0x06, 0xee, 0x11, 0xa7, 0x07, 0x2d, 0xee, + 0xd4, 0xd9, 0x7d, 0xd1, 0x85, 0xd6, 0xc2, 0xde, 0xe0, 0xe6, 0xec, 0xe8, + 0x49, 0xed, 0x72, 0xe9, 0xcc, 0xe9, 0x14, 0xf4, 0xd0, 0xeb, 0xef, 0xee, + 0x17, 0x01, 0x77, 0x01, 0x33, 0x04, 0x7d, 0x20, 0xbb, 0x39, 0xed, 0x44, + 0xde, 0x4a, 0xeb, 0x47, 0x47, 0x39, 0xcf, 0x27, 0xaf, 0x21, 0x3e, 0x26, + 0x96, 0x29, 0xf7, 0x1f, 0x3e, 0x15, 0x74, 0x06, 0x99, 0xf6, 0x8d, 0xdf, + 0x0a, 0xc2, 0x6f, 0xc3, 0x85, 0xd3, 0x12, 0xda, 0x8b, 0xdb, 0x23, 0xde, + 0x21, 0xe3, 0x57, 0xe3, 0x4a, 0xe3, 0xf9, 0xf2, 0xd6, 0x01, 0xa2, 0x10, + 0x81, 0x23, 0x56, 0x11, 0xf0, 0xf4, 0x7f, 0xe5, 0xa0, 0xdc, 0x99, 0xee, + 0xf1, 0x00, 0x43, 0xfb, 0x02, 0xe9, 0xa7, 0xdc, 0xf7, 0xe7, 0xac, 0xf0, + 0xca, 0xe8, 0x76, 0xee, 0x8e, 0xeb, 0xb0, 0xd4, 0x92, 0xc8, 0x5f, 0xc0, + 0x14, 0xb9, 0x79, 0xc7, 0x82, 0xd2, 0x2b, 0xc0, 0xbd, 0xb8, 0x0c, 0xba, + 0x9b, 0xb6, 0xce, 0xc5, 0xca, 0xd5, 0xc6, 0xd8, 0x7e, 0xe5, 0xb4, 0xf5, + 0xaa, 0xf5, 0x53, 0xf0, 0x39, 0xe8, 0xcf, 0x00, 0x0a, 0x30, 0x50, 0x31, + 0xf9, 0x2d, 0x3b, 0x26, 0xd8, 0xee, 0x5b, 0xc8, 0x16, 0xc3, 0xe1, 0xb8, + 0x78, 0xb0, 0x85, 0xa5, 0xf5, 0x95, 0x3a, 0x93, 0x90, 0x9b, 0xde, 0xa7, + 0x40, 0xa8, 0x25, 0x99, 0x08, 0x9e, 0xbb, 0xb5, 0x7c, 0xc8, 0x40, 0xce, + 0xb5, 0xc6, 0x9d, 0xcc, 0xc2, 0xcb, 0x86, 0xc3, 0x19, 0xd1, 0x30, 0xd3, + 0x2b, 0xd4, 0x9d, 0xdb, 0x2e, 0xd2, 0xe3, 0xc8, 0xef, 0xc5, 0xbc, 0xcc, + 0xd5, 0xd4, 0x15, 0xcb, 0xd1, 0xcb, 0x3c, 0xde, 0xd6, 0xe1, 0x38, 0xe2, + 0x6d, 0xf0, 0xa3, 0xfc, 0xdc, 0xed, 0xd8, 0xc3, 0xcd, 0xab, 0x37, 0xba, + 0x35, 0xce, 0x5d, 0xd6, 0xc2, 0xd5, 0x15, 0xdb, 0x10, 0xe7, 0x0e, 0xe7, + 0x53, 0xf2, 0x82, 0x06, 0xd8, 0x0b, 0x22, 0x09, 0x4b, 0x03, 0x0c, 0xfd, + 0x75, 0xfe, 0xe4, 0x0d, 0xfc, 0x1b, 0x43, 0x22, 0x24, 0x1c, 0xf7, 0x13, + 0x85, 0x18, 0x51, 0x1c, 0x74, 0x13, 0x0d, 0xf8, 0xf7, 0xd8, 0x6e, 0xc5, + 0xbd, 0xc5, 0x72, 0xc9, 0x2f, 0xbc, 0xec, 0xaf, 0x2b, 0xbb, 0x5d, 0xdb, + 0x09, 0xf2, 0x64, 0xee, 0x74, 0xe6, 0x91, 0xf6, 0x9c, 0x0e, 0x12, 0x12, + 0x16, 0x0a, 0xd2, 0x10, 0x74, 0x17, 0xf3, 0xfd, 0x4f, 0xde, 0xad, 0xd4, + 0x6f, 0xe5, 0xe4, 0x01, 0x40, 0x0b, 0x85, 0x00, 0xd4, 0xeb, 0xf7, 0xde, + 0xdc, 0xd9, 0x8b, 0xc4, 0xd7, 0xb4, 0xc4, 0xb7, 0x8b, 0xbb, 0xb9, 0xbd, + 0xa7, 0xbc, 0x45, 0xbf, 0x28, 0xc6, 0x28, 0xc3, 0xc6, 0xba, 0xfa, 0xc4, + 0xb5, 0xd0, 0x4c, 0xcc, 0x59, 0xc6, 0x4c, 0xc4, 0x7b, 0xca, 0x31, 0xd9, + 0x34, 0xf1, 0x9b, 0x04, 0x8b, 0x0e, 0x55, 0x15, 0xd3, 0x13, 0x35, 0x04, + 0x99, 0xf5, 0xb1, 0xf6, 0xa2, 0xec, 0xcf, 0xdf, 0xbf, 0xdc, 0x7a, 0xde, + 0x49, 0xee, 0x4d, 0xf6, 0xde, 0xf0, 0x3a, 0xf8, 0x96, 0x04, 0xd6, 0x07, + 0x99, 0x0b, 0xfa, 0x10, 0xa0, 0x16, 0x0d, 0x16, 0x45, 0x13, 0x47, 0x0d, + 0xa7, 0x06, 0xc0, 0x08, 0x4b, 0x06, 0x5d, 0x0a, 0xb6, 0x13, 0x79, 0x0f, + 0x25, 0x03, 0x29, 0xfb, 0xb4, 0xfd, 0x97, 0x12, 0x62, 0x24, 0x57, 0x1f, + 0x95, 0x21, 0xea, 0x19, 0xb1, 0xf7, 0x28, 0xdd, 0x5e, 0xd9, 0x84, 0xe7, + 0x61, 0xe6, 0x75, 0xce, 0x9e, 0xc8, 0x61, 0xc8, 0x13, 0xbd, 0x5c, 0xc8, + 0x6b, 0xd1, 0xa2, 0xc9, 0xa0, 0xd5, 0x4c, 0xdd, 0x4a, 0xcf, 0x98, 0xd0, + 0xc5, 0xe3, 0x67, 0xef, 0xd1, 0xe9, 0x42, 0xe1, 0x4d, 0xea, 0x5e, 0xf0, + 0x0f, 0xef, 0xec, 0xf5, 0xb0, 0x01, 0x69, 0x09, 0xb7, 0x00, 0xad, 0x00, + 0x01, 0x0c, 0x19, 0x02, 0x51, 0xf5, 0x11, 0xff, 0x0f, 0x06, 0xab, 0x0d, + 0x62, 0x28, 0x53, 0x38, 0x76, 0x3e, 0x83, 0x3e, 0xe0, 0x2c, 0xd2, 0x19, + 0xe2, 0x09, 0x9a, 0xf7, 0x68, 0xea, 0x3d, 0xed, 0x5e, 0xf7, 0x5f, 0xff, + 0x43, 0xff, 0xca, 0xf9, 0xfc, 0xf4, 0x75, 0xf0, 0x04, 0x00, 0x73, 0x24, + 0x31, 0x47, 0x68, 0x5a, 0x9e, 0x59, 0xdb, 0x4c, 0x2c, 0x3c, 0xf7, 0x33, + 0x8a, 0x3e, 0xda, 0x4c, 0x7c, 0x4a, 0xd9, 0x38, 0x88, 0x20, 0xdf, 0x16, + 0x33, 0x21, 0x56, 0x2a, 0x72, 0x36, 0x29, 0x3a, 0xbe, 0x2c, 0x23, 0x25, + 0xb7, 0x26, 0xfb, 0x26, 0xe2, 0x1f, 0x75, 0x22, 0x4d, 0x2c, 0xfb, 0x28, + 0xe8, 0x23, 0xd2, 0x24, 0xc6, 0x18, 0x47, 0xff, 0x03, 0xf4, 0x80, 0xf7, + 0x3e, 0x03, 0x39, 0x11, 0x05, 0x1f, 0x9d, 0x28, 0xfd, 0x1b, 0xe1, 0x0c, + 0x82, 0x08, 0x41, 0x07, 0x88, 0x05, 0xe7, 0x09, 0x84, 0x19, 0xa8, 0x1d, + 0x89, 0x11, 0xda, 0x05, 0x1b, 0x03, 0x02, 0x0a, 0xf9, 0x19, 0x9c, 0x24, + 0x60, 0x22, 0x13, 0x24, 0xe4, 0x31, 0x0d, 0x3a, 0x76, 0x34, 0xbb, 0x30, + 0x20, 0x2d, 0xa8, 0x37, 0x47, 0x4c, 0x9e, 0x4f, 0xc5, 0x4d, 0x2c, 0x51, + 0xe0, 0x53, 0x48, 0x4e, 0x2d, 0x49, 0xce, 0x43, 0x68, 0x3f, 0x79, 0x41, + 0x1c, 0x40, 0x94, 0x42, 0x7a, 0x4b, 0x5a, 0x57, 0x3e, 0x5f, 0x69, 0x5f, + 0x01, 0x50, 0xb0, 0x3c, 0x03, 0x3b, 0xd5, 0x35, 0x19, 0x2c, 0x21, 0x28, + 0x84, 0x22, 0x00, 0x1f, 0x82, 0x17, 0x99, 0x02, 0x9f, 0xfc, 0x68, 0x00, + 0x9a, 0xfc, 0x59, 0x11, 0xe8, 0x24, 0x71, 0x29, 0xf8, 0x37, 0x98, 0x39, + 0x39, 0x27, 0x37, 0x18, 0x95, 0x19, 0x68, 0x22, 0xf3, 0x15, 0xde, 0xfa, + 0xce, 0xed, 0x77, 0xd3, 0x29, 0xae, 0x47, 0xad, 0x23, 0xc4, 0xf5, 0xd0, + 0x38, 0xd2, 0x3b, 0xd4, 0xe2, 0xdf, 0xd3, 0xe4, 0x64, 0xda, 0x6d, 0xdc, + 0xc8, 0xe1, 0xc3, 0xd7, 0x60, 0xd6, 0xa8, 0xe7, 0x81, 0xfa, 0x94, 0x08, + 0x31, 0x10, 0xb0, 0x18, 0xeb, 0x17, 0x6a, 0x01, 0x95, 0x00, 0x6e, 0x0a, + 0xaf, 0x08, 0x75, 0x1b, 0x20, 0x32, 0x3a, 0x31, 0x89, 0x2b, 0x0b, 0x2e, + 0xd9, 0x34, 0xd0, 0x34, 0x86, 0x22, 0x04, 0x1b, 0xc2, 0x18, 0xde, 0x07, + 0xb6, 0xfa, 0xf0, 0xfb, 0x08, 0x04, 0x86, 0x06, 0xd5, 0x07, 0x85, 0x07, + 0xae, 0x10, 0xca, 0x1d, 0x98, 0x2c, 0xb2, 0x34, 0x1f, 0x2f, 0xa1, 0x32, + 0x20, 0x33, 0x16, 0x33, 0x34, 0x33, 0x88, 0x2f, 0xf7, 0x34, 0x56, 0x3e, + 0xde, 0x37, 0x83, 0x27, 0xab, 0x18, 0x57, 0x06, 0xf9, 0xf4, 0xce, 0xe9, + 0x33, 0xef, 0x82, 0xf4, 0x1d, 0xfa, 0x54, 0xfb, 0x3c, 0xef, 0xe4, 0xea, + 0xcd, 0xe3, 0x0e, 0xe4, 0x81, 0xf1, 0xc4, 0xf3, 0xcd, 0xf1, 0xf4, 0xf5, + 0x12, 0xf1, 0xd8, 0xe8, 0xd9, 0xe3, 0x1e, 0xe1, 0xe6, 0xee, 0x27, 0x04, + 0x53, 0x15, 0x98, 0x1e, 0xe8, 0x0e, 0x49, 0xf0, 0x16, 0xe8, 0x9d, 0xfa, + 0xa0, 0x10, 0x95, 0x0c, 0x57, 0xfc, 0xad, 0xf8, 0x3d, 0xf3, 0x44, 0xee, + 0x46, 0xed, 0xda, 0xf7, 0x47, 0x0a, 0xf5, 0x07, 0x43, 0xf5, 0x15, 0xf7, + 0xc6, 0x02, 0xd5, 0xf9, 0x0d, 0xf0, 0x68, 0xf0, 0x50, 0xfc, 0x3a, 0x0a, + 0x16, 0x0e, 0xac, 0x14, 0x22, 0x20, 0x2d, 0x2a, 0x7f, 0x2b, 0xc9, 0x2a, + 0x9c, 0x3b, 0x3d, 0x4a, 0xdb, 0x42, 0xc7, 0x40, 0x39, 0x42, 0x30, 0x3b, + 0xf0, 0x38, 0xbb, 0x2d, 0x68, 0x1f, 0x4d, 0x1d, 0xc5, 0x19, 0x85, 0x11, + 0xed, 0x04, 0xea, 0xf9, 0x7f, 0xf5, 0x04, 0xfa, 0x8e, 0xfe, 0xc4, 0xf9, + 0x48, 0xf0, 0x51, 0xea, 0x2a, 0xeb, 0xda, 0xea, 0x42, 0xe9, 0x05, 0xea, + 0x56, 0x02, 0x9c, 0x18, 0xab, 0x13, 0xe6, 0x0e, 0x1c, 0x08, 0x21, 0x00, + 0xb5, 0xf3, 0xb3, 0xee, 0x19, 0xec, 0xbf, 0xde, 0x9a, 0xd3, 0x41, 0xc8, + 0x21, 0xb9, 0x4d, 0xa5, 0x7b, 0x9f, 0x38, 0xa5, 0xa1, 0xa4, 0x52, 0xa3, + 0x6e, 0xb3, 0x71, 0xbf, 0xea, 0xbf, 0x7a, 0xc9, 0xde, 0xc4, 0xa1, 0xc1, + 0x1f, 0xd5, 0xcb, 0xe9, 0xe2, 0xed, 0x61, 0xf8, 0x63, 0x0b, 0x8a, 0x0e, + 0x21, 0x04, 0x94, 0xee, 0x99, 0xea, 0x9c, 0xfc, 0x11, 0x02, 0x7f, 0xf4, + 0xda, 0xf7, 0xa0, 0x06, 0xab, 0x03, 0xd4, 0x0c, 0x3c, 0x22, 0x9b, 0x2c, + 0x0f, 0x26, 0x98, 0x0b, 0xad, 0xf3, 0xc0, 0xeb, 0x57, 0xee, 0x4c, 0xfd, + 0x71, 0xfc, 0xfd, 0xf2, 0x8d, 0xfb, 0xdd, 0xf0, 0x34, 0xda, 0xff, 0xdf, + 0x35, 0xf4, 0x14, 0x05, 0x7d, 0x19, 0x26, 0x23, 0x82, 0x23, 0x8f, 0x2d, + 0x16, 0x2f, 0x56, 0x1d, 0x76, 0x17, 0xd2, 0x23, 0x50, 0x19, 0x6c, 0x03, + 0x77, 0xef, 0x66, 0xdb, 0xa9, 0xcf, 0x4f, 0xc6, 0x1e, 0xcd, 0xcc, 0xd4, + 0xb9, 0xd7, 0x0f, 0xd9, 0xd3, 0xc9, 0x6d, 0xb7, 0x69, 0xb4, 0x02, 0xc0, + 0x1e, 0xc3, 0x68, 0xc3, 0x55, 0xcb, 0xec, 0xc6, 0x28, 0xbe, 0x14, 0xc9, + 0xbf, 0xda, 0x99, 0xdd, 0x0f, 0xd1, 0xb2, 0xc6, 0xc5, 0xcd, 0xbd, 0xd3, + 0x1e, 0xce, 0xad, 0xc5, 0x09, 0xc4, 0x06, 0xca, 0xab, 0xc9, 0xef, 0xc3, + 0x27, 0xc2, 0x30, 0xc8, 0x6a, 0xd4, 0xb6, 0xdd, 0x85, 0xdb, 0x1f, 0xd9, + 0x4c, 0xdd, 0xaa, 0xda, 0x2f, 0xdb, 0x8a, 0xe0, 0x20, 0xd6, 0x8c, 0xcf, + 0xac, 0xdb, 0x18, 0xed, 0x36, 0x02, 0x6e, 0x11, 0x2e, 0x1d, 0x6f, 0x26, + 0x3a, 0x22, 0x27, 0x19, 0x66, 0x18, 0x34, 0x1c, 0xfd, 0x23, 0x30, 0x30, + 0xf0, 0x26, 0x1f, 0x17, 0x33, 0x1f, 0x48, 0x32, 0x42, 0x37, 0xb7, 0x28, + 0xa5, 0x23, 0x25, 0x22, 0x8e, 0x10, 0x94, 0x04, 0x3c, 0xfc, 0x7c, 0xf0, + 0x79, 0xe7, 0x8c, 0xd9, 0x46, 0xd7, 0x5f, 0xd9, 0x92, 0xd2, 0x98, 0xd7, + 0x7d, 0xd6, 0xf7, 0xc6, 0x93, 0xc3, 0x72, 0xcf, 0x7b, 0xd8, 0x0f, 0xdd, + 0xde, 0xe0, 0xc8, 0xdb, 0x5a, 0xd9, 0x89, 0xd9, 0x24, 0xc9, 0xd5, 0xb6, + 0x4b, 0xad, 0x94, 0xa9, 0xd6, 0xac, 0x4e, 0xa3, 0xa2, 0x97, 0x44, 0x94, + 0x15, 0x91, 0x50, 0x95, 0xd9, 0x99, 0x44, 0x9d, 0x90, 0xa0, 0xaa, 0xa4, + 0x4b, 0xab, 0xf5, 0xb9, 0x25, 0xc7, 0x9e, 0xcc, 0x08, 0xd6, 0x05, 0xda, + 0xfd, 0xe1, 0x86, 0xf0, 0xaa, 0xf9, 0x3f, 0xfa, 0x57, 0xf8, 0x65, 0xf5, + 0x36, 0xef, 0x67, 0xf9, 0x38, 0x03, 0x9b, 0x02, 0x9f, 0x09, 0x7f, 0x19, + 0xbb, 0x21, 0x8e, 0x1c, 0xf5, 0x21, 0x4d, 0x27, 0xd4, 0x2d, 0xb4, 0x33, + 0x4a, 0x1c, 0x70, 0x01, 0x12, 0x00, 0x81, 0x0b, 0xe2, 0x1b, 0xef, 0x2a, + 0x99, 0x24, 0xd5, 0x1b, 0x2d, 0x23, 0x8d, 0x31, 0x74, 0x32, 0xc5, 0x2c, + 0x37, 0x3c, 0x1f, 0x45, 0x7a, 0x3d, 0xd2, 0x37, 0x01, 0x3d, 0x7f, 0x3f, + 0x05, 0x43, 0xb5, 0x44, 0x6b, 0x28, 0xbf, 0x12, 0x68, 0x0a, 0xb9, 0x03, + 0xdd, 0xff, 0x77, 0xfa, 0x2a, 0xfc, 0xe9, 0x00, 0xfa, 0x00, 0x05, 0xfa, + 0x47, 0xf8, 0xc6, 0xf0, 0x39, 0xe6, 0xa5, 0xe8, 0x3f, 0xf2, 0xf9, 0xfe, + 0xe5, 0x08, 0x1e, 0x07, 0x02, 0xfb, 0x44, 0xf1, 0x80, 0xf3, 0x22, 0x04, + 0x18, 0x04, 0xe5, 0xf9, 0x61, 0xfe, 0x08, 0x03, 0xe0, 0x03, 0x22, 0x06, + 0x47, 0x0f, 0xeb, 0x16, 0xa5, 0x1c, 0xa9, 0x21, 0x2f, 0x25, 0x22, 0x25, + 0x16, 0x24, 0x68, 0x26, 0x0c, 0x1f, 0xf1, 0x15, 0x64, 0x17, 0x0b, 0x1c, + 0x55, 0x19, 0x27, 0x1b, 0x91, 0x21, 0x61, 0x27, 0x59, 0x35, 0x23, 0x43, + 0x17, 0x44, 0x22, 0x3e, 0xeb, 0x45, 0x03, 0x51, 0xbc, 0x50, 0xb1, 0x4c, + 0x3f, 0x4d, 0x44, 0x4b, 0x72, 0x51, 0x9c, 0x5a, 0x7b, 0x55, 0x66, 0x60, + 0xf4, 0x5f, 0x2c, 0x53, 0x5e, 0x56, 0xd6, 0x56, 0x76, 0x4f, 0xa4, 0x39, + 0x7b, 0x2f, 0x5d, 0x36, 0x8e, 0x38, 0x9d, 0x33, 0xd8, 0x2c, 0x9e, 0x29, + 0x08, 0x29, 0x30, 0x2c, 0x48, 0x29, 0xd8, 0x1d, 0x67, 0x11, 0x80, 0x12, + 0x19, 0x1c, 0x2b, 0x2a, 0xe2, 0x3b, 0x2d, 0x40, 0x80, 0x36, 0x93, 0x1d, + 0xae, 0x01, 0xc5, 0xfd, 0x59, 0x0f, 0x2e, 0x08, 0x18, 0xf2, 0x7a, 0xe6, + 0xea, 0xcb, 0xdd, 0xb7, 0x11, 0xb6, 0x42, 0xc1, 0xb3, 0xd0, 0x59, 0xd6, + 0xb6, 0xd9, 0x1b, 0xd4, 0xdd, 0xd2, 0x9c, 0xd9, 0x38, 0xdb, 0xf2, 0xdd, + 0x81, 0xe7, 0x24, 0xf4, 0x49, 0xfa, 0xeb, 0x03, 0x12, 0x12, 0xbb, 0x1c, + 0xce, 0x29, 0xbb, 0x35, 0x6e, 0x3a, 0x12, 0x34, 0x90, 0x27, 0xce, 0x1a, + 0x9d, 0x19, 0x78, 0x2c, 0xf3, 0x37, 0xdf, 0x2f, 0xfa, 0x2c, 0x19, 0x3c, + 0x00, 0x42, 0xc2, 0x36, 0x13, 0x2e, 0xdf, 0x21, 0x0f, 0x1d, 0xfc, 0x26, + 0xe1, 0x29, 0x9e, 0x21, 0x5e, 0x19, 0xd5, 0x17, 0x76, 0x1e, 0x72, 0x28, + 0xbd, 0x2c, 0x33, 0x30, 0x3e, 0x37, 0xc3, 0x3c, 0x5c, 0x3c, 0x7c, 0x37, + 0xfc, 0x33, 0x28, 0x36, 0x35, 0x40, 0xf4, 0x42, 0x3d, 0x37, 0x61, 0x27, + 0x96, 0x14, 0x10, 0x04, 0xed, 0xfc, 0xdc, 0xf7, 0x5f, 0xf4, 0x1b, 0xfd, + 0x0e, 0x03, 0xcc, 0x02, 0xc9, 0x04, 0x8b, 0xff, 0x9e, 0xf8, 0xfe, 0xf3, + 0xd3, 0xf3, 0x3b, 0xf9, 0xbe, 0x00, 0xf1, 0x06, 0xf4, 0x0c, 0x6b, 0x10, + 0xad, 0x05, 0xdf, 0x04, 0x5b, 0x13, 0x8c, 0x16, 0x49, 0x0f, 0x48, 0x0c, + 0x0f, 0x14, 0xc4, 0x16, 0x07, 0x12, 0x7b, 0x11, 0xb7, 0x11, 0xc1, 0x14, + 0xf5, 0x1e, 0x20, 0x22, 0x6d, 0x16, 0xce, 0x11, 0x8c, 0x17, 0xa8, 0x13, + 0x07, 0x0e, 0xd4, 0x13, 0x0f, 0x20, 0x64, 0x29, 0xb5, 0x2b, 0xba, 0x26, + 0x22, 0x1e, 0x98, 0x1e, 0x1b, 0x26, 0xdd, 0x34, 0x4a, 0x44, 0xc2, 0x49, + 0xf2, 0x52, 0x11, 0x51, 0x8e, 0x40, 0x7c, 0x40, 0xfe, 0x4a, 0x46, 0x4c, + 0x24, 0x4e, 0x69, 0x4d, 0x96, 0x42, 0xab, 0x3e, 0xfb, 0x3f, 0xe3, 0x3c, + 0xea, 0x37, 0xb5, 0x37, 0x89, 0x3e, 0x8d, 0x3e, 0x59, 0x2e, 0xc2, 0x1e, + 0xd9, 0x1a, 0xd6, 0x16, 0x85, 0x13, 0x8b, 0x11, 0x02, 0x0c, 0xf1, 0x0c, + 0x6f, 0x0d, 0xcc, 0xff, 0xb6, 0xfd, 0x64, 0x06, 0x2b, 0x0f, 0x73, 0x1f, + 0x2c, 0x1d, 0x9e, 0x13, 0x2f, 0x06, 0x60, 0xf7, 0xa7, 0x00, 0xfd, 0xfc, + 0xfe, 0xe7, 0x11, 0xdc, 0xa3, 0xce, 0xeb, 0xba, 0xd6, 0xaf, 0x9a, 0xb6, + 0x16, 0xc3, 0xb1, 0xc5, 0x3e, 0xc5, 0x9d, 0xcf, 0x34, 0xd6, 0xbb, 0xd5, + 0x66, 0xda, 0x43, 0xe2, 0x1b, 0xe9, 0xaa, 0xeb, 0xfd, 0xf8, 0xee, 0x0f, + 0x0a, 0x22, 0x12, 0x3c, 0xaf, 0x43, 0x1e, 0x32, 0xd3, 0x2b, 0x6d, 0x26, + 0xfe, 0x25, 0x98, 0x23, 0xc4, 0x1b, 0x80, 0x24, 0x77, 0x32, 0xa8, 0x3a, + 0xfa, 0x38, 0xd2, 0x3e, 0xe1, 0x41, 0xef, 0x36, 0x4a, 0x2f, 0x6c, 0x2c, + 0x2a, 0x29, 0xc2, 0x24, 0x81, 0x28, 0xc7, 0x26, 0x87, 0x2a, 0x61, 0x32, + 0x29, 0x31, 0xd7, 0x2e, 0x16, 0x2f, 0x0f, 0x3e, 0xae, 0x4d, 0x05, 0x5a, + 0xd8, 0x58, 0xcf, 0x4f, 0x62, 0x4d, 0x54, 0x48, 0x99, 0x42, 0x58, 0x3b, + 0x02, 0x35, 0xdd, 0x24, 0x59, 0x17, 0x00, 0x14, 0x80, 0x0d, 0x03, 0x03, + 0xa0, 0xf9, 0xb6, 0xf9, 0xfe, 0xfb, 0x66, 0x04, 0x85, 0x0b, 0x1b, 0x06, + 0xca, 0x02, 0x37, 0x08, 0xba, 0x0c, 0xd2, 0x13, 0xdd, 0x20, 0xee, 0x29, + 0x21, 0x2a, 0xc8, 0x17, 0xdc, 0x03, 0x8c, 0xff, 0x91, 0x05, 0x3e, 0x07, + 0x19, 0xf6, 0xc7, 0xe8, 0x2e, 0xe2, 0x80, 0xe0, 0xa9, 0xee, 0x66, 0xf3, + 0x5e, 0xf2, 0x06, 0xf3, 0x7f, 0xe6, 0x4a, 0xe4, 0x0c, 0xf0, 0x1d, 0xf3, + 0xde, 0xf4, 0x96, 0xfa, 0xbd, 0xf2, 0xe3, 0xe8, 0x34, 0xf1, 0x68, 0xfb, + 0xa5, 0xf8, 0xbf, 0xed, 0x85, 0xed, 0xe6, 0xf5, 0xff, 0xff, 0x56, 0x09, + 0x4d, 0x08, 0xa6, 0x06, 0x01, 0x08, 0x0f, 0x0f, 0x17, 0x17, 0x72, 0x17, + 0x51, 0x11, 0x0b, 0x0f, 0x36, 0x10, 0x8e, 0x0e, 0x90, 0x10, 0x6a, 0x13, + 0x40, 0x1a, 0x7c, 0x13, 0x79, 0x09, 0x1c, 0x0a, 0x64, 0x06, 0xf7, 0x08, + 0xba, 0x06, 0xcb, 0x07, 0xfa, 0x0f, 0x85, 0x08, 0x08, 0xf7, 0x0e, 0xf3, + 0xee, 0xf4, 0x05, 0xed, 0xc5, 0xea, 0x3b, 0xe9, 0xf9, 0xe9, 0xb0, 0xf0, + 0xba, 0xfa, 0x0d, 0x03, 0x44, 0x03, 0xe0, 0xfa, 0x73, 0xe6, 0xc0, 0xd4, + 0x0f, 0xce, 0xef, 0xcd, 0xb5, 0xc8, 0x34, 0xc2, 0x17, 0xbf, 0x24, 0xaf, + 0xa0, 0x9d, 0x84, 0xa0, 0xe2, 0xa3, 0x63, 0xa0, 0x7f, 0xa6, 0x55, 0xac, + 0x9a, 0xad, 0x6a, 0xaf, 0x23, 0xb4, 0xec, 0xad, 0xb2, 0xb2, 0x1d, 0xca, + 0x94, 0xd4, 0x98, 0xd8, 0x40, 0xce, 0x6c, 0xc9, 0xf0, 0xd0, 0x14, 0xd2, + 0x45, 0xcf, 0x8f, 0xcb, 0x59, 0xd5, 0x6b, 0xda, 0x2d, 0xdf, 0x46, 0xf2, + 0x1c, 0xf8, 0x14, 0xef, 0xa5, 0xf5, 0x8d, 0x00, 0x24, 0xf5, 0xf7, 0xe8, + 0xe3, 0xe9, 0x71, 0xed, 0xab, 0xea, 0x8c, 0xe1, 0x64, 0xd9, 0x77, 0xd4, + 0xd5, 0xd7, 0x43, 0xde, 0xe5, 0xd8, 0x55, 0xdb, 0x65, 0xed, 0x1d, 0xf3, + 0x01, 0xf5, 0x96, 0xf9, 0xc5, 0xfa, 0x08, 0xf9, 0x10, 0xf4, 0x59, 0xf7, + 0xde, 0xf5, 0xaf, 0xf0, 0x42, 0xf0, 0x75, 0xe4, 0x50, 0xd6, 0xb6, 0xc9, + 0xed, 0xbb, 0x03, 0xae, 0xa9, 0x9f, 0x24, 0x9a, 0x28, 0x9c, 0xb1, 0xa2, + 0x6c, 0xad, 0x60, 0xb8, 0x94, 0xb9, 0x90, 0xb1, 0x43, 0xb4, 0x95, 0xc6, + 0x6c, 0xd7, 0x80, 0xde, 0x8e, 0xe5, 0xc8, 0xe6, 0x29, 0xe3, 0x25, 0xe4, + 0x94, 0xe8, 0x6b, 0xf5, 0xad, 0xf8, 0x6c, 0xea, 0xfc, 0xdd, 0x41, 0xd2, + 0x06, 0xca, 0x46, 0xc9, 0x76, 0xbe, 0x2e, 0xb7, 0x92, 0xbe, 0x77, 0xb9, + 0x28, 0xb5, 0x7d, 0xbb, 0x17, 0xbb, 0x79, 0xb7, 0xcd, 0xb0, 0xb1, 0xb4, + 0x17, 0xc8, 0xd3, 0xd4, 0x1d, 0xd4, 0xa6, 0xd3, 0xec, 0xd9, 0x72, 0xdc, + 0x92, 0xdf, 0xf6, 0xe2, 0x92, 0xe2, 0xc6, 0xea, 0xe3, 0xf3, 0x43, 0xf7, + 0x2b, 0xfd, 0x21, 0x08, 0x4e, 0x08, 0xc1, 0xf9, 0x45, 0xea, 0xb2, 0xe2, + 0x1e, 0xde, 0x9f, 0xd5, 0x1e, 0xe4, 0xe3, 0xef, 0x4a, 0xe8, 0x2a, 0xe6, + 0x8f, 0xda, 0x90, 0xd8, 0x59, 0xe3, 0x00, 0xe9, 0x17, 0xe6, 0x77, 0xdf, + 0x94, 0xd7, 0x0f, 0xd0, 0xb5, 0xd6, 0x49, 0xdd, 0x8c, 0xe5, 0x23, 0xf1, + 0x7b, 0xec, 0x1b, 0xe4, 0xbf, 0xe0, 0x57, 0xce, 0xe4, 0xcc, 0x8d, 0xd4, + 0xea, 0xc6, 0x35, 0xc4, 0x3b, 0xb1, 0x85, 0x96, 0xe8, 0x95, 0xb3, 0x9b, + 0xe1, 0x9c, 0xcb, 0x9d, 0xde, 0x9f, 0x45, 0x9d, 0xb2, 0x9b, 0xd7, 0x9f, + 0x7f, 0xab, 0x83, 0xb1, 0x08, 0xb5, 0xcb, 0xbb, 0xb4, 0xbc, 0x1d, 0xb7, + 0x96, 0xb6, 0xe2, 0xbe, 0x21, 0xc9, 0x04, 0xd5, 0xda, 0xd5, 0x07, 0xd5, + 0x64, 0xde, 0xe1, 0xe6, 0x15, 0xde, 0x97, 0xd7, 0xf9, 0xd2, 0xf2, 0xc9, + 0x45, 0xcf, 0xf2, 0xd1, 0xf0, 0xd3, 0x92, 0xd1, 0xba, 0xd4, 0x3f, 0xda, + 0x6f, 0xdd, 0x53, 0xe8, 0xc7, 0xec, 0xa7, 0xed, 0x21, 0xed, 0x9c, 0xee, + 0xce, 0xe5, 0x88, 0xe2, 0x8f, 0xeb, 0xd3, 0xf4, 0xfb, 0xf8, 0x6b, 0xfa, + 0xde, 0x08, 0x36, 0x0e, 0x9b, 0x0d, 0x48, 0x0a, 0x26, 0x01, 0x42, 0x01, + 0x95, 0x07, 0xfa, 0x00, 0x57, 0xee, 0x03, 0xe1, 0x88, 0xdd, 0x73, 0xdd, + 0xc0, 0xd6, 0x38, 0xd5, 0x4f, 0xd4, 0xbd, 0xd2, 0xb4, 0xd1, 0x8c, 0xcc, + 0xd3, 0xca, 0x25, 0xd1, 0x50, 0xd9, 0xed, 0xd8, 0x18, 0xda, 0x64, 0xdd, + 0x7f, 0xe2, 0xdf, 0xe9, 0x03, 0xf6, 0xb4, 0xfe, 0x84, 0xfd, 0x47, 0xfb, + 0x35, 0xff, 0x6d, 0x0c, 0x6c, 0x18, 0x40, 0x2a, 0xd6, 0x33, 0x2e, 0x2d, + 0xc9, 0x25, 0x60, 0x25, 0xcc, 0x2c, 0xd9, 0x2c, 0xb0, 0x24, 0xc5, 0x1c, + 0xed, 0x1b, 0x15, 0x1c, 0x14, 0x1b, 0xac, 0x1c, 0xbc, 0x20, 0xe1, 0x1c, + 0xd0, 0x09, 0x6d, 0xf5, 0x6a, 0xe9, 0x56, 0xe5, 0x38, 0xe9, 0x5f, 0xf6, + 0x70, 0xff, 0x2f, 0x08, 0x35, 0x0e, 0x89, 0x0d, 0x45, 0x14, 0xca, 0x1f, + 0xd4, 0x25, 0x55, 0x26, 0x01, 0x2c, 0x9e, 0x31, 0x19, 0x32, 0x22, 0x29, + 0x70, 0x21, 0x9e, 0x20, 0x95, 0x19, 0xfb, 0x12, 0x77, 0x11, 0x37, 0x17, + 0x39, 0x1d, 0x81, 0x22, 0x71, 0x1f, 0x29, 0x0f, 0x2b, 0x08, 0x17, 0x10, + 0xaa, 0x10, 0x38, 0x11, 0x6c, 0x13, 0xeb, 0x00, 0xa1, 0xfa, 0x70, 0x01, + 0x9e, 0x0e, 0x18, 0x2c, 0x41, 0x3f, 0x07, 0x3d, 0x35, 0x25, 0x03, 0x10, + 0x7b, 0x0e, 0xc9, 0x11, 0x32, 0x12, 0xbb, 0x0f, 0x75, 0xf8, 0xc1, 0xde, + 0x7a, 0xdc, 0x91, 0xdb, 0x26, 0xde, 0x65, 0xe7, 0xeb, 0xec, 0x5b, 0xea, + 0xc5, 0xe6, 0xb6, 0xea, 0x88, 0xf2, 0xc3, 0xf9, 0x18, 0xfb, 0xdd, 0xf6, + 0xe2, 0xf9, 0x67, 0x08, 0x88, 0x1a, 0xc3, 0x2c, 0xa2, 0x31, 0xeb, 0x31, + 0x76, 0x34, 0x22, 0x37, 0x6b, 0x39, 0x07, 0x36, 0x67, 0x36, 0x85, 0x36, + 0x85, 0x2f, 0x5d, 0x27, 0x97, 0x25, 0xee, 0x1b, 0xd7, 0x17, 0xe0, 0x17, + 0x1a, 0x0f, 0x78, 0x15, 0xe4, 0x1a, 0x44, 0x1d, 0x61, 0x1c, 0xaa, 0x19, + 0xa9, 0x14, 0x4b, 0x11, 0xab, 0x1d, 0xb0, 0x28, 0xb8, 0x2d, 0xcf, 0x2d, + 0x47, 0x37, 0xd1, 0x3c, 0x52, 0x3e, 0x68, 0x3e, 0x60, 0x35, 0x77, 0x37, + 0x71, 0x35, 0xef, 0x31, 0xc9, 0x28, 0xc0, 0x1a, 0x9b, 0x16, 0x05, 0x17, + 0x3b, 0x13, 0x51, 0x02, 0xeb, 0xf5, 0x51, 0xee, 0xab, 0xeb, 0xcd, 0xef, + 0x00, 0xef, 0x53, 0xe8, 0xcb, 0xe1, 0x48, 0xe6, 0x2e, 0xf4, 0x5f, 0x05, + 0xde, 0x10, 0xf7, 0x14, 0x2d, 0x1b, 0xdd, 0x22, 0xfe, 0x28, 0x75, 0x2b, + 0xa9, 0x2a, 0x5b, 0x32, 0x0e, 0x3b, 0xf8, 0x36, 0x0a, 0x31, 0xb1, 0x31, + 0x80, 0x35, 0xc0, 0x3e, 0x16, 0x4c, 0x84, 0x50, 0x28, 0x4a, 0x9f, 0x3e, + 0x66, 0x38, 0x22, 0x3e, 0x5b, 0x44, 0x45, 0x41, 0x2e, 0x3b, 0x59, 0x39, + 0x18, 0x3d, 0xf1, 0x4a, 0x3d, 0x58, 0x94, 0x5b, 0xb2, 0x54, 0x2d, 0x4d, + 0xb9, 0x4e, 0xfa, 0x53, 0xc4, 0x52, 0x1b, 0x4e, 0xb7, 0x48, 0xd7, 0x37, + 0x83, 0x2d, 0xe9, 0x27, 0x55, 0x24, 0xe9, 0x2c, 0x7f, 0x2c, 0xa1, 0x27, + 0x3d, 0x2c, 0xbf, 0x37, 0xbc, 0x3a, 0x02, 0x35, 0xe1, 0x2f, 0xbb, 0x27, + 0xaf, 0x23, 0xdf, 0x2b, 0x71, 0x37, 0x5a, 0x3d, 0xbb, 0x3b, 0x2c, 0x32, + 0x24, 0x29, 0xd8, 0x20, 0xcc, 0x25, 0xfd, 0x2e, 0x89, 0x29, 0xdb, 0x29, + 0x79, 0x2d, 0x54, 0x24, 0x54, 0x1b, 0xc3, 0x1c, 0x3d, 0x15, 0xa3, 0x08, + 0x13, 0xfd, 0x4e, 0xef, 0xcd, 0xe8, 0x01, 0xe0, 0xb8, 0xdf, 0xa1, 0xeb, + 0x47, 0xef, 0xc3, 0xf5, 0xbb, 0xef, 0x16, 0xd7, 0x4e, 0xda, 0xa7, 0xec, + 0x6f, 0xfa, 0xa4, 0x0b, 0x75, 0x11, 0xf0, 0x09, 0x27, 0x07, 0x44, 0x04, + 0x88, 0xfc, 0x1d, 0x0b, 0x6e, 0x1c, 0xd0, 0x1a, 0xa1, 0x0d, 0x49, 0x09, + 0x19, 0x12, 0x3b, 0x21, 0x74, 0x31, 0x05, 0x2b, 0x22, 0x2b, 0x93, 0x30, + 0xda, 0x3a, 0x1f, 0x43, 0x18, 0x3d, 0x11, 0x3c, 0x8e, 0x2f, 0x38, 0x2a, + 0xaa, 0x26, 0x33, 0x24, 0x45, 0x2e, 0x26, 0x3a, 0x26, 0x39, 0x64, 0x36, + 0xf4, 0x3c, 0xc2, 0x34, 0x87, 0x37, 0xe5, 0x36, 0x79, 0x34, 0x9c, 0x3b, + 0x67, 0x38, 0x8d, 0x3a, 0x2e, 0x3b, 0x9b, 0x35, 0xc0, 0x2d, 0x32, 0x2c, + 0x83, 0x30, 0x94, 0x35, 0xd4, 0x33, 0x58, 0x2d, 0x6b, 0x25, 0x16, 0x16, + 0x78, 0x0e, 0x4a, 0x0f, 0x38, 0x0d, 0x0d, 0x09, 0x88, 0x04, 0xc4, 0xfc, + 0x90, 0xf9, 0xbc, 0xf6, 0x7a, 0xf0, 0x8e, 0xec, 0x5c, 0xed, 0x06, 0xf2, + 0xe0, 0xf6, 0xb4, 0x00, 0x4c, 0x0a, 0x4b, 0x12, 0xc3, 0x1b, 0x3d, 0x21, + 0x20, 0x1c, 0x39, 0x1d, 0xea, 0x2b, 0x92, 0x3d, 0xa9, 0x48, 0xdd, 0x48, + 0x99, 0x49, 0x1f, 0x48, 0xe0, 0x47, 0x40, 0x50, 0x39, 0x62, 0x5f, 0x6d, + 0xa9, 0x71, 0xfd, 0x6d, 0x23, 0x5b, 0xf8, 0x50, 0xa4, 0x4e, 0x58, 0x54, + 0xba, 0x55, 0x4b, 0x51, 0x04, 0x4f, 0x9f, 0x4a, 0x2f, 0x4e, 0x42, 0x57, + 0x13, 0x5d, 0xc4, 0x5d, 0x28, 0x60, 0xc6, 0x5f, 0x55, 0x61, 0xfa, 0x63, + 0x19, 0x64, 0x09, 0x62, 0xd1, 0x5a, 0x19, 0x57, 0xdf, 0x57, 0x52, 0x57, + 0x86, 0x4c, 0xc3, 0x41, 0x95, 0x38, 0x52, 0x30, 0x68, 0x2e, 0xb7, 0x30, + 0xeb, 0x30, 0x64, 0x26, 0xc5, 0x1b, 0x00, 0x15, 0x14, 0x15, 0x7d, 0x20, + 0x4f, 0x2e, 0xc5, 0x32, 0xc4, 0x30, 0x3f, 0x2a, 0xb2, 0x27, 0x83, 0x30, + 0x30, 0x2d, 0x3d, 0x25, 0x1c, 0x1f, 0x43, 0x14, 0x8e, 0x0e, 0xa2, 0x03, + 0xcd, 0xf2, 0x9e, 0xe5, 0x5f, 0xdb, 0xd1, 0xd3, 0xb1, 0xd6, 0xb9, 0xdf, + 0x36, 0xde, 0x54, 0xd1, 0x05, 0xbb, 0xcd, 0xb2, 0xf1, 0xc4, 0x2c, 0xd4, + 0x57, 0xde, 0x44, 0xe4, 0x46, 0xe2, 0xeb, 0xde, 0x52, 0xe0, 0xd3, 0xe3, + 0x20, 0xeb, 0x92, 0xff, 0x49, 0x08, 0x32, 0x0e, 0xdf, 0x10, 0xbc, 0x0d, + 0x66, 0x1d, 0x04, 0x22, 0x28, 0x18, 0xa4, 0x11, 0x53, 0x11, 0x79, 0x06, + 0x7b, 0xfe, 0xd1, 0x01, 0x64, 0xfc, 0xb3, 0x04, 0xdd, 0x08, 0x44, 0x05, + 0x9f, 0xfa, 0x5f, 0xf7, 0xba, 0x06, 0x39, 0x08, 0xfd, 0x11, 0xc7, 0x17, + 0xec, 0x1a, 0xeb, 0x24, 0x0f, 0x25, 0x7f, 0x23, 0x9e, 0x22, 0xe8, 0x25, + 0xf6, 0x21, 0xc5, 0x20, 0x15, 0x20, 0x07, 0x1d, 0x7f, 0x1c, 0xdf, 0x16, + 0x0f, 0x11, 0x23, 0x03, 0x28, 0xfc, 0x09, 0xf3, 0x40, 0xdf, 0xa6, 0xd0, + 0xdf, 0xc5, 0x8e, 0xc0, 0xa5, 0xb7, 0x89, 0xb4, 0x2b, 0xb4, 0x59, 0xb7, + 0xb8, 0xb8, 0xd8, 0xae, 0xa3, 0xab, 0x90, 0xa9, 0xfa, 0xaf, 0xb2, 0xb2, + 0x89, 0xad, 0x70, 0xac, 0xfc, 0xad, 0x4c, 0xb5, 0x60, 0xb7, 0x33, 0xb9, + 0x42, 0xb4, 0x5f, 0xaf, 0xe5, 0xb2, 0xe5, 0xb6, 0x9d, 0xb8, 0x9d, 0xc0, + 0x71, 0xd1, 0x1a, 0xd4, 0x8b, 0xd5, 0x54, 0xd6, 0x08, 0xd6, 0x1a, 0xdf, + 0x7d, 0xe4, 0x68, 0xeb, 0x3b, 0xf4, 0xb3, 0xfb, 0x20, 0xff, 0x80, 0xfa, + 0xbc, 0xfa, 0xd1, 0x04, 0x92, 0x0a, 0x9a, 0x11, 0xa4, 0x1a, 0xd8, 0x13, + 0x66, 0x0d, 0x29, 0x15, 0xd8, 0x1f, 0x82, 0x2e, 0x7e, 0x37, 0x30, 0x33, + 0x2a, 0x2d, 0xee, 0x23, 0xa9, 0x1c, 0x26, 0x1b, 0xcc, 0x15, 0xce, 0x12, + 0x94, 0x19, 0x35, 0x17, 0xf1, 0x0c, 0x44, 0x0c, 0x79, 0x11, 0x1b, 0x1b, + 0x1c, 0x1f, 0xb6, 0x1e, 0x09, 0x1f, 0xdc, 0x1c, 0x4f, 0x1d, 0x74, 0x24, + 0x9f, 0x2b, 0x13, 0x27, 0x3e, 0x1e, 0x5f, 0x12, 0x40, 0x00, 0xf3, 0xf1, + 0xae, 0xe9, 0x15, 0xe0, 0x69, 0xd9, 0x97, 0xd0, 0xc2, 0xc1, 0x00, 0xbe, + 0xc9, 0xba, 0x42, 0xb3, 0x81, 0xaf, 0x1c, 0xa7, 0xb9, 0xa2, 0x67, 0xa5, + 0x09, 0xa5, 0x0e, 0xa4, 0x9e, 0xa2, 0x36, 0xa4, 0x9d, 0xa7, 0xea, 0xa7, + 0x43, 0xa5, 0xd5, 0xa7, 0xf2, 0xae, 0x35, 0xaf, 0x37, 0xb0, 0x77, 0xaf, + 0x71, 0xb3, 0x3f, 0xba, 0x58, 0xbb, 0xef, 0xc1, 0x30, 0xc9, 0x26, 0xc6, + 0x12, 0xbe, 0x62, 0xc6, 0x63, 0xcf, 0x1a, 0xd6, 0xb1, 0xe3, 0x27, 0xed, + 0x84, 0xf7, 0xed, 0xfd, 0xc1, 0xff, 0x41, 0xfe, 0x88, 0x02, 0x63, 0x08, + 0xf3, 0x09, 0x91, 0x09, 0x7d, 0x05, 0x30, 0x08, 0xc8, 0x09, 0x60, 0x0a, + 0x0c, 0x0c, 0x8f, 0x09, 0x23, 0x06, 0xa4, 0x09, 0x51, 0x11, 0xd6, 0x1a, + 0x45, 0x2a, 0xf8, 0x2a, 0xda, 0x25, 0x0d, 0x2a, 0x7e, 0x2b, 0xd8, 0x2d, + 0xa0, 0x2b, 0x39, 0x22, 0x50, 0x1d, 0x18, 0x18, 0xea, 0x0e, 0xe5, 0x08, + 0x32, 0x01, 0x6f, 0xf6, 0xdb, 0xf3, 0x1f, 0xf5, 0x33, 0xf2, 0x10, 0xeb, + 0xf1, 0xde, 0x26, 0xd4, 0x8f, 0xce, 0xc6, 0xcd, 0xb2, 0xcc, 0x81, 0xc7, + 0xf5, 0xc1, 0xbc, 0xc0, 0x51, 0xc2, 0xdc, 0xbf, 0xd6, 0xbd, 0x0f, 0xc0, + 0xf8, 0xc5, 0xce, 0xc9, 0x10, 0xcf, 0x0d, 0xd7, 0x4d, 0xd4, 0xdd, 0xd0, + 0xfd, 0xd7, 0xac, 0xdc, 0xe6, 0xdd, 0x24, 0xe4, 0x17, 0xe8, 0x4d, 0xe9, + 0x0d, 0xe0, 0xe8, 0xd2, 0x62, 0xcf, 0x5c, 0xd0, 0x9b, 0xdb, 0xd8, 0xe0, + 0x32, 0xe5, 0x7b, 0xee, 0x24, 0xf6, 0xfb, 0x05, 0xc1, 0x10, 0xd1, 0x1b, + 0x72, 0x26, 0xae, 0x25, 0x78, 0x22, 0x40, 0x23, 0x96, 0x27, 0x4c, 0x27, + 0x07, 0x22, 0x37, 0x2a, 0x9e, 0x3c, 0x63, 0x3c, 0x89, 0x29, 0x98, 0x17, + 0x18, 0x16, 0xa3, 0x1a, 0xbf, 0x1d, 0x35, 0x25, 0xae, 0x1b, 0xe1, 0x08, + 0x12, 0x05, 0x90, 0x02, 0x3d, 0x04, 0x73, 0x0f, 0x8c, 0x13, 0x6e, 0x13, + 0x56, 0x12, 0xfb, 0x16, 0xb1, 0x24, 0xa5, 0x2f, 0x3b, 0x32, 0xc6, 0x2e, + 0xb6, 0x2d, 0x42, 0x2a, 0xbe, 0x1f, 0xf9, 0x16, 0xf7, 0x08, 0x0b, 0xef, + 0x8e, 0xd7, 0x69, 0xc3, 0xe1, 0xb6, 0x6f, 0xab, 0x52, 0x9d, 0xc8, 0x99, + 0x49, 0x93, 0x8f, 0x91, 0x83, 0x98, 0x38, 0xa0, 0xb2, 0xa8, 0xbb, 0xa7, + 0x6e, 0x9f, 0x01, 0xa2, 0xbe, 0xab, 0x47, 0xb0, 0x78, 0xb5, 0x59, 0xad, + 0xa6, 0xa7, 0xdd, 0xae, 0xac, 0xae, 0x8c, 0xad, 0x4b, 0xb6, 0x6b, 0xc1, + 0x35, 0xc5, 0xae, 0xcf, 0x02, 0xcf, 0x8a, 0xc9, 0x48, 0xd0, 0x68, 0xcb, + 0x02, 0xc7, 0x53, 0xc6, 0xe7, 0xc1, 0x4f, 0xc6, 0x65, 0xd0, 0xf6, 0xd4, + 0x7c, 0xdb, 0x8a, 0xe5, 0x29, 0xe6, 0xbc, 0xea, 0xa2, 0xf5, 0x3b, 0xfe, + 0x36, 0x0d, 0xe9, 0x18, 0xb5, 0x26, 0x98, 0x37, 0x09, 0x46, 0xe6, 0x53, + 0x62, 0x54, 0x24, 0x54, 0x30, 0x4c, 0x13, 0x3f, 0x1a, 0x38, 0x1f, 0x2e, + 0x0d, 0x2a, 0xac, 0x24, 0xfa, 0x16, 0x3b, 0x0b, 0x91, 0x04, 0x94, 0xfc, + 0x2e, 0x00, 0xd2, 0x05, 0x4f, 0x04, 0xe2, 0xfe, 0xee, 0xf5, 0x07, 0xf8, + 0xef, 0xfb, 0xd8, 0x01, 0xb6, 0xfd, 0x5b, 0xf1, 0x50, 0xe6, 0x64, 0xdb, + 0x29, 0xd8, 0x29, 0xd9, 0x5e, 0xdd, 0x30, 0xd9, 0x20, 0xd5, 0x74, 0xd1, + 0xaf, 0xd0, 0x3b, 0xd0, 0x89, 0xcd, 0x50, 0xd0, 0x51, 0xcd, 0xa8, 0xcd, + 0x01, 0xc9, 0xbb, 0xc5, 0x2f, 0xcc, 0x3b, 0xce, 0x86, 0xce, 0xe4, 0xcf, + 0x75, 0xce, 0xe9, 0xcc, 0x74, 0xd4, 0x16, 0xda, 0x70, 0xe3, 0x33, 0xf0, + 0x5c, 0xef, 0x7f, 0xeb, 0xbd, 0xec, 0x3d, 0xec, 0x14, 0xef, 0x12, 0xf9, + 0x33, 0xfe, 0x5f, 0xfe, 0x18, 0xfa, 0x2e, 0xf5, 0xe2, 0xfc, 0xe2, 0x07, + 0x9f, 0x0a, 0x38, 0x0e, 0xe2, 0x0d, 0x85, 0x0c, 0x4e, 0x17, 0xa1, 0x25, + 0x07, 0x35, 0x74, 0x3a, 0xfa, 0x2f, 0xc6, 0x28, 0x29, 0x2c, 0x90, 0x2e, + 0x77, 0x32, 0x6a, 0x39, 0x90, 0x34, 0x47, 0x2f, 0x3a, 0x2f, 0x99, 0x32, + 0xfb, 0x3a, 0x18, 0x3a, 0x12, 0x38, 0xce, 0x3b, 0xb0, 0x34, 0xf5, 0x29, + 0xf7, 0x2e, 0xfe, 0x37, 0x99, 0x38, 0x37, 0x30, 0x37, 0x24, 0x24, 0x1e, + 0xfb, 0x10, 0xf4, 0x04, 0x16, 0x09, 0xec, 0x06, 0xdf, 0xfa, 0xcf, 0xef, + 0x92, 0xe2, 0xae, 0xdc, 0xf5, 0xe2, 0x5f, 0xe1, 0xd8, 0xd9, 0x78, 0xd2, + 0x00, 0xc2, 0x3f, 0xc2, 0x81, 0xc9, 0x23, 0xbc, 0x57, 0xb7, 0xcf, 0xb8, + 0x23, 0xb5, 0x0f, 0xb8, 0xcb, 0xbc, 0xde, 0xc4, 0x89, 0xd1, 0xdc, 0xd5, + 0x54, 0xd3, 0x6d, 0xdb, 0x45, 0xe0, 0x75, 0xe2, 0xfa, 0xea, 0x58, 0xeb, + 0x0c, 0xe7, 0x6d, 0xe1, 0x40, 0xdc, 0x6c, 0xd4, 0x44, 0xd9, 0xeb, 0xdd, + 0x2a, 0xd7, 0x6a, 0xe2, 0x57, 0xe6, 0x3a, 0xe3, 0xde, 0xea, 0x58, 0xf2, + 0xd8, 0xf9, 0x6b, 0x04, 0xea, 0x0e, 0x4d, 0x18, 0x29, 0x23, 0x32, 0x2a, + 0x2d, 0x35, 0xf3, 0x34, 0xb7, 0x32, 0x76, 0x3e, 0x53, 0x45, 0x2a, 0x4a, + 0x41, 0x4a, 0xe5, 0x48, 0x4b, 0x40, 0x2e, 0x3a, 0xec, 0x40, 0xe0, 0x43, + 0xef, 0x42, 0x22, 0x38, 0x7d, 0x29, 0xaf, 0x1c, 0xaf, 0x11, 0xd2, 0x08, + 0xc7, 0x04, 0x22, 0x00, 0x7c, 0xf4, 0xc7, 0xf3, 0x32, 0xf7, 0xf0, 0xfd, + 0xa7, 0x05, 0xaf, 0x07, 0xa4, 0x0a, 0xd0, 0x05, 0xa2, 0x02, 0xf2, 0x04, + 0x45, 0x08, 0xde, 0x06, 0xdd, 0xfe, 0x20, 0xf8, 0x04, 0xef, 0x4c, 0xe9, + 0x54, 0xeb, 0xab, 0xf4, 0x85, 0xf6, 0x14, 0xef, 0x5c, 0xe9, 0xf6, 0xe7, + 0x9c, 0xeb, 0x86, 0xe5, 0x90, 0xde, 0xa7, 0xdd, 0x07, 0xe0, 0x93, 0xe5, + 0xe3, 0xe9, 0x39, 0xed, 0x4d, 0xee, 0x65, 0xf7, 0xb7, 0x01, 0x4e, 0x08, + 0x08, 0x10, 0x0c, 0x1a, 0x70, 0x20, 0xff, 0x1c, 0x30, 0x22, 0xd2, 0x28, + 0xdc, 0x28, 0x26, 0x2a, 0x65, 0x2d, 0xfd, 0x2e, 0x02, 0x27, 0x94, 0x1d, + 0xce, 0x13, 0x9b, 0x0f, 0xd3, 0x0f, 0xc0, 0x09, 0x64, 0x0a, 0xaf, 0x10, + 0x83, 0x1a, 0x5d, 0x2e, 0x76, 0x3f, 0x60, 0x4c, 0x36, 0x59, 0xbc, 0x5a, + 0x24, 0x58, 0x68, 0x60, 0xba, 0x63, 0xcc, 0x63, 0x59, 0x68, 0x7f, 0x60, + 0x36, 0x5d, 0x43, 0x53, 0x91, 0x38, 0x99, 0x35, 0x46, 0x39, 0xe7, 0x29, + 0x07, 0x16, 0xcf, 0x0e, 0x67, 0x0e, 0x24, 0x0b, 0x66, 0x06, 0xc0, 0x00, + 0x4e, 0x05, 0x12, 0x07, 0xb7, 0xff, 0x00, 0xfd, 0xd6, 0xfc, 0xbb, 0xfa, + 0x17, 0xf5, 0xaa, 0xef, 0x3a, 0xf1, 0xb7, 0xf7, 0x41, 0x02, 0x02, 0x0b, + 0x22, 0x10, 0x16, 0x14, 0x58, 0x0b, 0x18, 0x0b, 0x8f, 0x05, 0xce, 0xf1, + 0x80, 0xef, 0x6c, 0xe6, 0x7a, 0xd9, 0x08, 0xd2, 0x78, 0xce, 0x7f, 0xd0, + 0x4f, 0xca, 0x9a, 0xcc, 0xde, 0xd8, 0xfe, 0xe2, 0x64, 0xf2, 0x9e, 0xfe, + 0x96, 0xfc, 0x48, 0xf8, 0xfc, 0xfd, 0x05, 0x0e, 0x75, 0x12, 0x8b, 0x0d, + 0x96, 0x0f, 0x4a, 0x11, 0xab, 0x16, 0x36, 0x1a, 0xf4, 0x1b, 0x36, 0x21, + 0xf1, 0x22, 0xa0, 0x23, 0xd7, 0x22, 0x47, 0x21, 0xeb, 0x2b, 0xeb, 0x37, + 0x2b, 0x36, 0x46, 0x2c, 0x8b, 0x1f, 0x4c, 0x1e, 0x31, 0x21, 0xd7, 0x23, + 0xed, 0x2f, 0x65, 0x34, 0x95, 0x35, 0x77, 0x3b, 0x80, 0x35, 0x82, 0x31, + 0xbc, 0x31, 0x44, 0x2d, 0xb0, 0x27, 0xaa, 0x1b, 0x7c, 0x20, 0x15, 0x28, + 0xe9, 0x21, 0xb7, 0x1c, 0xc4, 0x11, 0xf0, 0x07, 0x5f, 0xfe, 0xb5, 0xf8, + 0xd7, 0xf9, 0x8b, 0xf6, 0xfc, 0xf6, 0x41, 0xfe, 0x2c, 0xfe, 0x7d, 0xf9, + 0xa8, 0xf9, 0x1b, 0xfd, 0xc5, 0x01, 0x0b, 0x05, 0x2d, 0x0c, 0xd7, 0x10, + 0x4f, 0x0b, 0x0f, 0x01, 0x62, 0xfc, 0x3b, 0xfe, 0xd2, 0xfc, 0xb9, 0xf9, + 0xbd, 0xf9, 0xf3, 0xf8, 0x0a, 0xee, 0x8f, 0xeb, 0xdc, 0xf4, 0xbb, 0xf8, + 0x35, 0xfb, 0xaf, 0xfb, 0x8b, 0xfa, 0x1c, 0xfa, 0x57, 0x04, 0x1c, 0x14, + 0x29, 0x1d, 0x1e, 0x25, 0x0d, 0x26, 0x8e, 0x26, 0xa4, 0x2e, 0x3b, 0x38, + 0x69, 0x38, 0xe9, 0x36, 0xcf, 0x41, 0x8a, 0x3e, 0x22, 0x2f, 0x0d, 0x27, + 0xc7, 0x25, 0xe0, 0x2d, 0xaa, 0x31, 0xbf, 0x31, 0x5a, 0x3a, 0xfd, 0x3a, + 0x3c, 0x30, 0x10, 0x34, 0xf1, 0x3b, 0xf0, 0x3c, 0x1e, 0x42, 0x20, 0x42, + 0x0c, 0x37, 0x65, 0x29, 0xa6, 0x25, 0xaa, 0x2d, 0xd5, 0x35, 0x8c, 0x30, + 0x43, 0x2d, 0xb5, 0x29, 0xbc, 0x1f, 0x1b, 0x21, 0x50, 0x20, 0x9c, 0x1d, + 0x7f, 0x1c, 0x58, 0x1a, 0x6a, 0x13, 0x27, 0x0b, 0x38, 0x0c, 0x31, 0x07, + 0xad, 0xfc, 0x29, 0xf7, 0x16, 0xfc, 0xc1, 0x03, 0xef, 0xfe, 0x74, 0xfd, + 0xf7, 0xff, 0xf5, 0xf4, 0x5a, 0xf8, 0x32, 0x00, 0xed, 0xfc, 0x57, 0x0a, + 0x5d, 0x0e, 0xda, 0x0b, 0x42, 0x09, 0xd0, 0xff, 0xe9, 0x01, 0x99, 0xfb, + 0xb9, 0xf0, 0x97, 0xf1, 0x86, 0xf1, 0xfb, 0xee, 0xcf, 0xee, 0xd0, 0xea, + 0x89, 0xe4, 0x07, 0xdb, 0x56, 0xd3, 0x1f, 0xd4, 0xaf, 0xd1, 0x55, 0xd8, + 0xb4, 0xe7, 0xba, 0xf3, 0xc9, 0x01, 0xe6, 0x0b, 0xee, 0x11, 0xa7, 0x18, + 0xca, 0x20, 0xd2, 0x2f, 0x8b, 0x33, 0x02, 0x27, 0xac, 0x20, 0xe4, 0x15, + 0x8d, 0x0e, 0xb0, 0x0d, 0x9c, 0x0b, 0x91, 0x11, 0x9d, 0x0c, 0x60, 0x09, + 0x37, 0x0f, 0xf3, 0x0d, 0xfc, 0x0e, 0xbb, 0x0d, 0xaf, 0x0c, 0x33, 0x10, + 0x33, 0x0f, 0xee, 0x15, 0xf4, 0x1c, 0x02, 0x1b, 0x42, 0x1f, 0x42, 0x1b, + 0x44, 0x18, 0xf5, 0x1c, 0x46, 0x1d, 0x20, 0x23, 0xd0, 0x25, 0x71, 0x2a, + 0x08, 0x2b, 0x98, 0x23, 0x46, 0x20, 0x8e, 0x1c, 0x9f, 0x1e, 0x6e, 0x1c, + 0x32, 0x11, 0x4f, 0x05, 0xea, 0xf6, 0x1a, 0xeb, 0xb7, 0xe3, 0xad, 0xdf, + 0x78, 0xe4, 0x64, 0xe8, 0xec, 0xea, 0x35, 0xf5, 0xda, 0xff, 0x4f, 0x0f, + 0x33, 0x19, 0x5a, 0x1b, 0x99, 0x1c, 0xad, 0x1b, 0x92, 0x1d, 0x41, 0x13, + 0x28, 0x06, 0x78, 0x07, 0xb8, 0x0b, 0xf3, 0x0c, 0xa0, 0x12, 0x09, 0x19, + 0x3b, 0x19, 0xe3, 0x19, 0x9c, 0x1d, 0xa9, 0x1e, 0x4b, 0x1e, 0x97, 0x1e, + 0x4f, 0x1c, 0x79, 0x21, 0xeb, 0x24, 0x29, 0x28, 0x65, 0x30, 0xf2, 0x32, + 0x17, 0x39, 0x43, 0x3c, 0x77, 0x41, 0xab, 0x45, 0x9f, 0x44, 0xd6, 0x47, + 0x2b, 0x46, 0x20, 0x49, 0x1b, 0x50, 0x2e, 0x4d, 0xd9, 0x4a, 0x41, 0x4a, + 0x9d, 0x42, 0xd0, 0x37, 0xfc, 0x2b, 0xf9, 0x1f, 0x79, 0x17, 0x57, 0x0f, + 0xde, 0x03, 0x62, 0xfe, 0xf8, 0x00, 0x8f, 0x0c, 0xf3, 0x17, 0x59, 0x17, + 0x88, 0x16, 0x1e, 0x18, 0xed, 0x1c, 0xd4, 0x1b, 0xeb, 0x1a, 0x5b, 0x1d, + 0x74, 0x11, 0x93, 0x09, 0xc0, 0x0b, 0xed, 0x09, 0x77, 0x08, 0x32, 0x06, + 0x60, 0xfe, 0x11, 0xf5, 0x1c, 0xef, 0x53, 0xee, 0x92, 0xe5, 0x69, 0xdd, + 0xb3, 0xd8, 0xc2, 0xd7, 0x24, 0xdc, 0xda, 0xd5, 0xdb, 0xda, 0xbc, 0xe1, + 0xbe, 0xe5, 0x84, 0xef, 0xa9, 0xef, 0x2b, 0xe8, 0x00, 0xe3, 0x86, 0xe5, + 0x5b, 0xe3, 0x54, 0xe4, 0x46, 0xe4, 0x00, 0xdc, 0x85, 0xde, 0xce, 0xe1, + 0xe3, 0xdf, 0x82, 0xe6, 0x71, 0xec, 0x9a, 0xf2, 0x29, 0xf4, 0x25, 0xe6, + 0xc1, 0xd9, 0xd1, 0xd1, 0x39, 0xc9, 0xbe, 0xc4, 0x75, 0xcd, 0x41, 0xd8, + 0x6c, 0xe8, 0x6b, 0xf5, 0xa8, 0xf4, 0x9a, 0xf6, 0x3d, 0xf5, 0x4c, 0xfc, + 0xe0, 0x03, 0xce, 0xfe, 0x0c, 0xf2, 0xbb, 0xe8, 0x9a, 0xe3, 0xf9, 0xe0, + 0x6a, 0xe6, 0xc4, 0xe9, 0xe2, 0xe9, 0xeb, 0xe7, 0x75, 0xe8, 0xbb, 0xe2, + 0x68, 0xe1, 0xf0, 0xe2, 0x9d, 0xe0, 0x86, 0xdf, 0x1a, 0xdc, 0x8e, 0xe0, + 0x99, 0xea, 0x19, 0xf5, 0x77, 0xf3, 0x20, 0xf3, 0xaa, 0xf4, 0xb9, 0xf3, + 0xa8, 0xf8, 0xed, 0xf8, 0xe8, 0xf5, 0x09, 0xee, 0x95, 0xe1, 0xa9, 0xdb, + 0x24, 0xdc, 0xd7, 0xd5, 0x58, 0xd2, 0x47, 0xcb, 0xdf, 0xc6, 0x9a, 0xc7, + 0xa6, 0xc4, 0x5a, 0xc4, 0xa0, 0xbd, 0x5e, 0xbd, 0xaa, 0xbb, 0x82, 0xbb, + 0x07, 0xc2, 0x39, 0xcc, 0xc6, 0xda, 0xd9, 0xe1, 0xe8, 0xed, 0xd0, 0xf6, + 0x69, 0xf1, 0x3e, 0xeb, 0x68, 0xeb, 0x3e, 0xee, 0x8a, 0xef, 0xbe, 0xe9, + 0x95, 0xe4, 0x5a, 0xe0, 0x8d, 0xe0, 0xd2, 0xe7, 0xea, 0xe8, 0x39, 0xe8, + 0x13, 0xe6, 0x29, 0xef, 0xff, 0xfb, 0x73, 0x01, 0x1f, 0x0a, 0xdc, 0x08, + 0x9d, 0x07, 0x7a, 0x0d, 0xc7, 0x0f, 0x96, 0x1a, 0x7a, 0x20, 0x7e, 0x1d, + 0x45, 0x21, 0xcf, 0x1b, 0x38, 0x12, 0xb3, 0x11, 0x96, 0x15, 0xa9, 0x14, + 0x17, 0x0b, 0xcb, 0x00, 0x34, 0x00, 0x2c, 0xfe, 0x6f, 0xf9, 0x54, 0xfd, + 0x2f, 0xfb, 0xcf, 0xf8, 0x88, 0xef, 0x2a, 0xef, 0xb1, 0xf0, 0xb6, 0xe7, + 0x69, 0xf5, 0x95, 0xf7, 0xa0, 0xf7, 0x6b, 0xff, 0x41, 0x02, 0x24, 0x16, + 0xff, 0x20, 0x7d, 0x1e, 0xfb, 0x19, 0x78, 0x0f, 0xdf, 0x0b, 0x22, 0x07, + 0x0b, 0xfe, 0xbc, 0xf8, 0xd2, 0xf2, 0x6b, 0xf1, 0x40, 0xee, 0x0d, 0xed, + 0xeb, 0xe6, 0xf2, 0xdd, 0x84, 0xe3, 0x0f, 0xe1, 0xc5, 0xdd, 0x01, 0xe7, + 0x4a, 0xef, 0xd0, 0xec, 0x1f, 0xe4, 0x58, 0xe1, 0xbe, 0xe5, 0xf9, 0xea, + 0xb7, 0xf3, 0x9d, 0x01, 0xa2, 0x0a, 0x00, 0x0e, 0x8c, 0x0d, 0x7d, 0x11, + 0x3e, 0x15, 0x89, 0x20, 0x4c, 0x26, 0x17, 0x1b, 0x89, 0x11, 0x48, 0x01, + 0x26, 0xfa, 0xc4, 0xf7, 0x71, 0xf0, 0x2d, 0xe9, 0xe3, 0xe3, 0xd9, 0xe0, + 0x95, 0xdd, 0x41, 0xe3, 0x6c, 0xea, 0x1f, 0xf6, 0x00, 0xfe, 0x51, 0x03, + 0x90, 0x07, 0xa2, 0x09, 0x99, 0x16, 0x6d, 0x22, 0x1d, 0x1d, 0xc5, 0x11, + 0x5a, 0x10, 0x30, 0x11, 0x90, 0x15, 0xc3, 0x18, 0xba, 0x1b, 0xf3, 0x1a, + 0x76, 0x1c, 0x87, 0x1e, 0xe2, 0x1a, 0xb4, 0x21, 0x14, 0x21, 0xc7, 0x1c, + 0x34, 0x15, 0xe7, 0x10, 0x1b, 0x0f, 0x2b, 0x0d, 0xc2, 0x13, 0xee, 0x14, + 0xf3, 0x15, 0x5a, 0x12, 0x7e, 0x15, 0x18, 0x1f, 0x49, 0x23, 0x1d, 0x20, + 0xf6, 0x16, 0x27, 0x0f, 0x77, 0x07, 0xcc, 0x02, 0x64, 0x05, 0xbb, 0x0a, + 0x8c, 0x06, 0xfc, 0xfe, 0x84, 0xf4, 0xfb, 0xf2, 0xfc, 0xf4, 0x39, 0xf4, + 0xc8, 0xf9, 0x66, 0xfa, 0x73, 0xf8, 0x1e, 0xf9, 0xbb, 0xff, 0xc1, 0x07, + 0x0e, 0x15, 0x98, 0x20, 0x30, 0x25, 0xb5, 0x25, 0xe5, 0x26, 0xc5, 0x28, + 0x55, 0x23, 0xb4, 0x1a, 0x02, 0x14, 0x3d, 0x19, 0xef, 0x14, 0x14, 0x0e, + 0x27, 0x16, 0x58, 0x21, 0xda, 0x1f, 0x82, 0x1b, 0xb9, 0x22, 0x12, 0x21, + 0xa5, 0x1d, 0x4b, 0x12, 0x35, 0x08, 0x23, 0x0d, 0xc9, 0x0c, 0x60, 0x0a, + 0xce, 0x0e, 0x96, 0x11, 0x52, 0x10, 0xfd, 0x0a, 0xf5, 0x04, 0x93, 0x08, + 0x42, 0x0a, 0x42, 0x11, 0x0a, 0x12, 0x8e, 0x0b, 0xc2, 0x06, 0xc2, 0xf9, + 0x84, 0xf5, 0x46, 0xee, 0x11, 0xeb, 0xa7, 0xee, 0x7a, 0xe5, 0x99, 0xe6, + 0xe1, 0xea, 0xb8, 0xe6, 0x6f, 0xe9, 0x70, 0xeb, 0x3a, 0xef, 0x9d, 0xed, + 0xcc, 0xed, 0x03, 0xf9, 0x0d, 0xfb, 0xce, 0xfd, 0xe1, 0x02, 0xc5, 0xfa, + 0x1a, 0xed, 0xf6, 0xe9, 0xe5, 0xdb, 0x5f, 0xd7, 0x4d, 0xdc, 0x09, 0xd3, + 0xef, 0xd2, 0xdf, 0xc6, 0xb3, 0xc0, 0xc6, 0xc6, 0xd8, 0xd0, 0x7b, 0xdb, + 0xbf, 0xe1, 0x34, 0xe9, 0x61, 0xdf, 0xb6, 0xda, 0x25, 0xdb, 0xdb, 0xde, + 0x61, 0xe0, 0x2b, 0xde, 0x90, 0xe3, 0x79, 0xe9, 0xf2, 0xec, 0x50, 0xed, + 0x86, 0xf3, 0x5a, 0xf0, 0x3b, 0xf5, 0x72, 0x00, 0x60, 0xff, 0xa7, 0xfe, + 0xb2, 0xfc, 0x51, 0xf6, 0xde, 0xe5, 0x8f, 0xdd, 0xd1, 0xda, 0x80, 0xd5, + 0x06, 0xd1, 0x8e, 0xc5, 0x65, 0xbe, 0x65, 0xc5, 0x7c, 0xd1, 0x2c, 0xdb, + 0x4b, 0xe5, 0x83, 0xe8, 0xa6, 0xe6, 0xf1, 0xef, 0x95, 0x00, 0xd4, 0x09, + 0x19, 0x0f, 0xd5, 0x12, 0x3b, 0x12, 0x61, 0x08, 0x5d, 0xfa, 0x1b, 0xfb, + 0xd6, 0xfc, 0x2a, 0xfb, 0xf6, 0xf8, 0x27, 0xf2, 0x08, 0xf4, 0x89, 0xf6, + 0x1c, 0xf7, 0x9a, 0xfa, 0xe8, 0xf5, 0x5e, 0xf5, 0xe0, 0xfd, 0x33, 0x00, + 0xf8, 0xfc, 0x39, 0xfa, 0x0f, 0xfa, 0xc5, 0xf8, 0x11, 0xf9, 0x0c, 0xfb, + 0x4d, 0x04, 0x05, 0x0c, 0x5a, 0x09, 0x26, 0x0a, 0x80, 0x06, 0x6e, 0x02, + 0xff, 0x00, 0x9f, 0x02, 0x1d, 0x02, 0x02, 0x00, 0x8e, 0x00, 0x16, 0xfd, + 0x61, 0xfe, 0x79, 0xfa, 0x9c, 0xf9, 0xce, 0xf5, 0xf6, 0xf1, 0x93, 0xfb, + 0xa1, 0xfe, 0x3f, 0x06, 0xac, 0x13, 0x85, 0x21, 0xb0, 0x2b, 0x3c, 0x30, + 0x23, 0x35, 0xde, 0x33, 0x2e, 0x2f, 0xe7, 0x30, 0x8d, 0x34, 0x9f, 0x33, + 0x02, 0x2e, 0x36, 0x26, 0xe7, 0x1f, 0xab, 0x17, 0x54, 0x10, 0xe4, 0x0d, + 0xa0, 0x0c, 0x6c, 0x02, 0x56, 0xfe, 0x1f, 0x00, 0xa4, 0xfb, 0xd5, 0xfa, + 0x5e, 0xfa, 0xca, 0x02, 0x4c, 0x05, 0xcb, 0x02, 0xb7, 0x0c, 0x22, 0x12, + 0xf6, 0x0f, 0xd7, 0x0d, 0xfa, 0x0f, 0xb3, 0x10, 0xb6, 0x10, 0x56, 0x15, + 0xb5, 0x10, 0x44, 0x0d, 0x5e, 0x12, 0xcf, 0x0a, 0x17, 0x05, 0x00, 0xfe, + 0x76, 0xfa, 0x3a, 0xfb, 0x3d, 0xf2, 0x52, 0xf2, 0xa2, 0xec, 0xcc, 0xeb, + 0xbe, 0xf0, 0x5f, 0xf3, 0xf8, 0xf4, 0x69, 0xeb, 0x39, 0xf0, 0xee, 0xfa, + 0x0e, 0xfe, 0xcc, 0x00, 0x5c, 0xfd, 0xa2, 0xf5, 0x6f, 0xf0, 0xae, 0xe9, + 0xcf, 0xdd, 0xdb, 0xd6, 0x10, 0xdd, 0x45, 0xdd, 0xe1, 0xd8, 0xfe, 0xe0, + 0x12, 0xe0, 0xd9, 0xe3, 0xb6, 0xec, 0x52, 0xe4, 0x32, 0xe0, 0xe2, 0xe2, + 0x6f, 0xe7, 0x34, 0xeb, 0x7a, 0xeb, 0x8b, 0xe9, 0x33, 0xe8, 0x6f, 0xea, + 0xb3, 0xe7, 0xa3, 0xf0, 0x47, 0xfc, 0x4d, 0x02, 0x8a, 0x0f, 0x49, 0x0d, + 0xfc, 0x08, 0xce, 0x09, 0x09, 0x05, 0xdf, 0xfe, 0x8a, 0xfb, 0x93, 0xf6, + 0xe8, 0xee, 0x4d, 0xea, 0x21, 0xda, 0x95, 0xcd, 0x7b, 0xca, 0xf0, 0xc9, + 0x57, 0xd1, 0x53, 0xe0, 0x0e, 0xe9, 0x53, 0xea, 0x5d, 0xed, 0xf6, 0xf3, + 0xc1, 0x01, 0x0b, 0x08, 0xf9, 0x13, 0x84, 0x16, 0xd8, 0x10, 0xa5, 0x0d, + 0x42, 0x04, 0x6f, 0xfe, 0x9f, 0xf6, 0xfe, 0xf8, 0x32, 0xf6, 0x15, 0xf1, + 0x00, 0xee, 0x6b, 0xee, 0x7b, 0xf2, 0x9c, 0xf1, 0x83, 0xf6, 0xcf, 0xf7, + 0x36, 0xf7, 0x74, 0xf3, 0x33, 0xf3, 0xd2, 0xf3, 0x68, 0xf4, 0x51, 0xf6, + 0x94, 0xfc, 0x93, 0xfd, 0xc6, 0xf9, 0xe5, 0xff, 0xad, 0xfd, 0xe4, 0xfb, + 0x5a, 0xf8, 0xb9, 0xfb, 0xba, 0x00, 0x47, 0x02, 0x9d, 0x04, 0x37, 0x02, + 0x41, 0x01, 0x8b, 0xf8, 0x8f, 0xf9, 0x62, 0xf6, 0x1f, 0xf1, 0x61, 0xf3, + 0xcf, 0xf8, 0x6f, 0xfd, 0x53, 0xfa, 0x13, 0x01, 0xdb, 0x0a, 0xb6, 0x16, + 0xf9, 0x1d, 0x22, 0x24, 0xb9, 0x2d, 0x58, 0x33, 0xe7, 0x31, 0x36, 0x2b, + 0x14, 0x28, 0xe5, 0x1d, 0xe9, 0x13, 0x56, 0x0f, 0x11, 0x01, 0x01, 0xf4, + 0x93, 0xf4, 0x7f, 0xf1, 0x9e, 0xeb, 0x2c, 0xed, 0x32, 0xf3, 0x35, 0xf0, + 0x89, 0xf1, 0x44, 0xf9, 0x22, 0xf2, 0x1f, 0xf5, 0x58, 0xf9, 0xf2, 0xf7, + 0x63, 0xfd, 0x66, 0x09, 0x86, 0x0b, 0x35, 0x07, 0xa2, 0x09, 0x02, 0x00, + 0x61, 0xfe, 0x04, 0xff, 0x6e, 0xfd, 0x7e, 0xfd, 0x81, 0xfc, 0x02, 0xff, + 0xd9, 0xfb, 0x65, 0xf5, 0xf9, 0xf1, 0x20, 0xfa, 0x9e, 0xf4, 0x1e, 0xf5, + 0xb6, 0xfc, 0xaf, 0xf3, 0x1d, 0xf3, 0x30, 0xf5, 0xcc, 0xee, 0xc4, 0xe9, + 0xba, 0xf0, 0x54, 0xf4, 0xf5, 0xf7, 0x3b, 0xf9, 0xf9, 0xf7, 0x24, 0xfa, + 0x71, 0xf6, 0x2a, 0xf5, 0x05, 0xef, 0x06, 0xed, 0xda, 0xeb, 0x80, 0xe3, + 0xac, 0xe2, 0xda, 0xea, 0x0a, 0xeb, 0x97, 0xe7, 0x3a, 0xf0, 0x72, 0xf4, + 0x6a, 0xf1, 0xf1, 0xf4, 0xd1, 0xf9, 0x0e, 0xf8, 0x82, 0xfe, 0xbc, 0x00, + 0x82, 0xfe, 0xe5, 0x01, 0x1d, 0x02, 0x40, 0x02, 0x4b, 0xff, 0x1e, 0xfe, + 0x67, 0x00, 0xc1, 0x02, 0xa9, 0x01, 0x20, 0x07, 0x48, 0x02, 0xd5, 0xf6, + 0xc0, 0xf4, 0xfc, 0xea, 0x29, 0xe8, 0x40, 0xeb, 0x6e, 0xe8, 0x2a, 0xde, + 0x32, 0xdc, 0x89, 0xdd, 0x2f, 0xe1, 0x78, 0xec, 0x10, 0xf1, 0xc0, 0xf6, + 0x42, 0xfa, 0x65, 0x05, 0x30, 0x13, 0xfe, 0x19, 0x08, 0x1e, 0xb1, 0x1e, + 0xf4, 0x19, 0x9e, 0x13, 0xa6, 0x10, 0xbf, 0x0a, 0x9e, 0x08, 0xc5, 0x05, + 0x66, 0xfc, 0x4b, 0xf0, 0x0b, 0xf2, 0xb4, 0xf6, 0x91, 0xf7, 0x78, 0xfd, + 0x10, 0xf7, 0x4b, 0xef, 0x54, 0xef, 0x4a, 0xf6, 0xe5, 0xfd, 0xfb, 0x05, + 0x21, 0x09, 0xe1, 0x05, 0x11, 0x07, 0x70, 0x07, 0x9b, 0x0f, 0xc4, 0x14, + 0x1b, 0x14, 0x3b, 0x15, 0x4f, 0x10, 0xf1, 0x0f, 0xb6, 0x10, 0x9d, 0x12, + 0xb1, 0x17, 0x0d, 0x14, 0xf6, 0x0d, 0x54, 0x03, 0x9b, 0xfc, 0xec, 0x02, + 0x62, 0x06, 0xf8, 0x06, 0xef, 0x04, 0xa4, 0x04, 0xaa, 0x0b, 0xbb, 0x10, + 0xb3, 0x13, 0x07, 0x19, 0x3f, 0x1e, 0x2f, 0x21, 0xee, 0x22, 0x0b, 0x21, + 0x90, 0x1c, 0xbe, 0x18, 0xfb, 0x14, 0x09, 0x11, 0xc2, 0x0d, 0x92, 0x0b, + 0xbb, 0x08, 0xcd, 0x05, 0x7c, 0xfc, 0xbb, 0xf4, 0x6f, 0xfd, 0x60, 0x00, + 0x2b, 0xfe, 0xac, 0xff, 0x07, 0xfc, 0xa5, 0xfd, 0xe2, 0x00, 0xee, 0x01, + 0x65, 0x02, 0xda, 0x08, 0xa3, 0x11, 0x08, 0x13, 0x5a, 0x10, 0xa0, 0x0c, + 0x26, 0x0d, 0x8c, 0x0c, 0xbf, 0x0c, 0xa3, 0x0b, 0x6a, 0x0a, 0xc3, 0x08, + 0x66, 0x04, 0x54, 0x06, 0x56, 0x03, 0x76, 0xfb, 0x46, 0xfa, 0x88, 0xfc, + 0x15, 0xfd, 0x90, 0xfb, 0x43, 0xfb, 0x34, 0x00, 0x2a, 0x01, 0x9b, 0xfb, + 0xc3, 0xf9, 0x95, 0xfd, 0x5e, 0x05, 0x4f, 0x07, 0xaa, 0x04, 0x59, 0xff, + 0x6b, 0xf8, 0xaa, 0xfb, 0x5c, 0xfe, 0xee, 0xf8, 0x33, 0xf4, 0xe2, 0xec, + 0xce, 0xeb, 0x14, 0xef, 0xeb, 0xe9, 0xb5, 0xec, 0x99, 0xf3, 0x8d, 0xf0, + 0x68, 0xed, 0xd0, 0xec, 0x5e, 0xe8, 0x86, 0xeb, 0xd2, 0xee, 0x12, 0xec, + 0x6e, 0xf3, 0xc2, 0xf7, 0x07, 0xfc, 0xee, 0x00, 0x00, 0x02, 0x61, 0x05, + 0x96, 0x04, 0xe5, 0x04, 0x9a, 0x04, 0x25, 0x05, 0x84, 0x06, 0xe1, 0x03, + 0x89, 0xfb, 0x54, 0xf3, 0x26, 0xf4, 0x7f, 0xf6, 0x5a, 0xf1, 0xaa, 0xec, + 0xa7, 0xe6, 0x1b, 0xd8, 0x39, 0xd3, 0x10, 0xd4, 0x03, 0xd9, 0xc5, 0xe1, + 0xa6, 0xe3, 0xdb, 0xe6, 0x6a, 0xeb, 0x60, 0xf1, 0xc8, 0xf7, 0x50, 0xff, + 0x4d, 0x04, 0x58, 0x05, 0xbe, 0x01, 0x63, 0xfe, 0xe9, 0xfa, 0xc3, 0xf5, + 0xd8, 0xfa, 0x10, 0xf8, 0x46, 0xed, 0xbd, 0xe8, 0x47, 0xef, 0x59, 0xf5, + 0xac, 0xf3, 0xd7, 0xf5, 0x30, 0xf6, 0x6a, 0xf9, 0x0e, 0xfd, 0xdc, 0xfd, + 0xc1, 0x00, 0x3c, 0x06, 0xe5, 0x07, 0xcb, 0x09, 0x68, 0x0d, 0x0b, 0x0e, + 0x23, 0x16, 0x72, 0x17, 0xfe, 0x14, 0xae, 0x15, 0xb4, 0x10, 0xcf, 0x09, + 0x4b, 0x0a, 0xcf, 0x0b, 0xea, 0x05, 0x60, 0x03, 0x73, 0x00, 0x99, 0xfe, + 0x8d, 0xfe, 0x1a, 0x01, 0x75, 0x07, 0x5e, 0x0d, 0xfc, 0x0f, 0x55, 0x0e, + 0x74, 0x0f, 0xc2, 0x10, 0xae, 0x13, 0x62, 0x17, 0x36, 0x19, 0xd4, 0x1a, + 0x82, 0x17, 0x26, 0x14, 0xa9, 0x14, 0x16, 0x12, 0x1b, 0x11, 0xb5, 0x0f, + 0xf7, 0x0d, 0xa0, 0x10, 0xce, 0x0d, 0x31, 0x0b, 0x7e, 0x08, 0x9e, 0x06, + 0x4f, 0x07, 0x7a, 0x05, 0xf2, 0x01, 0x68, 0xff, 0xc9, 0x02, 0x5a, 0x05, + 0x27, 0x06, 0xb3, 0x09, 0x80, 0x0c, 0x8f, 0x0c, 0x96, 0x0f, 0x1f, 0x0d, + 0x38, 0x0a, 0xf9, 0x0d, 0xe8, 0x0c, 0x0f, 0x0e, 0xd5, 0x0f, 0xed, 0x0d, + 0x29, 0x0a, 0xef, 0x09, 0x17, 0x09, 0x18, 0x05, 0x7b, 0x04, 0xd1, 0x02, + 0xad, 0x00, 0x60, 0xfe, 0x46, 0xff, 0x22, 0xff, 0x8a, 0xfd, 0x30, 0xfe, + 0x7e, 0xfd, 0xe1, 0xfc, 0xc5, 0xfa, 0x58, 0xfd, 0x13, 0x05, 0xe1, 0x08, + 0xec, 0x09, 0xb5, 0x05, 0x6e, 0x02, 0x70, 0x04, 0x18, 0x02, 0x76, 0x00, + 0x5b, 0xfe, 0x16, 0xf9, 0xd7, 0xf1, 0x16, 0xef, 0x59, 0xef, 0xe0, 0xee, + 0x22, 0xf3, 0xd8, 0xf1, 0x1e, 0xf2, 0x3b, 0xef, 0x07, 0xec, 0xbe, 0xec, + 0x02, 0xe9, 0xf4, 0xef, 0x61, 0xf0, 0xf4, 0xeb, 0xa1, 0xef, 0x22, 0xf1, + 0xe7, 0xf4, 0x54, 0xf9, 0x6a, 0xfa, 0xd6, 0xfa, 0xbf, 0xfd, 0x60, 0x00, + 0xe2, 0x00, 0xef, 0xff, 0x5a, 0xfc, 0x1e, 0xf4, 0xe3, 0xeb, 0xd8, 0xe6, + 0x9b, 0xe3, 0xef, 0xdf, 0xeb, 0xd7, 0xb1, 0xd2, 0x26, 0xce, 0x3e, 0xcf, + 0x52, 0xd8, 0x34, 0xda, 0xae, 0xd9, 0x2b, 0xdb, 0x80, 0xdc, 0x79, 0xe0, + 0x60, 0xe8, 0x92, 0xf0, 0xe2, 0xf0, 0x4d, 0xeb, 0xc0, 0xe6, 0x76, 0xe3, + 0xa5, 0xdf, 0x54, 0xdf, 0x07, 0xe1, 0xb0, 0xdc, 0xe5, 0xd8, 0x3c, 0xd6, + 0x36, 0xd4, 0x2b, 0xd9, 0x2e, 0xda, 0xb7, 0xd7, 0x34, 0xd6, 0x12, 0xd4, + 0xd9, 0xd3, 0xd7, 0xd6, 0x92, 0xdd, 0x0d, 0xe2, 0x84, 0xe8, 0x53, 0xeb, + 0x72, 0xe7, 0x29, 0xe8, 0x05, 0xea, 0x90, 0xed, 0x6c, 0xf0, 0x99, 0xf1, + 0xd1, 0xf0, 0x4a, 0xea, 0x5e, 0xe7, 0x38, 0xe9, 0x3c, 0xe9, 0xbe, 0xe8, + 0x72, 0xe8, 0x55, 0xe7, 0xa3, 0xe7, 0x2a, 0xe8, 0xc2, 0xe9, 0x6c, 0xec, + 0x54, 0xee, 0x1e, 0xf2, 0xe1, 0xf6, 0x40, 0xfa, 0x0a, 0xff, 0x0a, 0x06, + 0xa7, 0x07, 0x67, 0x08, 0x89, 0x0a, 0xa1, 0x08, 0xaf, 0x07, 0x00, 0x07, + 0x4e, 0x06, 0x77, 0x07, 0xda, 0x05, 0x55, 0x04, 0xbd, 0x08, 0xf0, 0x0b, + 0xf4, 0x0a, 0x04, 0x0b, 0x3a, 0x0a, 0xbe, 0x09, 0xab, 0x0a, 0x54, 0x0a, + 0xd8, 0x0b, 0x38, 0x0c, 0x55, 0x0a, 0xdf, 0x0d, 0x0a, 0x12, 0xa6, 0x17, + 0x5a, 0x20, 0x92, 0x24, 0x76, 0x23, 0xe0, 0x1f, 0x5f, 0x20, 0xaa, 0x23, + 0x68, 0x27, 0x37, 0x27, 0xdf, 0x23, 0xd8, 0x24, 0x2a, 0x23, 0xa3, 0x23, + 0xac, 0x25, 0xd4, 0x21, 0xd5, 0x1f, 0x84, 0x1c, 0x7d, 0x19, 0x6d, 0x1c, + 0x07, 0x20, 0xc2, 0x20, 0x70, 0x1d, 0x1a, 0x1c, 0x66, 0x21, 0x6e, 0x2b, + 0x47, 0x34, 0xc3, 0x37, 0x06, 0x39, 0xa2, 0x37, 0x9e, 0x37, 0xf3, 0x37, + 0x55, 0x34, 0xfb, 0x31, 0x2b, 0x2f, 0x2a, 0x28, 0x3f, 0x21, 0xaf, 0x1e, + 0x7f, 0x21, 0x2e, 0x25, 0xbe, 0x24, 0x01, 0x23, 0xa0, 0x20, 0x0f, 0x1e, + 0xed, 0x1a, 0xe6, 0x1c, 0xa4, 0x22, 0xbd, 0x24, 0xc8, 0x28, 0xd1, 0x2a, + 0xac, 0x2c, 0x96, 0x30, 0xa3, 0x32, 0x5f, 0x34, 0x18, 0x36, 0xe2, 0x34, + 0x02, 0x36, 0x87, 0x37, 0x7b, 0x2f, 0xe7, 0x27, 0xc4, 0x20, 0xc6, 0x1c, + 0xcd, 0x1a, 0xb9, 0x17, 0xe0, 0x12, 0x02, 0x09, 0x58, 0x02, 0x59, 0x01, + 0x44, 0x0b, 0x26, 0x14, 0xd6, 0x19, 0x0e, 0x18, 0x71, 0x10, 0x03, 0x13, + 0xd2, 0x16, 0xc4, 0x20, 0x02, 0x27, 0x91, 0x22, 0x20, 0x1f, 0xa6, 0x1a, + 0xd0, 0x10, 0xee, 0x08, 0xeb, 0x09, 0xcf, 0x0d, 0x65, 0x0c, 0x74, 0x06, + 0xb8, 0x05, 0x01, 0x04, 0x33, 0x02, 0x9a, 0x01, 0x50, 0x00, 0x7d, 0xff, + 0x97, 0xfd, 0x1f, 0xfe, 0xd1, 0xff, 0x08, 0x02, 0xe3, 0x03, 0x50, 0x08, + 0x98, 0x08, 0x90, 0x08, 0xf0, 0x0d, 0xb0, 0x12, 0xa6, 0x17, 0x23, 0x14, + 0x83, 0x0e, 0x37, 0x0c, 0xf8, 0x09, 0x15, 0x0a, 0x57, 0x07, 0xb9, 0x00, + 0x4f, 0xf9, 0xd6, 0xf2, 0x43, 0xf1, 0x5b, 0xf1, 0xf5, 0xf0, 0xd5, 0xf1, + 0x1b, 0xf2, 0xed, 0xf1, 0x81, 0xf2, 0x90, 0xf5, 0x4e, 0xf7, 0x61, 0xfa, + 0x67, 0xfe, 0x0c, 0x00, 0xb5, 0x02, 0x04, 0x06, 0x76, 0x09, 0x64, 0x0c, + 0xab, 0x0f, 0x2b, 0x0f, 0x52, 0x0d, 0xa6, 0x0c, 0x9b, 0x0b, 0x87, 0x0b, + 0xa0, 0x08, 0x14, 0x07, 0x17, 0x06, 0x00, 0x02, 0xbf, 0xff, 0xaa, 0xfe, + 0x20, 0xff, 0xab, 0x00, 0x3e, 0xfb, 0x99, 0xf8, 0x65, 0xfe, 0x18, 0x04, + 0xd6, 0x09, 0xc2, 0x0b, 0x8b, 0x0e, 0x77, 0x11, 0xd1, 0x0d, 0x75, 0x0d, + 0x7f, 0x0f, 0xfe, 0x0e, 0x32, 0x0e, 0xd0, 0x09, 0x78, 0x04, 0x62, 0x02, + 0x3a, 0x03, 0x90, 0x03, 0x29, 0x01, 0x3b, 0xff, 0x69, 0xfd, 0xb2, 0xfe, + 0x87, 0x04, 0x0e, 0x0a, 0xaf, 0x0d, 0x8f, 0x0e, 0x00, 0x0e, 0xea, 0x11, + 0xf1, 0x19, 0x97, 0x1d, 0x79, 0x1a, 0xa1, 0x14, 0x10, 0x15, 0x8b, 0x17, + 0x77, 0x19, 0x28, 0x1a, 0x06, 0x13, 0x3b, 0x0f, 0x31, 0x0f, 0x8f, 0x0e, + 0xb2, 0x0d, 0xf5, 0x0e, 0xb3, 0x14, 0xd9, 0x15, 0x08, 0x16, 0x60, 0x15, + 0xcb, 0x10, 0xd0, 0x11, 0x7f, 0x17, 0x75, 0x18, 0xd8, 0x16, 0xf8, 0x17, + 0x3a, 0x19, 0xa5, 0x1a, 0xc1, 0x1d, 0xef, 0x1f, 0x02, 0x1f, 0xb3, 0x1f, + 0x49, 0x24, 0x63, 0x26, 0x3a, 0x23, 0x8b, 0x1c, 0x2d, 0x16, 0x0f, 0x15, + 0xe7, 0x15, 0x7a, 0x12, 0xf7, 0x0b, 0x20, 0x02, 0x4f, 0xfb, 0xd7, 0xfa, + 0x22, 0xfa, 0x41, 0x02, 0x65, 0x0e, 0x27, 0x12, 0x41, 0x13, 0xff, 0x11, + 0x82, 0x14, 0xe7, 0x1c, 0x9a, 0x25, 0xda, 0x2a, 0xf6, 0x25, 0x52, 0x20, + 0xcc, 0x1a, 0x4a, 0x13, 0xd9, 0x11, 0xdb, 0x12, 0x20, 0x11, 0x4a, 0x08, + 0x78, 0x01, 0x26, 0xfd, 0x91, 0xf9, 0x26, 0xfb, 0xc5, 0xf7, 0x9c, 0xf3, + 0xcc, 0xf4, 0x32, 0xf7, 0x68, 0xf7, 0x97, 0xf8, 0x1d, 0xfa, 0xcf, 0xfa, + 0x6d, 0x01, 0x59, 0x06, 0xbf, 0x08, 0xbf, 0x0c, 0xba, 0x0e, 0x41, 0x0d, + 0x03, 0x0b, 0xc0, 0x0b, 0x14, 0x0e, 0x7b, 0x11, 0x36, 0x16, 0xdd, 0x14, + 0x74, 0x0a, 0xa4, 0x00, 0xaa, 0xfb, 0xfb, 0xf9, 0x1d, 0xf9, 0x4c, 0xf7, + 0xb9, 0xf4, 0xd3, 0xf2, 0xd5, 0xf2, 0xac, 0xf3, 0x32, 0xf7, 0x85, 0xfb, + 0x27, 0x00, 0xe0, 0x04, 0x11, 0x05, 0x04, 0x02, 0xf9, 0x02, 0x25, 0x08, + 0x29, 0x0c, 0xd9, 0x0c, 0xd4, 0x0a, 0x8c, 0x0b, 0x0c, 0x0e, 0x22, 0x0c, + 0xb2, 0x09, 0x14, 0x0a, 0xc1, 0x09, 0x6e, 0x05, 0xfa, 0xfc, 0x37, 0xf8, + 0x60, 0xf8, 0x64, 0xf9, 0x78, 0xf8, 0x66, 0xf5, 0x68, 0xf7, 0xc6, 0xfa, + 0xf3, 0xfc, 0xb6, 0xfc, 0x3a, 0xfc, 0x01, 0xfe, 0x92, 0xfc, 0xca, 0xfd, + 0x25, 0x02, 0x82, 0x05, 0x2b, 0x06, 0x40, 0x07, 0x9e, 0x09, 0x1e, 0x0b, + 0x6a, 0x0d, 0x7c, 0x09, 0x33, 0x06, 0x53, 0x05, 0x84, 0x02, 0xc8, 0x02, + 0x3e, 0x00, 0x65, 0xfc, 0x8e, 0xf9, 0x4b, 0xf8, 0x96, 0xfc, 0xaa, 0xff, + 0x90, 0xfe, 0xd1, 0xfe, 0x9b, 0x00, 0xa4, 0x02, 0x3b, 0x05, 0xe5, 0x02, + 0xe3, 0xff, 0x8a, 0x00, 0x0e, 0x01, 0x7c, 0x02, 0xb3, 0x01, 0xc3, 0xff, + 0x77, 0x02, 0x77, 0x07, 0xef, 0x08, 0x54, 0x08, 0xca, 0x05, 0x3b, 0x01, + 0x68, 0x01, 0xe8, 0x02, 0x24, 0x03, 0x78, 0x00, 0x82, 0xfa, 0xea, 0xfa, + 0x1f, 0x02, 0x7c, 0x06, 0x6a, 0x07, 0xdb, 0x08, 0x44, 0x09, 0x70, 0x0a, + 0x5b, 0x0c, 0x76, 0x0b, 0x87, 0x0a, 0x10, 0x0a, 0x64, 0x08, 0x29, 0x05, + 0x97, 0xfe, 0xd9, 0xfa, 0xb9, 0xfc, 0x04, 0xfc, 0x4a, 0xf9, 0xa7, 0xf6, + 0xd9, 0xf4, 0xe1, 0xf7, 0xae, 0xfd, 0xd3, 0xff, 0x24, 0xfd, 0xb8, 0xf9, + 0x1e, 0xf9, 0x7b, 0xfd, 0x38, 0x01, 0x54, 0x00, 0x97, 0x01, 0xb0, 0x01, + 0xac, 0xfb, 0x4a, 0xf7, 0x45, 0xf3, 0x84, 0xf3, 0xdd, 0xf8, 0x59, 0xf9, + 0x92, 0xf4, 0x0b, 0xec, 0xaf, 0xea, 0x62, 0xef, 0x27, 0xf1, 0xe9, 0xf2, + 0xb8, 0xee, 0x65, 0xe9, 0xe6, 0xe8, 0xf4, 0xeb, 0x2c, 0xf0, 0x27, 0xf0, + 0x91, 0xee, 0x23, 0xeb, 0xd5, 0xe8, 0x89, 0xe9, 0xa2, 0xea, 0xc3, 0xee, + 0x3b, 0xf0, 0x53, 0xee, 0xc0, 0xec, 0xd0, 0xec, 0xa1, 0xf0, 0x54, 0xf4, + 0x55, 0xf5, 0xfe, 0xf0, 0x12, 0xed, 0x9b, 0xec, 0xfc, 0xeb, 0xe3, 0xee, + 0xe3, 0xf0, 0x6e, 0xf0, 0x4c, 0xed, 0xe6, 0xe7, 0x8b, 0xe8, 0xb6, 0xed, + 0x5b, 0xf3, 0x50, 0xf7, 0xaf, 0xf8, 0x8f, 0xf7, 0x6f, 0xf8, 0x96, 0xfd, + 0x2e, 0x01, 0x35, 0x00, 0x8c, 0xfd, 0x18, 0x00, 0x5f, 0x02, 0x9e, 0xff, + 0x13, 0xfc, 0xc4, 0xfa, 0x93, 0xfb, 0x62, 0xfa, 0x29, 0xfa, 0xd2, 0xf9, + 0x94, 0xfa, 0x62, 0xff, 0x23, 0x05, 0x13, 0x09, 0x05, 0x04, 0xe2, 0xfe, + 0x36, 0x02, 0x92, 0x06, 0x99, 0x07, 0x0f, 0x04, 0xa7, 0xff, 0x31, 0xff, + 0xab, 0x04, 0x0d, 0x09, 0xac, 0x08, 0x1a, 0x0a, 0xfc, 0x0b, 0x61, 0x10, + 0xc0, 0x12, 0x64, 0x0e, 0xdb, 0x0d, 0x86, 0x0f, 0xd1, 0x10, 0x82, 0x10, + 0xce, 0x0d, 0x9d, 0x0b, 0x8b, 0x09, 0xb3, 0x09, 0x41, 0x0a, 0x7c, 0x0a, + 0x5d, 0x08, 0x45, 0x05, 0xfe, 0x03, 0x6b, 0x06, 0x49, 0x0e, 0x42, 0x10, + 0x55, 0x0e, 0x3b, 0x0e, 0x24, 0x0e, 0xfb, 0x10, 0x3f, 0x13, 0x3a, 0x13, + 0x34, 0x13, 0x4a, 0x14, 0x97, 0x14, 0x19, 0x15, 0xcd, 0x16, 0xf0, 0x16, + 0x8b, 0x17, 0xaf, 0x16, 0x1d, 0x14, 0x80, 0x15, 0x61, 0x19, 0xa8, 0x1a, + 0x57, 0x1b, 0xbc, 0x1c, 0x00, 0x1c, 0x70, 0x1a, 0x11, 0x19, 0x87, 0x1b, + 0x97, 0x1c, 0xa2, 0x16, 0x0e, 0x14, 0x68, 0x14, 0x4f, 0x13, 0x90, 0x12, + 0x78, 0x10, 0xdc, 0x0f, 0x84, 0x10, 0xe3, 0x0c, 0x4e, 0x07, 0x98, 0x05, + 0xbf, 0x0a, 0x12, 0x13, 0xe7, 0x15, 0x7b, 0x10, 0x1d, 0x08, 0xdd, 0x05, + 0xf2, 0x08, 0x0f, 0x0a, 0x32, 0x06, 0xde, 0xff, 0xb4, 0xfc, 0x48, 0xf8, + 0x0e, 0xf5, 0xd1, 0xf9, 0x33, 0xff, 0x6b, 0x01, 0xad, 0x00, 0xde, 0xfc, + 0x4c, 0xfa, 0x02, 0xfc, 0x19, 0xfe, 0xe4, 0xfc, 0x1a, 0xf9, 0x17, 0xf4, + 0x0c, 0xf1, 0xc4, 0xf0, 0x4b, 0xf4, 0xaa, 0xfc, 0x7e, 0xfe, 0x25, 0xf7, + 0xf1, 0xf1, 0x1d, 0xf1, 0x99, 0xf4, 0xbd, 0xf7, 0xdf, 0xf4, 0x5b, 0xf1, + 0xf1, 0xee, 0x59, 0xec, 0x8c, 0xee, 0xb0, 0xf2, 0x3b, 0xf3, 0xee, 0xf0, + 0x4e, 0xeb, 0x83, 0xe7, 0x32, 0xe9, 0x0b, 0xee, 0xf1, 0xf1, 0x5f, 0xf1, + 0x89, 0xf0, 0x3a, 0xef, 0x54, 0xed, 0x4f, 0xef, 0x9f, 0xf5, 0x5e, 0xfd, + 0xd6, 0xfd, 0xde, 0xf7, 0x8b, 0xf1, 0x0f, 0xf0, 0x6c, 0xf5, 0x4f, 0xf9, + 0xb8, 0xf8, 0xda, 0xf3, 0xc5, 0xf0, 0xe3, 0xee, 0xdc, 0xed, 0xe2, 0xef, + 0x2d, 0xf0, 0x9a, 0xf3, 0x12, 0xf4, 0xa2, 0xf2, 0x3c, 0xf3, 0x69, 0xf4, + 0xb3, 0xfa, 0x4f, 0xff, 0x31, 0x00, 0xfd, 0xfd, 0x8f, 0xfa, 0x30, 0xf8, + 0x42, 0xf9, 0xa4, 0xf9, 0x7b, 0xf6, 0x4a, 0xf7, 0x18, 0xf6, 0xc5, 0xf5, + 0x13, 0xf8, 0x0b, 0xf9, 0x5c, 0xfa, 0x66, 0xfa, 0xb0, 0xf9, 0x14, 0xf8, + 0x23, 0xf8, 0x00, 0xf9, 0xb6, 0xf9, 0x84, 0xf8, 0x36, 0xf6, 0xaf, 0xf6, + 0x59, 0xf6, 0xfc, 0xf7, 0x41, 0xfc, 0xb1, 0xfb, 0x20, 0xf5, 0xe7, 0xef, + 0xd0, 0xef, 0x9b, 0xf3, 0x02, 0xfa, 0x56, 0xfa, 0x87, 0xf4, 0xa9, 0xef, + 0xc3, 0xee, 0xf0, 0xf3, 0x6d, 0xf7, 0x7d, 0xf6, 0x9a, 0xf7, 0xa2, 0xf9, + 0x1a, 0xfb, 0x7c, 0xfb, 0xc9, 0xf9, 0x3b, 0xf8, 0x01, 0xf9, 0xc9, 0xfb, + 0xda, 0xfe, 0x4c, 0xfe, 0xcd, 0xfa, 0x35, 0xff, 0xca, 0x06, 0x7b, 0x08, + 0xc6, 0x09, 0xe8, 0x06, 0xdb, 0x04, 0x85, 0x08, 0xfa, 0x0a, 0x90, 0x0f, + 0xb4, 0x11, 0x15, 0x0b, 0x2e, 0x03, 0xcf, 0xff, 0x6f, 0xfe, 0xa7, 0xfe, + 0xbf, 0xfa, 0x8e, 0xf2, 0xbe, 0xef, 0x72, 0xf1, 0xde, 0xf7, 0xd6, 0xfe, + 0x14, 0x00, 0x0b, 0x00, 0x53, 0x02, 0x2f, 0x02, 0x5f, 0xff, 0x09, 0x01, + 0xc3, 0x03, 0x49, 0x03, 0x3d, 0x01, 0xde, 0xff, 0x3e, 0xfe, 0x89, 0xfb, + 0x60, 0xfa, 0xfd, 0xf7, 0xdc, 0xf4, 0xd7, 0xf3, 0xea, 0xf4, 0x29, 0xf5, + 0xd2, 0xf6, 0x86, 0xf9, 0x53, 0xf4, 0xa9, 0xea, 0x62, 0xe4, 0xd1, 0xe5, + 0x04, 0xec, 0x4d, 0xed, 0x56, 0xe7, 0xce, 0xe3, 0x2d, 0xe9, 0x0a, 0xf0, + 0xbf, 0xf3, 0xb2, 0xf0, 0xb2, 0xeb, 0x6c, 0xea, 0xd4, 0xea, 0x4f, 0xec, + 0x41, 0xed, 0xc6, 0xf0, 0x1f, 0xf3, 0x03, 0xf1, 0x24, 0xef, 0xe0, 0xee, + 0xf2, 0xee, 0x34, 0xee, 0x66, 0xf0, 0x64, 0xef, 0xbe, 0xe7, 0x34, 0xe1, + 0xcf, 0xdf, 0x24, 0xe5, 0x66, 0xed, 0xd6, 0xf4, 0x13, 0xf7, 0x6a, 0xf2, + 0xa3, 0xeb, 0xff, 0xe6, 0xa6, 0xe5, 0xa4, 0xe6, 0x50, 0xe9, 0x8c, 0xec, + 0xbd, 0xee, 0xa3, 0xed, 0x1c, 0xe8, 0x50, 0xe2, 0x4e, 0xe5, 0x66, 0xef, + 0x02, 0xf4, 0xdf, 0xee, 0x9e, 0xe5, 0xd0, 0xe4, 0x4b, 0xef, 0x88, 0xf6, + 0xb5, 0xf2, 0x90, 0xed, 0xd9, 0xee, 0x76, 0xf4, 0xee, 0xf4, 0x60, 0xed, + 0x97, 0xe6, 0xb5, 0xe6, 0x7c, 0xed, 0x18, 0xf0, 0x3a, 0xec, 0x08, 0xe8, + 0x3b, 0xe9, 0xaa, 0xef, 0x61, 0xf2, 0x59, 0xf0, 0x49, 0xec, 0xaa, 0xf0, + 0x7d, 0xfb, 0x61, 0xfe, 0x46, 0xf6, 0x1b, 0xeb, 0xf3, 0xe9, 0x4c, 0xf0, + 0xbe, 0xf5, 0xf2, 0xf5, 0x5a, 0xf4, 0xda, 0xf4, 0xcc, 0xf4, 0xec, 0xf4, + 0x1f, 0xf6, 0xe9, 0xf8, 0x8b, 0xf9, 0xcb, 0xf7, 0xbd, 0xf5, 0x35, 0xf2, + 0x53, 0xee, 0x97, 0xe9, 0xa8, 0xe5, 0x28, 0xe7, 0xec, 0xec, 0xa0, 0xf0, + 0x65, 0xed, 0x79, 0xe4, 0xa4, 0xe1, 0xad, 0xe7, 0xab, 0xef, 0xa9, 0xf2, + 0x0e, 0xed, 0x15, 0xe9, 0x26, 0xef, 0x43, 0xfb, 0xb0, 0x02, 0x36, 0x03, + 0x0f, 0x01, 0x94, 0xfd, 0xdb, 0xfc, 0x34, 0xfc, 0x89, 0xf9, 0x88, 0xf8, + 0xf7, 0xf5, 0x51, 0xee, 0x5e, 0xe8, 0x53, 0xea, 0xc7, 0xeb, 0x7e, 0xe4, + 0x87, 0xd8, 0x4a, 0xd2, 0xe5, 0xd3, 0x5c, 0xd4, 0x4b, 0xd2, 0xaf, 0xd2, + 0xd5, 0xd7, 0xf5, 0xdd, 0x51, 0xde, 0xf9, 0xd6, 0xe3, 0xd1, 0x99, 0xd5, + 0x75, 0xda, 0x1c, 0xde, 0xa5, 0xdf, 0x43, 0xde, 0x53, 0xdc, 0x35, 0xdb, + 0x58, 0xdd, 0xe1, 0xe0, 0xb0, 0xe1, 0xcd, 0xe3, 0xee, 0xe6, 0xfe, 0xe4, + 0xb0, 0xe1, 0x89, 0xd8, 0xcc, 0xce, 0x9b, 0xcc, 0x07, 0xce, 0xa9, 0xd2, + 0xbc, 0xd4, 0x27, 0xd5, 0xc0, 0xd4, 0x99, 0xd2, 0x2a, 0xd0, 0xad, 0xd0, + 0xc0, 0xd6, 0xf4, 0xd9, 0xd9, 0xd6, 0xe2, 0xd1, 0xea, 0xcd, 0x70, 0xca, + 0x15, 0xc9, 0x75, 0xcc, 0x84, 0xd2, 0xa6, 0xd6, 0x86, 0xd8, 0xd7, 0xd7, + 0x6f, 0xd7, 0xdc, 0xd9, 0xa3, 0xda, 0x9c, 0xdc, 0x4a, 0xde, 0xb4, 0xdd, + 0x6c, 0xdb, 0x1c, 0xd8, 0x52, 0xda, 0x99, 0xe2, 0xae, 0xec, 0x49, 0xf1, + 0xcb, 0xf0, 0x26, 0xf3, 0x28, 0xf7, 0x6c, 0xf9, 0x58, 0xf8, 0xd2, 0xf5, + 0xac, 0xf6, 0xf4, 0xfb, 0x42, 0x05, 0x4e, 0x11, 0xf8, 0x1d, 0x33, 0x25, + 0xa1, 0x23, 0x31, 0x19, 0x2a, 0x0c, 0x23, 0x08, 0x44, 0x08, 0xc7, 0x06, + 0x73, 0x05, 0x07, 0x05, 0x41, 0x07, 0xc6, 0x0d, 0x26, 0x15, 0x8e, 0x17, + 0x4d, 0x13, 0x13, 0x0d, 0x47, 0x0b, 0xa1, 0x08, 0xf9, 0x03, 0xae, 0xff, + 0x9a, 0x01, 0x93, 0x0b, 0x2d, 0x13, 0x67, 0x14, 0x3c, 0x0f, 0xa1, 0x0b, + 0xe5, 0x09, 0x7c, 0x05, 0x44, 0x01, 0x2d, 0xff, 0xd6, 0x04, 0x79, 0x0f, + 0xa3, 0x13, 0x06, 0x0e, 0xc1, 0x07, 0xa7, 0x09, 0x90, 0x14, 0x9c, 0x1e, + 0xba, 0x1e, 0x7f, 0x14, 0x6c, 0x03, 0xa9, 0xf6, 0xec, 0xf5, 0xcc, 0xfa, + 0x70, 0xfc, 0x4b, 0xfb, 0x58, 0xfd, 0xe7, 0x06, 0xce, 0x10, 0x0c, 0x19, + 0x5b, 0x24, 0xd4, 0x2a, 0x56, 0x28, 0x8f, 0x20, 0xa0, 0x18, 0xda, 0x17, + 0x59, 0x1d, 0xaf, 0x20, 0xe5, 0x20, 0x28, 0x22, 0xab, 0x25, 0xe1, 0x2b, + 0x28, 0x35, 0x99, 0x41, 0x21, 0x4f, 0xd8, 0x55, 0x36, 0x55, 0x1a, 0x53, + 0x65, 0x50, 0xd6, 0x50, 0x24, 0x4a, 0xdb, 0x35, 0x7b, 0x22, 0x90, 0x17, + 0xaa, 0x0f, 0x33, 0x03, 0xac, 0xf3, 0x87, 0xe7, 0x50, 0xe6, 0xeb, 0xed, + 0x8e, 0xf5, 0x45, 0xf6, 0x14, 0xf0, 0x48, 0xee, 0x41, 0xf8, 0x1c, 0x07, + 0xe8, 0x0a, 0x0a, 0x02, 0xa5, 0xf5, 0x61, 0xed, 0xfa, 0xee, 0x67, 0xf1, + 0xbd, 0xeb, 0x2b, 0xe4, 0xab, 0xe0, 0x36, 0xe4, 0x9a, 0xed, 0x25, 0xfa, + 0xba, 0x08, 0xbe, 0x11, 0x8a, 0x14, 0x46, 0x12, 0xe7, 0x0b, 0x12, 0x04, + 0x96, 0xf9, 0x6e, 0xee, 0x76, 0xe4, 0x3d, 0xe1, 0x28, 0xe6, 0x58, 0xf2, + 0x66, 0x00, 0x0c, 0x08, 0xda, 0x0d, 0x93, 0x13, 0xd7, 0x1b, 0xf9, 0x22, + 0x78, 0x1f, 0xea, 0x1b, 0x6d, 0x1f, 0x7b, 0x22, 0x05, 0x20, 0x1e, 0x19, + 0xd4, 0x14, 0x0c, 0x14, 0xc0, 0x11, 0x88, 0x0b, 0xed, 0x04, 0x9b, 0x02, + 0x9d, 0x03, 0xb3, 0x08, 0x0a, 0x0f, 0x05, 0x16, 0xee, 0x20, 0x3c, 0x24, + 0x44, 0x1e, 0x0b, 0x18, 0xfa, 0x0f, 0x9d, 0x02, 0xcd, 0xee, 0x7a, 0xd9, + 0xf1, 0xc8, 0xf3, 0xbb, 0xf8, 0xb3, 0x00, 0xb5, 0x98, 0xbb, 0xff, 0xc3, + 0x70, 0xcc, 0x71, 0xd3, 0xa6, 0xda, 0xa8, 0xe1, 0xad, 0xe2, 0x9e, 0xd9, + 0x66, 0xcf, 0x8d, 0xcc, 0xe5, 0xcf, 0x21, 0xd1, 0x69, 0xcc, 0x7d, 0xcc, + 0x2e, 0xd5, 0x67, 0xe1, 0xc2, 0xe9, 0xad, 0xeb, 0x90, 0xed, 0x6f, 0xf5, + 0xe3, 0x04, 0x1c, 0x14, 0xab, 0x1a, 0xd0, 0x19, 0xf1, 0x1a, 0x21, 0x1e, + 0x3b, 0x19, 0xf8, 0x12, 0x74, 0x13, 0xbc, 0x15, 0xfc, 0x17, 0x56, 0x18, + 0x26, 0x14, 0x25, 0x0b, 0xe1, 0x00, 0x39, 0xfd, 0x7a, 0x03, 0xf9, 0x11, + 0x6a, 0x23, 0xc6, 0x30, 0xd7, 0x34, 0x20, 0x2e, 0x3c, 0x24, 0xf4, 0x1b, + 0x69, 0x15, 0x4b, 0x11, 0x90, 0x0a, 0x8c, 0x03, 0x9e, 0x02, 0x91, 0x09, + 0x9f, 0x13, 0x58, 0x18, 0x71, 0x1b, 0x4f, 0x21, 0x22, 0x29, 0x7b, 0x31, + 0x06, 0x37, 0x2b, 0x38, 0xb9, 0x36, 0x6a, 0x30, 0x6a, 0x20, 0x7c, 0x0c, + 0x0f, 0x00, 0x7c, 0xff, 0xb8, 0x08, 0xe1, 0x18, 0x5c, 0x2a, 0x6c, 0x39, + 0xc2, 0x42, 0x8a, 0x43, 0x56, 0x3b, 0x56, 0x2c, 0x6e, 0x1f, 0x7e, 0x18, + 0x28, 0x17, 0x9d, 0x17, 0xd8, 0x19, 0x42, 0x1f, 0x0b, 0x28, 0x33, 0x34, + 0xc5, 0x3a, 0xfb, 0x38, 0x4f, 0x30, 0x11, 0x26, 0x71, 0x1f, 0xb8, 0x17, + 0x78, 0x0e, 0x6e, 0x05, 0xc0, 0xfb, 0xe7, 0xf2, 0x4e, 0xee, 0x08, 0xed, + 0x64, 0xf0, 0xe1, 0xf8, 0x1c, 0x00, 0xb0, 0x02, 0x44, 0xfd, 0x98, 0xf1, + 0x15, 0xe6, 0x4a, 0xdd, 0xae, 0xda, 0x6d, 0xde, 0xa7, 0xe5, 0x71, 0xf1, + 0x3c, 0x00, 0xd0, 0x08, 0xb0, 0x06, 0x92, 0xfe, 0xac, 0xf5, 0x46, 0xf3, + 0xdd, 0xf7, 0xd8, 0xfa, 0xcf, 0xf9, 0xfa, 0xf6, 0xe9, 0xf4, 0xc1, 0xf7, + 0x34, 0xfd, 0xbc, 0x01, 0xb9, 0x07, 0xcd, 0x0d, 0xea, 0x15, 0x62, 0x20, + 0x43, 0x29, 0x9c, 0x2f, 0x72, 0x2d, 0xc3, 0x23, 0x8b, 0x1a, 0x22, 0x13, + 0xe5, 0x0c, 0x82, 0x0a, 0x43, 0x0c, 0xff, 0x0f, 0x36, 0x14, 0x1d, 0x15, + 0xd9, 0x12, 0x56, 0x12, 0x6f, 0x15, 0xd2, 0x1a, 0x3d, 0x1d, 0xf2, 0x16, + 0x74, 0x0b, 0x1c, 0xfe, 0xc0, 0xf0, 0x47, 0xe7, 0xcb, 0xe2, 0x15, 0xe4, + 0x2a, 0xe7, 0x05, 0xe6, 0x4d, 0xdf, 0x6e, 0xd6, 0x17, 0xcf, 0x01, 0xcb, + 0x7d, 0xc8, 0xe7, 0xc4, 0x16, 0xc2, 0x9f, 0xc3, 0xb6, 0xcb, 0x4f, 0xd7, + 0x8a, 0xe2, 0xb2, 0xe9, 0x8d, 0xed, 0x59, 0xf0, 0x1a, 0xf0, 0xeb, 0xec, + 0x96, 0xe8, 0x60, 0xe9, 0x7e, 0xf1, 0x79, 0xfb, 0x40, 0x04, 0x4e, 0x0c, + 0x8e, 0x14, 0x9d, 0x1c, 0x6a, 0x22, 0xd9, 0x21, 0x42, 0x20, 0x05, 0x23, + 0x01, 0x24, 0xf8, 0x21, 0x8f, 0x1b, 0xdc, 0x11, 0xc8, 0x0c, 0xa6, 0x07, + 0xee, 0xfe, 0xab, 0xfd, 0xee, 0x04, 0x5e, 0x0d, 0x15, 0x15, 0xd5, 0x1b, + 0xaf, 0x24, 0xe8, 0x2d, 0x22, 0x30, 0x64, 0x2a, 0x48, 0x1f, 0xbd, 0x11, + 0xd3, 0x07, 0xbb, 0x04, 0x35, 0x02, 0x86, 0xfe, 0x68, 0xfe, 0x35, 0x04, + 0x4e, 0x0d, 0x68, 0x12, 0x63, 0x10, 0xb2, 0x0c, 0xbb, 0x0a, 0x59, 0x05, + 0x1e, 0xfc, 0x4f, 0xf1, 0xb1, 0xe6, 0x10, 0xde, 0xf6, 0xd9, 0x47, 0xd9, + 0xee, 0xd8, 0x6f, 0xdb, 0x5a, 0xde, 0x27, 0xe2, 0x26, 0xe7, 0x9b, 0xeb, + 0xbd, 0xee, 0x44, 0xf2, 0xa3, 0xfb, 0x60, 0x07, 0x32, 0x14, 0x3a, 0x20, + 0x79, 0x29, 0xc6, 0x2d, 0x7e, 0x25, 0x9d, 0x12, 0x14, 0x01, 0x6c, 0xf8, + 0xa7, 0xf6, 0xc1, 0xf8, 0x0f, 0xfa, 0xd5, 0xfb, 0xa4, 0xfe, 0x5f, 0x01, + 0xa0, 0x05, 0x40, 0x0c, 0x71, 0x16, 0x9c, 0x1f, 0x5e, 0x24, 0xaf, 0x22, + 0x48, 0x1f, 0x32, 0x1b, 0xe7, 0x13, 0x10, 0x0d, 0xb1, 0x03, 0xed, 0xf9, + 0xc3, 0xf4, 0xea, 0xf7, 0x5d, 0x00, 0xc4, 0x09, 0x8f, 0x15, 0x58, 0x20, + 0x72, 0x26, 0x15, 0x25, 0x7b, 0x22, 0xb9, 0x26, 0x8e, 0x2b, 0x7b, 0x2c, + 0x1c, 0x2b, 0xb8, 0x26, 0x18, 0x24, 0xa7, 0x20, 0x7b, 0x19, 0x5c, 0x17, + 0xb0, 0x1b, 0x00, 0x25, 0x9d, 0x30, 0x64, 0x3c, 0x4d, 0x47, 0xac, 0x4f, + 0x43, 0x55, 0x57, 0x53, 0xe4, 0x4a, 0x2d, 0x40, 0xa2, 0x37, 0xf2, 0x31, + 0xee, 0x2a, 0xa8, 0x22, 0x84, 0x1b, 0xac, 0x19, 0x31, 0x19, 0x06, 0x18, + 0x66, 0x1b, 0x41, 0x22, 0x28, 0x2b, 0x2c, 0x33, 0xc0, 0x36, 0xdc, 0x33, + 0x7f, 0x2a, 0x23, 0x1f, 0x28, 0x12, 0x26, 0x03, 0x8a, 0xf5, 0x42, 0xec, + 0x13, 0xe7, 0x82, 0xe5, 0xcf, 0xe5, 0x6c, 0xe7, 0x13, 0xea, 0x48, 0xea, + 0x0b, 0xe8, 0x11, 0xe6, 0x52, 0xec, 0x65, 0xfb, 0x38, 0x0b, 0x32, 0x17, + 0x2b, 0x1a, 0x26, 0x13, 0xc5, 0x06, 0x24, 0xfb, 0x9c, 0xf2, 0x26, 0xee, + 0xb4, 0xea, 0x99, 0xe8, 0x78, 0xeb, 0xa2, 0xee, 0x8b, 0xf2, 0xc6, 0xf7, + 0x82, 0xfe, 0xca, 0x06, 0xe3, 0x0b, 0xf9, 0x0d, 0xa5, 0x10, 0x2e, 0x14, + 0x28, 0x14, 0xc5, 0x0f, 0xba, 0x07, 0x54, 0xff, 0xd8, 0xfe, 0x82, 0x05, + 0x6a, 0x0e, 0x1f, 0x18, 0xa8, 0x21, 0xa6, 0x2b, 0xb5, 0x32, 0xe6, 0x32, + 0xc9, 0x2f, 0x5b, 0x2f, 0x7f, 0x32, 0x04, 0x37, 0xfa, 0x36, 0x94, 0x30, + 0xb0, 0x2b, 0x06, 0x2a, 0x54, 0x2d, 0xc3, 0x35, 0x37, 0x3a, 0xd9, 0x37, + 0xee, 0x33, 0xb7, 0x30, 0xa6, 0x2b, 0xcd, 0x20, 0x7c, 0x12, 0x68, 0x08, + 0x15, 0xfe, 0x34, 0xf3, 0x61, 0xf1, 0x0f, 0xf5, 0x92, 0xf8, 0xb5, 0xfa, + 0x52, 0xfc, 0x92, 0x01, 0xc7, 0x0b, 0xe6, 0x10, 0x93, 0x0b, 0x53, 0x05, + 0xc2, 0x05, 0xab, 0x0a, 0x68, 0x0b, 0x85, 0x06, 0x93, 0x02, 0x3b, 0x04, + 0xdb, 0x06, 0xf8, 0x03, 0x2d, 0xfd, 0xc1, 0xfc, 0x2f, 0x04, 0xc7, 0x0b, + 0xb6, 0x11, 0xca, 0x13, 0x2d, 0x16, 0x25, 0x1c, 0xf2, 0x22, 0xfd, 0x29, + 0xd4, 0x30, 0x4d, 0x35, 0x42, 0x35, 0xd6, 0x37, 0xcc, 0x3c, 0xb5, 0x3e, + 0x7a, 0x3e, 0x8c, 0x3a, 0x7a, 0x33, 0xf4, 0x2a, 0xdc, 0x24, 0x04, 0x23, + 0x33, 0x22, 0x8d, 0x21, 0x15, 0x21, 0x64, 0x1f, 0xda, 0x1d, 0xba, 0x1f, + 0xd3, 0x21, 0x21, 0x20, 0xe4, 0x20, 0x24, 0x25, 0x36, 0x27, 0x72, 0x27, + 0x73, 0x25, 0xc5, 0x21, 0xa8, 0x1c, 0x4d, 0x15, 0x33, 0x0f, 0xeb, 0x0a, + 0xe8, 0x04, 0x26, 0xfd, 0x04, 0xf5, 0x2f, 0xec, 0x1c, 0xe5, 0xa4, 0xe1, + 0xb4, 0xdd, 0x45, 0xd8, 0x73, 0xd4, 0x1b, 0xd5, 0x85, 0xdb, 0x46, 0xe2, + 0x57, 0xe8, 0x92, 0xee, 0x8d, 0xee, 0x6c, 0xea, 0xb8, 0xe8, 0x37, 0xe7, + 0x8b, 0xe1, 0xd1, 0xd8, 0xe4, 0xd1, 0x14, 0xce, 0x91, 0xcb, 0x8e, 0xcc, + 0xe2, 0xd1, 0xff, 0xd7, 0xdd, 0xdc, 0xb2, 0xe3, 0xbb, 0xed, 0x6f, 0xf6, + 0xe4, 0xf9, 0xf1, 0xf4, 0x90, 0xea, 0x33, 0xe3, 0x43, 0xe4, 0xfd, 0xed, + 0xc4, 0xf8, 0xaa, 0x00, 0x22, 0x09, 0x06, 0x11, 0x13, 0x16, 0xaa, 0x16, + 0xca, 0x0f, 0x19, 0x06, 0xea, 0xfb, 0x38, 0xf1, 0xa3, 0xea, 0x7b, 0xe7, + 0xcc, 0xe7, 0x6a, 0xec, 0x9e, 0xf2, 0x90, 0xf8, 0xd7, 0xfc, 0xe8, 0xfe, + 0x71, 0x01, 0x3f, 0x04, 0xf2, 0x02, 0xe9, 0x00, 0x08, 0xff, 0x23, 0xf9, + 0x38, 0xf0, 0xcb, 0xe6, 0x54, 0xe3, 0xa3, 0xea, 0x05, 0xf5, 0x1c, 0xfc, + 0x4b, 0x02, 0x50, 0x07, 0x63, 0x09, 0x17, 0x09, 0xa2, 0x08, 0xa1, 0x0a, + 0xe6, 0x0d, 0x5c, 0x0f, 0xb1, 0x0f, 0x85, 0x10, 0x13, 0x13, 0xd4, 0x19, + 0xd0, 0x22, 0xe1, 0x23, 0x97, 0x18, 0xb4, 0x0a, 0x01, 0x03, 0x79, 0x04, + 0x0b, 0x08, 0xe7, 0x07, 0x7e, 0x05, 0x73, 0x01, 0xf1, 0x02, 0xd5, 0x0b, + 0x1f, 0x18, 0x43, 0x21, 0xa0, 0x21, 0xcc, 0x18, 0x41, 0x0a, 0x11, 0xf9, + 0xa3, 0xe3, 0xa1, 0xd2, 0xab, 0xcb, 0x24, 0xce, 0xef, 0xd7, 0xe4, 0xe4, + 0xb1, 0xf3, 0x60, 0x01, 0x1a, 0x0c, 0x04, 0x0e, 0x84, 0x04, 0x0a, 0xf7, + 0xc7, 0xeb, 0xd2, 0xe4, 0xc6, 0xe2, 0xed, 0xe1, 0xfa, 0xe1, 0xa6, 0xe5, + 0xd2, 0xea, 0xcf, 0xef, 0xfb, 0xf2, 0x3f, 0xf2, 0xc3, 0xee, 0x47, 0xf2, + 0x91, 0xfb, 0x6c, 0x02, 0x01, 0x06, 0x21, 0x09, 0xd2, 0x10, 0x1c, 0x17, + 0x78, 0x1c, 0x68, 0x27, 0x00, 0x33, 0xf2, 0x39, 0xe7, 0x3a, 0xe2, 0x35, + 0xca, 0x30, 0x77, 0x31, 0xec, 0x35, 0x49, 0x3e, 0x49, 0x44, 0x51, 0x45, + 0x5b, 0x47, 0x83, 0x4a, 0x00, 0x4d, 0x4a, 0x4e, 0x99, 0x50, 0x80, 0x50, + 0xfe, 0x48, 0xbe, 0x38, 0x36, 0x25, 0x61, 0x16, 0xdc, 0x0b, 0xf9, 0x05, + 0x30, 0x02, 0x2a, 0xfd, 0x89, 0xfc, 0xb7, 0x01, 0x2e, 0x09, 0xe1, 0x0d, + 0xcb, 0x09, 0xea, 0xfd, 0x15, 0xf3, 0x3a, 0xec, 0xd4, 0xe4, 0x23, 0xde, + 0xa5, 0xd8, 0xd2, 0xd3, 0x09, 0xd3, 0xa4, 0xd9, 0xd2, 0xe4, 0xfc, 0xec, + 0xc7, 0xf2, 0xa5, 0xf5, 0xe8, 0xf6, 0x5d, 0xf8, 0xdf, 0xfa, 0x06, 0xff, + 0x80, 0x01, 0xc7, 0x06, 0x42, 0x0e, 0x38, 0x16, 0xb8, 0x19, 0x77, 0x16, + 0x02, 0x14, 0xbb, 0x11, 0x1f, 0x0f, 0xb4, 0x0a, 0x8f, 0x05, 0x0a, 0x04, + 0xf3, 0x0a, 0xc1, 0x14, 0xfb, 0x18, 0x28, 0x19, 0x03, 0x13, 0xce, 0x0c, + 0xb6, 0x0a, 0xcc, 0x09, 0x5a, 0x08, 0x1c, 0x01, 0x9d, 0xf7, 0xe3, 0xf1, + 0x41, 0xf1, 0x97, 0xf3, 0x94, 0xf7, 0xbd, 0xfa, 0x36, 0xf8, 0x0c, 0xf2, + 0xeb, 0xed, 0x9a, 0xef, 0x57, 0xf3, 0x2d, 0xf6, 0x9b, 0xf9, 0xda, 0xf7, + 0x07, 0xf0, 0xde, 0xe7, 0x23, 0xdf, 0x48, 0xd4, 0x2c, 0xc8, 0xb5, 0xbd, + 0xcd, 0xb7, 0xac, 0xb5, 0x5c, 0xb4, 0x23, 0xb2, 0x31, 0xae, 0x75, 0xab, + 0x43, 0xac, 0x55, 0xb0, 0xcd, 0xb3, 0x8f, 0xb4, 0x20, 0xb8, 0xfa, 0xbc, + 0x51, 0xbf, 0x08, 0xc0, 0x1f, 0xc6, 0x8e, 0xd3, 0x9c, 0xde, 0xe9, 0xdf, + 0x8a, 0xd6, 0xae, 0xcd, 0x9b, 0xcc, 0xb3, 0xce, 0x68, 0xd1, 0x53, 0xd5, + 0xdb, 0xd8, 0xb7, 0xd9, 0x35, 0xd8, 0x9d, 0xd3, 0x0a, 0xd1, 0x38, 0xd3, + 0xbd, 0xd7, 0xe2, 0xda, 0xde, 0xd9, 0x68, 0xdc, 0xf7, 0xe4, 0xcb, 0xef, + 0x86, 0xf9, 0x02, 0xfd, 0xbb, 0xf9, 0xbc, 0xf2, 0x07, 0xeb, 0xf0, 0xe5, + 0x14, 0xe5, 0x37, 0xe5, 0xe4, 0xe3, 0x95, 0xe7, 0xde, 0xed, 0x7e, 0xee, + 0x99, 0xf0, 0x43, 0xf5, 0x84, 0xf8, 0xb6, 0xfc, 0x08, 0x02, 0xc9, 0x08, + 0x0d, 0x11, 0xe0, 0x14, 0x10, 0x13, 0xb6, 0x16, 0x4a, 0x20, 0x64, 0x28, + 0xc0, 0x2a, 0x91, 0x25, 0x14, 0x21, 0x3d, 0x1d, 0xfa, 0x18, 0x16, 0x15, + 0xa1, 0x10, 0x27, 0x11, 0xd0, 0x15, 0xcb, 0x19, 0xf6, 0x19, 0x13, 0x19, + 0xf4, 0x17, 0xee, 0x18, 0x07, 0x1d, 0x00, 0x1b, 0x01, 0x17, 0xe2, 0x12, + 0xf1, 0x11, 0x73, 0x19, 0x21, 0x21, 0xe0, 0x24, 0x95, 0x21, 0x62, 0x14, + 0x57, 0x04, 0x9a, 0xf7, 0xb5, 0xec, 0x77, 0xe6, 0x2b, 0xe2, 0xed, 0xdc, + 0xef, 0xd9, 0xf9, 0xd5, 0xb8, 0xd1, 0x65, 0xd1, 0xd6, 0xd4, 0xee, 0xd8, + 0xa0, 0xdc, 0xe7, 0xdd, 0xf1, 0xe1, 0xab, 0xea, 0x26, 0xf1, 0x95, 0xf2, + 0x62, 0xed, 0x75, 0xe6, 0xe9, 0xe2, 0x83, 0xe4, 0x1f, 0xe7, 0x58, 0xea, + 0x80, 0xee, 0x13, 0xf2, 0x46, 0xf8, 0x76, 0xfc, 0x08, 0xfd, 0x82, 0xfb, + 0xb4, 0xfa, 0x30, 0xfa, 0x9c, 0xfa, 0xcd, 0xfb, 0x77, 0xfd, 0x07, 0x01, + 0x75, 0x02, 0x7d, 0x07, 0x9e, 0x10, 0xd6, 0x16, 0xed, 0x18, 0x81, 0x1a, + 0x93, 0x1c, 0x6f, 0x21, 0x43, 0x27, 0x5a, 0x27, 0x34, 0x26, 0x21, 0x27, + 0xff, 0x2b, 0x28, 0x2e, 0x3e, 0x2a, 0xc5, 0x26, 0x07, 0x27, 0xf7, 0x2a, + 0x43, 0x2c, 0x83, 0x2b, 0xe9, 0x2a, 0x98, 0x28, 0x77, 0x22, 0xcf, 0x19, + 0x57, 0x11, 0xad, 0x06, 0x6a, 0xf9, 0xf8, 0xeb, 0x39, 0xdf, 0x1e, 0xd6, + 0xf2, 0xd2, 0xe8, 0xd0, 0x9b, 0xd2, 0x57, 0xda, 0xd4, 0xe2, 0x6b, 0xe6, + 0xe0, 0xe5, 0xa1, 0xe8, 0x50, 0xef, 0x82, 0xf7, 0xe9, 0xfb, 0x28, 0xf9, + 0x48, 0xf1, 0xbe, 0xe7, 0x46, 0xe1, 0xc6, 0xdf, 0x51, 0xe2, 0x2e, 0xe4, + 0x4d, 0xe6, 0x71, 0xeb, 0xad, 0xf4, 0x55, 0x01, 0x1e, 0x0d, 0xfa, 0x14, + 0xf9, 0x17, 0x0e, 0x19, 0x50, 0x16, 0xf9, 0x11, 0x43, 0x12, 0xad, 0x14, + 0x96, 0x15, 0x91, 0x10, 0x73, 0x0a, 0xa7, 0x0c, 0x9b, 0x15, 0xf2, 0x1d, + 0x38, 0x1f, 0x0c, 0x1a, 0x1b, 0x17, 0x04, 0x1b, 0x70, 0x20, 0x39, 0x24, + 0xce, 0x23, 0x41, 0x1f, 0x24, 0x1e, 0xc7, 0x1f, 0x8f, 0x20, 0x92, 0x1e, + 0x62, 0x19, 0xc4, 0x12, 0x8a, 0x0a, 0xc8, 0x03, 0x88, 0x02, 0x58, 0x06, + 0xc8, 0x0a, 0xa6, 0x0e, 0x44, 0x12, 0xca, 0x0e, 0x21, 0x06, 0x58, 0xfe, + 0x0e, 0xf4, 0x11, 0xe9, 0x7b, 0xe0, 0x28, 0xd6, 0xd9, 0xcc, 0x49, 0xc8, + 0xa2, 0xc7, 0x27, 0xce, 0x9d, 0xd5, 0x53, 0xd8, 0xab, 0xdb, 0xc5, 0xe0, + 0xd6, 0xe5, 0x7e, 0xe9, 0x26, 0xe8, 0xb9, 0xe2, 0x78, 0xdf, 0xec, 0xd8, + 0x94, 0xd0, 0xd3, 0xcd, 0x75, 0xcd, 0x07, 0xd0, 0xd3, 0xd3, 0xc8, 0xd7, + 0xe5, 0xdd, 0xf5, 0xe8, 0x0f, 0xf7, 0xc2, 0x01, 0xc5, 0x05, 0x6e, 0x02, + 0xa8, 0xfe, 0x87, 0xfc, 0x75, 0xf9, 0x75, 0xf5, 0x44, 0xf4, 0xdc, 0xfa, + 0x7c, 0x05, 0xa3, 0x10, 0x6d, 0x18, 0x3a, 0x15, 0xd7, 0x0a, 0x3b, 0x01, + 0x35, 0xfa, 0xc8, 0xf6, 0x5a, 0xf3, 0x13, 0xf2, 0xe4, 0xf6, 0x89, 0xfb, + 0xe4, 0xfc, 0x22, 0xfe, 0x27, 0xff, 0xe3, 0xff, 0x2d, 0x00, 0xcc, 0xfe, + 0x2a, 0xff, 0x2b, 0xff, 0xf4, 0xfd, 0xda, 0xfe, 0xda, 0x03, 0xfe, 0x08, + 0x3e, 0x09, 0x38, 0x0a, 0x85, 0x09, 0xe5, 0x08, 0xcc, 0x0c, 0x05, 0x12, + 0x05, 0x17, 0x06, 0x1a, 0x3b, 0x1b, 0xd0, 0x18, 0x97, 0x12, 0x50, 0x0a, + 0x00, 0x07, 0x37, 0x09, 0x4a, 0x0c, 0x7c, 0x0e, 0x9a, 0x0b, 0x9d, 0x06, + 0x68, 0x00, 0x29, 0xfc, 0xa0, 0xf9, 0x05, 0xf5, 0x94, 0xf1, 0xa0, 0xf0, + 0x69, 0xf2, 0x5c, 0xf5, 0x95, 0xf7, 0x72, 0xfa, 0x27, 0x01, 0xa9, 0x04, + 0x79, 0x01, 0xf8, 0xfc, 0xe8, 0xf4, 0x62, 0xeb, 0xbc, 0xdf, 0xe9, 0xcf, + 0xc5, 0xc1, 0x9e, 0xba, 0xb1, 0xbc, 0x30, 0xc5, 0x95, 0xcc, 0xfa, 0xcf, + 0xc1, 0xd2, 0x25, 0xd2, 0xf6, 0xce, 0x61, 0xcb, 0x83, 0xc5, 0x5c, 0xc1, + 0x38, 0xc1, 0x06, 0xc7, 0x86, 0xd2, 0x55, 0xde, 0xfb, 0xe3, 0xb9, 0xe4, + 0x90, 0xe4, 0x61, 0xe5, 0x4f, 0xea, 0xae, 0xef, 0x62, 0xf1, 0x6b, 0xf1, + 0x08, 0xf6, 0x92, 0xfc, 0x5d, 0xff, 0xd1, 0x02, 0x8e, 0x08, 0x8c, 0x12, + 0xed, 0x1c, 0xb9, 0x20, 0x1f, 0x23, 0xdc, 0x28, 0xe6, 0x2f, 0x51, 0x34, + 0xca, 0x32, 0x32, 0x2f, 0xc2, 0x2f, 0x26, 0x2f, 0x94, 0x2a, 0xcc, 0x25, + 0x17, 0x20, 0x1e, 0x1e, 0xca, 0x1f, 0xc9, 0x20, 0xc0, 0x22, 0xf5, 0x23, + 0xa7, 0x23, 0xb0, 0x1c, 0x5d, 0x0b, 0x17, 0xf9, 0x32, 0xec, 0xc1, 0xe2, + 0xa8, 0xda, 0x48, 0xd6, 0xa8, 0xd6, 0xa4, 0xd6, 0x5c, 0xd0, 0x7d, 0xc8, + 0x07, 0xc4, 0xef, 0xc0, 0xe9, 0xbd, 0x73, 0xb8, 0xc2, 0xb4, 0x67, 0xb4, + 0xa6, 0xb4, 0x06, 0xb3, 0xde, 0xb0, 0x88, 0xb4, 0x4e, 0xba, 0x3a, 0xc1, + 0x3f, 0xc6, 0xf3, 0xc6, 0x3d, 0xcb, 0x09, 0xd4, 0x8a, 0xe0, 0x1a, 0xee, + 0x82, 0xf6, 0x37, 0xfa, 0xc5, 0xfe, 0xac, 0x01, 0xdf, 0x04, 0x08, 0x0b, + 0xe7, 0x0d, 0x20, 0x11, 0x86, 0x13, 0x24, 0x14, 0x01, 0x17, 0xfd, 0x18, + 0xbc, 0x18, 0x07, 0x16, 0xa1, 0x12, 0xcd, 0x12, 0xe1, 0x1a, 0x4e, 0x23, + 0x06, 0x24, 0x63, 0x21, 0x1a, 0x1c, 0x04, 0x17, 0xb4, 0x17, 0x45, 0x1a, + 0xac, 0x19, 0xf5, 0x15, 0xe9, 0x0e, 0x62, 0x09, 0x67, 0x05, 0x22, 0xff, + 0x8a, 0xf8, 0x70, 0xf2, 0x25, 0xf1, 0x1b, 0xf3, 0xdc, 0xf2, 0xc8, 0xee, + 0x40, 0xe6, 0xfb, 0xda, 0xbb, 0xd3, 0x06, 0xd1, 0xcc, 0xcc, 0x4f, 0xca, + 0xb8, 0xc8, 0xa7, 0xc6, 0xee, 0xc6, 0xd4, 0xc9, 0x61, 0xca, 0x7b, 0xc7, + 0xa5, 0xc4, 0xc2, 0xc1, 0x97, 0xc2, 0x3e, 0xc4, 0xf5, 0xc3, 0xf4, 0xc7, + 0x68, 0xd1, 0xdc, 0xdb, 0x6f, 0xe5, 0x79, 0xeb, 0xf5, 0xee, 0xe3, 0xf3, + 0x3d, 0xfa, 0xc3, 0xfe, 0xbb, 0xfc, 0x1a, 0xf9, 0xa4, 0xf5, 0x3e, 0xf7, + 0x67, 0xfc, 0x75, 0xfd, 0xc8, 0xfe, 0x3b, 0xfd, 0xdd, 0xfe, 0x12, 0x06, + 0x12, 0x0b, 0x9d, 0x10, 0x25, 0x15, 0x94, 0x17, 0xd0, 0x1a, 0x92, 0x1b, + 0x6f, 0x18, 0xae, 0x10, 0x1d, 0x03, 0x59, 0xfc, 0xe1, 0xfe, 0x26, 0x00, + 0xca, 0xff, 0x51, 0x02, 0xc6, 0x06, 0xb4, 0x0b, 0x33, 0x10, 0x28, 0x13, + 0x2c, 0x16, 0x51, 0x15, 0xe9, 0x13, 0x7d, 0x16, 0x1a, 0x1b, 0x6d, 0x20, + 0xd7, 0x25, 0x79, 0x2d, 0x92, 0x2f, 0x06, 0x2d, 0x55, 0x2d, 0xc8, 0x2e, + 0x6a, 0x30, 0xd6, 0x33, 0x4e, 0x38, 0xf4, 0x3a, 0x8f, 0x3f, 0x77, 0x41, + 0x52, 0x3f, 0xc3, 0x40, 0x26, 0x43, 0x85, 0x43, 0x63, 0x3d, 0x9c, 0x30, + 0x81, 0x24, 0x81, 0x1e, 0xae, 0x1e, 0x7e, 0x22, 0x90, 0x27, 0x71, 0x2b, + 0xc3, 0x2d, 0xd1, 0x2c, 0x36, 0x2a, 0xbb, 0x27, 0x10, 0x26, 0xf9, 0x21, + 0x41, 0x18, 0x42, 0x0d, 0x6c, 0x04, 0x7e, 0x04, 0x59, 0x06, 0xdb, 0x04, + 0xd1, 0x03, 0x42, 0x03, 0x5f, 0x06, 0x69, 0x05, 0xc3, 0x02, 0x9a, 0x01, + 0x45, 0x06, 0xf9, 0x12, 0x47, 0x19, 0x02, 0x15, 0x05, 0x08, 0x75, 0xfe, + 0xfd, 0xf7, 0x0d, 0xf3, 0x14, 0xf4, 0xa0, 0xf4, 0x2b, 0xf8, 0xaf, 0xf8, + 0x27, 0xfa, 0x30, 0x01, 0xe6, 0x04, 0x8a, 0x08, 0x4a, 0x08, 0xcb, 0x03, + 0x84, 0x00, 0x25, 0xfd, 0x29, 0xff, 0x1a, 0x04, 0x2b, 0x05, 0x95, 0x09, + 0xd8, 0x13, 0x86, 0x20, 0xcb, 0x29, 0x9a, 0x2e, 0xfc, 0x32, 0x47, 0x35, + 0xa3, 0x3a, 0x7c, 0x3f, 0x0a, 0x41, 0x98, 0x43, 0x90, 0x42, 0xb2, 0x42, + 0xd7, 0x42, 0x46, 0x3e, 0x84, 0x3c, 0x50, 0x3d, 0x02, 0x3d, 0x65, 0x3f, + 0xa9, 0x42, 0x7a, 0x40, 0xdf, 0x3c, 0x2b, 0x39, 0xc1, 0x32, 0xcf, 0x29, + 0x2d, 0x22, 0xc4, 0x1a, 0xdc, 0x0d, 0xc5, 0x04, 0x7b, 0xfb, 0xe0, 0xf5, + 0x4f, 0xf6, 0xdc, 0xec, 0xfc, 0xea, 0x2d, 0xee, 0xf6, 0xed, 0x6a, 0xf5, + 0xf7, 0xf8, 0x62, 0xfa, 0xdb, 0xfe, 0x93, 0xf8, 0xfe, 0xf2, 0xb2, 0xf2, + 0x43, 0xea, 0x38, 0xe7, 0xc5, 0xe3, 0xd7, 0xe3, 0xfb, 0xea, 0x03, 0xec, + 0xab, 0xf1, 0xe8, 0xf3, 0x92, 0xfa, 0xe9, 0x05, 0x25, 0x09, 0x84, 0x0e, + 0x8d, 0x11, 0x3a, 0x15, 0x15, 0x20, 0x61, 0x26, 0xa0, 0x2a, 0x0b, 0x33, + 0x0f, 0x35, 0xe0, 0x3b, 0x35, 0x40, 0x7d, 0x3d, 0xdb, 0x42, 0x3a, 0x41, + 0x90, 0x43, 0xac, 0x48, 0xd7, 0x46, 0x3f, 0x4e, 0xab, 0x4e, 0x06, 0x49, + 0xaf, 0x4b, 0xf4, 0x48, 0x5b, 0x4a, 0x41, 0x4a, 0x9c, 0x40, 0xbc, 0x3d, + 0x18, 0x38, 0xa9, 0x34, 0x0c, 0x31, 0x08, 0x2e, 0xaf, 0x31, 0x26, 0x2b, + 0x44, 0x27, 0xd2, 0x24, 0xa0, 0x19, 0x6a, 0x10, 0x25, 0x05, 0x90, 0xf5, + 0xf7, 0xee, 0x86, 0xe9, 0x92, 0xdf, 0xdd, 0xda, 0x5e, 0xd8, 0x8c, 0xd3, + 0xc9, 0xcc, 0x6f, 0xd1, 0x1f, 0xd7, 0x4d, 0xd7, 0xec, 0xdb, 0x77, 0xdc, + 0x22, 0xdb, 0xf4, 0xda, 0x69, 0xd8, 0x8c, 0xd6, 0x36, 0xd7, 0x5a, 0xd4, + 0x99, 0xd6, 0x88, 0xd4, 0x93, 0xcd, 0x01, 0xd5, 0xde, 0xdd, 0x0c, 0xe6, + 0xf9, 0xe8, 0x93, 0xe8, 0x07, 0xeb, 0x2a, 0xec, 0x35, 0xf0, 0xad, 0xf0, + 0x37, 0xf0, 0x70, 0xf2, 0xac, 0xf3, 0xc3, 0xf8, 0x64, 0xff, 0x11, 0x06, + 0xbb, 0x12, 0x4c, 0x18, 0xbd, 0x10, 0xb6, 0x03, 0x25, 0xfd, 0x68, 0x01, + 0xdc, 0x06, 0x2a, 0x0f, 0x17, 0x16, 0x26, 0x1a, 0x84, 0x25, 0xb7, 0x34, + 0x1b, 0x36, 0x62, 0x33, 0x50, 0x36, 0x36, 0x38, 0x10, 0x38, 0x7c, 0x30, + 0x41, 0x2c, 0x2e, 0x2d, 0x5a, 0x2f, 0xf0, 0x30, 0xe6, 0x2f, 0x8f, 0x2b, + 0xfa, 0x23, 0xd5, 0x23, 0x8e, 0x26, 0x8b, 0x23, 0x0b, 0x1d, 0x4f, 0x18, + 0xde, 0x0f, 0xf4, 0x0a, 0xaa, 0x0d, 0x4a, 0x0e, 0xb8, 0x0e, 0x56, 0x0b, + 0xb4, 0x06, 0x41, 0x0a, 0xa0, 0x11, 0x89, 0x0f, 0xfe, 0x0b, 0xe1, 0x0a, + 0x6f, 0x03, 0x41, 0xfc, 0x51, 0xfc, 0xe3, 0xf7, 0x43, 0xf1, 0x44, 0xf0, + 0x28, 0xeb, 0x9d, 0xee, 0xba, 0xf3, 0xa6, 0xf5, 0x56, 0xff, 0x3a, 0x03, + 0xc7, 0x02, 0x4f, 0x06, 0xa8, 0x02, 0xaa, 0xf6, 0x5f, 0xec, 0x49, 0xe1, + 0x89, 0xdd, 0x3a, 0xe2, 0x9c, 0xe4, 0x86, 0xe8, 0x59, 0xf0, 0xf7, 0xf4, + 0x9a, 0xf5, 0x6d, 0xf8, 0xcd, 0xf6, 0xd7, 0xf3, 0x09, 0xf2, 0xfa, 0xe9, + 0x7c, 0xe7, 0xd6, 0xeb, 0xd5, 0xe9, 0xba, 0xe9, 0xff, 0xe8, 0x4d, 0xe9, + 0xf4, 0xee, 0x0d, 0xf3, 0x3f, 0xf8, 0x9f, 0xfa, 0x0c, 0x01, 0x19, 0x05, + 0x3d, 0x0a, 0x19, 0x0e, 0x39, 0x0d, 0xec, 0x15, 0xcf, 0x20, 0x97, 0x2c, + 0x33, 0x35, 0x03, 0x3d, 0xb4, 0x39, 0x0e, 0x3d, 0xee, 0x48, 0x5a, 0x4a, + 0xb7, 0x50, 0x03, 0x51, 0x12, 0x52, 0x30, 0x4f, 0xfe, 0x4b, 0x8b, 0x4c, + 0xb4, 0x4e, 0x25, 0x57, 0x2c, 0x56, 0x65, 0x50, 0x27, 0x49, 0x53, 0x42, + 0x70, 0x35, 0xe4, 0x2d, 0x5a, 0x26, 0x8c, 0x18, 0x84, 0x12, 0x76, 0x13, + 0x6d, 0x18, 0x10, 0x1c, 0x07, 0x24, 0x62, 0x1f, 0xb5, 0x1c, 0x02, 0x19, + 0x81, 0x0f, 0x1c, 0x0c, 0x5f, 0x01, 0x9f, 0x01, 0xf9, 0xfd, 0x61, 0xf8, + 0x80, 0xf4, 0xab, 0xf7, 0xee, 0x02, 0xae, 0x04, 0x3a, 0x13, 0x5e, 0x1c, + 0x1d, 0x1f, 0xc8, 0x21, 0x80, 0x21, 0x2b, 0x22, 0x7f, 0x18, 0x6b, 0x16, + 0x3f, 0x16, 0x92, 0x12, 0x2a, 0x14, 0xc3, 0x14, 0xf9, 0x1e, 0x55, 0x29, + 0xbd, 0x23, 0xf3, 0x23, 0xf0, 0x29, 0xa6, 0x25, 0x75, 0x20, 0x22, 0x1e, + 0x7a, 0x1c, 0x44, 0x1d, 0xea, 0x1d, 0xc6, 0x1b, 0x78, 0x16, 0x89, 0x13, + 0x2d, 0x14, 0x29, 0x11, 0x33, 0x0e, 0x91, 0x09, 0x68, 0x01, 0x3b, 0xfc, + 0x0c, 0xf8, 0xbb, 0xef, 0x27, 0xe6, 0x7e, 0xdf, 0x71, 0xdc, 0x49, 0xdd, + 0x92, 0xd7, 0x16, 0xd9, 0x65, 0xe1, 0x75, 0xe3, 0x82, 0xde, 0xef, 0xd2, + 0x67, 0xd4, 0x8d, 0xd2, 0xb1, 0xcf, 0xd8, 0xcf, 0xed, 0xca, 0x94, 0xcf, + 0x2f, 0xd2, 0x79, 0xd4, 0xe4, 0xd4, 0xf7, 0xcd, 0x8c, 0xc3, 0x1a, 0xbe, + 0x9b, 0xba, 0xdc, 0xb1, 0x38, 0xb3, 0xc3, 0xb8, 0x3b, 0xb9, 0x3e, 0xba, + 0x01, 0xbc, 0x6c, 0xbc, 0x91, 0xbf, 0x62, 0xc0, 0x14, 0xbf, 0x66, 0xbd, + 0xcc, 0xb5, 0x1c, 0xb1, 0xa6, 0xaf, 0x38, 0xb1, 0xb4, 0xb5, 0xc1, 0xbb, + 0xe2, 0xbd, 0x6a, 0xbe, 0x3f, 0xc5, 0x07, 0xc8, 0xf6, 0xcc, 0x7e, 0xd3, + 0x46, 0xd6, 0x0e, 0xda, 0x50, 0xda, 0x90, 0xdb, 0x06, 0xdf, 0x31, 0xe5, + 0x4d, 0xe9, 0xe8, 0xe9, 0x1b, 0xec, 0x49, 0xe7, 0x1a, 0xee, 0x7b, 0xf7, + 0xbc, 0xf5, 0x84, 0xfe, 0x6b, 0x06, 0x06, 0x11, 0x5f, 0x1b, 0xaa, 0x1d, + 0xa9, 0x27, 0x61, 0x31, 0x18, 0x35, 0xf2, 0x38, 0x09, 0x3b, 0x94, 0x3a, + 0xb4, 0x37, 0xc5, 0x32, 0x67, 0x32, 0x93, 0x30, 0x80, 0x30, 0xa3, 0x31, + 0x88, 0x2b, 0x61, 0x2d, 0x58, 0x2f, 0x38, 0x2f, 0xef, 0x31, 0x6d, 0x2e, + 0xd1, 0x2e, 0x83, 0x2c, 0x5a, 0x22, 0xa2, 0x1d, 0x11, 0x1a, 0x80, 0x14, + 0x0e, 0x13, 0x8c, 0x16, 0x55, 0x18, 0x2a, 0x19, 0x8a, 0x1b, 0x1b, 0x1c, + 0x56, 0x20, 0x05, 0x23, 0x37, 0x1d, 0x0b, 0x15, 0x27, 0x10, 0x16, 0x09, + 0x53, 0x06, 0x32, 0x07, 0xf4, 0x04, 0x5e, 0x05, 0x05, 0xfc, 0xf7, 0xf2, + 0x69, 0xf1, 0x94, 0xf4, 0x94, 0xf6, 0x08, 0xf0, 0x01, 0xee, 0x4b, 0xef, + 0xca, 0xf5, 0xe5, 0xf5, 0x47, 0xf7, 0xbd, 0x01, 0x19, 0x03, 0x26, 0x01, + 0xd1, 0x00, 0xf1, 0x06, 0x02, 0x11, 0x39, 0x18, 0xd2, 0x25, 0xee, 0x38, + 0x68, 0x3d, 0xc7, 0x40, 0xc0, 0x44, 0x3f, 0x44, 0xab, 0x4d, 0xda, 0x4d, + 0xc9, 0x4d, 0x1f, 0x50, 0xf0, 0x4b, 0x18, 0x45, 0x68, 0x3d, 0x5c, 0x3a, + 0x12, 0x38, 0xd4, 0x3c, 0x68, 0x3e, 0xb7, 0x3e, 0x61, 0x42, 0xdd, 0x3c, + 0x82, 0x2e, 0xaf, 0x22, 0x31, 0x20, 0xfb, 0x1b, 0x22, 0x19, 0x53, 0x18, + 0x16, 0x10, 0xab, 0x04, 0xf1, 0x00, 0xff, 0xfd, 0xa3, 0xfa, 0xce, 0xfa, + 0x6d, 0xfa, 0x71, 0xfd, 0xc8, 0xf8, 0xba, 0xf3, 0x46, 0xf5, 0xa4, 0xf2, + 0x12, 0xeb, 0x90, 0xe3, 0x7c, 0xe3, 0x82, 0xe6, 0x1f, 0xe7, 0xaf, 0xe6, + 0x49, 0xe7, 0x67, 0xe2, 0x4c, 0xe3, 0x51, 0xe6, 0x35, 0xe3, 0x74, 0xe6, + 0x9e, 0xe8, 0x3e, 0xf0, 0x09, 0xf4, 0x1c, 0xf2, 0x84, 0xf5, 0x3c, 0xf3, + 0xda, 0xf3, 0xc4, 0xf5, 0x72, 0xfa, 0xf6, 0xfc, 0x26, 0xf7, 0x01, 0xfa, + 0xfd, 0xfb, 0x76, 0xfd, 0xa8, 0x04, 0xe2, 0x03, 0xb2, 0x02, 0xcb, 0x04, + 0xdf, 0x01, 0xc8, 0xfd, 0x7e, 0xfd, 0xde, 0x00, 0x1f, 0x05, 0xb3, 0x06, + 0xf4, 0x01, 0x31, 0xfd, 0x1a, 0x01, 0x0f, 0x03, 0xba, 0xff, 0x1f, 0x03, + 0xfa, 0x04, 0xad, 0x03, 0xf9, 0x04, 0x4d, 0x02, 0xe5, 0x00, 0x3e, 0x05, + 0x55, 0x0d, 0x02, 0x13, 0x35, 0x15, 0x6d, 0x10, 0xc1, 0x07, 0xea, 0x06, + 0x94, 0x03, 0x14, 0xfc, 0x17, 0xf7, 0x33, 0xf2, 0x51, 0xf1, 0x48, 0xf1, + 0x1a, 0xe9, 0x69, 0xe1, 0xe6, 0xdc, 0x5e, 0xd6, 0x45, 0xd3, 0x26, 0xce, + 0xd9, 0xc9, 0x19, 0xc8, 0x92, 0xc2, 0x96, 0xc1, 0xe5, 0xc2, 0xa8, 0xc4, + 0x46, 0xcd, 0x98, 0xd3, 0x46, 0xd5, 0xd3, 0xd8, 0x3a, 0xdc, 0xb8, 0xe0, + 0x7c, 0xe5, 0xee, 0xe6, 0xc3, 0xe6, 0xd9, 0xe7, 0xd9, 0xeb, 0x78, 0xf1, + 0x9b, 0xf6, 0x5c, 0xfa, 0xaa, 0xfe, 0x29, 0x0a, 0xc4, 0x15, 0xf4, 0x1c, + 0x57, 0x27, 0x29, 0x28, 0x9b, 0x24, 0xd9, 0x25, 0x8b, 0x21, 0x85, 0x1e, + 0x10, 0x1b, 0xc2, 0x15, 0xb5, 0x16, 0x87, 0x1a, 0x18, 0x1a, 0x5a, 0x18, + 0x70, 0x1d, 0x38, 0x21, 0xee, 0x1d, 0x30, 0x19, 0xa2, 0x10, 0x9b, 0x0c, + 0x34, 0x0f, 0xf3, 0x0b, 0x69, 0x0b, 0xa9, 0x0b, 0x77, 0x04, 0xe8, 0x01, + 0x38, 0x03, 0xd7, 0x04, 0xaa, 0x09, 0x35, 0x11, 0x78, 0x16, 0x21, 0x16, + 0xf3, 0x1c, 0xb0, 0x24, 0xd2, 0x2b, 0x8f, 0x2f, 0x1b, 0x29, 0x85, 0x26, + 0xac, 0x19, 0xc4, 0x11, 0x98, 0x15, 0xf0, 0x15, 0x6f, 0x20, 0x2f, 0x29, + 0xaf, 0x2e, 0x85, 0x32, 0xba, 0x31, 0x12, 0x33, 0x38, 0x35, 0xba, 0x2b, + 0xd2, 0x1e, 0x61, 0x13, 0x50, 0xfd, 0xf4, 0xef, 0x46, 0xef, 0xc8, 0xf0, + 0x0f, 0xeb, 0xbf, 0xde, 0xf6, 0xd2, 0x51, 0xcb, 0xc8, 0xc4, 0x23, 0xbd, + 0x2a, 0xc4, 0x80, 0xc7, 0x53, 0xc1, 0xb6, 0xbe, 0x3e, 0xbc, 0x1c, 0xbb, + 0x5e, 0xb8, 0x77, 0xb4, 0x75, 0xb1, 0xa7, 0xb1, 0x57, 0xb1, 0x17, 0xae, + 0x4b, 0xab, 0xe5, 0xa9, 0x7d, 0xab, 0x52, 0xb1, 0x5e, 0xb9, 0x17, 0xc4, + 0xbf, 0xc7, 0x8d, 0xc8, 0xaa, 0xd0, 0x9a, 0xd1, 0x6d, 0xd3, 0x00, 0xd9, + 0xb0, 0xdf, 0xde, 0xe8, 0x70, 0xea, 0x79, 0xe9, 0x48, 0xec, 0x6c, 0xf1, + 0x0e, 0xf7, 0x54, 0x00, 0x25, 0x07, 0xa2, 0x06, 0x51, 0x04, 0x6e, 0x04, + 0x8a, 0x05, 0x82, 0x04, 0x95, 0x08, 0xee, 0x0b, 0x2e, 0x08, 0x94, 0x04, + 0xaf, 0x01, 0x81, 0xff, 0x87, 0x00, 0xda, 0x06, 0x30, 0x0d, 0x51, 0x0e, + 0x1b, 0x0b, 0x81, 0x04, 0x77, 0x06, 0xd6, 0x03, 0xa9, 0xfa, 0x08, 0xfc, + 0xb3, 0xf8, 0x8b, 0xfa, 0xa6, 0x01, 0x1c, 0x00, 0x42, 0xfa, 0xf1, 0xf0, + 0x88, 0xe8, 0xc8, 0xdb, 0xc3, 0xce, 0x9c, 0xc4, 0xae, 0xc0, 0x44, 0xc3, + 0x5d, 0xc1, 0x73, 0xc1, 0x85, 0xc0, 0xe4, 0xbc, 0xa5, 0xbd, 0xc4, 0xbb, + 0x44, 0xb6, 0xe1, 0xaf, 0x05, 0xac, 0x9a, 0xa9, 0x4c, 0xa7, 0x36, 0xa8, + 0x9c, 0xaa, 0xeb, 0xae, 0x20, 0xb4, 0x3e, 0xbd, 0x58, 0xc6, 0x5f, 0xce, + 0xe6, 0xda, 0xa0, 0xe4, 0x16, 0xeb, 0x2d, 0xef, 0xca, 0xf1, 0x56, 0xf5, + 0xae, 0xfe, 0x63, 0x0f, 0xe5, 0x1e, 0xe0, 0x28, 0x0e, 0x31, 0x55, 0x3b, + 0x8b, 0x40, 0x21, 0x42, 0xa2, 0x42, 0x5d, 0x3f, 0xf7, 0x3f, 0x3e, 0x48, + 0x1c, 0x50, 0x87, 0x53, 0x1c, 0x53, 0x15, 0x51, 0xd6, 0x4f, 0xd8, 0x47, + 0x28, 0x43, 0x72, 0x44, 0x6d, 0x3d, 0x30, 0x33, 0x0b, 0x2a, 0xec, 0x23, + 0x8b, 0x19, 0x89, 0x0b, 0x6c, 0x06, 0xa6, 0x06, 0xf6, 0x06, 0x1e, 0x07, + 0x8b, 0x0d, 0xe9, 0x0e, 0x9a, 0xfd, 0xa4, 0xed, 0xf5, 0xe7, 0x73, 0xe1, + 0x03, 0xd5, 0x12, 0xd1, 0x56, 0xdc, 0x37, 0xe1, 0x89, 0xdb, 0x64, 0xd7, + 0xbb, 0xda, 0x1e, 0xe0, 0xe2, 0xde, 0x77, 0xde, 0xba, 0xde, 0xc4, 0xd5, + 0xa8, 0xca, 0x8a, 0xc4, 0x70, 0xc7, 0x51, 0xcf, 0x6f, 0xd4, 0xac, 0xdc, + 0x23, 0xde, 0x87, 0xda, 0x79, 0xd9, 0xc7, 0xda, 0x56, 0xe5, 0xf8, 0xe7, + 0xff, 0xe5, 0x28, 0xe9, 0x40, 0xea, 0xe8, 0xed, 0xd9, 0xf6, 0x75, 0x01, + 0x17, 0x07, 0x54, 0x09, 0x3a, 0x07, 0xee, 0xfd, 0x09, 0xfb, 0xc5, 0x02, + 0x1c, 0x02, 0x5f, 0xfe, 0xdf, 0xfe, 0x9a, 0xfa, 0x27, 0xfa, 0xa5, 0xf4, + 0xa9, 0xee, 0x37, 0xf4, 0x35, 0xf5, 0x2f, 0xf5, 0xbc, 0xf5, 0x58, 0xf4, + 0x31, 0xf3, 0xc7, 0xed, 0x47, 0xea, 0xfd, 0xe4, 0x73, 0xe0, 0xfb, 0xe5, + 0x08, 0xec, 0x97, 0xf2, 0xce, 0xf3, 0x10, 0xf4, 0xcd, 0xfd, 0xbb, 0x01, + 0xd2, 0x04, 0x53, 0x0a, 0xe4, 0x12, 0xc9, 0x1d, 0xd7, 0x20, 0xa3, 0x28, + 0xaa, 0x32, 0xe5, 0x3d, 0x1d, 0x49, 0x28, 0x4a, 0x82, 0x4a, 0x58, 0x49, + 0x3a, 0x46, 0x2e, 0x40, 0x83, 0x36, 0xa9, 0x2c, 0xb7, 0x1c, 0x5c, 0x11, + 0x43, 0x12, 0x55, 0x15, 0xa2, 0x1b, 0x8d, 0x1b, 0x05, 0x11, 0xc7, 0x0a, + 0xa7, 0x02, 0x2a, 0xfd, 0x2c, 0xf9, 0x71, 0xeb, 0xdd, 0xe2, 0xfa, 0xdc, + 0xa2, 0xd6, 0x5d, 0xd5, 0xf9, 0xd5, 0xe8, 0xd8, 0xe8, 0xdb, 0xe3, 0xdc, + 0x83, 0xdd, 0x74, 0xe1, 0xae, 0xe6, 0xb7, 0xec, 0xe0, 0xf4, 0x49, 0xf8, + 0xb6, 0xfa, 0xbb, 0xfd, 0xa7, 0xfa, 0x3a, 0xf9, 0x11, 0xfb, 0xb5, 0xfb, + 0x0e, 0xfd, 0x00, 0xfa, 0x9d, 0xf9, 0xd7, 0x02, 0xc4, 0x0b, 0xf5, 0x0d, + 0x1c, 0x0a, 0x98, 0x07, 0xb6, 0x06, 0xa9, 0x07, 0xb8, 0x0b, 0x94, 0x0a, + 0xfc, 0x07, 0x9a, 0x06, 0x6b, 0x04, 0x41, 0x07, 0x1e, 0x0d, 0x29, 0x13, + 0x9a, 0x18, 0x31, 0x1c, 0x83, 0x24, 0xe5, 0x2d, 0x65, 0x32, 0x93, 0x33, + 0x56, 0x30, 0xbd, 0x32, 0x49, 0x38, 0xf1, 0x37, 0x32, 0x39, 0x32, 0x39, + 0xed, 0x34, 0x8e, 0x30, 0xb7, 0x2d, 0x91, 0x2f, 0xe8, 0x32, 0xb4, 0x32, + 0x39, 0x2f, 0x15, 0x25, 0x68, 0x18, 0x99, 0x12, 0x33, 0x0e, 0x4d, 0x0c, + 0xcd, 0x09, 0x08, 0x03, 0x79, 0xff, 0x16, 0xfd, 0xbc, 0xfb, 0x45, 0xf9, + 0x47, 0xf6, 0xac, 0xf7, 0x6f, 0xfa, 0x8f, 0xfd, 0x9b, 0xfc, 0xe1, 0xf8, + 0xa1, 0xf8, 0x60, 0xf8, 0x89, 0xfa, 0xd0, 0xfc, 0x02, 0xf9, 0xde, 0xf9, + 0x23, 0xfd, 0x15, 0xfe, 0xa3, 0x00, 0x80, 0xfe, 0x04, 0x03, 0xcb, 0x0f, + 0xd1, 0x16, 0x31, 0x1b, 0xb2, 0x19, 0xf6, 0x11, 0xd0, 0x0e, 0x82, 0x16, + 0x40, 0x20, 0xc8, 0x1d, 0x53, 0x16, 0x51, 0x15, 0x20, 0x19, 0xe7, 0x1d, + 0xf0, 0x1c, 0x76, 0x15, 0xaf, 0x16, 0x9a, 0x23, 0x87, 0x2d, 0x41, 0x32, + 0x0f, 0x35, 0x68, 0x2f, 0xec, 0x28, 0x4e, 0x2f, 0xa3, 0x39, 0x5f, 0x40, + 0x83, 0x49, 0x0c, 0x4f, 0x97, 0x50, 0x3b, 0x53, 0x28, 0x50, 0x3a, 0x4d, + 0x9f, 0x47, 0x4b, 0x40, 0xd8, 0x39, 0xf4, 0x2f, 0x25, 0x2b, 0x25, 0x1e, + 0x7a, 0x13, 0x5f, 0x0c, 0xef, 0xf9, 0xd6, 0xed, 0x9f, 0xe1, 0x74, 0xd5, + 0xb6, 0xce, 0x59, 0xca, 0xee, 0xcd, 0xaf, 0xcc, 0xac, 0xc2, 0xb7, 0xbf, + 0x19, 0xbb, 0x5a, 0xba, 0x23, 0xc6, 0xd8, 0xcd, 0x5a, 0xd7, 0x8e, 0xdb, + 0xfd, 0xde, 0xfd, 0xe5, 0x57, 0xe6, 0x81, 0xe8, 0x3b, 0xe9, 0xd2, 0xec, + 0x61, 0xed, 0x45, 0xef, 0x40, 0xfa, 0xf4, 0x03, 0x7b, 0x0c, 0x2b, 0x0c, + 0x6f, 0x0a, 0x7d, 0x0f, 0x64, 0x14, 0xd4, 0x19, 0x32, 0x19, 0xf2, 0x0e, + 0x3b, 0x0b, 0x51, 0x0a, 0x16, 0x07, 0x60, 0x09, 0x94, 0x05, 0xa0, 0xfd, + 0x1f, 0xf9, 0xf4, 0xf2, 0x74, 0xf3, 0x9e, 0xf8, 0x76, 0xf6, 0x72, 0xf7, + 0xff, 0xf9, 0xfd, 0xfb, 0x3f, 0x08, 0xc1, 0x13, 0x0a, 0x1b, 0xf7, 0x20, + 0x47, 0x25, 0x9f, 0x24, 0x02, 0x23, 0x23, 0x28, 0xcc, 0x2d, 0x9a, 0x3a, + 0x2e, 0x43, 0xff, 0x46, 0x5a, 0x4a, 0xb1, 0x45, 0xe6, 0x4c, 0x13, 0x4e, + 0x2c, 0x42, 0x46, 0x3a, 0xda, 0x31, 0x44, 0x2d, 0xde, 0x28, 0x96, 0x24, + 0x03, 0x1c, 0x4c, 0x10, 0xed, 0x08, 0x18, 0x02, 0x60, 0xfe, 0x65, 0xfd, + 0x27, 0xfb, 0x75, 0xf5, 0xc3, 0xf2, 0x53, 0xf5, 0xa9, 0xf7, 0x3f, 0xf6, + 0x3a, 0xf2, 0x5b, 0xee, 0x23, 0xe8, 0x1c, 0xe5, 0xb9, 0xe7, 0x0e, 0xec, + 0xe4, 0xf4, 0xf0, 0xff, 0x32, 0x05, 0x31, 0x0a, 0x4c, 0x0f, 0x37, 0x13, + 0xe3, 0x17, 0xc5, 0x19, 0x5e, 0x1b, 0x67, 0x18, 0xa2, 0x18, 0x27, 0x1c, + 0xf9, 0x1b, 0x5e, 0x1c, 0x39, 0x1c, 0x09, 0x24, 0x7e, 0x29, 0xb0, 0x28, + 0x25, 0x27, 0x86, 0x22, 0x6c, 0x1f, 0x1b, 0x17, 0x25, 0x13, 0x3b, 0x13, + 0xe9, 0x0e, 0x49, 0x08, 0x97, 0xf9, 0x75, 0xf6, 0x6a, 0xfc, 0x90, 0xfa, + 0x6d, 0xfd, 0xd7, 0xfa, 0x9d, 0xf6, 0xe6, 0xfc, 0x6c, 0x00, 0xe1, 0x04, + 0x76, 0x07, 0x28, 0x05, 0x1e, 0x06, 0x6d, 0x08, 0xbf, 0x08, 0x63, 0x09, + 0xdd, 0x0e, 0x07, 0x15, 0x94, 0x16, 0xaa, 0x12, 0x72, 0x15, 0x96, 0x1f, + 0x30, 0x23, 0xf9, 0x1c, 0xa4, 0x16, 0x78, 0x18, 0x7d, 0x13, 0x03, 0x15, + 0x0e, 0x1d, 0x59, 0x1e, 0xb5, 0x1f, 0xb4, 0x15, 0x3a, 0x0e, 0xcf, 0x01, + 0xfb, 0xed, 0x2f, 0xed, 0x5d, 0xf4, 0x28, 0xfd, 0x35, 0x00, 0x32, 0xf6, + 0x4b, 0xf3, 0xef, 0xf8, 0x11, 0x01, 0xde, 0x13, 0xee, 0x1e, 0xe2, 0x20, + 0x6e, 0x1f, 0xc3, 0x18, 0x07, 0x1f, 0x85, 0x22, 0x81, 0x1e, 0xba, 0x18, + 0x49, 0x12, 0x4f, 0x16, 0xbc, 0x17, 0x9f, 0x1d, 0x8e, 0x28, 0xfe, 0x2e, + 0x37, 0x30, 0x4b, 0x21, 0x57, 0x17, 0x6c, 0x1b, 0xad, 0x1e, 0x1c, 0x1e, + 0x94, 0x1c, 0xaa, 0x1e, 0x0b, 0x1d, 0xda, 0x1b, 0x21, 0x1b, 0x38, 0x1b, + 0xe8, 0x1b, 0x12, 0x14, 0x46, 0x0f, 0x4b, 0x0d, 0xe7, 0x0e, 0x8f, 0x0e, + 0xde, 0x00, 0x68, 0xfb, 0x26, 0xff, 0x28, 0xfb, 0x15, 0x00, 0x79, 0x03, + 0x1c, 0xfb, 0x96, 0x04, 0xd1, 0x06, 0xc9, 0xfc, 0x1b, 0xfc, 0xe3, 0xf1, + 0x71, 0xe5, 0x28, 0xdb, 0x9c, 0xd2, 0x66, 0xd5, 0x07, 0xd8, 0x82, 0xd6, + 0x36, 0xd9, 0xd9, 0xd5, 0xed, 0xce, 0x3f, 0xcd, 0xe8, 0xc7, 0x19, 0xc7, + 0x31, 0xc9, 0x00, 0xc8, 0x1b, 0xc6, 0x0f, 0xc4, 0x1e, 0xc5, 0xb5, 0xc4, + 0xb3, 0xc6, 0x94, 0xc7, 0xcd, 0xc2, 0x7d, 0xc2, 0x5e, 0xc1, 0xb3, 0xbe, + 0x77, 0xbf, 0x86, 0xc1, 0x09, 0xc5, 0x71, 0xc6, 0xa6, 0xc6, 0x09, 0xcb, + 0x4e, 0xd3, 0x6c, 0xdc, 0xda, 0xdf, 0x0a, 0xdb, 0x26, 0xd8, 0x3d, 0xd8, + 0xfb, 0xd3, 0x05, 0xd1, 0x0a, 0xd0, 0xa7, 0xce, 0xdd, 0xd1, 0xe9, 0xd8, + 0x25, 0xe0, 0xcd, 0xe9, 0x8a, 0xf3, 0x36, 0xf8, 0xc4, 0xfa, 0x76, 0xfe, + 0xf5, 0x03, 0x5d, 0x06, 0xbb, 0x04, 0xb9, 0x03, 0xbc, 0x02, 0xbb, 0x04, + 0x2d, 0x07, 0xc8, 0x05, 0x67, 0x0a, 0x65, 0x18, 0x10, 0x28, 0xe6, 0x30, + 0x31, 0x35, 0xdc, 0x38, 0xec, 0x3a, 0x44, 0x3e, 0xb1, 0x43, 0xc9, 0x47, + 0xc9, 0x48, 0xfa, 0x45, 0x1c, 0x3f, 0x37, 0x40, 0x26, 0x43, 0x0e, 0x3c, + 0xaf, 0x32, 0xa3, 0x27, 0xe5, 0x23, 0xed, 0x24, 0xec, 0x24, 0xfe, 0x27, + 0x59, 0x29, 0xd7, 0x29, 0xfc, 0x2b, 0x55, 0x2d, 0xc8, 0x26, 0x59, 0x1b, + 0xa5, 0x11, 0xa5, 0x0c, 0xa7, 0x08, 0x77, 0x04, 0x3e, 0x02, 0x4c, 0xf9, + 0x00, 0xf5, 0x55, 0xfc, 0xc0, 0xfd, 0xb1, 0x03, 0x97, 0x0a, 0x6d, 0x01, + 0xf4, 0x02, 0xe2, 0x03, 0x2d, 0x00, 0x5a, 0x05, 0xba, 0xfb, 0x1f, 0xf9, + 0xe8, 0xf8, 0x99, 0xf2, 0x77, 0xfc, 0x89, 0xfd, 0x45, 0xfd, 0x7f, 0xff, + 0x66, 0xf7, 0x6b, 0xfc, 0x1a, 0x03, 0x36, 0x02, 0x76, 0x02, 0xb2, 0xff, + 0x8f, 0x03, 0x33, 0x0a, 0x87, 0x0e, 0xa3, 0x12, 0x35, 0x14, 0x6b, 0x15, + 0xd0, 0x16, 0x3b, 0x1e, 0x19, 0x29, 0xc2, 0x2a, 0xf7, 0x2d, 0x83, 0x3b, + 0xaa, 0x48, 0x07, 0x52, 0xbe, 0x54, 0xdb, 0x58, 0x3e, 0x5c, 0x7c, 0x5e, + 0xe1, 0x63, 0xae, 0x62, 0x80, 0x60, 0xca, 0x56, 0x80, 0x50, 0x9e, 0x54, + 0x26, 0x52, 0x03, 0x4e, 0xc4, 0x4b, 0x26, 0x49, 0x77, 0x3e, 0xff, 0x39, + 0x95, 0x41, 0xbe, 0x38, 0x9b, 0x26, 0x06, 0x16, 0x33, 0x03, 0x11, 0xff, + 0x53, 0xef, 0x8d, 0xda, 0xdb, 0xde, 0x23, 0xd8, 0xf1, 0xd5, 0xfa, 0xd4, + 0xbb, 0xcf, 0x44, 0xd8, 0x90, 0xd4, 0x13, 0xd5, 0xed, 0xd5, 0x56, 0xd2, + 0xc7, 0xd6, 0x1e, 0xdb, 0xd4, 0xde, 0x67, 0xdd, 0x13, 0xe5, 0x29, 0xec, + 0xfc, 0xe8, 0x3c, 0xf0, 0x25, 0xf4, 0x76, 0xf1, 0xdb, 0xfa, 0x0e, 0x02, + 0xad, 0x06, 0xf2, 0x08, 0x1a, 0x06, 0x1d, 0x0d, 0xd3, 0x0a, 0x3f, 0x07, + 0x4e, 0x0d, 0x82, 0x0b, 0x29, 0x0c, 0xcb, 0x0f, 0x63, 0x11, 0xc0, 0x0a, + 0x88, 0x05, 0x8e, 0x06, 0x4c, 0x04, 0x21, 0x0b, 0x9a, 0x0f, 0x8e, 0x10, + 0xb1, 0x12, 0xb1, 0x0b, 0x94, 0x08, 0x1d, 0x08, 0x8d, 0x07, 0xe6, 0x0c, + 0x8b, 0x0f, 0x74, 0x0c, 0xf0, 0x09, 0xfe, 0x06, 0xbd, 0x06, 0xcc, 0x07, + 0x23, 0x09, 0x33, 0x0e, 0xa2, 0x0b, 0x28, 0x0d, 0x43, 0x0f, 0x6e, 0x08, + 0xc3, 0x07, 0xc2, 0x02, 0xac, 0xfc, 0x5c, 0xf6, 0x7b, 0xeb, 0x20, 0xe7, + 0x48, 0xeb, 0x4f, 0xf1, 0xa7, 0xed, 0xc4, 0xe4, 0xde, 0xdc, 0xf6, 0xd9, + 0xe5, 0xdc, 0xb4, 0xd8, 0x7f, 0xd2, 0xea, 0xcb, 0xfe, 0xbf, 0xc5, 0xc1, + 0x40, 0xc7, 0x48, 0xc8, 0x3f, 0xcd, 0x88, 0xc8, 0xc8, 0xc7, 0x59, 0xcb, + 0xc0, 0xc7, 0xe0, 0xc8, 0x8c, 0xcb, 0x2d, 0xd0, 0xa7, 0xd8, 0xeb, 0xda, + 0xa8, 0xd9, 0x07, 0xde, 0x8b, 0xe5, 0x57, 0xea, 0xf0, 0xea, 0x3b, 0xed, + 0xb0, 0xec, 0xb2, 0xef, 0x03, 0xfc, 0x71, 0x00, 0xdc, 0x05, 0x4c, 0x09, + 0x1d, 0x04, 0xae, 0x06, 0xaf, 0x0b, 0x70, 0x0e, 0x43, 0x15, 0xc5, 0x10, + 0x94, 0x05, 0x66, 0x08, 0x61, 0x06, 0x93, 0x05, 0x1c, 0x0d, 0x60, 0x08, + 0xd8, 0x08, 0x4a, 0x0c, 0x68, 0x08, 0x5f, 0x16, 0xe5, 0x21, 0xbf, 0x1a, + 0xc5, 0x1e, 0xc6, 0x19, 0xb2, 0x0c, 0xc8, 0x11, 0x2d, 0x0e, 0xe1, 0x09, + 0xe4, 0x0d, 0xd8, 0x01, 0x20, 0xff, 0xfe, 0x09, 0x88, 0x0c, 0x32, 0x15, + 0xbd, 0x11, 0x4e, 0x00, 0x7f, 0x00, 0x4d, 0x05, 0xfb, 0x04, 0xf5, 0x04, + 0x25, 0x01, 0x5d, 0xfd, 0x24, 0xfd, 0x81, 0xff, 0x6d, 0x04, 0xda, 0x04, + 0x08, 0x08, 0x8a, 0x11, 0xa4, 0x17, 0xe6, 0x1b, 0x9c, 0x19, 0xfe, 0x19, + 0x45, 0x22, 0x00, 0x2c, 0x15, 0x32, 0x2f, 0x2b, 0xd2, 0x27, 0x3a, 0x20, + 0x03, 0x0f, 0x75, 0x08, 0x73, 0xf9, 0x7f, 0xec, 0xfb, 0xeb, 0x22, 0xdd, + 0x1e, 0xd3, 0xf9, 0xce, 0x8b, 0xbd, 0xd4, 0xb9, 0x16, 0xbf, 0x5c, 0xb7, + 0x7a, 0xb6, 0x29, 0xaf, 0xc2, 0x9c, 0x21, 0x9f, 0x1d, 0x9e, 0x6c, 0x99, + 0x53, 0xa6, 0x13, 0xa6, 0xd7, 0xa1, 0xae, 0xa7, 0xaa, 0xa4, 0xc3, 0xa7, + 0x8a, 0xae, 0x3a, 0xb1, 0x86, 0xbe, 0x5e, 0xc4, 0x93, 0xc8, 0x54, 0xd9, + 0x8a, 0xe4, 0x2b, 0xf0, 0x53, 0xfd, 0x8b, 0x03, 0x52, 0x0b, 0xfa, 0x0f, + 0x8e, 0x11, 0x90, 0x1f, 0xa3, 0x28, 0xf2, 0x23, 0x50, 0x23, 0x98, 0x25, + 0xd2, 0x24, 0x14, 0x21, 0xd4, 0x22, 0x58, 0x21, 0x72, 0x1b, 0xb2, 0x18, + 0xa5, 0x0f, 0x63, 0x06, 0x92, 0x01, 0xd0, 0xfe, 0x08, 0xfb, 0x42, 0xf9, + 0x03, 0xf5, 0x84, 0xee, 0x55, 0xef, 0x6a, 0xef, 0x5a, 0xf1, 0x2e, 0xef, + 0xe2, 0xec, 0x68, 0xf0, 0xcd, 0xeb, 0x1a, 0xe6, 0x24, 0xe3, 0xfb, 0xdd, + 0x87, 0xd9, 0x7d, 0xd7, 0x29, 0xd3, 0xdc, 0xd1, 0xe6, 0xd4, 0xa8, 0xd4, + 0xdf, 0xd4, 0x9d, 0xd2, 0x75, 0xcd, 0x9f, 0xc9, 0x1d, 0xc8, 0x90, 0xca, + 0x7a, 0xcb, 0x5c, 0xc9, 0x2a, 0xc1, 0x7a, 0xb6, 0xf6, 0xb4, 0xd0, 0xb4, + 0x83, 0xb3, 0x5e, 0xb8, 0x00, 0xbd, 0x2f, 0xc3, 0xa2, 0xc8, 0x25, 0xc7, + 0x6f, 0xcb, 0x91, 0xd1, 0x8e, 0xd7, 0x78, 0xe7, 0x69, 0xf2, 0xe5, 0xf3, + 0x87, 0xf8, 0x48, 0x00, 0x99, 0x0b, 0x33, 0x18, 0x32, 0x1e, 0x34, 0x20, + 0x6c, 0x24, 0xf6, 0x2f, 0xa1, 0x3e, 0x89, 0x43, 0xbe, 0x43, 0x11, 0x46, + 0x27, 0x41, 0xa9, 0x40, 0x03, 0x46, 0x77, 0x3d, 0x55, 0x39, 0x59, 0x3a, + 0x45, 0x2f, 0x22, 0x27, 0xb4, 0x1e, 0xc0, 0x10, 0x62, 0x12, 0x9a, 0x12, + 0x97, 0x05, 0x71, 0x08, 0x00, 0x04, 0x4f, 0xfe, 0x51, 0x06, 0x84, 0xf9, + 0x2e, 0xf1, 0x0e, 0xed, 0x71, 0xde, 0xd9, 0xe0, 0xbf, 0xdd, 0x7f, 0xd5, + 0xac, 0xe0, 0x72, 0xde, 0x0d, 0xde, 0xa9, 0xe1, 0x36, 0xd4, 0x43, 0xdd, + 0xd2, 0xe0, 0x44, 0xd7, 0x9f, 0xdb, 0x39, 0xd2, 0x38, 0xcb, 0x42, 0xcb, + 0x15, 0xc7, 0x75, 0xd2, 0xd7, 0xd9, 0x51, 0xd0, 0x8b, 0xcf, 0xf6, 0xd2, + 0xa2, 0xd7, 0x98, 0xe7, 0xb0, 0xec, 0x01, 0xe7, 0x4d, 0xef, 0x51, 0xf3, + 0xef, 0xf5, 0x99, 0x03, 0xf2, 0x06, 0x3b, 0x11, 0xb2, 0x21, 0x88, 0x28, + 0x80, 0x37, 0x09, 0x3e, 0xb2, 0x43, 0x60, 0x53, 0xe9, 0x4b, 0xcf, 0x44, + 0xdc, 0x3d, 0x70, 0x2c, 0x25, 0x2a, 0x8f, 0x22, 0x45, 0x10, 0xe1, 0x04, + 0x3b, 0x01, 0x6a, 0xf5, 0x82, 0xed, 0xc1, 0xec, 0xef, 0xdf, 0x2a, 0xd8, + 0xd4, 0xd1, 0x6e, 0xc7, 0x16, 0xc8, 0x26, 0xcb, 0x55, 0xbf, 0xa4, 0xbb, + 0x9c, 0xba, 0xe2, 0xb6, 0x78, 0xc3, 0xc7, 0xcc, 0xbf, 0xd4, 0xe4, 0xd8, + 0xc0, 0xd9, 0x63, 0xe1, 0x27, 0xe7, 0xd0, 0xeb, 0xa2, 0xf8, 0x8c, 0x02, + 0x0f, 0x08, 0xfd, 0x17, 0x98, 0x1d, 0x98, 0x1f, 0x84, 0x28, 0xff, 0x2a, + 0xca, 0x27, 0x50, 0x25, 0xbe, 0x21, 0xec, 0x1f, 0x4f, 0x25, 0xcf, 0x24, + 0x60, 0x20, 0x25, 0x1e, 0xee, 0x18, 0x6f, 0x13, 0x08, 0x12, 0xca, 0x0a, + 0xda, 0x05, 0x2b, 0x03, 0x37, 0xff, 0x33, 0xfe, 0xc9, 0xf3, 0x25, 0xed, + 0xb7, 0xe7, 0x1d, 0xe4, 0x66, 0xe7, 0xb9, 0xed, 0x3d, 0xf5, 0x6f, 0xf9, + 0xc8, 0xff, 0x99, 0x00, 0x81, 0x02, 0x6f, 0x08, 0x55, 0x0c, 0x71, 0x11, + 0x51, 0x15, 0x41, 0x14, 0xfd, 0x11, 0x24, 0x11, 0xb3, 0x10, 0x01, 0x10, + 0xaf, 0x10, 0x2a, 0x12, 0x9b, 0x0d, 0xb9, 0x0c, 0x16, 0x0a, 0xe3, 0x01, + 0xb3, 0xfa, 0xf0, 0xf0, 0x74, 0xea, 0x60, 0xe8, 0xae, 0xe7, 0xce, 0xe7, + 0x44, 0xe9, 0xa6, 0xe8, 0x50, 0xe6, 0x54, 0xe4, 0xd5, 0xe5, 0x38, 0xe5, + 0x57, 0xe3, 0x87, 0xe8, 0x20, 0xec, 0x87, 0xed, 0x0f, 0xf1, 0x7a, 0xf7, + 0x99, 0xfc, 0x28, 0x05, 0xc9, 0x0e, 0xe3, 0x11, 0x28, 0x19, 0x00, 0x1e, + 0x6a, 0x18, 0x2c, 0x17, 0x7e, 0x1c, 0x88, 0x1c, 0x90, 0x1c, 0xc7, 0x1e, + 0xa9, 0x1f, 0x76, 0x20, 0x82, 0x1c, 0xd6, 0x1a, 0xac, 0x1d, 0x8a, 0x1c, + 0x6a, 0x1e, 0x19, 0x18, 0xc8, 0x0a, 0x7e, 0x09, 0x33, 0x03, 0xaf, 0x00, + 0x02, 0x04, 0x1d, 0xf9, 0x05, 0xf6, 0x62, 0xf8, 0x6e, 0xf4, 0xa1, 0x00, + 0xa9, 0x09, 0xb9, 0x03, 0xcf, 0x06, 0xe7, 0xfd, 0x33, 0xf6, 0x11, 0x04, + 0x61, 0x07, 0x86, 0x0a, 0x44, 0x0e, 0xc5, 0x02, 0xb1, 0x0b, 0x5f, 0x1b, + 0x8f, 0x13, 0xae, 0x14, 0xd2, 0x14, 0x6c, 0x10, 0x33, 0x20, 0xb3, 0x25, + 0x0e, 0x23, 0x84, 0x27, 0xba, 0x1f, 0xee, 0x1f, 0xd5, 0x28, 0xe2, 0x2b, + 0xf5, 0x35, 0x8b, 0x3b, 0xe8, 0x37, 0x10, 0x36, 0x2a, 0x35, 0xce, 0x30, + 0x8b, 0x34, 0x04, 0x37, 0x3a, 0x2e, 0x52, 0x31, 0xc4, 0x31, 0x38, 0x2c, + 0x44, 0x2f, 0x33, 0x27, 0x54, 0x1e, 0xa7, 0x1c, 0x9d, 0x18, 0x00, 0x1c, + 0xb8, 0x19, 0xea, 0x0e, 0x60, 0x03, 0x22, 0xf4, 0x7d, 0xe5, 0xe4, 0xda, + 0x05, 0xdd, 0x92, 0xdd, 0xe5, 0xd9, 0x78, 0xdb, 0x41, 0xd7, 0x3a, 0xc8, + 0x07, 0xbf, 0x90, 0xbf, 0x4d, 0xbf, 0xa6, 0xc6, 0xc7, 0xcc, 0xf7, 0xcc, + 0x5c, 0xc4, 0x4f, 0xc0, 0x66, 0xc7, 0x62, 0xc8, 0x45, 0xd3, 0x1d, 0xdc, + 0x9b, 0xdb, 0x38, 0xe4, 0xf1, 0xf1, 0x32, 0xf7, 0xf9, 0xf9, 0x79, 0x02, + 0x5e, 0x01, 0x98, 0x08, 0x59, 0x1b, 0x2d, 0x26, 0xf0, 0x37, 0x43, 0x42, + 0x7e, 0x40, 0xac, 0x45, 0x19, 0x3f, 0x31, 0x36, 0x42, 0x39, 0x71, 0x35, + 0x60, 0x32, 0x39, 0x34, 0xe3, 0x2b, 0x6e, 0x27, 0x97, 0x25, 0xb1, 0x1b, + 0xc6, 0x19, 0xf7, 0x17, 0xbf, 0x15, 0x58, 0x1b, 0xb1, 0x21, 0x14, 0x1f, + 0xca, 0x1a, 0x20, 0x19, 0x64, 0x10, 0xcb, 0x10, 0x8a, 0x14, 0xcf, 0x17, + 0x8b, 0x21, 0x93, 0x23, 0x02, 0x1f, 0x6e, 0x1b, 0xa3, 0x1b, 0xe4, 0x1d, + 0xef, 0x1a, 0x1d, 0x15, 0xf8, 0x0f, 0xf3, 0x09, 0x63, 0x0a, 0x38, 0x08, + 0x67, 0xfe, 0x24, 0xf3, 0x22, 0xee, 0x8a, 0xef, 0x05, 0xed, 0xc9, 0xea, + 0x12, 0xe4, 0xbd, 0xdc, 0xa9, 0xd6, 0xdf, 0xd2, 0x5b, 0xd3, 0x0e, 0xd6, + 0x57, 0xdd, 0xb5, 0xe0, 0x6d, 0xe6, 0x72, 0xeb, 0xec, 0xee, 0x7e, 0xf6, + 0x78, 0xf8, 0xa9, 0xfe, 0xde, 0x08, 0x97, 0x0d, 0xa3, 0x15, 0x28, 0x19, + 0x02, 0x20, 0xe9, 0x2d, 0x4c, 0x31, 0xcc, 0x38, 0x26, 0x47, 0xf5, 0x52, + 0xa6, 0x56, 0x92, 0x53, 0xa4, 0x4d, 0x44, 0x4a, 0xa0, 0x4c, 0x97, 0x49, + 0x9a, 0x44, 0x87, 0x38, 0xc3, 0x2c, 0x37, 0x27, 0x90, 0x1d, 0x45, 0x16, + 0xcf, 0x10, 0xb1, 0x07, 0x6c, 0x05, 0x4a, 0x0a, 0xc3, 0x01, 0x4e, 0x01, + 0xb6, 0x03, 0x5d, 0xf5, 0x15, 0xf6, 0x2a, 0xf5, 0xa2, 0xec, 0xcf, 0xf1, + 0xbb, 0xec, 0xec, 0xe0, 0x8f, 0xe7, 0x59, 0xf1, 0x12, 0xf3, 0xab, 0xfb, + 0x3d, 0xf4, 0x36, 0xe6, 0x0d, 0xfd, 0x90, 0x06, 0xea, 0x05, 0x68, 0x14, + 0xc1, 0x04, 0x89, 0x01, 0x24, 0x0b, 0xe2, 0x02, 0x7c, 0x10, 0x50, 0x18, + 0xe6, 0x10, 0xfc, 0x13, 0x1f, 0x0d, 0x1b, 0x0a, 0x1d, 0x19, 0xdc, 0x19, + 0x62, 0x0f, 0x48, 0x0d, 0x95, 0x05, 0x1b, 0x04, 0x47, 0x0d, 0xf3, 0x01, + 0x0e, 0xf6, 0x92, 0xfd, 0xba, 0xf2, 0x53, 0xe8, 0x95, 0xf4, 0x62, 0xec, + 0xc4, 0xf1, 0xf3, 0x07, 0xbe, 0xfd, 0x22, 0xfe, 0x13, 0x03, 0x3c, 0xf9, + 0xeb, 0x07, 0x82, 0x1a, 0x37, 0x1d, 0x1d, 0x28, 0xe7, 0x20, 0x4c, 0x06, + 0x13, 0x03, 0xeb, 0xfe, 0x8c, 0xfc, 0xef, 0x0e, 0xa7, 0x10, 0xfa, 0x0d, + 0x9c, 0x0e, 0xe5, 0xfe, 0xd3, 0x02, 0xe8, 0x07, 0xbc, 0xfb, 0x11, 0x07, + 0x72, 0x09, 0x06, 0xfc, 0x7f, 0xfd, 0xfd, 0xf9, 0x2d, 0xf1, 0x3e, 0xf2, + 0x4d, 0xf3, 0x2e, 0xf3, 0x92, 0xf5, 0x49, 0xf9, 0x95, 0x05, 0xa8, 0x05, + 0xd4, 0x00, 0x14, 0x03, 0x80, 0xfa, 0x87, 0xfc, 0xdb, 0x05, 0xf1, 0x04, + 0xfd, 0x08, 0x60, 0x0c, 0x53, 0x07, 0x9c, 0x08, 0xd7, 0x04, 0x72, 0xf8, + 0xb8, 0xf9, 0x6e, 0xfd, 0x21, 0xfd, 0x0a, 0xfe, 0x5b, 0xf9, 0x8a, 0xf4, + 0xf2, 0xf0, 0x36, 0xf1, 0xf7, 0xf5, 0x9b, 0xee, 0x1b, 0xe8, 0xc2, 0xe8, + 0x03, 0xe2, 0x9c, 0xde, 0x9b, 0xdb, 0xf5, 0xd4, 0x71, 0xcf, 0xec, 0xc6, + 0x2c, 0xbe, 0x11, 0xbc, 0x9b, 0xbd, 0x93, 0xbe, 0x98, 0xc2, 0x56, 0xbf, + 0xd7, 0xba, 0x77, 0xba, 0x4c, 0xbc, 0xdc, 0xc3, 0x68, 0xc3, 0x4d, 0xc4, + 0x74, 0xc8, 0xec, 0xc7, 0x05, 0xce, 0x95, 0xd7, 0x5c, 0xda, 0x2e, 0xdc, + 0x84, 0xe2, 0x0f, 0xe9, 0x43, 0xf4, 0x48, 0xfd, 0x4e, 0x06, 0xff, 0x13, + 0x5f, 0x1e, 0x01, 0x2a, 0x03, 0x33, 0x53, 0x38, 0x64, 0x3f, 0xcb, 0x4b, + 0xa2, 0x58, 0x56, 0x5a, 0x59, 0x57, 0xe8, 0x54, 0xee, 0x4e, 0x4f, 0x51, + 0xa4, 0x5c, 0xb0, 0x61, 0x89, 0x64, 0xd3, 0x60, 0x0f, 0x55, 0x7a, 0x4c, + 0x2e, 0x4a, 0xe6, 0x4d, 0x2f, 0x4d, 0x2e, 0x42, 0x2c, 0x33, 0xb9, 0x21, + 0x56, 0x17, 0xff, 0x19, 0x5c, 0x1c, 0x8f, 0x22, 0xb3, 0x24, 0xf7, 0x18, + 0xda, 0x11, 0xbc, 0x0e, 0x93, 0x0e, 0x4a, 0x10, 0xc9, 0x0d, 0xda, 0x05, + 0x01, 0x00, 0xeb, 0x04, 0x7c, 0x05, 0xb3, 0x07, 0x2c, 0x0e, 0xf9, 0x0a, + 0x84, 0x0a, 0xf8, 0x0c, 0x52, 0x0c, 0x4e, 0x11, 0xa3, 0x19, 0x8e, 0x1c, + 0x7c, 0x21, 0x74, 0x21, 0x9d, 0x18, 0x57, 0x21, 0x28, 0x29, 0xdf, 0x29, + 0x00, 0x34, 0xb6, 0x32, 0x06, 0x32, 0x51, 0x37, 0x59, 0x37, 0xd0, 0x3c, + 0x81, 0x43, 0x84, 0x45, 0xc7, 0x48, 0x96, 0x42, 0x97, 0x32, 0x84, 0x2f, + 0x44, 0x2d, 0xc7, 0x2c, 0xa2, 0x32, 0x06, 0x2d, 0x04, 0x29, 0x49, 0x1e, + 0x2c, 0x10, 0x0b, 0x15, 0x30, 0x18, 0x76, 0x13, 0xac, 0x14, 0x64, 0x14, + 0x11, 0x17, 0xca, 0x27, 0xf9, 0x30, 0xb2, 0x32, 0xb2, 0x3a, 0x9e, 0x38, + 0xfe, 0x38, 0x16, 0x40, 0xe6, 0x39, 0x4d, 0x3a, 0x42, 0x3c, 0x8c, 0x32, + 0x53, 0x2e, 0xcc, 0x23, 0xff, 0x1c, 0xd8, 0x26, 0x1f, 0x25, 0x20, 0x23, + 0x6c, 0x28, 0x5f, 0x15, 0xc2, 0x05, 0x06, 0x08, 0x94, 0xfa, 0x93, 0xf8, + 0x43, 0xfd, 0xcd, 0xed, 0x2b, 0xe5, 0x92, 0xe0, 0x72, 0xdb, 0xa1, 0xde, + 0x8f, 0xe2, 0x00, 0xe4, 0x22, 0xe7, 0x15, 0xec, 0x0d, 0xf2, 0x24, 0xfd, + 0x28, 0x02, 0xa1, 0x06, 0xf6, 0x0f, 0xf5, 0x0e, 0x93, 0x13, 0x06, 0x1b, + 0x15, 0x21, 0x15, 0x34, 0x5e, 0x38, 0x27, 0x31, 0xb1, 0x30, 0x78, 0x2e, + 0x12, 0x32, 0x7a, 0x35, 0xd0, 0x33, 0x7f, 0x30, 0xe0, 0x29, 0x15, 0x24, + 0x64, 0x20, 0x62, 0x1a, 0x13, 0x11, 0x11, 0x0b, 0x75, 0x05, 0x38, 0xfc, + 0x11, 0xf2, 0x5b, 0xe9, 0x0b, 0xe4, 0x10, 0xe0, 0xc5, 0xde, 0x67, 0xdd, + 0xa3, 0xd6, 0x9a, 0xd1, 0xfb, 0xd2, 0x1a, 0xd7, 0x1c, 0xdb, 0xce, 0xde, + 0xd6, 0xdf, 0x73, 0xda, 0x1b, 0xd9, 0x78, 0xe0, 0xc5, 0xe7, 0xbc, 0xee, + 0x0b, 0xf9, 0xeb, 0x03, 0x61, 0x0b, 0xd1, 0x11, 0x17, 0x16, 0x0b, 0x19, + 0xe6, 0x1a, 0x04, 0x19, 0x1d, 0x1b, 0x86, 0x1e, 0xfd, 0x1b, 0xd5, 0x1b, + 0x6a, 0x16, 0x46, 0x0e, 0xac, 0x12, 0x96, 0x13, 0x71, 0x17, 0x9d, 0x1c, + 0x03, 0x15, 0x0a, 0x12, 0x07, 0x0f, 0xf8, 0x0b, 0x8d, 0x11, 0xed, 0x0e, + 0x8a, 0x06, 0xbe, 0x03, 0x33, 0xfd, 0x38, 0xf6, 0x98, 0xf4, 0x64, 0xf2, + 0x43, 0xf2, 0xaa, 0xf3, 0xe2, 0xef, 0xad, 0xeb, 0x4e, 0xee, 0xcd, 0xef, + 0x4f, 0xf4, 0x36, 0xfc, 0x63, 0xf9, 0x99, 0xf7, 0xea, 0xfa, 0xbe, 0xf5, + 0x6d, 0xf3, 0x81, 0xf3, 0x52, 0xec, 0x1b, 0xed, 0x3d, 0xf0, 0x06, 0xef, + 0xda, 0xf5, 0x2f, 0xfc, 0xa4, 0xfa, 0xa3, 0xfd, 0xf3, 0xfa, 0x37, 0xf3, + 0xc5, 0xfe, 0x2a, 0x09, 0xbe, 0x0c, 0xda, 0x14, 0x7a, 0x13, 0x51, 0x10, + 0xb6, 0x17, 0x47, 0x20, 0x68, 0x1f, 0xb0, 0x1e, 0xcb, 0x22, 0xcf, 0x26, + 0x7f, 0x2e, 0xc1, 0x31, 0x22, 0x2e, 0x52, 0x2d, 0x44, 0x28, 0x0f, 0x22, + 0x7d, 0x1a, 0xc7, 0x0b, 0xeb, 0x08, 0x63, 0x10, 0x3f, 0x10, 0xfe, 0x03, + 0x3b, 0xfa, 0x15, 0xf2, 0xba, 0xec, 0x7a, 0xf8, 0xaf, 0xf5, 0xe4, 0xe8, + 0x9b, 0xe3, 0x1c, 0xd9, 0x20, 0xda, 0xeb, 0xe0, 0x6c, 0xdb, 0xdc, 0xda, + 0xab, 0xe4, 0x4d, 0xee, 0x73, 0xf8, 0x1b, 0xfe, 0x2a, 0x02, 0xde, 0x00, + 0x01, 0xfd, 0xd1, 0x01, 0x09, 0x04, 0x83, 0x05, 0x21, 0x05, 0x89, 0xfe, + 0xf9, 0xf8, 0xec, 0xf8, 0xaa, 0xf7, 0xaf, 0xf1, 0x1c, 0xed, 0xee, 0xe6, + 0x78, 0xe3, 0x6c, 0xdf, 0xa2, 0xd4, 0xbd, 0xcc, 0x3d, 0xc5, 0xd0, 0xbf, + 0x99, 0xc4, 0xcc, 0xc3, 0x58, 0xbe, 0x3b, 0xbd, 0xa1, 0xbc, 0x6f, 0xbc, + 0xfe, 0xbd, 0xf8, 0xc6, 0x0d, 0xd3, 0x80, 0xdf, 0x4d, 0xe7, 0x0e, 0xeb, + 0x27, 0xee, 0x54, 0xf8, 0x63, 0x0a, 0x97, 0x15, 0x25, 0x1a, 0x84, 0x15, + 0xa0, 0x17, 0x57, 0x1c, 0xbd, 0x1c, 0x54, 0x20, 0x9d, 0x17, 0xbe, 0x0b, + 0xd3, 0x05, 0x03, 0x01, 0xa6, 0xf8, 0x29, 0xf1, 0x3b, 0xe9, 0x49, 0xdf, + 0xbe, 0xd7, 0x27, 0xcf, 0x24, 0xc6, 0x1f, 0xba, 0xc4, 0xaf, 0x32, 0xab, + 0x41, 0xaa, 0x62, 0xa8, 0xcd, 0xa8, 0x00, 0xab, 0x3c, 0xa9, 0x0e, 0xab, + 0x0f, 0xb2, 0xcd, 0xba, 0x3b, 0xc3, 0xc9, 0xca, 0xcd, 0xd1, 0x37, 0xd7, + 0x42, 0xdc, 0xb2, 0xe4, 0x39, 0xea, 0x58, 0xf0, 0xc1, 0xf9, 0x08, 0x00, + 0xc4, 0x06, 0x6e, 0x0c, 0xaf, 0x0f, 0xf5, 0x0c, 0xc9, 0x0b, 0x48, 0x08, + 0xc6, 0x04, 0x4e, 0x09, 0xff, 0x06, 0x86, 0x02, 0xba, 0xfd, 0xe1, 0xfa, + 0xe3, 0xf6, 0x5c, 0xf3, 0x3b, 0xf4, 0x89, 0xf1, 0xf5, 0xf3, 0x9a, 0xf6, + 0x12, 0xf4, 0x71, 0xf1, 0x7f, 0xef, 0x10, 0xef, 0x67, 0xed, 0xdd, 0xe8, + 0x7b, 0xe4, 0x84, 0xe3, 0x8d, 0xe7, 0x4f, 0xe9, 0x83, 0xe9, 0x87, 0xee, + 0xb6, 0xf2, 0x28, 0xfc, 0xe7, 0x02, 0x3a, 0x02, 0x8b, 0x03, 0xa3, 0xfe, + 0x8f, 0xf7, 0x98, 0xf3, 0xf8, 0xee, 0xd7, 0xee, 0xb2, 0xef, 0x4f, 0xee, + 0x28, 0xee, 0xaa, 0xe8, 0x09, 0xe7, 0x35, 0xea, 0x49, 0xe9, 0x45, 0xec, + 0x7d, 0xeb, 0x6b, 0xe9, 0xf8, 0xe7, 0x08, 0xe3, 0x43, 0xe7, 0x2f, 0xef, + 0x06, 0xf5, 0x47, 0xff, 0xd2, 0x03, 0xde, 0xff, 0xc1, 0xff, 0x00, 0x06, + 0xab, 0x10, 0x60, 0x1d, 0xff, 0x21, 0x20, 0x15, 0x1f, 0x08, 0x1c, 0x06, + 0x89, 0x07, 0x48, 0x0f, 0xe5, 0x0e, 0x42, 0xff, 0xfb, 0xf1, 0xf6, 0xe7, + 0xc1, 0xe4, 0x6d, 0xf0, 0x1c, 0xf4, 0x3a, 0xeb, 0x2d, 0xe5, 0xe5, 0xda, + 0xd7, 0xd3, 0x02, 0xde, 0x38, 0xe3, 0x66, 0xe2, 0x85, 0xe5, 0xdc, 0xd8, + 0x81, 0xd8, 0xa0, 0xe5, 0xc1, 0xe7, 0x12, 0xf5, 0x76, 0x00, 0x8d, 0xfb, + 0x0f, 0xfa, 0xc7, 0x06, 0x45, 0x13, 0xb7, 0x22, 0xb1, 0x2f, 0xaf, 0x28, + 0xca, 0x28, 0x4f, 0x31, 0x43, 0x36, 0x22, 0x3d, 0x83, 0x32, 0xff, 0x1b, + 0x7b, 0x12, 0x9e, 0x0a, 0x0c, 0x0c, 0xaf, 0x13, 0x3e, 0x04, 0xbc, 0xf6, + 0x91, 0xf4, 0x53, 0xe7, 0x4e, 0xe7, 0xfa, 0xf4, 0x49, 0xef, 0x52, 0xee, + 0x17, 0xf0, 0x18, 0xe2, 0x04, 0xe1, 0x42, 0xe2, 0x35, 0xde, 0x28, 0xea, + 0x20, 0xf2, 0x6e, 0xf4, 0xc9, 0x02, 0x7c, 0x06, 0x7e, 0x06, 0x19, 0x0d, + 0x90, 0x0a, 0xa6, 0x0c, 0xce, 0x12, 0x1d, 0x10, 0xf8, 0x11, 0x45, 0x16, + 0xee, 0x11, 0xc0, 0x0f, 0x24, 0x0d, 0x21, 0x06, 0x6c, 0xfd, 0xa1, 0xf4, + 0x82, 0xed, 0x05, 0xe9, 0x47, 0xe7, 0x03, 0xe2, 0xea, 0xda, 0xcc, 0xd1, + 0xdc, 0xcf, 0x15, 0xd3, 0x00, 0xd6, 0xa1, 0xda, 0x3d, 0xda, 0x40, 0xde, + 0xd7, 0xe0, 0x52, 0xe0, 0x55, 0xe5, 0xc0, 0xe6, 0x90, 0xec, 0x43, 0xf5, + 0x1c, 0xf7, 0x94, 0x02, 0xf7, 0x0f, 0x86, 0x18, 0xf7, 0x22, 0xa1, 0x25, + 0x64, 0x24, 0x5a, 0x24, 0x0c, 0x27, 0x95, 0x2d, 0x50, 0x35, 0xb6, 0x38, + 0xe0, 0x34, 0x0f, 0x26, 0x50, 0x19, 0x92, 0x17, 0xf7, 0x14, 0xe3, 0x17, + 0x07, 0x11, 0x96, 0x03, 0x3c, 0x00, 0xde, 0xfa, 0xbd, 0xf7, 0x75, 0xf9, + 0xa8, 0xfa, 0xf6, 0xfa, 0x3f, 0xfe, 0xc8, 0xfd, 0xf1, 0xfe, 0x35, 0x06, + 0xc1, 0x03, 0xf7, 0x03, 0x6c, 0x02, 0xc3, 0xf7, 0x42, 0xfa, 0xe1, 0xf6, + 0x41, 0xf1, 0xd8, 0xfd, 0xd2, 0xfa, 0x62, 0xfa, 0x78, 0x08, 0x89, 0x05, + 0x69, 0x09, 0xb9, 0x0d, 0xc2, 0x02, 0xe4, 0xfe, 0xef, 0xf7, 0x5a, 0xf0, + 0x26, 0xf0, 0x75, 0xe7, 0x61, 0xdc, 0xb0, 0xd9, 0xab, 0xd9, 0x4e, 0xde, + 0x04, 0xe6, 0xd0, 0xe2, 0xf4, 0xe2, 0x7b, 0xe8, 0x37, 0xed, 0xa8, 0xfc, + 0xe2, 0x00, 0xd6, 0xff, 0x5b, 0x08, 0xd5, 0x09, 0xb8, 0x12, 0xce, 0x23, + 0x05, 0x23, 0x37, 0x26, 0xbe, 0x2e, 0x5f, 0x20, 0x63, 0x1d, 0x5f, 0x20, + 0x7d, 0x1b, 0x53, 0x22, 0x3d, 0x18, 0xe3, 0x0d, 0xdd, 0x13, 0x88, 0x0b, + 0xc0, 0x04, 0x1e, 0x05, 0x0f, 0xf6, 0x38, 0xf0, 0x71, 0xf6, 0xce, 0xed, + 0x10, 0xee, 0x33, 0xef, 0x18, 0xdf, 0x34, 0xe0, 0x16, 0xe4, 0x98, 0xd8, + 0xc5, 0xe3, 0x98, 0xf2, 0x9e, 0xed, 0x25, 0xfb, 0xd3, 0x07, 0xcf, 0x04, + 0xd2, 0x13, 0x74, 0x20, 0x73, 0x20, 0x8d, 0x2e, 0x7d, 0x3a, 0xfb, 0x3a, + 0x86, 0x44, 0x5d, 0x4b, 0xfb, 0x49, 0x60, 0x4f, 0x51, 0x52, 0xa0, 0x4d, + 0xb2, 0x47, 0xc1, 0x38, 0xc7, 0x2a, 0xaa, 0x23, 0xfe, 0x13, 0x8e, 0x07, + 0xc6, 0x01, 0x9d, 0xf6, 0xbd, 0xed, 0x48, 0xe9, 0xb9, 0xe1, 0xc3, 0xdd, + 0xb7, 0xdf, 0x6f, 0xd7, 0x46, 0xd0, 0x65, 0xd3, 0xc9, 0xcc, 0xed, 0xc5, + 0xdd, 0xc5, 0x08, 0xc2, 0x13, 0xc8, 0xe2, 0xd5, 0xab, 0xd8, 0xe5, 0xdb, + 0x04, 0xea, 0xbf, 0xee, 0x50, 0xf3, 0xce, 0xff, 0xd9, 0x00, 0x3c, 0x03, + 0xba, 0x06, 0xc6, 0x06, 0xfd, 0x06, 0x29, 0x05, 0x3f, 0x0a, 0xf5, 0x0e, + 0x88, 0x0a, 0x02, 0x03, 0xf9, 0xfc, 0xe5, 0xf2, 0x21, 0xf0, 0x26, 0xf8, + 0xe4, 0xfb, 0x58, 0xfd, 0x2c, 0xf8, 0xd9, 0xf0, 0x31, 0xee, 0x50, 0xea, + 0xe4, 0xe9, 0x78, 0xf0, 0x0a, 0xf6, 0x3d, 0xfb, 0xea, 0x01, 0xb7, 0x02, + 0xb6, 0x01, 0xcf, 0x04, 0x83, 0x09, 0x2e, 0x14, 0x4e, 0x1f, 0xe5, 0x23, + 0x51, 0x2a, 0x5f, 0x2a, 0x0a, 0x26, 0x8e, 0x24, 0x48, 0x20, 0xd9, 0x1c, + 0x35, 0x18, 0x0c, 0x16, 0xb0, 0x1a, 0x1c, 0x1b, 0x34, 0x15, 0x37, 0x13, + 0x4b, 0x10, 0xc6, 0x0a, 0xfc, 0x09, 0x86, 0x07, 0xbb, 0x04, 0x79, 0x04, + 0xc2, 0x01, 0xb1, 0xfc, 0x62, 0xf8, 0xca, 0xfa, 0x3c, 0x05, 0x71, 0x0c, + 0x99, 0x13, 0x25, 0x1b, 0xd1, 0x16, 0x3c, 0x15, 0xc1, 0x13, 0x8e, 0x0d, + 0x5b, 0x0f, 0xb0, 0x04, 0xb6, 0xfa, 0x37, 0x01, 0x4e, 0xff, 0x58, 0x04, + 0xd8, 0x07, 0x0b, 0xff, 0x4f, 0x07, 0x8b, 0x0c, 0x94, 0x0b, 0x6c, 0x0f, + 0xb5, 0x05, 0x4b, 0xff, 0x94, 0xfe, 0xf8, 0xf9, 0x2f, 0x00, 0xd4, 0x05, + 0x18, 0x00, 0x98, 0xfb, 0x1a, 0xfb, 0x61, 0xf9, 0x87, 0xff, 0x04, 0x07, + 0x77, 0x04, 0xc0, 0x0c, 0x96, 0x11, 0x79, 0x11, 0x14, 0x1d, 0x28, 0x20, + 0xff, 0x28, 0x46, 0x31, 0x4f, 0x29, 0x73, 0x20, 0xb4, 0x11, 0xaa, 0x0e, + 0xbc, 0x12, 0x97, 0x0c, 0x3d, 0x0e, 0xab, 0x04, 0xe1, 0xf8, 0x19, 0xff, + 0xef, 0xf8, 0xc5, 0xf8, 0x97, 0xff, 0xea, 0xf1, 0xa6, 0xeb, 0xc3, 0xee, + 0xd4, 0xea, 0x41, 0xe7, 0xb9, 0xe5, 0x5a, 0xe3, 0x25, 0xe4, 0x2a, 0xed, + 0x19, 0xf2, 0x6b, 0xf4, 0xb2, 0xf4, 0x96, 0xef, 0xb0, 0xfa, 0xcf, 0x05, + 0x66, 0x0d, 0x9a, 0x1f, 0x67, 0x20, 0x96, 0x26, 0xd3, 0x39, 0x8a, 0x3a, + 0x14, 0x45, 0xff, 0x4e, 0xb0, 0x47, 0xb4, 0x4d, 0x31, 0x50, 0x46, 0x49, + 0x7c, 0x47, 0x46, 0x40, 0x04, 0x3a, 0x3d, 0x3a, 0xb0, 0x32, 0xac, 0x25, + 0x14, 0x18, 0x30, 0x05, 0xf9, 0xfa, 0xb3, 0xf6, 0x2b, 0xed, 0xc3, 0xe7, + 0x8c, 0xdd, 0x29, 0xcd, 0x86, 0xcb, 0x44, 0xcc, 0x33, 0xc7, 0xf7, 0xcc, + 0x04, 0xcc, 0xfc, 0xc4, 0x6f, 0xc7, 0xe4, 0xc1, 0x96, 0xbf, 0x2b, 0xc7, + 0xb4, 0xc8, 0xe2, 0xcc, 0x24, 0xd4, 0x7d, 0xd5, 0x9c, 0xde, 0xfe, 0xec, + 0x13, 0xed, 0x24, 0xec, 0xb8, 0xf0, 0xbb, 0xf3, 0x33, 0xfc, 0x92, 0x08, + 0x5e, 0x0c, 0x62, 0x07, 0x2d, 0x05, 0x0f, 0x02, 0x07, 0xfd, 0x00, 0xfd, + 0xa8, 0xfb, 0x8a, 0xf8, 0xaf, 0xfa, 0xa3, 0xfb, 0x7a, 0xf7, 0x15, 0xf3, + 0xd5, 0xed, 0x26, 0xee, 0x8b, 0xf3, 0x6a, 0xf3, 0x0b, 0xf3, 0x28, 0xf6, + 0xcd, 0xf3, 0x43, 0xf2, 0xa7, 0xf5, 0x0a, 0xf5, 0xaf, 0xf3, 0x52, 0xf3, + 0xa3, 0xef, 0xf2, 0xee, 0xeb, 0xf1, 0x0e, 0xf1, 0xd3, 0xf3, 0xc2, 0xf2, + 0x35, 0xf0, 0x59, 0xf2, 0x94, 0xe9, 0x0c, 0xe6, 0x40, 0xeb, 0xeb, 0xea, + 0x9e, 0xec, 0xaa, 0xee, 0x7e, 0xe6, 0x24, 0xe0, 0x4c, 0xe2, 0x2f, 0xe4, + 0x0a, 0xed, 0x65, 0xef, 0x78, 0xe7, 0x21, 0xe6, 0xb7, 0xe3, 0x68, 0xe4, + 0x0a, 0xee, 0x75, 0xef, 0xad, 0xf5, 0x45, 0x02, 0x89, 0x01, 0xa4, 0x05, + 0xd5, 0x09, 0x22, 0x09, 0xa0, 0x0e, 0xe6, 0x0d, 0x1e, 0x09, 0x08, 0x05, + 0x0f, 0xfd, 0x83, 0xf8, 0x48, 0xfb, 0xdf, 0xfa, 0x30, 0xfc, 0x47, 0x04, + 0x89, 0x05, 0xbc, 0x05, 0xe5, 0x09, 0x60, 0x06, 0xa7, 0x06, 0xb4, 0x0a, + 0x41, 0x08, 0xcf, 0x08, 0x08, 0x07, 0x1f, 0x04, 0x6b, 0x0a, 0x55, 0x11, + 0x87, 0x13, 0x91, 0x15, 0xa9, 0x14, 0x5d, 0x18, 0xa0, 0x22, 0x88, 0x28, + 0x44, 0x27, 0x24, 0x1d, 0xa5, 0x15, 0x86, 0x12, 0x6e, 0x0d, 0x5b, 0x0a, + 0x65, 0x08, 0x13, 0x04, 0x30, 0xfd, 0x96, 0xfd, 0x32, 0xfa, 0x17, 0xee, + 0x36, 0xf0, 0x29, 0xf3, 0xec, 0xf4, 0xf9, 0x02, 0xc0, 0x06, 0xcb, 0x05, + 0x89, 0x08, 0x45, 0x09, 0xcf, 0x0c, 0x3a, 0x0d, 0xce, 0x0a, 0xd6, 0x0d, + 0xf8, 0x1a, 0x7b, 0x2a, 0x0e, 0x34, 0x1f, 0x37, 0xa1, 0x37, 0x24, 0x37, + 0x7b, 0x38, 0x5f, 0x46, 0xcd, 0x55, 0x39, 0x59, 0x7b, 0x5e, 0xa8, 0x66, + 0x0d, 0x64, 0xec, 0x63, 0x96, 0x68, 0x67, 0x65, 0xc2, 0x66, 0x7b, 0x6d, + 0x50, 0x6b, 0x5b, 0x67, 0xdd, 0x62, 0x10, 0x59, 0x85, 0x54, 0xd7, 0x4e, + 0x04, 0x44, 0xc3, 0x3b, 0x9a, 0x32, 0xf9, 0x23, 0x7c, 0x18, 0x71, 0x0d, + 0x47, 0xfc, 0x01, 0xf5, 0x18, 0xf0, 0xa8, 0xe6, 0xc6, 0xdf, 0xfd, 0xd8, + 0x16, 0xd6, 0x87, 0xda, 0x64, 0xdd, 0x5c, 0xd9, 0x18, 0xd9, 0xc6, 0xd5, + 0x24, 0xd0, 0x0b, 0xd8, 0xbb, 0xe0, 0xde, 0xe4, 0x4b, 0xee, 0xde, 0xf2, + 0x7b, 0xf6, 0x8a, 0x02, 0x4b, 0x0d, 0xb1, 0x17, 0x27, 0x1f, 0x62, 0x23, + 0x34, 0x29, 0xfe, 0x2f, 0x6d, 0x33, 0x87, 0x35, 0xc5, 0x39, 0x21, 0x37, + 0x96, 0x35, 0xf8, 0x38, 0x0a, 0x34, 0xbb, 0x2f, 0x57, 0x30, 0x99, 0x28, + 0xdc, 0x24, 0xe7, 0x24, 0x9d, 0x1d, 0x5b, 0x1a, 0x37, 0x15, 0x90, 0x0d, + 0x60, 0x0b, 0x85, 0x0b, 0xef, 0x07, 0xe5, 0x03, 0x46, 0x04, 0x76, 0x02, + 0xee, 0xff, 0xf7, 0xfe, 0xd4, 0xfd, 0xa0, 0xfe, 0x0f, 0x02, 0x11, 0x04, + 0xd9, 0x07, 0xca, 0x09, 0xd4, 0x06, 0x2d, 0x06, 0x0d, 0x03, 0x88, 0x00, + 0x0a, 0x03, 0x62, 0x05, 0xd0, 0x05, 0x60, 0x09, 0xe2, 0x09, 0x5d, 0x06, + 0xa0, 0x07, 0x80, 0x02, 0xc7, 0xfc, 0xf6, 0xfd, 0xf6, 0xfa, 0x9f, 0xfa, + 0x6a, 0xfe, 0xb4, 0xfb, 0x56, 0xfe, 0x0e, 0xff, 0xbb, 0xfa, 0x95, 0x05, + 0xaf, 0x0d, 0xbc, 0x14, 0x9d, 0x1e, 0xd9, 0x18, 0xe0, 0x13, 0x9b, 0x17, + 0xa3, 0x18, 0x44, 0x1d, 0xbc, 0x1d, 0xd2, 0x11, 0x30, 0x0a, 0x27, 0x08, + 0x3e, 0x0b, 0x93, 0x12, 0x29, 0x14, 0x95, 0x12, 0x5a, 0x14, 0xf9, 0x13, + 0xde, 0x14, 0x4c, 0x18, 0x7d, 0x11, 0x94, 0x0f, 0x84, 0x0f, 0xda, 0x08, + 0x3a, 0x09, 0x49, 0x08, 0x5e, 0x06, 0x2a, 0x0c, 0x83, 0x0c, 0xef, 0x03, + 0x70, 0xfd, 0x0b, 0xf6, 0x6c, 0xee, 0x1b, 0xea, 0xf1, 0xec, 0x6d, 0xed, + 0xbc, 0xe5, 0x20, 0xe3, 0xfd, 0xdd, 0x61, 0xdd, 0x2d, 0xe4, 0x26, 0xe2, + 0x15, 0xe4, 0xa1, 0xe8, 0x25, 0xe4, 0x34, 0xe7, 0xfc, 0xea, 0x60, 0xea, + 0xd6, 0xf2, 0x10, 0xf7, 0xe8, 0xf9, 0xde, 0x0a, 0x1d, 0x16, 0xb8, 0x13, + 0x16, 0x1b, 0x39, 0x1b, 0x2f, 0x18, 0x61, 0x2b, 0xa8, 0x33, 0xe6, 0x35, + 0xf7, 0x3d, 0x33, 0x36, 0x71, 0x36, 0xd6, 0x3d, 0x72, 0x38, 0xad, 0x3b, + 0xf6, 0x39, 0x76, 0x37, 0x97, 0x41, 0x03, 0x3c, 0x75, 0x38, 0x91, 0x37, + 0x4b, 0x2d, 0x17, 0x2e, 0xa6, 0x31, 0xeb, 0x2a, 0x97, 0x25, 0xe0, 0x1d, + 0x2e, 0x0e, 0x8c, 0x0a, 0xaf, 0x05, 0xf3, 0xf4, 0xa9, 0xed, 0x3a, 0xea, + 0x8e, 0xe2, 0xc0, 0xdf, 0xf1, 0xdd, 0x23, 0xd4, 0x94, 0xc8, 0x48, 0xc4, + 0x12, 0xbf, 0x2b, 0xb4, 0x3b, 0xb6, 0x00, 0xb8, 0x59, 0xb0, 0x7e, 0xb9, + 0x6d, 0xbf, 0x5b, 0xb7, 0xed, 0xb9, 0x8e, 0xba, 0x5c, 0xb7, 0xcc, 0xc1, + 0xb3, 0xcf, 0x42, 0xd7, 0x1a, 0xdf, 0xd1, 0xe9, 0x3a, 0xea, 0x8e, 0xee, + 0x20, 0xff, 0x43, 0x07, 0xb0, 0x13, 0x83, 0x21, 0xa8, 0x24, 0xa8, 0x28, + 0xb1, 0x28, 0xb5, 0x29, 0xfb, 0x2a, 0xba, 0x23, 0x81, 0x22, 0x27, 0x20, + 0xcd, 0x1c, 0xcc, 0x20, 0x92, 0x1b, 0xe7, 0x14, 0xd7, 0x10, 0x54, 0x09, + 0xae, 0x01, 0x26, 0xfb, 0x02, 0xf6, 0xbd, 0xf0, 0x6e, 0xed, 0x5d, 0xe7, + 0x91, 0xdf, 0xde, 0xd8, 0x45, 0xd2, 0xb3, 0xcf, 0x05, 0xd3, 0x52, 0xd7, + 0x66, 0xd9, 0x14, 0xdd, 0xee, 0xde, 0x67, 0xde, 0x8a, 0xde, 0x39, 0xdf, + 0x6c, 0xdd, 0xd5, 0xdf, 0xdd, 0xe3, 0xd2, 0xe0, 0x2e, 0xe1, 0xe7, 0xe1, + 0x0b, 0xe6, 0x09, 0xeb, 0x46, 0xe9, 0x00, 0xed, 0xa9, 0xeb, 0x02, 0xe8, + 0xaf, 0xeb, 0x49, 0xe5, 0x2e, 0xde, 0x59, 0xdc, 0x70, 0xdb, 0xd2, 0xe3, + 0xaa, 0xe8, 0xfd, 0xec, 0x2a, 0xf1, 0xf0, 0xef, 0x56, 0xfa, 0x6b, 0x04, + 0x92, 0x0b, 0xaa, 0x12, 0xbe, 0x10, 0x7a, 0x0f, 0x34, 0x0e, 0x9d, 0x0c, + 0x70, 0x0c, 0xf7, 0x0c, 0xa9, 0x10, 0x20, 0x0f, 0xcd, 0x12, 0xa6, 0x18, + 0x7e, 0x11, 0x87, 0x12, 0x87, 0x15, 0x33, 0x10, 0xc3, 0x11, 0xf9, 0x13, + 0xb1, 0x10, 0x12, 0x0a, 0x81, 0xfe, 0x3d, 0xee, 0xc9, 0xe3, 0xe9, 0xdc, + 0x1d, 0xcf, 0x71, 0xc9, 0x9c, 0xc5, 0x71, 0xb9, 0x67, 0xbc, 0x3b, 0xc0, + 0x16, 0xbc, 0x56, 0xc0, 0x39, 0xbc, 0xef, 0xbc, 0xa4, 0xca, 0xb7, 0xcc, + 0x80, 0xd4, 0x31, 0xe2, 0xca, 0xda, 0x63, 0xda, 0xc3, 0xe3, 0x32, 0xdd, + 0x27, 0xe6, 0x1c, 0xf7, 0x37, 0xf8, 0x64, 0x06, 0x4f, 0x17, 0x02, 0x19, + 0x94, 0x21, 0x41, 0x28, 0xcc, 0x2a, 0x08, 0x35, 0x64, 0x32, 0x18, 0x30, + 0x5a, 0x3a, 0xeb, 0x3b, 0x18, 0x3b, 0x75, 0x32, 0x32, 0x1f, 0x1c, 0x19, + 0x79, 0x13, 0x63, 0x0c, 0x58, 0x11, 0x50, 0x0f, 0x1c, 0x08, 0x29, 0x06, + 0x9e, 0xfa, 0xe9, 0xef, 0x6f, 0xf9, 0xdf, 0x04, 0x0c, 0x10, 0x76, 0x1a, + 0x6f, 0x18, 0x05, 0x12, 0x3d, 0x0a, 0x01, 0x05, 0x8e, 0xfc, 0x41, 0xef, + 0x5c, 0xe3, 0xbd, 0xd8, 0xb0, 0xd5, 0x9b, 0xdb, 0xe3, 0xdd, 0xfa, 0xd6, + 0x76, 0xce, 0xc0, 0xc8, 0xa0, 0xc5, 0xb1, 0xc6, 0x06, 0xcc, 0x5a, 0xc6, + 0xb0, 0xc0, 0x57, 0xc1, 0x9b, 0xb7, 0x9e, 0xb2, 0xa7, 0xb9, 0xfb, 0xbe, + 0x38, 0xc2, 0xe4, 0xce, 0xb5, 0xd6, 0xae, 0xd8, 0xd9, 0xe4, 0xfb, 0xee, + 0x54, 0xf8, 0x6f, 0x06, 0xcf, 0x0f, 0x79, 0x1a, 0x12, 0x27, 0x09, 0x30, + 0x98, 0x3a, 0x28, 0x3e, 0x9a, 0x3d, 0x0b, 0x41, 0x58, 0x42, 0x12, 0x3c, + 0x7d, 0x35, 0x19, 0x35, 0xf0, 0x34, 0x53, 0x38, 0xf4, 0x37, 0x4d, 0x2c, + 0xe6, 0x1a, 0xde, 0x10, 0x27, 0x0c, 0x4b, 0x07, 0xfd, 0x03, 0xa6, 0xfb, + 0xec, 0xf2, 0x46, 0xea, 0x14, 0xe7, 0xb7, 0xe5, 0x98, 0xe0, 0x46, 0xdc, + 0x57, 0xd9, 0x8d, 0xdb, 0xb9, 0xde, 0x47, 0xe5, 0xc5, 0xeb, 0x7d, 0xec, + 0xc8, 0xed, 0xf7, 0xea, 0x9b, 0xe5, 0x10, 0xed, 0x7c, 0xf8, 0x0a, 0xff, + 0x16, 0x01, 0x44, 0xf9, 0x14, 0xf0, 0x09, 0xf3, 0x72, 0xff, 0xdb, 0x05, + 0x17, 0x0a, 0xa3, 0x0c, 0x1b, 0x06, 0x1c, 0x05, 0xd6, 0x08, 0xd3, 0x05, + 0x18, 0x08, 0xfb, 0x0b, 0xcd, 0x08, 0x06, 0x09, 0x5a, 0x0b, 0xb7, 0x14, + 0xaf, 0x22, 0x38, 0x2d, 0x29, 0x37, 0xe9, 0x3b, 0xa7, 0x3b, 0x47, 0x40, + 0x7b, 0x43, 0xc7, 0x3d, 0x8b, 0x41, 0x56, 0x41, 0xcb, 0x32, 0xe9, 0x30, + 0x2a, 0x32, 0xe0, 0x2b, 0x27, 0x34, 0xbd, 0x33, 0xfb, 0x21, 0xe0, 0x20, + 0x6e, 0x18, 0x09, 0x0f, 0x7d, 0x13, 0xc1, 0x04, 0x46, 0xf1, 0x4f, 0xe3, + 0x15, 0xd2, 0x22, 0xd2, 0xa3, 0xdd, 0x22, 0xd8, 0x95, 0xd0, 0x59, 0xd1, + 0x9f, 0xca, 0xa4, 0xcc, 0x2e, 0xd8, 0x6c, 0xd5, 0xb8, 0xda, 0x44, 0xe7, + 0x3f, 0xe1, 0x7b, 0xe4, 0x73, 0xef, 0xac, 0xef, 0x10, 0xfb, 0xf5, 0x0b, + 0x1e, 0x16, 0x0c, 0x20, 0x6e, 0x23, 0x41, 0x22, 0x91, 0x25, 0xc9, 0x2c, + 0xa8, 0x38, 0x74, 0x48, 0x4c, 0x4e, 0x32, 0x49, 0x87, 0x45, 0xfe, 0x38, + 0xed, 0x2e, 0x59, 0x30, 0xdf, 0x29, 0x2d, 0x26, 0x4a, 0x20, 0x06, 0x11, + 0xa5, 0x0a, 0x97, 0x01, 0xe4, 0xf8, 0x40, 0xfd, 0x62, 0xff, 0x72, 0x02, + 0x62, 0x04, 0xf7, 0xfe, 0x87, 0xf9, 0x48, 0xf7, 0x73, 0xfe, 0x88, 0x06, + 0xa9, 0x10, 0x12, 0x1c, 0x1a, 0x1a, 0xa6, 0x1b, 0x29, 0x20, 0xc2, 0x1e, + 0x4a, 0x20, 0xc9, 0x18, 0xc4, 0x0c, 0x22, 0x03, 0x33, 0xf5, 0xd0, 0xf0, + 0x45, 0xf3, 0xe6, 0xee, 0x43, 0xea, 0x47, 0xe7, 0xe2, 0xe0, 0xb2, 0xd7, + 0xf9, 0xd2, 0x06, 0xd2, 0x62, 0xcd, 0x84, 0xcc, 0x91, 0xc9, 0x28, 0xbf, + 0x9d, 0xbd, 0x01, 0xbe, 0x4b, 0xbf, 0xe2, 0xc6, 0x90, 0xcf, 0x3a, 0xda, + 0x99, 0xdf, 0xeb, 0xe8, 0x20, 0xf8, 0x15, 0x00, 0x1c, 0x09, 0x07, 0x15, + 0xd1, 0x1b, 0xbf, 0x25, 0x43, 0x31, 0xc3, 0x33, 0x67, 0x39, 0x14, 0x3d, + 0x89, 0x38, 0xd2, 0x36, 0xb5, 0x33, 0x4b, 0x32, 0xb7, 0x32, 0xc5, 0x2d, + 0x81, 0x28, 0xde, 0x24, 0x8f, 0x19, 0xf3, 0x0b, 0xb8, 0x03, 0x2d, 0xf8, + 0x87, 0xf0, 0x0c, 0xee, 0x3a, 0xe5, 0x3d, 0xdd, 0x01, 0xd7, 0x44, 0xd1, + 0xe9, 0xd2, 0xa1, 0xd1, 0x32, 0xcf, 0x40, 0xd1, 0x39, 0xcf, 0xe3, 0xd1, + 0xbe, 0xda, 0x13, 0xdf, 0x19, 0xe2, 0x1c, 0xe5, 0x60, 0xe7, 0xd0, 0xec, + 0x2d, 0xf0, 0x6f, 0xf6, 0xbd, 0x01, 0xf5, 0x07, 0x3e, 0x09, 0x3d, 0x07, + 0x91, 0x05, 0x1f, 0x04, 0x60, 0x09, 0xe7, 0x0e, 0xe1, 0x0f, 0xc1, 0x12, + 0x67, 0x0b, 0xdb, 0x03, 0x18, 0x04, 0xf5, 0x01, 0x26, 0x05, 0x2d, 0x0a, + 0x61, 0x09, 0xe8, 0x0c, 0x43, 0x13, 0x6e, 0x15, 0x99, 0x17, 0x1c, 0x1d, + 0x2f, 0x24, 0x65, 0x2c, 0xb7, 0x34, 0xe7, 0x35, 0x53, 0x35, 0xd5, 0x34, + 0x03, 0x34, 0x45, 0x35, 0xb0, 0x33, 0x30, 0x30, 0x25, 0x2a, 0x7d, 0x21, + 0xa4, 0x17, 0x97, 0x08, 0x81, 0xfb, 0xf1, 0xf5, 0xf5, 0xe9, 0x9c, 0xe6, + 0x81, 0xeb, 0x10, 0xdf, 0x60, 0xd9, 0x64, 0xd8, 0x84, 0xc9, 0x4b, 0xc8, + 0xec, 0xcf, 0xef, 0xcc, 0x69, 0xd0, 0x15, 0xd5, 0xcc, 0xd0, 0x90, 0xd1, + 0xae, 0xd8, 0xad, 0xda, 0xd8, 0xe0, 0x6f, 0xf2, 0x30, 0xfc, 0x65, 0x0c, + 0x1f, 0x22, 0x7c, 0x2a, 0x1c, 0x33, 0x85, 0x36, 0x83, 0x38, 0xd8, 0x3e, + 0x43, 0x3f, 0x20, 0x40, 0x94, 0x3d, 0x6d, 0x3a, 0x37, 0x36, 0x52, 0x29, + 0xa4, 0x26, 0x27, 0x25, 0x3d, 0x1b, 0x22, 0x15, 0xc2, 0x15, 0x75, 0x17, + 0xd4, 0x10, 0x9b, 0x0a, 0x86, 0x01, 0xba, 0xf4, 0x1e, 0xef, 0x47, 0xef, + 0x4c, 0xee, 0x0d, 0xf4, 0x25, 0x02, 0xe4, 0x02, 0x4e, 0xfd, 0xc5, 0xfa, + 0x99, 0xfd, 0xd1, 0x05, 0x99, 0x15, 0xc7, 0x29, 0x13, 0x2f, 0x13, 0x35, + 0xe0, 0x37, 0xa1, 0x33, 0x11, 0x37, 0xb4, 0x2c, 0xed, 0x21, 0xcf, 0x1b, + 0xc0, 0x08, 0xe0, 0xf8, 0x2c, 0xf3, 0x8a, 0xf1, 0x20, 0xea, 0x69, 0xe6, + 0x2a, 0xe1, 0x7c, 0xd0, 0xd8, 0xc8, 0x25, 0xc8, 0x02, 0xc8, 0xe5, 0xc6, + 0x19, 0xc6, 0x9e, 0xbf, 0xdd, 0xb4, 0x45, 0xb3, 0x2c, 0xb8, 0x95, 0xbf, + 0xa6, 0xc9, 0xbc, 0xd6, 0xbe, 0xdd, 0xc0, 0xe5, 0x78, 0xef, 0x38, 0xfa, + 0x6a, 0x0a, 0x9b, 0x17, 0x38, 0x27, 0x10, 0x34, 0x2c, 0x3e, 0x7c, 0x49, + 0x93, 0x4e, 0x21, 0x4f, 0x46, 0x4e, 0xd4, 0x47, 0xdb, 0x3f, 0xc8, 0x38, + 0x52, 0x30, 0x60, 0x2c, 0x8c, 0x23, 0xea, 0x1a, 0x49, 0x14, 0x04, 0x08, + 0x89, 0x00, 0x4e, 0xf9, 0xed, 0xef, 0x92, 0xe7, 0x43, 0xdf, 0xa5, 0xda, + 0x76, 0xd7, 0xac, 0xd3, 0x67, 0xd0, 0x98, 0xcf, 0x76, 0xd1, 0x77, 0xd1, + 0x41, 0xd7, 0x23, 0xda, 0x3c, 0xd8, 0x97, 0xe0, 0x2c, 0xe1, 0xe4, 0xe6, + 0x20, 0xf4, 0x9b, 0xf1, 0xa3, 0xf2, 0xe5, 0xf4, 0x98, 0xf3, 0x13, 0xfa, + 0x06, 0xfb, 0xa5, 0xf6, 0xaa, 0xf5, 0x19, 0xf1, 0x9b, 0xf0, 0x25, 0xf6, + 0xb8, 0xf5, 0x55, 0xf3, 0x15, 0xef, 0xd8, 0xea, 0x08, 0xed, 0x4e, 0xf0, + 0x18, 0xee, 0x37, 0xea, 0x0d, 0xeb, 0xfe, 0xea, 0xb2, 0xef, 0x73, 0xfa, + 0x9a, 0xfe, 0x57, 0x07, 0xa5, 0x10, 0x49, 0x15, 0x03, 0x22, 0x96, 0x24, + 0xe3, 0x24, 0x05, 0x2a, 0x9b, 0x24, 0x0f, 0x23, 0x68, 0x1a, 0x96, 0x07, + 0xbb, 0xf9, 0x0d, 0xf0, 0xcf, 0xec, 0xe1, 0xeb, 0xb7, 0xe8, 0x99, 0xde, + 0xe4, 0xd9, 0x2b, 0xdb, 0xe2, 0xd4, 0x48, 0xd7, 0xcb, 0xda, 0x13, 0xcf, + 0x56, 0xcb, 0xe7, 0xcd, 0xf5, 0xc5, 0xc8, 0xc8, 0xa4, 0xd1, 0x46, 0xd0, + 0x28, 0xd6, 0x35, 0xdf, 0xec, 0xe3, 0x4b, 0xef, 0xf9, 0xf9, 0xd6, 0xfc, + 0x3b, 0x02, 0x08, 0x09, 0x70, 0x0e, 0x0e, 0x18, 0xe1, 0x23, 0x51, 0x27, + 0xa8, 0x21, 0x95, 0x19, 0xc4, 0x15, 0x8a, 0x1a, 0xc7, 0x1a, 0x6a, 0x19, + 0xcd, 0x16, 0x51, 0x0b, 0xc9, 0x04, 0x49, 0x01, 0xcb, 0xfc, 0xa5, 0xfc, + 0xaf, 0xfa, 0xb1, 0xf7, 0x6b, 0xf9, 0x51, 0xfa, 0x49, 0xfb, 0x86, 0xfa, + 0xdc, 0xfa, 0x0b, 0x05, 0x2d, 0x0f, 0xc3, 0x12, 0xc3, 0x12, 0xc2, 0x13, + 0x04, 0x13, 0x07, 0x19, 0x65, 0x26, 0x86, 0x2c, 0x46, 0x31, 0x82, 0x36, + 0x00, 0x39, 0x04, 0x3d, 0x4a, 0x42, 0x84, 0x47, 0x62, 0x4e, 0x92, 0x4c, + 0xc6, 0x3d, 0x87, 0x2a, 0x25, 0x14, 0x3e, 0x01, 0xd1, 0xf9, 0xa6, 0xfa, + 0xc5, 0xf6, 0x63, 0xef, 0x94, 0xe9, 0x46, 0xdf, 0x9c, 0xdd, 0x7e, 0xe7, + 0x63, 0xe9, 0x27, 0xe8, 0xb5, 0xea, 0xfe, 0xe7, 0xc4, 0xe2, 0xbb, 0xdf, + 0x82, 0xdd, 0xf4, 0xde, 0xab, 0xec, 0x09, 0xfe, 0x18, 0x0a, 0xbc, 0x16, + 0x83, 0x22, 0x90, 0x2d, 0x7e, 0x3a, 0xf2, 0x47, 0x52, 0x4c, 0xd2, 0x4d, + 0x9e, 0x55, 0x6d, 0x58, 0x93, 0x5b, 0xfa, 0x60, 0x2a, 0x5d, 0x15, 0x56, + 0xd7, 0x51, 0x12, 0x4d, 0x50, 0x46, 0xe9, 0x3f, 0xd3, 0x39, 0xa0, 0x2b, + 0x87, 0x21, 0x7f, 0x1e, 0xf2, 0x15, 0xdf, 0x0f, 0x0f, 0x07, 0x61, 0xfa, + 0xc3, 0xf1, 0xca, 0xee, 0xf6, 0xef, 0x2d, 0xf4, 0x3d, 0xf9, 0x75, 0xf2, + 0x90, 0xe9, 0x2f, 0xe7, 0x1f, 0xe7, 0xe7, 0xeb, 0x53, 0xf6, 0xdd, 0xfe, + 0x57, 0x00, 0x8e, 0xff, 0x86, 0xff, 0x3a, 0x03, 0x32, 0x03, 0x39, 0x08, + 0x8d, 0x10, 0x3d, 0x0c, 0x68, 0x0b, 0xb8, 0x0b, 0x87, 0x07, 0x16, 0x05, + 0x2e, 0x04, 0x7f, 0x04, 0x75, 0x03, 0xb2, 0x07, 0xac, 0x0b, 0x2c, 0x0a, + 0x6f, 0x0b, 0xc6, 0x0a, 0xb2, 0x0b, 0xf5, 0x12, 0x19, 0x17, 0x0f, 0x1e, + 0xd4, 0x24, 0x6b, 0x26, 0xd6, 0x2d, 0x1b, 0x33, 0x29, 0x3b, 0x1c, 0x48, + 0xd5, 0x4d, 0xff, 0x52, 0xa3, 0x4e, 0x08, 0x45, 0x4b, 0x41, 0x79, 0x3a, + 0x30, 0x38, 0xb1, 0x33, 0x8e, 0x23, 0xdd, 0x14, 0x3d, 0x0c, 0x6a, 0x05, + 0x80, 0x01, 0xa4, 0xfe, 0x8f, 0xf7, 0xc6, 0xf4, 0x42, 0xf7, 0x30, 0xf5, + 0x67, 0xf3, 0x33, 0xf3, 0x5f, 0xe8, 0xcf, 0xe2, 0xb2, 0xe3, 0xd4, 0xda, + 0x3e, 0xdf, 0xe3, 0xe5, 0x0f, 0xe2, 0x5a, 0xe2, 0xf6, 0xe2, 0x22, 0xe5, + 0xc4, 0xe9, 0xe1, 0xf0, 0x91, 0xf6, 0xa9, 0xf7, 0x41, 0xf9, 0x48, 0xfe, + 0x31, 0x05, 0x4a, 0x0b, 0x56, 0x0d, 0x69, 0x08, 0x8a, 0x01, 0xa0, 0xff, + 0x51, 0x01, 0x61, 0x02, 0x43, 0x07, 0xd1, 0x0d, 0x7e, 0x0d, 0x32, 0x0b, + 0x97, 0x0b, 0x4c, 0x07, 0x45, 0x08, 0xe1, 0x11, 0x4f, 0x1a, 0x9d, 0x20, + 0x35, 0x1a, 0x50, 0x12, 0x9f, 0x0e, 0xca, 0x0f, 0x34, 0x16, 0xda, 0x17, + 0xfe, 0x1b, 0x2c, 0x1c, 0xd6, 0x1c, 0x66, 0x20, 0x24, 0x1f, 0x94, 0x1d, + 0x79, 0x1f, 0x99, 0x25, 0x14, 0x2c, 0x6f, 0x31, 0x46, 0x34, 0x1a, 0x32, + 0xf6, 0x27, 0xba, 0x22, 0x50, 0x20, 0xa8, 0x14, 0x53, 0x06, 0xa2, 0xf8, + 0x67, 0xeb, 0x4e, 0xdf, 0xc7, 0xda, 0x8d, 0xd9, 0x21, 0xdb, 0x8b, 0xde, + 0xb7, 0xda, 0x33, 0xd7, 0x13, 0xd8, 0x72, 0xd6, 0xc8, 0xd7, 0xd9, 0xdb, + 0xde, 0xd6, 0x16, 0xcf, 0xa4, 0xc7, 0xd1, 0xc5, 0x6f, 0xca, 0xe0, 0xd1, + 0x5e, 0xe0, 0x63, 0xef, 0x1a, 0xf8, 0x50, 0x00, 0x5e, 0x0f, 0xa4, 0x13, + 0x48, 0x18, 0x62, 0x25, 0x80, 0x26, 0xc1, 0x24, 0xac, 0x27, 0x88, 0x29, + 0x02, 0x23, 0xb7, 0x1f, 0x71, 0x1e, 0xe3, 0x18, 0x85, 0x12, 0x27, 0x0d, + 0xc2, 0x0d, 0x92, 0x09, 0xf8, 0x05, 0x1c, 0x03, 0xc7, 0xfd, 0x26, 0xf5, + 0x44, 0xe9, 0xbf, 0xe3, 0xb4, 0xe1, 0x95, 0xe4, 0x73, 0xe4, 0xb3, 0xdc, + 0x2a, 0xd4, 0xd3, 0xce, 0x44, 0xd4, 0x81, 0xde, 0x52, 0xe0, 0xe6, 0xdf, + 0x91, 0xdd, 0xa5, 0xd7, 0x7a, 0xdf, 0x6c, 0xe6, 0x7a, 0xe8, 0xb6, 0xf0, + 0xe8, 0xec, 0x1d, 0xe6, 0x8e, 0xe4, 0xcb, 0xe1, 0x73, 0xe3, 0xca, 0xe8, + 0x9f, 0xec, 0x93, 0xe9, 0x3b, 0xe7, 0x18, 0xe8, 0x63, 0xe7, 0x93, 0xed, + 0xea, 0xf5, 0x94, 0xfc, 0xc9, 0x02, 0x2f, 0x02, 0x5b, 0x03, 0xf7, 0x07, + 0x7f, 0x09, 0x0e, 0x11, 0x78, 0x1d, 0x38, 0x26, 0x32, 0x2d, 0x64, 0x2a, + 0x83, 0x20, 0x9f, 0x1d, 0x3e, 0x21, 0x93, 0x27, 0x51, 0x27, 0x33, 0x22, + 0x26, 0x1f, 0xcf, 0x17, 0x7f, 0x0f, 0x5f, 0x09, 0x40, 0x00, 0xe3, 0xf4, + 0x79, 0xe9, 0xde, 0xe8, 0x83, 0xea, 0x8b, 0xdf, 0x5e, 0xd6, 0x3f, 0xcd, + 0x95, 0xc6, 0x1e, 0xc7, 0x8c, 0xca, 0x29, 0xcf, 0xf2, 0xc6, 0x1d, 0xc4, + 0xa5, 0xc9, 0x6f, 0xc3, 0x84, 0xc3, 0xa3, 0xcb, 0xaf, 0xca, 0x3c, 0xc7, + 0xbc, 0xcd, 0x12, 0xd3, 0x22, 0xd2, 0xe5, 0xd8, 0x14, 0xdb, 0x29, 0xd7, + 0x58, 0xde, 0xe1, 0xe6, 0xa7, 0xe9, 0x16, 0xe8, 0x69, 0xec, 0x03, 0xf2, + 0xaa, 0xf2, 0x0d, 0xfa, 0x01, 0x01, 0x92, 0x04, 0x07, 0x02, 0xd2, 0x00, + 0xe3, 0x02, 0x72, 0x06, 0xff, 0x0e, 0xba, 0x11, 0x09, 0x14, 0x23, 0x11, + 0x0e, 0x09, 0xab, 0x07, 0xf0, 0x09, 0x41, 0x09, 0xd5, 0x08, 0xa7, 0x0f, + 0x39, 0x10, 0xbb, 0x0a, 0xab, 0x0c, 0xfe, 0x07, 0xba, 0xfa, 0xed, 0xfa, + 0x9e, 0x00, 0x1b, 0xff, 0xd0, 0xfd, 0xb6, 0xfe, 0xd4, 0xfd, 0xba, 0xff, + 0x0a, 0x03, 0xb9, 0x05, 0xda, 0x08, 0xf5, 0x04, 0x0d, 0x02, 0xf2, 0xf9, + 0xbb, 0xe9, 0xb2, 0xdd, 0x92, 0xd3, 0xce, 0xce, 0x41, 0xd2, 0x87, 0xd2, + 0x13, 0xcd, 0xa0, 0xcb, 0xfa, 0xc6, 0xc6, 0xc4, 0x87, 0xcd, 0x7e, 0xd1, + 0x4e, 0xcf, 0xf9, 0xce, 0x69, 0xcb, 0xd6, 0xc7, 0xcd, 0xc6, 0xe5, 0xc5, + 0x48, 0xca, 0x4c, 0xcf, 0x6a, 0xd9, 0xe6, 0xe9, 0xfe, 0xf5, 0xea, 0xf8, + 0xaf, 0xfd, 0x73, 0x03, 0xdd, 0x05, 0xf4, 0x11, 0xce, 0x1e, 0xd5, 0x25, + 0x04, 0x2c, 0xd8, 0x2d, 0x4e, 0x2a, 0xbd, 0x2b, 0x95, 0x2b, 0x2b, 0x2a, + 0xda, 0x2d, 0xd9, 0x29, 0x90, 0x21, 0xe1, 0x1c, 0xfa, 0x1a, 0x15, 0x18, + 0xa9, 0x18, 0x17, 0x14, 0x01, 0x0c, 0xcf, 0x04, 0x90, 0xfb, 0xf6, 0xf6, + 0xc4, 0xf0, 0x3d, 0xeb, 0xf3, 0xe9, 0xae, 0xe8, 0x78, 0xdf, 0x59, 0xda, + 0x11, 0xdb, 0xc7, 0xd9, 0xe6, 0xda, 0xad, 0xdf, 0x6f, 0xe3, 0x87, 0xe3, + 0xe2, 0xe8, 0x10, 0xe8, 0xbe, 0xe8, 0x25, 0xed, 0x9f, 0xef, 0xa5, 0xf6, + 0x54, 0x00, 0xb6, 0x05, 0x10, 0x06, 0x2b, 0x04, 0x57, 0xfc, 0x5b, 0x02, + 0xf7, 0x0d, 0xd2, 0x19, 0x97, 0x27, 0x30, 0x2c, 0xd6, 0x2c, 0x1c, 0x2f, + 0x15, 0x34, 0x17, 0x3a, 0x1a, 0x49, 0x49, 0x51, 0x4b, 0x4d, 0x17, 0x45, + 0x41, 0x3d, 0x99, 0x3a, 0x6f, 0x3b, 0xf9, 0x3a, 0xe2, 0x3c, 0x49, 0x3f, + 0x7c, 0x39, 0x09, 0x3d, 0xca, 0x3c, 0x0f, 0x37, 0x7c, 0x33, 0xf4, 0x26, + 0x80, 0x1f, 0x73, 0x1b, 0x9c, 0x0e, 0x46, 0x05, 0xdf, 0xfb, 0x2b, 0xe8, + 0x23, 0xe3, 0xda, 0xe2, 0x42, 0xdf, 0xdb, 0xe7, 0x11, 0xef, 0x6a, 0xeb, + 0xf0, 0xe8, 0xfc, 0xe6, 0x1a, 0xe3, 0xc7, 0xe3, 0x67, 0xdd, 0x31, 0xda, + 0x02, 0xdc, 0x6e, 0xda, 0x9b, 0xde, 0xb6, 0xe8, 0x4c, 0xec, 0x27, 0xec, + 0xb7, 0xef, 0x84, 0xf1, 0x98, 0xfe, 0x13, 0x0a, 0xb0, 0x0e, 0xe3, 0x15, + 0xc5, 0x15, 0x50, 0x15, 0xa3, 0x1b, 0x58, 0x20, 0x61, 0x1f, 0x3c, 0x24, + 0x16, 0x2b, 0xbf, 0x2c, 0x2b, 0x2e, 0xda, 0x2d, 0xc4, 0x27, 0x06, 0x24, + 0x35, 0x24, 0x3a, 0x23, 0x87, 0x24, 0x8f, 0x22, 0xaf, 0x1f, 0xbd, 0x1c, + 0x96, 0x15, 0xde, 0x0f, 0x50, 0x0d, 0x2a, 0x0e, 0xbe, 0x10, 0x10, 0x0f, + 0x15, 0x0b, 0x12, 0x05, 0xa6, 0x01, 0x95, 0x06, 0x08, 0x0a, 0xab, 0x09, + 0xde, 0x08, 0x26, 0x09, 0xf7, 0x0d, 0x8d, 0x19, 0xc7, 0x1f, 0xd3, 0x20, + 0x1d, 0x20, 0xbb, 0x14, 0xe5, 0x0c, 0x86, 0x08, 0x5e, 0xfd, 0x9f, 0xf4, + 0x5e, 0xf3, 0x1c, 0xee, 0xa1, 0xe4, 0x7f, 0xdd, 0x1e, 0xd7, 0x4c, 0xd8, + 0x5d, 0xe0, 0xb5, 0xe6, 0x16, 0xe6, 0x6f, 0xe3, 0x79, 0xde, 0xba, 0xd8, + 0xce, 0xd2, 0x44, 0xcd, 0xee, 0xcc, 0x9e, 0xd0, 0xbf, 0xdb, 0xe2, 0xea, + 0x3c, 0xf6, 0xea, 0xfa, 0x9f, 0x03, 0x97, 0x0a, 0x2d, 0x14, 0x9f, 0x25, + 0xb3, 0x2a, 0x78, 0x2f, 0x6c, 0x33, 0xaf, 0x35, 0x1f, 0x3b, 0xd4, 0x3a, + 0xcb, 0x37, 0x75, 0x36, 0x77, 0x33, 0x4d, 0x2d, 0xab, 0x2c, 0xff, 0x26, + 0x40, 0x24, 0xe7, 0x24, 0xe1, 0x19, 0x55, 0x0e, 0x09, 0x01, 0x37, 0xf5, + 0xf3, 0xf1, 0xdc, 0xed, 0x11, 0xea, 0x17, 0xe8, 0xae, 0xda, 0xca, 0xd0, + 0x74, 0xd4, 0xac, 0xd5, 0xde, 0xd6, 0x47, 0xdd, 0x59, 0xdc, 0xf2, 0xd7, + 0x23, 0xe0, 0x24, 0xe5, 0x00, 0xec, 0xf2, 0xf5, 0xbf, 0xf3, 0xec, 0xf3, + 0xa2, 0xf8, 0x3d, 0xff, 0xf5, 0x0c, 0x1d, 0x1c, 0x83, 0x1e, 0xe3, 0x1d, + 0xdf, 0x1f, 0x2e, 0x23, 0x2b, 0x2f, 0x70, 0x36, 0xce, 0x3c, 0x35, 0x44, + 0xbf, 0x42, 0x35, 0x47, 0x9e, 0x4a, 0xcb, 0x42, 0x2e, 0x3d, 0x8a, 0x32, + 0x96, 0x28, 0xe3, 0x27, 0x44, 0x27, 0x40, 0x22, 0x6c, 0x1a, 0x51, 0x14, + 0xa1, 0x08, 0x40, 0x0a, 0xda, 0x12, 0x67, 0x0c, 0xbb, 0x0b, 0x35, 0x0c, + 0x31, 0x00, 0xbb, 0xfa, 0xe2, 0xff, 0x09, 0xf8, 0x75, 0xec, 0xe4, 0xe4, + 0xbc, 0xd6, 0x1f, 0xd0, 0xb4, 0xd2, 0x07, 0xd5, 0x93, 0xd8, 0x09, 0xd9, + 0x7c, 0xd6, 0x3b, 0xda, 0x17, 0xdc, 0x5d, 0xdb, 0xc1, 0xdf, 0x24, 0xe2, + 0x9f, 0xe4, 0xa4, 0xe7, 0xdd, 0xe0, 0x17, 0xde, 0xae, 0xdf, 0xcd, 0xdb, + 0xb0, 0xe3, 0x7c, 0xe9, 0x70, 0xed, 0x7a, 0xf8, 0xf6, 0xfc, 0xc5, 0x02, + 0xce, 0x0a, 0xfc, 0x16, 0x17, 0x1d, 0x1b, 0x20, 0x9b, 0x28, 0xb8, 0x26, + 0xfe, 0x27, 0xe4, 0x2d, 0x92, 0x2c, 0x76, 0x2b, 0x96, 0x28, 0xec, 0x24, + 0x5b, 0x25, 0xc7, 0x25, 0xfb, 0x24, 0xff, 0x23, 0x95, 0x23, 0x74, 0x1f, + 0x57, 0x1a, 0x4d, 0x18, 0x06, 0x12, 0xf5, 0x0a, 0xef, 0x07, 0x95, 0x07, + 0xe6, 0x07, 0xb9, 0x07, 0x5a, 0x06, 0xe7, 0x05, 0x50, 0x03, 0x2b, 0xfe, + 0xdb, 0x00, 0x5c, 0x06, 0xdf, 0x0e, 0xdb, 0x16, 0x12, 0x18, 0x7a, 0x1b, + 0xfb, 0x1f, 0xd5, 0x21, 0xe0, 0x21, 0x11, 0x20, 0xac, 0x16, 0x2f, 0x09, + 0x7a, 0xfe, 0x21, 0xf9, 0x78, 0xf7, 0x66, 0xec, 0x3d, 0xdc, 0x1d, 0xd7, + 0x20, 0xd6, 0x36, 0xd7, 0x04, 0xe3, 0xa7, 0xe8, 0xde, 0xe2, 0x32, 0xde, + 0x76, 0xd9, 0x33, 0xd2, 0x14, 0xd1, 0x29, 0xd4, 0xc1, 0xce, 0x4a, 0xc8, + 0x27, 0xcf, 0xc8, 0xde, 0xd5, 0xe8, 0xeb, 0xf6, 0xd6, 0x08, 0xf0, 0x0d, + 0x89, 0x13, 0x43, 0x1e, 0xfe, 0x27, 0x45, 0x35, 0x7b, 0x40, 0xd6, 0x42, + 0xa1, 0x3d, 0x73, 0x36, 0x6b, 0x31, 0xc0, 0x30, 0x2d, 0x35, 0xb9, 0x35, + 0x8d, 0x31, 0x42, 0x2a, 0xbc, 0x21, 0x60, 0x1e, 0x24, 0x1a, 0x71, 0x13, + 0x93, 0x0e, 0x46, 0x08, 0x8a, 0xfc, 0xce, 0xf4, 0x5e, 0xf0, 0x47, 0xe9, + 0x4f, 0xe3, 0xbc, 0xdd, 0xf3, 0xdb, 0x53, 0xda, 0xa6, 0xdc, 0xdf, 0xe2, + 0xf6, 0xe0, 0x6f, 0xe3, 0x9b, 0xed, 0xce, 0xef, 0x1c, 0xf5, 0xbb, 0xfc, + 0xf6, 0xfd, 0x3e, 0xff, 0xc2, 0x02, 0x60, 0x0e, 0xab, 0x15, 0x7a, 0x19, + 0xd8, 0x1e, 0xdd, 0x1f, 0x4f, 0x1e, 0x8f, 0x1e, 0x9b, 0x25, 0xbc, 0x2b, + 0x12, 0x36, 0x73, 0x39, 0x5b, 0x30, 0x23, 0x2b, 0xc9, 0x22, 0x67, 0x13, + 0x51, 0x08, 0x65, 0xfe, 0x09, 0xf2, 0x16, 0xeb, 0x94, 0xe0, 0xab, 0xdb, + 0xd6, 0xdb, 0xd3, 0xd5, 0x7b, 0xd9, 0x12, 0xdd, 0x07, 0xda, 0xc9, 0xe3, + 0xc9, 0xeb, 0x28, 0xea, 0xed, 0xed, 0x06, 0xe6, 0xe8, 0xdb, 0x0c, 0xde, + 0x15, 0xde, 0x9f, 0xd9, 0x1f, 0xd9, 0x6d, 0xd7, 0x62, 0xd1, 0x68, 0xd7, + 0xdd, 0xd8, 0x0d, 0xdc, 0x6e, 0xe6, 0xfc, 0xe1, 0x28, 0xe0, 0xa8, 0xe4, + 0xa6, 0xe1, 0xf5, 0xde, 0x19, 0xe3, 0x81, 0xe0, 0xf0, 0xdc, 0xde, 0xdb, + 0x82, 0xd3, 0x73, 0xcd, 0x75, 0xce, 0x6b, 0xd3, 0x90, 0xd9, 0xca, 0xe2, + 0xa0, 0xe6, 0x23, 0xe4, 0x94, 0xe6, 0x78, 0xeb, 0x41, 0xf3, 0x3d, 0x00, + 0xb6, 0x04, 0x39, 0x01, 0x7f, 0x01, 0x04, 0xff, 0x76, 0xfb, 0x39, 0xfc, + 0xfa, 0xfc, 0xbb, 0xfb, 0x56, 0x00, 0xfc, 0x01, 0xeb, 0xfc, 0x01, 0xff, + 0x3e, 0xff, 0xf9, 0xfd, 0x9a, 0xfa, 0x07, 0xf7, 0x17, 0xf9, 0xfe, 0xf8, + 0xf6, 0xf9, 0x71, 0xf7, 0xdd, 0xec, 0x14, 0xe6, 0x98, 0xe7, 0x9e, 0xeb, + 0x47, 0xf4, 0xbb, 0xfa, 0xd8, 0xf8, 0xf3, 0xf6, 0x0f, 0xf9, 0x49, 0xff, + 0xb6, 0x09, 0x85, 0x14, 0x93, 0x1d, 0x1a, 0x25, 0x44, 0x24, 0xd4, 0x20, + 0xcb, 0x19, 0x8c, 0x0d, 0x25, 0x04, 0xfb, 0xfb, 0x4c, 0xf5, 0x26, 0xf0, + 0xfb, 0xeb, 0xa5, 0xe7, 0xaf, 0xe6, 0x35, 0xe6, 0x6c, 0xe8, 0x85, 0xef, + 0xea, 0xf3, 0x76, 0xf7, 0x61, 0xf5, 0x76, 0xed, 0xea, 0xe8, 0x84, 0xe6, + 0xf6, 0xe2, 0x1c, 0xe2, 0x9f, 0xe2, 0x2f, 0xec, 0xb3, 0xf7, 0x5f, 0x01, + 0x2a, 0x17, 0x0a, 0x27, 0x8b, 0x2b, 0xe5, 0x32, 0x25, 0x3b, 0xbf, 0x3b, + 0x1a, 0x44, 0x7b, 0x4c, 0x0f, 0x49, 0xf6, 0x4a, 0x01, 0x4c, 0x9f, 0x4c, + 0xee, 0x4e, 0xc1, 0x4b, 0x4e, 0x3f, 0xf7, 0x39, 0xe9, 0x3a, 0x2e, 0x38, + 0x0a, 0x3b, 0xe1, 0x34, 0x16, 0x2a, 0xe9, 0x23, 0xad, 0x1d, 0xd3, 0x13, + 0xae, 0x0c, 0x3e, 0x0e, 0x84, 0x0f, 0xa3, 0x10, 0xe8, 0x0a, 0xfe, 0xff, + 0x33, 0xf8, 0x5a, 0xf8, 0x26, 0x02, 0x2a, 0x0b, 0x14, 0x0e, 0x5a, 0x0f, + 0xd5, 0x0e, 0xc0, 0x0c, 0x68, 0x13, 0xab, 0x1d, 0xaa, 0x25, 0x4e, 0x31, + 0xd2, 0x35, 0x24, 0x31, 0xda, 0x33, 0x0a, 0x32, 0x6d, 0x2a, 0x39, 0x2f, + 0xc2, 0x30, 0xa8, 0x2a, 0xa3, 0x28, 0xcd, 0x27, 0x97, 0x1e, 0x77, 0x14, + 0xba, 0x10, 0xb8, 0x04, 0xf1, 0xfa, 0x4e, 0xfa, 0x8f, 0xfa, 0x9d, 0xf7, + 0xdf, 0xef, 0x6d, 0xec, 0x85, 0xe6, 0x4d, 0xe2, 0x8f, 0xe9, 0x14, 0xf8, + 0xdc, 0x03, 0xa8, 0x0b, 0x50, 0x13, 0x4c, 0x0d, 0x6e, 0x0a, 0x56, 0x0f, + 0xc5, 0x10, 0x73, 0x1b, 0xc6, 0x25, 0x2b, 0x21, 0x1e, 0x16, 0x72, 0x0f, + 0x9a, 0x07, 0x80, 0x0a, 0x76, 0x13, 0x01, 0x0f, 0x2b, 0x10, 0xa4, 0x13, + 0x02, 0x0d, 0xd0, 0x06, 0xc8, 0x04, 0xdd, 0x00, 0xce, 0xfb, 0xfd, 0xf9, + 0x28, 0xf2, 0x17, 0xe7, 0x3a, 0xe0, 0x2a, 0xda, 0xa6, 0xd8, 0xef, 0xde, + 0x1d, 0xe4, 0xbb, 0xe4, 0xb3, 0xea, 0xf5, 0xf2, 0xf0, 0xfa, 0x45, 0x05, + 0xd5, 0x0e, 0x53, 0x12, 0xb3, 0x0d, 0x92, 0x0e, 0xf5, 0x0e, 0x38, 0x0b, + 0xe0, 0x0d, 0xe6, 0x10, 0xb8, 0x11, 0x27, 0x10, 0xd8, 0x10, 0x49, 0x14, + 0xe3, 0x13, 0x97, 0x13, 0xad, 0x12, 0xd9, 0x0d, 0x08, 0x0b, 0x43, 0x07, + 0xb9, 0x00, 0x7b, 0xfa, 0x55, 0xf3, 0x55, 0xf0, 0xd9, 0xf1, 0xf8, 0xf5, + 0x72, 0xf7, 0xf2, 0xf4, 0x08, 0xf8, 0x0f, 0xfe, 0xeb, 0xfe, 0x6b, 0x00, + 0xc0, 0x01, 0x1f, 0xfe, 0x8e, 0x05, 0x77, 0x17, 0x36, 0x29, 0x57, 0x37, + 0x16, 0x3c, 0xfc, 0x38, 0x3d, 0x34, 0xb6, 0x30, 0xd8, 0x2b, 0x25, 0x27, + 0xff, 0x1d, 0x4b, 0x0f, 0x30, 0x01, 0x79, 0xf3, 0x9a, 0xe5, 0xaa, 0xe1, + 0x8e, 0xe5, 0x93, 0xe3, 0x29, 0xe5, 0x1e, 0xe9, 0xb9, 0xe4, 0x30, 0xdf, + 0xf4, 0xda, 0x80, 0xd2, 0x41, 0xca, 0x29, 0xc5, 0xa1, 0xc0, 0xda, 0xbe, + 0xbb, 0xc6, 0x43, 0xd4, 0xb9, 0xd9, 0x31, 0xe5, 0x98, 0xf8, 0xcb, 0xff, + 0x62, 0x03, 0x33, 0x10, 0x7f, 0x19, 0x93, 0x1f, 0x32, 0x31, 0x53, 0x41, + 0xb7, 0x44, 0x1d, 0x3f, 0x21, 0x3a, 0x30, 0x35, 0xa1, 0x2f, 0x2a, 0x36, + 0x38, 0x3d, 0x47, 0x35, 0xbe, 0x29, 0xe2, 0x23, 0xd8, 0x1b, 0x3d, 0x18, + 0x7b, 0x19, 0x54, 0x13, 0x26, 0x04, 0x0d, 0xf4, 0x9c, 0xf6, 0xd9, 0xf7, + 0xa6, 0xee, 0x49, 0xf3, 0x92, 0xec, 0x86, 0xda, 0x74, 0xda, 0x9d, 0xde, + 0x05, 0xe3, 0x4f, 0xef, 0xe1, 0xf6, 0x77, 0xef, 0xbd, 0xe5, 0x79, 0xe7, + 0x9f, 0xf1, 0xe8, 0xf9, 0xb5, 0xfe, 0x6e, 0x03, 0xb7, 0x00, 0xdb, 0xfa, + 0xca, 0xfa, 0x68, 0xfd, 0x3a, 0x03, 0x74, 0x09, 0x34, 0x02, 0xad, 0xf5, + 0x35, 0xee, 0xfb, 0xe0, 0xcb, 0xd5, 0x4a, 0xd1, 0x1b, 0xcd, 0x27, 0xc8, + 0x32, 0xc6, 0x2c, 0xc2, 0xec, 0xbc, 0x8c, 0xc2, 0x35, 0xcc, 0x7e, 0xd0, + 0x69, 0xd4, 0xa5, 0xe1, 0x0e, 0xeb, 0x92, 0xf3, 0xdf, 0x00, 0xdb, 0x03, + 0xac, 0x01, 0xe5, 0x03, 0xfa, 0x09, 0x0b, 0x10, 0xd2, 0x1e, 0x74, 0x25, + 0xdd, 0x1b, 0xa0, 0x13, 0x8b, 0x0d, 0x3c, 0x0b, 0xfe, 0x08, 0x9d, 0x06, + 0xfa, 0x00, 0xf5, 0xf8, 0x44, 0xf0, 0x26, 0xe9, 0x94, 0xe4, 0xbc, 0xdc, + 0xff, 0xd5, 0x90, 0xcf, 0x35, 0xc8, 0x83, 0xc2, 0x1a, 0xc4, 0xfc, 0xc2, + 0x8a, 0xc0, 0x91, 0xc2, 0x6d, 0xc1, 0x72, 0xc5, 0x7a, 0xcb, 0x42, 0xd2, + 0xf6, 0xd8, 0x93, 0xe2, 0x5b, 0xee, 0xbb, 0xf3, 0x29, 0xf8, 0x1c, 0xf6, + 0xdb, 0xf2, 0xfe, 0xf6, 0x2d, 0xfe, 0xf9, 0x01, 0xf4, 0x02, 0xda, 0x03, + 0xa4, 0x02, 0x23, 0x07, 0x78, 0x07, 0xa9, 0xf7, 0xe7, 0xe9, 0xd7, 0xea, + 0xb5, 0xee, 0x89, 0xf1, 0x51, 0xf4, 0x05, 0xec, 0x05, 0xdb, 0xf6, 0xcd, + 0xa6, 0xcd, 0x64, 0xd5, 0x50, 0xdc, 0x72, 0xe2, 0x06, 0xe7, 0xe5, 0xe5, + 0x42, 0xe2, 0x68, 0xe6, 0xd1, 0xee, 0xd6, 0xf9, 0xdd, 0x03, 0x7a, 0x09, + 0xf6, 0x12, 0x7c, 0x1d, 0x28, 0x28, 0x49, 0x33, 0xc5, 0x36, 0x90, 0x2d, + 0x38, 0x26, 0x21, 0x1f, 0xf6, 0x0f, 0x33, 0x09, 0xe1, 0xfe, 0x16, 0xee, + 0x4b, 0xe3, 0x4e, 0xd6, 0xdc, 0xcc, 0x6e, 0xd0, 0x2f, 0xd1, 0xe3, 0xc9, + 0xe1, 0xc7, 0xcc, 0xc2, 0xe0, 0xba, 0xba, 0xb7, 0x10, 0xb7, 0x15, 0xb4, + 0x9d, 0xb1, 0x1e, 0xb2, 0xb3, 0xb0, 0xc2, 0xb6, 0x88, 0xc6, 0x86, 0xd6, + 0x5e, 0xe2, 0x63, 0xf2, 0x6b, 0xfc, 0x17, 0xfd, 0xa5, 0x05, 0x40, 0x12, + 0x4a, 0x23, 0xf8, 0x38, 0x54, 0x46, 0x30, 0x45, 0x4b, 0x43, 0xee, 0x41, + 0xac, 0x3e, 0xc1, 0x3a, 0xe4, 0x34, 0x40, 0x37, 0xd3, 0x38, 0x85, 0x30, + 0xc6, 0x26, 0x35, 0x1b, 0x3a, 0x06, 0xa7, 0xff, 0xe7, 0x05, 0x0b, 0x02, + 0x67, 0xfc, 0xea, 0xf2, 0x6b, 0xe7, 0xe4, 0xdd, 0xa6, 0xda, 0xda, 0xd6, + 0xcb, 0xd5, 0xc3, 0xd8, 0x86, 0xd8, 0xc5, 0xdb, 0xe7, 0xd7, 0xa1, 0xd9, + 0xf9, 0xde, 0x1f, 0xdf, 0xa4, 0xeb, 0xe5, 0xfb, 0xab, 0xfc, 0x3e, 0xfc, + 0x14, 0x01, 0x7f, 0xf8, 0xa7, 0xf9, 0x1f, 0x05, 0x55, 0x05, 0x26, 0x08, + 0x5e, 0x08, 0xe9, 0xf8, 0xf2, 0xeb, 0xa6, 0xe8, 0x23, 0xe7, 0x3b, 0xec, + 0x3f, 0xf1, 0x42, 0xf3, 0x70, 0xf0, 0x63, 0xe6, 0xd5, 0xe5, 0x34, 0xea, + 0xeb, 0xe5, 0x25, 0xf0, 0xf6, 0x00, 0xa6, 0x04, 0x49, 0x13, 0xd0, 0x1d, + 0x32, 0x1a, 0x83, 0x20, 0x20, 0x2c, 0x30, 0x37, 0x13, 0x45, 0xfb, 0x4c, + 0xb9, 0x4c, 0xf5, 0x49, 0xae, 0x41, 0x2f, 0x3c, 0xdd, 0x3a, 0x33, 0x35, + 0x92, 0x2e, 0xf0, 0x23, 0xb7, 0x18, 0xa9, 0x12, 0x3f, 0x0d, 0xad, 0x09, + 0xe7, 0x02, 0xdf, 0xf7, 0xaa, 0xef, 0xc0, 0xe8, 0xde, 0xe3, 0x45, 0xe2, + 0x70, 0xdf, 0xf5, 0xdd, 0xea, 0xe1, 0xe2, 0xe1, 0xe1, 0xe1, 0x39, 0xe6, + 0x59, 0xe8, 0x6c, 0xef, 0x7a, 0xf5, 0xe0, 0xf8, 0xcf, 0x01, 0x2f, 0x07, + 0x50, 0x07, 0x67, 0x09, 0x53, 0x0b, 0xa2, 0x10, 0xd6, 0x1a, 0x60, 0x23, + 0xec, 0x28, 0x51, 0x26, 0x58, 0x1b, 0x43, 0x12, 0x75, 0x14, 0x44, 0x1a, + 0x53, 0x1c, 0x8a, 0x18, 0x9f, 0x0c, 0x8f, 0x05, 0xc5, 0x00, 0xaa, 0xfd, + 0x0c, 0xff, 0x19, 0xfb, 0x1d, 0xf3, 0x46, 0xec, 0xde, 0xec, 0xd0, 0xf5, + 0xfc, 0x00, 0xdc, 0x03, 0x2d, 0x00, 0xd0, 0x01, 0x43, 0x07, 0xf5, 0x0d, + 0xef, 0x15, 0x45, 0x21, 0x5e, 0x2d, 0x0c, 0x32, 0x52, 0x33, 0xf0, 0x37, + 0x65, 0x41, 0xf5, 0x4c, 0x07, 0x4f, 0x6b, 0x43, 0x0d, 0x36, 0x30, 0x2e, + 0x15, 0x26, 0x2b, 0x19, 0xe7, 0x09, 0xac, 0xfc, 0xcb, 0xf1, 0x71, 0xec, + 0x25, 0xee, 0xc4, 0xe8, 0x4d, 0xd9, 0xf3, 0xce, 0xf6, 0xce, 0x14, 0xd1, + 0xbd, 0xd0, 0x79, 0xce, 0xf6, 0xc7, 0xa9, 0xc5, 0x9f, 0xc9, 0x32, 0xcb, + 0x58, 0xd0, 0xfe, 0xe0, 0x9c, 0xf8, 0xb0, 0x08, 0x85, 0x10, 0xe7, 0x19, + 0x68, 0x23, 0x58, 0x31, 0x75, 0x43, 0x84, 0x4d, 0x20, 0x51, 0x54, 0x51, + 0x69, 0x51, 0xfb, 0x54, 0xfa, 0x53, 0xe6, 0x53, 0x63, 0x5b, 0x62, 0x59, + 0x50, 0x4a, 0xb4, 0x44, 0x9c, 0x3e, 0xc5, 0x2b, 0x68, 0x21, 0x87, 0x12, + 0x69, 0xfb, 0xc7, 0xee, 0x45, 0xe4, 0xf2, 0xd9, 0xba, 0xd7, 0x85, 0xd9, + 0x66, 0xd8, 0xe7, 0xd7, 0x81, 0xd4, 0x4b, 0xd4, 0xdf, 0xdc, 0x71, 0xe1, + 0x3b, 0xe2, 0x68, 0xdd, 0x4a, 0xd8, 0x7e, 0xdf, 0x14, 0xea, 0x30, 0xf2, + 0x8a, 0xfe, 0x3d, 0x05, 0x6a, 0x07, 0x30, 0x16, 0x64, 0x1f, 0x7d, 0x1f, + 0x9d, 0x29, 0xb8, 0x2c, 0x4e, 0x26, 0x0b, 0x27, 0xf9, 0x21, 0xd5, 0x15, + 0x12, 0x0b, 0xca, 0xfe, 0xa0, 0xff, 0xfc, 0xff, 0x3e, 0xf6, 0x58, 0xeb, + 0xa2, 0xda, 0x8e, 0xd9, 0xde, 0xe4, 0xd4, 0xeb, 0xe1, 0xef, 0xba, 0xf3, + 0x6b, 0xf7, 0xce, 0x00, 0xe0, 0x0e, 0xb7, 0x0c, 0x37, 0x11, 0xdd, 0x1c, + 0x2d, 0x20, 0x9a, 0x28, 0x6d, 0x2c, 0x9a, 0x2b, 0x17, 0x2e, 0xa5, 0x2f, + 0xcc, 0x28, 0x40, 0x25, 0x76, 0x25, 0x5d, 0x1b, 0x80, 0x11, 0x91, 0x0d, + 0xfd, 0x0a, 0x92, 0x0a, 0x0f, 0x03, 0xe8, 0xf4, 0x48, 0xef, 0x61, 0xec, + 0x25, 0xe9, 0xd8, 0xe4, 0x77, 0xe0, 0xd8, 0xdf, 0x89, 0xe0, 0x35, 0xe0, + 0x5b, 0xde, 0x2a, 0xde, 0x85, 0xdd, 0x09, 0xdf, 0x71, 0xe4, 0xb4, 0xee, + 0x42, 0xf6, 0x39, 0xfe, 0x27, 0x0c, 0xa5, 0x0f, 0xae, 0x0b, 0xc7, 0x0b, + 0x68, 0x13, 0xff, 0x1b, 0xe9, 0x23, 0x96, 0x25, 0x43, 0x1b, 0xaa, 0x13, + 0x54, 0x12, 0x08, 0x12, 0x34, 0x13, 0x5a, 0x14, 0x33, 0x16, 0x56, 0x15, + 0x85, 0x12, 0x79, 0x0e, 0xc8, 0xfb, 0x38, 0xef, 0xf6, 0xf3, 0x42, 0xfa, + 0x3f, 0x01, 0xd8, 0x01, 0x72, 0x00, 0x61, 0x05, 0x43, 0x0a, 0x87, 0x08, + 0x57, 0x02, 0x86, 0x01, 0xdc, 0x0d, 0xc9, 0x1a, 0x1d, 0x21, 0x0f, 0x21, + 0x4a, 0x1e, 0x44, 0x25, 0x94, 0x30, 0x04, 0x3e, 0x88, 0x4c, 0x30, 0x51, + 0x2d, 0x4b, 0x96, 0x3c, 0x3b, 0x29, 0xa2, 0x26, 0xab, 0x23, 0x80, 0x0e, + 0xaf, 0xfa, 0x27, 0xed, 0xe5, 0xf3, 0xe7, 0xfa, 0x0a, 0xf1, 0x04, 0xe5, + 0x48, 0xdb, 0x54, 0xdc, 0xd6, 0xe1, 0x7b, 0xda, 0x82, 0xcc, 0x06, 0xca, + 0x7c, 0xd1, 0xb6, 0xd5, 0xaa, 0xd3, 0x94, 0xd7, 0x5a, 0xe2, 0xf2, 0xf4, + 0x91, 0x05, 0x93, 0x12, 0x43, 0x21, 0xec, 0x23, 0xc6, 0x26, 0x74, 0x35, + 0x2c, 0x4c, 0xcb, 0x5c, 0xaa, 0x57, 0x9c, 0x41, 0xb9, 0x42, 0xc1, 0x4b, + 0x05, 0x43, 0x43, 0x44, 0xed, 0x38, 0x7b, 0x29, 0x19, 0x28, 0x71, 0x22, + 0x07, 0x1a, 0x93, 0x14, 0xcc, 0x08, 0xfd, 0xfd, 0xfb, 0xfb, 0x11, 0xf4, + 0x6a, 0xea, 0x34, 0xd9, 0x39, 0xd3, 0x48, 0xe1, 0x1d, 0xe0, 0x36, 0xd3, + 0x88, 0xd9, 0xca, 0xe6, 0x33, 0xec, 0x31, 0xf1, 0x58, 0xed, 0xe8, 0xef, + 0x99, 0xf3, 0x0d, 0xf9, 0xbf, 0x0e, 0xb5, 0x1e, 0x4c, 0x20, 0xaa, 0x18, + 0x20, 0x10, 0x12, 0x10, 0x0c, 0x18, 0xb6, 0x1f, 0x78, 0x29, 0xe6, 0x2e, + 0x00, 0x21, 0xfd, 0x10, 0x76, 0x07, 0x79, 0xf8, 0xef, 0xf9, 0xf6, 0x04, + 0xe5, 0xf9, 0xac, 0xe6, 0xc3, 0xdd, 0x57, 0xdd, 0x79, 0xda, 0x5f, 0xdf, + 0x1d, 0xed, 0xdb, 0xf8, 0x7e, 0xf6, 0x59, 0xf1, 0xbb, 0x05, 0xca, 0x12, + 0x57, 0xfc, 0x78, 0xe9, 0x38, 0xf8, 0x47, 0x11, 0x49, 0x2d, 0x82, 0x3b, + 0xf9, 0x30, 0x4c, 0x20, 0x2b, 0x04, 0xa0, 0xf8, 0x05, 0x0f, 0xfc, 0x1c, + 0xb5, 0x11, 0x7a, 0x10, 0x46, 0x16, 0xfe, 0x0a, 0xef, 0x05, 0xa0, 0x06, + 0x20, 0xfb, 0x25, 0xea, 0xc9, 0xda, 0x2d, 0xd6, 0x61, 0xce, 0x47, 0xbf, + 0x74, 0xc4, 0x1b, 0xd3, 0x29, 0xcd, 0x4c, 0xb8, 0x4f, 0xbe, 0xe2, 0xcc, + 0xfb, 0xc8, 0x61, 0xd3, 0xed, 0xe5, 0x48, 0xe8, 0xcc, 0xd9, 0x3f, 0xc9, + 0xda, 0xc4, 0xbe, 0xda, 0x4b, 0xf6, 0xb4, 0x02, 0x6e, 0xfa, 0x1f, 0xed, + 0xdf, 0xf9, 0x04, 0xff, 0x9e, 0x02, 0x3b, 0x00, 0x19, 0xe7, 0xe6, 0xe6, + 0xd8, 0x0a, 0x9d, 0x1f, 0xb8, 0x02, 0x20, 0xe8, 0x41, 0xe2, 0x10, 0xe0, + 0x7e, 0xe5, 0x98, 0xe5, 0xf7, 0xe7, 0x9b, 0xf0, 0xf9, 0xe6, 0x1b, 0xd4, + 0xca, 0xce, 0xf3, 0xd6, 0xbf, 0xe2, 0x3d, 0xe1, 0x5a, 0xe3, 0x0f, 0xee, + 0x0d, 0xf8, 0xae, 0xfd, 0x1d, 0xf7, 0x1f, 0xfc, 0xc5, 0x10, 0x69, 0x1a, + 0x0e, 0x28, 0xa5, 0x48, 0xd5, 0x51, 0xe9, 0x38, 0xda, 0x10, 0xec, 0x0f, + 0x84, 0x4d, 0xf1, 0x6a, 0xe3, 0x56, 0xfe, 0x40, 0x3e, 0x16, 0x03, 0xe2, + 0x89, 0xd4, 0x5c, 0xcb, 0x1f, 0xaf, 0x04, 0xa7, 0x2c, 0xb9, 0xdf, 0xd8, + 0xe6, 0xe9, 0x0d, 0xf3, 0x64, 0xfc, 0x1d, 0xef, 0x3b, 0xd2, 0x06, 0xc2, + 0x2d, 0xd5, 0x6b, 0xe4, 0x2d, 0xd7, 0xc1, 0xc9, 0x70, 0xde, 0xd4, 0x10, + 0xfd, 0x29, 0xda, 0x29, 0xb5, 0x2b, 0x8d, 0x38, 0x89, 0x42, 0x6c, 0x36, + 0x42, 0x26, 0x73, 0x30, 0xb1, 0x45, 0x49, 0x4a, 0x73, 0x57, 0x48, 0x5c, + 0x00, 0x57, 0x10, 0x4e, 0x43, 0x2a, 0x84, 0x1f, 0x2c, 0x24, 0xf2, 0x08, + 0xf3, 0xf6, 0x28, 0xfe, 0x43, 0x0a, 0x83, 0x14, 0x75, 0x03, 0x50, 0xe7, + 0x9e, 0xe1, 0x3b, 0xf0, 0x8c, 0x07, 0xca, 0xfa, 0x21, 0xde, 0xa0, 0xe8, + 0xb6, 0x01, 0x68, 0x04, 0x05, 0xe9, 0xb9, 0xd7, 0xc8, 0xf7, 0x85, 0x26, + 0xc2, 0x49, 0xa8, 0x54, 0xee, 0x4b, 0x97, 0x53, 0x70, 0x50, 0x37, 0x43, + 0xac, 0x39, 0xc1, 0x1a, 0xd5, 0x06, 0x8e, 0x07, 0x26, 0x06, 0xff, 0x0e, + 0x68, 0x08, 0xda, 0xf2, 0x2e, 0xfc, 0xf8, 0x13, 0x75, 0x26, 0x0a, 0x28, + 0xcf, 0x21, 0x6b, 0x22, 0x2d, 0x1c, 0xe5, 0x05, 0x98, 0xe7, 0x02, 0xe1, + 0x61, 0xf1, 0xad, 0x03, 0x00, 0x08, 0xd3, 0x10, 0x56, 0x23, 0x8f, 0x31, + 0xf3, 0x48, 0x41, 0x54, 0x83, 0x4b, 0x1e, 0x44, 0x1e, 0x49, 0x8c, 0x52, + 0xd3, 0x51, 0xfa, 0x41, 0x6e, 0x33, 0x19, 0x2e, 0xba, 0x28, 0x0b, 0x21, + 0xbc, 0x0e, 0x99, 0xfc, 0x93, 0xf4, 0x25, 0xfb, 0x64, 0x08, 0x5c, 0x0b, + 0xba, 0x09, 0xe6, 0x04, 0x34, 0xf2, 0x0f, 0xd9, 0x83, 0xc8, 0x81, 0xc9, + 0x38, 0xe3, 0xd4, 0xf8, 0x31, 0xf7, 0x18, 0xe9, 0xcb, 0xe0, 0xda, 0xe7, + 0x5a, 0xf8, 0x47, 0x0d, 0x0d, 0x12, 0x15, 0x08, 0x84, 0x07, 0x3f, 0x14, + 0x54, 0x21, 0xee, 0x22, 0x42, 0x1f, 0x3e, 0x1e, 0xff, 0x13, 0xc7, 0x14, + 0x3c, 0x28, 0xd5, 0x26, 0xd7, 0x12, 0x03, 0xfa, 0x2c, 0xed, 0x69, 0xf2, + 0x59, 0xee, 0x9f, 0xdb, 0x18, 0xd3, 0xbf, 0xea, 0xe4, 0x0e, 0xbb, 0x16, + 0xcb, 0x04, 0x68, 0x05, 0xe5, 0x08, 0x82, 0xf4, 0xe6, 0xf3, 0xdd, 0xf5, + 0xe7, 0xe3, 0x70, 0xed, 0x93, 0x0a, 0x87, 0x24, 0xf8, 0x37, 0xc8, 0x3e, + 0xb8, 0x3c, 0x2f, 0x35, 0xbf, 0x2d, 0xa4, 0x2e, 0x0b, 0x39, 0x20, 0x38, + 0xc5, 0x3b, 0xa9, 0x53, 0xac, 0x62, 0xd2, 0x59, 0x76, 0x44, 0x8b, 0x35, + 0xca, 0x24, 0x82, 0x0d, 0x5e, 0xfb, 0xf1, 0x0a, 0x14, 0x2b, 0xfa, 0x15, + 0x5d, 0xe3, 0x8d, 0xc1, 0x82, 0xae, 0xba, 0xb6, 0x54, 0xd1, 0xee, 0xdd, + 0xfe, 0xd0, 0x7c, 0xba, 0xae, 0xb1, 0x6c, 0xb8, 0xbc, 0xbc, 0x86, 0xbf, + 0xd5, 0xcc, 0xa5, 0xd2, 0xbc, 0xca, 0xc2, 0xbf, 0xfb, 0xc6, 0x6b, 0xeb, + 0xf3, 0x0b, 0x27, 0x10, 0xf2, 0x09, 0x44, 0x1e, 0x3a, 0x38, 0x9e, 0x3f, + 0x08, 0x2f, 0xe9, 0x1c, 0x75, 0x2c, 0x78, 0x2c, 0x84, 0x24, 0x43, 0x24, + 0x5b, 0x0f, 0xdf, 0xff, 0x48, 0xfa, 0x9a, 0xfe, 0x52, 0x13, 0x4b, 0x1b, + 0x8f, 0x18, 0x5c, 0x29, 0x75, 0x37, 0xdb, 0x26, 0xd7, 0xfb, 0x5b, 0xdb, + 0x29, 0xe6, 0x87, 0xf5, 0x35, 0xe3, 0x2e, 0xd3, 0x08, 0xdf, 0xbb, 0xed, + 0x75, 0xfc, 0xc3, 0xf9, 0xe4, 0xee, 0x56, 0x00, 0xd5, 0x15, 0xc0, 0x14, + 0x4d, 0x00, 0xdd, 0xff, 0xfc, 0x0f, 0xea, 0x0c, 0x7f, 0x11, 0xfc, 0x1e, + 0x25, 0x16, 0x5f, 0x10, 0xa5, 0x18, 0x16, 0xfb, 0x23, 0xc4, 0x43, 0xb3, + 0xd6, 0xc7, 0x65, 0xe8, 0x52, 0xfa, 0x2d, 0xe4, 0xdd, 0xc9, 0x2f, 0xcb, + 0x7e, 0xd2, 0x8d, 0xde, 0x1c, 0xe5, 0x1a, 0xe2, 0x3f, 0xdf, 0xa0, 0xcf, + 0x61, 0xda, 0xfd, 0xfc, 0x6e, 0x05, 0xda, 0x11, 0xd3, 0x25, 0x79, 0x24, + 0xf6, 0x23, 0x69, 0x30, 0x11, 0x24, 0xbb, 0xf7, 0x24, 0xda, 0xd4, 0xe5, + 0xa1, 0x0b, 0x57, 0x22, 0x04, 0x1a, 0xcc, 0x06, 0xae, 0xf4, 0x0a, 0xe2, + 0xe1, 0xe3, 0xef, 0xfe, 0x35, 0x01, 0x79, 0xea, 0x9d, 0xd3, 0xc1, 0xbf, + 0xa9, 0xba, 0x67, 0xb4, 0xdd, 0xb1, 0x64, 0xbd, 0x3a, 0xc5, 0x60, 0xcf, + 0x9f, 0xde, 0xf8, 0xe5, 0xd5, 0xdb, 0xea, 0xd3, 0x7c, 0xd5, 0xc0, 0xd7, + 0x80, 0xea, 0x78, 0xfa, 0x17, 0xf2, 0x98, 0xdc, 0x63, 0xdb, 0x7e, 0xfb, + 0x64, 0x1a, 0xc9, 0x0e, 0xe0, 0xe7, 0x5d, 0xe7, 0x48, 0xf5, 0x6e, 0xf1, + 0x0e, 0xf3, 0x18, 0xec, 0xac, 0xdc, 0x30, 0xe8, 0x2d, 0xf7, 0x72, 0xd6, + 0xb0, 0xb8, 0x19, 0xcb, 0x5d, 0xfa, 0xb9, 0x1b, 0xb4, 0x04, 0x9b, 0xe2, + 0x74, 0xea, 0xca, 0xf8, 0x26, 0xf5, 0xa8, 0x08, 0x4e, 0x09, 0xd0, 0xe7, + 0x1a, 0xef, 0x0f, 0x0a, 0x36, 0x2d, 0x87, 0x49, 0x3f, 0x48, 0x2c, 0x3d, + 0xe9, 0x24, 0xe0, 0x15, 0xd8, 0x22, 0x8c, 0x3d, 0xd6, 0x3d, 0x87, 0x2e, + 0x22, 0x27, 0xc3, 0x2b, 0x75, 0x37, 0x22, 0x1c, 0xb7, 0x03, 0x8c, 0x0c, + 0x17, 0x10, 0x4b, 0xfc, 0x8e, 0xdc, 0xe6, 0xc4, 0xf0, 0xbc, 0xf9, 0xc1, + 0x4a, 0xbb, 0xd6, 0xb1, 0x5d, 0xa7, 0x71, 0x9e, 0x77, 0x9c, 0xf7, 0xa1, + 0x57, 0xb8, 0x63, 0xcb, 0x20, 0xc9, 0xf9, 0xb5, 0x23, 0xac, 0x74, 0xb1, + 0xcc, 0xb0, 0xcf, 0xa3, 0x8b, 0xae, 0x67, 0xc3, 0xc6, 0xc7, 0x76, 0xde, + 0x4b, 0x03, 0x44, 0x15, 0x2d, 0x21, 0xd1, 0x37, 0xfd, 0x3c, 0x2c, 0x47, + 0xcf, 0x5d, 0xb2, 0x64, 0x67, 0x4a, 0xfc, 0x0c, 0xbd, 0xf9, 0x73, 0x30, + 0x2c, 0x5d, 0x65, 0x40, 0x6b, 0x0d, 0x3b, 0xf8, 0x5c, 0x02, 0xf9, 0x15, + 0xf7, 0x08, 0x3c, 0xdb, 0x9e, 0xcf, 0x98, 0xee, 0x46, 0xfc, 0x5e, 0xeb, + 0x6a, 0xc5, 0x40, 0xb7, 0x2f, 0xd0, 0x99, 0xef, 0x3b, 0xeb, 0x5d, 0xd5, + 0x19, 0xd9, 0x0b, 0xdc, 0x37, 0xe5, 0x3f, 0xf1, 0x59, 0xff, 0x0c, 0x18, + 0x81, 0x1d, 0xe2, 0x08, 0x85, 0xf4, 0xe8, 0xfc, 0x89, 0x11, 0x37, 0x00, + 0x7c, 0xda, 0x17, 0xd3, 0x2a, 0xfe, 0xa2, 0x23, 0x07, 0xef, 0x0c, 0xc1, + 0x35, 0xc9, 0xfa, 0xce, 0x05, 0xe6, 0x85, 0xef, 0x7f, 0xd1, 0x81, 0xc9, + 0x09, 0xe9, 0xf7, 0x03, 0x2a, 0x0f, 0x59, 0x03, 0x43, 0xfb, 0xb6, 0x03, + 0x46, 0x14, 0xa8, 0x15, 0xba, 0xf7, 0xcb, 0xea, 0x9d, 0x0b, 0x59, 0x41, + 0xe2, 0x42, 0x9d, 0x2e, 0x3f, 0x25, 0x65, 0x21, 0x59, 0x32, 0xa4, 0x43, + 0xc1, 0x56, 0x97, 0x47, 0x19, 0x14, 0x0a, 0xf5, 0x85, 0xfe, 0x5c, 0x07, + 0x9d, 0xff, 0xbe, 0xfc, 0xc7, 0xff, 0xda, 0x03, 0xcb, 0xef, 0xfa, 0xc8, + 0xed, 0xc4, 0xde, 0xf3, 0x4d, 0x13, 0x9b, 0xf7, 0xea, 0xc8, 0x3b, 0xcb, + 0xff, 0xe5, 0x60, 0xf2, 0xb0, 0xf3, 0x03, 0xe4, 0xac, 0xe4, 0x79, 0xe3, + 0x1f, 0xe6, 0xa5, 0x10, 0x0d, 0x23, 0xde, 0x0e, 0xd9, 0x18, 0x64, 0x2a, + 0x67, 0x20, 0x27, 0x14, 0xd1, 0x05, 0xc8, 0xe6, 0x11, 0xd7, 0xf0, 0xfe, + 0x5c, 0x21, 0x50, 0x25, 0xb8, 0x10, 0x5c, 0xfc, 0xfd, 0x18, 0x2e, 0x35, + 0xc6, 0x2b, 0x69, 0x17, 0x7b, 0x0d, 0x25, 0x00, 0x27, 0x0e, 0x25, 0x1e, + 0x99, 0x0f, 0x5e, 0x0a, 0x48, 0x01, 0x03, 0x0b, 0xf9, 0x27, 0xed, 0x40, + 0x27, 0x4a, 0xc9, 0x36, 0xa0, 0x26, 0xd0, 0x2d, 0x7d, 0x47, 0xfd, 0x54, + 0xbb, 0x48, 0xaf, 0x3f, 0xe3, 0x34, 0x6c, 0x1f, 0x3e, 0x1b, 0x59, 0x23, + 0xe3, 0x2e, 0xb8, 0x2f, 0x8c, 0x1a, 0xe4, 0x0e, 0x6c, 0x0a, 0xa3, 0xf9, + 0x90, 0xeb, 0xe8, 0xf3, 0x7d, 0xfd, 0x77, 0xef, 0xd0, 0xd7, 0x03, 0xc0, + 0x0b, 0xb2, 0x5f, 0xb4, 0x2e, 0xaf, 0x40, 0xaf, 0x68, 0xc2, 0xc2, 0xd6, + 0xa5, 0xdc, 0xdd, 0xcd, 0x40, 0xc9, 0xfb, 0xc9, 0x42, 0xce, 0x41, 0xd9, + 0xaf, 0xe5, 0xa2, 0x11, 0x8c, 0x37, 0xe5, 0x3c, 0xf6, 0x4f, 0xfc, 0x5a, + 0x73, 0x37, 0x2b, 0x2d, 0x24, 0x49, 0x17, 0x51, 0x0b, 0x3d, 0x8e, 0x22, + 0x3f, 0x32, 0x8f, 0x59, 0x14, 0x6a, 0xe6, 0x62, 0x8e, 0x55, 0xbd, 0x3e, + 0xc3, 0x25, 0x52, 0x17, 0xfa, 0x0f, 0xc2, 0x1c, 0xd9, 0x07, 0x19, 0xdf, + 0x25, 0xe5, 0xae, 0xf5, 0xd4, 0xf6, 0xac, 0xf0, 0x59, 0xea, 0xc2, 0xec, + 0x7c, 0xf8, 0xf5, 0xfe, 0x9c, 0xff, 0xe0, 0x07, 0x8a, 0x0f, 0x0a, 0x09, + 0xdd, 0x06, 0x54, 0x02, 0xbc, 0xf5, 0xb6, 0x03, 0x1d, 0x1b, 0x38, 0x26, + 0x02, 0x23, 0x3e, 0x0d, 0x9f, 0x02, 0xd8, 0x0e, 0x99, 0x00, 0x75, 0xe4, + 0x39, 0xe4, 0xe7, 0xf3, 0x70, 0x03, 0x1c, 0xea, 0x8d, 0xc7, 0xe4, 0xcd, + 0x6f, 0xe8, 0x70, 0xfd, 0x56, 0xfa, 0x55, 0xf0, 0x05, 0xf6, 0xc0, 0xfe, + 0xfd, 0xf0, 0x92, 0xda, 0x63, 0xe7, 0x22, 0x0b, 0xd2, 0x1b, 0xc6, 0x29, + 0xe9, 0x2a, 0x95, 0x20, 0xff, 0x27, 0xd1, 0x2f, 0x47, 0x49, 0xb2, 0x56, + 0x33, 0x39, 0xc4, 0x1c, 0xf4, 0x15, 0xfc, 0x1b, 0x8e, 0x1a, 0x76, 0x0c, + 0xa7, 0x14, 0x65, 0x28, 0x7e, 0x12, 0xe1, 0xed, 0x0c, 0xe6, 0x8d, 0x07, + 0xd3, 0x23, 0xa5, 0x11, 0x98, 0xe0, 0x3a, 0xb2, 0xbc, 0xaf, 0x68, 0xbe, + 0xd5, 0xcf, 0x04, 0xd7, 0xf5, 0xcf, 0x36, 0xd3, 0x15, 0xdb, 0x35, 0xe9, + 0xa8, 0xec, 0x04, 0xeb, 0xc7, 0xf9, 0x7e, 0x0e, 0xd1, 0x18, 0x2c, 0x13, + 0xb4, 0x01, 0x88, 0xfa, 0xf2, 0x06, 0xc4, 0x17, 0x64, 0x24, 0x84, 0x26, + 0x4e, 0x2c, 0x59, 0x2f, 0x79, 0x2a, 0xd0, 0x30, 0xc2, 0x31, 0x19, 0x12, + 0x88, 0xf0, 0xdc, 0xf7, 0x13, 0x15, 0xaf, 0x2c, 0x41, 0x2e, 0xd3, 0x1c, + 0xa4, 0x11, 0xd5, 0x0c, 0x34, 0x0e, 0x58, 0x25, 0xc8, 0x33, 0xc4, 0x17, + 0x05, 0xf2, 0x00, 0xf6, 0x89, 0x29, 0xdc, 0x57, 0x65, 0x4e, 0xf2, 0x1b, + 0xe6, 0x03, 0xcf, 0x05, 0xd7, 0x02, 0x48, 0x03, 0x2c, 0x01, 0xa6, 0x14, + 0x24, 0x2e, 0x2c, 0x1d, 0x6d, 0x03, 0x86, 0x11, 0x87, 0x2f, 0xe4, 0x2c, + 0x59, 0x0d, 0x20, 0xf5, 0x75, 0xf8, 0x00, 0x0a, 0xa4, 0x09, 0xc6, 0xeb, + 0xe4, 0xcb, 0x8c, 0xbe, 0x07, 0xc8, 0x38, 0xd3, 0xb2, 0xc8, 0xbe, 0xba, + 0xb6, 0xc1, 0xef, 0xdb, 0x1f, 0xe2, 0xd2, 0xdc, 0x92, 0xe5, 0x4e, 0xef, + 0x67, 0xfe, 0x37, 0x01, 0x93, 0xea, 0x64, 0xd6, 0x97, 0xde, 0x0d, 0x04, + 0xcd, 0x2c, 0xee, 0x3a, 0x38, 0x23, 0xd8, 0x02, 0xdf, 0x0a, 0x2a, 0x31, + 0x19, 0x4e, 0x7e, 0x58, 0xa0, 0x54, 0x50, 0x4b, 0xb7, 0x38, 0x78, 0x31, + 0x3d, 0x43, 0x04, 0x51, 0xe6, 0x48, 0xdb, 0x26, 0x29, 0x0e, 0x29, 0x14, + 0x44, 0x23, 0xb8, 0x22, 0x54, 0x03, 0x31, 0xe7, 0xfe, 0xe6, 0xaa, 0xf0, + 0x2c, 0xea, 0xb1, 0xd6, 0x04, 0xe0, 0x47, 0xfa, 0x4c, 0xfd, 0x1c, 0xfb, + 0x32, 0xee, 0x6c, 0xd7, 0x46, 0xe9, 0x26, 0x0a, 0xd1, 0x14, 0x5e, 0x0d, + 0xca, 0x06, 0x35, 0x10, 0xf1, 0x13, 0x1c, 0x0e, 0x01, 0x06, 0x5b, 0x14, + 0x31, 0x29, 0xfd, 0x19, 0x1e, 0x02, 0xd1, 0xf7, 0x76, 0xee, 0xac, 0xf4, + 0xbd, 0x03, 0xcf, 0xf0, 0x8b, 0xe3, 0xeb, 0xe0, 0x51, 0xd1, 0x5a, 0xe2, + 0x5f, 0x08, 0x94, 0x0e, 0x87, 0xf4, 0xda, 0xe9, 0xcf, 0xfd, 0x7a, 0x1b, + 0x02, 0x1c, 0x91, 0xfa, 0x21, 0xea, 0x12, 0x00, 0x1b, 0x26, 0xa9, 0x40, + 0x8f, 0x3e, 0x3b, 0x2c, 0x61, 0x2a, 0x81, 0x25, 0x3a, 0x1c, 0xa1, 0x1f, + 0x26, 0x1b, 0x39, 0x14, 0x40, 0x0e, 0xd7, 0xf9, 0x73, 0xe4, 0x2e, 0xeb, + 0x74, 0xff, 0x36, 0x00, 0xed, 0xe7, 0x1d, 0xd4, 0xa4, 0xdc, 0xf3, 0xec, + 0x71, 0xe3, 0xee, 0xd1, 0x02, 0xd2, 0x36, 0xc8, 0xf6, 0xb8, 0x79, 0xc1, + 0xa2, 0xda, 0x89, 0xe8, 0x49, 0xde, 0x1f, 0xcb, 0x5e, 0xd4, 0xc1, 0xe6, + 0x88, 0xe6, 0xdd, 0xf0, 0xae, 0xf7, 0xd8, 0xf4, 0xee, 0xed, 0x5c, 0xf2, + 0xee, 0x10, 0xfa, 0x22, 0x1e, 0x16, 0xfd, 0x06, 0x0b, 0x0b, 0xc5, 0x0e, + 0x18, 0x0a, 0xa9, 0x05, 0x5b, 0x03, 0x43, 0x0e, 0x62, 0x19, 0xec, 0x06, + 0xd9, 0xef, 0x36, 0xec, 0xa9, 0xfa, 0x7b, 0x0a, 0x02, 0x08, 0x11, 0xfd, + 0xf2, 0xde, 0xed, 0xd0, 0x71, 0xe6, 0xfc, 0xf2, 0xbc, 0xe3, 0xd3, 0xd5, + 0x43, 0xe0, 0xeb, 0xe9, 0x67, 0xee, 0x8f, 0xe4, 0x51, 0xe3, 0xb5, 0xf0, + 0xe9, 0xeb, 0x11, 0xef, 0x12, 0x01, 0x5b, 0x02, 0x84, 0x02, 0xf5, 0x09, + 0x28, 0x01, 0xb2, 0xfe, 0xce, 0xe9, 0x68, 0xcd, 0xd1, 0xd5, 0xee, 0xf2, + 0x0e, 0x18, 0xd3, 0x11, 0x30, 0xe9, 0x16, 0xd5, 0x6b, 0xdc, 0x59, 0xe3, + 0x3c, 0xdd, 0x29, 0xdd, 0xd5, 0xe2, 0x36, 0xd9, 0x92, 0xbb, 0x4e, 0xad, + 0xf7, 0xb7, 0x7c, 0xce, 0x24, 0xdc, 0xed, 0xd9, 0x50, 0xd2, 0x87, 0xdb, + 0xc1, 0xfd, 0x6b, 0x07, 0xe8, 0xf2, 0x0a, 0xe1, 0xed, 0xd8, 0x4f, 0xe9, + 0x6d, 0x12, 0xa8, 0x24, 0x7e, 0x1c, 0xfb, 0x10, 0xd1, 0x1d, 0x91, 0x3f, + 0x98, 0x46, 0x1b, 0x44, 0xec, 0x42, 0xd6, 0x4b, 0xfa, 0x46, 0xf4, 0x3d, + 0xf1, 0x50, 0x18, 0x50, 0x6f, 0x3d, 0x2f, 0x21, 0x9c, 0x08, 0x77, 0x09, + 0xaf, 0x1d, 0xb2, 0x1b, 0xcc, 0xff, 0xde, 0xff, 0xf1, 0x1d, 0x22, 0x24, + 0x8f, 0x06, 0xc6, 0x07, 0xc3, 0x02, 0xba, 0xeb, 0xee, 0xfd, 0x4a, 0x14, + 0xc0, 0x15, 0x79, 0x12, 0x75, 0x12, 0xa5, 0x1e, 0xad, 0x2e, 0x24, 0x26, + 0x63, 0x0e, 0x04, 0x06, 0x09, 0x1b, 0x33, 0x23, 0xeb, 0x19, 0x4d, 0x17, + 0x37, 0x0e, 0x2d, 0x11, 0x41, 0x11, 0x7d, 0x10, 0xfb, 0x11, 0x06, 0x0a, + 0x20, 0xf9, 0xca, 0xe3, 0xe6, 0xe7, 0xde, 0x0f, 0xdf, 0x35, 0x97, 0x1d, + 0xdc, 0xfc, 0x04, 0xfa, 0x69, 0xfc, 0x9b, 0x0f, 0xae, 0x1d, 0x96, 0x23, + 0x4b, 0x29, 0x57, 0x2e, 0xf3, 0x34, 0xa1, 0x43, 0x0f, 0x4f, 0x0e, 0x44, + 0x86, 0x37, 0x32, 0x2c, 0x7b, 0x2e, 0x37, 0x40, 0x33, 0x45, 0x82, 0x38, + 0xf8, 0x1e, 0x90, 0x0c, 0xe0, 0x07, 0x3f, 0x14, 0x13, 0x1a, 0x69, 0x07, + 0xb1, 0xfd, 0xaa, 0xfd, 0xd9, 0x04, 0x5e, 0x09, 0x03, 0xfd, 0x6b, 0xf3, + 0xad, 0xf6, 0x47, 0xfd, 0x2d, 0x03, 0x7c, 0x04, 0xff, 0x00, 0x2f, 0x0c, + 0x16, 0x13, 0x0e, 0x06, 0x6e, 0x06, 0x88, 0x23, 0x97, 0x40, 0x05, 0x39, + 0x48, 0x12, 0x4e, 0xed, 0xc0, 0xef, 0xb9, 0x1f, 0x8d, 0x41, 0xd3, 0x31, + 0xd2, 0x15, 0x89, 0x0a, 0x66, 0x0e, 0x80, 0x1f, 0x74, 0x37, 0x89, 0x32, + 0xac, 0x17, 0x58, 0x14, 0x60, 0x1a, 0xa3, 0x0f, 0xfe, 0xf9, 0x05, 0xf1, + 0x01, 0xff, 0x3d, 0x0f, 0xc6, 0x08, 0x9c, 0xf6, 0xc9, 0xf8, 0x50, 0x0b, + 0x78, 0x0e, 0x4c, 0x02, 0xb6, 0xf5, 0x04, 0xf2, 0x9a, 0xf9, 0x54, 0x04, + 0x19, 0x1a, 0x84, 0x1a, 0x57, 0x07, 0x17, 0x02, 0x17, 0xfd, 0xe0, 0xfc, + 0x9f, 0x07, 0x22, 0x0a, 0x27, 0x00, 0x65, 0x1a, 0xe3, 0x45, 0x0f, 0x3b, + 0xb8, 0x04, 0x2f, 0xe8, 0x43, 0xff, 0x75, 0x2a, 0xc3, 0x41, 0x1a, 0x2b, + 0x22, 0x18, 0x9b, 0x0f, 0x0a, 0xfe, 0x25, 0xf4, 0x7c, 0xe9, 0x44, 0xf2, + 0x62, 0xfd, 0xe3, 0xea, 0xfc, 0xdb, 0x68, 0xd3, 0x3d, 0xd0, 0x09, 0xe1, + 0x2b, 0xe1, 0x87, 0xd0, 0xd3, 0xca, 0x89, 0xd7, 0x11, 0xea, 0x13, 0xec, + 0xd0, 0xe5, 0x63, 0xe8, 0x8d, 0xf1, 0x26, 0xe9, 0x20, 0xdd, 0xac, 0xec, + 0xe2, 0x05, 0xd6, 0x05, 0xf1, 0x11, 0x3c, 0x26, 0xc3, 0x1a, 0x73, 0x21, + 0x2a, 0x35, 0x8a, 0x3b, 0x24, 0x35, 0x3a, 0x2a, 0x63, 0x27, 0xcd, 0x2d, + 0x1c, 0x36, 0x53, 0x27, 0x91, 0x11, 0x6d, 0xff, 0xea, 0xf8, 0xa7, 0x01, + 0x83, 0x07, 0xc7, 0x06, 0xa8, 0xfb, 0x76, 0xf4, 0x75, 0xf2, 0x7b, 0xec, + 0xb9, 0xed, 0x3a, 0xeb, 0x30, 0xe6, 0xfb, 0xf6, 0xb2, 0x0a, 0x4b, 0x11, + 0xdf, 0x1c, 0xf8, 0x21, 0x2b, 0x14, 0x94, 0x09, 0xfe, 0x03, 0x14, 0x0a, + 0x97, 0x18, 0x6d, 0x13, 0x7d, 0x04, 0x11, 0x04, 0xb2, 0x06, 0x23, 0xf1, + 0x5f, 0xdf, 0xec, 0xe6, 0x0f, 0xef, 0xba, 0xf1, 0xd8, 0xdf, 0x97, 0xc4, + 0x23, 0xd9, 0xb1, 0x02, 0x32, 0xfb, 0xfa, 0xdb, 0x57, 0xd1, 0x96, 0xd1, + 0x6d, 0xe2, 0x0a, 0x00, 0x4d, 0xf8, 0xf5, 0xda, 0x50, 0xd9, 0x04, 0xfc, + 0x25, 0x1e, 0x50, 0x22, 0x41, 0x1b, 0x8a, 0x10, 0x3c, 0x18, 0xaf, 0x1e, + 0x91, 0x1c, 0x10, 0x21, 0x87, 0x0b, 0x58, 0xec, 0x1e, 0xe7, 0x52, 0xff, + 0xcd, 0x1c, 0xb8, 0x11, 0xdb, 0xe0, 0xed, 0xd6, 0xef, 0xf3, 0x48, 0x07, + 0x22, 0xff, 0xaa, 0xdf, 0x89, 0xdc, 0x8e, 0xe7, 0xa2, 0xe3, 0x03, 0xe2, + 0xff, 0xdc, 0xcc, 0xdf, 0x3c, 0xf5, 0x0e, 0xf7, 0x13, 0xe4, 0x29, 0xd3, + 0x0f, 0xd2, 0xd5, 0xf2, 0x06, 0x0f, 0x06, 0x0d, 0x75, 0x00, 0x5a, 0xfc, + 0xaa, 0xf4, 0xb9, 0xe7, 0xd7, 0xee, 0xcf, 0xfa, 0x62, 0x01, 0x93, 0xfd, + 0xba, 0xe7, 0xd3, 0xdb, 0x73, 0xdc, 0x77, 0xd1, 0xe8, 0xcc, 0xf2, 0xd7, + 0x2f, 0xe4, 0x02, 0xe7, 0x2b, 0xd8, 0x61, 0xcb, 0xc7, 0xd1, 0x15, 0xde, + 0x6c, 0xe8, 0xc2, 0xe7, 0x83, 0xdc, 0x2f, 0xd6, 0x60, 0xc8, 0x7f, 0xcd, + 0xc2, 0xe4, 0xb0, 0xe9, 0x35, 0xee, 0xf0, 0xf3, 0xad, 0xf6, 0xc8, 0xf4, + 0x90, 0xf2, 0xde, 0x04, 0xe3, 0x27, 0xfb, 0x31, 0x70, 0x19, 0x81, 0x05, + 0xfe, 0x08, 0x5f, 0x12, 0xb8, 0x11, 0x7b, 0x10, 0x5b, 0x1d, 0xe6, 0x26, + 0xd7, 0x0e, 0xe5, 0x05, 0x63, 0x15, 0xfe, 0x1d, 0xa3, 0x24, 0x5f, 0x15, + 0x7a, 0x00, 0x26, 0xf4, 0xa9, 0xe8, 0x81, 0xd5, 0xc2, 0xbb, 0x6a, 0xb5, + 0x92, 0xc6, 0xa0, 0xc7, 0x0c, 0xb1, 0x5d, 0xa4, 0x75, 0xac, 0x0f, 0xc9, + 0xe2, 0xd2, 0x07, 0xc6, 0x75, 0xbd, 0x53, 0xc0, 0x60, 0xd1, 0x95, 0xd9, + 0x94, 0xd5, 0xc3, 0xd3, 0xd0, 0xde, 0x4d, 0xed, 0xfb, 0xed, 0x1b, 0xe2, + 0xd7, 0xe4, 0x94, 0x08, 0x16, 0x28, 0x21, 0x20, 0xc9, 0x11, 0xdf, 0x0a, + 0x61, 0x00, 0x39, 0x09, 0xa8, 0x11, 0xb1, 0x0f, 0xe8, 0x0d, 0xc1, 0x12, + 0xf0, 0x1a, 0x78, 0x0a, 0xc6, 0xe6, 0x8d, 0xd4, 0x95, 0xe8, 0xe9, 0xfa, + 0x6c, 0xf7, 0x69, 0xef, 0x94, 0xe7, 0xfe, 0xde, 0x6f, 0xe3, 0x42, 0xf2, + 0xff, 0xee, 0x26, 0xf3, 0x4b, 0x05, 0xdf, 0x11, 0x39, 0x0c, 0x3f, 0xf7, + 0x7c, 0xf1, 0x8e, 0x01, 0x19, 0x1a, 0x35, 0x1f, 0xc9, 0x10, 0xd5, 0xfd, + 0xde, 0xf0, 0xdf, 0xdf, 0x3d, 0xd0, 0x31, 0xe2, 0x5f, 0xe7, 0x5a, 0xd5, + 0xb9, 0xd7, 0x16, 0xdc, 0x83, 0xd2, 0xb8, 0xca, 0x85, 0xca, 0xd6, 0xca, + 0xf4, 0xd5, 0x0f, 0xe7, 0x69, 0xe6, 0x97, 0xd8, 0xd6, 0xc7, 0x23, 0xbb, + 0xe3, 0xc3, 0x94, 0xe5, 0x00, 0x03, 0x4c, 0x07, 0xf5, 0xfb, 0xc1, 0xf7, + 0x58, 0x07, 0xea, 0x29, 0x0a, 0x46, 0x44, 0x37, 0xea, 0x20, 0xb3, 0x27, + 0xd0, 0x37, 0xcd, 0x35, 0xd0, 0x1d, 0xdc, 0x0e, 0x56, 0x0e, 0x49, 0x14, + 0x6f, 0x1e, 0x63, 0x1c, 0x06, 0x14, 0x82, 0x11, 0xae, 0x08, 0x64, 0x08, + 0x82, 0x14, 0xb0, 0x17, 0xfc, 0x09, 0x67, 0xe6, 0xe8, 0xe1, 0x6a, 0x03, + 0x6d, 0x19, 0xb9, 0x1a, 0xd5, 0x0e, 0x52, 0x12, 0xaa, 0x15, 0x17, 0x09, + 0x5f, 0x01, 0xbd, 0xfc, 0x01, 0x02, 0x31, 0x11, 0x4c, 0x11, 0x5d, 0x08, + 0x81, 0xf7, 0xd0, 0xe5, 0x89, 0xe9, 0xb9, 0xf6, 0x0d, 0x08, 0xa1, 0x07, + 0x8b, 0xf1, 0xdc, 0xe4, 0x78, 0xf3, 0x5a, 0x06, 0x0d, 0xf8, 0x60, 0xdc, + 0x5e, 0xd3, 0xe6, 0xe3, 0x7f, 0xf2, 0x13, 0xef, 0xb7, 0xe3, 0xe7, 0xea, + 0xef, 0xfb, 0xb1, 0xf2, 0x38, 0xf7, 0xa5, 0x1a, 0x0a, 0x2f, 0xf6, 0x27, + 0xd6, 0x1a, 0x3e, 0x02, 0x34, 0xfd, 0x3c, 0x24, 0x67, 0x42, 0x4f, 0x3f, + 0x19, 0x22, 0xfa, 0x15, 0x11, 0x2f, 0x9b, 0x3e, 0x53, 0x2f, 0x49, 0x25, + 0x4b, 0x36, 0x11, 0x39, 0xe2, 0x27, 0x6f, 0x1f, 0x7d, 0x17, 0x87, 0x1b, + 0x6f, 0x31, 0xdb, 0x3c, 0x0c, 0x3a, 0x76, 0x22, 0xfc, 0x03, 0x3f, 0xfd, + 0x89, 0xfa, 0xa1, 0xef, 0x3b, 0xec, 0xf2, 0xe5, 0x99, 0xd5, 0xa7, 0xc6, + 0x65, 0xc6, 0x7e, 0xdc, 0x73, 0xeb, 0x8e, 0xdd, 0xaf, 0xc4, 0x0f, 0xc4, + 0xbd, 0xdb, 0x8f, 0xf3, 0x0d, 0xfa, 0xb4, 0xec, 0x4b, 0xea, 0xfd, 0xfb, + 0xe4, 0x0a, 0x2d, 0xfb, 0x90, 0xeb, 0x7f, 0xfa, 0x85, 0x13, 0xf6, 0x2b, + 0x64, 0x35, 0x7f, 0x31, 0x31, 0x32, 0x3c, 0x39, 0xcf, 0x3c, 0x90, 0x3c, + 0x06, 0x2d, 0x07, 0x22, 0x74, 0x2d, 0x18, 0x32, 0x5d, 0x30, 0x80, 0x2e, + 0x2b, 0x27, 0xe0, 0x15, 0x19, 0x01, 0x6f, 0xf5, 0xb6, 0x01, 0x86, 0x16, + 0xa5, 0x15, 0xdb, 0x00, 0xb8, 0xea, 0x00, 0xe5, 0x0c, 0xf5, 0xa3, 0x16, + 0xa9, 0x2c, 0x5c, 0x2d, 0x76, 0x1e, 0xb5, 0x18, 0x8c, 0x2f, 0x5e, 0x40, + 0x0d, 0x37, 0xcf, 0x1b, 0x1c, 0x00, 0xa6, 0xf6, 0x1e, 0x02, 0x28, 0xfb, + 0xde, 0xda, 0xa4, 0xce, 0x87, 0xe2, 0xda, 0xf5, 0xf0, 0xee, 0xce, 0xde, + 0xb0, 0xd5, 0x4b, 0xd6, 0xcd, 0xd9, 0xfd, 0xda, 0xde, 0xdd, 0x1e, 0xed, + 0xc5, 0xf5, 0x76, 0xe6, 0x33, 0xd9, 0xd4, 0xd9, 0x11, 0xfa, 0xa1, 0x28, + 0xc3, 0x23, 0xe0, 0x04, 0x43, 0x16, 0x19, 0x3b, 0x54, 0x4b, 0xce, 0x47, + 0x5f, 0x2f, 0xe7, 0x29, 0x25, 0x40, 0xb6, 0x51, 0x51, 0x56, 0x87, 0x48, + 0x44, 0x31, 0x49, 0x28, 0x2f, 0x2b, 0x9b, 0x28, 0xce, 0x11, 0xd1, 0xfe, + 0xc2, 0x15, 0x7a, 0x39, 0xe2, 0x35, 0x9a, 0x16, 0x81, 0x05, 0x78, 0xff, + 0xb1, 0xf8, 0x7e, 0xed, 0x57, 0xec, 0x51, 0x05, 0x4c, 0x1c, 0xc6, 0x0d, + 0xed, 0xe5, 0xc6, 0xd4, 0xd5, 0xe4, 0x62, 0xf9, 0x26, 0xf7, 0x31, 0xeb, + 0x44, 0xe1, 0xad, 0xe5, 0x87, 0xf9, 0xeb, 0xfb, 0xb6, 0xf1, 0x18, 0xeb, + 0xd5, 0xef, 0x8b, 0xe8, 0xdc, 0xdb, 0x54, 0xdb, 0x19, 0xd3, 0x47, 0xce, + 0x1e, 0xd7, 0x38, 0xdc, 0x2d, 0xd6, 0xd5, 0xe6, 0x3d, 0xfa, 0x5c, 0xfb, + 0xc3, 0xfa, 0xf4, 0xf5, 0x2d, 0xf4, 0x92, 0xf7, 0xb7, 0x06, 0x67, 0x10, + 0xe1, 0x15, 0xd8, 0x24, 0x7e, 0x26, 0xd7, 0x0c, 0x45, 0x06, 0xd0, 0x24, + 0x93, 0x2f, 0x67, 0x2b, 0xca, 0x1f, 0x9f, 0x19, 0xb0, 0x29, 0xf6, 0x2d, + 0xdc, 0x2e, 0x64, 0x3a, 0xc7, 0x39, 0x4c, 0x25, 0xa3, 0x17, 0x61, 0x17, + 0x7c, 0x1a, 0x6f, 0x24, 0x1c, 0x31, 0xd7, 0x3f, 0xf1, 0x42, 0xb1, 0x29, + 0xa6, 0x0b, 0xe1, 0x04, 0x8a, 0x16, 0x7d, 0x1c, 0x20, 0x00, 0x19, 0xf3, + 0xf8, 0xf9, 0x26, 0xe6, 0xa5, 0xca, 0xce, 0xc0, 0xf8, 0xc2, 0x6d, 0xdb, + 0x57, 0xf1, 0x07, 0xdc, 0x6a, 0xbf, 0xfb, 0xc5, 0xae, 0xe3, 0x5c, 0xf3, + 0x1d, 0xed, 0x7e, 0xe6, 0x03, 0xdf, 0xad, 0xdf, 0xdd, 0xe4, 0xbf, 0xde, + 0xc6, 0xde, 0x0b, 0xec, 0xe7, 0x00, 0x05, 0x0e, 0x29, 0x17, 0x6a, 0x21, + 0x15, 0x20, 0x18, 0x2c, 0x02, 0x36, 0x30, 0x26, 0xaa, 0x18, 0x54, 0x22, + 0xa2, 0x35, 0xd4, 0x34, 0xe4, 0x23, 0xa3, 0x0a, 0x2c, 0xfd, 0x5c, 0x05, + 0xa1, 0x13, 0xd7, 0x10, 0xd3, 0xf4, 0x98, 0xe7, 0x59, 0xf7, 0x73, 0x0e, + 0xe8, 0x13, 0xbb, 0x16, 0xbc, 0x1f, 0x7b, 0x1c, 0xb5, 0x17, 0xc5, 0x13, + 0xe3, 0x13, 0x00, 0x1e, 0x6e, 0x33, 0x6b, 0x3f, 0x8c, 0x29, 0x34, 0xfe, + 0xd6, 0xe5, 0xf4, 0xf6, 0xd6, 0x14, 0x7b, 0x1a, 0x2d, 0xfb, 0x76, 0xda, + 0x44, 0xd4, 0xaf, 0xda, 0xa6, 0xef, 0x3e, 0xfc, 0x94, 0xea, 0xe3, 0xed, + 0x9e, 0x00, 0x96, 0xf6, 0x54, 0xeb, 0x34, 0xe0, 0xad, 0xe2, 0x83, 0x0d, + 0x40, 0x24, 0x5f, 0x0c, 0x27, 0xf8, 0x1d, 0xfe, 0x9b, 0x1e, 0x09, 0x3f, + 0x7f, 0x43, 0xec, 0x3d, 0x39, 0x35, 0x1c, 0x37, 0x4c, 0x46, 0xcc, 0x3c, + 0x27, 0x26, 0x68, 0x21, 0x01, 0x2b, 0xfd, 0x3a, 0xe5, 0x33, 0x23, 0x18, + 0x9c, 0x0e, 0x23, 0x11, 0xf6, 0x12, 0x4d, 0x11, 0x14, 0x01, 0x81, 0xee, + 0x91, 0xf8, 0xe5, 0x0a, 0x44, 0x02, 0x0e, 0xe8, 0xc7, 0xcf, 0x5c, 0xd3, + 0xfa, 0xe4, 0x5d, 0xe7, 0x8d, 0xe5, 0x1d, 0xe0, 0xaa, 0xdd, 0x79, 0xe8, + 0xb9, 0xee, 0x80, 0xe8, 0x05, 0xe0, 0x52, 0xe2, 0x01, 0xed, 0xef, 0xec, + 0xa9, 0xd9, 0xc2, 0xc9, 0x5c, 0xd4, 0x7b, 0xed, 0x88, 0xfd, 0x90, 0xf5, + 0xa1, 0xe6, 0x23, 0xdb, 0x07, 0xd5, 0x72, 0xdf, 0x88, 0xe6, 0x98, 0xe0, + 0xc0, 0xdc, 0xe1, 0xeb, 0xf4, 0xf6, 0x57, 0xec, 0xf6, 0xe0, 0x1a, 0xdc, + 0xf2, 0xe7, 0xf9, 0xfe, 0xa2, 0x0b, 0xa4, 0x00, 0x7c, 0xf2, 0xd1, 0xf3, + 0xf7, 0xfa, 0x5d, 0x05, 0x60, 0x08, 0x40, 0x0c, 0xe5, 0x15, 0x0c, 0x12, + 0xbb, 0x0b, 0xe6, 0x0f, 0x43, 0x0f, 0x7d, 0x0e, 0x39, 0x0c, 0x26, 0x02, + 0x9f, 0x04, 0x0d, 0x09, 0x63, 0x04, 0xe9, 0xf1, 0xbf, 0xdd, 0x97, 0xe7, + 0xbf, 0xfd, 0xef, 0x10, 0x99, 0x12, 0x59, 0x01, 0x4a, 0x03, 0x42, 0x12, + 0x59, 0x04, 0xf0, 0xd6, 0x12, 0xbf, 0x2e, 0xce, 0x50, 0xd3, 0x18, 0xbd, + 0x8b, 0xad, 0x34, 0xae, 0x18, 0xb6, 0xf3, 0xb9, 0xd7, 0xb4, 0x46, 0xbb, + 0xf5, 0xba, 0x5d, 0xb6, 0x60, 0xbd, 0xcf, 0xc9, 0x21, 0xde, 0x54, 0xd8, + 0xbe, 0xcb, 0xa4, 0xd9, 0xd5, 0xe6, 0xf3, 0xe6, 0x25, 0xe4, 0xa0, 0xf1, + 0xc3, 0x0d, 0xa6, 0x1d, 0xcb, 0x16, 0xe0, 0x16, 0xe6, 0x22, 0x74, 0x27, + 0xc8, 0x24, 0xa5, 0x14, 0xa9, 0x09, 0x45, 0x1d, 0x29, 0x35, 0x25, 0x2d, + 0x1c, 0x0e, 0x28, 0xf9, 0x59, 0xfa, 0x0e, 0x07, 0x1b, 0x0c, 0x96, 0xfd, + 0x8c, 0xed, 0x93, 0xf6, 0x9b, 0x12, 0xdf, 0x22, 0xdb, 0x18, 0x40, 0x07, + 0x7a, 0x0b, 0x5e, 0x2e, 0x26, 0x4c, 0xe8, 0x45, 0xcd, 0x2f, 0x42, 0x26, + 0x5d, 0x2c, 0x3c, 0x37, 0x53, 0x35, 0x26, 0x27, 0x8b, 0x1d, 0x31, 0x17, + 0x8f, 0x0e, 0x66, 0x05, 0xa2, 0x06, 0xed, 0x04, 0x54, 0xf9, 0x8e, 0xfe, + 0xe7, 0x03, 0xb4, 0xf5, 0x4a, 0xf5, 0xe9, 0x0c, 0x54, 0x14, 0xa7, 0x07, + 0xf7, 0xf6, 0x4d, 0xf2, 0xe8, 0x0c, 0xa6, 0x26, 0xdc, 0x29, 0x74, 0x1e, + 0xbf, 0x1c, 0x9e, 0x31, 0x90, 0x44, 0xa7, 0x47, 0xbd, 0x44, 0x66, 0x4a, + 0x2c, 0x50, 0x2b, 0x52, 0x1e, 0x4e, 0x3f, 0x46, 0x1a, 0x43, 0xc7, 0x39, + 0x64, 0x2d, 0x9a, 0x25, 0x62, 0x1c, 0x60, 0x0c, 0xe7, 0x00, 0x51, 0x00, + 0x3c, 0x06, 0x65, 0x0a, 0x14, 0x08, 0xba, 0x02, 0x2a, 0xfe, 0x6c, 0xfa, + 0xe1, 0xf0, 0x30, 0xf3, 0xe1, 0x04, 0x1f, 0x11, 0x0a, 0x0b, 0x51, 0xf9, + 0xdd, 0xf0, 0x6e, 0xf0, 0x06, 0xf7, 0xb2, 0x04, 0x3d, 0x0f, 0x9d, 0x09, + 0xd2, 0x02, 0x4d, 0x0e, 0x53, 0x1c, 0x55, 0x20, 0x32, 0x1b, 0xf1, 0x18, + 0xf3, 0x22, 0xda, 0x28, 0x16, 0x13, 0xd1, 0xfc, 0xe1, 0x01, 0x53, 0x10, + 0x2d, 0x0b, 0xbb, 0xee, 0x38, 0xed, 0x79, 0x04, 0x2b, 0x0c, 0x3e, 0x0d, + 0xce, 0x06, 0x3d, 0xf9, 0x8f, 0xf4, 0xad, 0xf5, 0xda, 0x00, 0xa2, 0x11, + 0x75, 0x10, 0x59, 0x09, 0xdd, 0x07, 0x3d, 0x07, 0x18, 0x0f, 0x93, 0x16, + 0xb4, 0x14, 0x6d, 0x18, 0x9f, 0x26, 0xe6, 0x2e, 0xa2, 0x21, 0x37, 0x09, + 0xc3, 0x0a, 0x64, 0x2e, 0xb1, 0x40, 0xd4, 0x25, 0x65, 0x18, 0x4d, 0x2b, + 0x57, 0x31, 0xe9, 0x2c, 0x34, 0x29, 0x1a, 0x1f, 0xfa, 0x14, 0x98, 0x1e, + 0xc6, 0x36, 0xc1, 0x3b, 0xdf, 0x21, 0x8a, 0x00, 0x7f, 0xf9, 0xe4, 0xf5, + 0xe1, 0xe0, 0xc6, 0xe4, 0xdc, 0xf2, 0x52, 0xe3, 0x78, 0xc9, 0x1c, 0xba, + 0xc2, 0xba, 0x44, 0xca, 0x3c, 0xd3, 0x21, 0xd4, 0x86, 0xda, 0x03, 0xd9, + 0xfe, 0xe0, 0x44, 0xf1, 0x78, 0xf8, 0x13, 0xfb, 0xc8, 0xe5, 0x7e, 0xdf, + 0xfb, 0xf4, 0x95, 0x05, 0xee, 0x15, 0x09, 0x1a, 0xa5, 0x14, 0xf2, 0x1c, + 0x4e, 0x30, 0x43, 0x2e, 0x70, 0x15, 0x0e, 0x01, 0x0c, 0x0a, 0x6a, 0x25, + 0xc9, 0x25, 0x28, 0x12, 0x18, 0xfa, 0x78, 0xee, 0x25, 0xfe, 0xca, 0x05, + 0x5e, 0xf6, 0x96, 0xdf, 0x8c, 0xd1, 0xd9, 0xe5, 0x7f, 0x03, 0x66, 0x00, + 0x30, 0xfd, 0xfd, 0x07, 0x4b, 0x03, 0x1a, 0xf9, 0xf1, 0xff, 0xbf, 0x19, + 0x84, 0x3d, 0x19, 0x51, 0xe9, 0x4a, 0x1c, 0x3f, 0x89, 0x2f, 0x8b, 0x1f, + 0x86, 0x24, 0x49, 0x2d, 0xb6, 0x1b, 0x3f, 0x05, 0xcd, 0x00, 0xaf, 0x11, + 0x51, 0x22, 0x47, 0x10, 0x7e, 0xf2, 0xda, 0xe9, 0xeb, 0xf9, 0x26, 0x01, + 0x53, 0xf3, 0x39, 0xf4, 0xd0, 0x00, 0xb3, 0x09, 0xaf, 0x0b, 0xca, 0x03, + 0x89, 0x06, 0x7d, 0x16, 0xff, 0x10, 0x08, 0x0b, 0x07, 0x11, 0x1c, 0x0b, + 0xb6, 0x15, 0x2a, 0x2a, 0x8f, 0x26, 0x0f, 0x1e, 0xdb, 0x28, 0xd3, 0x24, + 0x1b, 0x10, 0xc0, 0x0a, 0x3a, 0x07, 0x95, 0x03, 0xe6, 0xf7, 0x2b, 0xe6, + 0x87, 0xd8, 0x68, 0xd1, 0xba, 0xd5, 0x6a, 0xde, 0x61, 0xd7, 0xf9, 0xba, + 0xea, 0xb4, 0x3c, 0xca, 0xbf, 0xdb, 0xef, 0xd9, 0x5d, 0xd0, 0xc8, 0xd3, + 0x02, 0xdf, 0x07, 0xe0, 0xc7, 0xd2, 0x89, 0xd6, 0x27, 0xea, 0x01, 0xf7, + 0x33, 0xf7, 0x87, 0xed, 0xc4, 0xf1, 0xf6, 0x02, 0x29, 0x03, 0xc8, 0xfa, + 0x63, 0xfd, 0xcb, 0x04, 0x4d, 0x10, 0xff, 0x0d, 0x35, 0xfc, 0x27, 0xf7, + 0x75, 0x06, 0xa7, 0x0d, 0x16, 0xf4, 0x49, 0xd5, 0x85, 0xce, 0x0a, 0xd9, + 0xde, 0xeb, 0x70, 0xfe, 0x77, 0xf3, 0x3f, 0xd5, 0x52, 0xc6, 0xfd, 0xc6, + 0x7e, 0xcb, 0x32, 0xd3, 0x98, 0xe3, 0xc4, 0xeb, 0xaa, 0xe8, 0x86, 0xdf, + 0x63, 0xdf, 0xf1, 0xf0, 0xee, 0xef, 0x27, 0xe2, 0x7d, 0xdc, 0xd0, 0xce, + 0x25, 0xd1, 0x64, 0xf0, 0x04, 0x06, 0x47, 0x0c, 0x98, 0xfe, 0x13, 0xe7, + 0xd2, 0xe7, 0x35, 0xf6, 0x25, 0x0d, 0x56, 0x1f, 0xf4, 0x10, 0x5f, 0xf8, + 0x41, 0xf1, 0xe0, 0xfa, 0xac, 0x0b, 0xbf, 0x16, 0x96, 0x13, 0xf0, 0x09, + 0xcd, 0xfb, 0x59, 0xdc, 0x70, 0xd2, 0xad, 0xe5, 0xc0, 0xd7, 0x44, 0xc1, + 0x31, 0xc3, 0x76, 0xbd, 0x84, 0xb4, 0xef, 0xba, 0x12, 0xca, 0x86, 0xd2, + 0xaf, 0xc5, 0x52, 0xba, 0x62, 0xcf, 0x26, 0xe6, 0x21, 0xde, 0x53, 0xd9, + 0xc8, 0xdd, 0x3f, 0xd6, 0x86, 0xe2, 0xfc, 0xf4, 0x63, 0xfe, 0xc9, 0x06, + 0x13, 0xfe, 0xf5, 0x01, 0x71, 0x12, 0x28, 0x0f, 0x25, 0xff, 0x1b, 0xf9, + 0x0c, 0xf4, 0xc0, 0xe8, 0x31, 0xed, 0x47, 0xef, 0x6b, 0xe1, 0xea, 0xdd, + 0x14, 0xe8, 0x10, 0xe7, 0xa6, 0xd7, 0x56, 0xc7, 0xb0, 0xc7, 0x51, 0xd4, + 0xd9, 0xdb, 0xe8, 0xe6, 0x5c, 0xed, 0x76, 0xec, 0x49, 0xeb, 0x92, 0xec, + 0x0d, 0xf5, 0x45, 0x03, 0xad, 0x18, 0x10, 0x27, 0x3f, 0x2b, 0x3a, 0x34, + 0x2f, 0x41, 0x21, 0x4a, 0x96, 0x3f, 0x3c, 0x21, 0x97, 0x0c, 0xaf, 0x04, + 0x7c, 0xfd, 0xfe, 0xfd, 0xb1, 0xfe, 0x6f, 0xed, 0xce, 0xd5, 0x68, 0xda, + 0xa5, 0xee, 0xc1, 0xf5, 0x97, 0xf4, 0xf0, 0xe7, 0xb4, 0xe2, 0x86, 0xec, + 0x83, 0xec, 0xff, 0xef, 0x1f, 0xf8, 0x57, 0x05, 0x69, 0x10, 0xe9, 0xf4, + 0x64, 0xde, 0xd1, 0xef, 0x51, 0x06, 0x73, 0x19, 0xd5, 0x0e, 0xff, 0xe9, + 0x18, 0xe9, 0x38, 0xfa, 0xcc, 0x05, 0xef, 0x0a, 0x33, 0xfd, 0x82, 0xf4, + 0x87, 0xf1, 0xbc, 0xec, 0x45, 0xd7, 0xce, 0xc0, 0x80, 0xc2, 0xf8, 0xba, + 0x81, 0xb1, 0x2f, 0xb2, 0x19, 0xb1, 0x57, 0xbf, 0x74, 0xdb, 0x0c, 0xe3, + 0x52, 0xd8, 0x57, 0xd2, 0x07, 0xd6, 0x33, 0xe5, 0xe9, 0xf7, 0x42, 0x04, + 0x87, 0x02, 0xed, 0x00, 0x3a, 0x03, 0x20, 0x0d, 0xfb, 0x1b, 0x14, 0x16, + 0x87, 0x11, 0x82, 0x1c, 0xf9, 0x2f, 0x22, 0x42, 0xd9, 0x3a, 0x11, 0x24, + 0xa1, 0x19, 0xe3, 0x1b, 0xd9, 0x1f, 0x69, 0x1e, 0x38, 0x0c, 0x7f, 0xfa, + 0x50, 0x05, 0x53, 0x19, 0x1e, 0x1a, 0xdf, 0x0b, 0x56, 0xf2, 0x42, 0xe7, + 0x12, 0xf9, 0xf4, 0xfe, 0xee, 0xf7, 0xd5, 0xf6, 0x3c, 0xf1, 0x78, 0xf0, + 0x1e, 0xfa, 0x8f, 0x01, 0xb4, 0x0f, 0xa6, 0x13, 0x05, 0x0b, 0x03, 0x13, + 0xf5, 0x0d, 0x6e, 0xfc, 0x59, 0xfa, 0x4d, 0xfd, 0xd4, 0xfd, 0xb3, 0xfa, + 0x4e, 0xf5, 0xdc, 0xfa, 0xa4, 0x0d, 0xf1, 0x14, 0x9a, 0x19, 0x4c, 0x1f, + 0x36, 0x10, 0xa3, 0x0a, 0x54, 0x1b, 0x0a, 0x23, 0x32, 0x26, 0xd0, 0x28, + 0x9e, 0x2c, 0xe6, 0x3a, 0x9e, 0x2d, 0xb4, 0x0a, 0xb7, 0x02, 0x8c, 0x02, + 0x8b, 0xfb, 0xa6, 0xf6, 0x1d, 0xe7, 0x51, 0xdb, 0x4d, 0xe0, 0x4e, 0xe5, + 0x40, 0xe3, 0x56, 0xde, 0xce, 0xdf, 0x44, 0xe6, 0x9a, 0xf3, 0xb6, 0x00, + 0xcc, 0x03, 0xfe, 0x08, 0x25, 0x0c, 0xbf, 0x05, 0x6d, 0x0a, 0x97, 0x1c, + 0x72, 0x17, 0xb5, 0x0d, 0xa6, 0x16, 0xb2, 0x23, 0x0e, 0x32, 0xd9, 0x2f, + 0xf0, 0x26, 0x98, 0x1c, 0x2d, 0x10, 0xa0, 0x10, 0x10, 0x1b, 0x52, 0x21, + 0xb9, 0x0f, 0x00, 0xfb, 0xac, 0xf1, 0x90, 0xf1, 0xfc, 0xfc, 0xb9, 0x05, + 0x8d, 0x05, 0x86, 0xfc, 0x2d, 0xec, 0x32, 0xe1, 0xd8, 0xeb, 0xf8, 0xfd, + 0x44, 0x08, 0xeb, 0x0d, 0x53, 0x16, 0x9a, 0x27, 0x2d, 0x2d, 0x1d, 0x2a, + 0x0e, 0x32, 0x63, 0x40, 0xfc, 0x4c, 0x7e, 0x56, 0xfd, 0x59, 0x85, 0x45, + 0x23, 0x26, 0xf6, 0x15, 0xda, 0x12, 0x0b, 0x18, 0xd6, 0x1b, 0xe4, 0x13, + 0x53, 0x07, 0x09, 0x03, 0xca, 0x06, 0x31, 0x03, 0x7b, 0xf9, 0xb0, 0xfc, + 0x95, 0x05, 0xbb, 0x12, 0x4a, 0x19, 0x8c, 0x10, 0x32, 0x0a, 0x35, 0x00, + 0xa2, 0x00, 0xca, 0x04, 0xff, 0x01, 0xb2, 0x09, 0xee, 0x11, 0xfd, 0x0e, + 0xa6, 0x0a, 0xa9, 0x14, 0x8c, 0x17, 0x60, 0x15, 0xe4, 0x16, 0xf1, 0x13, + 0x44, 0x15, 0xfe, 0x0d, 0xf2, 0x01, 0x54, 0xf7, 0x5b, 0xf3, 0xe2, 0xee, + 0x7b, 0xe2, 0x16, 0xe3, 0x82, 0xdb, 0x3f, 0xc4, 0x4c, 0xc2, 0xcc, 0xdb, + 0x81, 0xf5, 0x69, 0xf1, 0xcd, 0xe6, 0x36, 0xf0, 0xf9, 0xf0, 0x0b, 0xf0, + 0x20, 0xf5, 0x64, 0xf2, 0x50, 0xf7, 0x23, 0x0e, 0x81, 0x1f, 0xda, 0x11, + 0xcf, 0x04, 0xa6, 0x04, 0xb6, 0x07, 0x5d, 0x0f, 0x29, 0x10, 0xd1, 0x0f, + 0x07, 0x11, 0x96, 0x19, 0x66, 0x23, 0x3b, 0x22, 0x50, 0x14, 0x3e, 0x06, + 0x75, 0x0b, 0x63, 0x11, 0xc9, 0x0c, 0x05, 0x08, 0x31, 0x09, 0x53, 0x0c, + 0x89, 0x09, 0x80, 0x04, 0xef, 0xf9, 0x9d, 0xe6, 0xe4, 0xe3, 0x62, 0xf5, + 0x37, 0xf9, 0x20, 0xf7, 0xc8, 0xf8, 0xc5, 0xf9, 0xc7, 0xfd, 0x8d, 0xf8, + 0x24, 0xf5, 0x7f, 0x03, 0xcd, 0x0b, 0x77, 0x00, 0x89, 0xf7, 0xa9, 0xee, + 0x30, 0xe3, 0x06, 0xe6, 0x69, 0xf2, 0x2d, 0xf8, 0xb8, 0xf4, 0x9f, 0xf9, + 0x2d, 0x09, 0xfd, 0x21, 0xa6, 0x32, 0x32, 0x21, 0x90, 0x0b, 0xfd, 0x0f, + 0x70, 0x25, 0xc5, 0x36, 0x08, 0x33, 0x93, 0x2a, 0x14, 0x3f, 0xb5, 0x54, + 0xfa, 0x3b, 0xa1, 0x07, 0x9a, 0xe3, 0x58, 0xde, 0x9a, 0xe7, 0x10, 0xf0, + 0xb9, 0xf9, 0xcf, 0xfa, 0x38, 0xe5, 0xe0, 0xc9, 0x8a, 0xbc, 0x25, 0xc8, + 0x16, 0xe2, 0x88, 0xf9, 0x59, 0x06, 0x18, 0xfe, 0x10, 0xf7, 0x17, 0xf9, + 0xf9, 0xfd, 0x7d, 0xfb, 0xf9, 0xf0, 0xb8, 0xff, 0xc9, 0x15, 0xe2, 0x16, + 0x85, 0x15, 0xf6, 0x18, 0x84, 0x18, 0xf2, 0x15, 0x84, 0x16, 0x7f, 0x18, + 0xb3, 0x11, 0x87, 0x0a, 0x2c, 0x10, 0xb8, 0x12, 0x65, 0x07, 0x9f, 0xf5, + 0xec, 0xef, 0x78, 0xf8, 0x6e, 0xfd, 0x04, 0xf2, 0xc1, 0xea, 0x77, 0xf7, + 0x78, 0x00, 0x02, 0x06, 0xcf, 0x07, 0x71, 0x03, 0x9c, 0x0b, 0xee, 0x21, + 0xa2, 0x30, 0x0c, 0x27, 0x52, 0x20, 0xfc, 0x3c, 0x5a, 0x57, 0x68, 0x4b, + 0xa1, 0x45, 0xd6, 0x44, 0x83, 0x34, 0xed, 0x26, 0xe2, 0x0e, 0x2d, 0x0b, + 0x1b, 0x23, 0x78, 0x1a, 0x2e, 0x03, 0xa5, 0x01, 0xc8, 0xfd, 0xad, 0xf7, + 0x9c, 0xf4, 0x29, 0xee, 0x0d, 0x02, 0x54, 0x24, 0x60, 0x20, 0x21, 0xfc, + 0x02, 0xe5, 0xbf, 0xf2, 0xee, 0x19, 0xf8, 0x24, 0x80, 0x0f, 0x53, 0x0d, + 0xbc, 0x0d, 0x81, 0x06, 0x64, 0x03, 0x21, 0xfa, 0xd7, 0xfe, 0x33, 0x0e, + 0x8d, 0x0f, 0x9f, 0x14, 0xb5, 0x1d, 0x1b, 0x1c, 0xf3, 0x18, 0x68, 0x14, + 0x15, 0x15, 0x75, 0x0d, 0xdd, 0x01, 0xf3, 0x02, 0x45, 0xf9, 0x63, 0xe5, + 0xb8, 0xd5, 0x3a, 0xcc, 0x25, 0xcd, 0xf6, 0xe7, 0x27, 0x03, 0x69, 0x0d, + 0x9a, 0x0d, 0xae, 0xfb, 0xd4, 0xf0, 0x77, 0x00, 0x51, 0x1a, 0x12, 0x16, + 0xec, 0xfb, 0x19, 0xef, 0x56, 0xed, 0xb7, 0xed, 0xe5, 0xf8, 0x29, 0x02, + 0x8d, 0xfd, 0x50, 0x02, 0x83, 0x00, 0xc7, 0xfa, 0x61, 0xfc, 0xd6, 0xfc, + 0x68, 0xf8, 0x3e, 0xfb, 0x2a, 0x0c, 0x36, 0x10, 0xa7, 0x14, 0xb3, 0x1a, + 0x61, 0x15, 0x38, 0x0c, 0xc2, 0x0a, 0x3a, 0x06, 0xc1, 0xf7, 0xc2, 0xff, + 0x77, 0x11, 0xc9, 0x09, 0x19, 0xef, 0x21, 0xd7, 0xaf, 0xd1, 0x5d, 0xf2, + 0x3e, 0x0a, 0x0b, 0xfd, 0x8b, 0xf9, 0x2a, 0xf4, 0x60, 0xea, 0xc8, 0xeb, + 0xaf, 0xe1, 0xc0, 0xde, 0x16, 0xee, 0x4d, 0xef, 0x7c, 0xeb, 0x12, 0xe9, + 0xe1, 0xe8, 0xf0, 0xf1, 0x38, 0xfc, 0xff, 0x05, 0xb0, 0x0e, 0xd2, 0x1c, + 0x01, 0x1e, 0xf9, 0x16, 0xf0, 0x1f, 0x7c, 0x27, 0x4d, 0x22, 0x77, 0x1e, + 0x0e, 0x21, 0x1a, 0x27, 0xb2, 0x1c, 0x6f, 0xf6, 0x38, 0xde, 0xc5, 0xd9, + 0x41, 0xd1, 0x41, 0xc4, 0x89, 0xbb, 0x22, 0xbb, 0xb1, 0xc1, 0x30, 0xc2, + 0x40, 0xaa, 0x30, 0xa5, 0xd4, 0xbc, 0xa5, 0xca, 0x29, 0xd1, 0x7e, 0xc9, + 0x7f, 0xbf, 0x20, 0xd9, 0x44, 0xf7, 0x22, 0xf7, 0x34, 0xe8, 0xc8, 0xd4, + 0x8a, 0xd3, 0xbb, 0xe8, 0xc0, 0x09, 0x0b, 0x17, 0x6a, 0xff, 0x76, 0xee, + 0x85, 0xe0, 0x2f, 0xe7, 0x1c, 0x0b, 0xc1, 0x0d, 0x59, 0x04, 0x9f, 0x02, + 0x15, 0x00, 0xe6, 0xfe, 0xfc, 0xe9, 0x36, 0xdd, 0x8f, 0xe2, 0x4d, 0xea, + 0x42, 0xf7, 0x37, 0xfa, 0x9e, 0xf2, 0xd4, 0xec, 0xbb, 0xeb, 0x6d, 0xfd, + 0x50, 0x19, 0xa0, 0x1a, 0xa1, 0x11, 0xf2, 0x18, 0x69, 0x2a, 0xd4, 0x3a, + 0x7e, 0x3e, 0xd7, 0x30, 0xd6, 0x2c, 0x3b, 0x3f, 0x24, 0x3a, 0x3e, 0x19, + 0x0a, 0xfa, 0xe8, 0xf0, 0x88, 0x00, 0x39, 0x0a, 0x36, 0xf8, 0xf0, 0xde, + 0x0d, 0xde, 0x69, 0xe3, 0xef, 0xe7, 0x74, 0xf1, 0xf7, 0xf9, 0x2d, 0x04, + 0xc8, 0x01, 0x44, 0xf6, 0x03, 0xf2, 0x5a, 0xf6, 0x31, 0x02, 0x0b, 0x0c, + 0x17, 0x06, 0xcf, 0xf6, 0x76, 0xf2, 0x34, 0xf7, 0x28, 0xf7, 0xa3, 0xf1, + 0x67, 0xf0, 0xd0, 0x01, 0x00, 0x22, 0xd6, 0x39, 0x87, 0x34, 0x5e, 0x1c, + 0xd4, 0x19, 0x6e, 0x2f, 0x10, 0x3f, 0x0b, 0x47, 0x02, 0x43, 0x36, 0x29, + 0xb5, 0x16, 0x2d, 0x14, 0x13, 0x0d, 0xf6, 0x00, 0xd1, 0xfc, 0x48, 0x05, + 0x11, 0x0f, 0x4a, 0x17, 0x36, 0x16, 0xa1, 0x0e, 0x9f, 0x0d, 0xf7, 0x09, + 0x15, 0x04, 0x3c, 0x06, 0xa7, 0x10, 0xf1, 0x19, 0x8d, 0x12, 0x25, 0x06, + 0xd3, 0x04, 0xae, 0x01, 0x98, 0xfc, 0x32, 0xf5, 0x1a, 0xf5, 0xad, 0x06, + 0xc8, 0x13, 0x3f, 0x12, 0x4f, 0x0f, 0x23, 0x19, 0xe4, 0x27, 0xe5, 0x31, + 0xe6, 0x33, 0xbd, 0x2c, 0xb4, 0x28, 0x30, 0x34, 0x00, 0x35, 0x15, 0x22, + 0x82, 0x16, 0xfe, 0x08, 0x33, 0x02, 0x37, 0x06, 0xa6, 0x05, 0x38, 0x01, + 0x4b, 0x01, 0xfa, 0x08, 0x12, 0x11, 0xe8, 0x0f, 0x1d, 0xf6, 0x30, 0xeb, + 0x94, 0xf5, 0x3f, 0x01, 0xbd, 0x0c, 0x73, 0x03, 0x7d, 0xfc, 0x00, 0xf1, + 0xdd, 0xf0, 0x69, 0x10, 0x44, 0x1c, 0xb3, 0x15, 0x12, 0x0f, 0xd1, 0x0e, + 0x4a, 0x22, 0xd3, 0x39, 0xc2, 0x45, 0x87, 0x45, 0xfb, 0x3a, 0x57, 0x36, + 0x43, 0x3f, 0x34, 0x51, 0x65, 0x5a, 0x7e, 0x45, 0x89, 0x2a, 0x17, 0x1f, + 0x95, 0x13, 0x88, 0x00, 0x7d, 0xea, 0xe7, 0xd2, 0x10, 0xcd, 0x3d, 0xd7, + 0x16, 0xd3, 0xfb, 0xcd, 0x44, 0xce, 0x35, 0xc1, 0x01, 0xc1, 0xa9, 0xda, + 0xf1, 0xf1, 0x9a, 0x01, 0x1a, 0xff, 0x24, 0xf8, 0x96, 0x02, 0x79, 0x07, + 0x03, 0x05, 0x79, 0x02, 0x5f, 0x0b, 0xfd, 0x14, 0x0a, 0x11, 0xf9, 0x1a, + 0xc6, 0x27, 0x38, 0x26, 0x50, 0x2b, 0x51, 0x28, 0xf1, 0x13, 0xcb, 0x0f, + 0x32, 0x0d, 0x81, 0x12, 0xaf, 0x21, 0x25, 0x15, 0x89, 0x0e, 0xac, 0x0e, + 0x99, 0x0c, 0xb8, 0x15, 0xbd, 0x07, 0x6f, 0xf8, 0x71, 0x06, 0x42, 0x0f, + 0x2d, 0x14, 0x2d, 0x1e, 0x05, 0x15, 0xa6, 0x11, 0x5a, 0x27, 0x35, 0x3a, + 0x54, 0x44, 0x66, 0x3e, 0xa2, 0x29, 0xc0, 0x26, 0xc5, 0x27, 0x04, 0x11, + 0x8a, 0xfd, 0x68, 0xf7, 0x60, 0xf7, 0x1d, 0xfc, 0x7b, 0xf4, 0x98, 0xe8, + 0xaa, 0xec, 0xf1, 0xf5, 0xd1, 0xf3, 0x3d, 0xe9, 0xd2, 0xde, 0x32, 0xdc, + 0xac, 0xe7, 0x60, 0xf8, 0x00, 0x05, 0x51, 0x02, 0xde, 0xf0, 0xbd, 0xe8, + 0xbb, 0xe5, 0xd3, 0xe7, 0x66, 0xf8, 0xb5, 0x02, 0x30, 0xff, 0x96, 0xf5, + 0x43, 0xeb, 0x1a, 0xe6, 0xc3, 0xf0, 0x99, 0x03, 0x28, 0x04, 0xd7, 0xfa, + 0x6d, 0x0a, 0x12, 0x29, 0xf5, 0x35, 0xf2, 0x35, 0x6d, 0x2d, 0x84, 0x2b, + 0x50, 0x34, 0xe3, 0x36, 0xd9, 0x38, 0x54, 0x30, 0x72, 0x1c, 0x08, 0x0d, + 0x25, 0x09, 0x45, 0x0c, 0x25, 0x06, 0x43, 0xf5, 0x82, 0xf2, 0x4b, 0x03, + 0xd5, 0x07, 0x63, 0x01, 0x34, 0xff, 0xd8, 0xfa, 0x7b, 0xf9, 0xd1, 0xf8, + 0xd8, 0xec, 0x63, 0xe5, 0xaa, 0xf3, 0x2a, 0xfe, 0x06, 0xed, 0xf2, 0xd8, + 0x2e, 0xd5, 0x9c, 0xe0, 0x60, 0xf9, 0xf4, 0x03, 0x19, 0xfb, 0x6e, 0xf4, + 0x21, 0x05, 0xe8, 0x1d, 0x54, 0x16, 0x36, 0x08, 0xd6, 0x06, 0x6f, 0x0a, + 0xc9, 0x0c, 0x82, 0x01, 0x33, 0xf8, 0x97, 0xf9, 0xb7, 0xf7, 0x87, 0xeb, + 0xc3, 0xd8, 0x9c, 0xc7, 0x9a, 0xce, 0xe9, 0xd7, 0x8d, 0xd1, 0x8b, 0xcd, + 0x58, 0xc4, 0xe7, 0xca, 0x27, 0xd5, 0x8b, 0xd3, 0xd2, 0xd2, 0xe3, 0xd3, + 0x31, 0xe1, 0xf3, 0xe3, 0xd3, 0xea, 0x2e, 0xfc, 0x64, 0xf9, 0x69, 0xf9, + 0xf5, 0xfa, 0x4e, 0xf7, 0x72, 0x11, 0xb0, 0x1f, 0x10, 0x10, 0x1b, 0x1a, + 0x92, 0x18, 0x4f, 0x23, 0x30, 0x4a, 0x9c, 0x40, 0x2b, 0x24, 0x6f, 0x10, + 0xfa, 0x04, 0x6f, 0x01, 0xce, 0xed, 0xac, 0xd5, 0xaa, 0xc3, 0x6c, 0xb0, + 0x00, 0xab, 0x72, 0xa8, 0xa4, 0xa4, 0x3c, 0xb3, 0x43, 0xbc, 0x91, 0xbf, + 0xcd, 0xbc, 0x92, 0xb7, 0xff, 0xc6, 0x81, 0xdf, 0xe2, 0xe7, 0x3e, 0xe6, + 0x77, 0xe4, 0x1c, 0xe5, 0x3c, 0xf9, 0x66, 0xf7, 0xfb, 0xeb, 0xda, 0xef, + 0xc8, 0xf1, 0xda, 0x02, 0x7d, 0x07, 0xd9, 0xf6, 0xda, 0xeb, 0x3c, 0xe6, + 0x01, 0xe4, 0x88, 0xee, 0xcf, 0xf1, 0xb6, 0xf8, 0x53, 0x07, 0x2d, 0x0a, + 0xb7, 0x06, 0x21, 0xf2, 0xd4, 0xe7, 0x4a, 0xeb, 0x54, 0xf9, 0xe6, 0x05, + 0xf9, 0xfc, 0xd0, 0xee, 0x12, 0xe9, 0x7e, 0xf8, 0xe8, 0x05, 0x16, 0x0a, + 0x96, 0x0a, 0xf5, 0x09, 0x92, 0x06, 0x02, 0xfe, 0xbf, 0xed, 0x50, 0xdd, + 0xc5, 0xd8, 0xd7, 0xd7, 0x2f, 0xe0, 0xad, 0xdb, 0x1f, 0xcd, 0x0d, 0xc8, + 0x94, 0xcd, 0xbc, 0xd9, 0x5a, 0xda, 0xfc, 0xd3, 0x40, 0xcd, 0x43, 0xd0, + 0xbd, 0xd5, 0xff, 0xd9, 0xe0, 0xe2, 0xbc, 0xd8, 0x0c, 0xc6, 0xb1, 0xd3, + 0x33, 0xe8, 0x45, 0xeb, 0x2d, 0xeb, 0xcf, 0xe1, 0xaf, 0xde, 0xf9, 0xe4, + 0x65, 0xe3, 0xa5, 0xd7, 0x94, 0xcc, 0x54, 0xd1, 0x28, 0xe5, 0x41, 0xf7, + 0x2a, 0xf7, 0x16, 0xf1, 0xb2, 0xf6, 0x89, 0x04, 0xf5, 0x14, 0x4c, 0x1f, + 0x4f, 0x1e, 0xa6, 0x25, 0x22, 0x2e, 0x9d, 0x2d, 0x1c, 0x37, 0xdb, 0x30, + 0x47, 0x1d, 0x5a, 0x1b, 0x30, 0x14, 0xb3, 0x07, 0x6e, 0x03, 0xc9, 0xff, + 0xe1, 0xf9, 0x4f, 0xef, 0xd8, 0xe3, 0xb5, 0xdc, 0x3d, 0xdb, 0xc8, 0xd9, + 0x16, 0xda, 0x52, 0xdc, 0xb3, 0xe0, 0xfc, 0xe1, 0x4e, 0xd9, 0x58, 0xdb, + 0x09, 0xe6, 0x06, 0xe7, 0xc2, 0xdd, 0xe7, 0xd9, 0x2f, 0xe2, 0xcf, 0xf2, + 0xc9, 0xfd, 0xf7, 0xf7, 0xb6, 0xf0, 0x92, 0xef, 0x1e, 0xff, 0x69, 0x17, + 0xb4, 0x1f, 0xa2, 0x11, 0x6c, 0x02, 0x5c, 0xfe, 0x8c, 0xfe, 0x6b, 0x03, + 0x49, 0xfc, 0x0a, 0xf1, 0xd5, 0xe8, 0x1a, 0xdd, 0x9e, 0xda, 0x72, 0xe3, + 0x66, 0xe4, 0xd6, 0xe2, 0xa2, 0xe2, 0x9e, 0xda, 0xfe, 0xe3, 0x7c, 0xe5, + 0xec, 0xe3, 0x54, 0xfc, 0x02, 0x08, 0xad, 0x12, 0x25, 0x21, 0x9d, 0x1d, + 0xa4, 0x21, 0xb4, 0x2c, 0xb5, 0x27, 0x2a, 0x2c, 0x2c, 0x35, 0xd9, 0x2e, + 0x50, 0x33, 0x85, 0x37, 0x14, 0x3b, 0x95, 0x4a, 0xae, 0x53, 0x11, 0x4d, + 0x09, 0x39, 0x39, 0x32, 0xed, 0x2b, 0x30, 0x15, 0xd3, 0xfd, 0x48, 0xe2, + 0xfb, 0xd7, 0x8c, 0xd9, 0x25, 0xcf, 0xa0, 0xd0, 0x4a, 0xd9, 0xd6, 0xd2, + 0x8c, 0xd9, 0xf4, 0xe8, 0xd1, 0xef, 0x0e, 0x00, 0x02, 0x05, 0xed, 0xff, + 0xa6, 0x00, 0xcb, 0x01, 0xea, 0x09, 0x95, 0x16, 0xb7, 0x1a, 0x4c, 0x17, + 0x1a, 0x19, 0x3a, 0x19, 0x95, 0x10, 0xe9, 0x09, 0x5a, 0x0e, 0x31, 0x0c, + 0xe9, 0x0c, 0x4f, 0x15, 0xad, 0x0c, 0x7e, 0x0c, 0x90, 0x13, 0x19, 0x15, + 0xc7, 0x20, 0xd0, 0x20, 0x71, 0x1b, 0x76, 0x2f, 0xc9, 0x39, 0x49, 0x34, + 0x89, 0x31, 0x06, 0x26, 0xc0, 0x21, 0x84, 0x21, 0x6c, 0x1d, 0xc7, 0x19, + 0xd4, 0x14, 0x16, 0x15, 0x01, 0x1b, 0x60, 0x1b, 0x2c, 0x0b, 0x85, 0xf5, + 0xba, 0xf1, 0xdb, 0x00, 0x81, 0x09, 0x38, 0x01, 0xe9, 0xeb, 0x69, 0xde, + 0x41, 0xea, 0xcb, 0xfb, 0x9a, 0xfd, 0x09, 0xf4, 0x3e, 0xf1, 0x3a, 0xfb, + 0x6d, 0x06, 0x04, 0x05, 0x04, 0x03, 0x15, 0xfb, 0x7d, 0xef, 0xd3, 0xf6, + 0xb5, 0x01, 0x07, 0x10, 0xa1, 0x12, 0xc8, 0x01, 0xe4, 0xff, 0x3d, 0x0b, + 0x4d, 0x14, 0x0b, 0x10, 0x15, 0xfc, 0xd8, 0xf0, 0x31, 0xf6, 0xeb, 0xfe, + 0x84, 0x04, 0x6c, 0x02, 0x22, 0xfb, 0x75, 0x03, 0x79, 0x19, 0x69, 0x20, + 0x5d, 0x1f, 0x66, 0x1b, 0x48, 0x25, 0x00, 0x4c, 0x55, 0x56, 0x94, 0x47, + 0x56, 0x43, 0x2d, 0x3f, 0x5b, 0x42, 0x9c, 0x3c, 0xc1, 0x2c, 0xa6, 0x27, + 0xeb, 0x23, 0x88, 0x1a, 0xd5, 0x07, 0xb3, 0xf5, 0x0d, 0xea, 0xc7, 0xe6, + 0xd1, 0xed, 0x3e, 0xf2, 0xd2, 0xf7, 0x95, 0xf8, 0x75, 0xef, 0x6d, 0xf1, + 0x22, 0xfc, 0x8e, 0xf7, 0xc7, 0xea, 0x4a, 0xea, 0xf2, 0xef, 0x0e, 0xf3, + 0x13, 0xf1, 0x40, 0xf0, 0x02, 0xfb, 0x8d, 0x09, 0x02, 0x0d, 0x43, 0x08, + 0xca, 0x08, 0xad, 0x0e, 0xb3, 0x10, 0xd4, 0x0f, 0x04, 0x09, 0x5f, 0x02, + 0x7e, 0x05, 0xac, 0x02, 0xfd, 0x03, 0xbd, 0xfe, 0xf8, 0xe8, 0xa8, 0xe7, + 0x33, 0xea, 0xa7, 0xed, 0x53, 0xf5, 0xe2, 0xe7, 0x65, 0xe3, 0x96, 0xdf, + 0x15, 0xd5, 0x25, 0xea, 0x8e, 0xfe, 0x49, 0x07, 0x64, 0x10, 0x70, 0x0e, + 0xe4, 0x18, 0xc3, 0x26, 0x4f, 0x27, 0xa2, 0x23, 0x21, 0x17, 0xa8, 0x1b, + 0xab, 0x28, 0xd9, 0x29, 0xa1, 0x2f, 0xe1, 0x1f, 0xc9, 0x19, 0x7a, 0x30, + 0x31, 0x37, 0xd0, 0x2f, 0x41, 0x17, 0x36, 0x04, 0xac, 0x0a, 0x55, 0x0d, + 0x79, 0x00, 0xdc, 0xe9, 0xfc, 0xcc, 0x7a, 0xc9, 0xa9, 0xd3, 0xe5, 0xcf, + 0x80, 0xd6, 0x85, 0xd7, 0x9b, 0xe1, 0xdc, 0xef, 0x4d, 0xe6, 0x4e, 0xe6, + 0xea, 0xed, 0xf6, 0xfa, 0xa0, 0x0a, 0x86, 0x00, 0x57, 0xee, 0x73, 0xf0, + 0xa3, 0xf7, 0x4f, 0x0a, 0x0b, 0x17, 0xb3, 0x09, 0xc7, 0x0b, 0xad, 0x16, + 0x7e, 0x16, 0x80, 0x04, 0xfe, 0xed, 0x1e, 0xfa, 0xed, 0x09, 0x08, 0x0b, + 0x84, 0x11, 0x33, 0x16, 0xeb, 0x27, 0xcb, 0x31, 0x99, 0x27, 0x68, 0x2d, + 0xb3, 0x3c, 0x49, 0x44, 0x58, 0x37, 0xd6, 0x1c, 0xa5, 0x12, 0x72, 0x12, + 0xd4, 0x03, 0x04, 0x02, 0xae, 0x01, 0x6d, 0xf1, 0xc9, 0xf4, 0x00, 0xf3, + 0x7c, 0xef, 0xd5, 0xf6, 0xf2, 0xf9, 0xc9, 0xfd, 0x87, 0xff, 0xf7, 0xfb, + 0x82, 0xf2, 0x63, 0xeb, 0x8c, 0xeb, 0xfe, 0xf9, 0x8a, 0x00, 0x0a, 0xfe, + 0x73, 0xff, 0xdc, 0xf7, 0x4e, 0xf3, 0xdc, 0xf2, 0x76, 0xf8, 0x13, 0xff, + 0x01, 0xf9, 0xc8, 0xf9, 0xd6, 0x0a, 0x91, 0x11, 0xb0, 0x07, 0xd1, 0xfb, + 0xcb, 0xf8, 0xd5, 0x05, 0xda, 0x0a, 0xfe, 0xfa, 0x93, 0xeb, 0xbc, 0xea, + 0xe9, 0xf7, 0x40, 0x03, 0x9a, 0xfe, 0x00, 0xf6, 0x11, 0xf7, 0x77, 0x06, + 0x02, 0x1a, 0x6a, 0x1c, 0x68, 0x1c, 0x77, 0x2c, 0x69, 0x47, 0xe1, 0x5a, + 0x3d, 0x52, 0xe3, 0x42, 0xd3, 0x43, 0x43, 0x4f, 0xa1, 0x5c, 0xb9, 0x55, + 0x4a, 0x3b, 0xc1, 0x23, 0x5f, 0x11, 0xc0, 0x06, 0xe8, 0xff, 0x27, 0xfe, + 0x26, 0x01, 0xeb, 0xfe, 0xf8, 0xf7, 0xfc, 0xf0, 0x66, 0xf4, 0xab, 0xf8, + 0x7f, 0xf9, 0xac, 0xf8, 0xdf, 0xf6, 0x9f, 0xfd, 0x5c, 0x01, 0x0d, 0x00, + 0x87, 0xfa, 0x90, 0xef, 0xf0, 0xe9, 0xca, 0xf0, 0x5a, 0xfd, 0x5f, 0x08, + 0x85, 0x0d, 0xde, 0x07, 0x56, 0x0d, 0x83, 0x15, 0x0d, 0x17, 0xad, 0x17, + 0xdc, 0x10, 0xe0, 0x0d, 0x98, 0x08, 0x24, 0x02, 0x15, 0x00, 0x06, 0xff, + 0x94, 0xfc, 0x79, 0xfa, 0xb3, 0xf6, 0x10, 0xef, 0x81, 0xeb, 0xe7, 0xe6, + 0x79, 0xe5, 0x9b, 0xea, 0xc9, 0xf3, 0x47, 0xf7, 0x62, 0xf3, 0x64, 0xf2, + 0xf3, 0xfa, 0xe4, 0x03, 0xd1, 0x09, 0x9a, 0x14, 0x0a, 0x17, 0xbd, 0x1a, + 0x2f, 0x13, 0x8d, 0x09, 0x5f, 0x0f, 0x71, 0x0f, 0xb3, 0x11, 0x05, 0x0f, + 0x3b, 0x0c, 0xbb, 0x15, 0x06, 0x20, 0x27, 0x1f, 0x2e, 0x13, 0xea, 0x03, + 0xf6, 0xfd, 0x5d, 0xfc, 0xc2, 0xf3, 0x2f, 0xeb, 0xbc, 0xde, 0xd9, 0xd2, + 0x9e, 0xc9, 0x9e, 0xc3, 0x3b, 0xc8, 0xcc, 0xd7, 0x6f, 0xe2, 0x17, 0xe6, + 0x28, 0xe7, 0x0a, 0xde, 0x43, 0xde, 0xde, 0xea, 0x4d, 0xf6, 0x65, 0xf6, + 0xea, 0xe9, 0x30, 0xe5, 0x48, 0xf2, 0x1a, 0xf5, 0xa6, 0xf1, 0x83, 0xf6, + 0x33, 0xf7, 0xfd, 0xfc, 0x7c, 0xf4, 0x3b, 0xea, 0x36, 0xe8, 0xd4, 0xe9, + 0x5a, 0xff, 0x1f, 0x00, 0x13, 0xf1, 0x2c, 0xf8, 0x6d, 0x0b, 0x4c, 0x1d, + 0x01, 0x1c, 0xd7, 0x0e, 0x1e, 0x0d, 0xfe, 0x08, 0x9c, 0x05, 0xbb, 0x04, + 0xac, 0xfc, 0x47, 0xed, 0x41, 0xda, 0xeb, 0xd4, 0xd1, 0xd4, 0x4a, 0xd3, + 0x6d, 0xd2, 0x85, 0xd4, 0x8a, 0xd7, 0x6e, 0xe1, 0xaa, 0xed, 0x49, 0xe2, + 0xf8, 0xd2, 0x69, 0xd5, 0xe2, 0xe4, 0x7b, 0xf4, 0x0d, 0xf5, 0x18, 0xe5, + 0xa1, 0xdc, 0x37, 0xe8, 0xca, 0xf9, 0x7a, 0xfb, 0xc9, 0xef, 0x94, 0xe9, + 0xd5, 0xe4, 0x08, 0xeb, 0xbf, 0xed, 0xb5, 0xea, 0x2c, 0xef, 0xf5, 0xf1, + 0xd4, 0xf6, 0x15, 0xf7, 0x0f, 0xf3, 0xdf, 0xf5, 0xef, 0xfe, 0xf0, 0x02, + 0x35, 0xff, 0x63, 0xf2, 0x1f, 0xe1, 0x0b, 0xd7, 0x9d, 0xe0, 0xcb, 0xf8, + 0x89, 0x04, 0x1f, 0x04, 0x99, 0xfe, 0xb6, 0x06, 0xf9, 0x18, 0xe5, 0x26, + 0x2e, 0x37, 0x92, 0x44, 0x43, 0x46, 0x89, 0x3f, 0xd2, 0x44, 0xfb, 0x47, + 0x33, 0x43, 0xd7, 0x3f, 0x99, 0x36, 0x03, 0x28, 0xb1, 0x13, 0xab, 0x05, + 0x71, 0xff, 0x1a, 0xf5, 0x27, 0xe7, 0x13, 0xe1, 0xc4, 0xe4, 0x9d, 0xf0, + 0xf2, 0xfc, 0xb2, 0xfe, 0x3f, 0xfe, 0x0c, 0xfc, 0xc2, 0xfb, 0x8f, 0x00, + 0xfe, 0x04, 0x17, 0x06, 0x51, 0x03, 0x00, 0x04, 0x1f, 0x01, 0x2f, 0xf7, + 0x34, 0xf1, 0xb2, 0xf5, 0x81, 0x03, 0x28, 0x10, 0xb6, 0x1b, 0x42, 0x24, + 0x41, 0x25, 0x82, 0x25, 0xc3, 0x27, 0x33, 0x2b, 0x0b, 0x20, 0x7a, 0x0d, + 0x5f, 0x09, 0xd9, 0x13, 0x2d, 0x21, 0x78, 0x18, 0xce, 0x06, 0xf7, 0xfe, + 0xb4, 0x01, 0xc5, 0x07, 0xeb, 0x01, 0xee, 0xfa, 0xba, 0xfb, 0xe9, 0x05, + 0x20, 0x11, 0xfe, 0x0e, 0xb2, 0x06, 0x62, 0x0c, 0x33, 0x1d, 0x5e, 0x27, + 0x29, 0x24, 0x79, 0x20, 0xa1, 0x2d, 0xc5, 0x37, 0x53, 0x31, 0x56, 0x1f, + 0xd8, 0x10, 0x60, 0x10, 0x8e, 0x24, 0xe5, 0x3e, 0xf4, 0x37, 0x6c, 0x2c, + 0xe6, 0x28, 0xf3, 0x1f, 0x7b, 0x19, 0x16, 0x14, 0x31, 0x1a, 0x7a, 0x18, + 0x27, 0x0b, 0x3e, 0xfc, 0x3f, 0xf3, 0x57, 0xf8, 0x9d, 0xfa, 0x4a, 0x04, + 0x13, 0x07, 0xff, 0xf3, 0xed, 0xec, 0xb4, 0xff, 0x17, 0x15, 0xc6, 0x16, + 0xfe, 0x0b, 0x0c, 0xff, 0x02, 0xfe, 0xb0, 0x02, 0x01, 0x02, 0xd5, 0x06, + 0x4a, 0x10, 0x73, 0x17, 0xf8, 0x17, 0x2a, 0x16, 0xf1, 0x0f, 0x73, 0x0f, + 0xdc, 0x14, 0xf1, 0x14, 0xc3, 0x14, 0x85, 0x13, 0x44, 0x16, 0x2c, 0x1d, + 0xcf, 0x1e, 0x26, 0x17, 0xd3, 0x0c, 0x43, 0x05, 0xf0, 0x08, 0xca, 0x11, + 0xe8, 0x0b, 0xc4, 0xf6, 0x5a, 0xea, 0xba, 0xea, 0x32, 0xe5, 0x52, 0xe5, + 0x0d, 0xe3, 0x39, 0xe3, 0x80, 0xe8, 0xee, 0xe8, 0x90, 0xf4, 0xff, 0xfd, + 0x58, 0xff, 0x7c, 0xfa, 0xdf, 0xf7, 0x3a, 0xff, 0xaf, 0x03, 0x52, 0xff, + 0x3e, 0xfd, 0xdc, 0x03, 0x04, 0x09, 0xd6, 0x09, 0x32, 0x0c, 0xd1, 0x0f, + 0x5c, 0x0a, 0x00, 0x06, 0x87, 0x06, 0x49, 0x0b, 0x8b, 0x13, 0x22, 0x12, + 0x02, 0x0b, 0xf2, 0x03, 0xbd, 0x00, 0x5c, 0x04, 0x0e, 0x0c, 0xcc, 0x0d, + 0xdd, 0x0a, 0x12, 0x04, 0x56, 0x00, 0x73, 0x01, 0x57, 0xfd, 0xdf, 0xfc, + 0x3c, 0x04, 0xfe, 0x0e, 0x33, 0x14, 0xf5, 0x1c, 0x02, 0x29, 0xf2, 0x2c, + 0x80, 0x33, 0x42, 0x3b, 0x0b, 0x3d, 0x0b, 0x3f, 0x75, 0x45, 0x55, 0x46, + 0xb4, 0x41, 0xad, 0x40, 0x87, 0x3e, 0x12, 0x35, 0x1e, 0x2a, 0x3c, 0x1e, + 0x1a, 0x11, 0x68, 0x03, 0xe5, 0xf4, 0x78, 0xec, 0xc0, 0xeb, 0xf1, 0xea, + 0x7b, 0xe8, 0xf5, 0xed, 0x4b, 0xf2, 0x27, 0xf3, 0x73, 0xf4, 0xf9, 0xf4, + 0xe7, 0xf9, 0x32, 0xfc, 0xa7, 0xf7, 0xf6, 0xee, 0x57, 0xe9, 0x51, 0xea, + 0xc7, 0xec, 0x47, 0xe9, 0xa9, 0xe7, 0x9a, 0xed, 0xa1, 0xfa, 0x10, 0x08, + 0xcd, 0x08, 0x62, 0x0a, 0x6f, 0x0b, 0xc3, 0x09, 0x6c, 0x0a, 0xf7, 0x03, + 0xe6, 0xf9, 0x58, 0xf6, 0xeb, 0xf5, 0xb0, 0xf0, 0xe3, 0xea, 0xa1, 0xe7, + 0x3f, 0xe8, 0x60, 0xe6, 0x2b, 0xe5, 0x2f, 0xe7, 0x0e, 0xe4, 0x2f, 0xdd, + 0x75, 0xd7, 0x13, 0xd8, 0x37, 0xde, 0x7a, 0xe4, 0x6a, 0xe9, 0xc2, 0xf6, + 0xc1, 0x04, 0x96, 0x07, 0x75, 0x01, 0x2d, 0x03, 0xd4, 0x0d, 0xb6, 0x07, + 0x37, 0xf8, 0xb5, 0xec, 0x43, 0xf1, 0x72, 0x03, 0x0f, 0x0e, 0x2d, 0x07, + 0xd2, 0xf9, 0xff, 0xfc, 0xb0, 0x0b, 0x78, 0x18, 0x29, 0x11, 0xb4, 0xfc, + 0x75, 0xee, 0x85, 0xec, 0xf3, 0xf0, 0x9a, 0xef, 0xd7, 0xec, 0x11, 0xe6, + 0x12, 0xe5, 0xa3, 0xe3, 0xeb, 0xdb, 0xc4, 0xdc, 0xec, 0xe5, 0xc6, 0xf2, + 0x54, 0xf4, 0xa5, 0xe8, 0xd1, 0xe1, 0x43, 0xe5, 0x0c, 0xea, 0x1e, 0xec, + 0x06, 0xef, 0xb7, 0xfa, 0x04, 0x03, 0xbf, 0xfb, 0xc8, 0xf1, 0xe4, 0xf5, + 0x8f, 0x02, 0x47, 0x01, 0x49, 0xfb, 0xa7, 0xf6, 0x43, 0xf3, 0xac, 0xef, + 0x35, 0xee, 0x80, 0xf6, 0x60, 0xff, 0x43, 0xff, 0x3a, 0xf1, 0xfd, 0xe6, + 0xff, 0xe3, 0x7d, 0xe4, 0x6b, 0xe0, 0x13, 0xd5, 0x52, 0xcf, 0x17, 0xcb, + 0xed, 0xcd, 0xee, 0xcf, 0x3a, 0xcf, 0xbe, 0xd1, 0xdc, 0xd2, 0x38, 0xd3, + 0xf2, 0xd9, 0x39, 0xe5, 0xcc, 0xe4, 0x85, 0xdc, 0x80, 0xd3, 0xc2, 0xd3, + 0x0c, 0xda, 0x9f, 0xdb, 0x32, 0xdf, 0x9f, 0xe3, 0x1c, 0xe3, 0x1f, 0xe3, + 0x2d, 0xe9, 0xd5, 0xeb, 0x53, 0xe9, 0x68, 0xe6, 0x3b, 0xe6, 0x37, 0xe5, + 0xd8, 0xdc, 0x8d, 0xd8, 0xf1, 0xe0, 0x05, 0xec, 0x0d, 0xed, 0xc9, 0xe1, + 0x9d, 0xd9, 0x32, 0xe2, 0x7f, 0xea, 0xa3, 0xe8, 0xa8, 0xe8, 0x00, 0xe8, + 0x1c, 0xe6, 0xae, 0xea, 0x08, 0xf1, 0xe8, 0xf6, 0xea, 0x00, 0xff, 0x0a, + 0xe8, 0x11, 0x01, 0x15, 0x05, 0x15, 0x63, 0x1a, 0xc9, 0x24, 0xc4, 0x2a, + 0xec, 0x2b, 0x2c, 0x2b, 0xe1, 0x25, 0xf8, 0x19, 0xe1, 0x0c, 0x6f, 0x04, + 0xa2, 0x07, 0x6c, 0x08, 0xd6, 0xf4, 0x1b, 0xde, 0x63, 0xce, 0x23, 0xca, + 0x0a, 0xd0, 0x50, 0xd4, 0x74, 0xd7, 0xe1, 0xd8, 0x50, 0xdd, 0x64, 0xdf, + 0xf4, 0xdb, 0x8d, 0xdc, 0x1a, 0xe1, 0xfd, 0xe5, 0xca, 0xe3, 0xa4, 0xd8, + 0x9e, 0xcf, 0xb8, 0xd1, 0x1d, 0xd8, 0x28, 0xe1, 0x69, 0xea, 0x9f, 0xed, + 0xa9, 0xee, 0xff, 0xed, 0x82, 0xf2, 0x24, 0xf9, 0x37, 0xf8, 0xc6, 0xec, + 0x53, 0xdb, 0x6d, 0xdb, 0xbb, 0xe8, 0x3f, 0xe9, 0x2d, 0xe2, 0x0a, 0xdc, + 0xf1, 0xd9, 0xf1, 0xe2, 0xa9, 0xe8, 0x49, 0xe5, 0x5b, 0xdf, 0xf8, 0xd6, + 0xe3, 0xd2, 0x23, 0xd5, 0xd7, 0xdd, 0xc0, 0xe3, 0xa0, 0xe1, 0x5b, 0xe3, + 0x5a, 0xf1, 0x46, 0x04, 0x78, 0x0f, 0xf3, 0x13, 0x4f, 0x11, 0x2e, 0x0c, + 0x7e, 0x0a, 0x08, 0x07, 0x02, 0x04, 0xf5, 0x02, 0x11, 0x04, 0x0d, 0x0b, + 0x2e, 0x12, 0x9d, 0x14, 0xa6, 0x19, 0xe5, 0x23, 0x64, 0x29, 0x6c, 0x23, + 0x1d, 0x14, 0x89, 0x04, 0xd4, 0x01, 0x3d, 0x04, 0x81, 0x01, 0x9c, 0xfc, + 0x83, 0xf7, 0xfa, 0xfa, 0xb4, 0x02, 0xac, 0x02, 0xa3, 0xff, 0x9a, 0x01, + 0x97, 0x06, 0xcb, 0x06, 0x43, 0x01, 0xac, 0xfc, 0xd1, 0x00, 0x78, 0x09, + 0x21, 0x0d, 0x0b, 0x0c, 0x2b, 0x09, 0xd5, 0x09, 0xf8, 0x11, 0x1d, 0x1f, + 0x46, 0x27, 0xdd, 0x22, 0xa0, 0x17, 0x53, 0x0d, 0xaf, 0x06, 0x6e, 0x02, + 0x46, 0x03, 0x4f, 0x08, 0x86, 0x0b, 0xa7, 0x09, 0x41, 0x04, 0xe0, 0x05, + 0x66, 0x09, 0xe6, 0x08, 0xbb, 0x07, 0x18, 0x02, 0xfe, 0xf9, 0x9a, 0xf2, + 0xc4, 0xf0, 0x5e, 0xf3, 0x45, 0xf4, 0x32, 0xf2, 0xa4, 0xf2, 0x85, 0xf9, + 0x59, 0x01, 0x2e, 0x05, 0xa5, 0x03, 0x43, 0x02, 0x36, 0x05, 0x6b, 0x08, + 0x60, 0x09, 0x52, 0x08, 0x34, 0x06, 0x1a, 0x06, 0xf8, 0x08, 0x50, 0x0d, + 0x83, 0x11, 0x3d, 0x10, 0x5e, 0x0a, 0xe7, 0x05, 0xb5, 0x04, 0xd6, 0x02, + 0xba, 0xfb, 0xe3, 0xf6, 0x55, 0xfb, 0x42, 0x03, 0x06, 0x06, 0xf3, 0xfd, + 0x30, 0xfa, 0x3a, 0x03, 0x90, 0x0a, 0x3d, 0x0d, 0xfa, 0x09, 0x8e, 0x03, + 0x04, 0x04, 0x67, 0x0d, 0x8b, 0x18, 0x5d, 0x1b, 0xae, 0x19, 0x3d, 0x1c, + 0x80, 0x25, 0xcd, 0x31, 0xd8, 0x39, 0x8b, 0x3b, 0x17, 0x3c, 0x80, 0x3c, + 0x5e, 0x38, 0xa4, 0x33, 0xed, 0x35, 0x52, 0x3b, 0x41, 0x39, 0x5b, 0x30, + 0x3c, 0x26, 0x4e, 0x1c, 0xf5, 0x13, 0x53, 0x0a, 0x3c, 0xff, 0x73, 0xf8, + 0xc1, 0xf4, 0x2e, 0xf5, 0x45, 0xf8, 0x56, 0xf7, 0xd2, 0xf5, 0x99, 0xf7, + 0x09, 0xfd, 0x2c, 0x05, 0xdd, 0x0d, 0xaa, 0x11, 0xfd, 0x0f, 0x94, 0x08, + 0x14, 0xfd, 0x8a, 0xfa, 0x10, 0x03, 0x9d, 0x0d, 0xd7, 0x0b, 0x17, 0xff, + 0x2a, 0xfd, 0x5c, 0x06, 0x8c, 0x09, 0xbb, 0x06, 0x7d, 0x06, 0x4c, 0x0a, + 0x37, 0x11, 0x90, 0x09, 0xb4, 0xf8, 0x1e, 0xf6, 0xa5, 0xfb, 0xd6, 0x02, + 0x80, 0x00, 0xdb, 0xf7, 0x61, 0xf3, 0xeb, 0xf2, 0xaa, 0xf4, 0x9b, 0xf0, + 0x3b, 0xeb, 0x0a, 0xe7, 0x2e, 0xea, 0xab, 0xf1, 0x8d, 0xfa, 0x92, 0x04, + 0x06, 0x06, 0xf0, 0x09, 0x9a, 0x0f, 0xc9, 0x15, 0xab, 0x19, 0xe3, 0x16, + 0xb8, 0x13, 0x1f, 0x12, 0xbf, 0x13, 0x4b, 0x12, 0x25, 0x16, 0x24, 0x1e, + 0x97, 0x1f, 0x7f, 0x1b, 0x8c, 0x16, 0xdd, 0x19, 0x15, 0x20, 0xcb, 0x25, + 0x8d, 0x25, 0xd9, 0x1d, 0xdd, 0x12, 0x14, 0x06, 0xdb, 0x04, 0x97, 0x0b, + 0x0f, 0x0f, 0xca, 0x0c, 0x5c, 0x05, 0x7a, 0x03, 0x38, 0x0a, 0x4c, 0x13, + 0x1f, 0x18, 0x4f, 0x15, 0x8b, 0x0e, 0xae, 0x08, 0xb2, 0x07, 0x00, 0x0b, + 0x12, 0x11, 0xd9, 0x1b, 0x24, 0x23, 0x7c, 0x1d, 0x71, 0x13, 0x8f, 0x13, + 0xa4, 0x1d, 0x8d, 0x25, 0x84, 0x23, 0x2d, 0x18, 0x05, 0x0f, 0x08, 0x0a, + 0xb4, 0x06, 0xd2, 0x09, 0x10, 0x0f, 0x93, 0x12, 0x01, 0x0d, 0x64, 0x02, + 0x7f, 0xff, 0x5f, 0x02, 0xfe, 0x07, 0xab, 0x04, 0x83, 0xf7, 0xd3, 0xec, + 0x19, 0xe8, 0x11, 0xee, 0x1d, 0xf7, 0xd9, 0xfb, 0x6e, 0xfc, 0x27, 0xf4, + 0x82, 0xf0, 0xe4, 0xfa, 0x29, 0x05, 0x2e, 0x05, 0xf5, 0xfe, 0x68, 0xf7, + 0x9b, 0xf2, 0xee, 0xf4, 0xe7, 0xf6, 0xd9, 0xf5, 0xe1, 0xf5, 0x73, 0xf6, + 0x63, 0xf7, 0xd5, 0xf7, 0x0d, 0xfa, 0x60, 0xfa, 0x74, 0xf1, 0x2f, 0xe8, + 0x80, 0xe8, 0x2b, 0xea, 0xd7, 0xe7, 0xfb, 0xe1, 0x35, 0xe2, 0x91, 0xf1, + 0xd2, 0xfe, 0x21, 0xfb, 0x40, 0xeb, 0xd9, 0xe1, 0xec, 0xe8, 0x8c, 0xf0, + 0x81, 0xf1, 0x4d, 0xf4, 0xdb, 0xf8, 0xa6, 0xff, 0xd1, 0x05, 0x3d, 0x06, + 0xa2, 0x06, 0x31, 0x0b, 0xd8, 0x14, 0x93, 0x1a, 0xfb, 0x17, 0xfb, 0x17, + 0xa7, 0x1f, 0x6d, 0x2a, 0x24, 0x2c, 0xf9, 0x22, 0x39, 0x19, 0x84, 0x12, + 0xd5, 0x10, 0xed, 0x12, 0x39, 0x0d, 0x86, 0x00, 0xbf, 0xf0, 0x46, 0xe5, + 0x8c, 0xec, 0x30, 0xf4, 0x06, 0xf1, 0x0f, 0xf3, 0xc6, 0xf9, 0x38, 0xfd, + 0x91, 0xfc, 0x93, 0xfb, 0xd3, 0x03, 0x89, 0x0e, 0xf9, 0x0c, 0x56, 0x04, + 0x89, 0xfb, 0x56, 0xf6, 0x8a, 0xf9, 0x0f, 0x00, 0xe7, 0x02, 0xdc, 0x03, + 0x0f, 0x01, 0x09, 0xf9, 0x4f, 0xf7, 0x84, 0xfb, 0x29, 0xff, 0xe4, 0xfd, + 0xec, 0xf3, 0x3a, 0xed, 0x8f, 0xef, 0x6f, 0xf0, 0xc1, 0xeb, 0xa7, 0xe9, + 0xd1, 0xef, 0x82, 0xf6, 0xde, 0xf4, 0x70, 0xee, 0xd7, 0xe8, 0xea, 0xe4, + 0xac, 0xe0, 0x94, 0xdb, 0xbd, 0xdf, 0x7d, 0xed, 0xe1, 0xf9, 0x56, 0x01, + 0x6b, 0x00, 0x8a, 0xfe, 0xa2, 0x03, 0xe5, 0x0a, 0x6f, 0x11, 0x0b, 0x15, + 0xb1, 0x16, 0x0e, 0x11, 0xc3, 0x05, 0x25, 0x05, 0xef, 0x0a, 0x48, 0x10, + 0x24, 0x15, 0x0a, 0x16, 0x05, 0x18, 0x91, 0x1d, 0x68, 0x22, 0x7b, 0x22, + 0x5f, 0x1c, 0x57, 0x12, 0xf0, 0x0f, 0x76, 0x18, 0x90, 0x20, 0xcb, 0x25, + 0xc3, 0x23, 0x06, 0x1d, 0x02, 0x1c, 0x7d, 0x1e, 0xce, 0x22, 0x04, 0x28, + 0xc0, 0x29, 0xbb, 0x24, 0x51, 0x1a, 0xff, 0x14, 0x8e, 0x19, 0xa9, 0x22, + 0x2f, 0x28, 0xf0, 0x23, 0x46, 0x1e, 0x3d, 0x1f, 0x8a, 0x23, 0xfe, 0x23, + 0x1b, 0x1f, 0x89, 0x1d, 0x04, 0x1e, 0x08, 0x16, 0x19, 0x08, 0xe1, 0xfe, + 0x1e, 0x01, 0xc1, 0x0d, 0xce, 0x17, 0xa6, 0x18, 0x60, 0x11, 0xb5, 0x05, + 0x7d, 0x02, 0x81, 0x09, 0x08, 0x10, 0x76, 0x0c, 0xc9, 0x00, 0x54, 0xf8, + 0x29, 0xf9, 0x31, 0xfc, 0xde, 0xfd, 0x32, 0x03, 0x41, 0x06, 0x83, 0x02, + 0x1c, 0x00, 0x92, 0x05, 0xae, 0x08, 0xde, 0x03, 0x6b, 0xfc, 0xc0, 0xf4, + 0x50, 0xf4, 0x62, 0xf9, 0x87, 0xfd, 0xd6, 0xff, 0xc1, 0x03, 0x30, 0x07, + 0x0b, 0x00, 0xc1, 0xf3, 0xa9, 0xf0, 0xf0, 0xf5, 0xdf, 0xf6, 0xd1, 0xee, + 0xa3, 0xe4, 0x63, 0xe6, 0x7d, 0xf2, 0xd2, 0xf8, 0x2b, 0xfb, 0x9f, 0xf9, + 0xfc, 0xf2, 0xf0, 0xee, 0xd7, 0xed, 0x6d, 0xef, 0xca, 0xf3, 0xd0, 0xf3, + 0x81, 0xf0, 0x1b, 0xf0, 0x82, 0xf0, 0xc5, 0xf0, 0x83, 0xf1, 0x6f, 0xf5, + 0x2e, 0xfe, 0x75, 0x04, 0xb3, 0x03, 0x00, 0x01, 0x52, 0x01, 0x1b, 0x05, + 0x62, 0x08, 0x97, 0x06, 0x85, 0x05, 0x4f, 0x06, 0x07, 0x03, 0x98, 0xfc, + 0x13, 0xf7, 0xc5, 0xf6, 0x50, 0xfb, 0x18, 0xfd, 0xa9, 0xf5, 0xb2, 0xe8, + 0x21, 0xdc, 0xaf, 0xd6, 0xe0, 0xdb, 0xb2, 0xe6, 0x47, 0xf0, 0x33, 0xf1, + 0xfc, 0xe7, 0x0d, 0xe0, 0xa0, 0xe5, 0xd5, 0xf1, 0xc8, 0xf8, 0x61, 0xf8, + 0x89, 0xf3, 0x24, 0xf0, 0x55, 0xe9, 0x0a, 0xdd, 0xc7, 0xd8, 0x00, 0xe2, + 0x4f, 0xec, 0xa0, 0xeb, 0x61, 0xde, 0xe1, 0xd2, 0x0a, 0xd6, 0x0f, 0xdf, + 0xee, 0xe3, 0xcb, 0xde, 0x6d, 0xd3, 0x3e, 0xd1, 0xb7, 0xd6, 0xc9, 0xd9, + 0x12, 0xd8, 0x45, 0xd6, 0x4f, 0xd6, 0x49, 0xd2, 0x53, 0xcf, 0x71, 0xd2, + 0xf7, 0xd4, 0xa1, 0xd2, 0xf0, 0xcd, 0x76, 0xd2, 0x22, 0xde, 0x71, 0xdf, + 0xbd, 0xda, 0xb5, 0xdc, 0xdc, 0xe5, 0x27, 0xef, 0x9a, 0xeb, 0x40, 0xe5, + 0x61, 0xea, 0x75, 0xec, 0xfb, 0xea, 0x98, 0xec, 0xcf, 0xe8, 0x90, 0xe3, + 0xcb, 0xe6, 0x75, 0xf1, 0x5e, 0xfb, 0x80, 0xfd, 0x00, 0xf9, 0xeb, 0xf5, + 0x13, 0xf7, 0xfb, 0xf5, 0x49, 0xf4, 0x38, 0xf7, 0xa5, 0xfb, 0x80, 0x02, + 0xdb, 0x08, 0x19, 0x09, 0x8e, 0x08, 0x12, 0x0a, 0xa4, 0x0d, 0x77, 0x10, + 0xa0, 0x12, 0xfe, 0x13, 0xbd, 0x10, 0xf7, 0x0e, 0xa5, 0x11, 0x62, 0x14, + 0x79, 0x19, 0x2d, 0x20, 0xf3, 0x21, 0xc7, 0x21, 0x89, 0x23, 0xd0, 0x27, + 0x63, 0x2b, 0x1a, 0x27, 0x2c, 0x1e, 0x1e, 0x15, 0x68, 0x10, 0xb9, 0x13, + 0xc6, 0x1a, 0xce, 0x1d, 0x1f, 0x1f, 0xa3, 0x1f, 0xcb, 0x1d, 0xed, 0x1f, + 0x7e, 0x23, 0x3d, 0x26, 0x4a, 0x29, 0xbf, 0x2b, 0x36, 0x28, 0xaf, 0x1f, + 0x1b, 0x1e, 0x91, 0x23, 0x28, 0x27, 0x09, 0x27, 0x8f, 0x27, 0x32, 0x26, + 0x7c, 0x24, 0x67, 0x22, 0x68, 0x1d, 0xdf, 0x1a, 0x1e, 0x1b, 0xfd, 0x1e, + 0xd7, 0x20, 0xfa, 0x1b, 0x36, 0x17, 0xc6, 0x1b, 0x8b, 0x25, 0xc5, 0x25, + 0x11, 0x1f, 0xb3, 0x1a, 0xe2, 0x18, 0x5e, 0x17, 0xf0, 0x12, 0xf2, 0x10, + 0x93, 0x13, 0x3f, 0x10, 0x57, 0x0b, 0x42, 0x0f, 0x09, 0x19, 0xee, 0x1f, + 0xcd, 0x1a, 0x13, 0x10, 0x7d, 0x10, 0x29, 0x18, 0x0c, 0x1c, 0xf2, 0x1c, + 0xfe, 0x16, 0x18, 0x11, 0x21, 0x15, 0x18, 0x1d, 0xfb, 0x21, 0xba, 0x1e, + 0x6a, 0x18, 0x8c, 0x14, 0x54, 0x17, 0x7b, 0x1e, 0xff, 0x20, 0xb4, 0x1f, + 0x15, 0x1b, 0xf3, 0x18, 0xf4, 0x1a, 0xc5, 0x1a, 0x30, 0x1d, 0x28, 0x22, + 0xab, 0x20, 0x5f, 0x1a, 0x79, 0x14, 0xb5, 0x11, 0xae, 0x12, 0xf0, 0x10, + 0x98, 0x0b, 0x30, 0x09, 0x2c, 0x0d, 0xb8, 0x13, 0x4b, 0x16, 0xac, 0x15, + 0x26, 0x14, 0x27, 0x14, 0x69, 0x16, 0x67, 0x1a, 0x6f, 0x1e, 0xb8, 0x1e, + 0xda, 0x1b, 0xe9, 0x19, 0x50, 0x1d, 0xe5, 0x22, 0xab, 0x1f, 0x6b, 0x17, + 0x94, 0x16, 0xa2, 0x18, 0x38, 0x1b, 0x3d, 0x1c, 0x43, 0x16, 0xf3, 0x10, + 0xf7, 0x0e, 0x06, 0x0f, 0x6c, 0x0f, 0xb3, 0x0b, 0xdc, 0x06, 0x2c, 0x06, + 0x2a, 0x07, 0xa9, 0x03, 0x2d, 0x00, 0x68, 0x03, 0x08, 0x07, 0x3b, 0x01, + 0x2d, 0xf5, 0xd5, 0xee, 0x66, 0xf3, 0x3f, 0xf9, 0x2f, 0xf6, 0x97, 0xf0, + 0x95, 0xf0, 0xc5, 0xf4, 0xcc, 0xf8, 0x67, 0xf9, 0x21, 0xf9, 0x52, 0xfa, + 0x7d, 0xf7, 0x02, 0xf2, 0x78, 0xef, 0x74, 0xf1, 0xc0, 0xf6, 0x29, 0xf7, + 0x93, 0xf4, 0x96, 0xf3, 0xe7, 0xf0, 0x0d, 0xef, 0x78, 0xed, 0x7b, 0xec, + 0x65, 0xec, 0xb2, 0xe9, 0xfb, 0xea, 0x07, 0xf1, 0x38, 0xf1, 0x20, 0xed, + 0x34, 0xec, 0xa5, 0xf1, 0xb8, 0xfa, 0x17, 0xff, 0xf7, 0xfa, 0xe5, 0xf2, + 0xe0, 0xeb, 0x12, 0xeb, 0x80, 0xf3, 0xf0, 0xfa, 0xdc, 0xfa, 0xee, 0xf9, + 0xeb, 0xfa, 0x8f, 0xfd, 0x03, 0x01, 0x7e, 0x02, 0x16, 0x03, 0x14, 0x03, + 0x7e, 0xfe, 0x5f, 0xfb, 0x86, 0xff, 0x71, 0x00, 0xb1, 0xfb, 0x63, 0xf8, + 0x6d, 0xf6, 0xea, 0xfa, 0xdb, 0xfc, 0xf2, 0xf7, 0xc9, 0xfa, 0x74, 0xff, + 0x5a, 0x01, 0x4d, 0xff, 0xaa, 0xf8, 0xeb, 0xf6, 0xfd, 0xf8, 0x51, 0xfa, + 0xa6, 0xf9, 0x7e, 0xf9, 0xe9, 0xfb, 0x22, 0xfe, 0xdd, 0xfd, 0x4f, 0xfd, + 0x59, 0xfe, 0xe3, 0xfd, 0xf5, 0xfd, 0x28, 0xff, 0x4b, 0xfd, 0xa9, 0xf8, + 0x87, 0xf3, 0xba, 0xf1, 0x65, 0xf4, 0xe2, 0xf5, 0xfa, 0xf1, 0x31, 0xee, + 0x9a, 0xed, 0x1a, 0xef, 0xa8, 0xf2, 0x68, 0xf2, 0x78, 0xee, 0x20, 0xeb, + 0xd1, 0xe9, 0xea, 0xeb, 0x63, 0xed, 0x81, 0xeb, 0x75, 0xe8, 0xc0, 0xe5, + 0x67, 0xe5, 0x05, 0xe8, 0x80, 0xe8, 0x20, 0xe5, 0x12, 0xe4, 0x2c, 0xe8, + 0x4d, 0xed, 0x42, 0xed, 0xd4, 0xe8, 0xcd, 0xe9, 0x52, 0xf1, 0xd7, 0xf1, + 0x10, 0xea, 0x65, 0xe5, 0xdb, 0xe5, 0xbc, 0xea, 0x48, 0xef, 0x3e, 0xee, + 0x59, 0xec, 0xad, 0xe7, 0x11, 0xe2, 0xe6, 0xe5, 0x78, 0xec, 0x78, 0xed, + 0xa4, 0xec, 0x5f, 0xeb, 0xa5, 0xe9, 0x43, 0xeb, 0x8a, 0xec, 0x61, 0xef, + 0x20, 0xf3, 0x7f, 0xf0, 0x9d, 0xed, 0x14, 0xec, 0xa6, 0xeb, 0x8f, 0xed, + 0x1e, 0xf1, 0xad, 0xf5, 0xd5, 0xf7, 0x7c, 0xf2, 0xbb, 0xe7, 0xb2, 0xe5, + 0x56, 0xeb, 0x39, 0xf1, 0x90, 0xf6, 0xf8, 0xf7, 0x44, 0xf7, 0x75, 0xf6, + 0xe3, 0xf4, 0x9c, 0xf6, 0x98, 0xf7, 0x40, 0xf2, 0x0d, 0xf1, 0xec, 0xf2, + 0x60, 0xee, 0x89, 0xe7, 0xff, 0xe2, 0x1b, 0xe3, 0xf0, 0xea, 0x62, 0xf1, + 0xdf, 0xf0, 0x0c, 0xf1, 0x5c, 0xf0, 0xbb, 0xef, 0x91, 0xed, 0x13, 0xe8, + 0xff, 0xe4, 0xe0, 0xe5, 0xe7, 0xe8, 0x6c, 0xea, 0x40, 0xe9, 0x25, 0xe9, + 0x81, 0xed, 0x07, 0xf0, 0x04, 0xec, 0x8a, 0xe5, 0x2a, 0xe2, 0x37, 0xe2, + 0x58, 0xe2, 0x6c, 0xe4, 0x2f, 0xe7, 0xb4, 0xe9, 0x7a, 0xe9, 0x50, 0xe6, + 0xdc, 0xe2, 0xa0, 0xde, 0x37, 0xdf, 0x8b, 0xe4, 0x1e, 0xe7, 0x79, 0xe4, + 0xa0, 0xe1, 0x26, 0xe2, 0x6c, 0xe1, 0x9a, 0xde, 0xb0, 0xdc, 0x9d, 0xde, + 0x31, 0xe3, 0xe1, 0xe4, 0x4c, 0xe3, 0x11, 0xe1, 0xcc, 0xe1, 0xc3, 0xe5, + 0x26, 0xe9, 0xaf, 0xea, 0x67, 0xe8, 0x55, 0xe2, 0xe7, 0xe0, 0xee, 0xe6, + 0xc8, 0xeb, 0x22, 0xeb, 0xb0, 0xe9, 0xd8, 0xec, 0xb2, 0xef, 0x2c, 0xf2, + 0x71, 0xf3, 0x1e, 0xf1, 0x78, 0xf2, 0x79, 0xf6, 0x94, 0xf7, 0x2e, 0xf4, + 0x72, 0xf2, 0x11, 0xf2, 0x5e, 0xf2, 0x75, 0xf6, 0xc8, 0xf6, 0xf1, 0xf0, + 0x18, 0xeb, 0x77, 0xec, 0xd2, 0xf1, 0xe6, 0xf4, 0x6c, 0xf2, 0x41, 0xf0, + 0x73, 0xf5, 0x46, 0xf9, 0x03, 0xf8, 0xe3, 0xf5, 0xdb, 0xf4, 0xf9, 0xf5, + 0xbe, 0xf6, 0x6f, 0xf6, 0x58, 0xfc, 0xef, 0x01, 0x5a, 0xff, 0xc9, 0xfc, + 0x5f, 0xfc, 0xf2, 0xff, 0xf3, 0x04, 0xf2, 0x04, 0xa3, 0x03, 0x01, 0x03, + 0x2e, 0x03, 0x00, 0x04, 0x2e, 0x04, 0x7c, 0x04, 0xc9, 0x03, 0xb1, 0x02, + 0xee, 0x03, 0x81, 0x07, 0x35, 0x06, 0x28, 0xff, 0x9a, 0xfc, 0x07, 0xff, + 0xd7, 0x05, 0x65, 0x09, 0xda, 0x05, 0xd2, 0x02, 0x24, 0x00, 0xf5, 0xff, + 0xce, 0x02, 0xe9, 0x05, 0xdb, 0x08, 0xed, 0x06, 0x42, 0xff, 0x3f, 0xfe, + 0x72, 0x08, 0x27, 0x13, 0xa7, 0x14, 0x5f, 0x0d, 0x1d, 0x08, 0xbf, 0x06, + 0xf8, 0x03, 0x2c, 0x05, 0x1e, 0x09, 0x8c, 0x06, 0xbd, 0x05, 0xf6, 0x09, + 0x25, 0x09, 0xe5, 0x05, 0x67, 0x06, 0x2e, 0x07, 0xec, 0x04, 0x9d, 0x00, + 0x02, 0xff, 0xcd, 0x07, 0x55, 0x11, 0xfa, 0x10, 0x38, 0x0e, 0x8d, 0x0f, + 0x30, 0x13, 0x2c, 0x17, 0x12, 0x14, 0xff, 0x0d, 0x6a, 0x0f, 0xe1, 0x10, + 0xd0, 0x14, 0xd6, 0x16, 0x93, 0x16, 0xdf, 0x19, 0x1d, 0x1a, 0x49, 0x18, + 0x9b, 0x16, 0x9b, 0x1b, 0x3e, 0x21, 0xef, 0x1f, 0xd3, 0x1d, 0x5e, 0x1f, + 0x22, 0x1f, 0x50, 0x1b, 0xa1, 0x17, 0x77, 0x16, 0xf5, 0x1b, 0xe0, 0x1c, + 0x05, 0x19, 0x30, 0x16, 0x51, 0x16, 0xcc, 0x1b, 0x4d, 0x1c, 0x82, 0x18, + 0xea, 0x13, 0x35, 0x10, 0x94, 0x13, 0xac, 0x1a, 0x37, 0x1c, 0x35, 0x19, + 0x10, 0x14, 0x16, 0x10, 0xfa, 0x11, 0xe8, 0x16, 0x4f, 0x1c, 0x84, 0x1c, + 0x3f, 0x16, 0xbd, 0x10, 0xa0, 0x10, 0xbd, 0x13, 0x12, 0x15, 0xb5, 0x12, + 0x4e, 0x12, 0xa7, 0x14, 0xab, 0x15, 0x13, 0x16, 0x72, 0x13, 0x72, 0x0f, + 0x46, 0x0c, 0xd3, 0x0a, 0xf6, 0x0b, 0xb6, 0x0d, 0x3f, 0x0b, 0x09, 0x05, + 0x2d, 0x02, 0x87, 0x02, 0x2e, 0x03, 0xd2, 0x00, 0x9e, 0xfe, 0xa7, 0xfd, + 0x74, 0xfb, 0x21, 0xfd, 0x6f, 0x01, 0x00, 0x02, 0x1d, 0xfe, 0xc7, 0xfa, + 0x3b, 0xfa, 0xeb, 0xfb, 0xee, 0xfe, 0x42, 0xff, 0xed, 0xfb, 0xba, 0xf9, + 0x57, 0xfb, 0x97, 0x00, 0x63, 0x06, 0x9e, 0x04, 0x2b, 0xfe, 0x0d, 0xfd, + 0xbd, 0x01, 0x2b, 0x07, 0x1b, 0x08, 0xf5, 0x04, 0x36, 0x03, 0x63, 0x02, + 0x71, 0xff, 0x5e, 0xff, 0xe6, 0x02, 0xbe, 0x05, 0xef, 0x03, 0xf8, 0xfc, + 0xb3, 0xf8, 0xe4, 0xf6, 0xc4, 0xf6, 0xa4, 0xfc, 0x2f, 0x01, 0x0a, 0xff, + 0x1a, 0xfc, 0x05, 0xfc, 0xbe, 0xff, 0x4c, 0x02, 0xf9, 0xfe, 0x56, 0xfd, + 0x97, 0x01, 0x16, 0x06, 0x18, 0x07, 0x4f, 0x06, 0xec, 0x04, 0x21, 0x08, + 0x10, 0x0e, 0x8d, 0x0c, 0x50, 0x07, 0x09, 0x05, 0x62, 0x05, 0xfc, 0x03, + 0x7c, 0x02, 0x0a, 0x04, 0xb1, 0x05, 0x7b, 0x06, 0x45, 0x06, 0xa3, 0x07, + 0x8d, 0x06, 0x76, 0xff, 0xdf, 0xfa, 0xf0, 0xff, 0x0c, 0x07, 0x22, 0x08, + 0x3c, 0x05, 0xe0, 0x00, 0x4e, 0x00, 0x9b, 0x03, 0x47, 0x08, 0xa9, 0x0a, + 0x89, 0x08, 0x90, 0x03, 0xdf, 0xfd, 0x07, 0xfe, 0x95, 0x04, 0x64, 0x0b, + 0x41, 0x0a, 0x86, 0x06, 0xfa, 0x04, 0xb1, 0x03, 0x41, 0x07, 0x7d, 0x07, + 0xe4, 0x01, 0x3b, 0xfc, 0x5a, 0xfb, 0xf4, 0xff, 0x69, 0x02, 0xc1, 0x01, + 0x91, 0xfd, 0x55, 0xf8, 0x01, 0xf7, 0xf8, 0xf9, 0x30, 0xfd, 0x5b, 0x00, + 0x7c, 0x03, 0x4d, 0x02, 0xe6, 0xfe, 0x98, 0xfd, 0x72, 0xff, 0x1c, 0x01, + 0xf4, 0x03, 0xaa, 0x07, 0xea, 0x09, 0xd3, 0x07, 0x5f, 0x01, 0xa2, 0x02, + 0x0c, 0x0b, 0xb9, 0x0f, 0xcc, 0x0f, 0x0b, 0x0f, 0x8a, 0x0e, 0xdf, 0x0e, + 0x2e, 0x0f, 0x70, 0x0c, 0x5f, 0x0b, 0x30, 0x0a, 0x70, 0x08, 0x17, 0x0b, + 0xe7, 0x0d, 0xe6, 0x0f, 0x67, 0x0f, 0x55, 0x0c, 0x8e, 0x0b, 0x06, 0x0b, + 0x79, 0x0a, 0xea, 0x0b, 0x9c, 0x0e, 0x75, 0x10, 0x3d, 0x11, 0x00, 0x11, + 0x62, 0x0c, 0x7b, 0x07, 0x3e, 0x06, 0x48, 0x06, 0x56, 0x09, 0xae, 0x0f, + 0x52, 0x13, 0x08, 0x0f, 0x6c, 0x07, 0x66, 0x06, 0xb5, 0x0f, 0xd7, 0x16, + 0x85, 0x12, 0x31, 0x0a, 0x6d, 0x05, 0x81, 0x05, 0x2e, 0x09, 0xd6, 0x0d, + 0xd4, 0x0e, 0x3c, 0x0b, 0xd2, 0x04, 0x05, 0x02, 0x63, 0x04, 0x27, 0x03, + 0x16, 0xfe, 0x68, 0xfa, 0x7e, 0xfc, 0xc4, 0x02, 0x35, 0x02, 0x45, 0xfd, + 0x10, 0xfe, 0x7f, 0xfc, 0x5e, 0xf8, 0xed, 0xfa, 0x4a, 0x02, 0x3b, 0x09, + 0x5a, 0x07, 0x01, 0xff, 0x00, 0xfa, 0x2c, 0xf9, 0xc7, 0xf9, 0x23, 0xfd, + 0x73, 0x05, 0xad, 0x0c, 0xb1, 0x0c, 0x6e, 0x06, 0x1f, 0xff, 0xe6, 0xfd, + 0x33, 0x03, 0xb4, 0x09, 0x10, 0x0c, 0x40, 0x08, 0xdb, 0x02, 0x47, 0xfe, + 0xf3, 0xfe, 0x99, 0x03, 0x31, 0x04, 0x9e, 0xff, 0x90, 0xf8, 0x6b, 0xf5, + 0xbb, 0xf8, 0x89, 0xfd, 0xfb, 0xfd, 0x3f, 0xfa, 0x44, 0xf7, 0x66, 0xf8, + 0x94, 0xf9, 0x7a, 0xfa, 0xd0, 0xfe, 0x67, 0xff, 0x2a, 0xfc, 0xde, 0xfa, + 0x34, 0xfb, 0x91, 0xfe, 0x71, 0x02, 0x74, 0x02, 0xae, 0x00, 0x30, 0xff, + 0x05, 0xfe, 0x55, 0x00, 0x5c, 0x04, 0x72, 0x06, 0x60, 0x07, 0x46, 0x06, + 0x85, 0x03, 0xcb, 0x01, 0x61, 0x00, 0x97, 0x02, 0x30, 0x08, 0x0a, 0x0a, + 0xaa, 0x05, 0xb0, 0xfd, 0x09, 0xf8, 0xf3, 0xf8, 0xf6, 0xfe, 0xdd, 0x01, + 0x09, 0xff, 0xcb, 0xf9, 0x25, 0xf6, 0x31, 0xf8, 0xbc, 0xfc, 0x05, 0xff, + 0xdb, 0xfe, 0xd8, 0xfd, 0x5e, 0xfd, 0x51, 0x00, 0x22, 0x03, 0xcc, 0x00, + 0x6b, 0xfe, 0xc5, 0xfe, 0x55, 0xfe, 0x5b, 0xf9, 0x93, 0xf4, 0xba, 0xf8, + 0xfa, 0x02, 0x78, 0x06, 0xee, 0xfc, 0xe5, 0xf2, 0x7a, 0xf3, 0xfc, 0xf7, + 0xa4, 0xfb, 0xe1, 0xfb, 0xe8, 0xf8, 0xd6, 0xf6, 0x4d, 0xf5, 0x0c, 0xf5, + 0x5e, 0xf4, 0x9f, 0xf4, 0x7e, 0xf6, 0xb4, 0xf7, 0xc9, 0xf8, 0x72, 0xf8, + 0x73, 0xf6, 0x8a, 0xf5, 0x67, 0xf8, 0x30, 0xfb, 0x13, 0xfd, 0x08, 0xfc, + 0x2b, 0xfb, 0xdf, 0xff, 0x4d, 0x03, 0xb4, 0x02, 0xc1, 0xff, 0xe6, 0xfd, + 0xe6, 0xff, 0x31, 0x04, 0x26, 0x05, 0xbd, 0x02, 0x30, 0xfe, 0xc6, 0xfa, + 0x6b, 0x00, 0xf2, 0x06, 0x76, 0x06, 0x45, 0x02, 0x00, 0xff, 0x9b, 0xff, + 0x22, 0x01, 0xc8, 0xff, 0xc9, 0xff, 0x07, 0x04, 0x68, 0x03, 0x40, 0x00, + 0x70, 0x00, 0x83, 0xfd, 0xe8, 0xf8, 0x7b, 0xf8, 0x0d, 0xfb, 0x35, 0xfc, + 0xb8, 0xfb, 0xa4, 0xfa, 0x5e, 0xf7, 0x0e, 0xf6, 0xa6, 0xfa, 0x83, 0x01, + 0xfd, 0x03, 0xdf, 0x00, 0xd6, 0xfd, 0x4c, 0xff, 0x38, 0x01, 0x70, 0x00, + 0x23, 0x04, 0x82, 0x07, 0x96, 0x03, 0xa3, 0x00, 0xa6, 0x01, 0xa8, 0x03, + 0x52, 0x06, 0xde, 0x06, 0x00, 0x04, 0xca, 0x00, 0xe1, 0xfc, 0x29, 0xfb, + 0xda, 0xfd, 0xff, 0xfd, 0xf3, 0xfb, 0x52, 0xfe, 0x47, 0x02, 0xb1, 0x01, + 0xbf, 0xfb, 0x58, 0xf5, 0x72, 0xf8, 0x57, 0xfe, 0xb2, 0xfb, 0x4c, 0xf9, + 0x38, 0xfb, 0xa0, 0xfc, 0x55, 0x00, 0x90, 0x01, 0xde, 0xfe, 0x9a, 0xff, + 0xa0, 0xff, 0x44, 0x03, 0xa1, 0x09, 0xcf, 0x07, 0xf8, 0x02, 0xf2, 0x01, + 0xf9, 0x03, 0x7c, 0x06, 0x8f, 0x06, 0xb3, 0x02, 0x5d, 0xff, 0x97, 0xfe, + 0xea, 0xfd, 0x0b, 0xff, 0x62, 0xfd, 0x02, 0xf8, 0x14, 0xf7, 0x4f, 0xfa, + 0xad, 0xfa, 0xcf, 0xf8, 0x6d, 0xf9, 0xfe, 0xfa, 0x41, 0xfd, 0xa9, 0xfd, + 0xed, 0xf8, 0xe1, 0xf5, 0x03, 0xfa, 0xf0, 0x02, 0x0c, 0x06, 0x9d, 0x02, + 0x5c, 0xff, 0x93, 0xfb, 0x24, 0xfc, 0x88, 0x01, 0x5c, 0x06, 0xce, 0x06, + 0xa9, 0x04, 0x7e, 0x03, 0x65, 0x05, 0x29, 0x09, 0xec, 0x06, 0xb7, 0x02, + 0xf3, 0x01, 0xac, 0x02, 0xda, 0x03, 0xde, 0x01, 0x8e, 0xfb, 0xfc, 0xf7, + 0x7f, 0xf9, 0x92, 0xfd, 0x5c, 0x01, 0x1a, 0xfe, 0x4f, 0xfa, 0xd1, 0xfc, + 0x19, 0xff, 0x2d, 0xff, 0x7d, 0xff, 0xb7, 0xfe, 0x4d, 0xfe, 0x5d, 0x00, + 0x2d, 0xff, 0xb6, 0xfb, 0x74, 0xf9, 0xe8, 0xf7, 0x6d, 0xfa, 0xd3, 0xfc, + 0x34, 0xfe, 0x48, 0x01, 0x5c, 0x02, 0xb8, 0x00, 0x99, 0xfc, 0xa7, 0xf8, + 0xf8, 0xf8, 0x3e, 0xfd, 0x8d, 0x00, 0x7c, 0x00, 0x98, 0xfe, 0xf8, 0xfc, + 0xd5, 0xfe, 0x7d, 0xfe, 0xcd, 0xfc, 0x43, 0xff, 0x7c, 0xff, 0x8a, 0xfc, + 0x9a, 0xfc, 0x4f, 0xfe, 0xc2, 0xff, 0xb3, 0x00, 0xed, 0xfc, 0xf6, 0xf9, + 0xfc, 0xfb, 0x6e, 0xff, 0x29, 0x01, 0x3a, 0xff, 0x8d, 0xfe, 0x34, 0xfe, + 0xfc, 0xfa, 0xbb, 0xf9, 0xcd, 0xfb, 0x94, 0xfd, 0x5d, 0xff, 0xe8, 0xfe, + 0x5a, 0xfd, 0x13, 0xfe, 0x52, 0x00, 0xce, 0x02, 0x0e, 0x02, 0xab, 0x02, + 0xd4, 0x03, 0x98, 0x02, 0x81, 0x00, 0xf1, 0xfc, 0xd5, 0xfb, 0xe9, 0xff, + 0x86, 0x06, 0xef, 0x08, 0x00, 0x04, 0xf5, 0xfd, 0x25, 0xfd, 0xac, 0xfe, + 0xc4, 0x01, 0xd6, 0x01, 0xfc, 0xfa, 0xdc, 0xf6, 0xdf, 0xf7, 0xf2, 0xf9, + 0x5b, 0xfa, 0xac, 0xfc, 0xe8, 0xff, 0x98, 0x01, 0x1e, 0x03, 0xba, 0x01, + 0x52, 0x01, 0xbb, 0x02, 0x1c, 0x04, 0xdb, 0x05, 0xc0, 0x06, 0xae, 0x06, + 0x65, 0x08, 0x23, 0x09, 0x13, 0x08, 0xbe, 0x08, 0x35, 0x08, 0x2d, 0x07, + 0xb6, 0x05, 0x03, 0x0a, 0x84, 0x10, 0xb1, 0x0c, 0x35, 0x03, 0xa6, 0xfc, + 0x72, 0xfd, 0x1b, 0x04, 0x91, 0x08, 0xcd, 0x04, 0x8a, 0xff, 0x76, 0xfb, + 0x39, 0xfb, 0x9b, 0xff, 0x3a, 0xff, 0x82, 0xfc, 0x72, 0xfb, 0x5d, 0xfc, + 0x85, 0xfd, 0x43, 0xff, 0xd4, 0x01, 0x65, 0x03, 0x2e, 0x06, 0x7d, 0x07, + 0x13, 0x06, 0xa8, 0x03, 0x1b, 0x02, 0x18, 0x03, 0x6f, 0x05, 0xd0, 0x07, + 0x59, 0x08, 0x4b, 0x03, 0x27, 0xfe, 0x9d, 0xff, 0x5a, 0x03, 0xd7, 0x05, + 0x6b, 0x04, 0x1c, 0x00, 0xdd, 0xfd, 0xc0, 0xff, 0xd7, 0x00, 0x94, 0xfe, + 0x40, 0xfc, 0x15, 0xfb, 0xad, 0xfd, 0x33, 0xff, 0x3e, 0xfe, 0x98, 0xfe, + 0xb1, 0xff, 0x14, 0x01, 0xe0, 0x01, 0x2b, 0x04, 0xae, 0x05, 0x10, 0x05, + 0xb0, 0x03, 0x02, 0x03, 0x49, 0x04, 0xd5, 0x03, 0x9c, 0x03, 0x3b, 0x05, + 0x83, 0x04, 0x79, 0x00, 0xd5, 0xfe, 0x94, 0xff, 0x5e, 0xff, 0x8c, 0xff, + 0xdb, 0xff, 0x0e, 0x02, 0xda, 0x01, 0x59, 0xfc, 0x49, 0xf7, 0xf5, 0xf5, + 0x95, 0xf7, 0x6b, 0xfa, 0x45, 0xff, 0x32, 0x01, 0x09, 0xfe, 0x03, 0xf7, + 0xc9, 0xf2, 0x8c, 0xf8, 0x2a, 0xfd, 0xc9, 0xfb, 0x1b, 0xfc, 0x74, 0xfd, + 0x8c, 0xfb, 0x89, 0xf7, 0xdd, 0xf5, 0x90, 0xfb, 0x4e, 0x01, 0x1f, 0xfc, + 0x47, 0xf5, 0xc3, 0xf5, 0x8b, 0xf8, 0x84, 0xfb, 0x08, 0xfc, 0x00, 0xf7, + 0x35, 0xf3, 0xa6, 0xf2, 0x1a, 0xf5, 0x45, 0xf8, 0xbc, 0xf6, 0x80, 0xf7, + 0xb7, 0xfa, 0x6c, 0xfc, 0x18, 0xfb, 0x8e, 0xf8, 0xdb, 0xf9, 0x5a, 0xfa, + 0x51, 0xf9, 0xb8, 0xf8, 0xf9, 0xfa, 0xe7, 0xfc, 0x50, 0xf9, 0x5a, 0xf4, + 0x04, 0xf4, 0xf9, 0xf6, 0xee, 0xf8, 0x8f, 0xfc, 0xba, 0xfd, 0x73, 0xfb, + 0x9d, 0xf7, 0xb8, 0xf3, 0x68, 0xf6, 0x8e, 0xfa, 0xbd, 0xfc, 0xf1, 0xfb, + 0x7e, 0xf8, 0x55, 0xf6, 0x5f, 0xf5, 0x59, 0xf8, 0xb5, 0xfd, 0x33, 0xff, + 0xce, 0xfb, 0xf9, 0xf8, 0x8b, 0xfa, 0x18, 0xfc, 0x96, 0xf8, 0xf4, 0xf4, + 0xe0, 0xf6, 0x6d, 0xfc, 0xda, 0xfd, 0x5c, 0xf8, 0xc7, 0xf2, 0x88, 0xf0, + 0x8e, 0xf4, 0x43, 0xf9, 0xeb, 0xf8, 0x3b, 0xf7, 0x0f, 0xf6, 0x3e, 0xf9, + 0x2a, 0xfc, 0x76, 0xfe, 0x0c, 0x02, 0xd5, 0xff, 0x85, 0xfc, 0x73, 0xfd, + 0xb1, 0x00, 0x6b, 0x05, 0x99, 0x07, 0x8e, 0x05, 0xbc, 0x03, 0xeb, 0x03, + 0x8e, 0x04, 0x12, 0x03, 0xd8, 0x01, 0x7f, 0x05, 0x6f, 0x07, 0x86, 0x02, + 0x70, 0xfa, 0x7b, 0xf5, 0xd9, 0xf8, 0x4a, 0x00, 0xe6, 0x02, 0x04, 0xff, + 0x28, 0xf8, 0xd4, 0xf4, 0x02, 0xf8, 0x7e, 0xfc, 0x05, 0xfd, 0x0f, 0xfb, + 0x5c, 0xfb, 0x3b, 0xfc, 0x33, 0xfd, 0xd4, 0xff, 0xa2, 0x01, 0xd0, 0x01, + 0x6d, 0x00, 0xef, 0xff, 0x27, 0x04, 0x12, 0x07, 0xcb, 0x03, 0x10, 0x04, + 0xcd, 0x08, 0xf2, 0x09, 0x12, 0x08, 0xd1, 0x03, 0x72, 0x00, 0x8b, 0x02, + 0x51, 0x06, 0xf6, 0x06, 0x80, 0x04, 0xb9, 0x01, 0x36, 0x00, 0x52, 0xff, + 0xca, 0xff, 0x2f, 0x00, 0x15, 0xfd, 0x9f, 0xf8, 0x6e, 0xf8, 0x19, 0xfd, + 0x3d, 0x03, 0xae, 0x04, 0x64, 0x00, 0xd2, 0xfe, 0xd3, 0x01, 0x7d, 0x04, + 0x9d, 0x03, 0xd2, 0x00, 0x64, 0x01, 0x3e, 0x05, 0x79, 0x09, 0x8e, 0x0a, + 0x63, 0x08, 0x44, 0x04, 0xdf, 0xff, 0x62, 0x00, 0x77, 0x06, 0x07, 0x0c, + 0x41, 0x0a, 0x25, 0x04, 0xf3, 0xff, 0xf7, 0xfe, 0xcd, 0xff, 0xd4, 0xff, + 0xf4, 0xff, 0x74, 0xfe, 0x26, 0xfa, 0x60, 0xf7, 0x17, 0xf8, 0x83, 0xf9, + 0x6f, 0xf9, 0x72, 0xf9, 0x7f, 0xfb, 0x83, 0xfd, 0x07, 0xfc, 0xe4, 0xf7, + 0xb2, 0xf5, 0x90, 0xf7, 0x01, 0xfd, 0x7b, 0x02, 0x4d, 0x03, 0xc7, 0xfe, + 0xcb, 0xf7, 0xd7, 0xf5, 0x8a, 0xfc, 0xa8, 0x04, 0xae, 0x06, 0x3d, 0x01, + 0x6f, 0xfb, 0xbc, 0xfa, 0x33, 0xfe, 0xed, 0x01, 0xc9, 0x02, 0xc9, 0x00, + 0x48, 0xfd, 0x1f, 0xfc, 0xa1, 0xfc, 0x2d, 0xfc, 0x6c, 0xfc, 0x57, 0xff, + 0x9a, 0x02, 0xf7, 0x01, 0x62, 0xfe, 0xc7, 0xfc, 0x0c, 0xff, 0x1b, 0x03, + 0x99, 0x04, 0x25, 0x00, 0x88, 0xfc, 0xbd, 0xfd, 0x7d, 0x01, 0xe5, 0x00, + 0x67, 0xfb, 0xd4, 0xf9, 0x2a, 0xff, 0xef, 0x06, 0xff, 0x04, 0x2b, 0xfd, + 0x1c, 0xf7, 0x2e, 0xf8, 0xef, 0x00, 0x24, 0x05, 0x45, 0x04, 0x00, 0x01, + 0xc0, 0xfe, 0xeb, 0xfd, 0x3d, 0xfe, 0x44, 0x00, 0x91, 0x02, 0x37, 0x03, + 0x7b, 0x03, 0x6d, 0x03, 0xfe, 0xfe, 0x86, 0xfd, 0xc1, 0xff, 0x34, 0x03, + 0x44, 0x04, 0x44, 0x01, 0x9e, 0xfc, 0x26, 0xf9, 0x1e, 0xfb, 0x4d, 0xfe, + 0xc0, 0x00, 0xfd, 0xff, 0x88, 0xfd, 0x91, 0xfe, 0xea, 0x02, 0x6b, 0x06, + 0xd1, 0x07, 0x65, 0x08, 0x0f, 0x08, 0x29, 0x08, 0xd4, 0x06, 0xc3, 0x06, + 0x36, 0x09, 0xb2, 0x0a, 0x75, 0x0b, 0xec, 0x0c, 0x8a, 0x0b, 0xf2, 0x08, + 0xc2, 0x08, 0x92, 0x07, 0x87, 0x05, 0x1f, 0x04, 0x4b, 0x03, 0x0a, 0x03, + 0x20, 0x04, 0x7a, 0x05, 0x25, 0x05, 0x96, 0xff, 0xf7, 0xf8, 0x9a, 0xf7, + 0x06, 0xfc, 0xe2, 0x01, 0x0b, 0x04, 0xe1, 0x03, 0x44, 0xff, 0x24, 0xf9, + 0x1a, 0xf9, 0xa2, 0xfe, 0xbd, 0x02, 0xb2, 0x06, 0xa1, 0x0a, 0xba, 0x09, + 0x3f, 0x08, 0x14, 0x08, 0x0e, 0x08, 0x70, 0x09, 0x34, 0x0c, 0x71, 0x0c, + 0xb3, 0x0b, 0x7f, 0x07, 0x0f, 0x02, 0x0f, 0x01, 0xb2, 0x02, 0xef, 0x03, + 0x99, 0x03, 0xa3, 0xff, 0x5a, 0xf8, 0x46, 0xf6, 0xcb, 0xf7, 0x8f, 0xfb, + 0x21, 0xfd, 0x71, 0xfb, 0x9b, 0xfc, 0xce, 0x00, 0x26, 0x01, 0x6b, 0xfb, + 0xf4, 0xf9, 0xfa, 0xfc, 0x39, 0x04, 0x48, 0x05, 0x31, 0x01, 0x96, 0x03, + 0xe6, 0x07, 0x20, 0x09, 0x52, 0x07, 0xd5, 0x03, 0x18, 0x03, 0xbc, 0x08, + 0x40, 0x0b, 0xef, 0x0a, 0xa5, 0x05, 0x34, 0x01, 0xc1, 0x02, 0xb9, 0x03, + 0x3f, 0x03, 0x87, 0xff, 0x95, 0xfd, 0x9d, 0xfb, 0xa8, 0xfa, 0x96, 0xfb, + 0x0a, 0xfd, 0xdc, 0xfb, 0x6a, 0xf6, 0x63, 0xef, 0x89, 0xed, 0x3b, 0xef, + 0x60, 0xef, 0xfa, 0xf4, 0xc5, 0xf9, 0x4d, 0xfd, 0x7a, 0xfe, 0x48, 0xff, + 0x34, 0x05, 0x58, 0x0d, 0x38, 0x14, 0x62, 0x14, 0xc1, 0x08, 0xbd, 0xf4, + 0x4c, 0xee, 0xad, 0xfc, 0xf3, 0x07, 0x35, 0x02, 0xb0, 0x00, 0x76, 0xff, + 0xbb, 0xf4, 0x3c, 0xf3, 0xd9, 0xfa, 0x11, 0xfa, 0x15, 0xf8, 0xca, 0xfa, + 0x74, 0xf4, 0xeb, 0xf9, 0x76, 0x06, 0x1b, 0x06, 0x15, 0x07, 0x1b, 0x0c, + 0x43, 0x04, 0x5a, 0xfb, 0x65, 0x03, 0xd0, 0x03, 0x11, 0x03, 0x82, 0x0a, + 0xb1, 0x04, 0xe0, 0x04, 0xb9, 0x08, 0x8d, 0xfe, 0x15, 0xff, 0x17, 0xf8, + 0x51, 0xf0, 0x4f, 0xf1, 0x57, 0xf3, 0xc5, 0xfb, 0xab, 0xf9, 0x65, 0x01, + 0xac, 0xfc, 0x10, 0xfb, 0xc3, 0x00, 0x09, 0xfd, 0xa3, 0x01, 0x82, 0xff, + 0x62, 0x04, 0x98, 0x03, 0xce, 0x08, 0x5e, 0x05, 0x3f, 0xff, 0xe7, 0x06, + 0x96, 0x06, 0x02, 0x05, 0x15, 0xfd, 0x05, 0x04, 0x36, 0x05, 0x3f, 0x07, + 0xeb, 0x06, 0xae, 0x01, 0xd0, 0x06, 0xc6, 0x05, 0xa8, 0x07, 0x04, 0x01, + 0x17, 0x01, 0xb9, 0x01, 0x2c, 0x03, 0xca, 0x04, 0x80, 0x03, 0x5d, 0x05, + 0x00, 0x06, 0x69, 0x0a, 0x7a, 0x05, 0x38, 0x02, 0xb4, 0xfb, 0xba, 0xfd, + 0x34, 0x06, 0x8d, 0x0f, 0x3e, 0x17, 0xd1, 0x15, 0xb6, 0x15, 0x01, 0x0a, + 0x39, 0x06, 0xdd, 0x06, 0x2d, 0x03, 0xba, 0xfe, 0x2f, 0xfc, 0x49, 0xf8, + 0x99, 0xf8, 0xc7, 0x04, 0xdf, 0x06, 0xf9, 0xff, 0xd1, 0xed, 0x55, 0xe5, + 0xd9, 0xed, 0x63, 0xfd, 0xb3, 0x02, 0xd4, 0xf4, 0x6f, 0xee, 0xd7, 0xf6, + 0xb5, 0x04, 0xaf, 0x0a, 0x57, 0x14, 0xbd, 0x11, 0xfb, 0x03, 0xfe, 0xfb, + 0xe0, 0xfc, 0xf8, 0x0a, 0x2f, 0x14, 0xa8, 0x10, 0x73, 0x01, 0xf4, 0xfb, + 0x34, 0x01, 0xc7, 0x0b, 0xe7, 0x12, 0x58, 0x0b, 0x02, 0xf8, 0x24, 0xf3, + 0xa0, 0x00, 0xff, 0x01, 0x1c, 0x00, 0x54, 0xfb, 0x38, 0xf7, 0xdf, 0xf5, + 0x9c, 0xfc, 0x3e, 0x03, 0x6f, 0x05, 0xee, 0x04, 0x5e, 0x07, 0x7c, 0x09, + 0x7f, 0x02, 0xe2, 0x0c, 0xfa, 0x0f, 0x8a, 0x21, 0xb6, 0x1f, 0x9c, 0x0a, + 0x99, 0x06, 0xa6, 0x03, 0xe0, 0x13, 0x79, 0x08, 0xf3, 0x04, 0x8a, 0xf9, + 0xc9, 0xf4, 0x45, 0xfd, 0x0c, 0xf9, 0xbc, 0x04, 0x55, 0xf9, 0xbc, 0xfd, + 0x35, 0xf7, 0x45, 0xf4, 0x1f, 0xf7, 0x56, 0xf7, 0xe3, 0xfd, 0x03, 0xf7, + 0x0b, 0xfe, 0x79, 0xf7, 0x49, 0x05, 0x5e, 0x03, 0x0c, 0xf9, 0x8a, 0xfb, + 0xbd, 0xf7, 0x3d, 0xfe, 0xe4, 0xf7, 0x24, 0xf8, 0x1d, 0xf6, 0x8d, 0xf9, + 0x33, 0xff, 0x30, 0x09, 0xfc, 0x05, 0x83, 0xfa, 0xbb, 0x00, 0x77, 0x02, + 0xeb, 0x09, 0x2c, 0x0a, 0x21, 0x01, 0x94, 0xfc, 0x75, 0x04, 0x27, 0x02, + 0xae, 0x05, 0x44, 0x0e, 0xea, 0x06, 0x5d, 0x01, 0xba, 0xfb, 0x36, 0xf9, + 0x39, 0xf5, 0x3b, 0xf6, 0x4c, 0xf5, 0xc2, 0xfa, 0x8d, 0xfe, 0x91, 0xf9, + 0x84, 0xf4, 0x28, 0xf3, 0x39, 0xf6, 0x9c, 0xf6, 0x08, 0xf9, 0x79, 0xf6, + 0x9e, 0xfb, 0x0e, 0xfc, 0xf7, 0x00, 0xfa, 0x01, 0x60, 0xf8, 0xe3, 0xf4, + 0x11, 0xf9, 0x2e, 0x07, 0xb1, 0x08, 0x67, 0x0b, 0xc0, 0x07, 0x1e, 0x04, + 0x83, 0x04, 0x29, 0x05, 0xfe, 0x05, 0xd1, 0x03, 0xa6, 0x05, 0xd4, 0x01, + 0xec, 0x05, 0xeb, 0x04, 0x1f, 0xff, 0x78, 0xfc, 0x4d, 0xfe, 0xd9, 0xff, + 0x2d, 0x01, 0x39, 0xfd, 0xe4, 0xf0, 0x08, 0xf1, 0xb3, 0xf5, 0x70, 0xfc, + 0x5b, 0xfc, 0x57, 0xfd, 0x30, 0xf5, 0x64, 0xf5, 0xf5, 0xfe, 0xd1, 0xf9, + 0x77, 0xff, 0x5e, 0xf9, 0x24, 0xfc, 0xf5, 0x00, 0xb6, 0xfa, 0xfa, 0xfa, + 0xac, 0xf5, 0x48, 0xf9, 0x8a, 0xf8, 0xfe, 0xff, 0xb4, 0x05, 0xc2, 0x02, + 0x5a, 0x06, 0xf8, 0xfc, 0xd6, 0xfe, 0x61, 0xff, 0x6d, 0xfe, 0x5b, 0x02, + 0x03, 0xfc, 0x10, 0xfc, 0xdc, 0xf4, 0x9a, 0xf2, 0xbd, 0xf4, 0x01, 0xf7, + 0xae, 0xf8, 0xdb, 0xf2, 0x76, 0xf6, 0x5b, 0xf7, 0xc7, 0xf9, 0x4b, 0x02, + 0x73, 0x06, 0x79, 0x02, 0xcc, 0x06, 0xbf, 0x0c, 0x86, 0x11, 0x10, 0x19, + 0x79, 0x17, 0x38, 0x17, 0xd5, 0x0c, 0x4a, 0x07, 0xfd, 0x09, 0x58, 0x13, + 0x06, 0x17, 0x26, 0x0e, 0x56, 0x0b, 0xbb, 0x07, 0x7a, 0x0a, 0x96, 0x04, + 0xaf, 0x05, 0x45, 0x06, 0x2e, 0x06, 0xf0, 0x09, 0x0a, 0xfc, 0x0d, 0xf4, + 0xd9, 0xee, 0x4e, 0xfc, 0x50, 0x08, 0xae, 0x08, 0xed, 0x03, 0xbe, 0xfa, + 0x6a, 0xfe, 0xea, 0xfd, 0x24, 0x04, 0x54, 0x05, 0xd0, 0x04, 0xe5, 0x03, + 0x76, 0x02, 0xec, 0x0c, 0xb0, 0x0c, 0x7c, 0x09, 0x32, 0x04, 0x58, 0x01, + 0xf5, 0xfe, 0x1c, 0xfc, 0x4e, 0xfe, 0x27, 0xfc, 0xb2, 0xfa, 0x7e, 0xf3, + 0xff, 0xed, 0x2d, 0xf5, 0x58, 0x01, 0x19, 0x07, 0x6b, 0x02, 0x9b, 0xfe, + 0xe7, 0xfd, 0xb0, 0x01, 0x3b, 0x07, 0x29, 0x09, 0x20, 0x07, 0xba, 0x01, + 0xb1, 0x01, 0x04, 0x07, 0x23, 0x0b, 0x2e, 0x07, 0x09, 0x04, 0x3a, 0x08, + 0xee, 0x0c, 0xa5, 0x0c, 0x35, 0x05, 0x12, 0x05, 0xa7, 0x05, 0x66, 0x09, + 0xe2, 0x08, 0x15, 0x02, 0x8a, 0x01, 0xdd, 0xff, 0x6f, 0x04, 0x39, 0xfe, + 0x1f, 0xf7, 0x9f, 0xf3, 0x9b, 0xf4, 0x21, 0xf9, 0x4d, 0xf1, 0xe4, 0xef, + 0x92, 0xee, 0x6d, 0xef, 0xfe, 0xf1, 0xcc, 0xf8, 0xa0, 0xfa, 0xce, 0xf5, + 0x2b, 0xf5, 0xa6, 0xf1, 0x22, 0xf2, 0x28, 0xf1, 0xa3, 0xf3, 0xee, 0xee, + 0x81, 0xea, 0x95, 0xee, 0x2a, 0xf0, 0x5f, 0xf1, 0x8e, 0xf0, 0xe8, 0xf0, + 0x7b, 0xf4, 0x1c, 0xfa, 0xf5, 0xf8, 0xd0, 0xfa, 0x7a, 0xfb, 0xed, 0xfe, + 0x42, 0x02, 0xcc, 0x01, 0x94, 0xfe, 0xa1, 0xf9, 0x33, 0x06, 0x3b, 0x0b, + 0xd4, 0x0e, 0x65, 0x0d, 0x8f, 0x07, 0xda, 0x0b, 0xeb, 0x0e, 0xa6, 0x0f, + 0x23, 0x07, 0xc8, 0x00, 0x4b, 0xfa, 0x6e, 0xfc, 0x0b, 0xff, 0xa5, 0xfd, + 0x28, 0xfb, 0x2a, 0xf9, 0xf3, 0xfe, 0xf0, 0xf9, 0x06, 0xfb, 0xf1, 0xfe, + 0xde, 0x01, 0x5c, 0x02, 0xcb, 0xfd, 0xa2, 0xfb, 0x0c, 0xfc, 0x05, 0x04, + 0xb6, 0x01, 0x54, 0xfd, 0x3e, 0xff, 0xef, 0x04, 0xdd, 0x02, 0x8a, 0xf8, + 0xce, 0xf4, 0x17, 0xf3, 0xc2, 0xf1, 0xfc, 0xf0, 0xd0, 0xf2, 0x45, 0xf2, + 0xae, 0xf8, 0x58, 0xff, 0x31, 0x02, 0x97, 0x05, 0xbb, 0x05, 0xdb, 0x04, + 0x1f, 0xfd, 0x3a, 0xff, 0x35, 0x01, 0xa2, 0x01, 0x4f, 0x06, 0x7c, 0x03, + 0x91, 0x01, 0xab, 0x00, 0x9f, 0x05, 0x88, 0x09, 0x5b, 0x0a, 0xf4, 0x07, + 0x38, 0x0a, 0xa4, 0x10, 0x8d, 0x0a, 0x6c, 0x06, 0x79, 0x01, 0x96, 0x06, + 0xaf, 0x0b, 0xfc, 0x00, 0x07, 0x02, 0x18, 0x05, 0xe0, 0x0d, 0x09, 0x13, + 0xfe, 0x09, 0x13, 0x00, 0x41, 0xf7, 0x87, 0xfe, 0x4c, 0x04, 0xd8, 0x05, + 0xd1, 0x05, 0xf5, 0x00, 0x94, 0x01, 0x97, 0x00, 0x71, 0x03, 0x9c, 0xfd, + 0xe0, 0xf5, 0x03, 0xf9, 0x3c, 0xfe, 0x2d, 0x01, 0xcd, 0xfd, 0x8c, 0xfa, + 0xf6, 0xf5, 0xfc, 0xfa, 0x7a, 0x03, 0xcb, 0x09, 0xd1, 0x0f, 0x5e, 0x10, + 0x81, 0x12, 0x08, 0x0e, 0x83, 0x0f, 0x19, 0x15, 0x44, 0x17, 0x90, 0x14, + 0x50, 0x05, 0x6f, 0x00, 0x4b, 0x04, 0x8b, 0x07, 0xdf, 0x07, 0x4d, 0x0b, + 0xda, 0x10, 0x04, 0x08, 0xfe, 0x01, 0x07, 0x01, 0x7f, 0x02, 0x56, 0x04, + 0x97, 0xfe, 0xd1, 0x00, 0xb8, 0x04, 0x8d, 0x07, 0xe1, 0x05, 0x86, 0x00, + 0x8d, 0x06, 0xe4, 0x06, 0x29, 0x00, 0x5e, 0xfd, 0x77, 0x02, 0x95, 0x03, + 0xfb, 0xfb, 0xe9, 0xf9, 0x8d, 0xf2, 0x38, 0xec, 0x42, 0xef, 0xc6, 0xf5, + 0x82, 0xf9, 0xe0, 0xf8, 0x45, 0xf7, 0x58, 0xf2, 0xee, 0xed, 0x37, 0xee, + 0xe7, 0xf0, 0x22, 0xed, 0xda, 0xea, 0x42, 0xea, 0x77, 0xe9, 0x9f, 0xe7, + 0xb3, 0xe1, 0x23, 0xe4, 0x57, 0xe7, 0xfe, 0xe7, 0x23, 0xea, 0xab, 0xed, + 0xc8, 0xf1, 0xdd, 0xf5, 0xe4, 0xf3, 0x8f, 0xeb, 0x05, 0xec, 0xcc, 0xf4, + 0x9c, 0xf9, 0x43, 0xf4, 0xf0, 0xf2, 0x35, 0xf7, 0xc8, 0xfb, 0xc7, 0x05, + 0xc3, 0x0e, 0xb7, 0x0b, 0xd2, 0x00, 0xf5, 0xf7, 0x6f, 0xf2, 0x2e, 0xf9, + 0xe6, 0xfe, 0xcf, 0xf9, 0x68, 0xf3, 0xbe, 0xf5, 0x23, 0x06, 0x71, 0x08, + 0xc3, 0xf7, 0xca, 0xed, 0xa5, 0xf0, 0x59, 0xf9, 0xc0, 0xf9, 0x4d, 0xf1, + 0x74, 0xef, 0xc6, 0xef, 0x47, 0xec, 0xb3, 0xf1, 0x7a, 0xfc, 0x7c, 0xff, + 0x5a, 0x00, 0x67, 0xff, 0xd2, 0xf6, 0xc9, 0xed, 0x1d, 0xeb, 0x09, 0xf1, + 0x53, 0xf9, 0xeb, 0x00, 0x59, 0x04, 0xdd, 0xff, 0x85, 0xfa, 0x77, 0xfa, + 0x4f, 0x00, 0x83, 0x05, 0xeb, 0x07, 0x04, 0x0a, 0x37, 0x0e, 0x52, 0x13, + 0x47, 0x13, 0xe6, 0x0b, 0x22, 0x05, 0x7a, 0x09, 0x05, 0x12, 0x3e, 0x18, + 0x11, 0x1a, 0xf6, 0x15, 0xd9, 0x11, 0x5c, 0x0e, 0xe5, 0x0f, 0xd6, 0x0f, + 0xad, 0x0b, 0xb3, 0x0d, 0x93, 0x10, 0x48, 0x18, 0x78, 0x21, 0x25, 0x25, + 0x97, 0x1e, 0xfa, 0x17, 0x69, 0x1c, 0xc6, 0x1b, 0x8a, 0x1b, 0xc1, 0x1c, + 0xd1, 0x21, 0xe3, 0x20, 0x2e, 0x18, 0x98, 0x14, 0x20, 0x11, 0xe3, 0x16, + 0xd4, 0x13, 0x08, 0x0f, 0x42, 0x0e, 0xfa, 0x05, 0x8b, 0xfc, 0xfb, 0xf5, + 0x08, 0x01, 0xe6, 0x06, 0x6c, 0x04, 0x47, 0x08, 0x61, 0x06, 0xc2, 0x01, + 0x4a, 0xfc, 0x06, 0xf8, 0x13, 0xfb, 0xdc, 0xff, 0xa3, 0x00, 0xce, 0xfe, + 0xda, 0xf8, 0x33, 0xf2, 0xea, 0xfd, 0xe9, 0x10, 0x3a, 0x17, 0xce, 0x20, + 0xb9, 0x1f, 0xfe, 0x17, 0xba, 0x13, 0x13, 0x0f, 0xfd, 0x13, 0xee, 0x17, + 0xa6, 0x23, 0xea, 0x22, 0xf7, 0x13, 0x66, 0x06, 0x7f, 0x01, 0x3e, 0x0f, + 0xc8, 0x0d, 0x5e, 0x07, 0x66, 0x0f, 0xc4, 0x20, 0xd0, 0x29, 0x29, 0x21, + 0x76, 0x0f, 0xa6, 0x01, 0xcf, 0x00, 0x8d, 0x00, 0x98, 0xff, 0x81, 0xf5, + 0xcd, 0xf1, 0x74, 0xf8, 0xfd, 0xfb, 0x39, 0xfc, 0x53, 0xf7, 0x0e, 0xfb, + 0xc2, 0x01, 0x97, 0x05, 0x40, 0x04, 0x2a, 0x04, 0x10, 0x07, 0xdc, 0x05, + 0xb4, 0x05, 0x7a, 0x00, 0x28, 0xfa, 0x32, 0xfa, 0xe7, 0xfc, 0x1b, 0x04, + 0x61, 0x04, 0x25, 0xfd, 0x71, 0xff, 0x08, 0xf6, 0x2c, 0xe7, 0x72, 0xe2, + 0xee, 0xe1, 0x0a, 0xe7, 0x86, 0xec, 0xc2, 0xf9, 0xeb, 0x03, 0x80, 0x06, + 0x05, 0x03, 0x2b, 0xff, 0x77, 0xfb, 0xc7, 0xf0, 0x18, 0xf3, 0xf4, 0xfa, + 0xf7, 0xfc, 0x67, 0x01, 0x3a, 0x05, 0x65, 0xff, 0xb3, 0xfd, 0x4f, 0x03, + 0xe7, 0x07, 0xdb, 0x0d, 0x12, 0x0d, 0xcd, 0x07, 0x2f, 0x02, 0xcd, 0x00, + 0xab, 0x00, 0x1b, 0x00, 0x7e, 0xff, 0xd8, 0xfb, 0xe4, 0xf3, 0xcc, 0xed, + 0x8e, 0xf4, 0x3a, 0xf6, 0xf7, 0xef, 0x93, 0xe9, 0x7c, 0xe5, 0x16, 0xe5, + 0x4c, 0xe5, 0xdf, 0xe6, 0x4d, 0xe5, 0x8b, 0xe9, 0x97, 0xf0, 0xd9, 0xf3, + 0x6b, 0xf6, 0x1e, 0xf4, 0xbc, 0xf2, 0x4b, 0xf2, 0xfc, 0xe8, 0x69, 0xe3, + 0xc8, 0xe6, 0x99, 0xed, 0x49, 0xf1, 0xe3, 0xe8, 0x06, 0xe7, 0xa0, 0xe4, + 0x53, 0xdf, 0x94, 0xe9, 0x14, 0xf8, 0x83, 0x01, 0x7e, 0x02, 0x78, 0xff, + 0x7d, 0xff, 0xc5, 0x01, 0x5d, 0xff, 0x03, 0x01, 0xa0, 0x09, 0xac, 0x0c, + 0x8e, 0x0b, 0xc1, 0x0b, 0x5e, 0x0d, 0x29, 0x0e, 0x10, 0x12, 0x42, 0x0c, + 0xb8, 0x03, 0xaf, 0x04, 0xf4, 0x08, 0xf4, 0x0c, 0xaa, 0x07, 0x78, 0x04, + 0x68, 0x02, 0x4e, 0x01, 0x52, 0x07, 0x8d, 0x0f, 0x4b, 0x14, 0x2c, 0x11, + 0xe4, 0x0b, 0x65, 0x03, 0x1a, 0xfe, 0x6c, 0x01, 0x3f, 0x05, 0x9b, 0x02, + 0x7f, 0xfa, 0x8a, 0xf2, 0x62, 0xf0, 0x5d, 0xf2, 0xc6, 0xf6, 0x82, 0xfc, + 0xaf, 0x00, 0x4c, 0x01, 0x97, 0xff, 0x50, 0x04, 0xb1, 0x03, 0xc9, 0x02, + 0xf2, 0x00, 0x7a, 0xf6, 0xbf, 0xf3, 0xc2, 0xf0, 0x13, 0xf5, 0xf2, 0xfb, + 0xe5, 0xf8, 0x93, 0xf5, 0x48, 0xf0, 0x0c, 0xec, 0x17, 0xef, 0x76, 0xfd, + 0x3d, 0x0a, 0x90, 0x0d, 0xed, 0x0b, 0x32, 0x03, 0x9c, 0x01, 0x76, 0x06, + 0x5d, 0x09, 0xee, 0x10, 0xdb, 0x12, 0x75, 0x19, 0x84, 0x19, 0xcb, 0x0d, + 0xfa, 0x0c, 0xb9, 0x07, 0x8d, 0x10, 0x5c, 0x17, 0xa1, 0x14, 0x8a, 0x15, + 0x53, 0x0b, 0xa7, 0x10, 0x9c, 0x17, 0xc1, 0x1f, 0xb0, 0x23, 0xad, 0x19, + 0x3e, 0x11, 0x48, 0x02, 0xcb, 0xf4, 0x88, 0xe3, 0x12, 0xe5, 0xfd, 0xf1, + 0x64, 0xf4, 0x5e, 0xfa, 0xaf, 0xf7, 0x6c, 0xf1, 0x90, 0xee, 0xec, 0xed, + 0x45, 0xf1, 0xd6, 0xfc, 0xb6, 0x0f, 0x98, 0x1f, 0x19, 0x1b, 0x64, 0x03, + 0xb0, 0xf2, 0x27, 0xf0, 0xa0, 0xf3, 0xbd, 0xee, 0xef, 0xea, 0x00, 0xee, + 0x57, 0xec, 0x4a, 0xe0, 0x63, 0xd4, 0x23, 0xd5, 0x47, 0xd3, 0x8f, 0xd6, + 0x69, 0xda, 0xb2, 0xd2, 0xad, 0xd2, 0x1e, 0xdc, 0xa8, 0xe2, 0x47, 0xdf, + 0x06, 0xe0, 0xad, 0xea, 0x01, 0xf1, 0xc1, 0xea, 0xcb, 0xe1, 0x7f, 0xe0, + 0x73, 0xde, 0xa7, 0xd8, 0xa1, 0xd7, 0x5e, 0xe4, 0x97, 0xf0, 0x08, 0xed, + 0xd0, 0xea, 0x43, 0xee, 0xa3, 0xec, 0xdc, 0xec, 0xc5, 0xf2, 0x8e, 0xf5, + 0xcf, 0xf0, 0x44, 0xea, 0x4e, 0xeb, 0x98, 0xee, 0x8b, 0xef, 0x58, 0xf2, + 0x01, 0xf0, 0x76, 0xeb, 0x26, 0xed, 0x39, 0xef, 0x55, 0xf1, 0xf0, 0xf6, + 0xd7, 0xfb, 0xe4, 0x01, 0x1e, 0x05, 0x8e, 0x01, 0xbb, 0xff, 0x29, 0x06, + 0x12, 0x0f, 0x0f, 0x0c, 0xe5, 0x06, 0x9e, 0x0e, 0x23, 0x16, 0xc6, 0x0d, + 0x63, 0xff, 0xd5, 0xfa, 0x11, 0xfd, 0x57, 0x01, 0x3d, 0x05, 0x8a, 0x06, + 0x6c, 0x05, 0xb6, 0x06, 0x29, 0x0c, 0x1a, 0x0b, 0x88, 0x04, 0x8d, 0x03, + 0x28, 0x02, 0xa6, 0x03, 0x69, 0x0b, 0x44, 0x0c, 0xd9, 0x06, 0xe3, 0xfe, + 0x21, 0x02, 0x26, 0x0a, 0x9c, 0x05, 0xf4, 0xf9, 0x16, 0xf4, 0x63, 0xf6, + 0x29, 0xf4, 0x5a, 0xf5, 0x87, 0xf2, 0x29, 0xea, 0x97, 0xe4, 0x2c, 0xdf, + 0xf4, 0xda, 0xfe, 0xd5, 0x52, 0xdb, 0x76, 0xe2, 0xd7, 0xe0, 0x2d, 0xdc, + 0x14, 0xdc, 0xac, 0xe5, 0x45, 0x02, 0xe6, 0x1a, 0xdd, 0x14, 0xf0, 0xfd, + 0xd8, 0xe9, 0x2b, 0xee, 0xb4, 0xf3, 0xd3, 0xe7, 0x6e, 0xdc, 0x64, 0xec, + 0x02, 0xff, 0x2b, 0xf3, 0x09, 0xfd, 0xed, 0x14, 0x1d, 0x1b, 0xf7, 0x18, + 0x91, 0xfb, 0x23, 0xe0, 0xdd, 0xe3, 0x4b, 0xe6, 0x2b, 0xeb, 0xfb, 0xf4, + 0x59, 0xfe, 0xa1, 0x08, 0xe2, 0x1a, 0xda, 0x33, 0xad, 0x32, 0x8d, 0x2d, + 0x82, 0x28, 0x72, 0x29, 0x22, 0x33, 0x66, 0x2e, 0xc3, 0x2a, 0x7c, 0x27, + 0xe9, 0x29, 0x34, 0x29, 0x48, 0x25, 0x57, 0x24, 0xfe, 0x24, 0x61, 0x31, + 0x65, 0x41, 0xb0, 0x43, 0x70, 0x32, 0xcb, 0x18, 0xe4, 0x03, 0xdf, 0xfc, + 0xcd, 0xf1, 0x29, 0xea, 0x4b, 0xec, 0x49, 0xef, 0x2f, 0xf5, 0xc0, 0xf2, + 0xb5, 0xef, 0x80, 0xf3, 0x8f, 0xf7, 0x26, 0xff, 0xb9, 0x05, 0x0f, 0xfd, + 0xac, 0x02, 0xd7, 0x0a, 0x43, 0x02, 0x36, 0x09, 0x3d, 0x26, 0x59, 0x4e, + 0x59, 0x5a, 0x3e, 0x43, 0xf0, 0x1c, 0xc8, 0xfa, 0x67, 0xe0, 0x0f, 0xce, + 0xdd, 0xcf, 0xe2, 0xd1, 0xce, 0xdb, 0x89, 0xf2, 0xef, 0x03, 0x90, 0x12, + 0x1d, 0x21, 0x9d, 0x22, 0xd3, 0x1c, 0x70, 0x1a, 0x9e, 0x0e, 0x6f, 0xf9, + 0x86, 0xe6, 0x32, 0xed, 0x7d, 0x06, 0x75, 0x17, 0xa2, 0x2a, 0x97, 0x3d, + 0xc2, 0x39, 0x9b, 0x20, 0xba, 0x07, 0xf6, 0xfb, 0xc7, 0xf8, 0xa6, 0xfb, + 0x54, 0x0d, 0x85, 0x2b, 0x89, 0x35, 0xaa, 0x34, 0xc0, 0x46, 0x9c, 0x47, + 0x73, 0x27, 0x8d, 0x08, 0x1b, 0xf8, 0xfc, 0xf6, 0x94, 0x06, 0xe1, 0x12, + 0xcc, 0x15, 0xca, 0x13, 0x24, 0x07, 0x05, 0x01, 0x8d, 0x03, 0x61, 0xf8, + 0x3f, 0xf5, 0x00, 0x03, 0x3f, 0xfa, 0x4a, 0xf0, 0x46, 0xf3, 0x4d, 0xf4, + 0x5a, 0xf9, 0x6b, 0x05, 0x1a, 0x13, 0x2b, 0x0e, 0x39, 0x0f, 0xea, 0x1e, + 0xb8, 0x2d, 0x2e, 0x2c, 0xb2, 0x1e, 0xfb, 0x18, 0x7d, 0x11, 0x33, 0xfa, + 0x17, 0xd7, 0xdc, 0xd7, 0xb3, 0xdc, 0xa6, 0xe2, 0x23, 0xfb, 0xa9, 0xff, + 0xbf, 0x0c, 0x10, 0x18, 0xa9, 0x21, 0xa2, 0x2b, 0xe6, 0x35, 0xe4, 0x43, + 0x69, 0x2e, 0xf9, 0x07, 0xe9, 0xe9, 0xa2, 0xd8, 0x34, 0xd5, 0x1d, 0xd8, + 0x7f, 0xd8, 0x25, 0xe5, 0xe5, 0xfd, 0xf6, 0x1e, 0xd2, 0x53, 0x3a, 0x5f, + 0x58, 0x37, 0xd5, 0x0c, 0xb6, 0xf3, 0x3e, 0x07, 0xfa, 0x31, 0x04, 0x3e, + 0xd5, 0x21, 0x16, 0x04, 0x98, 0xfc, 0x63, 0xf7, 0x16, 0xed, 0x18, 0xed, + 0x6c, 0xf0, 0x5e, 0xf2, 0xa2, 0x0a, 0xdd, 0x27, 0x61, 0x37, 0xb3, 0x3e, + 0x4c, 0x32, 0xca, 0x2c, 0xf5, 0x29, 0xc2, 0x13, 0x96, 0x15, 0xd4, 0x1d, + 0x8f, 0x17, 0x2a, 0x13, 0x96, 0x04, 0xca, 0xf9, 0xb3, 0xf5, 0x42, 0xf6, + 0x2f, 0xf4, 0x3b, 0xef, 0xea, 0xf6, 0xb3, 0x05, 0xcd, 0x13, 0x4d, 0x1a, + 0x80, 0x2e, 0x91, 0x31, 0xf6, 0x0d, 0x16, 0xf4, 0xa7, 0xf7, 0x59, 0x1a, + 0x4c, 0x44, 0x3b, 0x56, 0xb1, 0x44, 0xfe, 0x21, 0x25, 0x07, 0xd5, 0xf8, + 0x69, 0xed, 0x35, 0xf0, 0x3d, 0xe7, 0x96, 0xc6, 0x62, 0xcb, 0x82, 0xe3, + 0x9e, 0xf9, 0x8d, 0xf7, 0xdd, 0xcf, 0xe5, 0xbd, 0x27, 0xc3, 0xfc, 0xbc, + 0xc9, 0xce, 0xb3, 0x07, 0xdc, 0x23, 0x8b, 0x2c, 0x4d, 0x28, 0x9b, 0x0b, + 0x61, 0xff, 0xb9, 0xf8, 0x91, 0xed, 0xb2, 0xdf, 0x59, 0xd7, 0xf4, 0xe8, + 0x07, 0x04, 0x22, 0x0a, 0xd8, 0xff, 0x7e, 0xfb, 0x75, 0xff, 0xb1, 0x0c, + 0xbe, 0x1b, 0x9e, 0x18, 0x49, 0x0d, 0x22, 0x0d, 0x8e, 0x1c, 0xfa, 0x22, + 0x11, 0x11, 0x19, 0x09, 0x24, 0x06, 0x3b, 0x00, 0x22, 0x00, 0xda, 0xff, + 0x31, 0x02, 0x7d, 0x02, 0xe2, 0x00, 0x6f, 0xff, 0xd8, 0xfb, 0xdf, 0xf4, + 0x7d, 0xf5, 0x2e, 0xfd, 0x74, 0x0d, 0x6b, 0x22, 0xba, 0x30, 0xf9, 0x34, + 0x5a, 0x25, 0x4f, 0x20, 0x88, 0x27, 0x47, 0x18, 0x4d, 0xfa, 0x20, 0xe8, + 0xe7, 0xe4, 0x36, 0xe7, 0xcb, 0xe5, 0x34, 0xe0, 0xc8, 0xdc, 0x2b, 0xd3, + 0xf6, 0xcc, 0x21, 0xcc, 0x04, 0xd0, 0x8d, 0xe2, 0x1f, 0x07, 0xd9, 0x2c, + 0x72, 0x33, 0xa7, 0x19, 0x3b, 0xfa, 0x90, 0xf9, 0xcd, 0x02, 0x9c, 0xf8, + 0xfa, 0xee, 0x89, 0xea, 0xf1, 0xea, 0x38, 0xf0, 0x3a, 0xf4, 0x97, 0x00, + 0x28, 0x08, 0x66, 0xf7, 0x8c, 0xec, 0x30, 0xf3, 0x05, 0xfd, 0x9d, 0x01, + 0xdc, 0xf5, 0xe3, 0xe9, 0x8b, 0xf6, 0xfd, 0x10, 0x0c, 0x2e, 0xf3, 0x48, + 0x55, 0x3d, 0xd9, 0x0f, 0xb3, 0xe6, 0xf1, 0xcc, 0x52, 0xcb, 0xf5, 0xe2, + 0xd7, 0x08, 0x47, 0x23, 0xea, 0x23, 0xc0, 0x16, 0xeb, 0x0c, 0x2e, 0x15, + 0xaf, 0x12, 0x79, 0x01, 0xe5, 0x01, 0x24, 0xff, 0xc0, 0x05, 0x27, 0x1c, + 0x50, 0x17, 0xa7, 0x11, 0x7c, 0x25, 0x0a, 0x32, 0x1c, 0x2b, 0xb1, 0x1a, + 0x7d, 0xfb, 0xa8, 0xe7, 0xc7, 0xe1, 0x08, 0xcc, 0x3d, 0xd7, 0x05, 0xea, + 0x36, 0xef, 0x14, 0x19, 0x20, 0x24, 0xe7, 0x0c, 0x89, 0xfc, 0xd1, 0xf6, + 0xf5, 0x08, 0x7b, 0x15, 0xef, 0x13, 0xea, 0x05, 0x08, 0xf3, 0xe7, 0xe1, + 0xce, 0xd8, 0x19, 0xdc, 0x54, 0xe1, 0xed, 0xe4, 0x04, 0xe5, 0x93, 0xe6, + 0xbe, 0xf1, 0x4b, 0xfc, 0x44, 0xf8, 0x63, 0xf3, 0xdb, 0xea, 0x6f, 0xe6, + 0xb4, 0xe1, 0x51, 0xe3, 0x21, 0xf7, 0x91, 0x08, 0x8d, 0x1e, 0x3f, 0x29, + 0x47, 0x2a, 0x97, 0x1e, 0x27, 0x0d, 0xb2, 0xfa, 0xb3, 0xe2, 0xae, 0xdb, + 0x2a, 0xd5, 0xf8, 0xbf, 0x99, 0xa6, 0xc9, 0xa4, 0x38, 0xae, 0x4c, 0xb8, + 0xa9, 0xc1, 0xa4, 0xcb, 0x0e, 0xd5, 0x8f, 0xdc, 0xe9, 0xea, 0xaa, 0xef, + 0x53, 0xf5, 0x74, 0xef, 0x06, 0xe8, 0x19, 0xe3, 0xed, 0xed, 0xb0, 0x05, + 0x20, 0xf9, 0x9a, 0xf2, 0x42, 0x01, 0x90, 0x08, 0xee, 0x01, 0xbb, 0xfd, + 0x70, 0xfd, 0xcc, 0x01, 0xba, 0xfc, 0xa8, 0xf0, 0x2f, 0x02, 0x52, 0x09, + 0x57, 0x0a, 0xab, 0x1b, 0x38, 0x1e, 0x36, 0x0f, 0x20, 0x0d, 0x50, 0x11, + 0x25, 0x09, 0x02, 0xfd, 0xdd, 0xef, 0xda, 0xea, 0x11, 0xe4, 0x16, 0xdd, + 0x88, 0xd7, 0xb1, 0xd7, 0x1c, 0xe6, 0xd4, 0xf3, 0x00, 0xff, 0x47, 0x18, + 0xfe, 0x3a, 0xee, 0x4b, 0x87, 0x41, 0x30, 0x1f, 0xc5, 0x05, 0x49, 0xf6, + 0x02, 0xda, 0xe9, 0xc2, 0x3f, 0xc5, 0xf4, 0xcc, 0x54, 0xcd, 0xe2, 0xda, + 0xb6, 0xe0, 0xd8, 0xe5, 0x2c, 0xf9, 0xfc, 0x08, 0xde, 0x0b, 0xa4, 0xf8, + 0x38, 0xe3, 0x1b, 0xdd, 0x4f, 0xe5, 0x1c, 0xe8, 0x41, 0xe6, 0x60, 0xe7, + 0x6a, 0xe1, 0xda, 0xea, 0x72, 0xf5, 0x47, 0xf1, 0xb2, 0xf0, 0xbb, 0xf2, + 0x22, 0x01, 0xe5, 0x09, 0x9f, 0xfd, 0xbf, 0xf8, 0x87, 0xf9, 0xdf, 0xf2, + 0x64, 0xe7, 0xcf, 0xe3, 0x14, 0x0d, 0x9e, 0x47, 0x35, 0x3f, 0xd2, 0x13, + 0x4a, 0xfc, 0x8d, 0xf4, 0x12, 0x00, 0x40, 0x04, 0x70, 0xfb, 0xa4, 0xfb, + 0xfe, 0xfc, 0x5d, 0xf1, 0xfd, 0xf0, 0x07, 0x00, 0x0c, 0x05, 0xc9, 0x0c, + 0x58, 0x15, 0x32, 0x1e, 0x5e, 0x2d, 0x40, 0x2f, 0x8a, 0x23, 0xa5, 0x1a, + 0xe8, 0x11, 0x99, 0x0f, 0x3a, 0x1c, 0x8a, 0x27, 0x86, 0x38, 0xab, 0x39, + 0x1d, 0x14, 0xa0, 0xf7, 0x18, 0xf7, 0xdf, 0x0d, 0xb2, 0x19, 0x9a, 0xf6, + 0x9e, 0xd7, 0x5b, 0xc5, 0x8c, 0xb8, 0x04, 0xc2, 0x19, 0xc4, 0xc2, 0xc9, + 0xed, 0xde, 0x17, 0xf8, 0xbf, 0x13, 0xe3, 0x20, 0x86, 0x16, 0xca, 0x0f, + 0x34, 0x0e, 0x1a, 0x03, 0xaf, 0xf5, 0x24, 0xe4, 0x6e, 0xee, 0xc8, 0x01, + 0x90, 0x03, 0xd8, 0x00, 0x4f, 0xf9, 0xcc, 0xf8, 0x87, 0xf8, 0x8f, 0xfa, + 0xad, 0xfe, 0xf2, 0x08, 0xd4, 0x0d, 0x0d, 0x0d, 0x2b, 0x16, 0xd1, 0x19, + 0xbb, 0x1e, 0x2d, 0x26, 0x01, 0x18, 0x88, 0xfc, 0x59, 0xf7, 0xaa, 0xff, + 0x60, 0x17, 0xba, 0x23, 0x96, 0x05, 0x10, 0xdf, 0x0b, 0xc8, 0xd1, 0xbf, + 0xa0, 0xba, 0xfd, 0xc0, 0x2c, 0xc6, 0xe1, 0xcf, 0x0f, 0xdb, 0xd5, 0xe6, + 0xe7, 0xfd, 0xf8, 0x0d, 0x01, 0x20, 0xb1, 0x21, 0x22, 0x19, 0x98, 0x15, + 0xd2, 0x04, 0x28, 0xea, 0x78, 0xdb, 0x83, 0xd3, 0x64, 0xd1, 0x4f, 0xd3, + 0x44, 0xce, 0x1d, 0xe0, 0x12, 0xf2, 0xab, 0xf8, 0x41, 0x05, 0xa6, 0x07, + 0xca, 0x06, 0xc0, 0x11, 0x77, 0x1a, 0xb5, 0x16, 0x8a, 0x0d, 0xed, 0x02, + 0x7c, 0xfb, 0x12, 0xf0, 0xc0, 0xec, 0x7f, 0xed, 0xeb, 0xe8, 0x2f, 0xe5, + 0xa8, 0xdb, 0x23, 0xd4, 0x92, 0xd9, 0x71, 0xec, 0xd4, 0x03, 0x2a, 0x1a, + 0xcd, 0x28, 0xe7, 0x32, 0x78, 0x31, 0x0e, 0x1e, 0xe2, 0x01, 0x07, 0xee, + 0x74, 0xe5, 0x07, 0xe8, 0x1a, 0xf8, 0x6a, 0xf3, 0xe1, 0xe3, 0xac, 0xdb, + 0x8f, 0xd8, 0x2b, 0xd7, 0x05, 0xd5, 0xb6, 0xd1, 0xa8, 0xce, 0x60, 0xda, + 0xe5, 0xe8, 0x54, 0x03, 0x2e, 0x1d, 0x47, 0x21, 0x6d, 0x13, 0x43, 0xf9, + 0xd5, 0xe6, 0x36, 0xdf, 0x2c, 0xdb, 0x40, 0xd6, 0xdf, 0xd6, 0x0d, 0xdf, + 0xb5, 0xfc, 0x8e, 0x26, 0x34, 0x3d, 0x3e, 0x36, 0x04, 0x1c, 0xb0, 0x0f, + 0x4f, 0x14, 0xd3, 0x1e, 0x68, 0x1f, 0xd4, 0x18, 0x24, 0x23, 0x01, 0x23, + 0x5d, 0x1c, 0xda, 0x25, 0xec, 0x1e, 0x28, 0x21, 0xfe, 0x22, 0xff, 0x1b, + 0xd3, 0x3a, 0x2c, 0x38, 0xad, 0x24, 0x73, 0x27, 0xd4, 0x11, 0xa5, 0x19, + 0xbe, 0x2a, 0xe3, 0x1e, 0x63, 0x2e, 0x09, 0x2b, 0x57, 0x1c, 0x2c, 0x37, + 0xd7, 0x3e, 0x97, 0x4a, 0x13, 0x46, 0x62, 0x28, 0xe9, 0x36, 0x1e, 0x35, + 0x58, 0x2e, 0x22, 0x32, 0x48, 0x20, 0x0a, 0x20, 0x2f, 0x1d, 0x09, 0x15, + 0x13, 0x1c, 0x55, 0x0c, 0x81, 0xfc, 0x1a, 0x01, 0x94, 0x00, 0x76, 0x02, + 0x42, 0x01, 0x4d, 0xfe, 0x28, 0xfe, 0xfa, 0x04, 0x4e, 0x0d, 0x25, 0x0d, + 0xe6, 0x15, 0xa9, 0x20, 0xae, 0x1e, 0xea, 0x23, 0x0d, 0x2c, 0xbc, 0x25, + 0xe7, 0x2e, 0xa4, 0x26, 0xfe, 0x1d, 0x84, 0x23, 0x99, 0x0e, 0x36, 0x12, + 0xe5, 0x12, 0xfe, 0x14, 0x74, 0x34, 0x97, 0x4c, 0x56, 0x4e, 0x97, 0x46, + 0xc0, 0x3f, 0x03, 0x27, 0xab, 0x11, 0xb3, 0xf3, 0x42, 0xe3, 0x37, 0xec, + 0xbd, 0xe5, 0x33, 0xe1, 0xd8, 0xdf, 0x42, 0xd1, 0x4b, 0xc6, 0xa5, 0xd0, + 0x97, 0xd4, 0x4b, 0xe6, 0xca, 0x03, 0x8f, 0x06, 0x42, 0x06, 0x26, 0xfc, + 0x11, 0xf0, 0x21, 0xf8, 0x31, 0xf7, 0xd8, 0xf6, 0xda, 0x10, 0x5a, 0x25, + 0xde, 0x29, 0xa7, 0x20, 0x28, 0x02, 0xbf, 0xea, 0xfe, 0xe2, 0xa5, 0xd9, + 0x62, 0xdf, 0x96, 0xf1, 0x94, 0x02, 0x7a, 0x12, 0xf2, 0x0b, 0x26, 0x05, + 0x62, 0x0a, 0x77, 0x0c, 0x2e, 0x10, 0x72, 0x14, 0x47, 0x14, 0x35, 0x0d, + 0xca, 0x12, 0x10, 0x26, 0xe4, 0x28, 0x71, 0x14, 0x74, 0x00, 0xcc, 0xf9, + 0x8c, 0xfa, 0x6c, 0xf6, 0x1b, 0xfb, 0x4f, 0x0b, 0x45, 0x0d, 0x37, 0x12, + 0xb4, 0x24, 0x14, 0x3e, 0xd9, 0x53, 0xb9, 0x50, 0x17, 0x34, 0x4e, 0x1a, + 0x74, 0x15, 0x5e, 0x1c, 0x47, 0x1a, 0x58, 0x02, 0x04, 0xeb, 0x29, 0xdb, + 0x18, 0xd5, 0x04, 0xd7, 0x5c, 0xdd, 0x9f, 0xf1, 0x01, 0x04, 0xfb, 0x0b, + 0xec, 0x08, 0x87, 0xf5, 0x99, 0xe9, 0xc8, 0xf5, 0xb2, 0xfb, 0x14, 0x00, + 0x58, 0xfe, 0xe0, 0xe8, 0xd8, 0xe0, 0x34, 0xe2, 0x98, 0xec, 0x81, 0xf3, + 0x35, 0xec, 0xb1, 0xe7, 0x87, 0xe3, 0xbd, 0xe0, 0xb3, 0xe4, 0x02, 0xf7, + 0x80, 0x05, 0x4d, 0x0a, 0x72, 0x10, 0xda, 0x19, 0x29, 0x21, 0x61, 0x21, + 0xa5, 0x1d, 0xc1, 0x10, 0xb0, 0x0a, 0xda, 0x0d, 0xde, 0x1c, 0x3a, 0x27, + 0x99, 0x1f, 0x1e, 0x1e, 0x3b, 0x0f, 0xcd, 0x08, 0xab, 0x0c, 0x6e, 0x02, + 0x76, 0x0b, 0x63, 0x1c, 0x25, 0x37, 0x65, 0x55, 0xa0, 0x4c, 0x0e, 0x36, + 0xd8, 0x29, 0x96, 0x25, 0x38, 0x34, 0x3b, 0x44, 0x64, 0x4a, 0xde, 0x50, + 0xe7, 0x4a, 0x1e, 0x44, 0xae, 0x45, 0x3f, 0x3f, 0x5b, 0x39, 0x5d, 0x2a, + 0xd5, 0x17, 0xd0, 0x11, 0x75, 0x05, 0x52, 0xfd, 0x4b, 0x04, 0x6d, 0xfc, + 0x9d, 0xe5, 0xfe, 0xe0, 0x27, 0xe4, 0x55, 0xee, 0x1a, 0xfc, 0xb1, 0xf2, + 0xa8, 0xe8, 0xa5, 0xe4, 0x81, 0xe5, 0xdf, 0xfa, 0x70, 0x11, 0xf0, 0x18, + 0x62, 0x15, 0x89, 0x02, 0x51, 0xf9, 0x4f, 0x05, 0xb3, 0x18, 0x7d, 0x35, + 0x67, 0x3d, 0x4e, 0x26, 0xd1, 0x11, 0xbf, 0x0d, 0x42, 0x0a, 0x0b, 0x0c, + 0xb1, 0x03, 0x9b, 0xe6, 0xa1, 0xd7, 0x92, 0xc9, 0x2b, 0xc1, 0x64, 0xc1, + 0xa9, 0xba, 0x4a, 0xb8, 0x47, 0xbd, 0x19, 0xbf, 0x11, 0xc2, 0xa1, 0xd2, + 0xc9, 0xd9, 0x89, 0xe1, 0xfe, 0xe4, 0x3c, 0xe0, 0x08, 0xe4, 0x0f, 0xf0, + 0x3a, 0x0c, 0x7b, 0x18, 0xf9, 0x14, 0x14, 0x06, 0xdb, 0xf9, 0xda, 0xfc, + 0xf3, 0xfc, 0x0a, 0x07, 0x57, 0x0c, 0xa7, 0x0c, 0x63, 0x09, 0x8e, 0x0c, + 0x3c, 0x11, 0xb2, 0x04, 0xc6, 0x04, 0xa4, 0xfe, 0xcc, 0xf6, 0x85, 0xfb, + 0x85, 0xfa, 0xf6, 0xfb, 0xc2, 0xf8, 0x08, 0xf6, 0x8f, 0xf9, 0xbb, 0xf6, + 0x8a, 0xf0, 0x8a, 0xf4, 0xd8, 0xfc, 0x48, 0x03, 0x63, 0x04, 0x2c, 0xfb, + 0xd5, 0x01, 0x8d, 0x11, 0xa0, 0x18, 0xba, 0x20, 0x17, 0x1f, 0x68, 0x19, + 0xee, 0x17, 0x90, 0x17, 0xdd, 0x17, 0xd5, 0x11, 0xbd, 0x08, 0x82, 0xff, + 0x4e, 0xf4, 0x69, 0xf0, 0x88, 0xf9, 0xa5, 0x03, 0x92, 0x0f, 0xe8, 0x11, + 0xee, 0xf8, 0x2a, 0xdc, 0xac, 0xd0, 0x6b, 0xd5, 0x44, 0xd6, 0x90, 0xca, + 0xc7, 0xc7, 0xa0, 0xce, 0x38, 0xd2, 0xc5, 0xdb, 0x98, 0xe0, 0x43, 0xde, + 0x3c, 0xe6, 0x02, 0xe5, 0x6c, 0xe2, 0xe2, 0xe8, 0x4e, 0xf5, 0x03, 0x06, + 0x11, 0xff, 0x9f, 0xee, 0x0f, 0xec, 0x5b, 0xf6, 0x01, 0x16, 0xb8, 0x30, + 0xcc, 0x24, 0x05, 0x0e, 0xa1, 0xff, 0xed, 0xfe, 0x42, 0x07, 0xec, 0x03, + 0x08, 0x00, 0x6e, 0xfb, 0xdf, 0xf2, 0x7b, 0xf3, 0xe6, 0x02, 0x77, 0x07, + 0x38, 0x04, 0x9a, 0x08, 0x24, 0x04, 0x45, 0x08, 0xa5, 0x0e, 0x29, 0x0d, + 0xcf, 0x0b, 0x6b, 0x0a, 0xa4, 0x08, 0xce, 0x04, 0x56, 0x09, 0xe2, 0x1a, + 0x03, 0x2a, 0x12, 0x28, 0x80, 0x26, 0x42, 0x26, 0x11, 0x34, 0xa4, 0x4f, + 0xb3, 0x57, 0x43, 0x47, 0x7f, 0x1a, 0x4e, 0xf5, 0xd7, 0xe2, 0xf9, 0xcc, + 0x7a, 0xc3, 0x0d, 0xc5, 0xb8, 0xc5, 0x21, 0xc7, 0xda, 0xc7, 0x53, 0xc6, + 0x38, 0xc3, 0xa2, 0xbb, 0x1f, 0xbe, 0xac, 0xd5, 0x27, 0xed, 0xa8, 0xf8, + 0xe4, 0xff, 0xda, 0xf5, 0xc0, 0xe8, 0x58, 0xee, 0x8b, 0xe9, 0x5a, 0xe4, + 0xf6, 0xf9, 0xa4, 0x18, 0xe9, 0x1f, 0xe9, 0x14, 0x3f, 0x10, 0x2e, 0x0d, + 0xa0, 0x08, 0x0f, 0x00, 0xb1, 0xfe, 0xa8, 0x01, 0xbe, 0xf8, 0xf1, 0xf0, + 0xeb, 0xeb, 0xaf, 0xe1, 0x13, 0xd6, 0x79, 0xcd, 0x7a, 0xba, 0xb3, 0xb2, + 0x39, 0xc4, 0x3c, 0xcc, 0xd1, 0xd4, 0xa6, 0xd6, 0xd7, 0xca, 0x37, 0xc9, + 0x93, 0xc8, 0xdc, 0xd1, 0x90, 0xe2, 0xbe, 0xf1, 0x3b, 0x05, 0xf5, 0x0f, + 0x49, 0x17, 0x0d, 0x20, 0x58, 0x22, 0x9a, 0x1c, 0x57, 0x14, 0x77, 0x10, + 0x82, 0x10, 0xa2, 0x17, 0xf8, 0x1d, 0x8d, 0x1c, 0xae, 0x13, 0xb2, 0x06, + 0xdf, 0xf9, 0x26, 0xec, 0x45, 0xef, 0xbb, 0xfb, 0x8d, 0x02, 0x28, 0x02, + 0xec, 0xf8, 0xb4, 0xf4, 0x50, 0xf0, 0xf3, 0xec, 0x1a, 0xea, 0x6b, 0xe6, + 0x30, 0xea, 0x7b, 0xf5, 0x55, 0x02, 0xd7, 0x03, 0x4d, 0xfe, 0xa7, 0xf4, + 0x93, 0xf1, 0x01, 0xf3, 0x31, 0xf7, 0x2e, 0x03, 0x5a, 0x0f, 0x5b, 0x22, + 0x78, 0x2b, 0xec, 0x1f, 0x9d, 0x0d, 0xf4, 0x04, 0x36, 0x01, 0xae, 0xf6, + 0x59, 0xec, 0x27, 0xdf, 0xfc, 0xd8, 0xe8, 0xe0, 0xd4, 0xef, 0xb7, 0xf3, + 0xe5, 0xe1, 0x41, 0xcc, 0x01, 0xc5, 0x51, 0xcd, 0xb8, 0xdb, 0x43, 0xeb, + 0x91, 0xf7, 0x14, 0xf8, 0xe3, 0xe9, 0xb1, 0xe0, 0xfa, 0xdf, 0x85, 0xe1, + 0x0b, 0xe9, 0x7d, 0xf0, 0x70, 0xf5, 0x37, 0xf7, 0x54, 0xfa, 0x44, 0xfb, + 0x74, 0xfc, 0x66, 0xfc, 0x74, 0xfb, 0xfd, 0x04, 0xce, 0x14, 0xde, 0x26, + 0xff, 0x21, 0xc5, 0x0c, 0xd4, 0x04, 0x19, 0xfb, 0xe1, 0xf7, 0x6d, 0x03, + 0xca, 0x08, 0x7e, 0x17, 0x14, 0x22, 0x4f, 0x0e, 0xc2, 0xfd, 0x43, 0xf0, + 0xbc, 0xe3, 0x9c, 0xf0, 0x00, 0x07, 0xf3, 0x18, 0xcc, 0x28, 0xbf, 0x28, + 0xce, 0x1e, 0x0d, 0x23, 0xdc, 0x26, 0x2f, 0x24, 0xd8, 0x26, 0x48, 0x23, + 0xf7, 0x18, 0xa9, 0x10, 0x24, 0x06, 0x50, 0x01, 0x7a, 0x03, 0x15, 0xf9, + 0xd4, 0xf6, 0xb9, 0x02, 0x5a, 0x06, 0x6c, 0x0c, 0x88, 0x08, 0x79, 0xf5, + 0xb8, 0xe0, 0x8a, 0xca, 0xba, 0xc6, 0x17, 0xcd, 0x67, 0xc7, 0x34, 0xc6, + 0x28, 0xd2, 0xe0, 0xd3, 0xe9, 0xd8, 0x66, 0xea, 0x5f, 0xe3, 0x6f, 0xdb, + 0x36, 0xe1, 0xa2, 0xe4, 0x17, 0xef, 0xe4, 0xf6, 0xc3, 0xf7, 0x3a, 0xff, + 0x25, 0x05, 0x97, 0x0b, 0x88, 0x24, 0x16, 0x28, 0x1c, 0x1c, 0x1d, 0x19, + 0x02, 0x0d, 0xff, 0xff, 0xf0, 0xf0, 0xcc, 0xe7, 0x02, 0xd8, 0x83, 0xca, + 0x80, 0xc9, 0x67, 0xc1, 0xee, 0xbd, 0x10, 0xc2, 0xdf, 0xc6, 0xa1, 0xcd, + 0x89, 0xe0, 0xc4, 0xe6, 0xbe, 0xe7, 0xdc, 0xf4, 0x87, 0x04, 0x5d, 0x0a, + 0xa6, 0x03, 0x6a, 0x0b, 0x4f, 0x08, 0xea, 0x00, 0x12, 0xff, 0xa2, 0xfd, + 0xc4, 0x05, 0x85, 0x11, 0x5a, 0x28, 0x95, 0x3e, 0xd0, 0x50, 0x34, 0x50, + 0x28, 0x4e, 0x11, 0x50, 0x23, 0x43, 0x82, 0x35, 0xc7, 0x29, 0x3e, 0x24, + 0xb0, 0x1c, 0xf1, 0x18, 0x2f, 0x17, 0x2a, 0x13, 0x47, 0x0b, 0xe8, 0xff, + 0x3c, 0xf7, 0x6f, 0xee, 0x85, 0xef, 0x19, 0xf4, 0x47, 0xf8, 0xc3, 0xf6, + 0x20, 0xff, 0x8d, 0x12, 0xc6, 0x1a, 0x80, 0x16, 0xdb, 0x0b, 0x71, 0x0b, + 0xb2, 0x09, 0xaf, 0x09, 0x1f, 0x12, 0xe5, 0x16, 0x58, 0x0a, 0xc7, 0xf4, + 0x4f, 0xee, 0x78, 0xeb, 0xcf, 0xeb, 0x50, 0xed, 0xc8, 0xee, 0xbb, 0xef, + 0x6c, 0xf6, 0xa7, 0x0d, 0x00, 0x1a, 0x17, 0x11, 0xf0, 0xf7, 0x68, 0xea, + 0xea, 0xf2, 0xdc, 0xf7, 0x6c, 0xfe, 0x81, 0x03, 0x8c, 0xf9, 0x5e, 0xea, + 0xe1, 0xe9, 0xf7, 0xea, 0x44, 0xf1, 0x71, 0x10, 0xe9, 0x25, 0x42, 0x31, + 0x03, 0x3a, 0x02, 0x3a, 0x17, 0x3a, 0x39, 0x34, 0x88, 0x34, 0x22, 0x3f, + 0x54, 0x43, 0x2d, 0x38, 0xe2, 0x34, 0xbc, 0x3e, 0x76, 0x49, 0xa2, 0x5b, + 0x55, 0x5e, 0xc3, 0x51, 0xf1, 0x42, 0xe5, 0x30, 0xe0, 0x2c, 0xf5, 0x39, + 0x67, 0x46, 0xed, 0x45, 0x4f, 0x3d, 0x88, 0x31, 0x15, 0x30, 0xfe, 0x2f, + 0xeb, 0x28, 0xf0, 0x2f, 0xd5, 0x27, 0x97, 0x12, 0xa3, 0x08, 0x88, 0xf8, + 0xb0, 0xfe, 0x5c, 0x0f, 0x0b, 0x11, 0xc3, 0x14, 0xce, 0x07, 0x9f, 0xfe, + 0x67, 0x0e, 0x6e, 0x1a, 0x14, 0x26, 0xfc, 0x2d, 0x54, 0x25, 0x1a, 0x2c, + 0x52, 0x2b, 0x8f, 0x12, 0x24, 0x0b, 0xb5, 0xff, 0x6f, 0xee, 0x31, 0xda, + 0x6c, 0xc2, 0x1d, 0xc7, 0xbd, 0xce, 0x9c, 0xd0, 0xc0, 0xdd, 0xba, 0xda, + 0x3d, 0xcd, 0x5f, 0xd8, 0xdd, 0xdf, 0x88, 0xeb, 0xf9, 0x0b, 0x0f, 0x16, + 0x60, 0x22, 0xd1, 0x1f, 0x70, 0x05, 0x1f, 0x12, 0xd1, 0x1b, 0xfa, 0x15, + 0x42, 0x13, 0x7c, 0xf4, 0xcd, 0xe3, 0x16, 0xf4, 0x0e, 0xf6, 0x30, 0xf5, + 0x64, 0xf6, 0x7e, 0xe7, 0x41, 0xe8, 0xeb, 0xf3, 0xcf, 0x00, 0xbc, 0x12, + 0xe6, 0x0e, 0xf0, 0x04, 0x92, 0x03, 0xee, 0xfa, 0x67, 0xf2, 0xa7, 0xfb, + 0xef, 0x01, 0x01, 0xfd, 0x78, 0x03, 0x18, 0x10, 0x31, 0x19, 0xd6, 0x1a, + 0x68, 0x1d, 0x38, 0x23, 0x84, 0x2a, 0x87, 0x2f, 0xed, 0x31, 0x86, 0x3a, + 0xd1, 0x44, 0x12, 0x48, 0xa7, 0x3f, 0xd8, 0x3f, 0x1e, 0x3f, 0x50, 0x35, + 0x4a, 0x2a, 0xd6, 0x14, 0x19, 0x02, 0x3d, 0xf6, 0x9b, 0xee, 0x6e, 0xe5, + 0x6c, 0xdf, 0x94, 0xdc, 0xbf, 0xdd, 0xf0, 0xe5, 0x7f, 0xe4, 0x5e, 0xe0, + 0x35, 0xdb, 0x68, 0xd9, 0xc3, 0xdc, 0xe2, 0xdd, 0xdc, 0xdd, 0x88, 0xd7, + 0xd3, 0xcf, 0xa2, 0xcb, 0x69, 0xca, 0xbf, 0xca, 0xff, 0xcf, 0x4a, 0xd9, + 0xab, 0xea, 0xf7, 0xff, 0x11, 0x03, 0x16, 0xfc, 0x0e, 0xf3, 0x8c, 0xed, + 0x6e, 0xf4, 0x32, 0xfd, 0xf7, 0xfc, 0x49, 0xf9, 0xe3, 0xfb, 0x09, 0xf8, + 0x02, 0xf8, 0x21, 0xfb, 0x85, 0xf0, 0xdb, 0xed, 0xa0, 0xf2, 0xaa, 0xfb, + 0xd9, 0x0b, 0xd4, 0x17, 0xb0, 0x1e, 0x3d, 0x1d, 0xe2, 0x19, 0x0e, 0x20, + 0x06, 0x27, 0x67, 0x2c, 0xd3, 0x34, 0x51, 0x3c, 0xe8, 0x49, 0x5a, 0x53, + 0x60, 0x4f, 0x64, 0x48, 0x5c, 0x42, 0x6c, 0x44, 0x89, 0x4b, 0xf1, 0x54, + 0x7b, 0x57, 0xe4, 0x53, 0x32, 0x50, 0x16, 0x49, 0x4d, 0x49, 0x94, 0x49, + 0xc9, 0x46, 0xd2, 0x40, 0x0c, 0x33, 0x25, 0x28, 0xcb, 0x1b, 0xfb, 0x08, + 0x06, 0xf6, 0xa4, 0xe3, 0xea, 0xd3, 0xd0, 0xcc, 0xfe, 0xce, 0xbb, 0xda, + 0x2c, 0xe6, 0xe8, 0xe5, 0x16, 0xe7, 0xfa, 0xec, 0x54, 0xf0, 0xf2, 0xf4, + 0xc6, 0xfc, 0xd2, 0x02, 0xc2, 0x01, 0x77, 0x0d, 0xb5, 0x1f, 0x75, 0x22, + 0xd0, 0x1f, 0x70, 0x10, 0xdb, 0xfc, 0x12, 0xf6, 0xc8, 0xf9, 0xdf, 0x07, + 0xcc, 0x08, 0xb6, 0xf4, 0xf5, 0xdb, 0x84, 0xc8, 0xbc, 0xc6, 0x12, 0xce, + 0xc5, 0xd5, 0x7f, 0xe3, 0xfb, 0xe7, 0xe0, 0xe2, 0x53, 0xe1, 0x40, 0xe4, + 0xaf, 0xef, 0x7d, 0xfa, 0xf6, 0x01, 0x21, 0x0c, 0x72, 0x04, 0xa3, 0xf1, + 0x08, 0xec, 0x19, 0xec, 0xdd, 0xf3, 0x7b, 0x00, 0xdd, 0x10, 0x67, 0x1e, + 0xd1, 0x17, 0x39, 0x0f, 0xa5, 0x0d, 0x1e, 0x14, 0xcd, 0x14, 0xdb, 0x04, + 0xde, 0xfe, 0xd8, 0x02, 0x22, 0x03, 0xd4, 0xfd, 0x10, 0xf6, 0xf2, 0xf0, + 0xdb, 0xf3, 0x65, 0x01, 0xf3, 0x0f, 0x36, 0x12, 0x36, 0x06, 0xbd, 0x04, + 0x3c, 0x0a, 0x15, 0x09, 0xee, 0x11, 0xc6, 0x17, 0x25, 0x17, 0xe2, 0x1b, + 0x7e, 0x24, 0x32, 0x32, 0xb8, 0x30, 0x4c, 0x1f, 0xa8, 0x18, 0x7b, 0x19, + 0xde, 0x0f, 0x0f, 0x04, 0xc0, 0xfc, 0x44, 0xf2, 0x4d, 0xe8, 0x49, 0xda, + 0xac, 0xd0, 0x58, 0xd5, 0xc9, 0xd3, 0x1b, 0xce, 0xfb, 0xcf, 0x9f, 0xcf, + 0x7b, 0xc9, 0xa5, 0xc2, 0xd4, 0xb9, 0x7f, 0xb2, 0x2e, 0xbb, 0x4e, 0xc7, + 0x6a, 0xc5, 0xfc, 0xbe, 0x27, 0xb7, 0x61, 0xb1, 0x35, 0xb1, 0x15, 0xb4, + 0x20, 0xba, 0xd3, 0xc9, 0xd4, 0xdb, 0xca, 0xe3, 0xbf, 0xe9, 0x34, 0xe8, + 0x5b, 0xe9, 0x63, 0xf6, 0x4f, 0xfe, 0xb9, 0xfd, 0x8f, 0xf1, 0x15, 0xe5, + 0xda, 0xe5, 0x80, 0xee, 0xe4, 0xf2, 0x51, 0xeb, 0x4c, 0xe0, 0xfb, 0xdb, + 0xaf, 0xe5, 0x53, 0xf1, 0x08, 0xf8, 0xc3, 0xfe, 0x7c, 0x05, 0xd7, 0x12, + 0x9d, 0x19, 0x11, 0x21, 0x99, 0x2f, 0x69, 0x38, 0x5c, 0x3d, 0x82, 0x3c, + 0xff, 0x40, 0x16, 0x47, 0x52, 0x49, 0xf6, 0x4d, 0x49, 0x53, 0xab, 0x5a, + 0xac, 0x5b, 0xc3, 0x4f, 0xc4, 0x40, 0xb4, 0x36, 0xe7, 0x2e, 0x8e, 0x2f, + 0x39, 0x23, 0xe9, 0x07, 0x7b, 0xf8, 0x93, 0xf0, 0x5b, 0xee, 0x47, 0xe5, + 0xf4, 0xd5, 0x31, 0xc7, 0x74, 0xb8, 0x33, 0xb7, 0xc1, 0xbf, 0xec, 0xc7, + 0xfa, 0xd3, 0xbf, 0xdf, 0xfc, 0xdb, 0xcf, 0xd1, 0x21, 0xd0, 0x51, 0xd8, + 0x33, 0xe2, 0x37, 0xe4, 0x4a, 0xe4, 0x74, 0xea, 0xd4, 0xf1, 0xe5, 0xfe, + 0xfb, 0x11, 0x1f, 0x10, 0xaf, 0xfc, 0x1b, 0xf1, 0x4d, 0xf7, 0xeb, 0x09, + 0x4e, 0x1f, 0xf8, 0x24, 0x80, 0x10, 0x92, 0xfc, 0x0b, 0xeb, 0x1a, 0xe5, + 0x38, 0xee, 0xa1, 0xec, 0x5f, 0xf5, 0xe2, 0xf3, 0x8c, 0xe0, 0x4a, 0xe0, + 0x2a, 0xe5, 0xca, 0xf8, 0x7e, 0x19, 0x94, 0x24, 0x0f, 0x23, 0xe7, 0x26, + 0x66, 0x20, 0x14, 0x20, 0x3f, 0x2b, 0x98, 0x1f, 0x72, 0x10, 0xd7, 0x06, + 0x01, 0x01, 0x5a, 0x02, 0x42, 0x05, 0x97, 0x09, 0x3b, 0x08, 0x85, 0xfe, + 0xa4, 0xf8, 0x29, 0x02, 0x18, 0x02, 0x14, 0x05, 0x02, 0x0e, 0x2d, 0x07, + 0x06, 0xfd, 0xcc, 0xee, 0x28, 0xe3, 0xa6, 0xdc, 0xc5, 0xd9, 0x1e, 0xd7, + 0xd1, 0xd2, 0xb0, 0xce, 0x66, 0xd2, 0xaf, 0xd9, 0xbd, 0xe1, 0x2f, 0xf5, + 0xbe, 0xfd, 0x28, 0xff, 0xa9, 0xfc, 0x57, 0xee, 0x30, 0xe7, 0xbd, 0xe8, + 0x7c, 0xeb, 0xf9, 0xeb, 0xfe, 0xe7, 0x94, 0xe7, 0x82, 0xea, 0x02, 0xe6, + 0xff, 0xe1, 0x61, 0xde, 0xcb, 0xd7, 0xca, 0xd1, 0xeb, 0xcb, 0xb2, 0xca, + 0xb5, 0xce, 0x66, 0xd4, 0xb6, 0xdf, 0x11, 0xe9, 0x53, 0xe2, 0xae, 0xda, + 0xd0, 0xd5, 0xb1, 0xd1, 0xd2, 0xce, 0xaf, 0xc7, 0x05, 0xc7, 0xdb, 0xcc, + 0xc2, 0xd1, 0x1b, 0xd8, 0x8b, 0xe2, 0x93, 0xe8, 0xff, 0xec, 0xc4, 0xf5, + 0xe8, 0xfc, 0xa0, 0x01, 0x61, 0x06, 0x45, 0x0b, 0x40, 0x07, 0x7e, 0xfe, + 0x64, 0xfc, 0x6c, 0xfb, 0xce, 0xf9, 0xbe, 0xfb, 0xb9, 0xfb, 0xa0, 0xfa, + 0x16, 0xfd, 0x77, 0xfd, 0xf6, 0x07, 0x2e, 0x20, 0x70, 0x33, 0xc5, 0x43, + 0x0d, 0x45, 0x7d, 0x36, 0x45, 0x30, 0xd1, 0x2d, 0x2e, 0x35, 0xeb, 0x43, + 0x3c, 0x4b, 0xfe, 0x47, 0x84, 0x34, 0xe1, 0x25, 0x9b, 0x27, 0x61, 0x27, + 0x71, 0x21, 0xa3, 0x18, 0x8f, 0x06, 0x85, 0xf6, 0x1a, 0xf0, 0xf5, 0xef, + 0xc8, 0xf2, 0xd5, 0xe7, 0xc9, 0xdc, 0xac, 0xe6, 0x27, 0xf3, 0xa9, 0xf3, + 0xa5, 0xec, 0xa3, 0xe0, 0x69, 0xd1, 0xcb, 0xc0, 0xcd, 0xbb, 0xf3, 0xc6, + 0x7a, 0xd6, 0x22, 0xe6, 0x65, 0xe7, 0x26, 0xd9, 0x19, 0xcf, 0x71, 0xd6, + 0x08, 0xe8, 0x96, 0xef, 0x1a, 0xf0, 0x0f, 0xf4, 0x58, 0xf6, 0x9b, 0xf7, + 0x18, 0x09, 0x52, 0x1e, 0x8c, 0x21, 0x8d, 0x2a, 0x3c, 0x3c, 0x20, 0x41, + 0x38, 0x3b, 0x7b, 0x30, 0xa7, 0x23, 0x04, 0x12, 0xd8, 0x04, 0xa4, 0x03, + 0xad, 0xff, 0x50, 0xfd, 0x73, 0xfe, 0x99, 0x02, 0x86, 0x12, 0x53, 0x1b, + 0x52, 0x23, 0xe6, 0x34, 0x47, 0x3c, 0x92, 0x46, 0xf8, 0x4e, 0x5e, 0x45, + 0x7a, 0x3f, 0xa5, 0x3a, 0x64, 0x31, 0xa7, 0x2a, 0x23, 0x1c, 0xe8, 0x09, + 0xeb, 0xfd, 0xdc, 0xf4, 0x41, 0xf0, 0xdb, 0xf5, 0x0d, 0xfc, 0xca, 0xfa, + 0x01, 0xfc, 0xc3, 0x01, 0x02, 0x00, 0x65, 0xfa, 0x9c, 0xf8, 0x70, 0xf7, + 0xa2, 0xf7, 0xb6, 0xf4, 0x2f, 0xf2, 0xd7, 0xe6, 0x94, 0xd4, 0x8e, 0xd2, + 0x7d, 0xd1, 0x41, 0xd2, 0x22, 0xe1, 0x7f, 0xf4, 0x31, 0xff, 0x87, 0xfe, + 0xa0, 0xfa, 0xd7, 0xfc, 0x8b, 0x0c, 0xa6, 0x1d, 0x65, 0x21, 0x84, 0x1e, + 0x38, 0x22, 0x4b, 0x1c, 0xdb, 0x15, 0x1e, 0x16, 0x93, 0x0f, 0x17, 0x0e, + 0xe0, 0x0d, 0x3e, 0x14, 0x2d, 0x1d, 0x28, 0x25, 0x8c, 0x2b, 0xa0, 0x27, + 0x2c, 0x21, 0x4e, 0x1c, 0xf8, 0x18, 0xeb, 0x15, 0x73, 0x19, 0x41, 0x1a, + 0x0d, 0x18, 0x53, 0x14, 0x0a, 0x10, 0xab, 0x10, 0x5e, 0x0d, 0xe0, 0x08, + 0x98, 0x05, 0xa7, 0x04, 0xd4, 0x06, 0xc1, 0x0e, 0xab, 0x17, 0x5b, 0x1e, + 0x0c, 0x1e, 0xe7, 0x17, 0x99, 0x13, 0x54, 0x0d, 0xfb, 0x0e, 0xd0, 0x12, + 0x38, 0x12, 0x82, 0x12, 0x28, 0x13, 0x3f, 0x0e, 0x60, 0x0e, 0x79, 0x19, + 0xb6, 0x24, 0x4c, 0x33, 0xe8, 0x37, 0x85, 0x39, 0xae, 0x3c, 0xf5, 0x30, + 0xc1, 0x25, 0x08, 0x1d, 0x60, 0x0f, 0x18, 0x0c, 0xa8, 0x10, 0x21, 0x11, + 0x15, 0x09, 0x60, 0xf2, 0x1f, 0xdf, 0x8e, 0xdc, 0xc3, 0xec, 0xce, 0x0b, + 0xc7, 0x17, 0x5a, 0x06, 0xce, 0xe6, 0xd9, 0xce, 0xa1, 0xd7, 0xee, 0xef, + 0x90, 0x06, 0x06, 0x14, 0x64, 0x04, 0xbc, 0xed, 0xcb, 0xe9, 0x71, 0xec, + 0x31, 0xf2, 0xd7, 0xf7, 0xdb, 0xef, 0x15, 0xe9, 0xbd, 0xea, 0x62, 0xef, + 0x82, 0x00, 0x70, 0x0c, 0x80, 0x12, 0x45, 0x23, 0x94, 0x21, 0xe4, 0x1b, + 0xfd, 0x32, 0x6c, 0x40, 0xbc, 0x41, 0xab, 0x3a, 0xee, 0x2b, 0x5e, 0x34, + 0x83, 0x38, 0x98, 0x34, 0x51, 0x3e, 0x3e, 0x43, 0xa9, 0x47, 0x33, 0x4f, + 0xa8, 0x41, 0x12, 0x30, 0x17, 0x2a, 0x16, 0x2a, 0x28, 0x38, 0x86, 0x3b, + 0x24, 0x35, 0x37, 0x3a, 0xf8, 0x3b, 0xa4, 0x3e, 0x1d, 0x4a, 0x81, 0x4a, + 0xbb, 0x38, 0xa4, 0x21, 0x3a, 0x18, 0x02, 0x0f, 0xc8, 0xfb, 0x40, 0xf5, + 0xa4, 0xe9, 0x21, 0xd8, 0xa4, 0xd1, 0xb2, 0xd0, 0xcc, 0xcf, 0x92, 0xce, + 0x5d, 0xcf, 0x02, 0xd0, 0xa9, 0xd4, 0x9a, 0xce, 0xb0, 0xce, 0xe7, 0xd1, + 0xa1, 0xc3, 0x98, 0xc2, 0xf0, 0xc0, 0x4d, 0xb8, 0x3a, 0xbf, 0xa0, 0xc7, + 0x04, 0xcd, 0x8a, 0xd5, 0x04, 0xd7, 0x51, 0xd1, 0x5f, 0xd5, 0x68, 0xe0, + 0x00, 0xe2, 0x62, 0xe3, 0x7d, 0xf1, 0x0d, 0x02, 0x88, 0x05, 0x2c, 0x05, + 0x6d, 0x0a, 0x65, 0x08, 0xfd, 0x08, 0xad, 0x0c, 0x05, 0x0f, 0x75, 0x15, + 0x17, 0x1a, 0xdb, 0x1c, 0xee, 0x17, 0x3a, 0x15, 0x77, 0x1d, 0x24, 0x22, + 0x07, 0x24, 0xe5, 0x25, 0x37, 0x23, 0x6b, 0x28, 0xb3, 0x30, 0xb1, 0x2e, + 0x45, 0x2a, 0x2e, 0x23, 0x9c, 0x20, 0xff, 0x24, 0x7b, 0x21, 0xd4, 0x1a, + 0x90, 0x17, 0xa6, 0x10, 0xc1, 0x0d, 0x9e, 0x11, 0xdb, 0x14, 0xff, 0x14, + 0x7e, 0x12, 0x45, 0x10, 0xa5, 0x10, 0xf6, 0x17, 0xd7, 0x1d, 0x57, 0x18, + 0xd9, 0x0f, 0xec, 0x11, 0xa5, 0x13, 0xfe, 0x0c, 0x03, 0x09, 0x93, 0x0d, + 0x91, 0x14, 0x63, 0x14, 0x26, 0x18, 0xa6, 0x18, 0xd5, 0x15, 0x20, 0x0f, + 0xe7, 0xfd, 0xc3, 0xfb, 0xe0, 0xff, 0xf3, 0xfa, 0x51, 0xf2, 0x57, 0xe4, + 0x1b, 0xd0, 0xb5, 0xc6, 0x00, 0xd6, 0x2e, 0xed, 0x63, 0xfd, 0xe4, 0xf5, + 0xda, 0xdb, 0x12, 0xcd, 0x9f, 0xd0, 0xeb, 0xe3, 0xed, 0xf5, 0x04, 0xfc, + 0x20, 0xfb, 0xc7, 0xef, 0x50, 0xe4, 0x4d, 0xe7, 0xa1, 0xf6, 0x86, 0x02, + 0xef, 0x0b, 0x37, 0x0d, 0xca, 0xf8, 0x2b, 0xef, 0xed, 0xff, 0xd6, 0x13, + 0xd9, 0x18, 0xeb, 0x12, 0x94, 0x0d, 0x7c, 0x0b, 0x56, 0x0b, 0xbd, 0x11, + 0x88, 0x22, 0xb5, 0x2d, 0x43, 0x39, 0x64, 0x41, 0x36, 0x3d, 0x6f, 0x3a, + 0xda, 0x2e, 0x23, 0x28, 0x45, 0x2e, 0x90, 0x34, 0x7c, 0x48, 0x67, 0x4f, + 0xae, 0x41, 0x7e, 0x41, 0xc6, 0x44, 0x39, 0x4c, 0x9b, 0x54, 0x8d, 0x54, + 0x64, 0x57, 0xc0, 0x4f, 0xba, 0x41, 0x92, 0x3b, 0x2d, 0x33, 0xc9, 0x20, + 0xad, 0x07, 0x9c, 0xec, 0x65, 0xd6, 0x1c, 0xc8, 0xb1, 0xc3, 0xf7, 0xc7, + 0x5f, 0xcf, 0xd9, 0xcd, 0xa2, 0xbc, 0xba, 0xbc, 0xf5, 0xc1, 0x2d, 0xb8, + 0x3e, 0xbc, 0x56, 0xba, 0xef, 0xb8, 0xa5, 0xc4, 0xbe, 0xc1, 0x7d, 0xbf, + 0xbb, 0xbb, 0xd9, 0xb0, 0xcc, 0xae, 0x7a, 0xb1, 0x35, 0xbc, 0x6a, 0xc8, + 0xf3, 0xd8, 0x0d, 0xed, 0xb9, 0xf2, 0xa6, 0xf3, 0xcd, 0xf2, 0x91, 0xf4, + 0xb0, 0x00, 0x40, 0x01, 0x71, 0xf7, 0xd2, 0xfa, 0xdd, 0xfa, 0x55, 0xf6, + 0x93, 0xf5, 0xeb, 0xed, 0xc6, 0xeb, 0x08, 0xec, 0x88, 0xf0, 0xe8, 0xf3, + 0x97, 0xf6, 0x38, 0x02, 0x6e, 0x01, 0x29, 0x02, 0xc8, 0x07, 0x94, 0x09, + 0x68, 0x0f, 0x9c, 0x17, 0x7f, 0x1f, 0x5d, 0x15, 0xb2, 0x02, 0x4a, 0xfa, + 0x96, 0xf0, 0x94, 0xe5, 0xb2, 0xe0, 0x9a, 0xdd, 0x1d, 0xe0, 0x0d, 0xea, + 0x27, 0xf1, 0xd7, 0xf6, 0xcd, 0xff, 0x22, 0x03, 0x84, 0xfc, 0x24, 0xf4, + 0x19, 0xee, 0x88, 0xe8, 0x1b, 0xe4, 0x06, 0xe3, 0x95, 0xe7, 0x89, 0xec, + 0x11, 0xeb, 0x48, 0xec, 0x1e, 0xf3, 0x2a, 0xf6, 0x82, 0xfd, 0x6d, 0x06, + 0x7e, 0x05, 0x54, 0x03, 0xa7, 0xfe, 0xf8, 0xf1, 0x6e, 0xe5, 0xfc, 0xe3, + 0xbc, 0xec, 0xe1, 0xf0, 0x43, 0xe9, 0x95, 0xd6, 0x98, 0xc2, 0x30, 0xc5, + 0xbb, 0xd8, 0x01, 0xe7, 0x50, 0xeb, 0x51, 0xde, 0xbb, 0xd4, 0xe0, 0xdf, + 0x2b, 0xf1, 0x6d, 0x00, 0xe0, 0x00, 0x02, 0xfb, 0x16, 0xf2, 0xb7, 0xe6, + 0x8b, 0xf0, 0x05, 0x00, 0x96, 0x06, 0xd4, 0x0b, 0xea, 0x03, 0xb8, 0xf6, + 0x47, 0xfa, 0x02, 0x06, 0x29, 0x0c, 0xa5, 0x05, 0x95, 0xf9, 0x6d, 0xfa, + 0x94, 0x07, 0x15, 0x1f, 0xca, 0x2d, 0x98, 0x20, 0x3f, 0x0f, 0x2b, 0x09, + 0xe5, 0x0d, 0x78, 0x17, 0x4f, 0x17, 0x8d, 0x15, 0xbf, 0x0f, 0x7a, 0xfe, + 0xbf, 0xfc, 0xe0, 0x0e, 0x3e, 0x1d, 0xe7, 0x22, 0x0a, 0x27, 0x46, 0x34, + 0xb5, 0x44, 0x10, 0x53, 0xb2, 0x61, 0x5b, 0x59, 0xe3, 0x4e, 0x58, 0x51, + 0x70, 0x48, 0xc8, 0x46, 0xbb, 0x3e, 0x93, 0x27, 0xa9, 0x1e, 0xe6, 0x18, + 0x4c, 0x0c, 0x28, 0x07, 0xa0, 0xf8, 0x48, 0xdc, 0x15, 0xd3, 0x37, 0xc8, + 0xa9, 0xb7, 0x53, 0xb8, 0x6c, 0xbe, 0x8c, 0xbe, 0x6f, 0xb7, 0x1a, 0xb2, + 0x51, 0xac, 0xd6, 0xac, 0x0a, 0xb1, 0x9a, 0xb7, 0xfc, 0xbe, 0x7a, 0xb7, + 0x39, 0xb5, 0xf2, 0xba, 0x97, 0xbc, 0x67, 0xbb, 0x19, 0xc2, 0xa5, 0xd4, + 0x87, 0xde, 0x95, 0xe7, 0x07, 0xf4, 0xa5, 0xfa, 0xf1, 0xfc, 0x8c, 0xfb, + 0x20, 0x03, 0x47, 0x0d, 0xda, 0x0d, 0x62, 0x0f, 0x49, 0x12, 0x5d, 0x0c, + 0x90, 0x03, 0x30, 0xfc, 0xef, 0xf3, 0x37, 0xf6, 0x94, 0xfe, 0x4e, 0x06, + 0x04, 0x0d, 0x7a, 0x0a, 0xab, 0x05, 0xd2, 0x04, 0x2f, 0x06, 0x43, 0x0c, + 0x40, 0x18, 0xba, 0x1e, 0xcf, 0x16, 0xdd, 0x11, 0x55, 0x10, 0x3e, 0x0a, + 0x57, 0x09, 0x02, 0x06, 0x6f, 0x07, 0xf9, 0x0f, 0xc4, 0x11, 0xcd, 0x11, + 0xa8, 0x12, 0xfb, 0x11, 0x54, 0x0a, 0xc4, 0x02, 0xdb, 0xff, 0xcb, 0x02, + 0x34, 0x02, 0x32, 0xfa, 0x9e, 0xf2, 0xf9, 0xe7, 0xf2, 0xe8, 0xa1, 0xea, + 0x54, 0xe5, 0xea, 0xe1, 0x9c, 0xdd, 0x9e, 0xd9, 0x7e, 0xd5, 0x29, 0xd4, + 0x4e, 0xd0, 0x2a, 0xce, 0x43, 0xce, 0x51, 0xcd, 0x57, 0xc6, 0x30, 0xbe, + 0x37, 0xb9, 0xa1, 0xb4, 0xb3, 0xbf, 0x97, 0xcf, 0x3a, 0xde, 0xe0, 0xe3, + 0xa7, 0xda, 0xb4, 0xd9, 0x06, 0xe4, 0xba, 0xf3, 0xf2, 0x05, 0xa8, 0x0d, + 0xf2, 0x04, 0xbc, 0xfd, 0xe5, 0x02, 0x3b, 0x10, 0x02, 0x1e, 0x7d, 0x21, + 0x74, 0x16, 0xd8, 0x07, 0x43, 0x07, 0x29, 0x11, 0xd2, 0x1c, 0x4a, 0x28, + 0xeb, 0x1f, 0x81, 0x0c, 0xaa, 0x07, 0xe9, 0x0a, 0x4d, 0x1b, 0xb0, 0x23, + 0x75, 0x1a, 0xe4, 0x1f, 0xab, 0x25, 0x7e, 0x27, 0xb7, 0x30, 0x79, 0x34, + 0x6d, 0x2f, 0x78, 0x26, 0x55, 0x1e, 0x91, 0x22, 0x60, 0x27, 0x77, 0x22, + 0x4d, 0x2a, 0x79, 0x2e, 0xbc, 0x2a, 0xe0, 0x29, 0xac, 0x28, 0x00, 0x36, + 0xa8, 0x3b, 0x89, 0x3b, 0x78, 0x40, 0x7b, 0x36, 0xa6, 0x2e, 0xd6, 0x31, + 0x69, 0x32, 0x46, 0x2b, 0x10, 0x24, 0x3f, 0x1a, 0x36, 0x11, 0xd2, 0x0e, + 0xe5, 0x12, 0xc7, 0x1e, 0x0b, 0x1f, 0xfe, 0x1d, 0x01, 0x17, 0x46, 0x05, + 0x22, 0x03, 0x19, 0xfe, 0x8f, 0xed, 0xbe, 0xe5, 0x94, 0xe2, 0x90, 0xdb, + 0x52, 0xd9, 0x97, 0xd1, 0x36, 0xcc, 0x2f, 0xd1, 0xc1, 0xd0, 0xf8, 0xd2, + 0xd1, 0xd3, 0xa1, 0xd7, 0xe4, 0xda, 0x39, 0xde, 0x6a, 0xf0, 0xe1, 0xfb, + 0xdb, 0x01, 0x78, 0x08, 0x2b, 0x02, 0xdd, 0x03, 0x63, 0x10, 0x9f, 0x0f, + 0xeb, 0x0f, 0x25, 0x14, 0x86, 0x16, 0xb2, 0x23, 0x12, 0x2d, 0x97, 0x30, + 0xac, 0x37, 0xf6, 0x3a, 0x83, 0x39, 0x95, 0x29, 0xfb, 0x1e, 0xfc, 0x27, + 0xd6, 0x2d, 0x1c, 0x37, 0x58, 0x37, 0xa7, 0x2c, 0xdf, 0x26, 0x77, 0x23, + 0x0d, 0x25, 0x86, 0x22, 0x7c, 0x1c, 0x55, 0x16, 0x1f, 0x16, 0x86, 0x1a, + 0x9d, 0x1f, 0x40, 0x23, 0xe4, 0x28, 0x9a, 0x2f, 0x81, 0x2f, 0x78, 0x35, + 0xee, 0x32, 0xb3, 0x2e, 0x85, 0x2e, 0xdf, 0x27, 0xf7, 0x26, 0xb9, 0x26, + 0x08, 0x26, 0x9c, 0x1e, 0x51, 0x18, 0xaa, 0x14, 0x2b, 0x0e, 0x97, 0x0a, + 0xa7, 0x00, 0xfd, 0xf1, 0x06, 0xe1, 0x12, 0xd6, 0x3e, 0xd4, 0x8a, 0xd3, + 0x27, 0xcf, 0x79, 0xc3, 0x00, 0xb5, 0x4e, 0xac, 0x3e, 0xb0, 0xfe, 0xbd, + 0x49, 0xcb, 0x9c, 0xcf, 0xdc, 0xd0, 0x91, 0xd6, 0xdc, 0xe5, 0x62, 0xf6, + 0x6b, 0xf6, 0x5a, 0xf2, 0xd3, 0xef, 0x5c, 0xf1, 0xa9, 0xff, 0xd8, 0x11, + 0xb9, 0x27, 0x9f, 0x2f, 0x6a, 0x26, 0x83, 0x21, 0x70, 0x24, 0xad, 0x37, + 0xa7, 0x42, 0xa4, 0x38, 0xc6, 0x31, 0xaa, 0x2d, 0xc0, 0x30, 0x93, 0x39, + 0x2c, 0x3b, 0x2a, 0x36, 0x55, 0x30, 0xd1, 0x30, 0x1d, 0x3f, 0x84, 0x4e, + 0x6e, 0x4c, 0xa9, 0x3c, 0x4b, 0x2a, 0x3f, 0x22, 0xa8, 0x24, 0x5a, 0x2d, + 0x40, 0x30, 0xb7, 0x28, 0xad, 0x24, 0xba, 0x25, 0xb3, 0x33, 0xc4, 0x3d, + 0xf5, 0x3c, 0x61, 0x3c, 0x38, 0x2c, 0xb1, 0x1f, 0x0e, 0x22, 0x56, 0x21, + 0xf0, 0x23, 0x60, 0x25, 0xdd, 0x1c, 0xd8, 0x14, 0x1e, 0x10, 0xff, 0x1a, + 0x7e, 0x33, 0xe5, 0x36, 0x0f, 0x29, 0x68, 0x19, 0x75, 0x03, 0x36, 0xf8, + 0xf7, 0x03, 0x26, 0x10, 0xb9, 0x0b, 0xfc, 0x01, 0x36, 0xf4, 0x23, 0xe5, + 0xc8, 0xda, 0x55, 0xc6, 0x66, 0xba, 0xf4, 0xbe, 0x7e, 0xb7, 0xb7, 0xb1, + 0x81, 0xb9, 0x04, 0xba, 0x10, 0xb4, 0xbe, 0xb2, 0x7b, 0xa7, 0xdb, 0xa7, + 0x67, 0xbb, 0xc3, 0xca, 0x7d, 0xe4, 0xcc, 0xea, 0xc0, 0xdb, 0xca, 0xd6, + 0xaf, 0xd4, 0x9b, 0xd6, 0xd2, 0xdc, 0x89, 0xe7, 0xa1, 0xf7, 0xa2, 0x07, + 0x5f, 0x0d, 0x39, 0x1e, 0x42, 0x2a, 0x68, 0x2c, 0x93, 0x38, 0x99, 0x2f, + 0xf6, 0x31, 0xf0, 0x39, 0x06, 0x39, 0x84, 0x43, 0xcf, 0x3f, 0xa9, 0x39, + 0xeb, 0x32, 0x4b, 0x28, 0x46, 0x2a, 0x4a, 0x30, 0x29, 0x2e, 0x88, 0x2a, + 0xd7, 0x29, 0x32, 0x2c, 0xcf, 0x2f, 0x5a, 0x33, 0xb2, 0x3e, 0x7d, 0x48, + 0x8e, 0x46, 0x3e, 0x3d, 0x13, 0x3b, 0x79, 0x3f, 0x36, 0x47, 0xf3, 0x4d, + 0x01, 0x46, 0xd0, 0x3b, 0x63, 0x33, 0xa5, 0x2d, 0xfc, 0x2e, 0x64, 0x31, + 0xb0, 0x2a, 0x59, 0x17, 0x01, 0x01, 0x8f, 0xf0, 0x96, 0xea, 0xd6, 0xe3, + 0x57, 0xd8, 0x97, 0xce, 0x55, 0xc0, 0xab, 0xab, 0x06, 0xa0, 0x7e, 0xa3, + 0xac, 0xaf, 0xb8, 0xbc, 0x69, 0xbe, 0xde, 0xb4, 0xe1, 0xad, 0xa4, 0xb2, + 0x47, 0xbf, 0xd7, 0xcd, 0x5f, 0xd5, 0x5b, 0xda, 0xce, 0xe5, 0xa9, 0xf1, + 0xbe, 0xfd, 0x52, 0x04, 0x81, 0x0b, 0x74, 0x13, 0x93, 0x10, 0x64, 0x16, + 0x21, 0x22, 0xfc, 0x28, 0xe3, 0x31, 0xd9, 0x2d, 0x1e, 0x2c, 0x54, 0x33, + 0x60, 0x36, 0xe6, 0x44, 0x1c, 0x4c, 0xe2, 0x3b, 0xf1, 0x27, 0x00, 0x1e, + 0x68, 0x1e, 0xa2, 0x29, 0xa0, 0x33, 0x91, 0x2a, 0xa7, 0x19, 0x67, 0x0a, + 0x6a, 0x0b, 0xb2, 0x10, 0xef, 0x0c, 0x94, 0x0e, 0x88, 0x14, 0xa3, 0x1f, + 0xd0, 0x1f, 0x57, 0x1e, 0x74, 0x22, 0x42, 0x20, 0xf7, 0x24, 0xfa, 0x25, + 0x3d, 0x25, 0x5f, 0x23, 0x76, 0x16, 0x16, 0x12, 0xa8, 0x11, 0x19, 0x0f, + 0x9f, 0x1d, 0xb2, 0x2c, 0xc3, 0x31, 0xe4, 0x3b, 0xd9, 0x39, 0x02, 0x32, + 0xde, 0x30, 0x16, 0x2c, 0xf4, 0x2c, 0x80, 0x26, 0x0b, 0x17, 0x5d, 0xfe, + 0x15, 0xda, 0xce, 0xc9, 0xdb, 0xc0, 0xe0, 0xb6, 0x76, 0xb3, 0xc3, 0xac, + 0x85, 0xaa, 0x4c, 0xaa, 0x71, 0xa4, 0x43, 0xa3, 0x0c, 0xac, 0xe0, 0xad, + 0xec, 0xb3, 0x0c, 0xc1, 0x3d, 0xc3, 0x21, 0xc3, 0x58, 0xbf, 0x45, 0xc3, + 0x79, 0xca, 0x13, 0xcb, 0x48, 0xd3, 0xe3, 0xe0, 0xb2, 0xe8, 0x71, 0xee, + 0x17, 0xfd, 0x62, 0xfe, 0xe5, 0xfe, 0x04, 0x10, 0x58, 0x12, 0x43, 0x15, + 0x9f, 0x18, 0x80, 0x12, 0x61, 0x23, 0x85, 0x28, 0xc2, 0x11, 0x83, 0x08, + 0xcf, 0xfb, 0x60, 0xef, 0x4e, 0xec, 0x5e, 0xe0, 0x48, 0xe3, 0xf6, 0xee, + 0x02, 0xf0, 0xbc, 0xfc, 0x85, 0x07, 0x56, 0x0d, 0x8c, 0x1e, 0x54, 0x22, + 0x80, 0x25, 0x96, 0x28, 0x05, 0x25, 0x5b, 0x2e, 0xa2, 0x2e, 0xfc, 0x29, + 0xa9, 0x28, 0xeb, 0x20, 0x10, 0x1e, 0x33, 0x1e, 0xab, 0x16, 0x74, 0x10, + 0x80, 0x0d, 0x89, 0x05, 0xa7, 0x00, 0x96, 0xf2, 0x50, 0xdc, 0x18, 0xca, + 0x2a, 0xbb, 0xe5, 0xb0, 0x43, 0xa8, 0xe5, 0xa2, 0xfd, 0x9b, 0xc4, 0x96, + 0x71, 0x95, 0x28, 0x9a, 0xe0, 0xa2, 0xdd, 0xa8, 0x27, 0xae, 0x15, 0xb0, + 0x29, 0xb0, 0xa1, 0xb3, 0xc1, 0xbf, 0xa0, 0xd0, 0x4e, 0xe0, 0xc9, 0xe5, + 0xe8, 0xe3, 0x13, 0xe9, 0x74, 0xf5, 0xb7, 0x07, 0xbd, 0x15, 0x30, 0x1b, + 0xb3, 0x19, 0x5d, 0x19, 0x72, 0x24, 0xd3, 0x32, 0x57, 0x3a, 0x0f, 0x3e, + 0xf7, 0x41, 0xcc, 0x44, 0x42, 0x48, 0xf0, 0x45, 0x97, 0x43, 0x33, 0x44, + 0x5b, 0x36, 0x1a, 0x21, 0x45, 0x18, 0x6b, 0x19, 0x8c, 0x1b, 0x83, 0x21, + 0x83, 0x26, 0x12, 0x20, 0x01, 0x17, 0x28, 0x12, 0x11, 0x16, 0x83, 0x22, + 0x5e, 0x28, 0x36, 0x2a, 0xb6, 0x2a, 0x8c, 0x27, 0x8d, 0x20, 0x9c, 0x1c, + 0xfc, 0x1b, 0xcb, 0x15, 0xbb, 0x16, 0x23, 0x17, 0x67, 0x10, 0x85, 0x0b, + 0xae, 0x05, 0x6d, 0xfe, 0xc8, 0xfd, 0x42, 0xfe, 0xdb, 0xf9, 0x22, 0xfc, + 0xd4, 0xfb, 0xd9, 0xfd, 0xfd, 0x04, 0xb0, 0x0f, 0xf4, 0x1d, 0x90, 0x21, + 0x01, 0x1e, 0xd8, 0x0e, 0x8f, 0xf7, 0xcc, 0xdd, 0x0c, 0xca, 0x13, 0xc0, + 0x1a, 0xb9, 0xd0, 0xb5, 0xd9, 0xaa, 0x53, 0xa1, 0x99, 0xa5, 0xf3, 0xab, + 0x22, 0xb2, 0x3f, 0xb9, 0x80, 0xb8, 0x11, 0xbe, 0x53, 0xcb, 0xc7, 0xcf, + 0x13, 0xcd, 0x1b, 0xcb, 0xef, 0xcb, 0xc7, 0xc2, 0x22, 0xc5, 0xa1, 0xd5, + 0xaa, 0xdd, 0x96, 0xe5, 0x67, 0xed, 0xcd, 0xf2, 0x95, 0xfb, 0x69, 0x0e, + 0x16, 0x1e, 0x0f, 0x2c, 0x91, 0x2e, 0x6b, 0x20, 0x84, 0x26, 0xb0, 0x2c, + 0x9c, 0x29, 0xe8, 0x2b, 0x24, 0x25, 0x09, 0x18, 0xa3, 0x06, 0x0f, 0xfc, + 0x6a, 0xfd, 0x7f, 0xfa, 0xbf, 0xf3, 0xa1, 0xf4, 0x0b, 0x02, 0xf0, 0x0c, + 0xaf, 0x12, 0x32, 0x1b, 0x98, 0x21, 0x18, 0x26, 0x10, 0x26, 0x03, 0x30, + 0xb8, 0x3c, 0x79, 0x38, 0xbc, 0x30, 0x8b, 0x22, 0x95, 0x13, 0x80, 0x0c, + 0xb8, 0x04, 0x2b, 0xfe, 0x53, 0x01, 0x90, 0x02, 0x8e, 0xf7, 0xc0, 0xec, + 0x6f, 0xdf, 0xe8, 0xcd, 0xea, 0xbf, 0x84, 0xbc, 0x8d, 0xb9, 0x15, 0xae, + 0xf4, 0xa2, 0xa0, 0x98, 0x58, 0x98, 0xe3, 0xa0, 0xff, 0xab, 0x6b, 0xb3, + 0xf8, 0xab, 0x58, 0xa5, 0x4c, 0xae, 0x60, 0xbf, 0xf4, 0xcf, 0x62, 0xdb, + 0xfa, 0xd6, 0x68, 0xcf, 0x37, 0xd7, 0x04, 0xe8, 0x3c, 0x00, 0xb9, 0x11, + 0xb8, 0x0f, 0xab, 0x09, 0x8e, 0x06, 0xcd, 0x0b, 0x83, 0x22, 0x90, 0x35, + 0x41, 0x36, 0xc4, 0x34, 0xf8, 0x30, 0xc7, 0x32, 0x8a, 0x3c, 0xfd, 0x3a, + 0x31, 0x3b, 0x8c, 0x3d, 0x58, 0x39, 0xd5, 0x38, 0x4d, 0x36, 0x5b, 0x31, + 0x43, 0x2f, 0x1b, 0x2a, 0x4b, 0x28, 0xd1, 0x28, 0x47, 0x23, 0x87, 0x24, + 0xd6, 0x26, 0x22, 0x2d, 0x35, 0x37, 0x0e, 0x37, 0x67, 0x3a, 0x11, 0x36, + 0xf2, 0x2a, 0x2a, 0x27, 0x60, 0x2a, 0xfa, 0x33, 0x8c, 0x32, 0xd6, 0x24, + 0xdf, 0x1a, 0xf3, 0x15, 0x55, 0x10, 0x37, 0x0f, 0xb6, 0x0a, 0x6e, 0x04, + 0x57, 0x07, 0x8a, 0x0b, 0xec, 0x13, 0x62, 0x20, 0xbb, 0x20, 0x62, 0x19, + 0xa1, 0x1a, 0x04, 0x1c, 0x10, 0x29, 0x52, 0x38, 0xc3, 0x31, 0xa4, 0x29, + 0xc1, 0x17, 0x1e, 0xf6, 0xab, 0xe4, 0xb4, 0xea, 0xf3, 0xeb, 0xa3, 0xe3, + 0x80, 0xd2, 0x58, 0xc3, 0x9a, 0xcd, 0x8c, 0xd4, 0xe1, 0xd3, 0xe9, 0xd8, + 0x14, 0xd7, 0x7c, 0xd1, 0x82, 0xda, 0xdf, 0xeb, 0x9a, 0xeb, 0x1c, 0xef, + 0xe9, 0xf7, 0x12, 0xee, 0x81, 0xf4, 0xc7, 0x03, 0xd8, 0x0c, 0x93, 0x25, + 0x42, 0x21, 0x6c, 0x18, 0xac, 0x25, 0xc1, 0x28, 0x0a, 0x35, 0x09, 0x3a, + 0x65, 0x3e, 0x49, 0x43, 0xee, 0x3c, 0xa2, 0x3a, 0xc6, 0x3c, 0x35, 0x42, + 0x07, 0x37, 0x15, 0x2c, 0x3a, 0x25, 0xad, 0x1e, 0x95, 0x1d, 0xfb, 0x19, + 0xf0, 0x1d, 0xf2, 0x1d, 0x76, 0x1d, 0x67, 0x26, 0x55, 0x30, 0xf3, 0x3a, + 0x43, 0x47, 0x17, 0x4b, 0x5d, 0x4a, 0x08, 0x4d, 0x1b, 0x48, 0x47, 0x44, + 0x47, 0x3e, 0xf4, 0x33, 0x94, 0x30, 0x09, 0x2f, 0x72, 0x30, 0x4d, 0x2c, + 0xb3, 0x25, 0x3c, 0x19, 0xba, 0x01, 0xee, 0xf4, 0xb3, 0xe9, 0xd8, 0xe0, + 0x92, 0xd4, 0x9b, 0xbc, 0xa2, 0xb2, 0x59, 0xb3, 0xa8, 0xb6, 0x0f, 0xbd, + 0x54, 0xc0, 0x87, 0xba, 0x30, 0xb4, 0xa4, 0xb2, 0x92, 0xbb, 0x5a, 0xce, + 0x2d, 0xd6, 0xe6, 0xd5, 0x2c, 0xd3, 0x9b, 0xd5, 0xe4, 0xdf, 0xc7, 0xee, + 0xab, 0xf9, 0x95, 0xfb, 0x39, 0x01, 0x0d, 0x09, 0x31, 0x13, 0x43, 0x1d, + 0xbf, 0x25, 0xd8, 0x2a, 0x51, 0x2a, 0xab, 0x24, 0x11, 0x24, 0x51, 0x30, + 0xc8, 0x41, 0x90, 0x50, 0x41, 0x4f, 0xf8, 0x43, 0x4f, 0x35, 0xe2, 0x2d, + 0xc6, 0x32, 0x90, 0x34, 0x13, 0x38, 0xe9, 0x39, 0xe7, 0x31, 0x30, 0x2b, + 0xe2, 0x2b, 0x69, 0x2d, 0xdf, 0x29, 0x32, 0x2f, 0x97, 0x3a, 0x55, 0x39, + 0x75, 0x39, 0x7e, 0x3a, 0x1f, 0x38, 0xdc, 0x3c, 0xcb, 0x40, 0x49, 0x39, + 0x44, 0x2f, 0x63, 0x2d, 0xaa, 0x29, 0x12, 0x25, 0xf2, 0x17, 0xe0, 0x09, + 0x57, 0x08, 0xaf, 0x05, 0xa7, 0x07, 0xaa, 0x0f, 0xd0, 0x14, 0x1a, 0x0d, + 0xac, 0x00, 0x66, 0xfa, 0x46, 0xf7, 0x6e, 0x07, 0xfa, 0x17, 0x96, 0x10, + 0x57, 0x0b, 0x04, 0x02, 0x83, 0xf5, 0xd7, 0xf5, 0x71, 0xf0, 0xb9, 0xe5, + 0x5f, 0xde, 0x57, 0xdc, 0x55, 0xd9, 0xb2, 0xd4, 0x8d, 0xcd, 0xe6, 0xc7, + 0x44, 0xc7, 0xcf, 0xc7, 0x0f, 0xcd, 0xb8, 0xcb, 0x50, 0xce, 0x55, 0xcf, + 0x32, 0xca, 0xd4, 0xd2, 0x06, 0xd7, 0x1c, 0xd3, 0x73, 0xd7, 0x7f, 0xda, + 0x35, 0xe4, 0x8d, 0xfd, 0x60, 0x0a, 0x3e, 0x0c, 0xcb, 0x0c, 0x7c, 0x0c, + 0xa5, 0x13, 0x22, 0x1f, 0x03, 0x20, 0x59, 0x1d, 0x8c, 0x20, 0xe2, 0x1e, + 0xc1, 0x26, 0x1c, 0x29, 0x4c, 0x2d, 0xa8, 0x38, 0xf1, 0x2e, 0x49, 0x2c, + 0x84, 0x28, 0x27, 0x23, 0xc0, 0x2a, 0x38, 0x25, 0x6f, 0x1d, 0x11, 0x1a, + 0x76, 0x18, 0x92, 0x22, 0xc3, 0x2e, 0x41, 0x35, 0x97, 0x3d, 0x05, 0x45, + 0x34, 0x41, 0x7c, 0x3f, 0xd7, 0x40, 0x75, 0x3f, 0xd6, 0x3c, 0xef, 0x32, + 0x3d, 0x2a, 0x4f, 0x23, 0xf5, 0x1b, 0x72, 0x12, 0x1f, 0x02, 0x08, 0xf1, + 0xc0, 0xec, 0xc0, 0xec, 0xe3, 0xe6, 0xc7, 0xdc, 0xc7, 0xc8, 0x92, 0xbf, + 0xe8, 0xc3, 0x6c, 0xc7, 0x27, 0xc3, 0xda, 0xbb, 0x3e, 0xb9, 0xe6, 0xbd, + 0x5f, 0xca, 0xb5, 0xcf, 0xa6, 0xd0, 0x1b, 0xce, 0xc1, 0xd2, 0x7e, 0xdd, + 0x02, 0xe5, 0xad, 0xee, 0x12, 0xf3, 0xac, 0xf1, 0x6c, 0xf3, 0xb6, 0xfb, + 0x83, 0x03, 0x45, 0x12, 0x79, 0x1a, 0x89, 0x1d, 0xca, 0x23, 0x10, 0x1d, + 0x16, 0x1e, 0xda, 0x25, 0x45, 0x27, 0xd0, 0x27, 0xd6, 0x22, 0x53, 0x1f, + 0x51, 0x1f, 0x12, 0x1e, 0xd4, 0x1f, 0x10, 0x1b, 0x02, 0x1c, 0x9e, 0x21, + 0xa4, 0x1e, 0xeb, 0x21, 0x2e, 0x20, 0xc1, 0x21, 0x98, 0x24, 0xe6, 0x20, + 0x50, 0x21, 0xc5, 0x1c, 0x42, 0x21, 0x8a, 0x2e, 0xf1, 0x34, 0xc1, 0x38, + 0x37, 0x3a, 0x92, 0x36, 0x6b, 0x2c, 0x47, 0x1a, 0x28, 0x11, 0xb2, 0x14, + 0x65, 0x11, 0x2a, 0x08, 0xfa, 0xfe, 0xa0, 0xfb, 0xf6, 0x01, 0x1f, 0x0e, + 0x92, 0x0e, 0x46, 0x00, 0x52, 0xf8, 0xaa, 0xf2, 0xf9, 0xf4, 0x53, 0xfd, + 0x30, 0xf7, 0x9a, 0xf2, 0x95, 0xe5, 0x7c, 0xd3, 0xe0, 0xdd, 0x78, 0xee, + 0xc9, 0xfe, 0x3b, 0x08, 0x10, 0xf7, 0x38, 0xec, 0x67, 0xec, 0x48, 0xeb, + 0x19, 0xf3, 0x10, 0xef, 0x53, 0xe2, 0xa1, 0xdf, 0xc8, 0xd9, 0x3b, 0xd2, + 0xa4, 0xc5, 0x2b, 0xb8, 0x65, 0xbb, 0x17, 0xca, 0xbc, 0xd1, 0x1a, 0xce, + 0x2c, 0xcd, 0x8a, 0xc7, 0x56, 0xc5, 0x23, 0xd0, 0x71, 0xdb, 0xf9, 0xed, + 0xd0, 0xfc, 0xcd, 0xf6, 0x6c, 0xee, 0x4c, 0xeb, 0x26, 0xe7, 0xe8, 0xf0, + 0x73, 0xfa, 0x9f, 0xf7, 0xc4, 0xf5, 0xfb, 0xf6, 0x56, 0x03, 0x33, 0x0c, + 0x31, 0x0b, 0xbb, 0x0f, 0xba, 0x0f, 0xea, 0x0c, 0x82, 0x0f, 0xdd, 0x12, + 0x7a, 0x1b, 0x68, 0x18, 0xa6, 0x07, 0xc8, 0xfb, 0x61, 0xf6, 0x00, 0xfd, + 0x58, 0x02, 0x9b, 0x05, 0x26, 0x0a, 0x20, 0x11, 0x3d, 0x1e, 0x2e, 0x23, + 0x6b, 0x22, 0xb7, 0x20, 0xd3, 0x18, 0x7f, 0x0d, 0x08, 0x02, 0x67, 0xf1, + 0x88, 0xe5, 0x46, 0xd9, 0x26, 0xd1, 0x19, 0xca, 0x3e, 0xb9, 0x3a, 0xb1, + 0x1b, 0xa7, 0xaa, 0xa9, 0xf1, 0xb6, 0x44, 0xbe, 0x3b, 0xc1, 0x0c, 0xba, + 0x10, 0xb4, 0x27, 0xb7, 0x2e, 0xbf, 0x78, 0xc2, 0xf6, 0xc4, 0x8d, 0xbc, + 0xfe, 0xb3, 0x05, 0xb6, 0x79, 0xbd, 0x3c, 0xce, 0x9c, 0xdd, 0x48, 0xe1, + 0xe2, 0xdc, 0xb5, 0xde, 0x9b, 0xe7, 0x2e, 0xfa, 0xeb, 0x02, 0x65, 0x05, + 0xed, 0x07, 0xe6, 0x03, 0x52, 0x08, 0x3b, 0x0c, 0xa5, 0x13, 0x22, 0x19, + 0x55, 0x15, 0xe5, 0x16, 0x05, 0x22, 0xad, 0x2c, 0xf7, 0x2f, 0x84, 0x29, + 0x42, 0x24, 0x02, 0x25, 0x38, 0x28, 0xf9, 0x30, 0xd5, 0x33, 0x16, 0x38, + 0xf3, 0x38, 0xd1, 0x37, 0x6c, 0x3a, 0xe7, 0x36, 0x3b, 0x32, 0x73, 0x30, + 0x8a, 0x2e, 0x15, 0x2d, 0xda, 0x2e, 0xa2, 0x2b, 0x7a, 0x27, 0x5d, 0x1d, + 0x18, 0x1c, 0x37, 0x21, 0xde, 0x1e, 0x0f, 0x1c, 0x07, 0x0e, 0x21, 0x06, + 0x9c, 0x08, 0xfc, 0x05, 0x31, 0xfc, 0xf0, 0xf1, 0xb6, 0xe7, 0x17, 0xe9, + 0xb8, 0xf1, 0x3f, 0xed, 0xbe, 0xe6, 0xf2, 0xdf, 0xab, 0xe1, 0x12, 0xeb, + 0xc0, 0xf3, 0x72, 0xfc, 0x59, 0xfc, 0xe9, 0xfe, 0x30, 0x04, 0xe8, 0xfb, + 0xaf, 0xf8, 0x2d, 0xf2, 0x54, 0xe9, 0x01, 0xf0, 0xa6, 0xeb, 0xb4, 0xe4, + 0x51, 0xda, 0x02, 0xc9, 0x04, 0xc3, 0x11, 0xc2, 0x48, 0xbe, 0x2a, 0xbe, + 0xe2, 0xc2, 0xf4, 0xc3, 0x53, 0xc4, 0x51, 0xc4, 0xae, 0xcb, 0x8b, 0xd1, + 0xe9, 0xd5, 0x11, 0xd9, 0x14, 0xd6, 0x90, 0xda, 0xc1, 0xdc, 0x38, 0xdf, + 0x84, 0xe5, 0x7a, 0xe4, 0xd3, 0xe2, 0x78, 0xec, 0x2f, 0xfa, 0x84, 0x0d, + 0x47, 0x17, 0xb2, 0x11, 0x8f, 0x18, 0x1e, 0x19, 0x98, 0x17, 0xc2, 0x1e, + 0x91, 0x19, 0x1e, 0x13, 0x0d, 0x13, 0x00, 0x10, 0x2b, 0x0a, 0xe5, 0x08, + 0x07, 0x0a, 0xcb, 0x0d, 0x8e, 0x16, 0x77, 0x15, 0xb8, 0x0f, 0x36, 0x16, + 0x4a, 0x1e, 0x77, 0x25, 0x49, 0x30, 0xe6, 0x2e, 0x4f, 0x24, 0xf2, 0x1c, + 0x7d, 0x0c, 0x5b, 0xfc, 0x00, 0xee, 0xce, 0xde, 0xa4, 0xdc, 0x72, 0xd6, + 0x18, 0xcb, 0x24, 0xbe, 0xc3, 0xb3, 0x14, 0xb7, 0x0d, 0xc1, 0xbd, 0xce, + 0x34, 0xd3, 0x4e, 0xc7, 0xb3, 0xbb, 0xb3, 0xb9, 0x8d, 0xbf, 0x6d, 0xc8, + 0x5b, 0xc9, 0xa0, 0xc7, 0x0a, 0xc5, 0xe0, 0xc3, 0x23, 0xcb, 0xe8, 0xd1, + 0x55, 0xd8, 0x30, 0xd8, 0xfc, 0xd3, 0x74, 0xd3, 0x15, 0xd4, 0xee, 0xdc, + 0x98, 0xea, 0xb8, 0xf0, 0x12, 0xf1, 0x5a, 0xf0, 0xd6, 0xf1, 0x08, 0xfc, + 0xb3, 0x06, 0x15, 0x0b, 0xee, 0x07, 0xc6, 0x04, 0x56, 0x0a, 0x53, 0x14, + 0x4a, 0x1d, 0x4b, 0x1e, 0x3b, 0x1c, 0x62, 0x1c, 0x9e, 0x25, 0x7a, 0x35, + 0x19, 0x45, 0xb2, 0x4d, 0xa0, 0x4d, 0xbf, 0x4f, 0x31, 0x51, 0x81, 0x53, + 0x59, 0x53, 0xce, 0x53, 0x64, 0x54, 0x3d, 0x51, 0xa5, 0x4c, 0xa3, 0x40, + 0x91, 0x38, 0x42, 0x33, 0xf0, 0x2b, 0x56, 0x25, 0x73, 0x21, 0x31, 0x1f, + 0x38, 0x1d, 0x2d, 0x1d, 0x40, 0x16, 0xff, 0x0c, 0x5e, 0x08, 0x2a, 0x05, + 0x24, 0x03, 0x2d, 0xfb, 0x55, 0xed, 0xd2, 0xef, 0x77, 0xf5, 0x29, 0xf6, + 0xcf, 0xff, 0x2b, 0x04, 0x18, 0x06, 0x00, 0x0a, 0xdc, 0x0d, 0xab, 0x14, + 0x06, 0x1c, 0x43, 0x21, 0x23, 0x26, 0xff, 0x26, 0x06, 0x25, 0x12, 0x24, + 0x80, 0x29, 0xc1, 0x32, 0x94, 0x31, 0x66, 0x28, 0x1d, 0x10, 0x68, 0xfc, + 0xfa, 0xf5, 0xe5, 0xed, 0xcb, 0xe7, 0xed, 0xe3, 0x59, 0xe3, 0x69, 0xe2, + 0x14, 0xe6, 0x21, 0xe8, 0x7b, 0xe9, 0xa2, 0xec, 0x40, 0xf1, 0xe6, 0xf9, + 0xc3, 0x02, 0xda, 0x08, 0x68, 0x12, 0x34, 0x1d, 0x9e, 0x1c, 0xa3, 0x20, + 0x83, 0x1f, 0xa7, 0x21, 0x43, 0x27, 0xfc, 0x26, 0x76, 0x2a, 0x18, 0x28, + 0xed, 0x2c, 0x07, 0x39, 0x2a, 0x3d, 0xf1, 0x36, 0x22, 0x3d, 0x2b, 0x3b, + 0xec, 0x34, 0x77, 0x39, 0xad, 0x2f, 0x27, 0x29, 0x74, 0x21, 0xb8, 0x1e, + 0x42, 0x23, 0xa6, 0x28, 0x3c, 0x29, 0xbd, 0x26, 0x9c, 0x2c, 0xf8, 0x33, + 0xae, 0x3b, 0x17, 0x38, 0x1b, 0x32, 0x6c, 0x28, 0xf9, 0x1c, 0xf1, 0x11, + 0x73, 0x08, 0xa1, 0x06, 0x49, 0xfd, 0x75, 0xec, 0x4c, 0xda, 0x97, 0xd7, + 0xb4, 0xe1, 0xec, 0xea, 0x01, 0xee, 0x5c, 0xe7, 0xa3, 0xdb, 0x68, 0xd5, + 0xc5, 0xd6, 0x5c, 0xdb, 0xd3, 0xe2, 0xfd, 0xe1, 0x0f, 0xdd, 0x8c, 0xd8, + 0x27, 0xd6, 0x18, 0xd9, 0x9f, 0xe1, 0x88, 0xe7, 0xcf, 0xe0, 0x41, 0xdb, + 0x85, 0xdb, 0xee, 0xdf, 0x33, 0xe9, 0xca, 0xeb, 0x62, 0xe8, 0x2d, 0xec, + 0x2f, 0xf6, 0xbb, 0x04, 0xbd, 0x09, 0x3c, 0x06, 0x53, 0x0a, 0xca, 0x10, + 0xc4, 0x16, 0xfd, 0x16, 0xad, 0x16, 0xdb, 0x19, 0x24, 0x27, 0xaf, 0x36, + 0xe8, 0x3d, 0xc9, 0x3f, 0x85, 0x3a, 0x99, 0x3a, 0x6a, 0x40, 0x7f, 0x4c, + 0xf9, 0x52, 0x64, 0x51, 0xce, 0x4f, 0x4a, 0x4b, 0x5e, 0x4a, 0xf9, 0x4a, + 0xfb, 0x47, 0x85, 0x43, 0x0c, 0x41, 0x63, 0x38, 0x23, 0x32, 0x99, 0x2b, + 0x13, 0x1e, 0x9a, 0x1a, 0x8b, 0x1a, 0x3f, 0x14, 0x22, 0x0e, 0x27, 0x09, + 0x78, 0xfe, 0x0a, 0xf4, 0x19, 0xee, 0xa0, 0xef, 0xe0, 0xf4, 0xdf, 0xf4, + 0x94, 0xef, 0xc5, 0xe8, 0xed, 0xe4, 0x7a, 0xe8, 0xa5, 0xf6, 0xfc, 0x01, + 0xd1, 0x02, 0xaa, 0xf9, 0xdf, 0xf7, 0xd3, 0xfe, 0x54, 0x04, 0x64, 0x07, + 0x04, 0x06, 0x50, 0x0c, 0x3e, 0x14, 0x10, 0x19, 0x87, 0x17, 0x63, 0x11, + 0x29, 0x0a, 0xc0, 0x09, 0xaf, 0x0a, 0x1b, 0x0c, 0x95, 0x12, 0x4b, 0x05, + 0xea, 0xff, 0x9b, 0xfe, 0xd8, 0xeb, 0x5e, 0xe2, 0x01, 0xeb, 0x2d, 0xf1, + 0x8e, 0xeb, 0x15, 0xe6, 0xa5, 0xdb, 0xfb, 0xd7, 0x77, 0xd8, 0x5f, 0xdc, + 0xfb, 0xe6, 0x8b, 0xf2, 0x72, 0x00, 0xd1, 0x09, 0x16, 0x0b, 0x33, 0x02, + 0x03, 0xff, 0x9c, 0xfe, 0xc0, 0x01, 0xf0, 0x07, 0x32, 0x0a, 0x5e, 0x11, + 0x87, 0x0f, 0x5b, 0x0b, 0xf0, 0x12, 0x0b, 0x14, 0x56, 0x17, 0x0f, 0x24, + 0xf1, 0x1f, 0x34, 0x21, 0x87, 0x28, 0x57, 0x1b, 0xc4, 0x18, 0xfe, 0x1d, + 0xf8, 0x17, 0x43, 0x1d, 0xcf, 0x24, 0x95, 0x25, 0xb9, 0x29, 0x67, 0x20, + 0x77, 0x10, 0x7b, 0x07, 0x57, 0x02, 0xdd, 0x00, 0x63, 0x01, 0x67, 0xfa, + 0x1c, 0xeb, 0x82, 0xe0, 0x38, 0xde, 0xc9, 0xeb, 0x46, 0xfb, 0xca, 0x00, + 0xee, 0xff, 0x79, 0xf3, 0x50, 0xea, 0x67, 0xf3, 0x49, 0xff, 0x22, 0x06, + 0x3f, 0x06, 0xc1, 0xf6, 0x6e, 0xed, 0x1b, 0xed, 0x7f, 0xef, 0x73, 0xfb, + 0x69, 0x04, 0x69, 0x01, 0x4f, 0xfd, 0x16, 0xfe, 0xb9, 0xf7, 0xf2, 0xf6, + 0xaf, 0xf8, 0x60, 0xf2, 0x33, 0xef, 0xbf, 0xec, 0x33, 0xf3, 0x9b, 0xfe, + 0x33, 0xff, 0x1f, 0xfe, 0x42, 0xff, 0x24, 0x00, 0xd8, 0x06, 0x3f, 0x0e, + 0xdd, 0x14, 0x4f, 0x1a, 0xb3, 0x1c, 0x58, 0x20, 0x91, 0x21, 0xb7, 0x22, + 0x14, 0x25, 0x12, 0x28, 0x09, 0x2a, 0x37, 0x27, 0x95, 0x21, 0xaa, 0x1c, + 0xed, 0x1e, 0x18, 0x25, 0x1f, 0x27, 0x69, 0x26, 0x47, 0x22, 0x49, 0x19, + 0xc6, 0x0c, 0x76, 0x01, 0x40, 0xfe, 0xd6, 0xfd, 0xfb, 0xf9, 0xbd, 0xf2, + 0x44, 0xea, 0x27, 0xed, 0x8b, 0xf7, 0x90, 0xfa, 0x39, 0xf6, 0x75, 0xee, + 0x50, 0xe6, 0x21, 0xe1, 0x2b, 0xe6, 0x77, 0xef, 0xd0, 0xf2, 0x25, 0xf4, + 0x66, 0xf2, 0x5b, 0xf6, 0x12, 0xfe, 0xa2, 0xfc, 0x22, 0x00, 0x4b, 0x04, + 0x48, 0x06, 0x91, 0x0a, 0x97, 0x09, 0x40, 0x0a, 0x6a, 0x10, 0xd3, 0x14, + 0x20, 0x14, 0x3a, 0x13, 0x00, 0x0d, 0x01, 0x05, 0xb5, 0xfe, 0x7b, 0xfa, + 0xd3, 0xfc, 0x0d, 0xf6, 0xa0, 0xf0, 0xdf, 0xf2, 0x55, 0xf0, 0x64, 0xec, + 0x21, 0xf0, 0x7f, 0xf6, 0x39, 0xf8, 0xdf, 0x03, 0xbb, 0x08, 0x37, 0x04, + 0x81, 0x09, 0x0d, 0x0c, 0x52, 0x05, 0x28, 0xf9, 0x59, 0xef, 0xa9, 0xea, + 0x68, 0xe4, 0xb7, 0xdb, 0x5c, 0xd6, 0xdc, 0xcd, 0x8c, 0xc6, 0x2a, 0xc7, + 0x30, 0xc7, 0xf6, 0xc9, 0x77, 0xce, 0x66, 0xd1, 0x82, 0xd3, 0x21, 0xd9, + 0x3f, 0xdb, 0x9c, 0xdb, 0xb1, 0xe1, 0xd6, 0xe0, 0xd4, 0xe4, 0x2e, 0xe7, + 0x97, 0xe3, 0x0d, 0xeb, 0xe9, 0xee, 0xdd, 0xf3, 0x02, 0x02, 0xa4, 0x0b, + 0x47, 0x13, 0xbb, 0x19, 0xd5, 0x16, 0x90, 0x15, 0x42, 0x13, 0x14, 0x04, + 0x19, 0xf7, 0x28, 0xea, 0xa3, 0xdc, 0x40, 0xd4, 0x3f, 0xc5, 0xd1, 0xb4, + 0xe8, 0xb1, 0x50, 0xb7, 0xc2, 0xc0, 0x79, 0xcd, 0x40, 0xcf, 0x5c, 0xcd, + 0xf6, 0xce, 0x78, 0xd5, 0x49, 0xe5, 0x5a, 0xf6, 0x94, 0xff, 0x3e, 0xfd, + 0x7a, 0xf9, 0x6d, 0xfa, 0xcf, 0x00, 0x05, 0x06, 0x48, 0x0a, 0xc0, 0x07, + 0xcb, 0xfe, 0x97, 0xfd, 0x0d, 0xff, 0x96, 0x06, 0x96, 0x06, 0x9c, 0x00, + 0x12, 0x02, 0x0b, 0x00, 0x71, 0xff, 0xce, 0xfd, 0x62, 0xf4, 0x1a, 0xed, + 0x44, 0xea, 0x05, 0xe4, 0x10, 0xe6, 0x03, 0xef, 0xe1, 0xf2, 0x11, 0xf8, + 0xfe, 0xf9, 0xbc, 0xf7, 0xdf, 0xfa, 0x7c, 0x00, 0xa4, 0x09, 0xf5, 0x18, + 0xce, 0x23, 0x17, 0x28, 0xdb, 0x26, 0xe7, 0x21, 0x55, 0x1a, 0xab, 0x15, + 0xd3, 0x17, 0xc0, 0x17, 0xaf, 0x13, 0xcb, 0x04, 0x05, 0xee, 0xe9, 0xdf, + 0x45, 0xdd, 0x34, 0xde, 0x7c, 0xdf, 0x4c, 0xdf, 0x3e, 0xda, 0x51, 0xd9, + 0xfd, 0xda, 0x81, 0xda, 0xf8, 0xdb, 0x9a, 0xd7, 0x27, 0xd3, 0x91, 0xd6, + 0x2b, 0xdd, 0xb7, 0xe3, 0x8e, 0xe9, 0xa8, 0xf1, 0xcd, 0xf6, 0x38, 0xfc, + 0x43, 0x05, 0x57, 0x16, 0xff, 0x2c, 0x9c, 0x3a, 0xd7, 0x3f, 0x38, 0x39, + 0x68, 0x30, 0xa4, 0x2f, 0x70, 0x32, 0x99, 0x34, 0xa2, 0x36, 0xb2, 0x35, + 0x03, 0x30, 0xb3, 0x2a, 0x21, 0x1d, 0x60, 0x12, 0xdc, 0x0f, 0x6f, 0x12, + 0xc8, 0x16, 0x46, 0x0f, 0x0c, 0xff, 0xc8, 0xf0, 0x06, 0xf3, 0x3b, 0xfd, + 0x75, 0x01, 0x97, 0xff, 0x00, 0xfb, 0x48, 0xff, 0x53, 0x09, 0x4a, 0x0d, + 0x93, 0x0f, 0x31, 0x11, 0xb8, 0x08, 0xb4, 0xfb, 0x10, 0xf3, 0xcd, 0xec, + 0xe4, 0xea, 0x96, 0xe3, 0x92, 0xd5, 0x54, 0xd0, 0xf6, 0xcd, 0x85, 0xca, + 0xf0, 0xc3, 0x20, 0xc0, 0xaf, 0xba, 0x0d, 0xb5, 0xeb, 0xb9, 0x93, 0xbd, + 0x74, 0xc2, 0xd0, 0xbb, 0xf0, 0xba, 0x76, 0xc0, 0x6b, 0xc0, 0xa8, 0xc9, + 0x0d, 0xcb, 0x0c, 0xd0, 0x43, 0xd8, 0x7a, 0xe1, 0x06, 0xf3, 0xea, 0xfe, + 0xeb, 0x04, 0xa0, 0x0f, 0xa6, 0x18, 0xa9, 0x1b, 0x7d, 0x15, 0xae, 0x00, + 0xb1, 0xf8, 0xc7, 0xf1, 0xb4, 0xe3, 0x2f, 0xd4, 0xaf, 0xc1, 0x08, 0xc3, + 0x41, 0xcf, 0x81, 0xda, 0xdc, 0xe1, 0x11, 0xde, 0x5d, 0xd6, 0xaf, 0xd7, + 0x0f, 0xdc, 0x4b, 0xea, 0x43, 0xfe, 0xe1, 0x01, 0x11, 0xfc, 0xcb, 0xf7, + 0x8a, 0xfc, 0x23, 0x08, 0x22, 0x18, 0xe1, 0x20, 0x5e, 0x1b, 0x92, 0x16, + 0xd4, 0x1a, 0x3d, 0x26, 0xd6, 0x34, 0xdd, 0x39, 0x1d, 0x31, 0x3b, 0x2c, + 0x2d, 0x2c, 0xa1, 0x2c, 0xb1, 0x26, 0xc6, 0x1a, 0x6a, 0x11, 0xe0, 0x06, + 0xa5, 0xfe, 0x1c, 0xf9, 0xb8, 0xf3, 0x9d, 0xef, 0x2b, 0xef, 0x6d, 0xf0, + 0xf0, 0xef, 0xca, 0xef, 0x05, 0xec, 0x2d, 0xe7, 0xdf, 0xe6, 0x67, 0xe6, + 0x71, 0xeb, 0x0a, 0xf8, 0x39, 0x00, 0x54, 0xfa, 0xa7, 0xee, 0x56, 0xec, + 0x82, 0xf4, 0xa0, 0xfe, 0x46, 0xfa, 0xf0, 0xed, 0xc5, 0xe3, 0xb4, 0xde, + 0x3d, 0xe2, 0xe6, 0xeb, 0x8e, 0xf5, 0x8b, 0xf5, 0xa6, 0xf3, 0x9c, 0xf4, + 0xb6, 0xfa, 0xc8, 0xff, 0x8c, 0x01, 0x52, 0xff, 0xc2, 0xf8, 0x87, 0xf7, + 0x86, 0xf9, 0x19, 0x00, 0xe8, 0x06, 0x2a, 0x08, 0x2e, 0x05, 0x23, 0x0c, + 0x48, 0x1e, 0x83, 0x30, 0xfb, 0x40, 0x35, 0x49, 0x73, 0x4a, 0x1c, 0x4e, + 0x01, 0x58, 0x4a, 0x5d, 0x4e, 0x5f, 0xd7, 0x5b, 0xb6, 0x58, 0x4a, 0x5f, + 0x11, 0x66, 0x8c, 0x6b, 0x9e, 0x69, 0x3c, 0x64, 0xb7, 0x61, 0xc6, 0x63, + 0xb8, 0x62, 0x80, 0x5c, 0xe0, 0x55, 0xc2, 0x47, 0x6b, 0x39, 0xb8, 0x35, + 0xeb, 0x32, 0xa5, 0x2c, 0x00, 0x2c, 0x24, 0x23, 0xd9, 0x17, 0x7b, 0x18, + 0x1d, 0x1c, 0x7f, 0x1f, 0xdb, 0x22, 0x1b, 0x1f, 0x50, 0x12, 0xd3, 0x0e, + 0xb0, 0x0e, 0x2e, 0x0d, 0x7d, 0x0e, 0x63, 0x02, 0x44, 0xf2, 0x5f, 0xed, + 0x1a, 0xec, 0xf3, 0xed, 0x73, 0xee, 0x88, 0xe9, 0x61, 0xe7, 0xcc, 0xe2, + 0x50, 0xe0, 0xd8, 0xe2, 0x00, 0xe8, 0x6e, 0xef, 0xe5, 0xef, 0x25, 0xe9, + 0xb5, 0xe5, 0xe8, 0xe7, 0x06, 0xe8, 0x53, 0xf4, 0x28, 0x02, 0x1a, 0x02, + 0xc0, 0x04, 0x5f, 0x05, 0x6f, 0x04, 0x43, 0x05, 0x6d, 0x03, 0x6e, 0x03, + 0x64, 0x06, 0xb5, 0x05, 0x18, 0xf8, 0xad, 0xe7, 0x29, 0xe5, 0x76, 0xed, + 0x6f, 0x00, 0xf5, 0x10, 0xca, 0x0a, 0xdb, 0xf9, 0x43, 0xf0, 0xbe, 0xf5, + 0xba, 0x02, 0x00, 0x10, 0x82, 0x15, 0x8a, 0x0e, 0xd4, 0x0a, 0xc9, 0x0e, + 0x1c, 0x1b, 0x52, 0x28, 0x70, 0x2c, 0x38, 0x27, 0xce, 0x20, 0x88, 0x25, + 0x9d, 0x2d, 0x3b, 0x3a, 0x35, 0x46, 0xa8, 0x45, 0xf9, 0x41, 0xc3, 0x3d, + 0x0e, 0x3d, 0x2d, 0x40, 0x19, 0x3d, 0xc6, 0x33, 0x10, 0x2e, 0x67, 0x2a, + 0x58, 0x25, 0x79, 0x22, 0x39, 0x1a, 0x04, 0x10, 0x8a, 0x06, 0xea, 0xfb, + 0x42, 0xf8, 0xde, 0xf4, 0x8f, 0xea, 0xb1, 0xe2, 0xdb, 0xe0, 0x1b, 0xe2, + 0xce, 0xe9, 0x81, 0xec, 0xa3, 0xe4, 0x97, 0xde, 0x5b, 0xdb, 0x54, 0xda, + 0x0d, 0xda, 0xc5, 0xda, 0x5a, 0xde, 0x73, 0xe1, 0x6f, 0xe0, 0xaa, 0xe0, + 0xdd, 0xe4, 0xb5, 0xe8, 0x3d, 0xef, 0x89, 0xf4, 0xe2, 0xfa, 0xb9, 0xff, + 0x45, 0xfd, 0x26, 0xf7, 0xff, 0xef, 0xe5, 0xf1, 0x2a, 0xf3, 0x2a, 0xf1, + 0xde, 0xf1, 0xfe, 0xec, 0x3d, 0xed, 0x97, 0xf2, 0xe8, 0xf6, 0x95, 0xfe, + 0xd9, 0x00, 0x6b, 0x05, 0xc1, 0x11, 0x7d, 0x17, 0x5b, 0x1f, 0x66, 0x29, + 0x82, 0x2d, 0xf8, 0x32, 0xd8, 0x33, 0xe3, 0x37, 0xbe, 0x48, 0x5a, 0x53, + 0x70, 0x55, 0xff, 0x50, 0xb8, 0x48, 0x3e, 0x4c, 0x32, 0x50, 0xa5, 0x50, + 0xb8, 0x50, 0x91, 0x48, 0x60, 0x3d, 0x0d, 0x36, 0x10, 0x31, 0x31, 0x2a, + 0x6c, 0x25, 0x6a, 0x1c, 0x56, 0x11, 0xcd, 0x08, 0x9d, 0xff, 0x03, 0xfc, + 0x25, 0xf5, 0x17, 0xef, 0x30, 0xf2, 0x8f, 0xf4, 0x3c, 0xf4, 0xdc, 0xfb, + 0x46, 0x05, 0x79, 0x07, 0xec, 0x08, 0x74, 0x08, 0x26, 0x09, 0x3d, 0x0a, + 0x3d, 0x08, 0x96, 0x06, 0xc3, 0x06, 0x97, 0x01, 0x9d, 0xfe, 0x07, 0x01, + 0x62, 0xfe, 0x61, 0xfb, 0xaa, 0xf4, 0x8d, 0xf6, 0x48, 0xf9, 0x36, 0xf5, + 0xdb, 0xf5, 0x55, 0xf1, 0x1f, 0xf5, 0x0f, 0xfc, 0x61, 0xfd, 0x3e, 0xfc, + 0x1c, 0xf8, 0x46, 0xf8, 0x1f, 0xef, 0xe6, 0xe2, 0x76, 0xe1, 0x96, 0xdc, + 0xba, 0xde, 0xc2, 0xe8, 0x22, 0xe6, 0xe7, 0xdf, 0xc4, 0xdc, 0x12, 0xe2, + 0xbe, 0xf4, 0xc3, 0x0f, 0x16, 0x1d, 0x58, 0x15, 0xc6, 0x07, 0x6f, 0xfd, + 0xcb, 0x06, 0x5c, 0x12, 0x57, 0x1a, 0x26, 0x1b, 0x22, 0x10, 0xfb, 0x07, + 0x67, 0x07, 0xa0, 0x16, 0x36, 0x23, 0xf8, 0x27, 0x77, 0x21, 0x16, 0x19, + 0x18, 0x1a, 0x6c, 0x1d, 0xb9, 0x24, 0xe6, 0x21, 0xb8, 0x20, 0x89, 0x20, + 0x53, 0x1e, 0xb4, 0x20, 0x4d, 0x1e, 0x00, 0x1a, 0x6a, 0x13, 0x86, 0x11, + 0x92, 0x13, 0xbd, 0x12, 0xfc, 0x10, 0x35, 0x0e, 0x62, 0x0a, 0x1b, 0x08, + 0xb5, 0x06, 0x7a, 0x03, 0x16, 0xfd, 0x6a, 0xf6, 0x27, 0xf3, 0xb1, 0xf1, + 0x3c, 0xf2, 0x65, 0xee, 0x36, 0xe9, 0x17, 0xe6, 0x04, 0xe2, 0x52, 0xe2, + 0x0f, 0xe6, 0x93, 0xe5, 0xbc, 0xdf, 0x8f, 0xdd, 0x3a, 0xde, 0x69, 0xde, + 0xa2, 0xdf, 0x0e, 0xe1, 0x05, 0xe4, 0x20, 0xe4, 0x70, 0xe3, 0x74, 0xe4, + 0x08, 0xe6, 0x9f, 0xe7, 0x1a, 0xe2, 0xf6, 0xdd, 0xc3, 0xe0, 0x08, 0xe8, + 0xb5, 0xf1, 0x20, 0xf7, 0xf9, 0xf7, 0x90, 0xf3, 0x29, 0xf4, 0x67, 0xf9, + 0x6c, 0xfb, 0xc6, 0xfc, 0x18, 0xfe, 0xdc, 0x05, 0xf2, 0x0b, 0xd4, 0x0b, + 0x0d, 0x0a, 0x6e, 0x07, 0x55, 0x08, 0xcf, 0x0b, 0xfa, 0x13, 0x3b, 0x1d, + 0xca, 0x20, 0x8f, 0x1b, 0x15, 0x15, 0x18, 0x15, 0x1f, 0x15, 0x4e, 0x17, + 0x1d, 0x1a, 0x58, 0x19, 0x00, 0x15, 0x18, 0x0c, 0xd4, 0x08, 0x2c, 0x0c, + 0x2e, 0x0e, 0x7b, 0x08, 0xf6, 0xfd, 0xbf, 0xf5, 0x21, 0xf0, 0x40, 0xee, + 0x57, 0xea, 0x87, 0xe5, 0xa5, 0xe6, 0x31, 0xe7, 0xd5, 0xe7, 0x61, 0xed, + 0xbd, 0xeb, 0xae, 0xe6, 0x99, 0xe3, 0xe4, 0xdf, 0x98, 0xe4, 0xeb, 0xe4, + 0x87, 0xe0, 0xd8, 0xe5, 0xf3, 0xea, 0x53, 0xed, 0x79, 0xef, 0x31, 0xeb, + 0x8f, 0xea, 0x9e, 0xee, 0x1d, 0xec, 0x59, 0xf1, 0x31, 0xf6, 0xe1, 0xf3, + 0x59, 0xf2, 0xb7, 0xee, 0x63, 0xf1, 0xc0, 0xf3, 0x9d, 0xf6, 0x8f, 0xfa, + 0x2f, 0xfd, 0xfb, 0x02, 0xc4, 0x03, 0xdf, 0xfe, 0x06, 0xf4, 0x58, 0xe8, + 0xeb, 0xde, 0x28, 0xd7, 0x81, 0xd7, 0xde, 0xda, 0x41, 0xd7, 0xbe, 0xcc, + 0x81, 0xc1, 0xeb, 0xbf, 0xae, 0xcc, 0xed, 0xd9, 0x23, 0xdf, 0x10, 0xdc, + 0xa5, 0xd2, 0xfb, 0xcf, 0x78, 0xdc, 0x58, 0xed, 0x83, 0xfa, 0xcc, 0xfd, + 0x6f, 0xf5, 0xcb, 0xf6, 0x8d, 0xfe, 0xbf, 0x05, 0xe5, 0x0d, 0x80, 0x0e, + 0xa1, 0x10, 0xbd, 0x12, 0xc4, 0x12, 0x10, 0x13, 0x15, 0x14, 0x1a, 0x14, + 0xd9, 0x0e, 0xd8, 0x0b, 0xb0, 0x05, 0x93, 0xfc, 0xa6, 0xf3, 0xc2, 0xe9, + 0xcf, 0xe6, 0xcc, 0xe8, 0x07, 0xe9, 0xd6, 0xe4, 0xbc, 0xe1, 0xd6, 0xe1, + 0x1a, 0xe5, 0xea, 0xe9, 0xdc, 0xe9, 0xdd, 0xe7, 0x07, 0xe3, 0xe2, 0xe2, + 0xbd, 0xee, 0x0c, 0xfa, 0xd4, 0x01, 0x1f, 0x05, 0x54, 0x02, 0x33, 0xff, + 0xec, 0xfd, 0x3e, 0xfe, 0xfd, 0xfd, 0xf2, 0xfb, 0x1b, 0xf9, 0xac, 0xfa, + 0x2c, 0xfe, 0x3e, 0xfe, 0xa8, 0xfc, 0xad, 0xf7, 0x76, 0xf6, 0x49, 0xf8, + 0xb8, 0xf5, 0x75, 0xf5, 0x7c, 0xf3, 0x65, 0xed, 0xb3, 0xe6, 0x96, 0xe1, + 0x6c, 0xe1, 0x0e, 0xe3, 0x1f, 0xe5, 0xf8, 0xe5, 0x8c, 0xe7, 0xfb, 0xe7, + 0xbe, 0xe7, 0xab, 0xea, 0x71, 0xf1, 0xdc, 0xfa, 0x3e, 0x02, 0x88, 0x0a, + 0x77, 0x0e, 0x4e, 0x0d, 0xba, 0x07, 0xc4, 0x03, 0x03, 0x07, 0x58, 0x02, + 0xce, 0xff, 0x62, 0x03, 0x12, 0x05, 0x18, 0x05, 0x4c, 0x01, 0x51, 0x02, + 0x63, 0x00, 0x13, 0xf8, 0x41, 0xf3, 0xd4, 0xf2, 0xd2, 0xf2, 0xf4, 0xea, + 0xfa, 0xe2, 0xf6, 0xe2, 0x38, 0xe6, 0x6f, 0xea, 0x06, 0xe9, 0x30, 0xe8, + 0x8c, 0xeb, 0x3c, 0xe9, 0x4f, 0xe7, 0xa0, 0xe6, 0x1a, 0xe6, 0xe6, 0xe9, + 0xab, 0xf0, 0x2a, 0xf7, 0xcc, 0xf7, 0xa0, 0xf5, 0xfa, 0xf4, 0x27, 0xf6, + 0x9a, 0xf8, 0x2f, 0xf9, 0xbb, 0xf6, 0xe3, 0xf3, 0xd8, 0xf0, 0x15, 0xef, + 0xa6, 0xf3, 0x6e, 0xf8, 0x84, 0xf7, 0x6e, 0xf8, 0x42, 0xff, 0xd2, 0xfe, + 0x65, 0xf8, 0xc4, 0xfc, 0x62, 0x05, 0xfc, 0x04, 0xcc, 0xff, 0xa4, 0x03, + 0x9e, 0x0c, 0x43, 0x11, 0x37, 0x14, 0x6e, 0x18, 0xd4, 0x1d, 0x7b, 0x1d, + 0x76, 0x1a, 0x90, 0x15, 0xf7, 0x0d, 0x08, 0x08, 0x5a, 0xfb, 0x95, 0xf3, + 0x9c, 0xf2, 0x58, 0xe6, 0x8d, 0xd6, 0x36, 0xca, 0xb7, 0xc9, 0xbe, 0xd5, + 0xbb, 0xdf, 0x27, 0xe2, 0x88, 0xdc, 0xfa, 0xd3, 0x9a, 0xcf, 0xff, 0xd7, + 0x20, 0xe9, 0x73, 0xf3, 0x54, 0xf3, 0x24, 0xed, 0x11, 0xe8, 0xda, 0xeb, + 0xac, 0xf9, 0x70, 0x08, 0x24, 0x0e, 0x05, 0x09, 0xdd, 0x01, 0x91, 0x01, + 0x08, 0x0a, 0xf3, 0x11, 0x6f, 0x0d, 0x97, 0x05, 0x2c, 0x00, 0x53, 0xfc, + 0xc4, 0xfa, 0xc2, 0xf5, 0xad, 0xef, 0x26, 0xea, 0x6b, 0xe8, 0x19, 0xed, + 0x00, 0xf0, 0xe1, 0xf3, 0x6b, 0xfa, 0xb2, 0xfc, 0xde, 0xfb, 0x5d, 0xf9, + 0x9f, 0xfa, 0xba, 0x02, 0xfe, 0x0d, 0xbc, 0x17, 0xe4, 0x1c, 0x21, 0x21, + 0x3a, 0x24, 0x57, 0x26, 0xcc, 0x2c, 0xf8, 0x33, 0x27, 0x37, 0x91, 0x36, + 0xa0, 0x30, 0x29, 0x2b, 0x3c, 0x2a, 0x1f, 0x28, 0x7f, 0x25, 0x91, 0x23, + 0x83, 0x1f, 0x26, 0x1b, 0x4b, 0x19, 0xb6, 0x15, 0xa8, 0x12, 0x48, 0x13, + 0x4f, 0x11, 0x52, 0x0b, 0x1b, 0x05, 0x77, 0x02, 0x5b, 0x04, 0x5c, 0x06, + 0x9c, 0x05, 0x16, 0x06, 0xab, 0x09, 0xfd, 0x0b, 0xc3, 0x0a, 0x3c, 0x0b, + 0xc9, 0x11, 0xb7, 0x1a, 0xf4, 0x21, 0x15, 0x24, 0x5a, 0x21, 0x53, 0x1d, + 0x6e, 0x1a, 0x57, 0x17, 0x30, 0x15, 0x6f, 0x17, 0x01, 0x16, 0xa6, 0x0f, + 0xc4, 0x0c, 0x08, 0x0c, 0xec, 0x09, 0x1e, 0x06, 0xbc, 0x03, 0x9f, 0x05, + 0x84, 0x08, 0x47, 0x08, 0xd4, 0x03, 0xb9, 0xfe, 0xe0, 0xfe, 0x01, 0x07, + 0x8c, 0x0f, 0x9b, 0x14, 0x1d, 0x1b, 0xb6, 0x20, 0xd0, 0x21, 0x1a, 0x1c, + 0xf3, 0x18, 0x5b, 0x1e, 0xe0, 0x22, 0x17, 0x26, 0xca, 0x2b, 0x48, 0x2e, + 0x38, 0x2b, 0x7c, 0x2a, 0xca, 0x29, 0x9b, 0x28, 0xa7, 0x2a, 0x9d, 0x29, + 0xb5, 0x25, 0x28, 0x21, 0xd7, 0x1f, 0x33, 0x21, 0xb8, 0x1f, 0x1e, 0x1e, + 0x3a, 0x1d, 0xa5, 0x1c, 0x27, 0x1e, 0xbf, 0x1f, 0xb5, 0x1f, 0x99, 0x1e, + 0x75, 0x1f, 0xa6, 0x23, 0x7d, 0x29, 0x82, 0x2d, 0xc4, 0x32, 0x08, 0x3b, + 0x9f, 0x40, 0xa8, 0x46, 0x14, 0x48, 0xc6, 0x46, 0x99, 0x44, 0xcd, 0x38, + 0x13, 0x2c, 0xef, 0x1e, 0x02, 0x15, 0x97, 0x0f, 0x56, 0x06, 0xb0, 0xf6, + 0x8f, 0xe2, 0xf0, 0xd6, 0x93, 0xda, 0x3a, 0xe8, 0xab, 0xf3, 0x5f, 0xf5, + 0x6a, 0xe9, 0x03, 0xda, 0x37, 0xd7, 0x07, 0xe1, 0x75, 0xf0, 0x5c, 0xf6, + 0x72, 0xeb, 0xdf, 0xdc, 0x29, 0xd9, 0x6f, 0xe0, 0x78, 0xf1, 0x9a, 0x02, + 0x22, 0x05, 0x52, 0xfb, 0x7c, 0xf3, 0x84, 0xf6, 0xe6, 0xfd, 0xb5, 0x05, + 0x1b, 0x06, 0xfa, 0x00, 0x34, 0xff, 0xc6, 0xfc, 0x9c, 0xfe, 0x56, 0x00, + 0x1c, 0xfc, 0xaf, 0xf4, 0x7b, 0xf0, 0x58, 0xf4, 0x12, 0xf9, 0x37, 0x01, + 0x6a, 0x07, 0xf9, 0x05, 0xd6, 0x06, 0x25, 0x09, 0x12, 0x0a, 0xe0, 0x0f, + 0x6d, 0x1b, 0xf1, 0x20, 0x7d, 0x22, 0x2c, 0x24, 0x8e, 0x27, 0xfa, 0x2f, + 0xe7, 0x34, 0x3d, 0x35, 0xf9, 0x2e, 0x03, 0x29, 0xc0, 0x25, 0x29, 0x23, + 0x63, 0x23, 0xff, 0x1e, 0x05, 0x1a, 0x99, 0x15, 0xed, 0x13, 0x04, 0x13, + 0x87, 0x0e, 0x85, 0x0a, 0x64, 0x07, 0xe1, 0x04, 0x67, 0xfe, 0x27, 0xf7, + 0x6d, 0xf1, 0x79, 0xed, 0x03, 0xea, 0xcb, 0xe6, 0x83, 0xe8, 0x62, 0xeb, + 0x86, 0xed, 0xfe, 0xee, 0xe7, 0xec, 0xbf, 0xea, 0xbc, 0xed, 0xea, 0xf1, + 0xb0, 0xf5, 0x71, 0xf7, 0x05, 0xf1, 0x2f, 0xe9, 0x52, 0xe6, 0xad, 0xe4, + 0x44, 0xe4, 0x1e, 0xe3, 0x48, 0xe1, 0xc2, 0xe0, 0x0c, 0xdf, 0x16, 0xde, + 0xc9, 0xdd, 0x1b, 0xdf, 0x4d, 0xe2, 0x9e, 0xe5, 0x34, 0xe8, 0x0f, 0xea, + 0x49, 0xed, 0xaa, 0xef, 0x91, 0xf3, 0x89, 0xf7, 0x87, 0xfa, 0xb4, 0xff, + 0x72, 0x05, 0x68, 0x0c, 0xba, 0x12, 0xe2, 0x13, 0xdb, 0x13, 0xde, 0x18, + 0xd1, 0x1d, 0xd0, 0x22, 0x23, 0x29, 0xf4, 0x28, 0xef, 0x26, 0xe6, 0x25, + 0xfe, 0x24, 0x24, 0x27, 0xa3, 0x27, 0x32, 0x25, 0x54, 0x25, 0xe8, 0x27, + 0x13, 0x26, 0x2e, 0x24, 0x25, 0x25, 0xdb, 0x24, 0x25, 0x26, 0xdc, 0x23, + 0x0d, 0x23, 0x36, 0x28, 0x52, 0x2d, 0x87, 0x31, 0xac, 0x30, 0x38, 0x2e, + 0x29, 0x31, 0xe1, 0x36, 0x86, 0x39, 0x3d, 0x3d, 0x46, 0x41, 0x65, 0x42, + 0x2f, 0x45, 0x23, 0x45, 0xd5, 0x42, 0xe4, 0x3d, 0x0c, 0x34, 0xfe, 0x2a, + 0x77, 0x20, 0xd4, 0x16, 0xa8, 0x0e, 0x5e, 0x01, 0xe5, 0xf3, 0x2b, 0xe7, + 0x0f, 0xd9, 0x59, 0xd1, 0xef, 0xd6, 0xe1, 0xdc, 0x5e, 0xdb, 0x87, 0xd7, + 0xc6, 0xcd, 0x95, 0xc8, 0x16, 0xcd, 0xa7, 0xd9, 0x7a, 0xe8, 0xa5, 0xec, + 0xcd, 0xe5, 0xca, 0xdf, 0xd2, 0xe2, 0x66, 0xeb, 0x9e, 0xfc, 0x79, 0x07, + 0x46, 0x03, 0x6e, 0xfd, 0x37, 0xfc, 0xd7, 0x03, 0x3f, 0x0c, 0xe8, 0x0e, + 0xcb, 0x08, 0x84, 0x01, 0x83, 0xff, 0xea, 0xfd, 0x0c, 0xfe, 0x89, 0xfb, + 0xbd, 0xf5, 0xee, 0xee, 0xdb, 0xeb, 0xc3, 0xf0, 0x7e, 0xf5, 0xee, 0xf8, + 0xfa, 0xfb, 0xe6, 0xfa, 0x6d, 0xfa, 0xe6, 0x00, 0x27, 0x0b, 0x1b, 0x13, + 0x8d, 0x19, 0xef, 0x1b, 0x98, 0x1c, 0x2a, 0x1e, 0x22, 0x23, 0xd7, 0x2b, + 0xda, 0x2d, 0xc1, 0x2d, 0xdf, 0x2a, 0x95, 0x27, 0xbb, 0x26, 0x1f, 0x23, + 0x74, 0x1d, 0x23, 0x14, 0x43, 0x0e, 0x08, 0x08, 0x4c, 0xfe, 0xa2, 0xf3, + 0x62, 0xec, 0x79, 0xe7, 0x4a, 0xe0, 0x31, 0xda, 0x13, 0xd3, 0x19, 0xd2, + 0x32, 0xd3, 0xdb, 0xcf, 0x9f, 0xca, 0x18, 0xc8, 0x78, 0xcb, 0xd1, 0xd0, + 0x60, 0xd5, 0x03, 0xd3, 0x7e, 0xce, 0x55, 0xcb, 0x3c, 0xcc, 0x58, 0xd1, + 0xe3, 0xd4, 0xbb, 0xd4, 0x24, 0xd1, 0x44, 0xce, 0xaf, 0xcb, 0x96, 0xca, + 0x2e, 0xca, 0xc8, 0xcb, 0x3c, 0xcc, 0x7e, 0xc8, 0x75, 0xc5, 0x86, 0xc5, + 0x8c, 0xc6, 0x42, 0xc7, 0x88, 0xc8, 0xb5, 0xc6, 0x70, 0xc7, 0x42, 0xc9, + 0xbb, 0xc9, 0xdc, 0xcd, 0x3f, 0xd1, 0xa8, 0xd4, 0xcb, 0xdb, 0xc3, 0xe5, + 0x08, 0xee, 0x57, 0xf6, 0x1e, 0xfc, 0xc2, 0xff, 0xf6, 0x08, 0xfd, 0x11, + 0xfc, 0x19, 0x36, 0x21, 0x08, 0x23, 0x3a, 0x20, 0x5a, 0x1d, 0xd5, 0x1b, + 0x66, 0x1c, 0x0a, 0x1e, 0xb9, 0x1b, 0x8a, 0x16, 0x70, 0x14, 0x5d, 0x15, + 0x52, 0x15, 0x6a, 0x13, 0x3c, 0x0f, 0x97, 0x0c, 0xe1, 0x09, 0x85, 0x08, + 0xae, 0x0c, 0x48, 0x10, 0x15, 0x11, 0xdb, 0x10, 0xf4, 0x12, 0x81, 0x14, + 0xd1, 0x18, 0xc1, 0x1f, 0xf8, 0x23, 0x85, 0x25, 0x69, 0x27, 0xdc, 0x2d, + 0xa1, 0x31, 0x40, 0x36, 0x66, 0x39, 0xe1, 0x33, 0xa4, 0x24, 0x1e, 0x12, + 0x5f, 0x05, 0xe9, 0xfb, 0x9b, 0xf4, 0xcf, 0xe7, 0xfa, 0xd6, 0x7f, 0xc6, + 0xbc, 0xbd, 0xb0, 0xb9, 0x57, 0xb9, 0xf1, 0xc1, 0x78, 0xc6, 0x39, 0xc2, + 0xa8, 0xb4, 0x64, 0xad, 0x3c, 0xb0, 0x51, 0xbb, 0x67, 0xcb, 0xe4, 0xcd, + 0x58, 0xca, 0x95, 0xc8, 0xf3, 0xca, 0x27, 0xda, 0x69, 0xed, 0x89, 0xf5, + 0xc3, 0xf6, 0xc9, 0xf4, 0x9b, 0xf5, 0x86, 0xfc, 0x02, 0x04, 0x69, 0x08, + 0xe3, 0x07, 0xc6, 0x07, 0x95, 0x09, 0x4f, 0x08, 0x10, 0x07, 0xd2, 0x0a, + 0x02, 0x0b, 0xaf, 0x0a, 0x53, 0x0a, 0x15, 0x0d, 0x6f, 0x12, 0xfc, 0x16, + 0xd7, 0x18, 0x96, 0x10, 0x00, 0x09, 0x72, 0x08, 0x28, 0x15, 0x4f, 0x17, + 0x9e, 0x14, 0x95, 0x15, 0x99, 0x17, 0x44, 0x23, 0x21, 0x25, 0x00, 0x27, + 0x9d, 0x20, 0xb7, 0x20, 0xe7, 0x20, 0x63, 0x1b, 0x6a, 0x19, 0xfa, 0x15, + 0xee, 0x19, 0x28, 0x0c, 0xf3, 0x05, 0x36, 0x01, 0xe2, 0xfc, 0xe3, 0xfc, + 0x89, 0xf6, 0x22, 0xf1, 0xf3, 0xe2, 0xf9, 0xe3, 0xb2, 0xe3, 0x18, 0xe5, + 0xfe, 0xe4, 0x2b, 0xdb, 0x0d, 0xd6, 0x94, 0xcf, 0x83, 0xd0, 0x9c, 0xce, + 0xed, 0xcd, 0xa6, 0xcd, 0xe1, 0xc8, 0x60, 0xc5, 0x2a, 0xc1, 0x25, 0xc4, + 0x4e, 0xcb, 0xc6, 0xcb, 0xea, 0xc9, 0x32, 0xc7, 0xd9, 0xc6, 0x67, 0xc9, + 0x83, 0xcb, 0x91, 0xd0, 0x41, 0xd2, 0xb3, 0xd2, 0xd2, 0xcd, 0x6f, 0xce, + 0xa2, 0xd3, 0x57, 0xd5, 0xb8, 0xd5, 0xe3, 0xd3, 0xb7, 0xd8, 0xa1, 0xd6, + 0xd9, 0xd7, 0x8e, 0xda, 0x79, 0xdc, 0x8a, 0xe3, 0xed, 0xe6, 0x18, 0xec, + 0x4e, 0xf0, 0x8d, 0xf7, 0xad, 0xfb, 0xd1, 0xfe, 0x1c, 0xfe, 0x68, 0xfe, + 0x85, 0x06, 0xcc, 0x07, 0x5f, 0x08, 0xd4, 0x08, 0xed, 0x0a, 0xc1, 0x0a, + 0x25, 0x09, 0xdd, 0x0b, 0xd3, 0x0f, 0x21, 0x14, 0xe3, 0x12, 0x27, 0x10, + 0x92, 0x0d, 0xcf, 0x12, 0x7a, 0x1e, 0xef, 0x1e, 0x02, 0x16, 0xcc, 0x0f, + 0x59, 0x12, 0x02, 0x19, 0x1a, 0x1f, 0xde, 0x20, 0xd1, 0x1c, 0xac, 0x17, + 0x97, 0x1a, 0x52, 0x24, 0xcd, 0x2b, 0x59, 0x2c, 0xa5, 0x23, 0x18, 0x1d, + 0x20, 0x1b, 0x12, 0x1f, 0x0a, 0x25, 0x32, 0x23, 0x1f, 0x1f, 0xf3, 0x18, + 0x2f, 0x12, 0xdf, 0x06, 0x16, 0xfc, 0x12, 0xf7, 0x5c, 0xf3, 0x9f, 0xeb, + 0x79, 0xde, 0x22, 0xd5, 0x41, 0xcb, 0x9d, 0xc4, 0x2b, 0xc5, 0x21, 0xcb, + 0x40, 0xd2, 0x77, 0xd2, 0x65, 0xcd, 0xbb, 0xcb, 0x1d, 0xd1, 0xdd, 0xdd, + 0x64, 0xf2, 0x63, 0xfb, 0x94, 0xfa, 0x48, 0xfa, 0x4f, 0xf8, 0x83, 0xfb, + 0x83, 0x08, 0x2b, 0x1a, 0x5f, 0x1a, 0x93, 0x0b, 0x97, 0x04, 0x7b, 0x08, + 0x1d, 0x14, 0x4f, 0x1b, 0x26, 0x1a, 0xfb, 0x1b, 0x08, 0x1c, 0xf4, 0x1c, + 0xfc, 0x1b, 0x45, 0x1b, 0x31, 0x22, 0x16, 0x21, 0xe9, 0x20, 0xbd, 0x20, + 0xbd, 0x22, 0xf8, 0x2d, 0xb8, 0x38, 0x5e, 0x3d, 0x5c, 0x3b, 0x97, 0x3f, + 0x29, 0x3f, 0x07, 0x43, 0xf0, 0x4e, 0x9f, 0x56, 0x2d, 0x5a, 0x07, 0x50, + 0xa7, 0x4d, 0x2f, 0x51, 0x90, 0x50, 0x4d, 0x51, 0x1b, 0x4d, 0x3d, 0x46, + 0x99, 0x40, 0xf9, 0x3c, 0x4c, 0x34, 0x72, 0x2e, 0x74, 0x27, 0x87, 0x1d, + 0xd2, 0x17, 0x57, 0x11, 0x13, 0x0f, 0xca, 0x0b, 0x33, 0x05, 0x34, 0xfe, + 0x90, 0xfd, 0xc8, 0xfe, 0xe5, 0x01, 0x76, 0x04, 0x24, 0x01, 0xf4, 0x00, + 0x34, 0xfa, 0x0d, 0xfb, 0xa1, 0xfe, 0xd3, 0xff, 0x01, 0x00, 0x67, 0xfc, + 0x03, 0x01, 0x16, 0xff, 0x1c, 0x02, 0x78, 0x04, 0xf7, 0x00, 0x9d, 0xfb, + 0x22, 0xf6, 0xf0, 0xf3, 0x69, 0xef, 0x88, 0xf4, 0x5e, 0xf3, 0x5c, 0xf3, + 0x04, 0xf2, 0x6c, 0xef, 0x7b, 0xf3, 0xa5, 0xf3, 0xa7, 0xf5, 0x62, 0xf3, + 0xf7, 0xf5, 0xff, 0xf5, 0x11, 0xf8, 0x28, 0xfc, 0xdb, 0xfb, 0x26, 0x00, + 0xd8, 0x04, 0x75, 0x0f, 0xc9, 0x12, 0xbb, 0x17, 0x26, 0x1c, 0x86, 0x19, + 0x48, 0x19, 0xe2, 0x17, 0x8d, 0x1d, 0x79, 0x24, 0x4d, 0x29, 0x19, 0x28, + 0xf3, 0x24, 0xb2, 0x23, 0xca, 0x21, 0xa3, 0x23, 0x6f, 0x22, 0xbd, 0x1f, + 0xa2, 0x1d, 0xf0, 0x1c, 0xf5, 0x1d, 0x6d, 0x20, 0xb4, 0x22, 0x20, 0x22, + 0x4c, 0x20, 0x8e, 0x1e, 0x22, 0x22, 0xf5, 0x25, 0x69, 0x26, 0xee, 0x24, + 0x9c, 0x1f, 0x59, 0x1f, 0x13, 0x23, 0x46, 0x21, 0xc6, 0x1c, 0x34, 0x17, + 0x25, 0x14, 0x32, 0x14, 0x24, 0x14, 0x54, 0x15, 0xc4, 0x14, 0x38, 0x12, + 0x4f, 0x10, 0xbf, 0x10, 0x3b, 0x13, 0xd8, 0x12, 0x42, 0x0f, 0x0a, 0x09, + 0xe2, 0xfe, 0x6f, 0xf8, 0x8a, 0xf5, 0xec, 0xef, 0x93, 0xeb, 0xcf, 0xe4, + 0xde, 0xdc, 0x68, 0xd7, 0xce, 0xd4, 0xbe, 0xda, 0xfe, 0xde, 0x24, 0xde, + 0xb1, 0xdb, 0xc2, 0xd6, 0x81, 0xdb, 0xec, 0xe4, 0xc5, 0xee, 0x80, 0xf7, + 0x16, 0xf8, 0x47, 0xf8, 0x4d, 0xf6, 0xd9, 0xfa, 0x46, 0x02, 0xe3, 0x08, + 0xc1, 0x0d, 0x9d, 0x0a, 0x65, 0x0d, 0xb7, 0x05, 0xfd, 0xfe, 0x40, 0x03, + 0x42, 0x04, 0xe2, 0x0a, 0x6e, 0x0a, 0x65, 0x05, 0x99, 0x06, 0x55, 0x0a, + 0x3a, 0x0b, 0x58, 0x07, 0x9a, 0x01, 0x99, 0x06, 0x12, 0x0d, 0xd3, 0x08, + 0x1f, 0x03, 0xe9, 0xf7, 0x05, 0xfc, 0xa6, 0x09, 0xe8, 0x0a, 0xce, 0x09, + 0xc8, 0x0f, 0x0e, 0x19, 0x99, 0x1b, 0x75, 0x24, 0xd5, 0x2f, 0xfc, 0x37, + 0xc4, 0x3b, 0x3b, 0x3c, 0xb0, 0x3e, 0x68, 0x3a, 0x73, 0x32, 0x59, 0x27, + 0xb8, 0x21, 0x7c, 0x1a, 0xd1, 0x0c, 0x9a, 0x03, 0xbf, 0xfb, 0x46, 0xfa, + 0x0f, 0xf3, 0x32, 0xec, 0x7b, 0xee, 0xe6, 0xf0, 0x17, 0xf0, 0x42, 0xef, + 0x50, 0xf4, 0xa7, 0xef, 0x6e, 0xf2, 0xed, 0xf3, 0x56, 0xed, 0xa4, 0xee, + 0xd0, 0xea, 0x2f, 0xef, 0xae, 0xee, 0xd5, 0xef, 0xb8, 0xf2, 0x80, 0xf4, + 0x74, 0x00, 0x70, 0x07, 0xca, 0x10, 0x06, 0x12, 0x7a, 0x14, 0x4d, 0x12, + 0xc4, 0x0b, 0x08, 0x0c, 0x17, 0x08, 0x28, 0x07, 0x1b, 0xfc, 0x70, 0xf1, + 0x1b, 0xeb, 0x98, 0xeb, 0x2b, 0xef, 0xef, 0xef, 0xe2, 0xf3, 0x22, 0xee, + 0x96, 0xec, 0x2c, 0xf0, 0x14, 0xf9, 0x0a, 0x02, 0x10, 0x06, 0xc9, 0x07, + 0xd6, 0x06, 0x1f, 0x0e, 0x98, 0x12, 0x68, 0x18, 0xb2, 0x18, 0x2b, 0x18, + 0x58, 0x1d, 0xad, 0x1c, 0xf4, 0x24, 0xb9, 0x28, 0x13, 0x2a, 0x1c, 0x28, + 0xdb, 0x21, 0xc5, 0x24, 0x3f, 0x25, 0x11, 0x28, 0xf5, 0x24, 0x7e, 0x23, + 0x03, 0x24, 0x9a, 0x1a, 0x43, 0x17, 0x7b, 0x15, 0x18, 0x12, 0x28, 0x0c, + 0x23, 0x04, 0x1f, 0xff, 0x69, 0xfc, 0xa3, 0xfc, 0xae, 0xff, 0x5e, 0xff, + 0xd5, 0xff, 0x5c, 0x01, 0x62, 0xff, 0xdc, 0x02, 0x87, 0x05, 0xb8, 0x06, + 0xe1, 0x01, 0x7a, 0xfa, 0x73, 0xf9, 0xd4, 0xf4, 0x0c, 0xf0, 0x1e, 0xee, + 0x8c, 0xed, 0xca, 0xeb, 0x55, 0xea, 0x21, 0xea, 0x81, 0xed, 0xdb, 0xf2, + 0xe5, 0xf5, 0x9a, 0xf6, 0x4f, 0xf7, 0x49, 0xfb, 0xb0, 0xf7, 0x71, 0xf1, + 0x20, 0xec, 0x01, 0xe7, 0xb7, 0xe5, 0x25, 0xe3, 0xcf, 0xe0, 0x9d, 0xe1, + 0xf9, 0xe1, 0xba, 0xe2, 0xf0, 0xe4, 0x1a, 0xe4, 0x88, 0xea, 0x6d, 0xf6, + 0x14, 0xfe, 0x96, 0xfd, 0xd4, 0xfd, 0x70, 0x06, 0x2a, 0x0b, 0x14, 0x11, + 0x43, 0x14, 0xc0, 0x15, 0x98, 0x19, 0x83, 0x18, 0x51, 0x15, 0xc2, 0x0f, + 0xce, 0x0d, 0xbc, 0x0d, 0x81, 0x0b, 0xb2, 0x09, 0xc2, 0x05, 0xb8, 0x01, + 0x92, 0x02, 0xa5, 0x05, 0x6d, 0x07, 0xf5, 0x01, 0x38, 0xf8, 0x9c, 0xf7, + 0x02, 0xf6, 0xdf, 0xf3, 0x44, 0xf2, 0x40, 0xe8, 0x41, 0xe4, 0xde, 0xe5, + 0x12, 0xe5, 0x26, 0xe1, 0xef, 0xdf, 0x60, 0xe0, 0x95, 0xe1, 0x28, 0xe6, + 0x51, 0xe3, 0x3f, 0xec, 0x26, 0xf9, 0xa8, 0xf8, 0xc3, 0xf8, 0x61, 0xf9, + 0x66, 0xfd, 0xee, 0xfe, 0x52, 0xfe, 0x16, 0xf9, 0x01, 0xec, 0x11, 0xe3, + 0x46, 0xe0, 0x56, 0xde, 0xae, 0xd7, 0x02, 0xcc, 0xe4, 0xc1, 0x88, 0xc0, + 0x81, 0xc1, 0x27, 0xc2, 0x21, 0xc3, 0x65, 0xc6, 0xf5, 0xc9, 0x60, 0xc9, + 0xe5, 0xc9, 0x50, 0xcc, 0x2e, 0xcf, 0x69, 0xd0, 0x19, 0xcf, 0xea, 0xca, + 0x97, 0xc9, 0xf0, 0xcd, 0x91, 0xd2, 0x21, 0xd7, 0xa0, 0xdc, 0x4d, 0xdc, + 0x45, 0xdf, 0xa6, 0xe9, 0x0f, 0xed, 0x3e, 0xee, 0x61, 0xef, 0xbe, 0xf3, + 0xda, 0xf5, 0xfe, 0xf5, 0x9b, 0xf6, 0xc5, 0xf5, 0xa0, 0xf3, 0xa7, 0xec, + 0x0d, 0xeb, 0x31, 0xeb, 0x1d, 0xf4, 0xb9, 0xfa, 0x83, 0xfb, 0xe4, 0xfe, + 0xb7, 0xff, 0x30, 0x08, 0x56, 0x10, 0x7b, 0x16, 0x5e, 0x16, 0x51, 0x17, + 0xce, 0x19, 0xfd, 0x1c, 0x6b, 0x24, 0x5b, 0x24, 0x2f, 0x25, 0xb6, 0x22, + 0xa1, 0x21, 0x09, 0x23, 0x44, 0x20, 0xfb, 0x1e, 0x2a, 0x1d, 0x63, 0x18, + 0x25, 0x14, 0x7c, 0x10, 0x56, 0x0b, 0x16, 0x08, 0xd2, 0x00, 0x8f, 0xf9, + 0x89, 0xf6, 0xaa, 0xf2, 0xe4, 0xee, 0xa4, 0xeb, 0x66, 0xe8, 0xb0, 0xe6, + 0x53, 0xe8, 0x1d, 0xe9, 0xe8, 0xe7, 0x1c, 0xe3, 0x7c, 0xdb, 0x51, 0xd8, + 0x63, 0xda, 0x18, 0xe0, 0x2c, 0xe4, 0xf4, 0xde, 0x26, 0xdc, 0xa1, 0xde, + 0x20, 0xe1, 0x14, 0xe6, 0x1e, 0xe7, 0xcb, 0xe0, 0x69, 0xda, 0x1a, 0xdc, + 0x77, 0xdf, 0x0e, 0xe4, 0x07, 0xe6, 0x90, 0xe1, 0x97, 0xe1, 0xfc, 0xe1, + 0x4f, 0xdf, 0xc1, 0xdf, 0xce, 0xde, 0x8c, 0xde, 0x20, 0xe4, 0xaa, 0xe0, + 0xbe, 0xdf, 0xfa, 0xe5, 0x6f, 0xea, 0x02, 0xf2, 0x89, 0xf6, 0xb6, 0xfd, + 0xbe, 0x04, 0x8d, 0x0a, 0xeb, 0x10, 0xf9, 0x16, 0x8e, 0x1b, 0x4e, 0x1f, + 0xec, 0x25, 0x28, 0x27, 0xbf, 0x27, 0x3c, 0x28, 0xb6, 0x26, 0xa6, 0x26, + 0xb8, 0x29, 0x4f, 0x27, 0xf8, 0x20, 0xed, 0x1a, 0xee, 0x14, 0xa3, 0x17, + 0xeb, 0x13, 0x7f, 0x0e, 0xbb, 0x09, 0xc1, 0x04, 0x8b, 0x06, 0x1d, 0x05, + 0x79, 0x06, 0x13, 0x07, 0x12, 0x06, 0x4c, 0x04, 0xff, 0xfc, 0x65, 0xfc, + 0x2d, 0x01, 0x5e, 0xfe, 0x8e, 0xfe, 0x69, 0xfb, 0x17, 0xf6, 0x2c, 0xfe, + 0xfd, 0xfd, 0x1f, 0xfd, 0x67, 0xfb, 0xe9, 0xf2, 0x67, 0xf4, 0x08, 0xf2, + 0xe1, 0xec, 0xcd, 0xeb, 0xaa, 0xe6, 0xf2, 0xe2, 0x09, 0xe4, 0x0e, 0xe0, + 0x53, 0xdc, 0xd0, 0xde, 0x3c, 0xe0, 0xed, 0xe2, 0xd8, 0xe2, 0xf9, 0xdd, + 0x90, 0xdf, 0xfa, 0xe4, 0x20, 0xe7, 0xbd, 0xe6, 0x0c, 0xde, 0xa2, 0xd8, + 0x22, 0xda, 0xdc, 0xd5, 0x45, 0xd5, 0xaf, 0xd6, 0x1b, 0xd5, 0x0d, 0xd3, + 0x45, 0xd0, 0x6f, 0xcf, 0xc3, 0xce, 0x74, 0xce, 0x94, 0xcf, 0x26, 0xd4, + 0xe1, 0xd7, 0xcf, 0xd8, 0x9b, 0xdd, 0x4f, 0xe1, 0x32, 0xe3, 0x0a, 0xe5, + 0xb6, 0xe8, 0x0e, 0xf1, 0xd5, 0xf6, 0x16, 0xf8, 0x30, 0xf6, 0x42, 0xfa, + 0x9d, 0x03, 0xe1, 0x07, 0x60, 0x0c, 0xe6, 0x11, 0x30, 0x17, 0x71, 0x1c, + 0xe3, 0x1c, 0x85, 0x1c, 0x93, 0x1e, 0x07, 0x1f, 0x14, 0x1e, 0x91, 0x1c, + 0xf3, 0x1a, 0x56, 0x1a, 0x64, 0x17, 0x95, 0x12, 0x7f, 0x12, 0x39, 0x14, + 0xa2, 0x14, 0x0f, 0x14, 0xa2, 0x0f, 0x34, 0x10, 0x23, 0x16, 0x1d, 0x1d, + 0xee, 0x21, 0x55, 0x21, 0xf6, 0x21, 0x49, 0x23, 0x0f, 0x26, 0x9a, 0x2b, + 0xad, 0x2e, 0x0d, 0x2b, 0xa1, 0x25, 0xe3, 0x21, 0x8f, 0x1f, 0xe2, 0x1e, + 0x7f, 0x1e, 0x42, 0x1b, 0x00, 0x13, 0x17, 0x0e, 0x79, 0x0e, 0x09, 0x12, + 0xbf, 0x12, 0x95, 0x10, 0xa5, 0x0c, 0x7c, 0x08, 0x4a, 0x0a, 0x29, 0x0c, + 0xb4, 0x0e, 0x5f, 0x0e, 0xfc, 0x0b, 0xcb, 0x09, 0xa1, 0x08, 0x66, 0x09, + 0x59, 0x0d, 0xac, 0x0f, 0x54, 0x0b, 0xe3, 0x0c, 0xb4, 0x0e, 0x88, 0x11, + 0xc2, 0x12, 0x88, 0x0f, 0xa1, 0x0f, 0x3e, 0x0e, 0xbc, 0x0f, 0x0e, 0x16, + 0x4f, 0x18, 0xde, 0x16, 0x79, 0x16, 0x71, 0x16, 0x2c, 0x17, 0xdb, 0x11, + 0xd6, 0x11, 0x06, 0x15, 0xa1, 0x18, 0xca, 0x1c, 0xed, 0x13, 0x2d, 0x13, + 0x72, 0x17, 0x57, 0x22, 0xb5, 0x30, 0x78, 0x2f, 0x6c, 0x30, 0x65, 0x34, + 0x76, 0x36, 0xfa, 0x3e, 0x56, 0x44, 0x9e, 0x44, 0xcf, 0x46, 0x4f, 0x40, + 0xb3, 0x3d, 0xc0, 0x3c, 0x96, 0x36, 0x31, 0x36, 0xaf, 0x31, 0xeb, 0x27, + 0xb9, 0x21, 0x79, 0x21, 0xb7, 0x26, 0xa1, 0x2d, 0xef, 0x29, 0x79, 0x24, + 0xee, 0x25, 0x2e, 0x24, 0x1b, 0x1e, 0xf9, 0x23, 0x86, 0x2c, 0x51, 0x29, + 0xaf, 0x24, 0x6f, 0x18, 0x31, 0x1b, 0x10, 0x28, 0xe9, 0x26, 0x9e, 0x1d, + 0xc0, 0x14, 0x9e, 0x19, 0x02, 0x1e, 0xdb, 0x1f, 0x18, 0x1b, 0xdf, 0x12, + 0xe3, 0x16, 0x2f, 0x15, 0xc8, 0x10, 0x4d, 0x10, 0x23, 0x0d, 0x05, 0x08, + 0x24, 0xf6, 0xb6, 0xed, 0x58, 0xf9, 0x80, 0xf7, 0x9c, 0xf6, 0xa0, 0xfa, + 0x75, 0xf6, 0xbd, 0xef, 0xcb, 0xda, 0x89, 0xd9, 0x92, 0xf3, 0x48, 0x06, + 0xff, 0x11, 0xee, 0x09, 0x09, 0xfe, 0x30, 0xfe, 0x06, 0x0e, 0x57, 0x1e, + 0x89, 0x19, 0x5f, 0x0f, 0xe1, 0x01, 0xb3, 0xfd, 0x2a, 0x03, 0xcf, 0x0f, + 0x68, 0x0d, 0x25, 0xf7, 0xe8, 0xe9, 0xd7, 0xeb, 0xf8, 0xf3, 0x33, 0xf1, + 0x61, 0xf5, 0x4d, 0xfc, 0x2a, 0xfa, 0x07, 0xe8, 0xcd, 0xdf, 0x59, 0xe3, + 0x77, 0xee, 0x7c, 0x05, 0x0d, 0x00, 0x01, 0xf9, 0xd5, 0xe8, 0x3a, 0xe6, + 0x7a, 0xf7, 0x1d, 0x01, 0xb0, 0x0d, 0xb2, 0x09, 0x77, 0x0d, 0xc3, 0x15, + 0x1b, 0x16, 0x6e, 0x03, 0x4a, 0xeb, 0x0b, 0xec, 0x11, 0x01, 0x72, 0x12, + 0xbb, 0x02, 0xb6, 0xe4, 0xbf, 0xe2, 0x62, 0xf4, 0xc1, 0xfb, 0xa5, 0xff, + 0xbc, 0xec, 0x34, 0xdf, 0xda, 0xe1, 0xc6, 0xe1, 0x39, 0xea, 0x7d, 0xdd, + 0x32, 0xd6, 0xec, 0xf0, 0x33, 0x0a, 0xb7, 0xfb, 0xa8, 0xdb, 0x99, 0xd4, + 0xef, 0xe3, 0xeb, 0xfa, 0xa6, 0x00, 0xd1, 0xef, 0x93, 0xf1, 0x01, 0x03, + 0xc8, 0x0c, 0xfd, 0xfd, 0x9b, 0xd2, 0x3c, 0xc7, 0xbe, 0xd5, 0x38, 0xee, + 0xcb, 0xfa, 0x58, 0xef, 0x0c, 0xe9, 0xc8, 0xdb, 0xe5, 0xde, 0x43, 0xec, + 0xe5, 0xef, 0x0c, 0xed, 0x7e, 0xf2, 0x7a, 0xf1, 0x03, 0xe8, 0x28, 0xe3, + 0x33, 0xd8, 0xb7, 0xcc, 0x6c, 0xae, 0xb4, 0x98, 0x0f, 0x94, 0xf6, 0xab, + 0xf9, 0xd0, 0xbf, 0x0d, 0x90, 0x67, 0xc5, 0x7c, 0x55, 0x7a, 0xb5, 0x6c, + 0xce, 0x2d, 0xa6, 0xe9, 0x1d, 0xc2, 0xa0, 0xb5, 0x09, 0xc4, 0xc2, 0xe8, + 0x99, 0x09, 0xfa, 0x1a, 0x7c, 0x11, 0xc3, 0x15, 0xff, 0x15, 0x15, 0x06, + 0x33, 0xf6, 0x07, 0xeb, 0x0e, 0xfe, 0xc0, 0x00, 0xf1, 0xf6, 0x26, 0xf8, + 0xc7, 0xfc, 0xb2, 0x03, 0x84, 0x07, 0x24, 0xfd, 0xcd, 0xf0, 0xfb, 0xf3, + 0x74, 0x02, 0xeb, 0x0a, 0x79, 0x00, 0x3e, 0x04, 0xf5, 0x06, 0xd6, 0x07, + 0xd2, 0x0a, 0xa9, 0xfe, 0x55, 0xf0, 0x09, 0xe9, 0x96, 0xeb, 0x7b, 0xf6, + 0x70, 0x07, 0x36, 0x0a, 0xac, 0x1a, 0x5b, 0x32, 0xd4, 0x3c, 0x9c, 0x40, + 0x1d, 0x39, 0x51, 0x33, 0x69, 0x32, 0x66, 0x3a, 0x2b, 0x41, 0x6e, 0x45, + 0x99, 0x3a, 0x96, 0x2d, 0x38, 0x22, 0x9a, 0x1f, 0x4c, 0x38, 0x67, 0x4d, + 0xa0, 0x5e, 0x69, 0x65, 0x7f, 0x5b, 0x91, 0x52, 0x56, 0x57, 0x4a, 0x58, + 0xdb, 0x59, 0x45, 0x5a, 0xde, 0x4a, 0x52, 0x39, 0x31, 0x25, 0xc4, 0x1e, + 0xd1, 0x20, 0x10, 0x24, 0xf3, 0x20, 0xfe, 0x1e, 0xbe, 0x26, 0x71, 0x25, + 0xe7, 0x1e, 0x4b, 0x20, 0x64, 0x36, 0xe8, 0x4c, 0xb2, 0x4b, 0x50, 0x3e, + 0xa9, 0x3b, 0xb0, 0x37, 0x5c, 0x35, 0x71, 0x3d, 0x75, 0x3d, 0x79, 0x37, + 0xd0, 0x2e, 0x35, 0x28, 0x10, 0x2c, 0x74, 0x3a, 0x83, 0x42, 0x5c, 0x40, + 0x8e, 0x37, 0x99, 0x2f, 0xcd, 0x33, 0x83, 0x3a, 0xf2, 0x32, 0x6b, 0x23, + 0x0c, 0x16, 0xd5, 0x0b, 0x08, 0x1a, 0xf4, 0x2e, 0x38, 0x37, 0x7e, 0x34, + 0xea, 0x31, 0x59, 0x3a, 0xeb, 0x42, 0xb2, 0x44, 0xbc, 0x3a, 0xba, 0x37, + 0x7d, 0x3c, 0x3e, 0x3b, 0xfb, 0x2d, 0x7f, 0x23, 0x40, 0x26, 0x99, 0x2c, + 0x95, 0x2f, 0x8a, 0x27, 0xc2, 0x26, 0x59, 0x25, 0xa3, 0x21, 0x2e, 0x23, + 0xb3, 0x20, 0xee, 0x1d, 0x6c, 0x1b, 0x7b, 0x1e, 0x04, 0x28, 0xa0, 0x26, + 0xce, 0x0e, 0x30, 0xf6, 0x20, 0xea, 0xac, 0xea, 0x5e, 0xe1, 0xd8, 0xc5, + 0xf1, 0xaf, 0x23, 0xad, 0x96, 0xbe, 0x6f, 0xc9, 0xea, 0xcc, 0xed, 0xd7, + 0x93, 0xe9, 0x85, 0xec, 0x5c, 0xe0, 0x18, 0xe0, 0xbc, 0xdf, 0x86, 0xd6, + 0x5e, 0xcc, 0x5c, 0xc4, 0xf5, 0xc2, 0xa0, 0xc7, 0x21, 0xc3, 0x43, 0xc0, + 0x4a, 0xc6, 0xe7, 0xcf, 0xb9, 0xd9, 0x86, 0xd9, 0x79, 0xdd, 0xe7, 0xe4, + 0xf6, 0xf1, 0x58, 0xf2, 0x08, 0xdd, 0x9c, 0xcd, 0x74, 0xca, 0xcf, 0xd3, + 0x11, 0xe1, 0x26, 0xe6, 0xa3, 0xd7, 0xcc, 0xcb, 0xd9, 0xcc, 0xab, 0xcb, + 0xc5, 0xc6, 0xf8, 0xbb, 0x36, 0xb4, 0x31, 0xba, 0x69, 0xcf, 0x64, 0xdf, + 0xcf, 0xd4, 0x20, 0xb8, 0x3f, 0xad, 0xad, 0xb6, 0x03, 0xc0, 0x5c, 0xb9, + 0xb5, 0xa5, 0x94, 0x9e, 0xde, 0x9e, 0xec, 0xa4, 0x97, 0xa9, 0x2d, 0xab, + 0x14, 0xb2, 0x68, 0xb8, 0x20, 0xbc, 0x55, 0xba, 0xd4, 0xb7, 0xa1, 0xba, + 0x6b, 0xbd, 0x88, 0xb4, 0xff, 0xa3, 0x6b, 0x96, 0x9c, 0x92, 0x79, 0x91, + 0x34, 0x91, 0xb3, 0x96, 0x35, 0xa3, 0x81, 0xb7, 0xe3, 0xba, 0x9b, 0xb5, + 0x48, 0xb3, 0xfd, 0xaf, 0x6a, 0xb7, 0x9c, 0xb6, 0xcf, 0xa9, 0x4d, 0xa3, + 0x19, 0xa4, 0xc2, 0xab, 0xfb, 0xb3, 0x6b, 0xbc, 0xde, 0xc5, 0x72, 0xc4, + 0x8e, 0xc4, 0xdf, 0xcb, 0x8d, 0xcb, 0xfe, 0xc6, 0x55, 0xb9, 0x18, 0xac, + 0xa0, 0xa6, 0xa8, 0x9d, 0xf8, 0x9a, 0x5f, 0x9a, 0x3c, 0xa3, 0x04, 0xac, + 0xbb, 0xa9, 0xb6, 0xab, 0x1d, 0xa6, 0x8a, 0xac, 0xe3, 0xac, 0x48, 0x9c, + 0x99, 0x9a, 0x0a, 0x9d, 0xf3, 0xad, 0xb4, 0xbf, 0xde, 0xc2, 0x23, 0xc6, + 0x7f, 0xc9, 0xf6, 0xd2, 0x53, 0xdd, 0x7d, 0xdd, 0x8d, 0xd3, 0xe4, 0xc3, + 0x84, 0xc8, 0xc5, 0xdd, 0x53, 0xe3, 0xab, 0xd9, 0xf7, 0xcc, 0xca, 0xdf, + 0x19, 0xff, 0x26, 0x06, 0xe9, 0x0d, 0xe4, 0x17, 0x5e, 0x22, 0x36, 0x33, + 0xca, 0x40, 0x07, 0x3a, 0x7d, 0x25, 0x6f, 0x1c, 0xe4, 0x22, 0xa3, 0x27, + 0x17, 0x1e, 0x84, 0x12, 0x54, 0x0e, 0xf0, 0x0c, 0x87, 0x0c, 0xff, 0x13, + 0x06, 0x21, 0x2b, 0x21, 0x92, 0x11, 0x35, 0x06, 0x40, 0x04, 0x3c, 0x0c, + 0x41, 0x0f, 0xc0, 0xfd, 0x48, 0xf1, 0x9e, 0xf2, 0x80, 0x00, 0x41, 0x08, + 0x25, 0xfd, 0xab, 0xf3, 0xd5, 0xec, 0x49, 0xf0, 0x63, 0xed, 0x9e, 0xe2, + 0x45, 0xe4, 0x3d, 0xe4, 0xc3, 0xf2, 0x64, 0xff, 0x6a, 0x05, 0x6a, 0x18, + 0x6f, 0x1e, 0x72, 0x20, 0xf7, 0x13, 0x58, 0x04, 0xfa, 0x0c, 0x72, 0x11, + 0x5e, 0x19, 0x51, 0x24, 0xd2, 0x23, 0xbf, 0x2e, 0x9e, 0x49, 0xf2, 0x5e, + 0xcb, 0x65, 0x17, 0x62, 0xc3, 0x66, 0x9d, 0x72, 0x14, 0x77, 0xe2, 0x76, + 0x4b, 0x71, 0x3b, 0x6b, 0x8f, 0x6a, 0x85, 0x6d, 0x26, 0x69, 0x31, 0x61, + 0x33, 0x5e, 0xe6, 0x62, 0xe4, 0x69, 0x8a, 0x67, 0xd8, 0x6a, 0x49, 0x71, + 0xc1, 0x70, 0x49, 0x6d, 0x7c, 0x61, 0xb5, 0x54, 0xd7, 0x49, 0x44, 0x40, + 0x22, 0x45, 0x0f, 0x48, 0xa7, 0x41, 0xd8, 0x3b, 0x0f, 0x37, 0x2a, 0x40, + 0x6b, 0x4a, 0x16, 0x46, 0x22, 0x3a, 0x0b, 0x34, 0xb3, 0x30, 0xe9, 0x2a, + 0xb4, 0x25, 0x46, 0x12, 0xd2, 0xf9, 0x9f, 0xf0, 0x84, 0xfb, 0xf8, 0x0e, + 0xd5, 0x12, 0x65, 0x00, 0x4f, 0xf5, 0xc1, 0xfe, 0x43, 0x08, 0xfb, 0x11, + 0xce, 0x19, 0xca, 0x18, 0x5c, 0x1a, 0x5a, 0x2d, 0xe8, 0x43, 0x5d, 0x4b, + 0x41, 0x41, 0x9d, 0x21, 0x50, 0x04, 0xa9, 0xf7, 0xd5, 0xee, 0x0c, 0xf3, + 0x1c, 0xf5, 0x72, 0xef, 0x1b, 0xfd, 0xc5, 0x09, 0x29, 0x0b, 0xae, 0x07, + 0x97, 0x08, 0x6e, 0x11, 0x55, 0x12, 0x01, 0x19, 0x36, 0x1f, 0x3e, 0x1b, + 0x91, 0x10, 0xfd, 0x02, 0xd8, 0xfa, 0xd2, 0xee, 0x3d, 0xe4, 0x4c, 0xe9, + 0x38, 0xfa, 0x23, 0x04, 0x00, 0x04, 0x9b, 0x05, 0xbc, 0x0a, 0x8b, 0x13, + 0x64, 0x15, 0x02, 0x0f, 0x3e, 0x0f, 0xb9, 0x13, 0x3d, 0x17, 0x76, 0x13, + 0x5c, 0x0e, 0x4e, 0x13, 0xc1, 0x13, 0x29, 0x0d, 0x33, 0xff, 0x95, 0xfe, + 0x3e, 0x17, 0xf2, 0x25, 0xea, 0x28, 0x94, 0x2b, 0x09, 0x31, 0x07, 0x37, + 0x4d, 0x31, 0xf4, 0x25, 0x7c, 0x19, 0x6f, 0x10, 0xbf, 0x11, 0x30, 0x0f, + 0xd2, 0x0d, 0x73, 0x0f, 0x53, 0x14, 0xcf, 0x1d, 0xae, 0x10, 0x6a, 0x08, + 0xeb, 0x0e, 0x04, 0x1b, 0xed, 0x21, 0x77, 0x0d, 0x1e, 0xfa, 0x57, 0xeb, + 0x9c, 0xe8, 0xc9, 0xe8, 0x69, 0xdb, 0x82, 0xce, 0x63, 0xce, 0x4d, 0xe3, + 0x84, 0xf2, 0x5f, 0xe5, 0x5c, 0xca, 0x44, 0xbd, 0xfd, 0xb9, 0x3d, 0xc7, + 0x7c, 0xd9, 0x18, 0xe6, 0x46, 0xf1, 0x80, 0xe7, 0x86, 0xdd, 0x49, 0xd4, + 0xd1, 0xce, 0xd7, 0xc7, 0x24, 0xb6, 0x57, 0xad, 0xdd, 0xa5, 0xa7, 0xa5, + 0xfd, 0xb5, 0xa3, 0xc6, 0x14, 0xcc, 0xea, 0xcb, 0xd7, 0xcd, 0xf1, 0xda, + 0xbf, 0xe5, 0xe1, 0xea, 0xba, 0xee, 0xef, 0xee, 0x35, 0xf9, 0x3f, 0xf9, + 0x71, 0xe9, 0x63, 0xd7, 0x5a, 0xc3, 0x72, 0xc4, 0x6a, 0xd1, 0x91, 0xdd, + 0x5c, 0xf7, 0x72, 0x02, 0xac, 0x0e, 0x4b, 0x22, 0x85, 0x1c, 0xaa, 0x0d, + 0x94, 0x03, 0x63, 0x0e, 0xa9, 0x0c, 0x23, 0x00, 0x2b, 0x00, 0xd1, 0xf7, + 0x31, 0xfa, 0xb3, 0x00, 0xb5, 0x0e, 0xbf, 0x1f, 0x89, 0x26, 0x81, 0x2b, + 0x3f, 0x28, 0x1f, 0x1f, 0x1c, 0x11, 0xc3, 0x06, 0xda, 0xf6, 0x98, 0xe9, + 0x35, 0xee, 0x53, 0xef, 0x78, 0xec, 0xbb, 0xdf, 0x1e, 0xcd, 0xde, 0xc9, + 0x69, 0xd9, 0xfa, 0xef, 0xa4, 0xf1, 0x3b, 0xe3, 0x0e, 0xe0, 0x0c, 0xea, + 0x57, 0xed, 0x88, 0xf5, 0xbd, 0x06, 0x98, 0x06, 0xe0, 0x03, 0x78, 0x05, + 0x34, 0x04, 0xc2, 0x09, 0x02, 0x19, 0x65, 0x29, 0xe5, 0x3d, 0xf0, 0x46, + 0x93, 0x41, 0xa9, 0x3f, 0xa4, 0x41, 0x26, 0x52, 0x2c, 0x53, 0xd8, 0x4d, + 0x94, 0x4e, 0xc3, 0x54, 0x9a, 0x64, 0x82, 0x60, 0x16, 0x60, 0xe2, 0x56, + 0xcf, 0x4c, 0xdf, 0x47, 0x7c, 0x3a, 0xe8, 0x3d, 0x18, 0x48, 0x5f, 0x4f, + 0xf9, 0x44, 0x91, 0x39, 0x20, 0x39, 0xc5, 0x40, 0x53, 0x4b, 0x26, 0x4b, + 0xcd, 0x48, 0xf8, 0x4a, 0x05, 0x55, 0x11, 0x5e, 0x3f, 0x61, 0x8a, 0x59, + 0xda, 0x56, 0x38, 0x56, 0xfc, 0x49, 0x00, 0x36, 0xb5, 0x29, 0x86, 0x30, + 0xed, 0x2b, 0x8b, 0x21, 0x4f, 0x10, 0xb1, 0xfe, 0xbc, 0x02, 0x11, 0x13, + 0x02, 0x1e, 0x2e, 0x14, 0x83, 0x0c, 0x13, 0x0e, 0xae, 0x1b, 0x2d, 0x38, + 0x29, 0x4f, 0xbc, 0x4e, 0xde, 0x48, 0x4b, 0x4d, 0x95, 0x4c, 0xe4, 0x4d, + 0x5b, 0x49, 0xae, 0x3a, 0xc6, 0x30, 0x08, 0x34, 0xfe, 0x3f, 0x30, 0x45, + 0x59, 0x45, 0x05, 0x4a, 0x73, 0x54, 0x06, 0x5e, 0x11, 0x5c, 0x28, 0x4a, + 0xd2, 0x3d, 0x8e, 0x41, 0x12, 0x4a, 0x77, 0x4a, 0xea, 0x3f, 0xeb, 0x3a, + 0xfc, 0x3a, 0xe1, 0x41, 0x83, 0x50, 0x38, 0x53, 0x93, 0x4b, 0x3d, 0x3c, + 0xbb, 0x2f, 0x9e, 0x35, 0xf5, 0x35, 0xae, 0x30, 0x10, 0x29, 0xf5, 0x28, + 0x4c, 0x36, 0x82, 0x34, 0xaa, 0x33, 0x91, 0x30, 0xbc, 0x27, 0x21, 0x2c, + 0xdb, 0x2f, 0x9c, 0x33, 0x26, 0x30, 0x03, 0x21, 0x35, 0x18, 0x7b, 0x10, + 0xa9, 0x11, 0xf2, 0x16, 0xd5, 0x17, 0xc8, 0x1b, 0x73, 0x11, 0x2b, 0x1e, + 0x3f, 0x31, 0xd0, 0x29, 0xa1, 0x25, 0xe7, 0x11, 0xfb, 0x07, 0xfb, 0x0b, + 0xc0, 0x06, 0xc7, 0x04, 0x13, 0xfe, 0x01, 0xfb, 0xaa, 0xfb, 0x3b, 0xf8, + 0xc8, 0xfb, 0x4b, 0xf2, 0x44, 0xe4, 0x1a, 0xee, 0xe3, 0xf2, 0x7c, 0xf4, + 0xf6, 0xea, 0x3e, 0xe0, 0xea, 0xf1, 0x49, 0xfa, 0x30, 0xfc, 0x03, 0xfd, + 0x8e, 0xf0, 0xec, 0xe8, 0x96, 0xe3, 0x44, 0xd8, 0x5f, 0xc7, 0x31, 0xb3, + 0xfd, 0xad, 0xca, 0xab, 0x9a, 0xae, 0xfd, 0xbd, 0xf2, 0xc2, 0xb2, 0xd3, + 0x8a, 0xe3, 0x87, 0xde, 0x6b, 0xd2, 0x58, 0xc1, 0x6b, 0xb3, 0x29, 0xa4, + 0x43, 0x97, 0x04, 0x98, 0x2b, 0x9c, 0x3a, 0x9e, 0xda, 0xa4, 0xf5, 0xa1, + 0x24, 0xa1, 0xf0, 0xa3, 0x33, 0xa1, 0x0a, 0xa3, 0xac, 0xa5, 0x49, 0xb7, + 0x99, 0xc1, 0xaf, 0xc1, 0xbf, 0xcc, 0xed, 0xcd, 0x86, 0xce, 0x18, 0xd8, + 0xc1, 0xe2, 0x0e, 0xec, 0xf6, 0xdc, 0xf7, 0xc7, 0xca, 0xc9, 0x6c, 0xc5, + 0x9f, 0xc0, 0x06, 0xbf, 0x12, 0xbd, 0x5d, 0xc1, 0x13, 0xc2, 0xcc, 0xcc, + 0xa2, 0xd9, 0xe7, 0xdf, 0xe1, 0xe0, 0x46, 0xd6, 0xf6, 0xc6, 0xd2, 0xc1, + 0xe4, 0xbb, 0xd8, 0xac, 0x6b, 0xa9, 0xbe, 0xa4, 0x47, 0xa1, 0x97, 0xa1, + 0x4e, 0x9e, 0xd9, 0xa3, 0x38, 0xae, 0xf5, 0xbf, 0x10, 0xc6, 0xda, 0xba, + 0x70, 0xb1, 0x96, 0xa9, 0x17, 0xa0, 0x72, 0x93, 0x3b, 0x91, 0x15, 0x92, + 0xba, 0x90, 0x33, 0x93, 0xa3, 0x90, 0x98, 0x91, 0x05, 0x9b, 0x64, 0xa8, + 0x68, 0xb4, 0x6c, 0xb4, 0xa2, 0xab, 0xf0, 0xae, 0x65, 0xbf, 0x19, 0xda, + 0x3d, 0xf2, 0xf8, 0xf4, 0x8f, 0xf5, 0x29, 0xf9, 0x5e, 0x05, 0x75, 0x13, + 0x16, 0x19, 0x33, 0x16, 0x17, 0x0e, 0x6c, 0x0e, 0x60, 0x0f, 0x30, 0x18, + 0x4f, 0x20, 0x9e, 0x2c, 0xfd, 0x34, 0x48, 0x2b, 0x69, 0x23, 0xff, 0x20, + 0x7d, 0x22, 0xe8, 0x15, 0xbb, 0x04, 0x14, 0xf1, 0x09, 0xe9, 0x79, 0xe9, + 0x4e, 0xe8, 0x3f, 0xf5, 0x4c, 0xf6, 0x88, 0xf7, 0x80, 0xef, 0x1c, 0xeb, + 0x05, 0x00, 0x31, 0x11, 0xa4, 0x15, 0x2b, 0x06, 0x07, 0xf7, 0x7e, 0xf1, + 0xf6, 0xea, 0x14, 0xdf, 0x47, 0xd4, 0x08, 0xcc, 0x04, 0xc5, 0x04, 0xbf, + 0x5c, 0xbd, 0xb2, 0xc2, 0xd8, 0xc3, 0xb0, 0xc4, 0xf7, 0xc0, 0x02, 0xbd, + 0x30, 0xbe, 0x3d, 0xc6, 0xcf, 0xcb, 0xa5, 0xcc, 0x68, 0xd2, 0x62, 0xd7, + 0x13, 0xe8, 0xfc, 0xf3, 0x7d, 0xf5, 0xbf, 0xf8, 0x28, 0xf8, 0xbb, 0xfe, + 0x25, 0x0e, 0xd4, 0x14, 0xc6, 0x15, 0x2e, 0x16, 0x05, 0x1a, 0xbe, 0x2c, + 0xcc, 0x34, 0x92, 0x34, 0x1a, 0x36, 0x2e, 0x3d, 0xcd, 0x3f, 0xb2, 0x2f, + 0xa5, 0x2c, 0x56, 0x2d, 0x02, 0x2d, 0x8b, 0x28, 0x14, 0x23, 0xe3, 0x25, + 0x46, 0x20, 0x2c, 0x1d, 0x07, 0x1c, 0xc8, 0x27, 0x78, 0x36, 0x48, 0x38, + 0x86, 0x41, 0xc9, 0x4d, 0xb4, 0x55, 0x1f, 0x54, 0xd9, 0x50, 0x93, 0x57, + 0x19, 0x5a, 0x88, 0x54, 0x92, 0x4f, 0x2b, 0x4d, 0xba, 0x54, 0xe2, 0x5e, + 0x97, 0x64, 0x80, 0x6b, 0x48, 0x6f, 0x2c, 0x70, 0x68, 0x6f, 0x10, 0x6b, + 0x72, 0x63, 0x80, 0x5c, 0xcf, 0x54, 0x7d, 0x46, 0x00, 0x2c, 0x09, 0x0f, + 0x6a, 0x0b, 0xf4, 0x16, 0x3f, 0x1e, 0xc5, 0x21, 0xbc, 0x17, 0x93, 0x14, + 0x71, 0x1e, 0x46, 0x22, 0x40, 0x29, 0xbc, 0x33, 0xd2, 0x3e, 0x85, 0x44, + 0xb2, 0x49, 0x83, 0x49, 0x03, 0x40, 0xf1, 0x31, 0x0d, 0x1b, 0xdf, 0x13, + 0xe0, 0xfe, 0x4c, 0xe5, 0xf0, 0xe3, 0x79, 0xd8, 0x9c, 0xda, 0xb6, 0xd7, + 0xfe, 0xc7, 0xc8, 0xd1, 0xec, 0xd6, 0x17, 0xd6, 0x53, 0xda, 0x31, 0xd6, + 0x60, 0xda, 0xf3, 0xde, 0x3a, 0xe0, 0x89, 0xe6, 0xc8, 0xe6, 0x86, 0xe3, + 0x85, 0xde, 0x8b, 0xe4, 0xea, 0xe8, 0xfc, 0xef, 0x3c, 0x01, 0x2d, 0x0e, + 0xc9, 0x24, 0x2e, 0x2e, 0x27, 0x38, 0xaa, 0x45, 0x03, 0x42, 0x53, 0x46, + 0xc8, 0x3f, 0xe9, 0x36, 0xe3, 0x38, 0x7b, 0x2a, 0x0a, 0x18, 0xfd, 0x0d, + 0x31, 0x0b, 0x26, 0x06, 0x9b, 0x00, 0x66, 0x06, 0xb6, 0x05, 0xbb, 0x06, + 0xb2, 0x10, 0xdd, 0x1b, 0x91, 0x2a, 0x22, 0x2c, 0x53, 0x28, 0x1a, 0x2a, + 0x3c, 0x30, 0xa3, 0x3a, 0x2e, 0x3c, 0x66, 0x35, 0x03, 0x27, 0x24, 0x1f, + 0x8e, 0x24, 0x29, 0x22, 0x44, 0x1f, 0x1a, 0x13, 0x7b, 0xfe, 0x0b, 0xf4, + 0x46, 0xe9, 0x30, 0xe7, 0x2e, 0xe3, 0xea, 0xd5, 0x91, 0xc7, 0x21, 0xb9, + 0x16, 0xb4, 0x00, 0xb0, 0x10, 0xb4, 0xa4, 0xbb, 0xce, 0xbe, 0x4d, 0xc2, + 0x71, 0xba, 0x7b, 0xbb, 0x97, 0xc4, 0xed, 0xc1, 0x0d, 0xc2, 0x9c, 0xba, + 0x25, 0xb9, 0x61, 0xc7, 0x92, 0xc9, 0x9e, 0xd1, 0xb4, 0xd9, 0x7d, 0xd8, + 0xcf, 0xde, 0xb0, 0xe7, 0x80, 0xf2, 0x40, 0xf7, 0x08, 0xed, 0xbd, 0xda, + 0x46, 0xd1, 0x0d, 0xd6, 0x62, 0xde, 0x61, 0xdc, 0x73, 0xd0, 0xb0, 0xd0, + 0x19, 0xdd, 0x81, 0xe8, 0x54, 0xf6, 0x81, 0xfe, 0x62, 0x08, 0xd8, 0x15, + 0x23, 0x15, 0x52, 0x17, 0x5c, 0x18, 0x8b, 0x16, 0xd4, 0x1a, 0xe5, 0x19, + 0xac, 0x1b, 0x8e, 0x19, 0xa0, 0x17, 0xf7, 0x16, 0xcc, 0x0a, 0x9f, 0x02, + 0x1b, 0xfc, 0xf4, 0xfa, 0xc5, 0x0a, 0x2a, 0x18, 0xbf, 0x1b, 0x12, 0x1c, + 0xba, 0x19, 0xfd, 0x13, 0x6f, 0x14, 0xdf, 0x19, 0x87, 0x16, 0xeb, 0x09, + 0x19, 0xfa, 0x56, 0xf0, 0xdf, 0xe9, 0xf1, 0xe6, 0xf3, 0xd8, 0x97, 0xc3, + 0xaf, 0xc6, 0xc7, 0xdf, 0x00, 0xfc, 0x68, 0x04, 0x8f, 0xfc, 0xa9, 0xf0, + 0x36, 0xf0, 0xe2, 0xfd, 0x99, 0x06, 0xb1, 0x01, 0x9c, 0xf5, 0xf9, 0xf2, + 0xf3, 0xf2, 0x6a, 0xec, 0x84, 0xe5, 0xd9, 0xeb, 0x24, 0xea, 0x66, 0xde, + 0xb1, 0xda, 0xbf, 0xd9, 0xa3, 0xe0, 0xce, 0xdf, 0xb0, 0xd8, 0xf7, 0xd4, + 0xda, 0xd7, 0x51, 0xe0, 0x87, 0xdf, 0xf6, 0xd2, 0x5c, 0xde, 0xb8, 0xf7, + 0xd4, 0xf8, 0xe6, 0xf3, 0x3e, 0xe2, 0xa0, 0xdc, 0xb5, 0xd8, 0x5f, 0xcd, + 0xc8, 0xd0, 0xcd, 0xc9, 0x7d, 0xce, 0x1d, 0xd7, 0x20, 0xd6, 0x56, 0xda, + 0x3a, 0xd4, 0x7f, 0xc9, 0xa9, 0xd2, 0xfe, 0xd7, 0x23, 0xdb, 0x4a, 0xda, + 0xc7, 0xce, 0xfa, 0xd8, 0x42, 0xda, 0xd7, 0xde, 0x6b, 0xe1, 0x34, 0xdf, + 0xa7, 0xee, 0xa4, 0xf2, 0xab, 0xf4, 0x98, 0xee, 0x48, 0xfa, 0x40, 0x12, + 0x9e, 0x16, 0xa3, 0x19, 0x2a, 0x1d, 0x47, 0x38, 0xee, 0x55, 0x73, 0x53, + 0x6b, 0x51, 0x16, 0x51, 0xa9, 0x4e, 0x59, 0x57, 0xaa, 0x57, 0x5c, 0x51, + 0x13, 0x41, 0x84, 0x37, 0x81, 0x3b, 0xa7, 0x35, 0x9d, 0x37, 0xb3, 0x33, + 0xc3, 0x29, 0x29, 0x28, 0x96, 0x24, 0xff, 0x24, 0x50, 0x24, 0x06, 0x1c, + 0x91, 0x13, 0x04, 0x09, 0x70, 0x01, 0x8a, 0xf8, 0x2b, 0xe8, 0x36, 0xe1, + 0x1c, 0xe0, 0x68, 0xee, 0x6b, 0xf4, 0xe6, 0xed, 0xa5, 0xf6, 0x09, 0xfb, + 0x5a, 0xff, 0x17, 0xf1, 0xad, 0xde, 0x12, 0xda, 0xf9, 0xd6, 0xf7, 0xdb, + 0x45, 0xdc, 0x44, 0xdc, 0x98, 0xd9, 0x96, 0xda, 0x6a, 0xd7, 0x11, 0xd0, + 0x37, 0xd0, 0x30, 0xd4, 0x31, 0xe3, 0xd5, 0xe9, 0x8c, 0xe9, 0xea, 0xea, + 0x50, 0xf3, 0x47, 0x02, 0x84, 0x16, 0xac, 0x2b, 0x6a, 0x32, 0x74, 0x3c, + 0x7c, 0x4a, 0xe2, 0x56, 0x01, 0x59, 0x59, 0x55, 0xa4, 0x5b, 0x0d, 0x60, + 0xb5, 0x5c, 0xa1, 0x59, 0x2d, 0x58, 0x1c, 0x4b, 0x39, 0x3f, 0x53, 0x3b, + 0xb8, 0x3b, 0x12, 0x3b, 0x3f, 0x34, 0xe2, 0x34, 0x4e, 0x35, 0x02, 0x37, + 0x73, 0x37, 0x75, 0x2c, 0x5a, 0x1f, 0x0f, 0x20, 0x65, 0x2f, 0xfd, 0x3c, + 0x5d, 0x43, 0x10, 0x3c, 0x27, 0x38, 0xd1, 0x3f, 0xb5, 0x45, 0xac, 0x48, + 0x8d, 0x3b, 0x50, 0x27, 0x70, 0x1d, 0x45, 0x16, 0x2c, 0x0c, 0xcc, 0x08, + 0xd2, 0x0e, 0x10, 0x15, 0xd7, 0x18, 0x53, 0x14, 0x37, 0x16, 0x2e, 0x28, + 0x05, 0x36, 0xae, 0x3e, 0x40, 0x45, 0x1e, 0x4e, 0x95, 0x5d, 0x7b, 0x63, + 0x45, 0x64, 0xfa, 0x6c, 0x42, 0x72, 0x20, 0x76, 0xba, 0x79, 0x1e, 0x78, + 0xa4, 0x79, 0x87, 0x78, 0x40, 0x77, 0x62, 0x77, 0xc2, 0x74, 0xbf, 0x74, + 0x17, 0x73, 0x2f, 0x72, 0xf9, 0x70, 0xea, 0x6e, 0x7c, 0x6a, 0x9e, 0x60, + 0x86, 0x55, 0x69, 0x4c, 0x79, 0x42, 0x7d, 0x31, 0x5c, 0x23, 0xf9, 0x17, + 0x67, 0x16, 0x4e, 0x22, 0xcc, 0x28, 0xee, 0x25, 0xdd, 0x1c, 0xe4, 0x1b, + 0x10, 0x26, 0x26, 0x2a, 0xbc, 0x29, 0x1c, 0x2b, 0x8f, 0x22, 0x01, 0x17, + 0x9b, 0x0b, 0x3b, 0xfd, 0x07, 0xf1, 0x6f, 0xe1, 0xc7, 0xd6, 0x04, 0xc8, + 0x93, 0xc2, 0xea, 0xc7, 0x01, 0xc4, 0x8f, 0xc2, 0xc1, 0xb7, 0xfc, 0xb1, + 0x8c, 0xb9, 0x8b, 0xbf, 0x19, 0xc2, 0x3b, 0xc0, 0xe8, 0xc4, 0x40, 0xd3, + 0xf9, 0xde, 0x14, 0xf2, 0x4c, 0x0c, 0x50, 0x0d, 0xd2, 0x12, 0xc8, 0x13, + 0x27, 0x11, 0x59, 0x22, 0x55, 0x21, 0xca, 0x24, 0xc8, 0x1e, 0xfb, 0x17, + 0x31, 0x22, 0xd1, 0x1d, 0xed, 0x1e, 0x70, 0x1c, 0x9a, 0x16, 0xaf, 0x15, + 0xe3, 0x17, 0x47, 0x1e, 0xe7, 0x1a, 0xe2, 0x16, 0xe7, 0x10, 0x3d, 0x08, + 0xda, 0x0e, 0x35, 0x16, 0x26, 0x16, 0xa7, 0x16, 0x8d, 0x13, 0xec, 0x1f, + 0x10, 0x32, 0x56, 0x38, 0xd9, 0x3b, 0x59, 0x40, 0x21, 0x40, 0x66, 0x2f, + 0x7a, 0x1a, 0x76, 0x0a, 0xfa, 0x06, 0xef, 0x07, 0x10, 0xff, 0x7c, 0xef, + 0x77, 0xde, 0x91, 0xd5, 0xd7, 0xce, 0x8a, 0xd0, 0xb8, 0xd7, 0x31, 0xda, + 0x24, 0xd7, 0x01, 0xd0, 0xd9, 0xd4, 0xc7, 0xe0, 0x15, 0xe6, 0x52, 0xe5, + 0x0e, 0xde, 0x69, 0xd4, 0xe4, 0xcc, 0x9d, 0xc0, 0xf6, 0xb8, 0x6e, 0xb6, + 0xbb, 0xb4, 0x64, 0xb4, 0xae, 0xb2, 0x6d, 0xb6, 0xad, 0xb2, 0x13, 0xb5, + 0xbd, 0xbd, 0xaa, 0xbb, 0x5a, 0xb4, 0x32, 0xa8, 0x42, 0xa6, 0x7d, 0xa4, + 0xfa, 0x9e, 0x80, 0x9a, 0xc3, 0x97, 0x31, 0x9a, 0x37, 0x9b, 0x6a, 0x9f, + 0x63, 0x9e, 0xe3, 0x9d, 0xde, 0x9f, 0xaa, 0xa4, 0x6d, 0xb2, 0x2d, 0xbc, + 0xb9, 0xbd, 0xde, 0xbd, 0x2e, 0xc6, 0x8a, 0xc3, 0xad, 0xbc, 0x87, 0xc3, + 0x79, 0xc5, 0xaa, 0xc1, 0xd3, 0xbb, 0x52, 0xc0, 0x90, 0xcc, 0xb0, 0xd0, + 0xbc, 0xd3, 0xff, 0xd2, 0xa7, 0xd4, 0x48, 0xdf, 0x0b, 0xe2, 0x74, 0xe2, + 0x38, 0xe7, 0x75, 0xed, 0x44, 0xf9, 0x6e, 0xfa, 0xf4, 0xfa, 0xb4, 0x07, + 0x6f, 0x13, 0x96, 0x16, 0x80, 0x0e, 0x01, 0x09, 0xf9, 0x0a, 0x10, 0x15, + 0xbd, 0x17, 0xac, 0x0e, 0x10, 0x0b, 0x79, 0x0d, 0x82, 0x15, 0xf5, 0x14, + 0xf8, 0x10, 0x0e, 0x13, 0xaf, 0x0a, 0x07, 0x01, 0xf2, 0x06, 0xe0, 0x0c, + 0x92, 0x14, 0xea, 0x18, 0x54, 0x0c, 0x44, 0x01, 0x45, 0xf1, 0x26, 0xef, + 0xd8, 0xfa, 0xed, 0xf0, 0x3b, 0xdb, 0x77, 0xc1, 0xe7, 0xb3, 0x02, 0xb5, + 0xc8, 0xb0, 0xbe, 0xaa, 0xae, 0xa7, 0x48, 0x9f, 0x7f, 0x9e, 0x77, 0xa1, + 0xa3, 0x9b, 0x83, 0xa0, 0xbd, 0xa0, 0xbd, 0x9c, 0x69, 0xa3, 0xf2, 0xa5, + 0xcd, 0xa5, 0x85, 0xa6, 0xe0, 0xa8, 0x8c, 0xaf, 0xbe, 0xb6, 0x9a, 0xb9, + 0x99, 0xbe, 0xa1, 0xc0, 0xe2, 0xc2, 0x63, 0xc1, 0x4b, 0xb3, 0x8d, 0xbb, + 0x95, 0xc6, 0xf5, 0xc8, 0x0f, 0xd1, 0x12, 0xd0, 0xfc, 0xd6, 0xf8, 0xd6, + 0xa9, 0xd6, 0x7e, 0xdd, 0xb0, 0xdc, 0xf2, 0xe9, 0x5f, 0xf3, 0x4b, 0xfc, + 0xac, 0x01, 0x3a, 0xfe, 0xae, 0x10, 0x7f, 0x24, 0xdf, 0x2b, 0xf1, 0x23, + 0x21, 0x1f, 0x60, 0x2b, 0x8c, 0x32, 0xf7, 0x34, 0xc6, 0x29, 0xf4, 0x28, + 0x7b, 0x2f, 0xe9, 0x2f, 0x92, 0x34, 0x56, 0x26, 0xe4, 0x1e, 0xf1, 0x14, + 0xc6, 0x05, 0xa8, 0xfe, 0xc9, 0xf0, 0x2c, 0xef, 0xc1, 0xe5, 0x05, 0xd9, + 0x28, 0xd9, 0xa5, 0xd8, 0xef, 0xd6, 0x45, 0xd9, 0x5d, 0xdc, 0x6b, 0xe0, + 0xf5, 0xeb, 0x7f, 0xf1, 0xd5, 0xf6, 0x02, 0xfe, 0x79, 0x05, 0x0b, 0x0f, + 0x58, 0x0c, 0xbe, 0xfb, 0x9f, 0xef, 0x81, 0xe6, 0x0b, 0xdc, 0x44, 0xd6, + 0xd1, 0xcc, 0x38, 0xc8, 0xb7, 0xc3, 0x76, 0xbe, 0xb0, 0xbb, 0x1e, 0xc2, + 0x36, 0xca, 0x1c, 0xc9, 0x98, 0xcb, 0xbf, 0xc5, 0x84, 0xcc, 0xf1, 0xd6, + 0xc0, 0xd9, 0xa3, 0xe4, 0x59, 0xec, 0x98, 0xf4, 0x7d, 0xf9, 0xcb, 0xfc, + 0xbf, 0xfc, 0xa9, 0xf8, 0x90, 0xee, 0x8e, 0xe4, 0x12, 0xe6, 0x55, 0xea, + 0xed, 0xec, 0x5f, 0xea, 0x3a, 0xe7, 0xd7, 0xe7, 0x01, 0xeb, 0x6f, 0xe7, + 0x77, 0xde, 0x24, 0xde, 0xb1, 0xe1, 0x3e, 0xe4, 0x93, 0xeb, 0xef, 0xf2, + 0x04, 0xfd, 0x90, 0x0d, 0x68, 0x1a, 0x4e, 0x24, 0xea, 0x2b, 0xb6, 0x35, + 0xa3, 0x42, 0x9f, 0x50, 0x27, 0x5d, 0x62, 0x61, 0x71, 0x62, 0x45, 0x61, + 0xf9, 0x60, 0xd0, 0x63, 0x27, 0x62, 0xf0, 0x5e, 0xdf, 0x58, 0x8f, 0x4d, + 0x3b, 0x49, 0x42, 0x47, 0x1c, 0x4e, 0x9b, 0x56, 0x1c, 0x4f, 0x25, 0x4a, + 0x0f, 0x42, 0x6f, 0x3f, 0x43, 0x46, 0x69, 0x45, 0x3c, 0x4d, 0xab, 0x5b, + 0x75, 0x64, 0x8a, 0x6a, 0xf8, 0x6a, 0xcd, 0x69, 0x7e, 0x6e, 0xe7, 0x70, + 0xce, 0x6f, 0xec, 0x68, 0x8a, 0x5b, 0x40, 0x50, 0xb8, 0x48, 0xa1, 0x44, + 0x20, 0x41, 0xba, 0x41, 0xed, 0x42, 0x02, 0x44, 0x72, 0x46, 0xf2, 0x44, + 0x0f, 0x42, 0xbd, 0x3e, 0xb9, 0x3c, 0xc3, 0x37, 0x40, 0x30, 0x9f, 0x2e, + 0x99, 0x30, 0x2d, 0x30, 0x98, 0x2d, 0x33, 0x28, 0x8d, 0x24, 0xc5, 0x25, + 0x2b, 0x28, 0x31, 0x2b, 0x60, 0x31, 0x8b, 0x3f, 0x5e, 0x46, 0xf5, 0x4c, + 0xe3, 0x59, 0xdb, 0x5b, 0x68, 0x5d, 0x0e, 0x61, 0x44, 0x66, 0xc9, 0x66, + 0x74, 0x5f, 0x43, 0x5d, 0xd6, 0x57, 0x82, 0x4b, 0x8f, 0x45, 0x5a, 0x44, + 0x36, 0x46, 0xfc, 0x46, 0x79, 0x3a, 0x82, 0x35, 0xf3, 0x44, 0x80, 0x5a, + 0x7d, 0x62, 0x2d, 0x63, 0xc4, 0x64, 0xe4, 0x5a, 0x3b, 0x5b, 0xdf, 0x59, + 0x66, 0x4b, 0x66, 0x3d, 0x65, 0x2c, 0xab, 0x29, 0x8f, 0x30, 0x6f, 0x33, + 0x17, 0x3b, 0xe9, 0x3e, 0xca, 0x3a, 0x54, 0x41, 0x14, 0x3d, 0x07, 0x37, + 0x76, 0x3f, 0x34, 0x37, 0xbb, 0x39, 0x5c, 0x3b, 0xb4, 0x33, 0xcb, 0x3c, + 0x5f, 0x38, 0x9d, 0x39, 0x1a, 0x49, 0x84, 0x50, 0xf3, 0x5a, 0x36, 0x61, + 0x33, 0x5e, 0x9a, 0x60, 0xc9, 0x65, 0x8a, 0x66, 0x1a, 0x69, 0xed, 0x67, + 0xb1, 0x66, 0x78, 0x68, 0xb7, 0x68, 0xc6, 0x6b, 0x74, 0x6b, 0x5c, 0x67, + 0xea, 0x66, 0xe8, 0x67, 0xf8, 0x63, 0x9f, 0x60, 0x43, 0x5b, 0x42, 0x53, + 0x93, 0x4d, 0x03, 0x46, 0x00, 0x49, 0xaa, 0x50, 0x4b, 0x4f, 0x5c, 0x4f, + 0xa7, 0x4f, 0xe5, 0x49, 0xdb, 0x45, 0xf6, 0x3d, 0x29, 0x31, 0xf2, 0x29, + 0x62, 0x1c, 0x81, 0x0c, 0xcf, 0xfe, 0x8e, 0xf1, 0x6a, 0xef, 0x17, 0xf0, + 0x8a, 0xf0, 0x55, 0xec, 0x88, 0xe2, 0xeb, 0xd8, 0x51, 0xce, 0x81, 0xcb, + 0x8e, 0xc6, 0x4d, 0xbf, 0x7b, 0xbc, 0xd6, 0xb5, 0x60, 0xb3, 0x60, 0xb3, + 0xda, 0xae, 0xaa, 0xab, 0x70, 0xa6, 0x1f, 0xa4, 0x4a, 0xa6, 0x73, 0xa1, + 0xa3, 0xa2, 0x00, 0xa1, 0x27, 0x9e, 0x17, 0xa5, 0x7b, 0xab, 0x0f, 0xb6, + 0xc7, 0xb4, 0xe4, 0xb6, 0xb0, 0xbd, 0x25, 0xc0, 0xc0, 0xca, 0x08, 0xce, + 0x2d, 0xd1, 0x3f, 0xd8, 0xa9, 0xdc, 0x75, 0xdb, 0x13, 0xd9, 0x2c, 0xd6, + 0xb5, 0xdd, 0x5c, 0xe5, 0x4a, 0xe5, 0x48, 0xeb, 0xbd, 0xed, 0xdc, 0xfc, + 0x66, 0x05, 0x1b, 0x01, 0x7c, 0xfb, 0xc5, 0xf5, 0xb0, 0xf6, 0x93, 0xf4, + 0xf5, 0xf5, 0x12, 0xf6, 0xbd, 0xfb, 0x1f, 0xfd, 0x21, 0x00, 0x0c, 0x0b, + 0x71, 0x11, 0x52, 0x17, 0xc3, 0x17, 0xc3, 0x1a, 0xbe, 0x19, 0xd4, 0x17, + 0x98, 0x1b, 0x75, 0x1d, 0xc9, 0x1a, 0x42, 0x17, 0xa9, 0x12, 0x9e, 0x11, + 0xaf, 0x18, 0x66, 0x19, 0xac, 0x12, 0x92, 0x09, 0xbc, 0x07, 0x11, 0x0c, + 0xb4, 0x11, 0x08, 0x0e, 0x98, 0x04, 0x5e, 0x02, 0x06, 0xfd, 0xe4, 0xf8, + 0x51, 0xef, 0xf1, 0xe1, 0xa0, 0xd4, 0xef, 0xbe, 0x42, 0xb2, 0x98, 0xae, + 0x06, 0xae, 0xcb, 0xb3, 0x41, 0xb1, 0xb5, 0xac, 0x60, 0xb0, 0xb9, 0xb6, + 0xc1, 0xbd, 0x83, 0xbc, 0x97, 0xb3, 0xee, 0xac, 0xac, 0xa9, 0x83, 0xa9, + 0x59, 0xb0, 0x18, 0xb1, 0xee, 0xaa, 0x22, 0xa4, 0xf9, 0x9d, 0x7f, 0xa3, + 0x83, 0xa8, 0x14, 0xab, 0xbb, 0xaa, 0x3d, 0xa3, 0x71, 0xa6, 0xb5, 0xa8, + 0x4a, 0xa2, 0xd7, 0xa8, 0x2c, 0xab, 0x22, 0xac, 0xd0, 0xb0, 0x19, 0xac, + 0x64, 0xb7, 0xe8, 0xc6, 0xb9, 0xd4, 0x23, 0xe1, 0x40, 0xdd, 0x72, 0xe0, + 0x6a, 0xf1, 0xb7, 0x01, 0xdd, 0x13, 0xd6, 0x18, 0x6e, 0x14, 0x32, 0x1b, + 0x8b, 0x22, 0x68, 0x35, 0x4f, 0x3b, 0xa3, 0x34, 0x34, 0x32, 0x98, 0x2c, + 0xda, 0x33, 0xc8, 0x33, 0x5c, 0x34, 0x76, 0x33, 0x82, 0x2e, 0x08, 0x27, + 0x15, 0x1b, 0x55, 0x1f, 0xbb, 0x2a, 0x9f, 0x31, 0x3f, 0x2b, 0x2a, 0x20, + 0xd7, 0x10, 0xa8, 0x0e, 0x20, 0x17, 0xa4, 0x23, 0xff, 0x2f, 0xe8, 0x23, + 0x64, 0x1f, 0x01, 0x16, 0x25, 0x0e, 0xf4, 0x0a, 0x2f, 0xf7, 0x2f, 0xed, + 0x83, 0xdf, 0x1d, 0xd8, 0x8b, 0xd7, 0x47, 0xce, 0x2f, 0xc6, 0x26, 0xbe, + 0x6d, 0xbf, 0x90, 0xcc, 0x2d, 0xdc, 0x4b, 0xe0, 0xe8, 0xdd, 0x71, 0xdd, + 0xe5, 0xdf, 0xd7, 0xde, 0xb7, 0xd8, 0xfa, 0xd2, 0x5a, 0xc9, 0xe0, 0xc6, + 0x73, 0xbf, 0xc6, 0xba, 0xc5, 0xbc, 0x1a, 0xbf, 0x5d, 0xc6, 0x78, 0xc1, + 0x4b, 0xc9, 0xa3, 0xce, 0x67, 0xd6, 0xf4, 0xe7, 0xf4, 0xe6, 0x74, 0xe7, + 0x32, 0xe6, 0x89, 0xef, 0xad, 0xf4, 0x04, 0xeb, 0xc1, 0xe4, 0xb6, 0xdd, + 0x46, 0xe1, 0x8d, 0xe8, 0x5f, 0xec, 0x95, 0xee, 0x9a, 0xf0, 0x68, 0xf1, + 0x3b, 0xf5, 0x2f, 0xf6, 0x8c, 0xf7, 0x10, 0xfd, 0x84, 0x01, 0x96, 0x09, + 0xe3, 0x08, 0xe3, 0x03, 0xe0, 0xfd, 0x95, 0xfb, 0xed, 0xf9, 0x76, 0xf6, + 0xee, 0xf2, 0x1a, 0xeb, 0x3f, 0xef, 0xa2, 0xf3, 0x46, 0xf7, 0x9a, 0xf7, + 0x64, 0xf1, 0x39, 0xf5, 0xb0, 0xf7, 0xc6, 0xf4, 0x1b, 0xf5, 0xe5, 0xf5, + 0xd0, 0xfb, 0x6b, 0x01, 0x45, 0xf7, 0x8e, 0xf2, 0x35, 0xf8, 0xce, 0xfe, + 0x24, 0x02, 0x85, 0xfd, 0x17, 0xfd, 0x76, 0x03, 0xb4, 0x0c, 0x20, 0x0d, + 0x6d, 0x0a, 0xd0, 0x07, 0xb8, 0x0e, 0x45, 0x17, 0x4a, 0x13, 0x28, 0x16, + 0xdf, 0x13, 0x43, 0x1d, 0x36, 0x2e, 0xca, 0x3d, 0x50, 0x51, 0xa3, 0x4e, + 0xd0, 0x52, 0x04, 0x52, 0xbe, 0x43, 0xe8, 0x41, 0xe9, 0x38, 0x61, 0x31, + 0xd3, 0x25, 0x66, 0x0f, 0xfd, 0x01, 0xda, 0xf8, 0x98, 0xfe, 0x39, 0x0d, + 0x59, 0x05, 0x0f, 0xf5, 0x2b, 0xf0, 0xbf, 0xf1, 0xed, 0xfc, 0x3d, 0x04, + 0x31, 0xfe, 0x76, 0xff, 0x23, 0xf9, 0x0a, 0xef, 0x6f, 0xf6, 0x5e, 0xf3, + 0x89, 0xf2, 0x70, 0xf5, 0x9e, 0xef, 0x5e, 0xf3, 0x1b, 0xf3, 0x1b, 0xf3, + 0xb6, 0xfd, 0xde, 0x04, 0xe1, 0x05, 0x0a, 0x0a, 0xe8, 0x0c, 0x40, 0x10, + 0xba, 0x19, 0x0e, 0x1c, 0xf1, 0x21, 0x74, 0x26, 0xa4, 0x27, 0x5b, 0x31, + 0x15, 0x35, 0x0b, 0x36, 0x3b, 0x37, 0x06, 0x33, 0xe4, 0x26, 0x7e, 0x25, + 0x27, 0x2b, 0x4f, 0x2c, 0x21, 0x31, 0x64, 0x2d, 0x8d, 0x32, 0xe7, 0x39, + 0x05, 0x3d, 0xd4, 0x44, 0xc9, 0x40, 0x47, 0x37, 0x17, 0x35, 0x3d, 0x3c, + 0x05, 0x43, 0xe6, 0x48, 0xf2, 0x3d, 0xaf, 0x38, 0x48, 0x3d, 0x0b, 0x32, + 0xa6, 0x33, 0x4c, 0x2a, 0x91, 0x1d, 0xe1, 0x17, 0x5a, 0x12, 0x6a, 0x13, + 0xa3, 0x0e, 0x8b, 0x11, 0x53, 0x12, 0xcf, 0x17, 0xee, 0x14, 0x3a, 0x11, + 0x36, 0x10, 0x69, 0x0d, 0xf6, 0x1a, 0xfa, 0x17, 0x9e, 0x1c, 0x62, 0x17, + 0xe3, 0x11, 0xf7, 0x1b, 0x17, 0x1f, 0xdb, 0x29, 0x91, 0x1d, 0x31, 0x1d, + 0x0b, 0x1e, 0x10, 0x1f, 0x4d, 0x29, 0x12, 0x2b, 0xa5, 0x32, 0x57, 0x2c, + 0x99, 0x32, 0xb2, 0x36, 0x1a, 0x3e, 0x62, 0x3f, 0xbf, 0x33, 0x4a, 0x2c, + 0x73, 0x20, 0xef, 0x24, 0xde, 0x21, 0x54, 0x24, 0xcc, 0x1b, 0x73, 0x11, + 0x7a, 0x0e, 0xfe, 0x07, 0x83, 0x0e, 0xf0, 0x0a, 0xb5, 0x11, 0x05, 0x0e, + 0x56, 0x06, 0x0d, 0x03, 0xe9, 0xff, 0x44, 0x07, 0xfa, 0x01, 0x49, 0xf1, + 0x2f, 0xdc, 0x6b, 0xd0, 0x54, 0xcb, 0x06, 0xcc, 0x00, 0xc4, 0x87, 0xc4, + 0x95, 0xc3, 0x22, 0xbe, 0xd6, 0xc5, 0xc9, 0xbf, 0x01, 0xc5, 0x9a, 0xbe, + 0xb0, 0xb9, 0x3e, 0xbe, 0xea, 0xbc, 0x5e, 0xc7, 0xa5, 0xc3, 0x6d, 0xca, + 0xcc, 0xdd, 0x70, 0xeb, 0xde, 0xf1, 0x02, 0xf2, 0x65, 0xfa, 0xb3, 0x08, + 0xdb, 0x0d, 0x63, 0x0c, 0xaa, 0x0d, 0x4e, 0x11, 0x2a, 0x21, 0x43, 0x2c, + 0xdf, 0x35, 0xf1, 0x3c, 0x26, 0x3d, 0x04, 0x42, 0xab, 0x42, 0xba, 0x48, + 0xa8, 0x4c, 0x37, 0x50, 0xe7, 0x54, 0x51, 0x55, 0x86, 0x56, 0x6f, 0x5a, + 0xae, 0x63, 0xf4, 0x68, 0xd5, 0x6b, 0x5b, 0x64, 0x25, 0x5e, 0xb8, 0x5a, + 0x1d, 0x55, 0x37, 0x59, 0xdc, 0x54, 0xff, 0x4c, 0xa6, 0x43, 0x38, 0x36, + 0x1f, 0x30, 0x4f, 0x2b, 0xf2, 0x1f, 0xa6, 0x14, 0xcd, 0x03, 0x3e, 0xed, + 0x01, 0xde, 0x9a, 0xc6, 0xcc, 0xb8, 0x75, 0xb9, 0xb2, 0xb2, 0x26, 0xb0, + 0x23, 0xb0, 0x7f, 0xb1, 0x92, 0xb8, 0x43, 0xbd, 0x38, 0xbc, 0xbb, 0xc1, + 0x0d, 0xc3, 0x4b, 0xba, 0xac, 0xb0, 0x65, 0xa5, 0x45, 0xa5, 0xb7, 0xa6, + 0x12, 0xa5, 0x0f, 0xa6, 0xf6, 0xa2, 0x8e, 0xa6, 0x6e, 0xaf, 0xc0, 0xb3, + 0x97, 0xb8, 0x1d, 0xbd, 0xdb, 0xc5, 0x98, 0xce, 0x57, 0xd0, 0xa7, 0xd3, + 0xae, 0xd6, 0xf3, 0xdc, 0x0b, 0xe0, 0x4f, 0xe5, 0x52, 0xf6, 0x71, 0x07, + 0xad, 0x1d, 0xd4, 0x28, 0x1b, 0x2e, 0x2b, 0x3f, 0x9c, 0x4a, 0x27, 0x51, + 0x5c, 0x52, 0xdd, 0x4d, 0x0d, 0x47, 0x62, 0x3c, 0x07, 0x35, 0xd7, 0x33, + 0xcb, 0x2e, 0x00, 0x23, 0x1b, 0x1d, 0x9e, 0x19, 0x16, 0x1b, 0x0c, 0x22, + 0xa5, 0x22, 0x01, 0x29, 0x45, 0x31, 0x05, 0x30, 0xaa, 0x2e, 0xd3, 0x36, + 0x3c, 0x41, 0x45, 0x48, 0x0b, 0x4d, 0x41, 0x42, 0xd0, 0x3c, 0x5e, 0x3d, + 0x6c, 0x2d, 0xcf, 0x2b, 0x5a, 0x24, 0xab, 0x15, 0xb0, 0x14, 0x9e, 0x08, + 0x1f, 0x0d, 0x4f, 0x13, 0xc9, 0x14, 0xd2, 0x1d, 0xdf, 0x15, 0x6a, 0x0f, + 0x4a, 0x06, 0x3e, 0xff, 0xc8, 0xf6, 0xf2, 0xee, 0x0d, 0xf1, 0xbc, 0xf2, + 0xf2, 0xfb, 0xd9, 0xf7, 0xc1, 0xf1, 0xcc, 0xf1, 0xdb, 0xf2, 0x27, 0xf9, + 0xa7, 0xf6, 0x51, 0xf1, 0x6f, 0xf1, 0x09, 0xf1, 0x9e, 0xe7, 0x50, 0xe3, + 0x38, 0xdf, 0x1a, 0xd6, 0x0c, 0xcf, 0x13, 0xc6, 0x88, 0xbd, 0x32, 0xb5, + 0x9c, 0xb0, 0x5d, 0xab, 0x79, 0xaa, 0x94, 0xad, 0x0c, 0xb2, 0xe6, 0xb3, + 0x0c, 0xb2, 0x07, 0xb0, 0x38, 0xad, 0xcc, 0xb9, 0x3c, 0xc7, 0xb0, 0xd2, + 0x04, 0xdc, 0x7e, 0xdb, 0x20, 0xe1, 0x3c, 0xe4, 0xd5, 0xe3, 0x6c, 0xe0, + 0x6d, 0xd8, 0xf8, 0xd4, 0xf5, 0xd1, 0x7b, 0xd0, 0x8c, 0xcf, 0xb1, 0xcc, + 0x4f, 0xcb, 0xc5, 0xc8, 0xa0, 0xd0, 0x15, 0xde, 0xb1, 0xe5, 0x74, 0xea, + 0x8e, 0xeb, 0x46, 0xf4, 0x5e, 0xfd, 0x9f, 0x07, 0xb2, 0x0f, 0xd9, 0x12, + 0xdb, 0x15, 0x6a, 0x0e, 0x69, 0x08, 0xc4, 0x03, 0xdc, 0x02, 0xf3, 0x00, + 0x20, 0xff, 0xe6, 0x01, 0x55, 0x00, 0xdf, 0xfb, 0xf9, 0xf3, 0xd9, 0xee, + 0x41, 0xea, 0x8c, 0xe6, 0x1b, 0xda, 0xee, 0xd0, 0x39, 0xcd, 0x76, 0xcd, + 0x25, 0xd8, 0x55, 0xd3, 0x90, 0xd5, 0x62, 0xd7, 0xdf, 0xd8, 0x6b, 0xe7, + 0xe0, 0xe9, 0x5e, 0xf2, 0x43, 0xfd, 0x46, 0xff, 0x44, 0x05, 0xe6, 0x02, + 0xc8, 0xfb, 0xcb, 0xf7, 0x48, 0xe9, 0x9e, 0xdb, 0xeb, 0xd1, 0x97, 0xc7, + 0x5f, 0xbb, 0x46, 0xaf, 0x43, 0xac, 0xd7, 0xb3, 0xa6, 0xbb, 0x54, 0xb6, + 0x3c, 0xb4, 0x3b, 0xb7, 0xdb, 0xc9, 0x56, 0xdc, 0x98, 0xe0, 0x16, 0xe8, + 0x68, 0xeb, 0x74, 0xf3, 0x64, 0xf6, 0x00, 0xf9, 0x45, 0xff, 0x4d, 0x04, + 0xc5, 0x01, 0x8b, 0xf3, 0xd2, 0xea, 0x11, 0xee, 0x31, 0xfe, 0xd8, 0xff, + 0xa3, 0xf9, 0x06, 0xf4, 0x7c, 0xf1, 0x07, 0xf7, 0xb7, 0xf6, 0xe3, 0xf9, + 0xcf, 0xf2, 0x5f, 0xea, 0xbf, 0xe4, 0xb7, 0xdf, 0xda, 0xf0, 0x92, 0x00, + 0xe1, 0x06, 0x94, 0x03, 0x69, 0xfe, 0x38, 0x0b, 0x40, 0x14, 0xc7, 0x17, + 0xd2, 0x11, 0xf7, 0x0a, 0x8a, 0x13, 0x24, 0x18, 0xae, 0x1a, 0xd1, 0x17, + 0x9b, 0x15, 0x36, 0x13, 0xf8, 0x0b, 0xb4, 0x09, 0x3c, 0x02, 0xd6, 0xf7, + 0xfa, 0xf3, 0xdf, 0xec, 0x32, 0xe8, 0x31, 0xea, 0x4f, 0xe0, 0x30, 0xeb, + 0x1f, 0xf5, 0x5e, 0xec, 0xba, 0xf4, 0x5e, 0xf7, 0x31, 0x07, 0xaa, 0x18, + 0xb2, 0x19, 0x3f, 0x24, 0xe7, 0x2f, 0x96, 0x3b, 0xf3, 0x3e, 0xf7, 0x34, + 0x49, 0x36, 0xa4, 0x35, 0xfb, 0x26, 0xf9, 0x26, 0x0a, 0x21, 0xe9, 0x23, + 0xf5, 0x34, 0x27, 0x2c, 0xfa, 0x29, 0x09, 0x26, 0x17, 0x20, 0xad, 0x2e, + 0x01, 0x2b, 0x05, 0x26, 0xc5, 0x27, 0xa5, 0x1b, 0x6b, 0x21, 0xd5, 0x25, + 0x56, 0x28, 0xee, 0x33, 0xf0, 0x2a, 0xc9, 0x26, 0xeb, 0x2d, 0x68, 0x30, + 0xfb, 0x31, 0xef, 0x36, 0xaf, 0x31, 0xab, 0x2a, 0x41, 0x28, 0xb4, 0x14, + 0xad, 0x0d, 0x4d, 0x0c, 0xb5, 0x03, 0x1f, 0xf5, 0x00, 0xe8, 0x06, 0xed, + 0x75, 0xee, 0xc9, 0xf8, 0x22, 0xfd, 0xc8, 0xf8, 0xb5, 0xfe, 0x8f, 0x03, + 0x5b, 0x11, 0xa8, 0x17, 0x62, 0x12, 0xa1, 0x16, 0x48, 0x21, 0x12, 0x28, + 0x84, 0x2d, 0x9f, 0x2c, 0xd2, 0x28, 0x25, 0x27, 0xa8, 0x1c, 0x0a, 0x16, + 0xfe, 0x10, 0x59, 0x08, 0x03, 0xfe, 0xc4, 0xef, 0x1b, 0xee, 0xd2, 0xf8, + 0xb3, 0x01, 0xc6, 0x0c, 0xff, 0x17, 0x1d, 0x1d, 0x38, 0x24, 0x3c, 0x26, + 0xec, 0x25, 0x19, 0x29, 0x6e, 0x2b, 0x0f, 0x2a, 0xc5, 0x21, 0xe2, 0x22, + 0x05, 0x2e, 0x66, 0x33, 0x74, 0x33, 0xc5, 0x32, 0x64, 0x2f, 0xe2, 0x2c, + 0xf2, 0x2b, 0xbe, 0x2a, 0x81, 0x2a, 0x93, 0x29, 0xf2, 0x23, 0x48, 0x1b, + 0xad, 0x1e, 0x85, 0x25, 0xfc, 0x27, 0xf7, 0x29, 0xd3, 0x29, 0x3c, 0x2d, + 0x8b, 0x36, 0xce, 0x42, 0xe9, 0x4d, 0xde, 0x53, 0xb5, 0x4c, 0x2a, 0x4a, + 0x8f, 0x47, 0x13, 0x3d, 0xb8, 0x3a, 0xdb, 0x2f, 0x0b, 0x25, 0x45, 0x1b, + 0xde, 0x0c, 0x50, 0x08, 0xf5, 0x06, 0x5e, 0x06, 0xa1, 0x06, 0x38, 0x02, + 0xb1, 0x02, 0xfe, 0x08, 0xe5, 0x04, 0x4f, 0x04, 0x35, 0x05, 0xc3, 0x07, + 0xc6, 0x0d, 0xed, 0x03, 0xd1, 0xfe, 0xff, 0xf3, 0x81, 0xe5, 0xba, 0xe1, + 0x76, 0xda, 0x8e, 0xdf, 0x30, 0xe1, 0x88, 0xdb, 0xe6, 0xdf, 0x4a, 0xdf, + 0x56, 0xe0, 0x50, 0xe5, 0xdb, 0xe0, 0xe1, 0xdf, 0xc7, 0xe3, 0x39, 0xe5, + 0xd8, 0xe8, 0xe9, 0xe7, 0x04, 0xe7, 0xd7, 0xed, 0x39, 0xf6, 0xe7, 0x05, + 0x52, 0x11, 0x05, 0x15, 0x19, 0x26, 0x7a, 0x31, 0x6a, 0x36, 0x38, 0x3f, + 0xe1, 0x41, 0x4a, 0x4b, 0xe6, 0x51, 0xf9, 0x50, 0xfa, 0x4f, 0xab, 0x4c, + 0x60, 0x4d, 0x30, 0x55, 0x0b, 0x59, 0xb1, 0x57, 0xff, 0x5b, 0x79, 0x5c, + 0x88, 0x5c, 0x8e, 0x5a, 0x3a, 0x5a, 0x43, 0x65, 0xd8, 0x67, 0x12, 0x64, + 0xaf, 0x60, 0x0c, 0x5a, 0xcf, 0x55, 0x45, 0x55, 0xfc, 0x4e, 0x0b, 0x48, + 0x1a, 0x3f, 0xb8, 0x38, 0xc3, 0x3a, 0x08, 0x31, 0x48, 0x2a, 0xc9, 0x19, + 0x40, 0x09, 0x7a, 0x0f, 0x15, 0x08, 0x28, 0x07, 0x4f, 0x02, 0x55, 0xf2, + 0x1b, 0xf7, 0xf7, 0xf2, 0x91, 0xe3, 0x23, 0xdd, 0xf8, 0xda, 0xc8, 0xd8, + 0x2a, 0xd6, 0x16, 0xce, 0x2c, 0xcf, 0xd8, 0xd2, 0x35, 0xca, 0x06, 0xcd, + 0x29, 0xcc, 0x5f, 0xc9, 0x05, 0xcc, 0x94, 0xc4, 0xca, 0xc3, 0xb7, 0xc6, + 0x5f, 0xc7, 0x8c, 0xca, 0x96, 0xce, 0x18, 0xd3, 0xc1, 0xd3, 0x45, 0xcb, + 0xfc, 0xc6, 0x68, 0xc7, 0x59, 0xc2, 0xfa, 0xc1, 0x17, 0xbe, 0xd4, 0xc0, + 0xd2, 0xc9, 0xd8, 0xc4, 0xd4, 0xc7, 0xd4, 0xd4, 0xab, 0xdf, 0x87, 0xe7, + 0x0a, 0xec, 0x95, 0xf8, 0xf0, 0x03, 0xd0, 0x03, 0x72, 0x05, 0xd1, 0x04, + 0xbe, 0x04, 0xa5, 0x07, 0xf7, 0x01, 0x27, 0xfb, 0x8c, 0xf5, 0x39, 0xf4, + 0x7c, 0xf6, 0x84, 0xf5, 0x45, 0xf8, 0xae, 0xff, 0x14, 0x07, 0xcf, 0x09, + 0xf5, 0x09, 0xbd, 0x0b, 0x01, 0x16, 0x4f, 0x22, 0x2b, 0x25, 0xc1, 0x22, + 0x45, 0x20, 0x6a, 0x28, 0xee, 0x2d, 0x71, 0x2c, 0x0f, 0x2f, 0x2e, 0x2b, + 0x46, 0x2a, 0xe9, 0x2c, 0x0e, 0x25, 0x14, 0x26, 0x8a, 0x2d, 0x08, 0x27, + 0x77, 0x22, 0x61, 0x20, 0x21, 0x1c, 0xf0, 0x17, 0xe3, 0x11, 0x07, 0x10, + 0x58, 0x0a, 0x05, 0x06, 0x22, 0x00, 0x9e, 0xfb, 0x76, 0x02, 0x32, 0x08, + 0x1a, 0x0a, 0xa8, 0x03, 0x0f, 0x01, 0x7b, 0x06, 0x9c, 0x05, 0xaf, 0xfb, + 0x0b, 0xee, 0x38, 0xde, 0x6f, 0xc7, 0xc1, 0xb6, 0x3e, 0xaf, 0x0e, 0xac, + 0x81, 0xac, 0x66, 0xa9, 0x6e, 0xa6, 0xaa, 0xa7, 0x57, 0xaa, 0xac, 0xb1, + 0xb4, 0xb6, 0xe4, 0xb8, 0x53, 0xbc, 0x88, 0xb8, 0xd9, 0xb8, 0xf5, 0xb9, + 0xdb, 0xba, 0xa0, 0xbe, 0xaf, 0xb8, 0x05, 0xb4, 0xa5, 0xb1, 0x6d, 0xb4, + 0x00, 0xbf, 0xf7, 0xc4, 0xba, 0xc5, 0x32, 0xc6, 0x69, 0xc7, 0x54, 0xca, + 0xae, 0xd1, 0xe0, 0xd5, 0xb5, 0xd9, 0x3c, 0xdd, 0xe5, 0xdf, 0xd5, 0xe7, + 0xe7, 0xea, 0x27, 0xef, 0x43, 0xf6, 0x5d, 0xfa, 0x7e, 0xfc, 0x23, 0xff, + 0xd4, 0x07, 0x14, 0x0f, 0x41, 0x18, 0xc7, 0x1c, 0x99, 0x1c, 0x1d, 0x21, + 0x0b, 0x25, 0x3f, 0x2b, 0x17, 0x24, 0x28, 0x18, 0x5d, 0x16, 0x3d, 0x11, + 0x83, 0x04, 0x0b, 0xf7, 0x88, 0xf0, 0x77, 0xef, 0xcc, 0xf5, 0xb4, 0xf4, + 0x37, 0xf0, 0x59, 0xef, 0x51, 0xed, 0x6e, 0xfb, 0xd6, 0x02, 0xe9, 0xff, + 0x06, 0x01, 0x27, 0xfa, 0x17, 0x01, 0x92, 0x0c, 0x2e, 0x08, 0x1f, 0x0b, + 0x82, 0x08, 0xbb, 0x04, 0xe9, 0x10, 0x5e, 0x0e, 0x34, 0x0b, 0xfe, 0x07, + 0xab, 0xf8, 0x4f, 0xfd, 0x26, 0xfb, 0x2e, 0xf1, 0x51, 0xf5, 0x1f, 0xf0, + 0x3d, 0xf2, 0x1f, 0xfb, 0x5d, 0x00, 0x74, 0x0c, 0x9a, 0x1c, 0x5e, 0x27, + 0x1b, 0x27, 0x8e, 0x24, 0xeb, 0x23, 0x46, 0x2e, 0xb5, 0x35, 0xd0, 0x31, + 0x64, 0x2b, 0x27, 0x1e, 0x4b, 0x18, 0xa4, 0x1e, 0xe6, 0x21, 0x3d, 0x1e, + 0x2a, 0x1e, 0x83, 0x12, 0xbb, 0x0b, 0x30, 0x0b, 0x46, 0xff, 0x8a, 0xfc, + 0x56, 0xec, 0xb0, 0xe3, 0x5a, 0xe3, 0x55, 0xd4, 0xde, 0xd1, 0x43, 0xd1, + 0x97, 0xcf, 0x1c, 0xd1, 0x32, 0xcd, 0xb7, 0xca, 0x80, 0xd4, 0x4b, 0xda, + 0xbe, 0xdc, 0x39, 0xde, 0xf5, 0xd8, 0x51, 0xde, 0x1c, 0xe3, 0xd7, 0xdd, + 0x23, 0xd4, 0x00, 0xd1, 0xe6, 0xca, 0x0a, 0xc3, 0xb2, 0xc0, 0x93, 0xbb, + 0x72, 0xbb, 0xee, 0xba, 0x57, 0xb7, 0x90, 0xb4, 0xf3, 0xb9, 0x5e, 0xbd, + 0xb4, 0xc8, 0x92, 0xd7, 0xfa, 0xda, 0x81, 0xeb, 0x42, 0xf7, 0x2a, 0x00, + 0x8d, 0x11, 0x34, 0x19, 0x2a, 0x1c, 0x40, 0x23, 0x00, 0x27, 0xa3, 0x2f, + 0xa8, 0x37, 0x0e, 0x35, 0xbb, 0x3a, 0xf4, 0x3c, 0xed, 0x3e, 0x0c, 0x41, + 0x1b, 0x3b, 0xf5, 0x34, 0x6f, 0x32, 0xd9, 0x37, 0xb4, 0x3e, 0xb5, 0x42, + 0x9e, 0x3e, 0x42, 0x3f, 0x31, 0x41, 0x2d, 0x44, 0x00, 0x4e, 0xba, 0x52, + 0xe0, 0x54, 0x74, 0x4f, 0x37, 0x45, 0x64, 0x3b, 0x45, 0x31, 0xa2, 0x25, + 0x68, 0x15, 0xc6, 0x04, 0xdb, 0xf5, 0xd9, 0xed, 0xa4, 0xe9, 0x76, 0xdd, + 0xaa, 0xd8, 0x04, 0xdd, 0x73, 0xe1, 0x43, 0xe5, 0x5a, 0xdd, 0x59, 0xdb, + 0xcf, 0xdd, 0x3b, 0xdb, 0xd4, 0xd8, 0x7a, 0xd4, 0x7f, 0xd5, 0x50, 0xda, + 0x2e, 0xdd, 0x81, 0xda, 0x1b, 0xd9, 0xb4, 0xde, 0x42, 0xe5, 0xee, 0xe4, + 0xb7, 0xdf, 0x3f, 0xd8, 0xfd, 0xd3, 0x7b, 0xd6, 0x5e, 0xd4, 0x18, 0xd0, + 0xf9, 0xcd, 0x69, 0xc9, 0xf9, 0xc8, 0xb3, 0xcb, 0x3d, 0xc4, 0x85, 0xc6, + 0x85, 0xcc, 0xc2, 0xcd, 0x2e, 0xd8, 0x3a, 0xd6, 0x72, 0xd9, 0x35, 0xe3, + 0x18, 0xe9, 0x4d, 0xfa, 0x6c, 0x02, 0x48, 0x00, 0x4d, 0x03, 0xa6, 0x05, + 0x36, 0x07, 0x9a, 0x0a, 0xb2, 0x02, 0x2a, 0xf8, 0xd1, 0xf7, 0x2c, 0xf4, + 0x83, 0xf4, 0x7e, 0xf8, 0xb7, 0xf5, 0x3b, 0xfa, 0xa7, 0xfb, 0x6a, 0xfc, + 0x79, 0x06, 0x79, 0x0c, 0x1d, 0x17, 0xa2, 0x1b, 0x4b, 0x1d, 0x46, 0x27, + 0x36, 0x28, 0x85, 0x2e, 0x51, 0x39, 0x6c, 0x3d, 0x97, 0x46, 0x3b, 0x4b, + 0xc4, 0x4e, 0x96, 0x56, 0xcb, 0x58, 0x96, 0x5b, 0x90, 0x5a, 0x14, 0x56, + 0xc1, 0x59, 0x0b, 0x5d, 0x42, 0x5a, 0xa4, 0x5c, 0x18, 0x5b, 0x26, 0x5a, + 0xf3, 0x59, 0xce, 0x4b, 0x86, 0x4a, 0xa8, 0x46, 0x7e, 0x37, 0x00, 0x2a, + 0xd6, 0x1b, 0x75, 0x1c, 0x71, 0x1e, 0x57, 0x24, 0xe8, 0x2d, 0x96, 0x2a, + 0x57, 0x23, 0xa2, 0x1a, 0xb2, 0x13, 0x31, 0x19, 0xdf, 0x1d, 0xcd, 0x15, + 0x4d, 0x09, 0xad, 0xfe, 0x6e, 0xf5, 0xf8, 0xe5, 0xd2, 0xdc, 0x71, 0xd9, + 0xa0, 0xdb, 0x6b, 0xd8, 0xd2, 0xc5, 0xe3, 0xcb, 0xa9, 0xd0, 0x12, 0xcb, + 0xd5, 0xcf, 0x5f, 0xcb, 0xa4, 0xd4, 0x33, 0xdb, 0x04, 0xd9, 0x28, 0xec, + 0x15, 0xf2, 0x30, 0xf7, 0xf1, 0x08, 0x73, 0x0d, 0x78, 0x1a, 0x77, 0x1d, + 0x2a, 0x13, 0x87, 0x19, 0xa5, 0x1f, 0x68, 0x26, 0x87, 0x2e, 0xaf, 0x30, + 0xe7, 0x2e, 0xcc, 0x2d, 0x1b, 0x35, 0xd7, 0x3a, 0x65, 0x3b, 0x96, 0x3e, + 0x9a, 0x3f, 0x72, 0x43, 0xb6, 0x4c, 0x90, 0x4b, 0x98, 0x50, 0xaf, 0x5a, + 0xf9, 0x5a, 0x3b, 0x61, 0xd5, 0x60, 0x3d, 0x60, 0xe8, 0x65, 0x2c, 0x5f, + 0xf4, 0x5a, 0xc4, 0x5a, 0x36, 0x57, 0x1c, 0x57, 0xeb, 0x4e, 0x4c, 0x43, + 0x70, 0x42, 0x04, 0x40, 0xd7, 0x3b, 0x2a, 0x33, 0xb6, 0x27, 0x74, 0x25, + 0x44, 0x1f, 0xf6, 0x19, 0xc1, 0x19, 0x0b, 0x1a, 0x2f, 0x1f, 0xcc, 0x20, + 0x83, 0x21, 0xf3, 0x21, 0x4c, 0x1f, 0x7c, 0x1f, 0xda, 0x1a, 0x1a, 0x0c, + 0xec, 0xfb, 0x4c, 0xef, 0x4f, 0xe6, 0x02, 0xe4, 0x46, 0xe3, 0x37, 0xdc, + 0x39, 0xd9, 0x5b, 0xe0, 0xdf, 0xe9, 0x98, 0xf2, 0x92, 0xf8, 0x71, 0xf8, + 0xc9, 0xf8, 0x1a, 0x03, 0x9b, 0x08, 0x33, 0x04, 0xf2, 0x01, 0xef, 0xfd, + 0x1a, 0xfd, 0x57, 0x00, 0x48, 0xfd, 0x7d, 0xfc, 0xa2, 0x03, 0xe3, 0x07, + 0x71, 0x09, 0x69, 0x08, 0x13, 0x05, 0x48, 0x0c, 0x54, 0x0e, 0xf4, 0x07, + 0x8c, 0x05, 0x0f, 0x00, 0x8f, 0x02, 0x0b, 0x00, 0x8c, 0xf7, 0x60, 0xfc, + 0xa1, 0xff, 0x15, 0x02, 0xf9, 0x02, 0xa3, 0x05, 0x31, 0x0b, 0xdb, 0x0b, + 0x7b, 0x0d, 0x95, 0x0e, 0x61, 0x18, 0x9d, 0x21, 0x36, 0x24, 0x4d, 0x28, + 0x59, 0x27, 0x14, 0x23, 0xe6, 0x1f, 0x1a, 0x1e, 0xaf, 0x14, 0x07, 0x14, + 0x2e, 0x15, 0x70, 0x0b, 0x7d, 0x10, 0xef, 0x11, 0x07, 0x14, 0xf9, 0x1c, + 0x9b, 0x18, 0xde, 0x22, 0x83, 0x27, 0x43, 0x19, 0x9b, 0x20, 0x82, 0x21, + 0xe9, 0x1a, 0x06, 0x1e, 0x1a, 0x15, 0x9f, 0x1a, 0xed, 0x1e, 0xe6, 0x10, + 0x03, 0x15, 0x02, 0x1c, 0x91, 0x1b, 0xe7, 0x18, 0xf8, 0x0d, 0xb8, 0x10, + 0xbc, 0x1b, 0xa6, 0x1f, 0x76, 0x1f, 0x57, 0x14, 0xd1, 0x11, 0xa5, 0x1a, + 0xc9, 0x1e, 0x85, 0x1f, 0x5f, 0x1d, 0xda, 0x19, 0xf8, 0x16, 0x7b, 0x1e, + 0x47, 0x28, 0xf6, 0x27, 0x1d, 0x1d, 0x70, 0x12, 0xff, 0x11, 0x7e, 0x15, + 0x4d, 0x13, 0xdc, 0xff, 0x8b, 0xfb, 0xee, 0x04, 0x75, 0xff, 0x92, 0x01, + 0x6c, 0xfe, 0xc6, 0xfb, 0x6d, 0x05, 0x67, 0x02, 0xc6, 0xfd, 0x2b, 0xf9, + 0xb6, 0xf2, 0x39, 0xf3, 0xee, 0xee, 0x24, 0xee, 0xe6, 0xf2, 0xd8, 0xeb, + 0xfd, 0xe7, 0x70, 0xe5, 0xc2, 0xdc, 0xf2, 0xe0, 0xcf, 0xe2, 0x3c, 0xe1, + 0xab, 0xe5, 0x71, 0xd7, 0x94, 0xcf, 0x51, 0xd8, 0x07, 0xd7, 0x8c, 0xde, + 0x32, 0xcf, 0x3e, 0xba, 0x2c, 0xc1, 0x98, 0xb8, 0xe4, 0xc1, 0xd9, 0xc9, + 0xfd, 0xc2, 0xe1, 0xc8, 0xd0, 0xbd, 0xb1, 0xba, 0x70, 0xc5, 0x33, 0xcc, + 0x48, 0xd1, 0x1d, 0xd1, 0xb3, 0xcb, 0xeb, 0xc9, 0x40, 0xce, 0xce, 0xd4, + 0xa1, 0xde, 0x2f, 0xdf, 0xa4, 0xda, 0x4d, 0xd5, 0x96, 0xd8, 0x82, 0xe2, + 0x53, 0xe6, 0xfa, 0xec, 0x8c, 0xea, 0xe8, 0xe8, 0xae, 0xf4, 0x00, 0xf7, + 0x1e, 0xf7, 0xb6, 0xfd, 0x43, 0x04, 0x25, 0x10, 0xb6, 0x19, 0x64, 0x22, + 0xa4, 0x30, 0xe4, 0x3b, 0x18, 0x41, 0x6a, 0x47, 0xf1, 0x4e, 0xca, 0x54, + 0x64, 0x5a, 0x4b, 0x50, 0x85, 0x3f, 0x80, 0x33, 0x53, 0x2a, 0xd6, 0x24, + 0xe5, 0x16, 0xfb, 0x0a, 0x59, 0x01, 0xe3, 0xf9, 0x9f, 0xfc, 0x45, 0x01, + 0x9c, 0x08, 0x32, 0x10, 0x6b, 0x12, 0x32, 0x0d, 0x86, 0x08, 0x98, 0x09, + 0xf5, 0x09, 0x70, 0x09, 0x18, 0x04, 0x87, 0xfa, 0x50, 0xf1, 0xea, 0xe7, + 0x30, 0xe4, 0xc4, 0xe2, 0x2a, 0xe0, 0xff, 0xdc, 0x85, 0xd3, 0xcd, 0xc9, + 0xb3, 0xc3, 0x76, 0xc0, 0xc3, 0xbf, 0xbb, 0xbd, 0x23, 0xba, 0xe9, 0xb4, + 0x73, 0xb1, 0x61, 0xb4, 0x84, 0xb7, 0x8c, 0xba, 0x3a, 0xbe, 0x2d, 0xbb, + 0xbb, 0xb6, 0x8d, 0xb5, 0x1a, 0xba, 0x20, 0xc4, 0x76, 0xca, 0x46, 0xc9, + 0x24, 0xc7, 0x78, 0xcb, 0x46, 0xd6, 0xd6, 0xe0, 0x5b, 0xe1, 0x92, 0xdf, + 0x1b, 0xdf, 0xb9, 0xda, 0x4f, 0xd9, 0xc6, 0xd6, 0x19, 0xd6, 0x3e, 0xd6, + 0xee, 0xd1, 0x01, 0xd9, 0xa8, 0xe2, 0x2e, 0xec, 0x5a, 0xf9, 0xfe, 0xfb, + 0xf4, 0x03, 0x19, 0x0c, 0xb4, 0x0c, 0x07, 0x15, 0xe8, 0x1b, 0x12, 0x26, + 0x36, 0x29, 0x9b, 0x1d, 0x6d, 0x1e, 0x2f, 0x23, 0x93, 0x21, 0xad, 0x1c, + 0x9e, 0x14, 0x9d, 0x10, 0xa1, 0x0b, 0x0b, 0x0a, 0x5f, 0x0c, 0xe7, 0x0d, + 0x05, 0x0c, 0xef, 0x00, 0x67, 0xff, 0xf7, 0x05, 0xc5, 0x0b, 0x5a, 0x13, + 0xbb, 0x0d, 0xfb, 0x09, 0xb5, 0x0d, 0x91, 0x09, 0xfc, 0x0a, 0xf7, 0x0d, + 0xe4, 0x0d, 0x07, 0x0d, 0xd6, 0x08, 0xd4, 0x0e, 0xea, 0x16, 0xa0, 0x16, + 0xea, 0x17, 0xa9, 0x1e, 0xfe, 0x21, 0x3d, 0x1b, 0xb3, 0x0b, 0x5d, 0xf6, + 0x38, 0xe9, 0xb2, 0xe2, 0xe5, 0xd7, 0xd8, 0xc9, 0x90, 0xc0, 0xa4, 0xc1, + 0xc6, 0xc4, 0x68, 0xca, 0xde, 0xcf, 0xee, 0xd5, 0xcb, 0xdf, 0xfd, 0xdf, + 0x45, 0xdf, 0x50, 0xdf, 0x5e, 0xd9, 0x7b, 0xe0, 0x22, 0xe2, 0xe7, 0xd6, + 0x3e, 0xd8, 0x6d, 0xd0, 0xcf, 0xc4, 0xfb, 0xc7, 0x6a, 0xc1, 0xdd, 0xc1, + 0x68, 0xc6, 0xe5, 0xb4, 0x9a, 0xb3, 0xfd, 0xb5, 0xf9, 0xb7, 0x48, 0xc4, + 0xcf, 0xb7, 0x1d, 0xb7, 0x95, 0xbd, 0x48, 0xc1, 0x11, 0xce, 0xa7, 0xca, + 0xfe, 0xcb, 0xd2, 0xd1, 0xc2, 0xdb, 0x3b, 0xe1, 0x6e, 0xdc, 0x09, 0xdf, + 0x90, 0xe2, 0x89, 0xe6, 0x1f, 0xee, 0xf4, 0xf6, 0x62, 0xf7, 0xce, 0xfa, + 0x79, 0xf6, 0xa3, 0xec, 0xa3, 0xef, 0xed, 0xf0, 0xdf, 0xf3, 0x76, 0xf0, + 0x39, 0xea, 0x8d, 0xe9, 0x24, 0xec, 0x3f, 0xf1, 0xdc, 0xf8, 0x6a, 0x04, + 0xb6, 0x0d, 0x49, 0x16, 0xff, 0x1b, 0x84, 0x25, 0x91, 0x30, 0x61, 0x37, + 0xde, 0x35, 0x8b, 0x28, 0x70, 0x18, 0x1e, 0x0a, 0x07, 0x00, 0xf0, 0xf3, + 0x03, 0xe5, 0x14, 0xd5, 0x84, 0xce, 0x9b, 0xce, 0xf6, 0xcb, 0x3a, 0xd1, + 0xb7, 0xdd, 0xf8, 0xe4, 0xa8, 0xe3, 0xa7, 0xe1, 0xc3, 0xdd, 0x27, 0xe3, + 0x4a, 0xec, 0x47, 0xec, 0xb1, 0xe9, 0x55, 0xdf, 0x01, 0xda, 0x8e, 0xdd, + 0xe1, 0xe0, 0x8f, 0xe2, 0x3a, 0xe2, 0xbe, 0xe3, 0x2d, 0xe1, 0xb9, 0xda, + 0xdf, 0xda, 0x54, 0xdf, 0x13, 0xe2, 0x9a, 0xdf, 0x2e, 0xd7, 0x75, 0xd4, + 0x85, 0xd8, 0xfe, 0xd9, 0x1b, 0xdc, 0x4a, 0xde, 0x89, 0xe0, 0xdf, 0xe4, + 0xf3, 0xe4, 0xa2, 0xea, 0xc7, 0xf4, 0x52, 0xfb, 0x78, 0x00, 0xe2, 0xff, + 0x6e, 0x09, 0x04, 0x18, 0x0d, 0x1f, 0xc9, 0x22, 0xe3, 0x1c, 0x82, 0x16, + 0xe9, 0x12, 0xc4, 0x0b, 0xec, 0x00, 0x7d, 0xf3, 0x0c, 0xeb, 0xe1, 0xe9, + 0x88, 0xe9, 0xde, 0xe7, 0xb0, 0xe9, 0x88, 0xf4, 0x87, 0xfc, 0x38, 0xfb, + 0x40, 0xfd, 0xe1, 0xff, 0xa1, 0xfd, 0x3f, 0xfb, 0xfe, 0xfa, 0x2e, 0xf8, + 0x13, 0xf5, 0x0d, 0xf2, 0x73, 0xee, 0x86, 0xed, 0xa5, 0xe5, 0x96, 0xe2, + 0xa1, 0xeb, 0x23, 0xf2, 0x9c, 0xed, 0xec, 0xe5, 0xc6, 0xe1, 0xeb, 0xdd, + 0xfb, 0xde, 0x47, 0xdd, 0xae, 0xe4, 0x66, 0xeb, 0xa4, 0xe4, 0x63, 0xe7, + 0x73, 0xe5, 0x0c, 0xea, 0x0c, 0xf7, 0x8a, 0xf8, 0x3c, 0xfb, 0x9a, 0xf8, + 0xec, 0xf9, 0xd9, 0x04, 0xb7, 0x0d, 0x0f, 0x18, 0x9f, 0x27, 0x69, 0x3a, + 0xc8, 0x34, 0x0e, 0x28, 0xfe, 0x27, 0x8c, 0x26, 0x93, 0x33, 0x87, 0x29, + 0xe7, 0x0e, 0xe1, 0x0a, 0x28, 0x00, 0xa2, 0xff, 0xae, 0x04, 0x14, 0x02, + 0xbe, 0x0b, 0xf3, 0x0b, 0xf5, 0xfb, 0x83, 0xf6, 0x89, 0xfc, 0x8c, 0x0a, + 0xd9, 0x1a, 0xe9, 0x0b, 0x87, 0xfe, 0x03, 0x08, 0x0d, 0x0c, 0x4b, 0x18, + 0xdf, 0x18, 0x20, 0x0f, 0xe9, 0x0e, 0x6a, 0x04, 0x83, 0xfe, 0x7b, 0x03, + 0xe2, 0x01, 0x44, 0x00, 0x66, 0xf9, 0xa2, 0xeb, 0x81, 0xec, 0xf8, 0xf3, + 0x68, 0xf8, 0xc2, 0xfd, 0x9c, 0xfe, 0x65, 0xf9, 0x84, 0xfa, 0xa6, 0x05, + 0x4d, 0x07, 0x4a, 0x05, 0x11, 0x05, 0xf8, 0x03, 0x85, 0x09, 0x3a, 0x0a, + 0xc8, 0x0c, 0x9f, 0x18, 0xef, 0x1d, 0x0f, 0x26, 0xf2, 0x2d, 0x30, 0x2c, + 0xc4, 0x2e, 0x72, 0x2c, 0x87, 0x25, 0x16, 0x22, 0xd6, 0x24, 0x09, 0x2c, + 0x1a, 0x28, 0x57, 0x27, 0xa1, 0x2d, 0xcd, 0x35, 0x81, 0x43, 0xf3, 0x46, + 0x7a, 0x46, 0xdc, 0x49, 0xb8, 0x48, 0xbc, 0x46, 0x46, 0x3e, 0x23, 0x35, + 0x2b, 0x33, 0x51, 0x2a, 0x44, 0x20, 0x86, 0x1b, 0x9f, 0x16, 0xf0, 0x13, + 0x58, 0x10, 0x07, 0x10, 0x0d, 0x1d, 0x4d, 0x29, 0x72, 0x2d, 0xeb, 0x2e, + 0x76, 0x29, 0xd6, 0x24, 0x0e, 0x26, 0xbe, 0x27, 0x9d, 0x23, 0x16, 0x1d, + 0xf7, 0x18, 0x7f, 0x13, 0x93, 0x0e, 0x26, 0x0c, 0xd5, 0x0e, 0x93, 0x11, + 0x8b, 0x11, 0x60, 0x0e, 0x39, 0x0b, 0x8e, 0x0d, 0x45, 0x0e, 0x84, 0x0e, + 0xad, 0x0b, 0xc2, 0x05, 0x11, 0x08, 0x67, 0x0b, 0x71, 0x0c, 0x9f, 0x0e, + 0x47, 0x0d, 0x02, 0x0d, 0x12, 0x0b, 0xc1, 0x07, 0x0f, 0x0a, 0xa2, 0x0c, + 0xe0, 0x0f, 0xe4, 0x11, 0x0f, 0x15, 0xb6, 0x1a, 0x1b, 0x1f, 0x41, 0x23, + 0x40, 0x25, 0x61, 0x28, 0xe7, 0x2a, 0x47, 0x29, 0x8a, 0x22, 0x39, 0x1e, + 0x34, 0x1d, 0x0d, 0x1a, 0x25, 0x1a, 0x36, 0x15, 0x14, 0x16, 0x7b, 0x1f, + 0xdf, 0x25, 0xd9, 0x30, 0x14, 0x36, 0xc2, 0x38, 0xb0, 0x3c, 0x47, 0x3a, + 0x10, 0x38, 0x7e, 0x36, 0x6d, 0x35, 0xc6, 0x34, 0xd3, 0x34, 0xb5, 0x35, + 0x86, 0x32, 0x1e, 0x2d, 0x17, 0x2d, 0x3e, 0x2d, 0x83, 0x2d, 0xac, 0x2e, + 0x82, 0x29, 0x2c, 0x25, 0x40, 0x1e, 0xe3, 0x19, 0x28, 0x1f, 0x0e, 0x22, + 0x59, 0x22, 0x91, 0x20, 0x6b, 0x1e, 0xcd, 0x20, 0xcf, 0x23, 0x42, 0x26, + 0xbe, 0x25, 0x72, 0x21, 0x29, 0x21, 0xe1, 0x1f, 0x0a, 0x19, 0x1a, 0x14, + 0xb0, 0x18, 0xb8, 0x1f, 0x3d, 0x1f, 0x7f, 0x1f, 0x04, 0x1a, 0x2d, 0x17, + 0x49, 0x17, 0x4f, 0x06, 0x24, 0xfd, 0x5a, 0xfb, 0xc9, 0xef, 0xb3, 0xe8, + 0x66, 0xdf, 0xa7, 0xd9, 0x03, 0xe4, 0x4b, 0xe6, 0x23, 0xe7, 0xec, 0xf4, + 0x51, 0xf9, 0x50, 0xfe, 0x60, 0x03, 0x7b, 0x00, 0xd3, 0x0b, 0x6c, 0x09, + 0x7e, 0xff, 0x67, 0x02, 0xe4, 0xf7, 0x15, 0xf2, 0xfc, 0xeb, 0x86, 0xdf, + 0x1e, 0xdf, 0x01, 0xdb, 0x54, 0xd5, 0x6f, 0xd9, 0x18, 0xd8, 0x1b, 0xd8, + 0xf5, 0xe4, 0xc6, 0xe8, 0xc6, 0xe8, 0x53, 0xea, 0xbd, 0xec, 0x2b, 0xf9, + 0x05, 0xfe, 0x6b, 0xfc, 0x77, 0x02, 0x1a, 0x02, 0x46, 0x01, 0x96, 0x0b, + 0xc0, 0x08, 0xe1, 0x0a, 0x43, 0x15, 0x12, 0x17, 0x69, 0x1f, 0xfd, 0x1c, + 0x00, 0x1f, 0xcd, 0x2a, 0x22, 0x27, 0x69, 0x1b, 0xcc, 0x14, 0xae, 0x17, + 0xd0, 0x16, 0xf8, 0x17, 0xfc, 0x16, 0x3e, 0x15, 0x79, 0x23, 0x11, 0x27, + 0x33, 0x28, 0x03, 0x36, 0x9a, 0x3d, 0x81, 0x46, 0xe3, 0x4a, 0xd0, 0x46, + 0x31, 0x45, 0xd2, 0x39, 0xf6, 0x2e, 0x75, 0x26, 0x0c, 0x17, 0xc8, 0x10, + 0x1c, 0x0a, 0x77, 0x00, 0x6b, 0xf5, 0x84, 0xec, 0x7a, 0xf3, 0x36, 0xfa, + 0xb8, 0xff, 0x88, 0x01, 0x35, 0x00, 0xbf, 0x05, 0xeb, 0x07, 0xfb, 0x08, + 0x42, 0x0c, 0x3b, 0x0c, 0x6b, 0x06, 0xf2, 0x01, 0x7e, 0xfc, 0x17, 0xfb, + 0x3d, 0x00, 0xad, 0x02, 0xa6, 0x04, 0xfd, 0xff, 0x99, 0xfe, 0xef, 0x02, + 0x6b, 0x02, 0x59, 0x01, 0x59, 0xfe, 0xee, 0xfa, 0xf7, 0xfa, 0xf7, 0xf9, + 0x39, 0xf7, 0xd1, 0xf5, 0xe4, 0xf6, 0x7e, 0xfc, 0x47, 0xfd, 0xae, 0xfa, + 0x5d, 0xfc, 0x42, 0x01, 0xb7, 0x09, 0x45, 0x0e, 0xd4, 0x11, 0xf3, 0x1a, + 0x99, 0x22, 0xf6, 0x24, 0x2a, 0x2b, 0x66, 0x31, 0xc5, 0x2f, 0xf0, 0x2b, + 0x40, 0x27, 0x13, 0x22, 0xa4, 0x1b, 0x6a, 0x17, 0xd0, 0x13, 0xe9, 0x0d, + 0x96, 0x0e, 0x3a, 0x10, 0x51, 0x0f, 0x15, 0x18, 0xbf, 0x25, 0x6a, 0x2d, + 0x54, 0x2e, 0x9e, 0x31, 0x6c, 0x3a, 0x74, 0x3b, 0x4e, 0x3d, 0x89, 0x3f, + 0x7f, 0x38, 0x30, 0x32, 0x18, 0x2d, 0x8d, 0x31, 0xa0, 0x36, 0x8c, 0x2b, + 0x12, 0x25, 0x03, 0x2a, 0x35, 0x2b, 0x15, 0x23, 0xa0, 0x1a, 0xeb, 0x18, + 0xc1, 0x17, 0x4c, 0x15, 0x39, 0x16, 0x61, 0x19, 0xea, 0x17, 0xcb, 0x17, + 0x9a, 0x16, 0xa1, 0x0e, 0xe1, 0x10, 0x3f, 0x19, 0x7c, 0x1e, 0x49, 0x1a, + 0x49, 0x09, 0xdb, 0x08, 0x0c, 0x1d, 0xce, 0x2d, 0xf6, 0x2c, 0x88, 0x22, + 0x6a, 0x21, 0xdc, 0x26, 0x6c, 0x2e, 0x73, 0x2e, 0xf1, 0x24, 0xe9, 0x15, + 0x48, 0x06, 0x13, 0xff, 0x78, 0xf0, 0x1e, 0xe9, 0x1f, 0xed, 0x9c, 0xed, + 0x2a, 0xf2, 0x1b, 0xec, 0xfa, 0xee, 0x29, 0x01, 0x48, 0x0b, 0xb2, 0x12, + 0xc7, 0x0f, 0x5b, 0x11, 0x5e, 0x1e, 0xaf, 0x1c, 0xbb, 0x16, 0x1b, 0x17, + 0x5d, 0x1d, 0x0e, 0x20, 0x2b, 0x12, 0xdd, 0x05, 0x22, 0xfe, 0x2d, 0xfc, + 0x33, 0xfe, 0x05, 0xf3, 0xce, 0xe7, 0x4c, 0xe2, 0x41, 0xe0, 0xc0, 0xe3, + 0x73, 0xe0, 0xea, 0xda, 0xe0, 0xdf, 0x24, 0xe9, 0x4f, 0xee, 0x6b, 0xed, + 0x69, 0xed, 0x0d, 0xf8, 0x74, 0xfe, 0xc0, 0xfe, 0x95, 0x02, 0x60, 0x00, + 0x8a, 0x01, 0xb2, 0x06, 0xac, 0x04, 0x41, 0x02, 0x11, 0x02, 0x9e, 0x07, + 0xb6, 0x08, 0x05, 0x00, 0xe3, 0xfe, 0xd9, 0x02, 0xde, 0x03, 0x86, 0x00, + 0xe6, 0xf7, 0x8a, 0xfb, 0x2d, 0x04, 0x2d, 0x05, 0x76, 0x0a, 0x12, 0x08, + 0xb8, 0x06, 0x3d, 0x0a, 0xb0, 0x06, 0x52, 0x03, 0xb4, 0xfd, 0x20, 0xfd, + 0x9e, 0xfa, 0xdf, 0xf7, 0x5c, 0xfc, 0x93, 0xff, 0x25, 0x00, 0x3a, 0x07, + 0xb3, 0x14, 0xb5, 0x12, 0xd4, 0x0f, 0x9c, 0x0f, 0xdc, 0x0f, 0x99, 0x0b, + 0x74, 0xff, 0xf5, 0xff, 0x63, 0xfa, 0x83, 0xf3, 0xa4, 0xef, 0xa3, 0xe1, + 0x1c, 0xde, 0xa9, 0xe7, 0xbd, 0xeb, 0x35, 0xee, 0x58, 0xef, 0x18, 0xef, + 0x6a, 0xf6, 0xdd, 0xf5, 0xbf, 0xf4, 0xe6, 0xf5, 0x15, 0xf9, 0x86, 0xfc, + 0xbc, 0xf6, 0x12, 0xf5, 0x44, 0xf6, 0xff, 0xf6, 0xf1, 0xf1, 0x8d, 0xee, + 0x8d, 0xee, 0x8a, 0xf1, 0xeb, 0xf3, 0x74, 0xeb, 0x84, 0xe7, 0x3e, 0xec, + 0x9e, 0xf6, 0x7d, 0xf7, 0x79, 0xf3, 0xfd, 0xf6, 0x9f, 0xf7, 0xa4, 0xf8, + 0x2b, 0xfb, 0x05, 0xfd, 0x5d, 0xfa, 0xad, 0xf3, 0x6a, 0xf4, 0xf6, 0xf9, + 0xa6, 0xfa, 0x2c, 0xfe, 0x3c, 0x00, 0x8d, 0x03, 0xb5, 0x0b, 0xe2, 0x0e, + 0x45, 0x15, 0x69, 0x1a, 0x0f, 0x13, 0x11, 0x09, 0x28, 0x0e, 0x4d, 0x12, + 0x93, 0x0d, 0x80, 0x09, 0x0e, 0x05, 0xd0, 0x05, 0x63, 0x04, 0x81, 0x05, + 0xa2, 0x09, 0x0b, 0x08, 0x48, 0x07, 0x2b, 0x0b, 0x3f, 0x0e, 0x9d, 0x09, + 0xf6, 0x02, 0x68, 0x05, 0x51, 0x0d, 0x2a, 0x0b, 0xbc, 0x04, 0xa7, 0x03, + 0xe9, 0x05, 0x39, 0xfe, 0x07, 0xf7, 0x84, 0x00, 0x32, 0x03, 0xba, 0xfc, + 0x4d, 0xf7, 0xb2, 0xf6, 0xf7, 0xfc, 0x9d, 0x01, 0x07, 0x01, 0xd0, 0x02, + 0xf2, 0x04, 0x23, 0x00, 0x41, 0x01, 0x92, 0x08, 0xa4, 0x09, 0x46, 0x04, + 0xe7, 0x02, 0x89, 0xff, 0x4c, 0xf6, 0x63, 0xef, 0x59, 0xe7, 0xa7, 0xe0, + 0x64, 0xda, 0x38, 0xd7, 0x42, 0xd6, 0x7d, 0xd0, 0x04, 0xc8, 0x76, 0xc4, + 0x4e, 0xcb, 0xb3, 0xd1, 0x21, 0xd5, 0x11, 0xd8, 0x81, 0xd7, 0x81, 0xd5, + 0x56, 0xd7, 0xa2, 0xd9, 0xb0, 0xd9, 0xd9, 0xd8, 0x49, 0xd8, 0x1e, 0xd8, + 0x8f, 0xce, 0x71, 0xc5, 0xbd, 0xc6, 0x78, 0xcd, 0xbf, 0xd1, 0xfd, 0xcc, + 0x19, 0xc7, 0x33, 0xc2, 0x81, 0xc3, 0x11, 0xcc, 0x6a, 0xcb, 0xe6, 0xc1, + 0xde, 0xc0, 0xfb, 0xc5, 0x23, 0xc8, 0xe6, 0xc3, 0x00, 0xbf, 0xbb, 0xc3, + 0xa8, 0xcd, 0x69, 0xd3, 0xd0, 0xd5, 0x6d, 0xdb, 0xc0, 0xdd, 0x56, 0xe6, + 0x6a, 0xf1, 0x50, 0xf5, 0xc1, 0xf9, 0x13, 0xf8, 0xe4, 0xfc, 0x37, 0xfb, + 0x31, 0xf4, 0x17, 0xfa, 0xe5, 0xfd, 0xbf, 0x00, 0xa0, 0xfd, 0xf7, 0xf5, + 0xec, 0xf6, 0x6b, 0xf5, 0x07, 0xed, 0x60, 0xea, 0xd0, 0xe2, 0x2e, 0xde, + 0x45, 0xdb, 0xb6, 0xce, 0x70, 0xcc, 0x2f, 0xc8, 0x65, 0xc9, 0xab, 0xd1, + 0x0d, 0xd6, 0x91, 0xdf, 0x29, 0xe9, 0xec, 0xf0, 0x62, 0xf0, 0xb6, 0xf1, + 0x70, 0xf1, 0x13, 0xe9, 0x67, 0xe5, 0x92, 0xdc, 0x44, 0xcf, 0xf6, 0xc6, + 0x5c, 0xc0, 0x54, 0xba, 0x72, 0xba, 0x63, 0xbd, 0x91, 0xbe, 0x13, 0xbf, + 0x68, 0xbe, 0x54, 0xbe, 0x28, 0xbd, 0xbd, 0xbe, 0x13, 0xc4, 0xb6, 0xca, + 0x91, 0xcf, 0x49, 0xd0, 0xad, 0xd1, 0x7c, 0xd1, 0x57, 0xd2, 0xf1, 0xd5, + 0x79, 0xda, 0x4b, 0xdb, 0x1a, 0xd8, 0xb1, 0xd5, 0xb6, 0xd2, 0xea, 0xd3, + 0x36, 0xd6, 0xe7, 0xd8, 0x40, 0xd7, 0xfe, 0xd8, 0x70, 0xdf, 0x7b, 0xde, + 0xa8, 0xe0, 0xd6, 0xe0, 0x75, 0xe1, 0xd3, 0xe2, 0xb4, 0xde, 0xd2, 0xdd, + 0x62, 0xe5, 0x69, 0xec, 0x3f, 0xf0, 0x6e, 0xfa, 0xae, 0x00, 0x11, 0x08, + 0xd6, 0x12, 0xca, 0x19, 0x13, 0x21, 0x33, 0x26, 0xad, 0x21, 0xad, 0x1c, + 0x79, 0x1b, 0x01, 0x16, 0xd5, 0x14, 0xe0, 0x0d, 0x52, 0x08, 0x68, 0x08, + 0xc5, 0x06, 0x89, 0x0e, 0xd2, 0x0f, 0xf2, 0x08, 0xf2, 0x09, 0x46, 0x0e, + 0xe8, 0x0b, 0x81, 0x0b, 0xff, 0x0b, 0x35, 0x0b, 0xfe, 0x0b, 0x63, 0x05, + 0xd8, 0x05, 0x78, 0x0b, 0x8e, 0x0a, 0xa2, 0x08, 0x54, 0x03, 0x1b, 0xff, + 0x4a, 0xfd, 0xdd, 0xfb, 0x5f, 0x01, 0x94, 0x01, 0x9a, 0xf8, 0xb0, 0xf6, + 0x01, 0xfb, 0x45, 0xfc, 0x70, 0xf9, 0x0e, 0xf9, 0x79, 0xf5, 0x66, 0xf0, + 0xc0, 0xf3, 0x2f, 0xf7, 0xdc, 0xf2, 0xa3, 0xea, 0xb5, 0xee, 0xb5, 0xfd, + 0x04, 0x01, 0xc9, 0xf6, 0x43, 0xef, 0x33, 0xed, 0x4d, 0xe8, 0x97, 0xe3, + 0x8a, 0xe2, 0x31, 0xe2, 0xb4, 0xdd, 0x0c, 0xda, 0xaa, 0xd7, 0xc1, 0xd2, + 0xa2, 0xdc, 0x79, 0xeb, 0xfc, 0xf0, 0xbf, 0xe9, 0xb0, 0xde, 0x0d, 0xea, + 0x5e, 0xf4, 0xde, 0xed, 0xa5, 0xe7, 0xf4, 0xe6, 0x9b, 0xe3, 0xea, 0xde, + 0x86, 0xdc, 0x74, 0xdc, 0x3a, 0xe2, 0x21, 0xda, 0xe6, 0xd6, 0x9c, 0xdb, + 0xc6, 0xd6, 0xe5, 0xda, 0x1f, 0xde, 0x3b, 0xda, 0x30, 0xd3, 0x9f, 0xd1, + 0xea, 0xd9, 0x14, 0xde, 0x17, 0xdd, 0x16, 0xe2, 0xd3, 0xea, 0xc9, 0xee, + 0xef, 0xef, 0xe4, 0xf0, 0xb9, 0xf4, 0x0a, 0xf9, 0xd2, 0xfd, 0xeb, 0x00, + 0x99, 0x01, 0x50, 0x00, 0xeb, 0x04, 0xd4, 0x0c, 0x8e, 0x0d, 0xae, 0x0d, + 0x67, 0x09, 0x0b, 0x05, 0x24, 0xf8, 0x5a, 0xe8, 0x54, 0xe1, 0x81, 0xd9, + 0xbb, 0xd3, 0x88, 0xc8, 0x7e, 0xc3, 0x4c, 0xc4, 0xbe, 0xc3, 0x9d, 0xc8, + 0xce, 0xd0, 0x97, 0xdf, 0xb2, 0xed, 0x58, 0xf6, 0x17, 0xfa, 0x88, 0xfd, + 0xf6, 0x01, 0xcc, 0x03, 0xf2, 0xff, 0x51, 0xf6, 0xf2, 0xea, 0xea, 0xdb, + 0x8e, 0xd1, 0x8f, 0xcb, 0x95, 0xc6, 0xf8, 0xc8, 0x8d, 0xc8, 0x4c, 0xc3, + 0x53, 0xc2, 0xfd, 0xc2, 0x03, 0xc6, 0xf0, 0xc9, 0xd1, 0xcc, 0xb9, 0xce, + 0x2e, 0xcc, 0x27, 0xce, 0x1e, 0xd4, 0xe4, 0xd9, 0x2c, 0xde, 0x31, 0xdf, + 0x21, 0xe5, 0x7b, 0xea, 0x11, 0xed, 0x63, 0xf1, 0xea, 0xf4, 0x6d, 0xf4, + 0x63, 0xf2, 0x7f, 0xf3, 0xa4, 0xf3, 0x6e, 0xf2, 0x5e, 0xee, 0x1a, 0xea, + 0x56, 0xe9, 0xea, 0xe7, 0x0f, 0xe7, 0xfd, 0xe6, 0x87, 0xe5, 0x3a, 0xe3, + 0x1a, 0xe7, 0xc4, 0xef, 0x7f, 0xf6, 0xfc, 0xf8, 0x0a, 0xfb, 0x1a, 0x06, + 0xb9, 0x14, 0xff, 0x1e, 0x49, 0x27, 0x01, 0x2f, 0xbe, 0x34, 0x3e, 0x36, + 0x87, 0x32, 0x16, 0x2e, 0xe1, 0x2a, 0xb3, 0x23, 0xa8, 0x1c, 0x65, 0x19, + 0xc4, 0x14, 0xea, 0x0f, 0x2f, 0x0d, 0xcc, 0x0d, 0x1f, 0x0d, 0xeb, 0x06, + 0x5d, 0x03, 0x6a, 0x06, 0xdc, 0x0a, 0x17, 0x0a, 0x67, 0x06, 0xb0, 0x09, + 0x4c, 0x10, 0x38, 0x0f, 0x2a, 0x0f, 0xda, 0x1c, 0xab, 0x25, 0xda, 0x1f, + 0xf1, 0x18, 0xa7, 0x1a, 0x2c, 0x22, 0x34, 0x1d, 0xac, 0x16, 0x75, 0x19, + 0x15, 0x13, 0x9c, 0x09, 0xd0, 0x0a, 0xd7, 0x10, 0xf6, 0x0b, 0x6f, 0x00, + 0x8e, 0x04, 0xea, 0x0b, 0x29, 0x01, 0x67, 0xf7, 0x17, 0xff, 0x6f, 0x09, + 0x44, 0x0b, 0x9e, 0x09, 0xef, 0x12, 0xec, 0x1b, 0x64, 0x1a, 0x66, 0x26, + 0xa3, 0x36, 0x09, 0x37, 0xf8, 0x2f, 0x38, 0x31, 0x6f, 0x34, 0x4b, 0x26, + 0xca, 0x13, 0xda, 0x0f, 0x25, 0x14, 0x27, 0x0a, 0xd1, 0xfc, 0xf7, 0xfe, + 0x8c, 0x03, 0x5d, 0x05, 0xd4, 0x05, 0x6b, 0x09, 0x70, 0x08, 0xb1, 0x00, + 0xfa, 0x04, 0x97, 0x0f, 0xd0, 0x0d, 0x28, 0x0a, 0x3d, 0x0d, 0xd4, 0x0b, + 0x3e, 0x08, 0x68, 0x05, 0xf7, 0x08, 0xa3, 0x10, 0xaa, 0x11, 0x6f, 0x0d, + 0x2a, 0x06, 0xdf, 0x00, 0xff, 0x03, 0x24, 0x0e, 0x03, 0x12, 0x54, 0x0c, + 0x23, 0x08, 0x00, 0x0a, 0xd8, 0x0a, 0x0e, 0x07, 0x6e, 0x06, 0xa9, 0x0c, + 0x96, 0x13, 0x44, 0x14, 0x57, 0x14, 0x1c, 0x17, 0x16, 0x1e, 0x0f, 0x28, + 0xd9, 0x2f, 0xdd, 0x2f, 0xf6, 0x29, 0x1b, 0x2a, 0xed, 0x2b, 0xdc, 0x27, + 0xf2, 0x1a, 0x9f, 0x0c, 0xb9, 0x01, 0x5e, 0xf7, 0xbc, 0xf2, 0x25, 0xf3, + 0x34, 0xf4, 0x9e, 0xf0, 0x25, 0xf1, 0x06, 0xfa, 0x9b, 0x03, 0xfc, 0x0b, + 0x82, 0x0f, 0x4e, 0x0f, 0x67, 0x10, 0xf4, 0x0f, 0x1c, 0x0b, 0x09, 0x07, + 0xcc, 0x01, 0xa3, 0xfc, 0x72, 0xf7, 0x3e, 0xef, 0x4c, 0xe9, 0xee, 0xe8, + 0xfc, 0xeb, 0x38, 0xef, 0xcc, 0xf3, 0x59, 0xf1, 0x1c, 0xed, 0xa6, 0xee, + 0x00, 0xf1, 0x9b, 0xf4, 0xbc, 0xf2, 0x8f, 0xec, 0x41, 0xe8, 0xe6, 0xe5, + 0x12, 0xe6, 0xe4, 0xe8, 0x16, 0xed, 0x5f, 0xf2, 0x4b, 0xf7, 0x0c, 0xfa, + 0x1a, 0xfe, 0xf7, 0x06, 0x45, 0x12, 0xe7, 0x16, 0xc8, 0x13, 0x77, 0x12, + 0x2a, 0x14, 0xf8, 0x13, 0x04, 0x14, 0xd0, 0x11, 0xab, 0x0c, 0xbe, 0x0b, + 0xe7, 0x0c, 0xcb, 0x0d, 0xa2, 0x0b, 0xf8, 0x09, 0xeb, 0x0e, 0x12, 0x15, + 0x0c, 0x1a, 0x83, 0x21, 0xbb, 0x2d, 0x67, 0x38, 0x26, 0x3b, 0xb2, 0x3e, + 0xa8, 0x43, 0x54, 0x47, 0x0a, 0x4c, 0xda, 0x49, 0xfd, 0x44, 0x3c, 0x3d, + 0xe2, 0x38, 0x0c, 0x40, 0x5b, 0x41, 0x84, 0x3d, 0xf5, 0x3e, 0x3d, 0x46, + 0x68, 0x4b, 0x58, 0x4c, 0x21, 0x4d, 0xe0, 0x4c, 0x80, 0x4b, 0xce, 0x49, + 0x3e, 0x4c, 0x38, 0x49, 0x32, 0x3d, 0xac, 0x37, 0xf7, 0x39, 0xd3, 0x3b, + 0x5f, 0x3b, 0xcd, 0x3a, 0xc4, 0x3d, 0xdc, 0x3d, 0x65, 0x3a, 0x6f, 0x3b, + 0xf7, 0x3c, 0x3d, 0x3d, 0x4b, 0x39, 0x47, 0x33, 0xdf, 0x2e, 0x9f, 0x29, + 0xa9, 0x25, 0xbb, 0x23, 0x2d, 0x24, 0x5c, 0x23, 0x8d, 0x20, 0x58, 0x20, + 0x18, 0x21, 0x82, 0x1d, 0x53, 0x1c, 0x84, 0x22, 0x53, 0x2b, 0x35, 0x33, + 0xe1, 0x37, 0x72, 0x3c, 0x90, 0x40, 0x3f, 0x43, 0xad, 0x47, 0x80, 0x49, + 0xa7, 0x43, 0xda, 0x3f, 0x37, 0x3e, 0x2d, 0x3a, 0xba, 0x35, 0x8a, 0x2e, + 0x37, 0x2c, 0xfc, 0x2c, 0xae, 0x2a, 0x85, 0x27, 0x3e, 0x25, 0x4f, 0x28, + 0xbe, 0x2e, 0x36, 0x2f, 0x89, 0x2b, 0xef, 0x2e, 0xc1, 0x34, 0xc4, 0x32, + 0x96, 0x2b, 0x63, 0x2c, 0x4a, 0x34, 0xa7, 0x35, 0x7c, 0x32, 0xbc, 0x32, + 0xa3, 0x34, 0x9f, 0x35, 0x1c, 0x35, 0xed, 0x31, 0x64, 0x33, 0xef, 0x35, + 0xe4, 0x35, 0xb3, 0x39, 0x08, 0x39, 0xe4, 0x37, 0x1a, 0x3a, 0x08, 0x36, + 0x2a, 0x34, 0x65, 0x34, 0x90, 0x39, 0xa0, 0x42, 0xd4, 0x3d, 0xb0, 0x37, + 0xe9, 0x3b, 0x1a, 0x43, 0x75, 0x46, 0xbd, 0x45, 0x43, 0x42, 0x3b, 0x3e, + 0x9a, 0x3b, 0x7e, 0x36, 0xeb, 0x2f, 0xfa, 0x24, 0xc4, 0x1a, 0x97, 0x13, + 0xf7, 0x0c, 0xa5, 0x09, 0xea, 0x07, 0x14, 0x0e, 0x8c, 0x1b, 0xde, 0x24, + 0x2c, 0x24, 0x8c, 0x22, 0xaf, 0x23, 0xfe, 0x28, 0x07, 0x2e, 0x92, 0x28, + 0x68, 0x1f, 0x0f, 0x12, 0xbc, 0x04, 0xa8, 0xfb, 0x66, 0xf3, 0xc2, 0xf0, + 0x80, 0xef, 0x0b, 0xec, 0x04, 0xeb, 0x12, 0xe8, 0x1b, 0xe5, 0x22, 0xe7, + 0x6a, 0xeb, 0x1f, 0xf1, 0xb3, 0xef, 0xc4, 0xea, 0x2e, 0xe7, 0x9e, 0xe3, + 0xef, 0xe5, 0x10, 0xe7, 0x52, 0xe9, 0xd3, 0xec, 0xd2, 0xea, 0xda, 0xed, + 0xd7, 0xef, 0x3e, 0xf0, 0x00, 0xf5, 0xba, 0xf3, 0x56, 0xf5, 0x98, 0xf9, + 0x8b, 0xfb, 0xe4, 0xff, 0x07, 0x01, 0x6a, 0x01, 0xec, 0x00, 0x4d, 0xfe, + 0x37, 0xfa, 0x36, 0xf7, 0x3a, 0xf4, 0x72, 0xf0, 0x60, 0xf2, 0x7e, 0xf4, + 0x90, 0xf7, 0x60, 0xfd, 0x6d, 0x03, 0x41, 0x0f, 0xce, 0x1a, 0x71, 0x21, + 0xad, 0x26, 0x6f, 0x28, 0xfe, 0x2c, 0xb3, 0x2f, 0x59, 0x2b, 0x96, 0x28, + 0x50, 0x25, 0xca, 0x26, 0xd8, 0x27, 0x04, 0x21, 0x61, 0x1d, 0xda, 0x1e, + 0xe1, 0x22, 0x4b, 0x26, 0x10, 0x26, 0x8e, 0x24, 0x30, 0x28, 0x64, 0x2c, + 0x4a, 0x2d, 0x57, 0x2f, 0xfc, 0x2c, 0x19, 0x28, 0xb2, 0x25, 0xd9, 0x24, + 0xc0, 0x23, 0x50, 0x21, 0x7c, 0x1f, 0xf3, 0x1a, 0x2f, 0x16, 0xd2, 0x14, + 0x63, 0x12, 0xd6, 0x0f, 0xeb, 0x0b, 0xf9, 0x06, 0x6e, 0x04, 0x69, 0x03, + 0x03, 0x05, 0x35, 0x04, 0x70, 0xfe, 0xff, 0xf7, 0x99, 0xf2, 0xb9, 0xef, + 0x47, 0xef, 0x4e, 0xf4, 0x4f, 0xf6, 0xd1, 0xf1, 0x33, 0xef, 0x45, 0xf1, + 0x2d, 0xf8, 0xa2, 0xf9, 0xb1, 0xfa, 0x3b, 0x03, 0xad, 0x07, 0xb6, 0x02, + 0x1b, 0xfe, 0x5e, 0x01, 0xd9, 0x09, 0xff, 0x0e, 0x3d, 0x08, 0x45, 0x00, + 0xb5, 0xf8, 0xea, 0xf3, 0x2d, 0xf9, 0xfd, 0xf7, 0xd9, 0xf2, 0xc5, 0xf1, + 0xc7, 0xf4, 0x31, 0xfa, 0xf3, 0xf8, 0x8f, 0xf9, 0x10, 0x00, 0xc3, 0x03, + 0x4d, 0x04, 0xd3, 0x07, 0x05, 0x0e, 0xcf, 0x0b, 0x06, 0x04, 0xae, 0x03, + 0xa2, 0x0b, 0x27, 0x11, 0x7d, 0x10, 0xc1, 0x0f, 0x86, 0x0b, 0xf8, 0x04, + 0xa1, 0x02, 0x06, 0x07, 0xad, 0x0a, 0x2d, 0x07, 0xbf, 0x04, 0x3e, 0x02, + 0x32, 0x04, 0xd8, 0x06, 0x19, 0x06, 0x5e, 0x0c, 0x05, 0x10, 0x76, 0x0e, + 0x07, 0x0f, 0x81, 0x14, 0x20, 0x1b, 0xfc, 0x1f, 0x16, 0x20, 0xdb, 0x1c, + 0x2d, 0x1e, 0xd5, 0x1d, 0x3d, 0x1c, 0xc9, 0x16, 0x7a, 0x0f, 0xca, 0x0d, + 0xa7, 0x04, 0x62, 0xf6, 0x6c, 0xed, 0x2f, 0xeb, 0x16, 0xec, 0x35, 0xe8, + 0x23, 0xe6, 0xea, 0xe7, 0x3f, 0xed, 0xa9, 0xf6, 0x3e, 0xfb, 0x9f, 0xff, + 0xbc, 0x01, 0x96, 0xfe, 0xfb, 0xfb, 0x78, 0xf6, 0xad, 0xf0, 0x90, 0xe9, + 0xfa, 0xe1, 0xeb, 0xdd, 0x59, 0xd8, 0xef, 0xd1, 0x81, 0xcf, 0x1e, 0xd1, + 0x0d, 0xd3, 0x72, 0xd2, 0x38, 0xcd, 0x51, 0xc7, 0x72, 0xc5, 0xe9, 0xc3, + 0xe6, 0xc2, 0x85, 0xc1, 0xc6, 0xbb, 0x36, 0xb6, 0xd4, 0xb4, 0xce, 0xb7, + 0x11, 0xbf, 0x28, 0xc3, 0xfc, 0xc1, 0x4c, 0xc1, 0x20, 0xc3, 0x26, 0xc8, + 0x8d, 0xcd, 0x65, 0xce, 0x62, 0xce, 0xa6, 0xcf, 0x77, 0xd0, 0x6f, 0xd1, + 0x33, 0xcf, 0xb5, 0xcc, 0x62, 0xca, 0xca, 0xc5, 0xb7, 0xc1, 0xa3, 0xbd, + 0xb2, 0xbb, 0xe1, 0xb9, 0x3f, 0xbb, 0xd1, 0xbe, 0x28, 0xc1, 0x27, 0xc9, + 0xee, 0xd0, 0x9d, 0xd8, 0x6c, 0xe0, 0x7a, 0xe4, 0x6c, 0xe9, 0xe2, 0xec, + 0xe4, 0xec, 0x3d, 0xec, 0x00, 0xed, 0x39, 0xee, 0xb8, 0xed, 0x4c, 0xee, + 0x00, 0xf1, 0x80, 0xf2, 0xba, 0xf3, 0x28, 0xf6, 0x3b, 0xf8, 0xee, 0xf8, + 0x6e, 0xf9, 0xf5, 0xfa, 0xba, 0xf9, 0x83, 0xf7, 0x05, 0xf6, 0x52, 0xf4, + 0xe6, 0xf6, 0xaa, 0xf8, 0xc2, 0xf6, 0x9e, 0xf7, 0x00, 0xfa, 0x7a, 0xfc, + 0x7c, 0xfe, 0x06, 0xfe, 0xdd, 0xfd, 0x3a, 0xfe, 0x06, 0xfa, 0x94, 0xf5, + 0x3f, 0xf5, 0xdf, 0xf2, 0xb4, 0xee, 0xbd, 0xe9, 0xa0, 0xe5, 0x30, 0xe5, + 0x46, 0xe1, 0x05, 0xda, 0x93, 0xd4, 0xaf, 0xd0, 0x26, 0xd2, 0x9b, 0xd4, + 0xdd, 0xd0, 0x0e, 0xce, 0x45, 0xce, 0x55, 0xd0, 0xa6, 0xd2, 0xf1, 0xd3, + 0x46, 0xd8, 0x17, 0xdd, 0xe8, 0xdc, 0xa7, 0xd4, 0x96, 0xd1, 0x53, 0xd9, + 0x1f, 0xdf, 0x90, 0xde, 0x12, 0xd9, 0xc3, 0xd2, 0xc2, 0xce, 0x8a, 0xcf, + 0xea, 0xd1, 0x6c, 0xd4, 0x07, 0xd5, 0x47, 0xcf, 0xb5, 0xc9, 0xe9, 0xc7, + 0xeb, 0xc7, 0xaf, 0xcb, 0x7e, 0xd2, 0xb4, 0xd4, 0x65, 0xd3, 0xda, 0xd2, + 0x15, 0xd4, 0x0d, 0xd8, 0x9d, 0xda, 0x21, 0xde, 0xd6, 0xe2, 0x4f, 0xe5, + 0xfe, 0xe4, 0x96, 0xe5, 0x7d, 0xea, 0x79, 0xe8, 0xa9, 0xe0, 0xef, 0xdf, + 0x65, 0xe2, 0xa7, 0xe3, 0x39, 0xe3, 0xa5, 0xdd, 0xba, 0xd8, 0x71, 0xda, + 0xf7, 0xdf, 0x9c, 0xe5, 0x36, 0xe9, 0x4f, 0xed, 0x00, 0xf4, 0x93, 0xfc, + 0x24, 0x05, 0xaf, 0x0c, 0xe8, 0x13, 0xcc, 0x17, 0xfb, 0x17, 0x93, 0x16, + 0x88, 0x19, 0x81, 0x1c, 0xc3, 0x14, 0x27, 0x0b, 0x67, 0x00, 0x78, 0xf5, + 0x81, 0xf0, 0x66, 0xed, 0xbe, 0xeb, 0xa4, 0xe9, 0x81, 0xe8, 0xd4, 0xe9, + 0x23, 0xee, 0x0b, 0xf4, 0xe0, 0xf7, 0x7f, 0xfc, 0x7d, 0x02, 0xf3, 0x05, + 0x01, 0x05, 0x03, 0x01, 0x4a, 0xfb, 0xb9, 0xf7, 0x60, 0xf4, 0x96, 0xef, + 0x2b, 0xea, 0x82, 0xe2, 0xd4, 0xde, 0x7e, 0xdf, 0xaa, 0xde, 0x99, 0xdc, + 0x3b, 0xd9, 0x0b, 0xd5, 0x1d, 0xd3, 0x8e, 0xd0, 0xb5, 0xcd, 0x70, 0xcb, + 0x72, 0xc6, 0x31, 0xc1, 0x1e, 0xbd, 0xba, 0xbb, 0x36, 0xbc, 0xa7, 0xbe, + 0x8a, 0xc3, 0xe7, 0xc4, 0xb3, 0xc2, 0x6c, 0xc2, 0x6f, 0xc5, 0x4c, 0xc9, + 0xaf, 0xcb, 0xe3, 0xca, 0x2c, 0xc9, 0x80, 0xc8, 0x01, 0xc8, 0x07, 0xc9, + 0x6b, 0xca, 0x91, 0xc9, 0x92, 0xc6, 0x2d, 0xc3, 0xbd, 0xc0, 0xf1, 0xbe, + 0xd2, 0xbf, 0x2e, 0xc1, 0x59, 0xc1, 0xc4, 0xc4, 0xb1, 0xca, 0x66, 0xd0, + 0xe4, 0xd4, 0x82, 0xd7, 0x90, 0xd9, 0x50, 0xdc, 0xf6, 0xdf, 0xed, 0xe3, + 0x9a, 0xe6, 0x43, 0xe5, 0x59, 0xe4, 0x4c, 0xe6, 0x7c, 0xe6, 0xa0, 0xe7, + 0x20, 0xea, 0x1c, 0xec, 0x0c, 0xef, 0xba, 0xf1, 0x14, 0xf4, 0x6e, 0xf7, + 0x85, 0xf9, 0x17, 0xfa, 0x6c, 0xfc, 0xf0, 0xfd, 0x67, 0x00, 0xba, 0x04, + 0xb3, 0x07, 0xbf, 0x0c, 0x11, 0x13, 0x1e, 0x18, 0x76, 0x1b, 0xbb, 0x1c, + 0xed, 0x1e, 0x35, 0x22, 0x91, 0x25, 0x8d, 0x26, 0x50, 0x23, 0x09, 0x1d, + 0x72, 0x18, 0x40, 0x18, 0x6a, 0x19, 0xaf, 0x1c, 0xb5, 0x1c, 0x5a, 0x17, + 0x39, 0x13, 0x41, 0x10, 0x21, 0x11, 0x85, 0x13, 0x8b, 0x14, 0x74, 0x15, + 0x15, 0x13, 0xc0, 0x10, 0x59, 0x11, 0xee, 0x13, 0xbe, 0x16, 0x0c, 0x18, + 0x4b, 0x19, 0xba, 0x1a, 0x19, 0x1d, 0xfe, 0x1e, 0x5e, 0x1e, 0x1c, 0x1e, + 0xe4, 0x1e, 0xd7, 0x21, 0x09, 0x26, 0x7d, 0x25, 0x73, 0x21, 0xfd, 0x1e, + 0xa8, 0x1e, 0x62, 0x1d, 0xda, 0x19, 0x85, 0x17, 0x4a, 0x17, 0x39, 0x12, + 0x59, 0x0a, 0x9e, 0x08, 0xe3, 0x0a, 0xe4, 0x0d, 0x77, 0x10, 0xc0, 0x10, + 0xce, 0x11, 0xb5, 0x14, 0x59, 0x14, 0xce, 0x13, 0x6b, 0x1a, 0x00, 0x21, + 0x73, 0x20, 0x4d, 0x1d, 0xd8, 0x1a, 0x59, 0x1b, 0x66, 0x1f, 0x93, 0x20, + 0x67, 0x1c, 0xf0, 0x16, 0xdb, 0x14, 0x97, 0x14, 0x45, 0x14, 0x41, 0x17, + 0x82, 0x1a, 0xfa, 0x1c, 0x06, 0x22, 0x57, 0x27, 0xaa, 0x2a, 0x3c, 0x32, + 0xe7, 0x3d, 0x42, 0x44, 0x5c, 0x44, 0xfe, 0x3f, 0xd1, 0x3c, 0xbb, 0x3d, + 0xff, 0x3b, 0xdf, 0x37, 0x7a, 0x33, 0xe0, 0x2f, 0x14, 0x2b, 0x3a, 0x24, + 0xa1, 0x22, 0x8f, 0x24, 0x42, 0x24, 0x23, 0x23, 0x35, 0x26, 0x8e, 0x2c, + 0x0a, 0x30, 0x31, 0x30, 0xbd, 0x2d, 0xca, 0x2f, 0xee, 0x38, 0xa4, 0x3d, + 0xc2, 0x39, 0x38, 0x34, 0x4c, 0x31, 0xf8, 0x31, 0x86, 0x34, 0x56, 0x35, + 0x92, 0x32, 0x2a, 0x2d, 0x6b, 0x2b, 0x25, 0x2d, 0x6d, 0x2d, 0xc9, 0x2b, + 0xd8, 0x28, 0xaa, 0x26, 0x14, 0x25, 0xeb, 0x21, 0x43, 0x1c, 0xe5, 0x17, + 0x9e, 0x14, 0xe2, 0x10, 0x60, 0x0f, 0x72, 0x0e, 0x51, 0x0d, 0xac, 0x0e, + 0xe3, 0x0f, 0x47, 0x0f, 0x91, 0x11, 0xdd, 0x11, 0xca, 0x10, 0xa7, 0x11, + 0xa4, 0x10, 0x1d, 0x0e, 0x96, 0x0a, 0xc7, 0x07, 0xc0, 0x05, 0x7f, 0x03, + 0x6f, 0xfe, 0x6a, 0xf9, 0x85, 0xf8, 0x21, 0xf6, 0xc9, 0xf2, 0x5c, 0xf0, + 0x10, 0xee, 0x77, 0xec, 0x06, 0xeb, 0xfd, 0xeb, 0x61, 0xee, 0x4b, 0xee, + 0x18, 0xee, 0x26, 0xef, 0xc6, 0xf0, 0xf9, 0xf3, 0x11, 0xf5, 0x9c, 0xf2, + 0xaa, 0xf0, 0x15, 0xf0, 0xff, 0xee, 0x85, 0xec, 0xee, 0xe9, 0x0d, 0xea, + 0x2a, 0xec, 0xd5, 0xed, 0x89, 0xec, 0x64, 0xeb, 0x10, 0xeb, 0x80, 0xec, + 0x1d, 0xf1, 0xa8, 0xf2, 0x2b, 0xf4, 0x17, 0xf7, 0x69, 0xf8, 0x10, 0xf9, + 0x14, 0xfa, 0x09, 0xfd, 0x93, 0x01, 0xbe, 0x03, 0x99, 0x00, 0x86, 0xfe, + 0xaf, 0x00, 0x4b, 0x05, 0xaf, 0x08, 0xd4, 0x0a, 0xe2, 0x0d, 0x39, 0x0f, + 0x9a, 0x0e, 0x70, 0x0c, 0x37, 0x0d, 0x9e, 0x12, 0x4c, 0x19, 0xcc, 0x1a, + 0x6c, 0x16, 0xa2, 0x12, 0x0c, 0x10, 0x04, 0x10, 0xb3, 0x12, 0x9b, 0x13, + 0x54, 0x12, 0xfc, 0x11, 0x27, 0x12, 0x05, 0x14, 0x1b, 0x17, 0x62, 0x1b, + 0xe5, 0x21, 0xa7, 0x25, 0x49, 0x25, 0x1d, 0x24, 0xf7, 0x24, 0x0c, 0x27, + 0xf8, 0x27, 0xb8, 0x28, 0xb7, 0x2a, 0x26, 0x2c, 0x53, 0x2a, 0xb1, 0x25, + 0xcf, 0x21, 0xee, 0x20, 0x7f, 0x22, 0x88, 0x23, 0x2e, 0x1f, 0xac, 0x19, + 0xd1, 0x15, 0x16, 0x11, 0xa3, 0x0d, 0xf5, 0x0d, 0x22, 0x11, 0xce, 0x12, + 0x70, 0x0f, 0xa1, 0x09, 0x41, 0x07, 0x12, 0x08, 0x20, 0x0c, 0x5a, 0x10, + 0xc2, 0x0e, 0xd0, 0x09, 0xf0, 0x05, 0x94, 0x07, 0x80, 0x0d, 0xb3, 0x0e, + 0xa9, 0x0a, 0xb3, 0x07, 0x6c, 0x04, 0x30, 0x00, 0x0f, 0xff, 0x0d, 0x00, + 0x7d, 0x00, 0x83, 0xfe, 0xd6, 0xf9, 0x9f, 0xf6, 0x8d, 0xf5, 0x82, 0xf7, + 0x33, 0xfe, 0xe5, 0x03, 0xec, 0x06, 0x9e, 0x08, 0x20, 0x09, 0xd3, 0x08, + 0xc1, 0x08, 0xa9, 0x09, 0x2e, 0x0a, 0x5b, 0x09, 0x0d, 0x03, 0xb0, 0xfc, + 0xa0, 0xfb, 0x67, 0xf9, 0xc8, 0xf5, 0x32, 0xf1, 0xd9, 0xee, 0x3a, 0xf2, + 0x79, 0xf4, 0x5a, 0xf3, 0x82, 0xf3, 0x39, 0xf8, 0x0f, 0x00, 0x69, 0x06, + 0xa1, 0x08, 0xb8, 0x0a, 0xb0, 0x0f, 0xd6, 0x13, 0x67, 0x14, 0x71, 0x13, + 0xb6, 0x13, 0x69, 0x14, 0xd3, 0x15, 0x69, 0x15, 0x49, 0x15, 0x12, 0x17, + 0x40, 0x16, 0x65, 0x15, 0x25, 0x13, 0x47, 0x11, 0x6e, 0x10, 0xc0, 0x0c, + 0xa1, 0x09, 0x15, 0x06, 0xb0, 0x03, 0x25, 0x04, 0x53, 0x05, 0x60, 0x05, + 0xa0, 0x04, 0x09, 0x06, 0x5d, 0x07, 0x9f, 0x06, 0xb0, 0x06, 0x10, 0x0a, + 0x83, 0x0d, 0xdd, 0x0c, 0xca, 0x08, 0x11, 0x06, 0xf6, 0x05, 0xc6, 0x04, + 0xa0, 0x02, 0x27, 0x01, 0xb6, 0x00, 0x99, 0xff, 0x47, 0xfc, 0x6a, 0xf9, + 0x92, 0xf6, 0xe3, 0xf2, 0xd6, 0xef, 0x1f, 0xeb, 0xac, 0xe7, 0xab, 0xe6, + 0x71, 0xe5, 0x1b, 0xe4, 0x10, 0xe1, 0x4a, 0xde, 0x19, 0xde, 0xef, 0xde, + 0x5b, 0xde, 0x67, 0xde, 0x20, 0xde, 0xe8, 0xdb, 0xee, 0xdb, 0xd6, 0xdd, + 0xa3, 0xdf, 0x97, 0xdf, 0x71, 0xdf, 0xd8, 0xdf, 0x07, 0xe0, 0xda, 0xdf, + 0xf5, 0xde, 0xbb, 0xe0, 0x28, 0xe2, 0x24, 0xe1, 0x90, 0xdf, 0x32, 0xde, + 0xc5, 0xdf, 0x8e, 0xe1, 0xf8, 0xe1, 0x80, 0xe2, 0xd4, 0xe1, 0x43, 0xe2, + 0x94, 0xe2, 0x17, 0xe0, 0x0f, 0xe1, 0x98, 0xe4, 0xcc, 0xe4, 0x1c, 0xe5, + 0xca, 0xe6, 0x0e, 0xe8, 0x5d, 0xeb, 0x74, 0xf0, 0x3a, 0xf5, 0x09, 0xf8, + 0xc3, 0xf5, 0x7e, 0xf3, 0x86, 0xf6, 0x92, 0xf9, 0xd2, 0xf9, 0x32, 0xf9, + 0xf1, 0xf7, 0x24, 0xf7, 0xd1, 0xf6, 0x44, 0xf7, 0x75, 0xfa, 0xc1, 0xfe, + 0x70, 0x01, 0x56, 0x04, 0x68, 0x08, 0xf5, 0x0a, 0xd5, 0x0b, 0x97, 0x0c, + 0x73, 0x0e, 0x69, 0x12, 0x54, 0x14, 0xaa, 0x13, 0x44, 0x14, 0x4d, 0x15, + 0x90, 0x15, 0x99, 0x15, 0x82, 0x15, 0x52, 0x16, 0xdb, 0x16, 0x73, 0x15, + 0x77, 0x14, 0x46, 0x12, 0xf7, 0x0f, 0xd2, 0x10, 0x42, 0x10, 0x42, 0x0c, + 0x58, 0x07, 0xd8, 0x04, 0x34, 0x06, 0x06, 0x08, 0x41, 0x06, 0xaf, 0x02, + 0xfc, 0xfe, 0x68, 0xfc, 0x77, 0xfe, 0xa3, 0x00, 0xb9, 0xfe, 0xf8, 0xfa, + 0xfe, 0xf5, 0x16, 0xf3, 0x90, 0xf3, 0xd7, 0xf1, 0x6e, 0xef, 0x5a, 0xee, + 0xf2, 0xe9, 0x2f, 0xe6, 0xdb, 0xe4, 0x13, 0xe1, 0xcc, 0xde, 0x18, 0xde, + 0x17, 0xda, 0xec, 0xd7, 0x59, 0xd7, 0xc6, 0xd5, 0x58, 0xd8, 0x78, 0xdb, + 0x0d, 0xdb, 0x75, 0xd9, 0xeb, 0xd6, 0x73, 0xd5, 0x7a, 0xd6, 0x28, 0xd8, + 0xb9, 0xd9, 0xd6, 0xd9, 0xa5, 0xd7, 0x70, 0xd6, 0xb4, 0xd6, 0xde, 0xd6, + 0xfd, 0xd8, 0x17, 0xdb, 0xf3, 0xda, 0xf9, 0xdb, 0x9d, 0xdb, 0x2b, 0xd9, + 0x37, 0xd8, 0x0e, 0xd8, 0xa2, 0xd9, 0x68, 0xdb, 0x61, 0xdb, 0xb3, 0xdb, + 0xbd, 0xdd, 0xad, 0xe0, 0x7e, 0xe3, 0x5d, 0xe7, 0x14, 0xed, 0xb6, 0xf2, + 0x9e, 0xf4, 0x15, 0xf5, 0x5b, 0xf7, 0x2f, 0xf9, 0x6e, 0xfb, 0x3c, 0xff, + 0x03, 0x02, 0xcf, 0x02, 0xac, 0x02, 0x63, 0x03, 0xe3, 0x05, 0xa7, 0x07, + 0xde, 0x06, 0xaa, 0x05, 0x7d, 0x06, 0x65, 0x08, 0xfc, 0x0a, 0x96, 0x0d, + 0xc3, 0x0e, 0x0b, 0x0e, 0x9c, 0x0c, 0xb1, 0x0e, 0x34, 0x12, 0x62, 0x12, + 0x62, 0x12, 0x35, 0x13, 0xc4, 0x13, 0x78, 0x13, 0x88, 0x12, 0xca, 0x11, + 0xcc, 0x11, 0xb9, 0x10, 0xdd, 0x0c, 0xba, 0x0b, 0x26, 0x0b, 0x35, 0x07, + 0x55, 0x04, 0x39, 0x03, 0x19, 0x03, 0xde, 0x01, 0x95, 0xfe, 0xa4, 0xfa, + 0x2f, 0xf8, 0xf4, 0xf5, 0x66, 0xf2, 0x91, 0xf0, 0xd1, 0xee, 0x9d, 0xec, + 0x7a, 0xea, 0x39, 0xe8, 0x41, 0xe8, 0xf0, 0xe8, 0x34, 0xe7, 0x87, 0xe5, + 0x7f, 0xe3, 0x27, 0xe0, 0x7b, 0xdd, 0x88, 0xda, 0x5c, 0xd9, 0x9f, 0xd7, + 0xb7, 0xd3, 0xf6, 0xd1, 0x35, 0xd1, 0x7e, 0xd1, 0xc0, 0xd1, 0x9d, 0xcf, + 0x7b, 0xce, 0xa6, 0xd0, 0x8a, 0xd1, 0xe1, 0xd1, 0xc3, 0xd3, 0xf3, 0xd4, + 0xe8, 0xd5, 0x94, 0xd5, 0xd6, 0xd5, 0x28, 0xd9, 0xd2, 0xdc, 0x70, 0xdd, + 0x10, 0xdd, 0xa4, 0xde, 0xcd, 0xe0, 0x7a, 0xe1, 0x62, 0xe0, 0x52, 0xe2, + 0x8c, 0xe7, 0x1e, 0xec, 0xc5, 0xee, 0x34, 0xef, 0x70, 0xee, 0x69, 0xef, + 0xf1, 0xf1, 0x1b, 0xf3, 0x5d, 0xf6, 0xc9, 0xf9, 0x25, 0xfb, 0x2d, 0xfd, + 0x8c, 0xfe, 0x11, 0x03, 0x55, 0x0b, 0x07, 0x10, 0x1e, 0x13, 0xad, 0x19, + 0x7a, 0x1f, 0x6c, 0x21, 0xc5, 0x21, 0x75, 0x23, 0xe8, 0x26, 0x3f, 0x27, + 0x6e, 0x22, 0x2b, 0x1f, 0x24, 0x22, 0x3a, 0x27, 0xf8, 0x29, 0x95, 0x29, + 0x66, 0x29, 0x0c, 0x2b, 0xb2, 0x2c, 0x32, 0x2f, 0x11, 0x31, 0xa8, 0x30, + 0x44, 0x2e, 0x30, 0x2c, 0x11, 0x2d, 0x76, 0x2d, 0xf3, 0x29, 0x26, 0x25, + 0x8c, 0x22, 0x8d, 0x21, 0x62, 0x21, 0x20, 0x21, 0x01, 0x1f, 0x34, 0x1d, + 0x10, 0x1d, 0x07, 0x1c, 0xc2, 0x1b, 0xff, 0x1b, 0x8b, 0x1a, 0x12, 0x19, + 0xa2, 0x17, 0x52, 0x16, 0x44, 0x15, 0x25, 0x13, 0xa9, 0x0e, 0xdc, 0x0b, + 0xd9, 0x0a, 0x87, 0x05, 0x1d, 0xff, 0x4e, 0xfc, 0x3e, 0xfe, 0x11, 0x01, + 0xdc, 0xff, 0x11, 0xfe, 0x89, 0xfd, 0xbb, 0xfe, 0x17, 0x02, 0x03, 0x05, + 0x5f, 0x06, 0x83, 0x05, 0x54, 0x03, 0x01, 0x02, 0xab, 0x01, 0xf5, 0x00, + 0xf0, 0xff, 0xb5, 0x00, 0x8e, 0x01, 0x6c, 0x00, 0x6d, 0xff, 0xd0, 0xff, + 0x1f, 0x02, 0xa0, 0x04, 0xd2, 0x06, 0x9f, 0x08, 0x7a, 0x08, 0x45, 0x09, + 0x7c, 0x0d, 0x33, 0x13, 0x0a, 0x18, 0x1e, 0x1b, 0x20, 0x1b, 0xe9, 0x1c, + 0x7d, 0x21, 0x23, 0x23, 0x68, 0x25, 0x13, 0x28, 0x10, 0x2a, 0xcb, 0x2e, + 0xe2, 0x31, 0x1d, 0x32, 0x61, 0x32, 0x85, 0x32, 0x36, 0x33, 0xe1, 0x34, + 0xb5, 0x37, 0x26, 0x39, 0x7c, 0x37, 0x93, 0x34, 0xbb, 0x33, 0x00, 0x37, + 0x01, 0x3a, 0x4c, 0x3a, 0x26, 0x3b, 0x89, 0x3d, 0x18, 0x41, 0x5b, 0x43, + 0x57, 0x44, 0xab, 0x46, 0x4c, 0x48, 0x36, 0x47, 0x90, 0x45, 0x07, 0x45, + 0x63, 0x43, 0xd8, 0x3f, 0x6d, 0x3c, 0xb7, 0x39, 0x9c, 0x37, 0x4e, 0x35, + 0xc9, 0x33, 0xc5, 0x31, 0xf9, 0x2d, 0x25, 0x2a, 0xc1, 0x27, 0x2b, 0x26, + 0x16, 0x24, 0xc5, 0x21, 0xd8, 0x1e, 0xb9, 0x1c, 0x2f, 0x1b, 0x91, 0x18, + 0x48, 0x16, 0xf8, 0x12, 0xa0, 0x0f, 0x24, 0x0e, 0xef, 0x0b, 0x16, 0x0a, + 0x1e, 0x0a, 0xb9, 0x08, 0x95, 0x06, 0x03, 0x04, 0x53, 0x01, 0x9e, 0x01, + 0xd6, 0xff, 0x13, 0xfb, 0x81, 0xf8, 0xf1, 0xf6, 0x64, 0xf5, 0x45, 0xf3, + 0x26, 0xef, 0xbc, 0xed, 0xbc, 0xed, 0x72, 0xe9, 0xc5, 0xe5, 0x03, 0xe4, + 0xea, 0xe4, 0x76, 0xe7, 0x0b, 0xe6, 0x2f, 0xe4, 0x3e, 0xe4, 0x6a, 0xe5, + 0x75, 0xe7, 0xf3, 0xe7, 0x1d, 0xe7, 0x72, 0xe6, 0x33, 0xe6, 0x0e, 0xe6, + 0x6b, 0xe6, 0xd0, 0xe7, 0xe6, 0xe9, 0x74, 0xeb, 0x3e, 0xeb, 0x9d, 0xea, + 0x91, 0xeb, 0x23, 0xed, 0x65, 0xee, 0xdd, 0xef, 0x64, 0xf1, 0x6f, 0xf2, + 0x7f, 0xf3, 0x9a, 0xf4, 0x58, 0xf6, 0x39, 0xfa, 0xb0, 0xfd, 0x71, 0xff, + 0x19, 0xff, 0x0b, 0xff, 0x26, 0x03, 0x9e, 0x08, 0x9b, 0x0b, 0x81, 0x0c, + 0x26, 0x0e, 0xbc, 0x0f, 0xaa, 0x0f, 0x75, 0x0e, 0x84, 0x0c, 0x23, 0x0b, + 0xe5, 0x09, 0xe8, 0x08, 0x51, 0x08, 0xb5, 0x08, 0xb8, 0x0a, 0xc6, 0x0b, + 0x99, 0x09, 0xbe, 0x05, 0xf8, 0x04, 0xf7, 0x09, 0x54, 0x10, 0x62, 0x10, + 0xee, 0x0c, 0x76, 0x0b, 0xbc, 0x0a, 0xfd, 0x0b, 0xbf, 0x0e, 0xec, 0x11, + 0x12, 0x14, 0x4c, 0x12, 0x59, 0x0f, 0x6a, 0x0f, 0x1d, 0x10, 0xe4, 0x0e, + 0x67, 0x0d, 0x1f, 0x0b, 0x4b, 0x06, 0xe7, 0x00, 0x60, 0xfd, 0xbc, 0xfb, + 0xdc, 0xfb, 0x82, 0xfa, 0x80, 0xf7, 0x91, 0xf5, 0x3e, 0xf4, 0x21, 0xf4, + 0x9f, 0xf5, 0x90, 0xf8, 0x48, 0xf9, 0x84, 0xf5, 0x83, 0xf1, 0xe5, 0xf0, + 0x62, 0xf3, 0x54, 0xf6, 0x10, 0xf7, 0xa3, 0xf4, 0x86, 0xf3, 0x12, 0xf4, + 0xf5, 0xf4, 0xb0, 0xf7, 0xb9, 0xf9, 0xf7, 0xf9, 0xcb, 0xf9, 0x32, 0xf8, + 0x4d, 0xf6, 0x01, 0xf6, 0xd0, 0xf5, 0x27, 0xf6, 0x46, 0xf6, 0x99, 0xf4, + 0xf8, 0xf2, 0xa4, 0xf2, 0x99, 0xf3, 0xe5, 0xf6, 0xae, 0xfa, 0xa5, 0xfc, + 0x5c, 0x01, 0x40, 0x05, 0x52, 0x06, 0x54, 0x08, 0xdd, 0x07, 0x5c, 0x0a, + 0xca, 0x10, 0x01, 0x16, 0x98, 0x19, 0xf8, 0x1a, 0x50, 0x1a, 0x7b, 0x19, + 0x31, 0x1c, 0x71, 0x1e, 0xfe, 0x1e, 0x76, 0x1f, 0x46, 0x1f, 0xf9, 0x1e, + 0x12, 0x1d, 0xb6, 0x1b, 0x1b, 0x1c, 0xcc, 0x1c, 0x71, 0x1c, 0x4e, 0x1b, + 0xe0, 0x1a, 0x86, 0x1a, 0x6f, 0x19, 0xd1, 0x17, 0xb6, 0x17, 0xef, 0x17, + 0xf8, 0x17, 0x11, 0x19, 0xf0, 0x19, 0xa7, 0x19, 0xbb, 0x19, 0xf2, 0x19, + 0xe2, 0x19, 0xdc, 0x1a, 0xd4, 0x1b, 0x42, 0x1b, 0x43, 0x1a, 0xc1, 0x18, + 0xbd, 0x16, 0x93, 0x15, 0x2f, 0x14, 0xe2, 0x13, 0x57, 0x14, 0x89, 0x12, + 0x9f, 0x10, 0x1c, 0x0f, 0x1f, 0x0d, 0xef, 0x0c, 0x3a, 0x0c, 0x2e, 0x0a, + 0x16, 0x0a, 0x56, 0x08, 0x6e, 0x06, 0x7c, 0x05, 0x7d, 0x04, 0xfb, 0x04, + 0xbc, 0x03, 0xd9, 0x01, 0x6c, 0x00, 0x3a, 0xff, 0x58, 0xfd, 0x74, 0xfc, + 0x88, 0xfc, 0x4b, 0xfa, 0x27, 0xf9, 0x59, 0xf7, 0xad, 0xf4, 0x62, 0xf3, + 0x8c, 0xf1, 0x74, 0xf1, 0xcd, 0xf1, 0x30, 0xef, 0x9d, 0xed, 0xde, 0xee, + 0xbc, 0xef, 0x3d, 0xf0, 0x9b, 0xf0, 0x3f, 0xf1, 0xeb, 0xf1, 0xc6, 0xf0, + 0xe1, 0xf0, 0x04, 0xf4, 0x88, 0xf6, 0xbb, 0xf7, 0x45, 0xf7, 0xe3, 0xf4, + 0x55, 0xf3, 0x32, 0xf2, 0x70, 0xf1, 0x60, 0xf2, 0x92, 0xf3, 0xe6, 0xf2, + 0x07, 0xf3, 0xc4, 0xf4, 0x56, 0xf5, 0xbb, 0xf5, 0x3e, 0xf5, 0x76, 0xf7, + 0xf2, 0xfb, 0x81, 0xfc, 0xf8, 0xfb, 0xae, 0xfc, 0x25, 0xfe, 0x25, 0x00, + 0xdf, 0x00, 0x1b, 0x00, 0xd4, 0x00, 0x25, 0x03, 0x3e, 0x03, 0xd5, 0x01, + 0xdf, 0x00, 0xe6, 0xff, 0x6d, 0x00, 0x52, 0xff, 0x2d, 0xfa, 0x5a, 0xf7, + 0x94, 0xf7, 0xa9, 0xf6, 0x11, 0xf4, 0xcf, 0xf1, 0x2b, 0xf3, 0x4b, 0xf7, + 0x20, 0xf9, 0x6b, 0xf8, 0x68, 0xf7, 0x82, 0xf7, 0xa5, 0xf9, 0xb6, 0xfa, + 0xa5, 0xfa, 0x62, 0xfa, 0xfe, 0xf8, 0x5f, 0xf8, 0x43, 0xf8, 0x18, 0xf6, + 0xb6, 0xf3, 0x39, 0xf1, 0xfc, 0xee, 0xbc, 0xed, 0xc8, 0xeb, 0x5f, 0xeb, + 0x45, 0xec, 0x7d, 0xec, 0xf9, 0xeb, 0xdc, 0xeb, 0xda, 0xed, 0xc2, 0xef, + 0xca, 0xef, 0xb6, 0xed, 0x82, 0xec, 0xfc, 0xec, 0xfd, 0xec, 0xb1, 0xeb, + 0xd7, 0xea, 0xe5, 0xeb, 0xa7, 0xed, 0xc0, 0xee, 0x6e, 0xed, 0x63, 0xed, + 0x48, 0xee, 0x28, 0xef, 0xcf, 0xf0, 0x44, 0xef, 0x01, 0xee, 0xe9, 0xee, + 0x07, 0xef, 0xfc, 0xee, 0xa5, 0xee, 0x5e, 0xec, 0x63, 0xeb, 0xa0, 0xeb, + 0x16, 0xea, 0x1c, 0xeb, 0xcb, 0xed, 0x95, 0xef, 0xd5, 0xf0, 0x9d, 0xf1, + 0x6b, 0xf2, 0xd0, 0xf4, 0x99, 0xf8, 0x2f, 0xfb, 0xca, 0xfd, 0x5e, 0xff, + 0xa5, 0xfe, 0xd5, 0xfd, 0x1e, 0xfc, 0x65, 0xfd, 0x81, 0x00, 0x82, 0xff, + 0x43, 0xfe, 0xed, 0xfd, 0x2f, 0xff, 0xec, 0x00, 0x8e, 0xff, 0x83, 0xfe, + 0xf2, 0xfe, 0x04, 0x00, 0xcd, 0x00, 0x14, 0x01, 0x85, 0x02, 0xfe, 0x04, + 0x46, 0x06, 0xed, 0x05, 0x3b, 0x05, 0xf4, 0x04, 0xce, 0x06, 0xfe, 0x09, + 0xe1, 0x0a, 0x80, 0x09, 0xb8, 0x09, 0xfc, 0x09, 0x7d, 0x09, 0x79, 0x09, + 0x63, 0x08, 0x36, 0x08, 0xf5, 0x07, 0xb7, 0x06, 0xe3, 0x05, 0x37, 0x04, + 0x36, 0x03, 0xab, 0x01, 0x81, 0x00, 0xd0, 0xff, 0xeb, 0xff, 0xc7, 0x01, + 0xd1, 0x00, 0xf2, 0xff, 0xd2, 0xff, 0xdf, 0xff, 0xce, 0x02, 0xe5, 0x03, + 0x7f, 0x04, 0x99, 0x05, 0x8c, 0x05, 0x28, 0x07, 0xe7, 0x07, 0x2d, 0x06, + 0x53, 0x05, 0x89, 0x04, 0x9e, 0x02, 0xc4, 0x00, 0x69, 0xfd, 0xda, 0xfb, + 0x80, 0xfb, 0x66, 0xf9, 0x42, 0xf7, 0x5d, 0xf5, 0x8a, 0xf4, 0x07, 0xf4, + 0x06, 0xf3, 0x1a, 0xf2, 0x0e, 0xf3, 0xa5, 0xf4, 0x98, 0xf5, 0x26, 0xf6, + 0x8f, 0xf5, 0xe4, 0xf4, 0xc2, 0xf5, 0x6b, 0xf9, 0xbe, 0xfa, 0xd3, 0xf9, + 0x5f, 0xf7, 0x5b, 0xf5, 0xeb, 0xf7, 0x5c, 0xf8, 0x85, 0xf8, 0x13, 0xf8, + 0x0c, 0xf7, 0xc2, 0xf9, 0x31, 0xfa, 0x03, 0xf8, 0x9e, 0xf7, 0xfa, 0xf8, + 0x76, 0xfa, 0xc8, 0xfb, 0x56, 0xfa, 0xe3, 0xf9, 0x50, 0xfd, 0xa1, 0xff, + 0xa0, 0x00, 0x07, 0x00, 0x90, 0x00, 0x94, 0x05, 0xc1, 0x09, 0xf6, 0x09, + 0xb9, 0x09, 0x25, 0x0b, 0xa0, 0x0c, 0xbe, 0x0b, 0xd4, 0x09, 0x62, 0x09, + 0x48, 0x0a, 0xb1, 0x08, 0x43, 0x05, 0xa8, 0x03, 0xbf, 0x02, 0x3d, 0x03, + 0xe0, 0x02, 0x89, 0x02, 0x81, 0x03, 0x9d, 0x04, 0xc0, 0x06, 0xa4, 0x06, + 0x26, 0x06, 0xe1, 0x06, 0x23, 0x08, 0x29, 0x0b, 0xfe, 0x0c, 0xde, 0x0b, + 0xae, 0x0a, 0x98, 0x09, 0xad, 0x0c, 0xb1, 0x10, 0xbd, 0x0f, 0x3f, 0x0f, + 0xdb, 0x0c, 0x8c, 0x0c, 0x19, 0x0e, 0x24, 0x0c, 0x68, 0x0c, 0xd9, 0x0a, + 0x1e, 0x07, 0x96, 0x06, 0x73, 0x06, 0x30, 0x07, 0xb7, 0x08, 0x1f, 0x07, + 0x13, 0x07, 0xe1, 0x08, 0xc8, 0x09, 0xe1, 0x0c, 0xa8, 0x0e, 0x7f, 0x10, + 0x41, 0x15, 0x71, 0x17, 0x9c, 0x19, 0xe4, 0x1d, 0x9d, 0x1f, 0x04, 0x21, + 0x1c, 0x21, 0x9b, 0x20, 0xad, 0x22, 0x13, 0x24, 0x2f, 0x21, 0x6e, 0x1d, + 0x55, 0x1b, 0x31, 0x19, 0x64, 0x18, 0x5b, 0x16, 0x31, 0x17, 0x45, 0x17, + 0x53, 0x15, 0x7a, 0x16, 0x9f, 0x16, 0x3d, 0x1a, 0x04, 0x1b, 0x6f, 0x19, + 0x79, 0x19, 0x3d, 0x18, 0xa6, 0x1a, 0x71, 0x1b, 0x4e, 0x1b, 0xed, 0x1b, + 0x19, 0x19, 0x74, 0x18, 0x47, 0x1b, 0xcf, 0x1c, 0x0d, 0x1f, 0x0c, 0x20, + 0x06, 0x20, 0x16, 0x24, 0x43, 0x26, 0x71, 0x24, 0x43, 0x24, 0xc1, 0x23, + 0xd1, 0x22, 0x63, 0x24, 0x75, 0x22, 0x71, 0x1f, 0x99, 0x1d, 0xcf, 0x1b, + 0x66, 0x1d, 0x14, 0x1d, 0xaf, 0x1b, 0x41, 0x1a, 0x32, 0x19, 0x70, 0x1a, + 0xf0, 0x1a, 0x1c, 0x1c, 0x38, 0x1b, 0x2c, 0x1a, 0x5a, 0x1a, 0x1b, 0x19, + 0x6f, 0x18, 0x19, 0x18, 0x14, 0x1a, 0x38, 0x1b, 0x4c, 0x19, 0x03, 0x17, + 0x9a, 0x17, 0x42, 0x1b, 0xe3, 0x1d, 0xd8, 0x1e, 0xd1, 0x1d, 0xa1, 0x1e, + 0x42, 0x1f, 0x61, 0x1e, 0xa7, 0x1f, 0x0b, 0x1e, 0xd0, 0x1a, 0x77, 0x17, + 0xa1, 0x12, 0xc2, 0x10, 0xd7, 0x0e, 0x52, 0x0b, 0xb2, 0x09, 0xc6, 0x07, + 0xe6, 0x07, 0xe0, 0x07, 0x74, 0x06, 0x60, 0x06, 0x42, 0x06, 0x2f, 0x06, + 0x1a, 0x06, 0x74, 0x07, 0x65, 0x08, 0x97, 0x0a, 0xb6, 0x0b, 0xe0, 0x0a, + 0xf1, 0x0a, 0x82, 0x08, 0x66, 0x08, 0x31, 0x09, 0xda, 0x07, 0x1e, 0x07, + 0xcb, 0x05, 0x76, 0x05, 0x46, 0x05, 0x93, 0x04, 0x39, 0x05, 0x8f, 0x05, + 0x35, 0x04, 0x5e, 0x01, 0xed, 0xfc, 0x3b, 0xfa, 0x86, 0xf7, 0xd4, 0xf4, + 0x7b, 0xf4, 0x71, 0xf3, 0x9b, 0xf0, 0x11, 0xed, 0xa9, 0xeb, 0x62, 0xed, + 0x73, 0xef, 0xc8, 0xee, 0x98, 0xef, 0xd6, 0xf2, 0xcd, 0xf2, 0x9a, 0xf3, + 0x9d, 0xf4, 0x22, 0xf5, 0x23, 0xf8, 0xb0, 0xf6, 0x58, 0xf5, 0x3b, 0xf4, + 0xad, 0xed, 0x82, 0xea, 0x91, 0xea, 0xb4, 0xeb, 0xbb, 0xea, 0xa9, 0xe4, + 0xf8, 0xe2, 0xd0, 0xe5, 0xbf, 0xe5, 0xb1, 0xe2, 0x7e, 0xe1, 0x1d, 0xe3, + 0xc5, 0xe3, 0xd3, 0xe2, 0x8b, 0xe1, 0xb8, 0xdf, 0xd0, 0xde, 0xbc, 0xde, + 0x2f, 0xe0, 0xaa, 0xe1, 0xce, 0xe0, 0x75, 0xe0, 0x10, 0xe0, 0x16, 0xe1, + 0xb1, 0xe2, 0xf3, 0xe2, 0xd5, 0xe4, 0x7e, 0xe3, 0xdc, 0xe1, 0x1e, 0xe5, + 0xbf, 0xe6, 0x8b, 0xe6, 0x6d, 0xe3, 0x80, 0xe1, 0xef, 0xe4, 0xd1, 0xe5, + 0x93, 0xe6, 0xc6, 0xe7, 0x16, 0xe7, 0x95, 0xe7, 0x52, 0xe8, 0x20, 0xea, + 0xec, 0xeb, 0x3b, 0xec, 0x6d, 0xee, 0x66, 0xf2, 0x6a, 0xf2, 0xce, 0xf3, + 0x2f, 0xf7, 0x31, 0xf8, 0x99, 0xfb, 0x17, 0xf9, 0xc1, 0xf6, 0x8e, 0xf9, + 0x1b, 0xf8, 0x40, 0xfa, 0x0d, 0xfe, 0x0a, 0xfe, 0xd6, 0xff, 0xd0, 0x01, + 0x3c, 0x00, 0x65, 0x02, 0x80, 0x02, 0x86, 0xfd, 0xc3, 0xfc, 0xfa, 0xfa, + 0x46, 0xfc, 0x1c, 0xfe, 0xa3, 0xfc, 0xae, 0xfe, 0x6e, 0xfc, 0x6d, 0xfd, + 0x0d, 0x01, 0xfb, 0xfe, 0x64, 0x03, 0x1d, 0x05, 0x0a, 0x01, 0xd8, 0xfd, + 0xc9, 0xfe, 0x3e, 0x05, 0x75, 0x06, 0x29, 0x06, 0x90, 0x00, 0x49, 0xfe, + 0x70, 0x01, 0x0f, 0x04, 0xe0, 0x09, 0xe9, 0x06, 0xd3, 0x03, 0x68, 0x00, + 0x68, 0x02, 0x6b, 0x09, 0x4f, 0x0b, 0x76, 0x0d, 0x91, 0x0d, 0x98, 0x0c, + 0xaa, 0x04, 0x10, 0x03, 0xf2, 0x05, 0x49, 0x05, 0xd0, 0xff, 0x01, 0xf5, + 0x58, 0xf4, 0xf6, 0xf5, 0x5f, 0xf8, 0x6e, 0xf8, 0xca, 0xf9, 0xcd, 0x00, + 0xc4, 0x05, 0x86, 0x06, 0xd4, 0x04, 0xdb, 0x06, 0xf1, 0x04, 0x93, 0x03, + 0x20, 0x03, 0xe1, 0x00, 0x79, 0x01, 0x98, 0xfd, 0x5b, 0xfc, 0x7f, 0xff, + 0x7f, 0x00, 0x6f, 0x01, 0x33, 0xfd, 0x3f, 0xfa, 0xe2, 0xfa, 0x07, 0xfa, + 0xa4, 0xfa, 0x3a, 0xf8, 0x0d, 0xf7, 0x40, 0xf3, 0x08, 0xf0, 0x08, 0xf1, + 0x79, 0xef, 0xfd, 0xee, 0x4f, 0xec, 0x08, 0xec, 0x72, 0xeb, 0x40, 0xeb, + 0x6d, 0xed, 0x5f, 0xed, 0x2d, 0xef, 0xe1, 0xed, 0x1f, 0xef, 0x27, 0xf2, + 0xac, 0xf3, 0x02, 0xf7, 0xcf, 0xf5, 0xd6, 0xf4, 0xbc, 0xf0, 0x9c, 0xea, + 0x50, 0xea, 0xe8, 0xe7, 0xa5, 0xe5, 0x68, 0xe2, 0x64, 0xe0, 0x7f, 0xe0, + 0xea, 0xe0, 0xf2, 0xe4, 0xb4, 0xe5, 0x42, 0xe6, 0x0f, 0xe3, 0xf4, 0xdf, + 0x00, 0xdf, 0x57, 0xdd, 0xbd, 0xde, 0xfd, 0xdb, 0x35, 0xda, 0xcf, 0xd9, + 0x47, 0xdc, 0x41, 0xdf, 0xc0, 0xdd, 0xc8, 0xdf, 0x51, 0xe1, 0xbd, 0xe2, + 0x2b, 0xe5, 0xea, 0xe4, 0x72, 0xe4, 0x6b, 0xe3, 0x04, 0xdf, 0x32, 0xdb, + 0xa5, 0xda, 0xe8, 0xd9, 0x2c, 0xd8, 0x53, 0xd3, 0x58, 0xcd, 0xfc, 0xca, + 0xc2, 0xc8, 0x01, 0xc9, 0x41, 0xca, 0xc4, 0xc9, 0x6b, 0xcd, 0x64, 0xd1, + 0xb8, 0xd4, 0xf7, 0xd7, 0x56, 0xd4, 0xd1, 0xd2, 0x6a, 0xd8, 0x8b, 0xd5, + 0xa9, 0xd0, 0xcf, 0xcb, 0x19, 0xca, 0xc1, 0xd0, 0xe3, 0xcc, 0xbf, 0xcb, + 0xf4, 0xce, 0xb8, 0xcd, 0x7f, 0xd5, 0x7f, 0xdd, 0xa3, 0xdc, 0xb4, 0xdc, + 0xf0, 0xdd, 0x15, 0xe2, 0xbf, 0xea, 0x4b, 0xe5, 0xb4, 0xdf, 0xa5, 0xdc, + 0xc2, 0xd6, 0xf2, 0xdf, 0x97, 0xe1, 0x43, 0xe1, 0x4a, 0xea, 0x23, 0xdf, + 0xbe, 0xd6, 0xd5, 0xdc, 0x5e, 0xde, 0xa0, 0xea, 0xd7, 0xee, 0xc3, 0xef, + 0xed, 0xf2, 0xa3, 0xe2, 0x09, 0xdf, 0xbe, 0xe2, 0xeb, 0xe9, 0xaf, 0xf8, + 0x84, 0xf2, 0x54, 0xe1, 0x66, 0xd3, 0x09, 0xd8, 0xf8, 0xec, 0x8b, 0xf4, + 0xa8, 0xf1, 0xda, 0xe8, 0x56, 0xdd, 0x9a, 0xe3, 0x50, 0xf2, 0x69, 0xf8, + 0xc1, 0xf4, 0x50, 0xe1, 0x07, 0xd3, 0xd0, 0xd2, 0x86, 0xd1, 0xcf, 0xd9, + 0xeb, 0xdf, 0x5d, 0xe8, 0xfc, 0xec, 0xe0, 0xd9, 0x70, 0xd2, 0x15, 0xd9, + 0xa9, 0xec, 0xed, 0x02, 0x41, 0x01, 0x38, 0xf3, 0xde, 0xe4, 0xbc, 0xda, + 0x0c, 0xe2, 0xe1, 0xf4, 0xc9, 0xf8, 0x26, 0xf9, 0x62, 0xf3, 0xb7, 0xef, + 0x30, 0xf2, 0x02, 0xdc, 0x10, 0xd0, 0x32, 0xe0, 0xfc, 0xf8, 0xe6, 0x08, + 0xb7, 0xf4, 0x03, 0xdc, 0x8e, 0xe4, 0x50, 0xfa, 0xd3, 0x0c, 0x97, 0x06, + 0xa2, 0xeb, 0xee, 0xe6, 0x4b, 0xee, 0xe4, 0xf1, 0xee, 0xf4, 0xe7, 0xe6, + 0x7e, 0xe3, 0x7c, 0x05, 0x21, 0x17, 0x59, 0xff, 0x1d, 0xe8, 0x33, 0xee, + 0x40, 0x09, 0x12, 0x1a, 0x0e, 0x0d, 0x59, 0xfa, 0x9b, 0xf6, 0x97, 0x05, + 0x2b, 0x12, 0xe4, 0xf4, 0xff, 0xdd, 0xa9, 0xe4, 0xda, 0xff, 0x18, 0x1a, + 0xa4, 0x0a, 0xa5, 0x00, 0x68, 0xfb, 0x24, 0xee, 0xc5, 0xeb, 0x75, 0xf0, + 0xa5, 0xf4, 0xc5, 0xfb, 0xcd, 0x03, 0x89, 0xfe, 0x3d, 0xff, 0x87, 0xf9, + 0xb4, 0xf9, 0xfa, 0x01, 0xb7, 0x07, 0x21, 0x15, 0x55, 0x0e, 0x9e, 0xfa, + 0xa5, 0xdf, 0x00, 0xd9, 0x04, 0xee, 0x09, 0xf8, 0x73, 0xf8, 0x05, 0xe6, + 0xf6, 0xcc, 0x32, 0xcc, 0x81, 0xd1, 0x29, 0xd6, 0xa4, 0xd7, 0x8b, 0xd4, + 0x6f, 0xd4, 0xaa, 0xc2, 0x66, 0xc4, 0x9f, 0xd9, 0xe6, 0xda, 0x42, 0xd6, + 0xcd, 0xc3, 0x19, 0xbe, 0x33, 0xcc, 0x4f, 0xd2, 0x17, 0xd4, 0x6c, 0xd0, + 0xea, 0xcb, 0xf3, 0xd3, 0xf6, 0xe1, 0xfc, 0xe0, 0x44, 0xd5, 0xe1, 0xd7, + 0xb1, 0xe6, 0xf4, 0xe4, 0xed, 0xdd, 0x6a, 0xe2, 0xf7, 0xe3, 0x1e, 0xe5, + 0x54, 0xeb, 0x60, 0xe9, 0xcd, 0xe0, 0xa2, 0xdb, 0xab, 0xdc, 0x6c, 0xe7, + 0xe9, 0xe7, 0x0c, 0xe3, 0x95, 0xea, 0x6b, 0xf6, 0x31, 0xf4, 0x87, 0xe7, + 0x7b, 0xe7, 0x3a, 0xeb, 0x69, 0xf9, 0xaf, 0x09, 0xdd, 0x0e, 0x2c, 0x0e, + 0xe6, 0x06, 0x73, 0xf9, 0xe7, 0xe2, 0x3e, 0xe6, 0x5f, 0x02, 0x8d, 0x10, + 0x14, 0x10, 0x5f, 0x0b, 0x9a, 0x00, 0x30, 0xf7, 0xfb, 0xf8, 0xdd, 0xff, + 0x3d, 0x09, 0x19, 0x0e, 0x63, 0x0b, 0x8f, 0xff, 0x3f, 0xf3, 0x33, 0xf2, + 0xcb, 0xfa, 0xe8, 0x03, 0x3b, 0x02, 0x75, 0xff, 0xd4, 0x00, 0xd1, 0xfb, + 0x8b, 0xf3, 0xde, 0xf9, 0xba, 0x0b, 0x67, 0x1a, 0xe5, 0x14, 0x02, 0x02, + 0x87, 0x00, 0x02, 0x03, 0x43, 0x01, 0xd8, 0x08, 0x7e, 0x10, 0xf5, 0x14, + 0x45, 0x15, 0x3a, 0x12, 0xca, 0x14, 0xfc, 0x15, 0x92, 0x11, 0x86, 0x0b, + 0x36, 0x0a, 0xb5, 0x0c, 0x9c, 0x12, 0x10, 0x20, 0xd9, 0x21, 0xec, 0x17, + 0x4e, 0x0d, 0x06, 0x0a, 0x37, 0x17, 0x24, 0x24, 0xb1, 0x20, 0xa0, 0x19, + 0x07, 0x17, 0xa2, 0x19, 0xb5, 0x26, 0x04, 0x2a, 0xe7, 0x29, 0x53, 0x31, + 0xee, 0x3e, 0x9a, 0x4a, 0xeb, 0x3b, 0x00, 0x30, 0xbc, 0x33, 0xa5, 0x3f, + 0x66, 0x4e, 0x96, 0x45, 0xe2, 0x36, 0xa1, 0x36, 0x50, 0x38, 0x08, 0x39, + 0x27, 0x2e, 0xe4, 0x20, 0x39, 0x28, 0xc4, 0x3a, 0x9b, 0x52, 0x2d, 0x59, + 0xd6, 0x47, 0x82, 0x35, 0x63, 0x36, 0x46, 0x4d, 0x54, 0x58, 0x82, 0x4d, + 0x53, 0x38, 0xe8, 0x30, 0x1a, 0x3a, 0x6e, 0x3f, 0x28, 0x40, 0x80, 0x3f, + 0xe1, 0x41, 0xfb, 0x39, 0x53, 0x33, 0x15, 0x3e, 0x64, 0x47, 0x6d, 0x42, + 0x05, 0x38, 0x35, 0x32, 0xd9, 0x30, 0x09, 0x39, 0xe3, 0x37, 0x9c, 0x31, + 0x85, 0x2f, 0x0b, 0x24, 0xf7, 0x1d, 0xa5, 0x1b, 0x79, 0x23, 0xdd, 0x2f, + 0xe7, 0x28, 0x25, 0x1e, 0x55, 0x13, 0xd3, 0x0e, 0xcd, 0x16, 0x32, 0x1d, + 0x7e, 0x28, 0xd0, 0x28, 0xae, 0x0e, 0x92, 0x09, 0x55, 0x1b, 0x1e, 0x28, + 0x7f, 0x2f, 0x67, 0x19, 0x19, 0x03, 0xc0, 0x0d, 0xb5, 0x23, 0x53, 0x30, + 0x49, 0x17, 0xdf, 0xfc, 0xf2, 0x04, 0x93, 0x11, 0x18, 0x23, 0xe3, 0x26, + 0xae, 0x14, 0xcc, 0x0f, 0x9f, 0x05, 0x1e, 0x08, 0xe3, 0x1c, 0xf2, 0x17, + 0x07, 0x16, 0x08, 0x11, 0x26, 0x08, 0xc4, 0x0e, 0x7c, 0x0e, 0xcd, 0x16, + 0xcf, 0x25, 0x7c, 0x1f, 0xe1, 0x15, 0x3b, 0x1e, 0x64, 0x20, 0xe5, 0x1c, + 0xbd, 0x0f, 0xdf, 0x05, 0xe0, 0x17, 0x37, 0x1b, 0xc5, 0x13, 0x2a, 0x0e, + 0x0f, 0x06, 0x17, 0x09, 0x43, 0x17, 0x83, 0x20, 0x85, 0x1a, 0xd1, 0x10, + 0x90, 0x0e, 0x70, 0x14, 0x22, 0x15, 0x6d, 0x1c, 0x40, 0x16, 0xb8, 0x07, + 0xc9, 0x0c, 0x01, 0x0f, 0xc6, 0x13, 0x87, 0x09, 0xc7, 0xfe, 0xf2, 0x0a, + 0x7e, 0x0e, 0xef, 0x0f, 0x6d, 0x15, 0x7d, 0x11, 0x10, 0x14, 0xe3, 0x14, + 0xe1, 0x0b, 0xf7, 0x08, 0xd6, 0x02, 0x77, 0x00, 0xa6, 0xf6, 0x11, 0xe9, + 0xec, 0xdc, 0x78, 0xd6, 0x75, 0xe4, 0xa6, 0xe1, 0xf4, 0xd5, 0x85, 0xcd, + 0xcc, 0xce, 0xa5, 0xe2, 0x37, 0xf3, 0xa0, 0xef, 0x61, 0xe5, 0xbe, 0xe9, + 0xbf, 0xf2, 0x95, 0x05, 0x1e, 0x04, 0x5d, 0xe6, 0x88, 0xda, 0x18, 0xee, + 0x60, 0x08, 0x27, 0x06, 0x73, 0xf8, 0x2b, 0xf7, 0xdf, 0xfb, 0x07, 0x04, + 0x01, 0x0d, 0x24, 0x07, 0xec, 0xfe, 0xf9, 0x03, 0xd5, 0x0d, 0xa6, 0x10, + 0xd0, 0x07, 0xcc, 0x01, 0x45, 0xfd, 0xdd, 0xfd, 0x2f, 0x00, 0xee, 0x07, + 0x1f, 0x15, 0xdf, 0x12, 0x67, 0x0f, 0x3a, 0x12, 0xc9, 0x19, 0xa9, 0x2a, + 0xcc, 0x38, 0xd0, 0x39, 0xa2, 0x31, 0x1b, 0x2d, 0x23, 0x34, 0x11, 0x36, + 0x8c, 0x2f, 0x72, 0x2a, 0xa4, 0x28, 0x2d, 0x2b, 0x52, 0x26, 0xe4, 0x1e, + 0xc0, 0x1c, 0x45, 0x1b, 0xf0, 0x19, 0x44, 0x1e, 0x76, 0x21, 0x76, 0x23, + 0xf2, 0x28, 0x3b, 0x23, 0x2c, 0x19, 0xc7, 0x17, 0xbd, 0x1f, 0xb3, 0x1e, + 0xb2, 0x1a, 0x9c, 0x1c, 0xbb, 0x14, 0x16, 0x14, 0x5c, 0x22, 0xba, 0x2a, + 0x6c, 0x24, 0x3a, 0x22, 0xb7, 0x29, 0x27, 0x35, 0xec, 0x3c, 0x9d, 0x37, + 0x53, 0x2c, 0x5d, 0x26, 0xc4, 0x2d, 0x0a, 0x38, 0xa5, 0x38, 0x55, 0x30, + 0x89, 0x26, 0x1d, 0x1d, 0x55, 0x17, 0x60, 0x12, 0xdb, 0x11, 0x4b, 0x19, + 0x5f, 0x1c, 0x9b, 0x1f, 0xfe, 0x1c, 0x20, 0x16, 0x19, 0x14, 0x57, 0x16, + 0x40, 0x1e, 0x6e, 0x26, 0x56, 0x24, 0xe3, 0x15, 0xee, 0x0d, 0x58, 0x13, + 0x35, 0x1a, 0xae, 0x10, 0xeb, 0x03, 0xbe, 0x06, 0x60, 0x0c, 0x34, 0x16, + 0xcc, 0x21, 0xf1, 0x21, 0x8a, 0x1b, 0x47, 0x15, 0x2b, 0x18, 0xe4, 0x24, + 0x48, 0x25, 0x0a, 0x18, 0xe8, 0x09, 0x1a, 0x05, 0x2a, 0x0b, 0x7d, 0x19, + 0x2a, 0x26, 0x13, 0x14, 0x6d, 0xfe, 0xd3, 0x05, 0x67, 0x16, 0xf6, 0x1b, + 0xc2, 0x0b, 0xef, 0xf4, 0x00, 0xec, 0x38, 0xed, 0x73, 0xef, 0x36, 0xf8, + 0x9d, 0xfd, 0xf9, 0xf6, 0x1a, 0xfe, 0x21, 0x11, 0xad, 0x14, 0x8c, 0x0b, + 0x19, 0x02, 0xfc, 0xfb, 0x10, 0xfa, 0xa3, 0xff, 0x8b, 0x08, 0x02, 0x08, + 0x47, 0x04, 0x56, 0x01, 0x31, 0xfd, 0x59, 0xf4, 0x56, 0xe9, 0xce, 0xf0, + 0x9c, 0xff, 0x6c, 0x03, 0xa1, 0xf7, 0x08, 0xe6, 0x49, 0xe9, 0xa9, 0xf3, + 0xe0, 0xf0, 0x42, 0xe8, 0x99, 0xe5, 0xbd, 0xf3, 0xb9, 0xff, 0xdf, 0xfa, + 0xe6, 0xf9, 0xa4, 0xff, 0xd0, 0x07, 0x11, 0x03, 0x72, 0xed, 0x77, 0xf0, + 0x3a, 0x01, 0x92, 0x01, 0x63, 0xf7, 0xc6, 0xef, 0xde, 0x04, 0xfa, 0x28, + 0x29, 0x37, 0x09, 0x25, 0x34, 0x08, 0xfb, 0xf5, 0xbb, 0xe6, 0xd1, 0xe0, + 0x0a, 0xe3, 0x7f, 0xe5, 0x25, 0xf2, 0x3e, 0xfe, 0x88, 0xff, 0x5d, 0xfe, + 0x3d, 0x02, 0x83, 0x06, 0x3c, 0x07, 0xe7, 0x03, 0xf1, 0xf3, 0x2a, 0xe7, + 0x44, 0xe3, 0x91, 0xe6, 0xef, 0xf9, 0x0d, 0x05, 0xcd, 0x0e, 0xab, 0x16, + 0xb6, 0x0b, 0x44, 0xfd, 0x59, 0xe5, 0x9b, 0xd7, 0xfb, 0xd2, 0x88, 0xce, + 0xb2, 0xe2, 0x29, 0xf0, 0x31, 0xf5, 0x80, 0xfa, 0x3d, 0xf1, 0x4a, 0xf2, + 0xfa, 0xeb, 0x6f, 0xdf, 0x26, 0xe4, 0xd3, 0xd6, 0x87, 0xd3, 0x8d, 0xe5, + 0x65, 0xec, 0x1e, 0x02, 0x24, 0x08, 0xf5, 0xf3, 0x6b, 0xe5, 0xbc, 0xd8, + 0xf9, 0xe3, 0xea, 0xf1, 0x6f, 0xe7, 0x6b, 0xe6, 0xa7, 0xed, 0x41, 0xef, + 0xf9, 0xfa, 0x4e, 0x09, 0xfd, 0x11, 0xf5, 0x13, 0x59, 0x18, 0x9e, 0x26, + 0xb9, 0x2b, 0xb1, 0x2d, 0x45, 0x2c, 0x58, 0x23, 0xdb, 0x0e, 0xcc, 0xf1, + 0x98, 0xf1, 0xba, 0x06, 0x1b, 0x0b, 0x56, 0x09, 0xbc, 0x0f, 0x8a, 0x0b, + 0x3c, 0x0c, 0x36, 0x0a, 0x2c, 0x0e, 0xa1, 0x23, 0x0a, 0x1e, 0xbd, 0x10, + 0xe1, 0xfb, 0x9e, 0xe0, 0x00, 0xd5, 0x77, 0xce, 0x94, 0xc3, 0x70, 0xbd, + 0xe7, 0xcb, 0x9d, 0xd9, 0x28, 0xec, 0x85, 0xfb, 0x11, 0xfb, 0x35, 0xf8, + 0xcc, 0xf0, 0x0d, 0xe1, 0x30, 0xd6, 0x03, 0xdf, 0xba, 0xf5, 0x7e, 0x0c, + 0xf5, 0xfd, 0xdf, 0xe5, 0xb9, 0xdc, 0xcc, 0xd8, 0x20, 0xe2, 0x84, 0xe8, + 0xb0, 0xee, 0x86, 0xf6, 0x40, 0x01, 0xb6, 0x0a, 0x39, 0x11, 0xe0, 0x10, + 0xbd, 0x0c, 0xb3, 0x0a, 0x8b, 0x03, 0xe9, 0xf4, 0x61, 0xe1, 0x76, 0xdc, + 0x28, 0xe3, 0x3d, 0xea, 0x34, 0xe3, 0x9a, 0xde, 0x73, 0xdf, 0x3e, 0xdc, + 0x60, 0xe2, 0xf7, 0xe6, 0xaf, 0xf0, 0x31, 0xfb, 0x72, 0x05, 0xc9, 0x08, + 0xbf, 0x06, 0x55, 0x01, 0x11, 0xf1, 0x20, 0xe7, 0x3d, 0xe6, 0xe2, 0xf6, + 0x42, 0x05, 0x8a, 0x01, 0xf4, 0xf1, 0xae, 0xdc, 0x58, 0xcd, 0x7c, 0xc3, + 0xca, 0xc6, 0x1d, 0xd8, 0x38, 0xde, 0xad, 0xd2, 0x49, 0xd8, 0x94, 0xe6, + 0x66, 0xe5, 0x2e, 0xde, 0x1d, 0xcd, 0xbf, 0xba, 0xcc, 0xbb, 0xdb, 0xc7, + 0xe5, 0xd0, 0xc7, 0xda, 0x67, 0xe6, 0x9e, 0xe5, 0x4f, 0xdc, 0xce, 0xdb, + 0xac, 0xdc, 0x5a, 0xdb, 0xab, 0xda, 0x4c, 0xdf, 0xd8, 0xe5, 0xdc, 0xe9, + 0xa6, 0xeb, 0x93, 0xe2, 0x27, 0xdd, 0x02, 0xe7, 0x2d, 0xf4, 0x6d, 0xf6, + 0x63, 0xf0, 0xe9, 0xeb, 0x95, 0xec, 0xf6, 0xee, 0x6f, 0xee, 0x16, 0xed, + 0x2a, 0xeb, 0x50, 0xeb, 0x42, 0xec, 0xf4, 0xee, 0xa1, 0xf1, 0xd6, 0xf1, + 0x39, 0xef, 0x64, 0xf2, 0xc7, 0x01, 0x50, 0x0a, 0x67, 0x04, 0xfd, 0xfe, + 0x2c, 0x01, 0x63, 0x0b, 0xb0, 0x1b, 0x6e, 0x22, 0x5b, 0x25, 0x9e, 0x2d, + 0x00, 0x31, 0xc1, 0x27, 0x55, 0x16, 0x89, 0x10, 0x4a, 0x10, 0x71, 0x0f, + 0x2a, 0x13, 0x53, 0x0e, 0x6a, 0x03, 0xcc, 0xfb, 0x7f, 0xf9, 0x96, 0xfe, + 0xe6, 0x00, 0xa0, 0xfd, 0x43, 0xf7, 0xeb, 0xf8, 0x8d, 0x0e, 0xc7, 0x2a, + 0xcc, 0x38, 0x8f, 0x2a, 0x25, 0x0f, 0x5d, 0xfc, 0x75, 0xff, 0x7b, 0x09, + 0xb8, 0x09, 0x12, 0x0a, 0xd5, 0x08, 0x93, 0x0c, 0x75, 0x0b, 0xcc, 0x0b, + 0xbd, 0x14, 0xef, 0x12, 0x2b, 0x10, 0x6a, 0x0f, 0x0b, 0x0e, 0x3e, 0x07, + 0x62, 0xf5, 0xde, 0xef, 0x5f, 0x07, 0x5a, 0x1d, 0x03, 0x24, 0xdf, 0x1c, + 0xb4, 0x01, 0xfb, 0xec, 0x54, 0xe9, 0xf8, 0xec, 0xfa, 0xef, 0x88, 0xf6, + 0x42, 0x01, 0xe9, 0x01, 0xb6, 0x03, 0x1d, 0x10, 0x0e, 0x17, 0x23, 0x15, + 0x71, 0x10, 0x80, 0x04, 0x6e, 0x00, 0x63, 0x0b, 0x81, 0x17, 0xae, 0x1a, + 0xff, 0x13, 0x51, 0x12, 0xc2, 0x1a, 0x4b, 0x27, 0x49, 0x2c, 0xb2, 0x23, + 0xdc, 0x16, 0x50, 0x0b, 0xd3, 0x02, 0xfb, 0x04, 0x31, 0x17, 0xc6, 0x29, + 0xcc, 0x2a, 0xf4, 0x23, 0x93, 0x24, 0xdc, 0x23, 0x4d, 0x22, 0x20, 0x29, + 0xb1, 0x28, 0xcb, 0x1f, 0x98, 0x14, 0xdd, 0x09, 0xd5, 0x0d, 0x29, 0x13, + 0x6c, 0x14, 0x5d, 0x16, 0x47, 0x14, 0x81, 0x14, 0x8a, 0x14, 0xa1, 0x1e, + 0x3b, 0x2c, 0x84, 0x2b, 0x16, 0x2a, 0xbc, 0x24, 0x04, 0x19, 0xf2, 0x13, + 0x30, 0x13, 0x42, 0x1c, 0xc0, 0x26, 0x78, 0x25, 0x83, 0x2e, 0xed, 0x2c, + 0xe2, 0x1b, 0x6a, 0x14, 0x44, 0x0a, 0x8a, 0x05, 0xad, 0x08, 0xf5, 0x09, + 0x0d, 0x0c, 0x38, 0x0f, 0x0b, 0x00, 0x7e, 0xf1, 0xb8, 0xff, 0xc5, 0x11, + 0xae, 0x1d, 0x13, 0x24, 0x66, 0x25, 0xc5, 0x25, 0x6c, 0x2d, 0x21, 0x33, + 0x37, 0x3b, 0x6d, 0x38, 0x97, 0x21, 0x6e, 0x1c, 0x20, 0x20, 0x9b, 0x2e, + 0xb5, 0x33, 0xbe, 0x23, 0x4e, 0x15, 0x13, 0x0a, 0x90, 0x07, 0x18, 0xfe, + 0xa0, 0xf0, 0x0b, 0xe5, 0x57, 0xe4, 0xdd, 0xe8, 0x8d, 0xf5, 0xec, 0x05, + 0x4e, 0x01, 0x3c, 0xf9, 0x76, 0xec, 0xab, 0xeb, 0xaa, 0xf9, 0x7a, 0x02, + 0x78, 0xfb, 0x24, 0xea, 0x22, 0xe7, 0x01, 0xe3, 0x52, 0xe0, 0xf1, 0xe4, + 0x42, 0xe9, 0x3f, 0xeb, 0x7b, 0xe6, 0x1e, 0xe5, 0x52, 0xe7, 0x71, 0xf5, + 0x43, 0x0d, 0x75, 0x0b, 0x4b, 0xf2, 0x2a, 0xd8, 0x81, 0xce, 0xed, 0xd6, + 0x61, 0xdc, 0x72, 0xdd, 0x27, 0xd5, 0xea, 0xcf, 0x1d, 0xd8, 0x44, 0xeb, + 0xa7, 0x03, 0xdc, 0x13, 0x12, 0x1c, 0xae, 0x15, 0xda, 0x11, 0xec, 0x08, + 0xa3, 0x07, 0xff, 0x14, 0x0d, 0x10, 0xb3, 0x07, 0x01, 0x01, 0x40, 0x09, + 0xe3, 0x15, 0x1b, 0x16, 0x26, 0x0c, 0x3d, 0x04, 0xbc, 0x05, 0x09, 0x04, + 0x2c, 0x11, 0x0f, 0x14, 0x76, 0x06, 0xa9, 0xfc, 0x53, 0xf2, 0x7b, 0xf1, + 0xaa, 0xf3, 0x3e, 0xf5, 0xe3, 0x02, 0x16, 0x14, 0x9c, 0x10, 0xe3, 0x04, + 0x16, 0x00, 0xf6, 0xfd, 0xb8, 0xfe, 0xfa, 0xfe, 0x43, 0xfa, 0xb2, 0xf6, + 0xf5, 0xf4, 0xef, 0xef, 0xfe, 0xec, 0x44, 0xeb, 0x56, 0xef, 0x22, 0xeb, + 0x7f, 0xe0, 0x56, 0xe3, 0xa6, 0xe7, 0x3d, 0xea, 0xbb, 0xea, 0x5c, 0xe0, + 0x5c, 0xd4, 0x96, 0xd5, 0xcf, 0xde, 0xe6, 0xed, 0xd7, 0xf5, 0xd1, 0xee, + 0xae, 0xe4, 0x2f, 0xe3, 0xf1, 0xf0, 0x55, 0xfe, 0x17, 0xff, 0xdc, 0xef, + 0x7c, 0xe3, 0x4c, 0xdd, 0x30, 0xda, 0x7c, 0xe0, 0x9c, 0xe5, 0xd1, 0xed, + 0x78, 0xf6, 0x82, 0xfe, 0x52, 0x06, 0x72, 0x09, 0xc5, 0x0a, 0x0f, 0x10, + 0xee, 0x10, 0x92, 0xfd, 0x4a, 0xe8, 0x63, 0xdf, 0x41, 0xe6, 0xf5, 0xf9, + 0x33, 0x05, 0x3c, 0x06, 0xdc, 0x02, 0x75, 0xf5, 0xa1, 0xf1, 0xae, 0xfb, + 0xe2, 0x04, 0x04, 0x10, 0xeb, 0x0e, 0x2b, 0x09, 0x4e, 0x03, 0x2a, 0xf9, + 0xb3, 0xfa, 0xea, 0xff, 0xd4, 0xfa, 0x59, 0xee, 0x4d, 0xed, 0xf2, 0xf3, + 0xf3, 0xfb, 0x7d, 0x08, 0xc3, 0x0b, 0x84, 0x04, 0xa9, 0xf2, 0x73, 0xdd, + 0x17, 0xd1, 0x2d, 0xd1, 0xb8, 0xdb, 0x0e, 0xe3, 0x00, 0xe8, 0xa2, 0xf2, + 0xb6, 0xfa, 0xf8, 0xff, 0xea, 0x02, 0xba, 0x00, 0xbc, 0x00, 0xe5, 0xfb, + 0x6d, 0xf3, 0xf9, 0xf3, 0x6a, 0xf7, 0x30, 0xf4, 0x41, 0xef, 0x0a, 0xf2, + 0x35, 0xf4, 0x0c, 0xf4, 0x99, 0xfc, 0x7b, 0x06, 0x10, 0x08, 0xf4, 0x05, + 0x77, 0x03, 0xcc, 0x06, 0xb0, 0x0c, 0xfa, 0x0a, 0xa4, 0x07, 0x67, 0x05, + 0x6e, 0x06, 0x3f, 0x09, 0x39, 0x09, 0x6c, 0x0b, 0xac, 0x0c, 0x97, 0x0b, + 0xf7, 0x0b, 0x55, 0x08, 0xce, 0x08, 0xd0, 0x0d, 0x64, 0x0c, 0x1c, 0x11, + 0x95, 0x19, 0x8d, 0x1b, 0xd5, 0x12, 0xbb, 0x03, 0x75, 0xff, 0xd8, 0x00, + 0x08, 0x02, 0x27, 0x04, 0xec, 0x07, 0xb3, 0x0c, 0x84, 0x0c, 0x26, 0x0d, + 0xc9, 0x0a, 0x12, 0x03, 0x9a, 0xfd, 0x31, 0xf8, 0x4e, 0xfd, 0xbe, 0x09, + 0xcd, 0x1c, 0xd1, 0x33, 0xe9, 0x36, 0xf3, 0x2d, 0xe9, 0x1f, 0xb2, 0x14, + 0x82, 0x19, 0x84, 0x25, 0xe7, 0x26, 0x02, 0x1d, 0xed, 0x12, 0x97, 0x0a, + 0x7e, 0x14, 0xea, 0x21, 0x0a, 0x22, 0x9e, 0x17, 0x93, 0xfd, 0xec, 0xe7, + 0x57, 0xdc, 0x69, 0xd8, 0x6d, 0xd9, 0x77, 0xd9, 0x77, 0xe0, 0xdc, 0xea, + 0x9f, 0xee, 0x73, 0xe8, 0xfe, 0xe5, 0xc1, 0xec, 0xf3, 0xf0, 0x63, 0xfa, + 0x0a, 0x00, 0x84, 0xf5, 0x21, 0xeb, 0x28, 0xe5, 0xe7, 0xe8, 0x63, 0xea, + 0x82, 0xe1, 0xb1, 0xe0, 0x9a, 0xe5, 0x38, 0xeb, 0xc3, 0xed, 0xb0, 0xf5, + 0xa3, 0xfb, 0x4a, 0xf9, 0x6a, 0xfc, 0x4a, 0xf1, 0x35, 0xe2, 0x67, 0xda, + 0x91, 0xd5, 0x3a, 0xdc, 0xe5, 0xe2, 0x42, 0xe9, 0xd1, 0xe8, 0x2a, 0xde, + 0x0e, 0xd6, 0xb0, 0xe0, 0x48, 0xed, 0xf6, 0xe7, 0x1f, 0xe7, 0x02, 0xe4, + 0x46, 0xe4, 0x18, 0xea, 0x32, 0xe2, 0xe9, 0xdc, 0xbe, 0xdf, 0x01, 0xe2, + 0x32, 0xe5, 0x89, 0xe1, 0xd5, 0xd7, 0xe6, 0xd7, 0xec, 0xd7, 0xb6, 0xd7, + 0x49, 0xd6, 0xd9, 0xcc, 0x9c, 0xc9, 0x74, 0xc6, 0x5a, 0xc2, 0x75, 0xc0, + 0xa3, 0xc1, 0xaa, 0xce, 0xcc, 0xd8, 0xd1, 0xd9, 0x36, 0xe6, 0xc2, 0xea, + 0xdc, 0xde, 0x34, 0xdb, 0x1b, 0xd8, 0x15, 0xd3, 0xae, 0xd6, 0x90, 0xde, + 0xd6, 0xdd, 0x1b, 0xe8, 0x73, 0xf5, 0x1a, 0xfc, 0x44, 0x09, 0x17, 0x01, + 0x71, 0xff, 0x9c, 0x08, 0x77, 0x09, 0xb8, 0x12, 0xe4, 0x0c, 0xf5, 0xf6, + 0x29, 0xee, 0xec, 0xef, 0x76, 0xed, 0x0b, 0xf9, 0x51, 0x03, 0x76, 0x07, + 0x6c, 0x14, 0x13, 0x0d, 0x43, 0xf8, 0xee, 0xe6, 0x94, 0xe1, 0xb0, 0xeb, + 0xec, 0xee, 0x0a, 0xe1, 0xc9, 0xde, 0x4a, 0xf4, 0xdb, 0xf9, 0x5c, 0xef, + 0xef, 0xe6, 0xb8, 0xdc, 0x56, 0xd8, 0x70, 0xd6, 0x96, 0xd9, 0x8c, 0xe0, + 0x6b, 0xde, 0xa4, 0xd5, 0x6f, 0xcb, 0xc2, 0xc4, 0x4f, 0xc0, 0x7e, 0xbb, + 0x16, 0xb3, 0x59, 0xaf, 0x5a, 0xb0, 0xa3, 0xb0, 0x47, 0xb4, 0x43, 0xb8, + 0xc8, 0xc5, 0x7c, 0xd3, 0xb2, 0xd7, 0x7d, 0xd2, 0x77, 0xc7, 0xf2, 0xc1, + 0xe7, 0xc7, 0xde, 0xd0, 0xd5, 0xc9, 0x97, 0xbd, 0xb8, 0xbd, 0x55, 0xce, + 0x7d, 0xd5, 0x37, 0xd2, 0xea, 0xd4, 0xca, 0xd5, 0xa1, 0xdf, 0x1b, 0xe9, + 0xef, 0xe9, 0x4b, 0xec, 0x59, 0xec, 0xd3, 0xe6, 0xe1, 0xe8, 0x50, 0xea, + 0x25, 0xea, 0x43, 0xf1, 0x86, 0xf2, 0xa5, 0xf5, 0xa3, 0xf8, 0x59, 0xf6, + 0x0a, 0xf6, 0xc9, 0xfc, 0x17, 0x07, 0x93, 0x0b, 0x15, 0x04, 0x46, 0xfc, + 0xaf, 0x03, 0x1b, 0x11, 0x05, 0x17, 0xea, 0x14, 0xbb, 0x19, 0x58, 0x1a, + 0x9c, 0x0f, 0x86, 0x08, 0x08, 0x06, 0x65, 0x08, 0xd8, 0x13, 0xc2, 0x20, + 0x9b, 0x1e, 0xaa, 0x12, 0xa7, 0x08, 0x64, 0x04, 0x3f, 0x04, 0x24, 0x06, + 0x4f, 0x08, 0xfd, 0x0e, 0xce, 0x16, 0xdb, 0x19, 0x2b, 0x17, 0x0c, 0x09, + 0x8f, 0xff, 0xb0, 0xff, 0x62, 0x01, 0x02, 0x06, 0x72, 0x0b, 0x8e, 0x0c, + 0x8c, 0x0e, 0x8c, 0x0c, 0xfb, 0x09, 0x93, 0x0c, 0x97, 0x00, 0x9d, 0xf5, + 0x1d, 0xf6, 0x85, 0xfb, 0x8b, 0x00, 0x66, 0xf9, 0x3a, 0xf4, 0xe0, 0xfd, + 0x11, 0x04, 0x14, 0x04, 0xc5, 0x04, 0x8e, 0x04, 0xbf, 0x0c, 0x1b, 0x0c, + 0x5b, 0x07, 0x97, 0x0a, 0x38, 0x0e, 0xf0, 0x19, 0xd3, 0x23, 0x5b, 0x25, + 0xec, 0x20, 0xe8, 0x1a, 0x80, 0x14, 0xa2, 0x0d, 0xfe, 0x11, 0x9c, 0x1e, + 0xc9, 0x1a, 0xa5, 0x02, 0x91, 0xed, 0x5c, 0xe7, 0xc3, 0xe7, 0x28, 0xec, + 0xcd, 0xef, 0x39, 0xec, 0x3a, 0xed, 0x4b, 0xed, 0x8f, 0xee, 0xec, 0xf5, + 0xbc, 0xf8, 0xe7, 0x00, 0xe7, 0x0f, 0x68, 0x11, 0x9b, 0x0a, 0x22, 0x02, + 0xc2, 0xf8, 0x91, 0xff, 0x5c, 0x04, 0x30, 0x06, 0x56, 0x0c, 0xf9, 0x0e, + 0x64, 0x17, 0xd3, 0x1c, 0x86, 0x18, 0x40, 0x0d, 0x76, 0x07, 0x61, 0x02, + 0xec, 0xfd, 0xe7, 0x01, 0x16, 0x00, 0x9d, 0xfd, 0xb9, 0xfc, 0xec, 0xfa, + 0x19, 0x04, 0x7c, 0x0d, 0xe3, 0x04, 0x40, 0x04, 0xb4, 0x11, 0x2e, 0x11, + 0x6a, 0x11, 0xcd, 0x1a, 0xcd, 0x22, 0xb8, 0x26, 0x1c, 0x22, 0xc3, 0x19, + 0x22, 0x10, 0x9b, 0x15, 0xdc, 0x29, 0x80, 0x31, 0x36, 0x2c, 0x8d, 0x28, + 0x53, 0x26, 0x46, 0x20, 0x94, 0x1c, 0xe6, 0x1b, 0x75, 0x21, 0xc8, 0x29, + 0xda, 0x2c, 0xd4, 0x2a, 0xa5, 0x26, 0x43, 0x21, 0x28, 0x22, 0x27, 0x2b, + 0x2b, 0x2a, 0xbb, 0x30, 0x71, 0x34, 0x3f, 0x30, 0x03, 0x39, 0x18, 0x3d, + 0x74, 0x41, 0x5e, 0x39, 0xe9, 0x27, 0x1e, 0x28, 0x3d, 0x2e, 0x27, 0x33, + 0xd4, 0x31, 0xf5, 0x27, 0xf4, 0x28, 0x1e, 0x2d, 0x67, 0x2b, 0x8d, 0x26, + 0x27, 0x17, 0xcc, 0x11, 0xfc, 0x10, 0x7c, 0x08, 0x64, 0x06, 0xe9, 0x0a, + 0x84, 0x06, 0x41, 0x00, 0xe3, 0x04, 0x7e, 0x08, 0x3c, 0x0c, 0xc7, 0x12, + 0x3a, 0x13, 0x38, 0x05, 0xbd, 0xf9, 0xa6, 0xee, 0xcc, 0xeb, 0x00, 0xfa, + 0x11, 0xff, 0x64, 0xfa, 0xa5, 0xf7, 0xd9, 0xfa, 0x51, 0xf2, 0x1d, 0xf6, + 0x74, 0x04, 0x73, 0x04, 0x55, 0x07, 0xf0, 0x04, 0xf8, 0xfd, 0x64, 0x00, + 0xc9, 0x06, 0x46, 0x07, 0xb5, 0x0d, 0x38, 0x08, 0xe8, 0xff, 0x92, 0x04, + 0x52, 0x06, 0x34, 0x08, 0xdb, 0x02, 0xf5, 0x06, 0x2a, 0x12, 0xef, 0x1d, + 0x2b, 0x23, 0xd8, 0x2a, 0x29, 0x32, 0xd8, 0x21, 0xac, 0x17, 0x8a, 0x10, + 0x82, 0x11, 0xad, 0x1c, 0x3a, 0x27, 0x9a, 0x2e, 0x6c, 0x29, 0x2d, 0x26, + 0xce, 0x1f, 0x90, 0x1e, 0x6b, 0x23, 0x8d, 0x29, 0xd7, 0x34, 0xe5, 0x35, + 0xff, 0x2e, 0xbe, 0x27, 0x96, 0x25, 0xc8, 0x1e, 0x3d, 0x1d, 0xe2, 0x23, + 0x02, 0x25, 0x85, 0x2d, 0xf9, 0x28, 0xca, 0x19, 0xe5, 0x13, 0x5a, 0x19, + 0xcc, 0x1f, 0x56, 0x19, 0x5c, 0x12, 0xf7, 0x0c, 0x16, 0x15, 0x03, 0x1e, + 0xa7, 0x1e, 0xd7, 0x1f, 0x3e, 0x19, 0xd0, 0x0e, 0x98, 0x0c, 0x8d, 0x1b, + 0x1f, 0x28, 0x52, 0x30, 0x33, 0x2e, 0x32, 0x1d, 0x5d, 0x0c, 0x95, 0x02, + 0x9f, 0x04, 0x29, 0x04, 0x5d, 0x02, 0x6a, 0x03, 0x27, 0x08, 0x41, 0x10, + 0x5b, 0x16, 0x28, 0x15, 0xf7, 0x11, 0x68, 0x17, 0xa5, 0x17, 0xe3, 0x0f, + 0xd5, 0x0e, 0xe9, 0x15, 0x11, 0x16, 0x1a, 0x15, 0x8a, 0x15, 0x13, 0x0f, + 0x88, 0x07, 0x9d, 0x00, 0xaf, 0x06, 0x94, 0x18, 0xf6, 0x21, 0x17, 0x20, + 0xfd, 0x1b, 0xb7, 0x18, 0xb6, 0x19, 0x8c, 0x18, 0xc4, 0x14, 0x93, 0x19, + 0xe2, 0x1d, 0x49, 0x1d, 0x1e, 0x1f, 0x6f, 0x21, 0x77, 0x23, 0xed, 0x21, + 0x6b, 0x16, 0x6f, 0x0b, 0x6a, 0x0b, 0xcf, 0x13, 0x6a, 0x22, 0x31, 0x2f, + 0xfa, 0x2b, 0xb9, 0x24, 0xcf, 0x26, 0x79, 0x27, 0x70, 0x23, 0xb3, 0x1b, + 0x84, 0x1c, 0xe8, 0x27, 0xbf, 0x2d, 0x66, 0x28, 0x45, 0x22, 0x93, 0x19, + 0xf8, 0x04, 0xf3, 0xf7, 0x90, 0xf3, 0x15, 0xf3, 0x49, 0xf6, 0x82, 0xf4, + 0x77, 0xee, 0xad, 0xea, 0x53, 0xf3, 0xa9, 0xfa, 0xa5, 0xf9, 0xfe, 0xf6, + 0x05, 0xf2, 0x4e, 0xf0, 0x7c, 0xf3, 0x92, 0xf9, 0xbb, 0x02, 0x79, 0x01, + 0xab, 0xf7, 0x65, 0xf5, 0x37, 0xf2, 0xe6, 0xf8, 0x99, 0x0b, 0xc3, 0x14, + 0x1f, 0x15, 0x71, 0x13, 0xea, 0x0d, 0x5d, 0x02, 0x83, 0xfa, 0x43, 0xfd, + 0xf8, 0x08, 0x3e, 0x11, 0xd8, 0x0d, 0xd6, 0x00, 0xe4, 0xef, 0xd7, 0xea, + 0x33, 0xf1, 0x15, 0xf9, 0xac, 0xf8, 0xb9, 0xf7, 0x09, 0x02, 0x51, 0x07, + 0xb8, 0x08, 0xa1, 0x0f, 0x09, 0x16, 0xfa, 0x1b, 0xb9, 0x20, 0xc6, 0x1f, + 0x55, 0x25, 0x4e, 0x2f, 0x2b, 0x30, 0xc8, 0x33, 0x45, 0x33, 0xcb, 0x29, + 0xd1, 0x26, 0x3e, 0x28, 0xb7, 0x25, 0xd9, 0x29, 0x44, 0x33, 0x31, 0x2c, + 0x5f, 0x21, 0x89, 0x1a, 0xd6, 0x17, 0x88, 0x1e, 0x62, 0x1f, 0x0c, 0x1c, + 0xb7, 0x19, 0x31, 0x18, 0xe7, 0x1b, 0x04, 0x21, 0xd8, 0x1f, 0x0d, 0x1b, + 0xd8, 0x16, 0x07, 0x17, 0xdc, 0x20, 0xb5, 0x24, 0xb6, 0x23, 0x6f, 0x29, + 0xd5, 0x2a, 0x2c, 0x2a, 0xb8, 0x2a, 0x05, 0x27, 0x9d, 0x25, 0x52, 0x22, + 0xb0, 0x18, 0x0e, 0x16, 0xff, 0x16, 0x93, 0x16, 0x56, 0x1a, 0xba, 0x18, + 0xaa, 0x0e, 0x40, 0x06, 0x9d, 0x00, 0xe9, 0xfa, 0xa9, 0xf8, 0xe3, 0xfb, + 0xc3, 0xfc, 0xdf, 0xf6, 0xb0, 0xf4, 0xbe, 0xf7, 0xda, 0xf4, 0xab, 0xf1, + 0xcf, 0xf2, 0xe8, 0xee, 0xf1, 0xee, 0x78, 0xea, 0xd2, 0xde, 0x6a, 0xe0, + 0xef, 0xe3, 0x5d, 0xe8, 0x92, 0xf5, 0xc9, 0x05, 0x72, 0x0f, 0xb9, 0x0f, + 0x87, 0x0a, 0x38, 0x05, 0xaa, 0x05, 0x41, 0xfd, 0x55, 0xf4, 0x6b, 0xec, + 0xcf, 0xe5, 0xb2, 0xf1, 0x56, 0xf1, 0xf5, 0xec, 0x86, 0xfd, 0x46, 0xfb, + 0x32, 0xed, 0x11, 0xf2, 0xc9, 0xe7, 0xfd, 0xe0, 0x49, 0xf3, 0x4a, 0xef, + 0xf1, 0xeb, 0xbd, 0xef, 0xee, 0xd7, 0x02, 0xcf, 0x3d, 0xe0, 0x6f, 0xdd, + 0x97, 0xdd, 0x33, 0xe8, 0x02, 0xe0, 0x86, 0xe5, 0x11, 0xf1, 0x44, 0xf3, + 0x15, 0xfd, 0x76, 0xfa, 0xf8, 0xe6, 0xff, 0xdf, 0x8d, 0xee, 0x32, 0xf7, + 0xb6, 0xff, 0x5c, 0x0a, 0x62, 0x00, 0x0d, 0xf5, 0x4c, 0xf3, 0x25, 0xf2, + 0xdf, 0xf6, 0xab, 0xfa, 0x86, 0xf2, 0x9d, 0xec, 0x5e, 0xe6, 0xd1, 0xdd, + 0xa9, 0xe2, 0xbb, 0xe6, 0x90, 0xe7, 0x64, 0xf0, 0xda, 0xf2, 0x56, 0xef, + 0x5d, 0xf4, 0xa7, 0xef, 0xb4, 0xe5, 0x7a, 0xe7, 0x3a, 0xe2, 0x28, 0xde, + 0x49, 0xe0, 0xbf, 0xe0, 0x67, 0xe2, 0xeb, 0xe7, 0x7a, 0xf1, 0x60, 0xf7, + 0xfc, 0xf9, 0x32, 0xf1, 0x8c, 0xe6, 0xfc, 0xdf, 0x9f, 0xd4, 0xbb, 0xd5, + 0xe8, 0xda, 0x17, 0xd6, 0x52, 0xd5, 0x4e, 0xd6, 0x8f, 0xcf, 0xa6, 0xd1, + 0x19, 0xda, 0xb2, 0xdc, 0xc2, 0xe2, 0x4a, 0xe5, 0xe8, 0xe2, 0x6d, 0xe3, + 0xce, 0xe3, 0xc5, 0xe1, 0xc2, 0xe6, 0x57, 0xeb, 0x96, 0xe7, 0x6c, 0xe8, + 0x52, 0xe6, 0x3c, 0xe5, 0xc1, 0xe8, 0x07, 0xeb, 0x10, 0xf3, 0xc5, 0xfc, + 0x65, 0x00, 0x13, 0xfd, 0x87, 0xf7, 0x1b, 0xf3, 0x3c, 0xf3, 0x20, 0xf8, + 0x3f, 0xf9, 0x71, 0xf9, 0xa7, 0xfd, 0x43, 0xfd, 0x3a, 0xff, 0x7b, 0x02, + 0xcd, 0xfa, 0x74, 0xf6, 0xb5, 0xf4, 0x1c, 0xf6, 0xf5, 0x01, 0xc9, 0x09, + 0x51, 0x04, 0x0e, 0xf3, 0x49, 0xe3, 0xde, 0xdf, 0xeb, 0xe5, 0x3c, 0xeb, + 0x1d, 0xe3, 0x61, 0xd1, 0x39, 0xc2, 0xad, 0xbf, 0xe9, 0xd3, 0x2e, 0xe8, + 0x63, 0xe9, 0x2d, 0xe4, 0xb6, 0xda, 0xe4, 0xd7, 0x7b, 0xe0, 0x38, 0xeb, + 0x9c, 0xf4, 0x90, 0xf4, 0xc8, 0xea, 0xf4, 0xdd, 0xa0, 0xd8, 0x7f, 0xe1, + 0xd2, 0xf4, 0x78, 0x08, 0x5a, 0x09, 0x87, 0xfe, 0x6e, 0xfc, 0xfa, 0x01, + 0x10, 0x11, 0x28, 0x12, 0x77, 0xfb, 0xda, 0xeb, 0xbf, 0xe8, 0x73, 0xf0, + 0x91, 0xfe, 0xea, 0x06, 0xc1, 0x06, 0x96, 0x03, 0x8d, 0x04, 0x2e, 0x0f, + 0xb6, 0x17, 0x40, 0x0f, 0x15, 0x09, 0x5c, 0x0d, 0xe2, 0x0e, 0x56, 0x0c, + 0xa2, 0x09, 0x4c, 0x09, 0x79, 0x0a, 0x37, 0x0b, 0xc4, 0x10, 0x1f, 0x14, + 0xd8, 0x11, 0x20, 0x0f, 0x97, 0x02, 0x5f, 0xfc, 0x1a, 0xfe, 0x3c, 0xfe, + 0xff, 0x01, 0x1d, 0xfe, 0x06, 0xf7, 0x2b, 0xef, 0xbe, 0xed, 0x83, 0xfc, + 0xa8, 0x0c, 0x1b, 0x0c, 0xe4, 0xfc, 0x23, 0xed, 0x47, 0xde, 0xc1, 0xd6, + 0xbe, 0xd8, 0xa6, 0xde, 0x9d, 0xe3, 0x99, 0xdf, 0xc5, 0xdb, 0xe6, 0xdf, + 0xf1, 0xe5, 0xf5, 0xe8, 0x1a, 0xe7, 0xa7, 0xe5, 0xf6, 0xe6, 0x9a, 0xee, + 0xa2, 0xf7, 0xb6, 0xf3, 0x82, 0xea, 0xdb, 0xe2, 0x49, 0xde, 0x56, 0xe2, + 0x29, 0xe9, 0x05, 0xe5, 0xf8, 0xdc, 0x14, 0xe0, 0x35, 0xe1, 0x57, 0xe1, + 0x57, 0xe8, 0x44, 0xea, 0xb8, 0xeb, 0xcd, 0xf1, 0xce, 0xf2, 0xe4, 0xf3, + 0x6e, 0xf9, 0x1e, 0xfc, 0xc7, 0xff, 0x00, 0x08, 0x20, 0x0e, 0x96, 0x0c, + 0x44, 0x0b, 0x16, 0x09, 0xda, 0x00, 0xeb, 0xf9, 0x5e, 0xfa, 0x1e, 0x00, + 0x5d, 0x00, 0x2e, 0xf9, 0x6d, 0xee, 0x69, 0xe8, 0x91, 0xe8, 0x42, 0xeb, + 0x9b, 0xef, 0x2d, 0xf3, 0x6e, 0xf4, 0xde, 0xe9, 0xd7, 0xe3, 0x09, 0xe5, + 0x9e, 0xe0, 0x44, 0xea, 0x7e, 0xf9, 0x54, 0xfb, 0xc3, 0xfd, 0x6a, 0x01, + 0x2e, 0xfc, 0xf4, 0xfc, 0xf2, 0x04, 0x64, 0x0f, 0xdb, 0x1a, 0xf9, 0x1d, + 0x4a, 0x1f, 0xb4, 0x19, 0x0a, 0x13, 0x6d, 0x12, 0x87, 0x14, 0x18, 0x18, + 0xf0, 0x0d, 0x67, 0x08, 0xd7, 0x0b, 0x3d, 0x09, 0x36, 0x0a, 0x2f, 0x05, + 0xa7, 0xfa, 0xa9, 0xf6, 0xf3, 0xf1, 0x7a, 0xec, 0x41, 0xed, 0x5f, 0xeb, + 0xac, 0xdd, 0x05, 0xd3, 0x3f, 0xd6, 0x2c, 0xdd, 0x15, 0xe3, 0x74, 0xe9, + 0x04, 0xe9, 0x5b, 0xe2, 0x1d, 0xe6, 0x0b, 0xf3, 0x70, 0xf4, 0x88, 0xef, + 0xa9, 0xf7, 0xb6, 0xfd, 0xf0, 0xfe, 0xd6, 0x0b, 0xdd, 0x0d, 0xbd, 0x09, + 0xfd, 0x12, 0xc9, 0x1e, 0x2c, 0x26, 0x4d, 0x24, 0x7f, 0x20, 0xa1, 0x1b, + 0xdd, 0x1a, 0xea, 0x18, 0x31, 0x12, 0x40, 0x11, 0x22, 0x0e, 0xa3, 0x0e, + 0xe0, 0x0c, 0x0d, 0x0a, 0xaf, 0x0c, 0x3b, 0x0d, 0x96, 0x0d, 0xea, 0x12, + 0x1d, 0x17, 0x95, 0x13, 0xc0, 0x12, 0xe9, 0x0d, 0x44, 0x10, 0x17, 0x19, + 0x54, 0x20, 0xa1, 0x27, 0xfe, 0x25, 0x57, 0x2a, 0x8f, 0x29, 0x61, 0x26, + 0xca, 0x26, 0x0b, 0x29, 0x65, 0x2c, 0xdf, 0x26, 0x2e, 0x26, 0x1c, 0x24, + 0xea, 0x20, 0xc2, 0x1f, 0x98, 0x1d, 0x9d, 0x15, 0xd7, 0x0a, 0xb2, 0x07, + 0xbb, 0x06, 0x3b, 0x0d, 0x7f, 0x11, 0x43, 0x13, 0x5d, 0x14, 0x13, 0x12, + 0x13, 0x12, 0xc7, 0x13, 0x5c, 0x1c, 0x08, 0x24, 0x97, 0x25, 0x2c, 0x25, + 0x02, 0x28, 0x35, 0x2e, 0x07, 0x36, 0x54, 0x38, 0x00, 0x31, 0x29, 0x27, + 0x79, 0x20, 0xd5, 0x22, 0x42, 0x1f, 0xa2, 0x13, 0x1a, 0x0a, 0x7d, 0xff, + 0xcf, 0xfc, 0x44, 0x05, 0x66, 0x0f, 0x61, 0x15, 0xfa, 0x10, 0x5c, 0x04, + 0x2e, 0xfd, 0x2c, 0xfe, 0x3f, 0x08, 0x1a, 0x16, 0x2f, 0x19, 0x59, 0x0d, + 0xa0, 0xfd, 0xd6, 0xfa, 0x6d, 0x05, 0x4c, 0x17, 0xd3, 0x26, 0x3c, 0x2b, + 0xeb, 0x29, 0x25, 0x27, 0x9b, 0x28, 0x9f, 0x2e, 0x77, 0x2e, 0x2a, 0x2e, + 0x6d, 0x31, 0x7b, 0x27, 0x4f, 0x18, 0x5c, 0x15, 0xe0, 0x19, 0xbd, 0x1d, + 0xb7, 0x1b, 0x50, 0x18, 0x3d, 0x19, 0x7e, 0x18, 0xae, 0x10, 0xc0, 0x00, + 0x2f, 0xf6, 0x38, 0xfc, 0x09, 0x06, 0xa0, 0x0a, 0x50, 0x0c, 0xda, 0x0e, + 0xd1, 0x14, 0x0f, 0x18, 0xb3, 0x13, 0x0e, 0x12, 0xa5, 0x16, 0xcb, 0x19, + 0xfd, 0x1c, 0x0b, 0x19, 0xa4, 0x09, 0x30, 0x02, 0x75, 0x07, 0x9a, 0x0b, + 0x04, 0x0f, 0xb9, 0x10, 0x43, 0x0d, 0xbd, 0x09, 0x3c, 0x02, 0x94, 0xfa, + 0x72, 0xfd, 0x81, 0xfb, 0x68, 0xf1, 0x00, 0xec, 0x99, 0xeb, 0x67, 0xed, + 0x1c, 0xe7, 0xa8, 0xdd, 0x97, 0xd9, 0xf1, 0xda, 0x82, 0xe3, 0xee, 0xea, + 0xe1, 0xed, 0xc9, 0xee, 0x97, 0xf1, 0x12, 0xf4, 0xde, 0xf6, 0x5c, 0xf9, + 0x79, 0xf6, 0x5f, 0xf5, 0x87, 0xfc, 0xf8, 0x01, 0xb5, 0x00, 0xbb, 0x07, + 0xa5, 0x06, 0x06, 0xf8, 0x81, 0xeb, 0xfe, 0xe1, 0x7d, 0xe7, 0xc4, 0xec, + 0xe3, 0xe6, 0xaf, 0xe3, 0xec, 0xe2, 0x38, 0xe9, 0x25, 0xfa, 0xa3, 0x05, + 0xc8, 0x06, 0x5a, 0x06, 0x2b, 0x04, 0x1f, 0x03, 0x78, 0x02, 0xf3, 0x01, + 0xb8, 0x04, 0xc7, 0x07, 0x2a, 0x0c, 0x97, 0x10, 0xf9, 0x12, 0x29, 0x18, + 0xe1, 0x1b, 0xa5, 0x1a, 0x1e, 0x18, 0x07, 0x12, 0x49, 0x06, 0x97, 0xf8, + 0xb5, 0xef, 0x73, 0xea, 0xe4, 0xec, 0x07, 0xf2, 0xb7, 0xea, 0x2d, 0xdb, + 0xda, 0xcc, 0xea, 0xca, 0xab, 0xd2, 0x60, 0xd7, 0x81, 0xd7, 0xf1, 0xcf, + 0x1e, 0xca, 0xe1, 0xcf, 0x2c, 0xd7, 0xc5, 0xde, 0x2d, 0xe0, 0x57, 0xdd, + 0x7b, 0xe3, 0x63, 0xec, 0xdb, 0xf9, 0x48, 0x07, 0xa8, 0x10, 0xed, 0x14, + 0x0e, 0x0f, 0xc3, 0x0b, 0x76, 0x16, 0x25, 0x28, 0x02, 0x30, 0x3e, 0x27, + 0xce, 0x1a, 0x2f, 0x20, 0xcc, 0x29, 0xf5, 0x30, 0x9f, 0x39, 0x1f, 0x30, + 0x89, 0x27, 0xf0, 0x26, 0xf5, 0x16, 0x0e, 0x0e, 0xfa, 0x15, 0x5b, 0x14, + 0x6e, 0x14, 0x52, 0x15, 0x6a, 0x0a, 0xfd, 0x06, 0x12, 0x0a, 0x07, 0x06, + 0xb3, 0x00, 0x54, 0x03, 0x59, 0xfd, 0xa9, 0xf3, 0xca, 0xf4, 0x0e, 0xf2, + 0xab, 0xef, 0x21, 0xf3, 0x55, 0xfa, 0xa3, 0x02, 0xc5, 0x08, 0x4d, 0x0c, + 0xb3, 0x04, 0x02, 0xfc, 0xf0, 0xfb, 0xa8, 0xf6, 0x9e, 0xf0, 0xad, 0xf8, + 0x74, 0xfe, 0xc8, 0xfc, 0x82, 0xf9, 0x3c, 0xe8, 0xf6, 0xe0, 0xaa, 0xec, + 0xc0, 0xf3, 0x06, 0xf5, 0x06, 0xf2, 0x9a, 0xf0, 0x9f, 0xf1, 0xb7, 0xfa, + 0x7e, 0x05, 0xa4, 0x07, 0x8b, 0x0e, 0x7f, 0x13, 0xdd, 0x13, 0xed, 0x16, + 0x70, 0x18, 0xb8, 0x15, 0x76, 0x11, 0x6d, 0x0c, 0x0f, 0x09, 0x6b, 0x0b, + 0xfb, 0x10, 0xd8, 0x16, 0x06, 0x1a, 0x9e, 0x1d, 0xa0, 0x20, 0x97, 0x24, + 0xa0, 0x2a, 0x62, 0x29, 0x3e, 0x24, 0x3c, 0x20, 0xd2, 0x17, 0x36, 0x0f, + 0xb6, 0x11, 0xd4, 0x19, 0xfd, 0x19, 0x4c, 0x11, 0x86, 0x08, 0x69, 0xff, + 0x98, 0xf5, 0x66, 0xf6, 0x09, 0xfe, 0x8f, 0xff, 0x9f, 0xfc, 0x8c, 0xf4, + 0x7d, 0xeb, 0xb7, 0xec, 0xff, 0xf1, 0xa6, 0xf5, 0x7b, 0xef, 0x1e, 0xe2, + 0xf3, 0xd7, 0x9f, 0xd6, 0x24, 0xe4, 0x81, 0xee, 0x43, 0xed, 0x94, 0xe5, + 0x49, 0xde, 0xd7, 0xe1, 0x3a, 0xf0, 0xc9, 0x01, 0x26, 0x09, 0xd9, 0x00, + 0x17, 0xf0, 0xa9, 0xe7, 0x40, 0xef, 0x65, 0xfd, 0x04, 0x04, 0x07, 0xff, + 0x17, 0xfc, 0x55, 0xfb, 0x4d, 0xf7, 0x8a, 0xf9, 0x00, 0xfb, 0x69, 0xfb, + 0x3c, 0x01, 0xfb, 0xfd, 0xbe, 0xf7, 0x6a, 0xf5, 0x64, 0xeb, 0x07, 0xde, + 0x46, 0xd7, 0x70, 0xd1, 0x75, 0xcf, 0x6b, 0xd3, 0xce, 0xd1, 0xae, 0xcd, + 0x43, 0xcc, 0xd4, 0xd3, 0xbf, 0xdb, 0x60, 0xda, 0x3b, 0xd5, 0xe2, 0xce, + 0xf1, 0xd4, 0xe3, 0xdf, 0x3c, 0xe0, 0x61, 0xe0, 0xac, 0xe3, 0x7b, 0xe2, + 0xe2, 0xde, 0x03, 0xdc, 0xaa, 0xdb, 0xb5, 0xde, 0x5f, 0xe2, 0x82, 0xdf, + 0xc1, 0xd6, 0x44, 0xd8, 0x46, 0xe0, 0xe7, 0xe5, 0x45, 0xea, 0x3f, 0xea, + 0x79, 0xea, 0xbc, 0xec, 0x1a, 0xeb, 0x41, 0xe5, 0x3a, 0xe0, 0xdf, 0xde, + 0xb9, 0xdf, 0x2e, 0xdd, 0x09, 0xdc, 0x97, 0xe3, 0xfe, 0xea, 0x8c, 0xec, + 0xf5, 0xe9, 0x7f, 0xe6, 0xcf, 0xee, 0x06, 0xfb, 0x3c, 0xfe, 0x41, 0x00, + 0x67, 0xfa, 0x50, 0xf5, 0x25, 0xf8, 0x2a, 0xf2, 0xdd, 0xea, 0xa5, 0xe9, + 0xbd, 0xeb, 0xeb, 0xef, 0x2a, 0xf4, 0x73, 0xf5, 0x0a, 0xee, 0x6f, 0xe5, + 0x5f, 0xe4, 0xba, 0xe1, 0xa8, 0xe1, 0x5d, 0xe8, 0xba, 0xe8, 0xac, 0xe7, + 0xb2, 0xe9, 0x9f, 0xf0, 0x2d, 0xfb, 0x37, 0x00, 0x5f, 0x02, 0xc6, 0x02, + 0xaf, 0xff, 0x8d, 0xfe, 0x07, 0x04, 0x6f, 0x07, 0xb0, 0x0b, 0x4d, 0x12, + 0xc3, 0x14, 0xd0, 0x19, 0xc0, 0x19, 0xd3, 0x19, 0x5e, 0x1d, 0xe4, 0x11, + 0x06, 0x04, 0xb1, 0xfe, 0xc9, 0xf6, 0x77, 0xf2, 0xd8, 0xf0, 0x27, 0xe7, + 0x97, 0xe5, 0xa0, 0xeb, 0xe2, 0xe7, 0xe2, 0xe6, 0x74, 0xec, 0x9f, 0xed, + 0x7b, 0xed, 0x9b, 0xee, 0xae, 0xee, 0x99, 0xeb, 0x66, 0xe2, 0xe4, 0xd9, + 0x4a, 0xdd, 0x39, 0xe5, 0x2e, 0xed, 0xd1, 0xf3, 0x15, 0xf4, 0x8d, 0xf2, + 0x7f, 0xf1, 0x1a, 0xf7, 0xe1, 0xfd, 0x34, 0x04, 0x00, 0x0d, 0x0b, 0x0a, + 0x7b, 0x04, 0xfd, 0x01, 0x54, 0xfa, 0xfb, 0xf9, 0x4a, 0x03, 0x41, 0x08, + 0xc4, 0x07, 0x5d, 0xfe, 0xea, 0xf1, 0x7b, 0xf6, 0x84, 0xfe, 0x13, 0x02, + 0x1c, 0x06, 0x72, 0xfc, 0x5b, 0xf4, 0x79, 0x03, 0x18, 0x13, 0xe6, 0x1a, + 0x8b, 0x23, 0xb6, 0x22, 0xb3, 0x1d, 0x1b, 0x1d, 0x12, 0x21, 0xda, 0x25, + 0xff, 0x2a, 0x43, 0x2c, 0x1b, 0x23, 0x21, 0x1b, 0x96, 0x13, 0xa8, 0x10, + 0x36, 0x0f, 0x10, 0x04, 0x87, 0xfb, 0xbd, 0xf1, 0x53, 0xe6, 0xfa, 0xe2, + 0xc2, 0xe2, 0x68, 0xe5, 0x18, 0xe7, 0x83, 0xe1, 0x8b, 0xdd, 0x5c, 0xdc, + 0x1e, 0xde, 0xb0, 0xe5, 0x3f, 0xe6, 0x76, 0xe4, 0x78, 0xe7, 0x9f, 0xe9, + 0x0a, 0xf1, 0x17, 0xfc, 0x84, 0x01, 0xd1, 0x09, 0xc9, 0x13, 0xbe, 0x12, + 0x89, 0x14, 0x2c, 0x17, 0x92, 0x16, 0x56, 0x1e, 0xb2, 0x1a, 0xe8, 0x0d, + 0x4b, 0x0e, 0xed, 0x0f, 0xf6, 0x13, 0x29, 0x1f, 0x42, 0x21, 0x58, 0x22, + 0xba, 0x24, 0xd1, 0x1e, 0x9a, 0x1d, 0xa0, 0x20, 0x5e, 0x24, 0x0a, 0x29, + 0x1f, 0x27, 0x71, 0x27, 0x20, 0x2f, 0x43, 0x31, 0xec, 0x2e, 0x30, 0x2f, + 0xbe, 0x2b, 0x7d, 0x27, 0xaa, 0x27, 0xab, 0x28, 0x1c, 0x2b, 0x98, 0x2d, + 0xc8, 0x27, 0x9e, 0x1e, 0x2e, 0x1b, 0xdf, 0x19, 0xc7, 0x17, 0xbb, 0x0c, + 0x87, 0xf7, 0xef, 0xe7, 0x5d, 0xe7, 0xe6, 0xef, 0x69, 0xf8, 0x0f, 0xf5, + 0xcc, 0xe0, 0x17, 0xd0, 0xad, 0xd2, 0xdc, 0xe3, 0x18, 0xf7, 0x67, 0xff, + 0x21, 0xfd, 0x09, 0xf7, 0x0f, 0xf2, 0x2e, 0xf6, 0x97, 0x02, 0x0e, 0x06, + 0xd1, 0xfc, 0x33, 0xf3, 0x4c, 0xef, 0x1b, 0xf5, 0x7b, 0xff, 0xb0, 0x04, + 0x46, 0x07, 0x77, 0x0a, 0x4c, 0x0b, 0x9b, 0x0c, 0xc0, 0x11, 0x72, 0x16, + 0xf4, 0x18, 0x84, 0x18, 0x44, 0x10, 0x8d, 0x07, 0x39, 0x05, 0xa8, 0x00, + 0x64, 0xf9, 0xaf, 0xf7, 0x0d, 0xfb, 0x0a, 0x00, 0x57, 0x04, 0x7f, 0x04, + 0xbd, 0x05, 0x8e, 0x0e, 0xce, 0x19, 0xca, 0x1d, 0x6f, 0x1b, 0x65, 0x1d, + 0xe9, 0x23, 0xe5, 0x2a, 0xe8, 0x2d, 0xe7, 0x2a, 0x19, 0x29, 0x86, 0x25, + 0x0a, 0x1d, 0x31, 0x18, 0x5c, 0x1a, 0x6f, 0x1e, 0xb2, 0x23, 0x61, 0x24, + 0x07, 0x1e, 0xae, 0x1d, 0xbf, 0x1d, 0x6a, 0x1b, 0xbc, 0x1b, 0xbf, 0x15, + 0x8c, 0x0c, 0x60, 0x05, 0x9b, 0xff, 0x8e, 0xfa, 0xbb, 0xf7, 0x0d, 0xfd, + 0x7d, 0x06, 0x22, 0x09, 0xbd, 0x05, 0xdc, 0x04, 0xca, 0x09, 0x44, 0x16, + 0x22, 0x1c, 0x87, 0x17, 0x78, 0x14, 0xec, 0x10, 0x43, 0x17, 0x8c, 0x26, + 0xaa, 0x2b, 0x19, 0x28, 0x43, 0x23, 0x24, 0x1c, 0xc6, 0x19, 0x81, 0x1b, + 0x32, 0x1a, 0xdc, 0x18, 0x7b, 0x11, 0x02, 0x0e, 0x16, 0x14, 0x37, 0x1b, + 0xcd, 0x26, 0x03, 0x2a, 0xc4, 0x23, 0xe3, 0x25, 0xc6, 0x2a, 0xe6, 0x2c, + 0x30, 0x32, 0x76, 0x30, 0xd3, 0x2a, 0xcf, 0x29, 0x29, 0x28, 0xd2, 0x2a, + 0xee, 0x28, 0x5d, 0x20, 0x30, 0x1d, 0x6a, 0x1e, 0xa4, 0x1d, 0x73, 0x18, + 0x46, 0x17, 0xe4, 0x12, 0x13, 0x0c, 0x3a, 0x0b, 0xdb, 0x07, 0x44, 0x0c, + 0x8b, 0x13, 0xbb, 0x11, 0x4c, 0x0c, 0x3a, 0x02, 0x25, 0xfc, 0xbc, 0xfb, + 0xcb, 0xfb, 0x1f, 0xfb, 0x13, 0xfc, 0x25, 0x01, 0x63, 0x03, 0x83, 0x05, + 0x46, 0x08, 0x0a, 0x0b, 0x78, 0x0e, 0xd0, 0x0f, 0xcf, 0x10, 0x14, 0x11, + 0xd3, 0x10, 0x2d, 0x17, 0x00, 0x20, 0xe5, 0x1d, 0x3b, 0x17, 0xac, 0x11, + 0xd5, 0x0f, 0x47, 0x16, 0xf2, 0x19, 0xbe, 0x14, 0xc3, 0x0d, 0x21, 0x0a, + 0xb6, 0x0d, 0x76, 0x17, 0xc9, 0x1b, 0x20, 0x1a, 0x11, 0x13, 0x92, 0x0a, + 0xf7, 0x08, 0x65, 0x09, 0x89, 0x10, 0x04, 0x16, 0xc5, 0x0e, 0xd6, 0x04, + 0xa0, 0x03, 0x8e, 0x0c, 0x13, 0x1a, 0x54, 0x26, 0xb7, 0x28, 0x89, 0x26, + 0x73, 0x24, 0x08, 0x21, 0x34, 0x21, 0xe2, 0x24, 0x6f, 0x2a, 0x1a, 0x29, + 0x4f, 0x1e, 0x7e, 0x18, 0x80, 0x19, 0x1d, 0x1a, 0x86, 0x1b, 0x92, 0x17, + 0xbd, 0x0b, 0xd7, 0x04, 0xde, 0xff, 0x61, 0xf3, 0xb9, 0xe8, 0x27, 0xe0, + 0xf2, 0xd4, 0xec, 0xd5, 0x94, 0xdc, 0x03, 0xd9, 0x9a, 0xd9, 0x3c, 0xdb, + 0x63, 0xd2, 0x01, 0xd2, 0xf0, 0xda, 0xa6, 0xdf, 0x2a, 0xe8, 0x1a, 0xec, + 0x25, 0xe5, 0xaf, 0xe5, 0xc7, 0xe7, 0x50, 0xe9, 0x7e, 0xf8, 0x44, 0x06, + 0x6e, 0x09, 0x7c, 0x0d, 0x5d, 0x0b, 0xed, 0x04, 0x99, 0x0d, 0x0f, 0x13, + 0x96, 0x0b, 0xfc, 0x08, 0x85, 0x07, 0x8c, 0x0b, 0xb6, 0x13, 0x62, 0x10, + 0x86, 0x08, 0xb4, 0x07, 0x53, 0x09, 0x38, 0x0a, 0xc5, 0x09, 0xe1, 0x09, + 0x43, 0x0b, 0x55, 0x03, 0x56, 0xff, 0x42, 0x02, 0x3c, 0x04, 0x70, 0x0e, + 0xf0, 0x13, 0x0e, 0x14, 0xc4, 0x10, 0xa9, 0x06, 0xe9, 0xfd, 0x59, 0xf6, + 0x6f, 0xf2, 0x8d, 0xf4, 0x8d, 0xfa, 0x58, 0xfa, 0xe8, 0xf1, 0xac, 0xf0, + 0xcf, 0xf3, 0xd5, 0xf0, 0xe7, 0xf0, 0x6b, 0xf3, 0xd4, 0xf0, 0xcb, 0xf3, + 0x0c, 0xf7, 0x90, 0xf2, 0x8e, 0xf1, 0x3d, 0xf3, 0x4b, 0xf2, 0x41, 0xee, + 0xb9, 0xe7, 0xcc, 0xe5, 0xe6, 0xe9, 0xad, 0xed, 0x9c, 0xeb, 0xa9, 0xe8, + 0x7c, 0xec, 0x2d, 0xf3, 0x6c, 0xfa, 0x8e, 0xfd, 0xf9, 0xfa, 0xe1, 0xfb, + 0xd9, 0xfe, 0xd8, 0xfb, 0x61, 0xfb, 0xf5, 0xff, 0x78, 0x00, 0x07, 0x05, + 0x93, 0x08, 0xa0, 0x02, 0xa4, 0x00, 0x45, 0x01, 0x9c, 0x02, 0xfc, 0x08, + 0x4b, 0x0a, 0xe7, 0x0a, 0x57, 0x0e, 0x30, 0x0a, 0x2c, 0x07, 0xda, 0x08, + 0xa8, 0x09, 0x55, 0x0c, 0x8f, 0x0f, 0x61, 0x10, 0x88, 0x0d, 0x59, 0x05, + 0xd1, 0xfd, 0xfc, 0xfc, 0x6a, 0xfe, 0xd6, 0x01, 0x1f, 0xff, 0x26, 0xf9, + 0x9c, 0xfa, 0x9f, 0xfb, 0xb2, 0xfd, 0xfe, 0xff, 0x3b, 0x04, 0x33, 0x0d, + 0x69, 0x0f, 0x19, 0x08, 0x8e, 0xff, 0x2a, 0xfb, 0xdf, 0xfd, 0x75, 0x00, + 0xf4, 0xf9, 0x23, 0xf7, 0x87, 0xf4, 0x2d, 0xf2, 0xa4, 0xf6, 0x46, 0xfa, + 0x18, 0x02, 0x02, 0x04, 0xc0, 0xfc, 0xf2, 0xf5, 0xc8, 0xf3, 0x7c, 0xf8, + 0xf3, 0xfe, 0xb6, 0xff, 0xe3, 0xfb, 0xee, 0xfe, 0xe9, 0x03, 0xa5, 0x09, + 0xd6, 0x0d, 0x6d, 0x0f, 0x8a, 0x17, 0x68, 0x19, 0x56, 0x15, 0x15, 0x0f, + 0xd4, 0x0a, 0xfc, 0x11, 0x0b, 0x14, 0x0b, 0x0a, 0x12, 0x00, 0xd6, 0xf9, + 0xaf, 0xf5, 0x2f, 0xf4, 0x85, 0xf1, 0xd5, 0xec, 0xd5, 0xe6, 0x3d, 0xdd, + 0x8b, 0xd6, 0x24, 0xd4, 0xfb, 0xd3, 0x0d, 0xd8, 0xa5, 0xda, 0x89, 0xd9, + 0xd5, 0xda, 0xf1, 0xd8, 0x21, 0xd6, 0x27, 0xd9, 0xcb, 0xd8, 0xdc, 0xd6, + 0x7c, 0xd4, 0x35, 0xd7, 0x3a, 0xe1, 0xe1, 0xe7, 0x09, 0xee, 0x95, 0xf0, + 0x40, 0xee, 0x3a, 0xf0, 0xb9, 0xf2, 0xcf, 0xee, 0x62, 0xeb, 0x33, 0xea, + 0x07, 0xeb, 0x14, 0xf0, 0x01, 0xef, 0x9e, 0xe8, 0x2a, 0xe3, 0x7e, 0xe3, + 0xe9, 0xe7, 0xf1, 0xe5, 0x70, 0xe2, 0x68, 0xe2, 0x04, 0xe2, 0xcb, 0xe2, + 0xbe, 0xe6, 0xbc, 0xeb, 0x0a, 0xf2, 0xfb, 0xf3, 0xb3, 0xec, 0x6d, 0xe8, + 0x6b, 0xed, 0xa1, 0xf2, 0x90, 0xf8, 0x23, 0xfd, 0x11, 0xfa, 0x48, 0xf8, + 0x86, 0xf6, 0xf1, 0xf4, 0xd4, 0xf8, 0x13, 0xfd, 0x75, 0x02, 0x53, 0x05, + 0xd1, 0xff, 0xf9, 0xfa, 0xd4, 0xfb, 0x71, 0xfd, 0xa3, 0x01, 0xae, 0x04, + 0x71, 0x01, 0x7e, 0xfc, 0xd5, 0xf7, 0x64, 0xf2, 0xb0, 0xf3, 0x44, 0xf9, + 0x48, 0xf6, 0x12, 0xf9, 0x52, 0xfe, 0xd5, 0xfc, 0x52, 0x05, 0x67, 0x0b, + 0x1f, 0x03, 0x61, 0xfc, 0x63, 0xf5, 0x64, 0xeb, 0x1e, 0xef, 0x56, 0xf2, + 0x6f, 0xec, 0x2d, 0xec, 0x67, 0xe4, 0x68, 0xd6, 0x59, 0xd3, 0x6e, 0xd4, + 0x92, 0xd2, 0x65, 0xd8, 0xe8, 0xda, 0x03, 0xd5, 0xed, 0xd5, 0x12, 0xd5, + 0xcd, 0xd7, 0xda, 0xe0, 0x62, 0xe2, 0xe7, 0xe2, 0xe5, 0xe6, 0x2d, 0xea, + 0xc3, 0xed, 0x7c, 0xf0, 0xa1, 0xef, 0xa9, 0xef, 0x9c, 0xf2, 0x6a, 0xf7, + 0x5d, 0xfe, 0x49, 0x04, 0x8b, 0x09, 0x94, 0x12, 0x6c, 0x14, 0x46, 0x0e, + 0x9c, 0x0e, 0x50, 0x0b, 0x20, 0x08, 0x4f, 0x0c, 0x61, 0x05, 0x04, 0xfb, + 0xc5, 0xf3, 0x2d, 0xec, 0x3c, 0xf1, 0x53, 0xf3, 0x4b, 0xec, 0xd8, 0xea, + 0xe7, 0xe1, 0xf4, 0xda, 0xcf, 0xe1, 0x95, 0xe7, 0x90, 0xf0, 0xb4, 0xf7, + 0x8f, 0xf3, 0x0c, 0xeb, 0x59, 0xe2, 0x6d, 0xe6, 0x30, 0xf4, 0x53, 0xfa, + 0x95, 0xf6, 0x01, 0xec, 0xcb, 0xe3, 0xb3, 0xe6, 0x76, 0xf1, 0x15, 0xfc, + 0x95, 0x04, 0xdb, 0x05, 0x3d, 0xff, 0x4b, 0xf5, 0xe3, 0xee, 0x93, 0xe9, + 0xdc, 0xdf, 0x9d, 0xdb, 0x8a, 0xd8, 0xb0, 0xd4, 0x7a, 0xd3, 0x2b, 0xd1, + 0xe5, 0xd0, 0x6c, 0xd0, 0xaf, 0xd0, 0x16, 0xd6, 0x0b, 0xda, 0x78, 0xd9, + 0x1b, 0xda, 0x57, 0xdb, 0xba, 0xdc, 0xe7, 0xda, 0x9d, 0xd8, 0x3b, 0xdd, + 0x90, 0xe5, 0x25, 0xec, 0x3f, 0xee, 0x9c, 0xf1, 0x8c, 0xf8, 0xe0, 0x00, + 0xf0, 0x04, 0x64, 0x04, 0x7c, 0x03, 0x9a, 0x07, 0x4a, 0x0c, 0xdf, 0x04, + 0x1c, 0xff, 0x72, 0x03, 0x06, 0x0c, 0x70, 0x13, 0x2c, 0x14, 0xf7, 0x0f, + 0xb5, 0x06, 0x3d, 0xf7, 0xc9, 0xe9, 0xd7, 0xe9, 0x95, 0xf0, 0x7a, 0xf4, + 0x83, 0xf2, 0x3f, 0xed, 0x17, 0xec, 0x90, 0xf2, 0x6c, 0xfd, 0x91, 0x01, + 0xea, 0x00, 0x06, 0x03, 0x96, 0x02, 0xda, 0x00, 0x97, 0x01, 0xc7, 0x04, + 0xb4, 0x0b, 0x30, 0x0c, 0xdc, 0x06, 0x65, 0x07, 0x3c, 0x0b, 0xde, 0x0f, + 0xc6, 0x13, 0x74, 0x14, 0xb1, 0x13, 0x79, 0x11, 0x23, 0x0e, 0x30, 0x0b, + 0x0c, 0x09, 0xf1, 0x08, 0xba, 0x01, 0x47, 0xf6, 0xba, 0xf3, 0x97, 0xf2, + 0x52, 0xf2, 0xb1, 0xeb, 0xf2, 0xdb, 0xc2, 0xd5, 0x8e, 0xd4, 0x0f, 0xd6, + 0x0b, 0xdc, 0xce, 0xdd, 0x00, 0xe0, 0x11, 0xe2, 0x86, 0xe2, 0xf4, 0xe9, + 0x2c, 0xf2, 0x57, 0xf6, 0x97, 0xf7, 0x41, 0xf1, 0x9b, 0xeb, 0xba, 0xee, + 0xa3, 0xf6, 0xf3, 0xfc, 0x91, 0xfd, 0xb8, 0xf9, 0x33, 0xf9, 0xc7, 0xfa, + 0xda, 0xfd, 0x1c, 0x07, 0x29, 0x06, 0x8f, 0x02, 0x22, 0x05, 0xf7, 0x03, + 0x16, 0x09, 0xb1, 0x0a, 0xa7, 0x04, 0xee, 0x01, 0x8b, 0xff, 0xe4, 0xfb, + 0x78, 0xfa, 0x12, 0xfd, 0x5d, 0xff, 0x54, 0x05, 0xbe, 0x0a, 0xdc, 0x0c, + 0x3b, 0x11, 0xd2, 0x18, 0xd3, 0x24, 0x84, 0x2b, 0xdb, 0x2c, 0x57, 0x28, + 0xc6, 0x1e, 0x9c, 0x1c, 0xc5, 0x20, 0x71, 0x26, 0xa4, 0x29, 0x89, 0x27, + 0xde, 0x22, 0xdb, 0x20, 0xa6, 0x21, 0xc7, 0x22, 0xe5, 0x22, 0xef, 0x21, + 0xc3, 0x20, 0xa6, 0x1d, 0x4f, 0x1b, 0x36, 0x1a, 0x3e, 0x19, 0x4d, 0x15, + 0x72, 0x10, 0x49, 0x10, 0x4e, 0x12, 0xdc, 0x13, 0x0b, 0x10, 0xa8, 0x0d, + 0xdb, 0x12, 0x57, 0x16, 0x35, 0x16, 0x0a, 0x17, 0xe5, 0x16, 0x63, 0x1a, + 0x2f, 0x24, 0xb7, 0x23, 0xc4, 0x1f, 0xbb, 0x23, 0xd6, 0x1e, 0xe0, 0x17, + 0x9a, 0x18, 0xb3, 0x18, 0x7d, 0x22, 0xa3, 0x27, 0xe5, 0x1d, 0xac, 0x1b, + 0x15, 0x18, 0xcd, 0x10, 0x06, 0x10, 0x5e, 0x0c, 0x9b, 0x03, 0x3d, 0xff, + 0x41, 0xfb, 0xa2, 0xf3, 0xf9, 0xf2, 0xf0, 0xf1, 0x9f, 0xef, 0x5a, 0xf3, + 0x2a, 0xf6, 0x26, 0xf8, 0xf8, 0xfb, 0xaa, 0xfe, 0xf6, 0x02, 0x2e, 0x09, + 0x11, 0x0c, 0x17, 0x10, 0x1d, 0x13, 0x3c, 0x13, 0x39, 0x18, 0xcd, 0x1e, + 0x98, 0x24, 0x78, 0x2d, 0xb5, 0x2e, 0xdf, 0x2e, 0xfa, 0x39, 0x51, 0x3d, + 0x4b, 0x3a, 0xff, 0x3b, 0x4a, 0x3c, 0x34, 0x3b, 0x31, 0x3b, 0x48, 0x38, + 0x4f, 0x36, 0xf6, 0x36, 0x90, 0x35, 0x87, 0x38, 0xe8, 0x3a, 0xbc, 0x37, + 0x23, 0x32, 0xd9, 0x28, 0xc2, 0x24, 0x3e, 0x29, 0x60, 0x2e, 0xf6, 0x2d, + 0xbb, 0x2a, 0x13, 0x26, 0x17, 0x25, 0x23, 0x2c, 0xdb, 0x2c, 0x3b, 0x2a, + 0x6c, 0x29, 0xd8, 0x22, 0xb4, 0x1c, 0xa4, 0x18, 0x46, 0x16, 0xad, 0x15, + 0x1f, 0x15, 0xbb, 0x0e, 0x9f, 0x04, 0x11, 0x01, 0x22, 0xff, 0xce, 0xf9, + 0x38, 0xf0, 0xba, 0xe7, 0xdd, 0xe3, 0x91, 0xe2, 0x03, 0xe0, 0x02, 0xdd, + 0x4b, 0xde, 0x52, 0xde, 0x40, 0xdf, 0x94, 0xe1, 0xc4, 0xe3, 0xb7, 0xe3, + 0x1f, 0xdf, 0x1c, 0xdc, 0xfd, 0xde, 0xe2, 0xe8, 0xe6, 0xef, 0x00, 0xef, + 0x9e, 0xed, 0xed, 0xf0, 0x6e, 0xf7, 0x85, 0x00, 0x32, 0x0a, 0xfd, 0x11, + 0x22, 0x16, 0x71, 0x12, 0xbb, 0x0b, 0xbf, 0x08, 0x3a, 0x0a, 0x43, 0x0e, + 0x97, 0x13, 0x54, 0x16, 0x80, 0x16, 0xa0, 0x15, 0x64, 0x13, 0x12, 0x14, + 0xb4, 0x18, 0xbc, 0x1a, 0xfb, 0x14, 0x11, 0x0c, 0xf8, 0x05, 0x93, 0x07, + 0x75, 0x0a, 0xbf, 0x0a, 0x94, 0x09, 0xf2, 0x03, 0x49, 0x03, 0xb4, 0x08, + 0x78, 0x12, 0x72, 0x1a, 0x32, 0x15, 0x42, 0x0b, 0x80, 0x07, 0xdb, 0x08, + 0x55, 0x0b, 0xeb, 0x0c, 0x89, 0x09, 0x95, 0x01, 0x1f, 0xf8, 0x8b, 0xf0, + 0xf7, 0xec, 0x70, 0xe8, 0xdd, 0xdf, 0xce, 0xd7, 0x8a, 0xd3, 0xd7, 0xd2, + 0x79, 0xd4, 0x5c, 0xd1, 0xce, 0xcc, 0x28, 0xcc, 0xef, 0xce, 0x6c, 0xd4, + 0x8e, 0xd3, 0xb5, 0xd0, 0x93, 0xcf, 0x70, 0xcb, 0x5e, 0xcc, 0x0f, 0xcf, + 0xc4, 0xd1, 0xe2, 0xda, 0xd1, 0xdf, 0x4f, 0xe4, 0xad, 0xee, 0xe0, 0xf3, + 0xdd, 0xf6, 0x51, 0xfc, 0xe8, 0xfe, 0xb3, 0x03, 0x99, 0x0c, 0x6b, 0x0f, + 0x7d, 0x0e, 0x87, 0x0d, 0xa2, 0x0c, 0xcc, 0x0d, 0x11, 0x0c, 0x7c, 0x08, + 0x54, 0x02, 0xbd, 0xfd, 0xad, 0x00, 0x81, 0x05, 0xba, 0x06, 0x11, 0x05, + 0x8f, 0x03, 0x32, 0x02, 0x2e, 0x04, 0xe6, 0x07, 0x76, 0x0b, 0xba, 0x0e, + 0x66, 0x0e, 0xb7, 0x0d, 0x08, 0x12, 0xee, 0x17, 0x5b, 0x19, 0x77, 0x18, + 0x09, 0x16, 0x96, 0x15, 0x4a, 0x1a, 0x2c, 0x1e, 0x71, 0x1f, 0x47, 0x1d, + 0xe7, 0x18, 0xcb, 0x18, 0xb7, 0x19, 0x9b, 0x17, 0x0c, 0x13, 0xad, 0x09, + 0x15, 0x02, 0xa1, 0xff, 0x5e, 0x00, 0x3f, 0x02, 0xfc, 0x01, 0x08, 0x01, + 0xbb, 0xff, 0x25, 0xfe, 0x83, 0xfd, 0xbd, 0xfc, 0x4e, 0xfa, 0x49, 0xf7, + 0x06, 0xf6, 0x5a, 0xfa, 0x53, 0x01, 0xee, 0x04, 0x25, 0x04, 0x9c, 0x01, + 0x1f, 0x06, 0xac, 0x0e, 0x4e, 0x14, 0x2a, 0x17, 0x5c, 0x16, 0xa1, 0x17, + 0x47, 0x1d, 0xd7, 0x20, 0x04, 0x21, 0x76, 0x20, 0x50, 0x1d, 0x52, 0x1a, + 0x6c, 0x1a, 0xd4, 0x19, 0x47, 0x1b, 0x4f, 0x1f, 0x20, 0x1d, 0xe6, 0x17, + 0x5b, 0x14, 0xc2, 0x13, 0x78, 0x13, 0x5f, 0x08, 0xb5, 0xfa, 0x6e, 0xf4, + 0x22, 0xf1, 0xe6, 0xf1, 0x51, 0xf6, 0xa5, 0xfb, 0x3f, 0xfe, 0xab, 0xf8, + 0x4f, 0xf3, 0x72, 0xf7, 0x5b, 0xfc, 0xdd, 0x01, 0x0b, 0x05, 0x44, 0x01, + 0xcd, 0xfe, 0x32, 0xfd, 0x0a, 0xfe, 0xdc, 0x03, 0xec, 0x0a, 0x7a, 0x0b, + 0x5c, 0x0b, 0x49, 0x0d, 0x5c, 0x08, 0x80, 0x0b, 0xfb, 0x12, 0x72, 0x11, + 0xba, 0x0d, 0xaa, 0x0a, 0x35, 0x0c, 0x16, 0x0d, 0xd9, 0x0a, 0xff, 0x0d, + 0x36, 0x14, 0xd1, 0x12, 0xd3, 0x0f, 0x0b, 0x14, 0xb4, 0x15, 0xe5, 0x13, + 0x0d, 0x11, 0xa4, 0x0d, 0x23, 0x0a, 0x01, 0x05, 0x5c, 0x00, 0x7a, 0x00, + 0x5d, 0x04, 0x7b, 0x03, 0xa9, 0x00, 0x46, 0xf8, 0x0c, 0xee, 0x1b, 0xef, + 0xa2, 0xf1, 0xbe, 0xf2, 0x38, 0xf3, 0x27, 0xf1, 0x72, 0xee, 0x65, 0xed, + 0x3a, 0xf0, 0x34, 0xf1, 0x69, 0xf0, 0x57, 0xf0, 0x14, 0xf1, 0x27, 0xf2, + 0x4f, 0xef, 0x72, 0xe5, 0x5a, 0xdc, 0x22, 0xdb, 0x8a, 0xdd, 0xda, 0xe1, + 0x4f, 0xe1, 0x0f, 0xdf, 0x74, 0xe0, 0x34, 0xdf, 0x39, 0xe3, 0x02, 0xed, + 0x58, 0xf2, 0x48, 0xf2, 0xb3, 0xef, 0x52, 0xed, 0xf8, 0xed, 0xe3, 0xee, + 0x2a, 0xee, 0xd8, 0xf1, 0x1e, 0xf6, 0xde, 0xf8, 0x87, 0xfb, 0xfc, 0xfc, + 0xe3, 0xff, 0x74, 0x03, 0x30, 0x09, 0xab, 0x0e, 0xa0, 0x10, 0x38, 0x10, + 0x8c, 0x11, 0x59, 0x18, 0x74, 0x1e, 0xc8, 0x1f, 0xfa, 0x1a, 0x15, 0x12, + 0xd2, 0x0e, 0xa6, 0x12, 0x5d, 0x16, 0xb3, 0x15, 0x44, 0x0c, 0xa3, 0xff, + 0x6c, 0xf6, 0xf0, 0xf0, 0x7e, 0xf3, 0xcc, 0xf6, 0xe7, 0xf3, 0x04, 0xee, + 0xf9, 0xe7, 0x56, 0xe3, 0xfd, 0xe0, 0x47, 0xe0, 0xfd, 0xdf, 0x2b, 0xdf, + 0x5f, 0xda, 0x78, 0xd6, 0xd2, 0xd6, 0x9c, 0xd7, 0x9c, 0xd7, 0xa6, 0xd7, + 0x06, 0xd8, 0x40, 0xd9, 0x7d, 0xde, 0xc5, 0xe1, 0x8e, 0xe3, 0x08, 0xe8, + 0x76, 0xe8, 0xef, 0xe9, 0x99, 0xec, 0xaa, 0xec, 0xa1, 0xef, 0x22, 0xf1, + 0x69, 0xf0, 0x5f, 0xf0, 0xfb, 0xed, 0x33, 0xec, 0x86, 0xec, 0xed, 0xed, + 0x21, 0xf0, 0x8e, 0xf1, 0xe6, 0xf2, 0x61, 0xf6, 0xd9, 0xf9, 0x4d, 0xfb, + 0xe6, 0xfc, 0x23, 0x00, 0x6c, 0x04, 0x86, 0x09, 0x9b, 0x0c, 0xa5, 0x09, + 0x88, 0x06, 0xe8, 0x07, 0xdc, 0x08, 0x6c, 0x09, 0x4a, 0x0b, 0x09, 0x0b, + 0x68, 0x0b, 0x45, 0x0c, 0xda, 0x0e, 0x7d, 0x15, 0x18, 0x16, 0xa0, 0x14, + 0xb0, 0x12, 0xf9, 0x0c, 0x60, 0x0f, 0x8f, 0x10, 0xa0, 0x0b, 0x75, 0x07, + 0xb6, 0xfc, 0x5f, 0xf6, 0x2a, 0xf6, 0x07, 0xf1, 0x9e, 0xf0, 0x23, 0xf1, + 0x4f, 0xf1, 0xaa, 0xf6, 0x2a, 0xf9, 0xc3, 0xfa, 0x9d, 0xfb, 0x41, 0xf8, + 0xc8, 0xf4, 0x4b, 0xf1, 0x93, 0xf0, 0xea, 0xf2, 0xda, 0xf3, 0xce, 0xf3, + 0x76, 0xf3, 0x67, 0xf7, 0xcb, 0xfb, 0xf1, 0xfb, 0xee, 0xfe, 0x20, 0x01, + 0x3e, 0x01, 0xe8, 0x01, 0x1d, 0x00, 0x7e, 0x01, 0xad, 0x03, 0xd6, 0x02, + 0x4d, 0x04, 0x3d, 0x02, 0x73, 0x02, 0xbb, 0x07, 0x9b, 0x08, 0x02, 0x0c, + 0x24, 0x0c, 0xf4, 0x09, 0xf7, 0x0b, 0xbe, 0x09, 0x41, 0x09, 0x5e, 0x0f, + 0xfe, 0x13, 0x46, 0x18, 0xa4, 0x19, 0xca, 0x16, 0x95, 0x18, 0xc8, 0x1c, + 0xa1, 0x23, 0x4a, 0x2b, 0x0c, 0x30, 0x4f, 0x2d, 0x67, 0x20, 0x8b, 0x15, + 0xda, 0x0b, 0x29, 0x06, 0xd1, 0x04, 0xea, 0xfb, 0x27, 0xf5, 0x65, 0xf5, + 0x5e, 0xf4, 0x3b, 0xf6, 0xe5, 0xf5, 0x46, 0xf2, 0x0f, 0xf6, 0x6d, 0xf4, + 0x7c, 0xf0, 0x57, 0xf4, 0xd0, 0xee, 0x42, 0xe9, 0x24, 0xeb, 0x33, 0xe7, + 0x39, 0xea, 0x9b, 0xf5, 0xfa, 0xfe, 0x99, 0x07, 0xb3, 0x06, 0x53, 0x01, + 0xaa, 0x04, 0x87, 0x0c, 0x52, 0x12, 0x52, 0x14, 0x3f, 0x14, 0x57, 0x11, + 0xf7, 0x0d, 0x9f, 0x0e, 0x4c, 0x0f, 0x67, 0x13, 0x58, 0x14, 0x0f, 0x12, + 0x48, 0x17, 0xb8, 0x15, 0x6d, 0x16, 0x7e, 0x19, 0xd2, 0x10, 0x73, 0x0c, + 0x03, 0x0e, 0x13, 0x0f, 0xda, 0x14, 0xb4, 0x18, 0xc6, 0x19, 0xb0, 0x1f, + 0x81, 0x1e, 0x0f, 0x1c, 0xed, 0x19, 0x7c, 0x11, 0xa0, 0x0e, 0x82, 0x0e, + 0x49, 0x13, 0x0c, 0x19, 0x07, 0x19, 0x58, 0x17, 0x22, 0x18, 0x2e, 0x1e, + 0x91, 0x25, 0x21, 0x28, 0x77, 0x22, 0xdc, 0x19, 0x83, 0x11, 0x37, 0x0d, + 0xe1, 0x08, 0x32, 0x02, 0xc8, 0xfc, 0x6c, 0xf6, 0x29, 0xf2, 0x6d, 0xf2, + 0x1f, 0xf6, 0x00, 0xf6, 0x4b, 0xf4, 0x6f, 0xf0, 0xf7, 0xeb, 0xa9, 0xf0, + 0xfd, 0xf7, 0xa4, 0xfd, 0xea, 0x00, 0xfa, 0xff, 0x2d, 0xfc, 0xe8, 0xfa, + 0x09, 0xfd, 0xa0, 0xff, 0x7a, 0x02, 0x80, 0x04, 0x64, 0x05, 0xcd, 0x01, + 0x82, 0xfd, 0x4c, 0xfc, 0x68, 0xff, 0xd7, 0x06, 0xd5, 0x09, 0x40, 0x07, + 0x20, 0x05, 0x4d, 0x02, 0x24, 0xff, 0x9b, 0xfe, 0x16, 0xfd, 0x49, 0xfe, + 0xf8, 0xff, 0x27, 0xfc, 0x77, 0xf7, 0xf7, 0xf3, 0xbe, 0xf6, 0x51, 0xfd, + 0x1d, 0xff, 0x6f, 0xff, 0x68, 0xff, 0x49, 0x00, 0x73, 0x02, 0x9a, 0x03, + 0x05, 0x06, 0x6b, 0x08, 0x58, 0x0b, 0x95, 0x0c, 0x5d, 0x0b, 0xf0, 0x08, + 0xc6, 0x05, 0x4c, 0x06, 0xf7, 0x07, 0x69, 0x07, 0x8e, 0x07, 0x39, 0x0a, + 0xdb, 0x09, 0x92, 0x08, 0xad, 0x05, 0x50, 0x03, 0x50, 0x08, 0x4a, 0x0d, + 0xea, 0x0e, 0x25, 0x0c, 0x7f, 0x08, 0xe2, 0x05, 0xa1, 0x04, 0x16, 0x02, + 0x14, 0x00, 0x43, 0x01, 0xd8, 0x02, 0xf4, 0x07, 0x9b, 0x09, 0x2d, 0x09, + 0x3b, 0x0a, 0x51, 0x0c, 0xe3, 0x0a, 0xab, 0x06, 0x38, 0x04, 0x56, 0x01, + 0x6f, 0x00, 0x60, 0xfe, 0xd6, 0xff, 0xc4, 0x04, 0x6b, 0x09, 0x40, 0x08, + 0xc2, 0x06, 0xc8, 0x08, 0xdb, 0x09, 0xf9, 0x0e, 0x1b, 0x0b, 0x4e, 0x04, + 0x3e, 0x02, 0x77, 0x01, 0xfb, 0x04, 0x5f, 0x07, 0xfa, 0x04, 0x53, 0x05, + 0xb4, 0x05, 0xd1, 0x04, 0xaf, 0x0a, 0x00, 0x0b, 0xf4, 0x0a, 0x77, 0x07, + 0x4d, 0xff, 0xab, 0xff, 0x20, 0xff, 0x55, 0x00, 0x07, 0x04, 0x5a, 0x05, + 0xa5, 0x06, 0x2d, 0x09, 0x60, 0x0a, 0x45, 0x0d, 0xf9, 0x0d, 0x59, 0x0b, + 0x49, 0x0a, 0xac, 0x07, 0xaa, 0x08, 0xde, 0x09, 0x17, 0x0b, 0x8f, 0x0d, + 0x84, 0x0e, 0x44, 0x10, 0x09, 0x0e, 0x9e, 0x0a, 0xa9, 0x09, 0x42, 0x07, + 0x74, 0x06, 0x65, 0x05, 0x34, 0x01, 0x81, 0x02, 0xd2, 0x01, 0xf4, 0x00, + 0x62, 0x07, 0x28, 0x09, 0xbe, 0x08, 0x8c, 0x08, 0xba, 0x07, 0x23, 0x0b, + 0xc7, 0x0e, 0xab, 0x12, 0x3b, 0x14, 0xf0, 0x0e, 0x15, 0x0a, 0x73, 0x08, + 0xa9, 0x08, 0x68, 0x05, 0xf3, 0xfe, 0x65, 0xfc, 0x28, 0xf7, 0x57, 0xef, + 0x29, 0xea, 0xe9, 0xe7, 0x7e, 0xeb, 0xcf, 0xeb, 0x3e, 0xea, 0x3e, 0xf1, + 0x5e, 0xf1, 0x1b, 0xed, 0x93, 0xf1, 0x40, 0xf0, 0xad, 0xee, 0xd1, 0xf1, + 0x23, 0xee, 0x9c, 0xef, 0x91, 0xf0, 0x8c, 0xeb, 0x6f, 0xf1, 0x30, 0xf6, + 0xdc, 0xf2, 0xbe, 0xf6, 0x13, 0xfe, 0x84, 0x03, 0x22, 0x0b, 0xa2, 0x0e, + 0x60, 0x10, 0xfb, 0x0e, 0x5c, 0x06, 0x1d, 0x06, 0x22, 0x0a, 0xd4, 0x08, + 0xb5, 0x06, 0x57, 0x06, 0xd8, 0x03, 0xea, 0xfe, 0x8c, 0xfe, 0x07, 0x03, + 0xf5, 0x0a, 0x74, 0x0c, 0x50, 0x09, 0x01, 0x0a, 0xaf, 0x08, 0x84, 0x07, + 0x6b, 0x0b, 0x59, 0x10, 0xfc, 0x11, 0x85, 0x0d, 0x7b, 0x07, 0xca, 0x08, + 0xe7, 0x0a, 0xb2, 0x0a, 0x04, 0x0c, 0x77, 0x08, 0x4e, 0x03, 0x1a, 0x04, + 0x92, 0x05, 0xe4, 0x05, 0xfd, 0x02, 0x52, 0xfa, 0x16, 0xf7, 0x2b, 0xf7, + 0xc8, 0xf2, 0xdd, 0xec, 0xf3, 0xe5, 0xe0, 0xe2, 0x2b, 0xe2, 0x74, 0xe1, + 0x93, 0xe6, 0x9c, 0xe9, 0x61, 0xe5, 0x6f, 0xe2, 0x88, 0xe0, 0xb1, 0xde, + 0x16, 0xdb, 0x0c, 0xd4, 0xd6, 0xd1, 0x2a, 0xd6, 0xa3, 0xd9, 0x70, 0xdc, + 0xbb, 0xdf, 0x14, 0xe0, 0xd2, 0xe0, 0x7c, 0xdf, 0xbf, 0xdc, 0xb6, 0xe0, + 0xda, 0xe6, 0xdd, 0xe8, 0xf6, 0xe6, 0x9b, 0xe2, 0x7d, 0xe1, 0xbd, 0xe2, + 0x30, 0xe3, 0x42, 0xe8, 0x4a, 0xeb, 0x8c, 0xe8, 0xe1, 0xe4, 0x0b, 0xe5, + 0x08, 0xed, 0x83, 0xf3, 0x9f, 0xf0, 0xe9, 0xea, 0xb8, 0xe9, 0xaa, 0xec, + 0xc0, 0xf0, 0xcd, 0xf4, 0x3f, 0xf9, 0xda, 0xfb, 0x53, 0xfc, 0xad, 0xf8, + 0x53, 0xf7, 0x9d, 0xf9, 0xdc, 0xf6, 0xb7, 0xf4, 0xc8, 0xf1, 0x86, 0xf2, + 0x96, 0xf7, 0x3d, 0xf9, 0x3e, 0xf8, 0xb5, 0xf7, 0xc9, 0xf9, 0xbf, 0xfc, + 0x49, 0xfe, 0xdb, 0xf9, 0xdc, 0xf6, 0x54, 0xf2, 0x22, 0xed, 0xaa, 0xec, + 0x1d, 0xef, 0x89, 0xf2, 0x5e, 0xf1, 0xc7, 0xf0, 0xb7, 0xee, 0xb0, 0xef, + 0xea, 0xee, 0x77, 0xec, 0x55, 0xee, 0x9d, 0xec, 0x14, 0xed, 0x27, 0xef, + 0xf6, 0xf2, 0xf0, 0xf6, 0x45, 0xf8, 0x34, 0xf6, 0x88, 0xf4, 0xe0, 0xf4, + 0x2e, 0xf4, 0xfa, 0xf5, 0x13, 0xf7, 0xce, 0xf7, 0xb1, 0xf5, 0x25, 0xf3, + 0x55, 0xf3, 0x96, 0xf6, 0x2d, 0xf9, 0x53, 0xf8, 0x22, 0xf9, 0xe4, 0xf8, + 0xcd, 0xf8, 0xd1, 0xf6, 0xa3, 0xf6, 0xfd, 0xf7, 0x8b, 0xf7, 0x1c, 0xf7, + 0x8d, 0xf2, 0xa2, 0xef, 0x19, 0xf0, 0xc4, 0xf1, 0x8a, 0xf5, 0x83, 0xf9, + 0xdb, 0xfb, 0x60, 0xff, 0x32, 0x00, 0x6e, 0xff, 0x92, 0x00, 0x69, 0xfe, + 0xa9, 0xff, 0xfd, 0x01, 0x00, 0x02, 0x48, 0x01, 0x09, 0xff, 0x22, 0xff, + 0xe7, 0xff, 0xa7, 0x01, 0x89, 0x04, 0x31, 0x06, 0xa9, 0x05, 0x4a, 0x04, + 0xef, 0x03, 0x9d, 0x05, 0x19, 0x08, 0xdf, 0x08, 0x2b, 0x0b, 0x9f, 0x0c, + 0x56, 0x0b, 0xc0, 0x09, 0x08, 0x07, 0x36, 0x06, 0x9f, 0x09, 0x75, 0x0c, + 0x5c, 0x0d, 0x37, 0x0e, 0x84, 0x0c, 0x34, 0x0b, 0x43, 0x0d, 0xc3, 0x0d, + 0x35, 0x0e, 0x7e, 0x0d, 0x9a, 0x09, 0xc2, 0x08, 0x0d, 0x0a, 0xd9, 0x0a, + 0x15, 0x08, 0xa8, 0x01, 0xac, 0xfc, 0x9c, 0xf8, 0xfd, 0xf4, 0x10, 0xf0, + 0x93, 0xec, 0x32, 0xec, 0x4d, 0xec, 0xfb, 0xea, 0x73, 0xe7, 0x23, 0xea, + 0x01, 0xf0, 0x5d, 0xf0, 0xac, 0xf0, 0xd5, 0xef, 0xb0, 0xeb, 0x30, 0xe8, + 0xeb, 0xe4, 0xab, 0xe7, 0x38, 0xed, 0x8e, 0xf0, 0x17, 0xf5, 0xea, 0xf6, + 0x6f, 0xf9, 0xba, 0xfd, 0x88, 0x01, 0x39, 0x03, 0x21, 0x03, 0xfc, 0x02, + 0x1d, 0x00, 0x61, 0x00, 0x55, 0x01, 0x5f, 0xff, 0xe3, 0xfe, 0x02, 0xff, + 0x83, 0xff, 0x7f, 0x00, 0x91, 0x01, 0xcc, 0x05, 0x2b, 0x0b, 0xf0, 0x0c, + 0xa9, 0x0e, 0xf1, 0x0f, 0xbe, 0x10, 0x6e, 0x11, 0x6e, 0x12, 0x06, 0x17, + 0xdf, 0x18, 0x97, 0x16, 0x2e, 0x16, 0x15, 0x18, 0xc4, 0x18, 0xa1, 0x18, + 0x26, 0x17, 0x82, 0x14, 0x6f, 0x14, 0x4d, 0x17, 0x63, 0x1b, 0x3e, 0x1c, + 0x27, 0x19, 0x94, 0x14, 0x8d, 0x12, 0x28, 0x13, 0x3e, 0x10, 0x95, 0x0a, + 0x94, 0x07, 0xa2, 0x06, 0x79, 0x02, 0x87, 0xfa, 0x23, 0xf4, 0xb6, 0xf2, + 0xae, 0xf0, 0x98, 0xeb, 0xb7, 0xe9, 0x98, 0xeb, 0x7c, 0xeb, 0x36, 0xe6, + 0xd4, 0xde, 0xd0, 0xdc, 0x18, 0xe0, 0x83, 0xe2, 0x9f, 0xe2, 0x21, 0xdf, + 0x86, 0xd8, 0xb8, 0xd0, 0x9d, 0xcc, 0xde, 0xce, 0x43, 0xd3, 0xdc, 0xd7, + 0x25, 0xdb, 0x58, 0xdb, 0x30, 0xdc, 0xa1, 0xe1, 0x8a, 0xe6, 0x3d, 0xe9, + 0x26, 0xe7, 0x96, 0xe3, 0x8d, 0xe5, 0xda, 0xe7, 0x6d, 0xea, 0x75, 0xea, + 0xcd, 0xea, 0x3c, 0xec, 0x1c, 0xed, 0x7d, 0xf2, 0xcf, 0xf8, 0xd9, 0xfc, + 0xf4, 0xfe, 0x06, 0x02, 0x82, 0x02, 0x68, 0xff, 0x49, 0xfc, 0x02, 0xff, + 0x80, 0x02, 0x63, 0x01, 0xba, 0x00, 0xf9, 0xff, 0x8d, 0x03, 0x01, 0x03, + 0x80, 0xfe, 0xe1, 0xfb, 0x2e, 0xfb, 0x66, 0xfc, 0x42, 0xfd, 0x29, 0x01, + 0x10, 0x00, 0xe9, 0xff, 0xb2, 0x02, 0xa6, 0x04, 0x42, 0x05, 0xfb, 0x01, + 0xbb, 0xfe, 0x30, 0xfd, 0xcf, 0xfb, 0xf5, 0xf6, 0xa7, 0xf6, 0x09, 0xf4, + 0x8b, 0xf1, 0x41, 0xf4, 0xed, 0xf5, 0x53, 0xfd, 0xd0, 0x02, 0xa1, 0x03, + 0x70, 0x05, 0x24, 0x06, 0x33, 0x04, 0x0d, 0x04, 0x4a, 0xff, 0xe7, 0xf5, + 0x50, 0xf1, 0xc6, 0xec, 0x1c, 0xeb, 0x5f, 0xea, 0x09, 0xe9, 0xa5, 0xec, + 0xcb, 0xef, 0x08, 0xef, 0x30, 0xef, 0x49, 0xf0, 0x3a, 0xf1, 0x34, 0xf2, + 0x00, 0xf3, 0xc7, 0xf5, 0x17, 0xf9, 0x92, 0xfa, 0x42, 0xfb, 0xd7, 0xfd, + 0x96, 0xff, 0xf2, 0xff, 0x54, 0x01, 0x14, 0x02, 0x7b, 0x01, 0x85, 0x02, + 0x6b, 0x03, 0xc1, 0x04, 0xf1, 0x07, 0xa5, 0x09, 0x10, 0x0e, 0x22, 0x10, + 0x7b, 0x0e, 0x98, 0x0d, 0xef, 0x0b, 0xd4, 0x0b, 0x7a, 0x0b, 0x6e, 0x09, + 0x3c, 0x09, 0xec, 0x08, 0xd6, 0x05, 0xb9, 0x06, 0xa6, 0x07, 0x62, 0x08, + 0xb9, 0x0a, 0x2b, 0x0c, 0xf3, 0x0e, 0xb3, 0x0f, 0xf0, 0x10, 0xcd, 0x12, + 0x3b, 0x15, 0xb4, 0x15, 0x48, 0x13, 0xaa, 0x12, 0x8a, 0x14, 0x78, 0x15, + 0x76, 0x14, 0x97, 0x15, 0xec, 0x14, 0x40, 0x15, 0x5b, 0x16, 0x9b, 0x16, + 0x94, 0x16, 0x4d, 0x13, 0x70, 0x12, 0x36, 0x13, 0x58, 0x13, 0xd6, 0x12, + 0x5b, 0x0d, 0x69, 0x05, 0xb7, 0xfe, 0x44, 0xf8, 0x89, 0xf5, 0x67, 0xf4, + 0x08, 0xf1, 0xc7, 0xf0, 0x93, 0xf2, 0xe8, 0xf3, 0x66, 0xf7, 0x91, 0xf9, + 0x83, 0xf9, 0x8c, 0xf8, 0x45, 0xf8, 0x34, 0xfd, 0x45, 0x01, 0x10, 0xfe, + 0x7b, 0xfa, 0xad, 0xfc, 0x7d, 0x00, 0x57, 0x03, 0x02, 0x07, 0xfe, 0x0a, + 0x8e, 0x10, 0xc0, 0x16, 0xf4, 0x19, 0x95, 0x1c, 0xc3, 0x1e, 0x88, 0x1e, + 0x81, 0x20, 0x02, 0x22, 0xef, 0x21, 0x46, 0x23, 0x27, 0x23, 0x0a, 0x20, + 0x36, 0x1d, 0xe5, 0x1d, 0xca, 0x22, 0xf3, 0x29, 0xa0, 0x2a, 0x9a, 0x29, + 0x66, 0x28, 0xa6, 0x27, 0xeb, 0x2c, 0xec, 0x2f, 0xbd, 0x31, 0x2a, 0x33, + 0xcb, 0x2f, 0xee, 0x2b, 0xc5, 0x2c, 0xa1, 0x2d, 0xcc, 0x2b, 0x71, 0x27, + 0x54, 0x1f, 0xf4, 0x19, 0x22, 0x17, 0x61, 0x16, 0xab, 0x15, 0x20, 0x0e, + 0x5e, 0x05, 0x8c, 0x02, 0x93, 0xff, 0x2b, 0xfd, 0x59, 0xfc, 0xbc, 0xf6, + 0xb3, 0xed, 0x85, 0xe3, 0x8d, 0xdd, 0xed, 0xdd, 0x28, 0xe0, 0x51, 0xde, + 0x4a, 0xd8, 0x87, 0xd2, 0xb8, 0xcd, 0xd5, 0xcd, 0x20, 0xd5, 0xef, 0xdd, + 0x72, 0xe1, 0x60, 0xe0, 0x08, 0xe1, 0xc3, 0xe5, 0x21, 0xea, 0x84, 0xed, + 0xb3, 0xf0, 0x8c, 0xf4, 0x87, 0xf9, 0xac, 0xfb, 0xf3, 0xfd, 0xf3, 0x01, + 0xd2, 0x03, 0x32, 0x04, 0xe4, 0x05, 0x1b, 0x07, 0x0b, 0x0a, 0x67, 0x0c, + 0xd1, 0x0a, 0xbc, 0x0a, 0x31, 0x0b, 0x04, 0x0b, 0xbd, 0x09, 0x56, 0x08, + 0x5d, 0x05, 0xc9, 0x03, 0x50, 0x06, 0x40, 0x05, 0x2f, 0x02, 0x8e, 0xff, + 0x7f, 0xfe, 0x27, 0xff, 0x23, 0xff, 0xfd, 0xff, 0x06, 0x03, 0x18, 0x05, + 0x4e, 0x06, 0xf2, 0x09, 0x4f, 0x0b, 0x3f, 0x0b, 0xad, 0x0b, 0xec, 0x0a, + 0x9d, 0x09, 0x3e, 0x06, 0xcb, 0x03, 0x02, 0x04, 0x6d, 0x02, 0xd4, 0xff, + 0xb1, 0xff, 0x53, 0xff, 0x9f, 0xfd, 0xc1, 0xfb, 0x43, 0xfa, 0x67, 0xf9, + 0x3e, 0xf4, 0x12, 0xec, 0xfd, 0xe6, 0x09, 0xe3, 0x3d, 0xe0, 0x7b, 0xde, + 0x2b, 0xdf, 0xcc, 0xe1, 0xc7, 0xe2, 0x5a, 0xe4, 0x9e, 0xe6, 0x3d, 0xe8, + 0x38, 0xeb, 0xa4, 0xee, 0x68, 0xf0, 0xa0, 0xf1, 0xfb, 0xf1, 0xf5, 0xf5, + 0x30, 0xfb, 0x35, 0xfd, 0x1f, 0x02, 0xf5, 0x07, 0xec, 0x0b, 0x4e, 0x0e, + 0x5b, 0x0e, 0x96, 0x0d, 0x71, 0x0c, 0xe3, 0x08, 0xa8, 0x05, 0xd6, 0x06, + 0x47, 0x08, 0x57, 0x08, 0xf8, 0x04, 0x45, 0x01, 0x43, 0x02, 0x56, 0x04, + 0x8d, 0x06, 0x13, 0x07, 0x95, 0x03, 0x57, 0x00, 0xb6, 0xff, 0x9c, 0xff, + 0xbd, 0x00, 0x6c, 0x01, 0x23, 0x02, 0x90, 0x04, 0xd8, 0x06, 0xc3, 0x09, + 0x44, 0x0c, 0xa7, 0x0b, 0x81, 0x0b, 0x21, 0x0e, 0x56, 0x11, 0xd5, 0x13, + 0x01, 0x14, 0x1b, 0x14, 0x46, 0x15, 0xf1, 0x13, 0xdf, 0x10, 0x21, 0x0e, + 0x9f, 0x0d, 0x87, 0x0d, 0x1c, 0x0b, 0xd0, 0x0a, 0x27, 0x0d, 0xac, 0x0e, + 0x54, 0x0f, 0x0e, 0x0f, 0x71, 0x0e, 0x14, 0x0e, 0x6d, 0x0d, 0xf7, 0x0a, + 0xa1, 0x09, 0xdc, 0x09, 0x69, 0x0a, 0xef, 0x0b, 0x2e, 0x08, 0xfe, 0x01, + 0x3b, 0x03, 0x9a, 0x08, 0xa0, 0x0c, 0x4b, 0x0f, 0x4c, 0x0c, 0xe8, 0x04, + 0x98, 0xfe, 0x57, 0xfc, 0x46, 0x01, 0xfe, 0x04, 0xb7, 0x02, 0x67, 0x01, + 0x1e, 0xff, 0x2c, 0xfb, 0xa0, 0xfc, 0xb4, 0xfd, 0x75, 0xfc, 0x56, 0xfc, + 0xbd, 0xf8, 0x2b, 0xf8, 0x20, 0xfb, 0xe8, 0xf9, 0x52, 0xf8, 0x69, 0xf9, + 0x02, 0xfc, 0x3c, 0x01, 0x48, 0x05, 0xa8, 0x05, 0x3e, 0x04, 0x18, 0x02, + 0x7e, 0x04, 0x8f, 0x0a, 0x3b, 0x0d, 0x8f, 0x0e, 0x3b, 0x11, 0x9c, 0x10, + 0xc6, 0x10, 0x85, 0x15, 0xe8, 0x18, 0x7e, 0x1a, 0x6c, 0x1c, 0x0c, 0x1e, + 0x5e, 0x1e, 0xf2, 0x20, 0xb3, 0x22, 0xef, 0x22, 0x1a, 0x25, 0x7b, 0x29, + 0x7c, 0x2d, 0xa7, 0x29, 0x6e, 0x24, 0xaa, 0x20, 0x41, 0x1c, 0x5e, 0x19, + 0x51, 0x16, 0x33, 0x11, 0xba, 0x0a, 0x7c, 0x08, 0xce, 0x06, 0x94, 0x05, + 0x1c, 0x08, 0xc0, 0x0b, 0x4a, 0x0e, 0xa5, 0x0e, 0x9f, 0x0e, 0x13, 0x0d, + 0x09, 0x0b, 0x33, 0x07, 0xa1, 0x02, 0x77, 0x00, 0x27, 0x00, 0xfc, 0x01, + 0xc7, 0x04, 0x9e, 0x08, 0x2a, 0x0a, 0x62, 0x09, 0x52, 0x0b, 0xcf, 0x0e, + 0x13, 0x0e, 0x45, 0x08, 0x2c, 0x04, 0x29, 0x03, 0x9e, 0x03, 0x4f, 0x01, + 0x9f, 0xfa, 0x8b, 0xf4, 0x86, 0xf1, 0x38, 0xf0, 0xa4, 0xed, 0x78, 0xec, + 0xe2, 0xec, 0xcf, 0xeb, 0xea, 0xe8, 0xa2, 0xe6, 0x66, 0xea, 0xb9, 0xef, + 0xd5, 0xf2, 0x96, 0xf2, 0x69, 0xef, 0xcd, 0xef, 0x57, 0xf3, 0x2f, 0xf6, + 0x79, 0xf7, 0x8e, 0xf7, 0x23, 0xf7, 0x59, 0xf8, 0x38, 0xfa, 0x91, 0xfe, + 0x8e, 0x06, 0x62, 0x0d, 0x4f, 0x11, 0xdb, 0x10, 0x5b, 0x10, 0xdf, 0x11, + 0x29, 0x13, 0xa3, 0x12, 0x32, 0x0d, 0x4e, 0x06, 0xb8, 0x02, 0x75, 0x01, + 0x6c, 0x00, 0x55, 0xff, 0xbf, 0xfd, 0xaa, 0xfc, 0x1d, 0xfa, 0xa9, 0xf6, + 0xa8, 0xf5, 0x6d, 0xf6, 0x55, 0xf7, 0x43, 0xf6, 0xaa, 0xf4, 0x31, 0xf6, + 0x27, 0xfa, 0x90, 0xfd, 0x74, 0xff, 0xaf, 0xfe, 0x3e, 0xfc, 0xad, 0xfb, + 0xec, 0xfa, 0xe0, 0xf9, 0xfa, 0xfa, 0x6b, 0xfd, 0x0e, 0x00, 0xf4, 0x00, + 0xce, 0xff, 0x54, 0x00, 0x97, 0x02, 0x09, 0x05, 0x8f, 0x06, 0xf1, 0x04, + 0x9d, 0x03, 0x20, 0x03, 0xa2, 0x02, 0xfa, 0x00, 0x8b, 0xfe, 0xbd, 0xfd, + 0x00, 0xfd, 0x5d, 0xfb, 0x00, 0xf8, 0xa1, 0xf6, 0x1b, 0xf9, 0x1d, 0xfd, + 0x6c, 0xff, 0xd8, 0xfe, 0x74, 0xfe, 0x84, 0xfd, 0x0d, 0xfd, 0xdc, 0xfd, + 0x7e, 0xff, 0x99, 0x01, 0x88, 0x01, 0xd1, 0x00, 0x13, 0x02, 0x5e, 0x06, + 0xfe, 0x09, 0x18, 0x0b, 0x39, 0x0b, 0xa6, 0x09, 0x9a, 0x08, 0x66, 0x09, + 0xc2, 0x0b, 0x39, 0x0c, 0xc3, 0x09, 0xaf, 0x07, 0xc4, 0x07, 0x58, 0x0a, + 0x7a, 0x09, 0xdc, 0x05, 0x15, 0x02, 0x48, 0xff, 0xfe, 0x00, 0x2f, 0x04, + 0xcc, 0x07, 0x22, 0x08, 0x78, 0x03, 0x08, 0x01, 0x7e, 0x02, 0x84, 0x04, + 0xfd, 0x04, 0x9a, 0x03, 0x39, 0x01, 0x68, 0x00, 0x89, 0x01, 0x62, 0x04, + 0x35, 0x07, 0x81, 0x05, 0x22, 0x02, 0xc1, 0x03, 0x80, 0x07, 0x4c, 0x0a, + 0x38, 0x0b, 0x79, 0x08, 0x0f, 0x06, 0x96, 0x07, 0xc1, 0x0b, 0xea, 0x0d, + 0xe4, 0x0b, 0x4c, 0x07, 0x48, 0x03, 0x15, 0xff, 0xfc, 0xfa, 0x3f, 0xfb, + 0x26, 0xfc, 0xc8, 0xfb, 0x76, 0xfb, 0x51, 0xfc, 0x38, 0xfe, 0xcc, 0xfe, + 0x82, 0xfe, 0x7f, 0xff, 0x89, 0x01, 0xcd, 0x01, 0xf4, 0x03, 0x2f, 0x07, + 0x06, 0x05, 0xd7, 0x00, 0x03, 0x03, 0x83, 0x0a, 0xe0, 0x10, 0x27, 0x14, + 0xef, 0x13, 0x0e, 0x14, 0x3d, 0x16, 0xd4, 0x19, 0x97, 0x1b, 0xf3, 0x1b, + 0x8c, 0x1d, 0xf6, 0x1c, 0x40, 0x1c, 0x69, 0x1b, 0x68, 0x1a, 0x00, 0x1b, + 0x1f, 0x1d, 0xd8, 0x1c, 0x45, 0x18, 0xde, 0x12, 0xaf, 0x0e, 0x5c, 0x0f, + 0x9f, 0x0e, 0x3d, 0x0a, 0x98, 0x04, 0xe9, 0xfc, 0xbc, 0xf8, 0xe0, 0xf8, + 0x0d, 0xfa, 0xc4, 0xf7, 0x78, 0xf3, 0x36, 0xf0, 0x20, 0xee, 0xb8, 0xed, + 0x5e, 0xee, 0x3a, 0xef, 0xf9, 0xed, 0x59, 0xeb, 0xb6, 0xe9, 0xb7, 0xec, + 0x0a, 0xf1, 0xd6, 0xf0, 0xc0, 0xef, 0xf2, 0xee, 0x0c, 0xee, 0x3b, 0xef, + 0x8b, 0xf2, 0x2d, 0xf5, 0x4d, 0xf4, 0xeb, 0xf2, 0xe0, 0xf6, 0x76, 0xfb, + 0x78, 0xfb, 0x18, 0xfb, 0xea, 0xfb, 0xaa, 0xfe, 0x2b, 0x00, 0xb7, 0xfd, + 0x8b, 0xfd, 0x8c, 0xfe, 0x75, 0xfb, 0x46, 0xf6, 0x6d, 0xf4, 0xd4, 0xf6, + 0x8b, 0xfa, 0x6b, 0xfc, 0xd1, 0xfb, 0x2f, 0xfb, 0xc6, 0xf9, 0x97, 0xf9, + 0x44, 0xfb, 0xaa, 0xfc, 0x51, 0xfe, 0xda, 0xff, 0xfc, 0x00, 0xf6, 0x00, + 0xa2, 0x01, 0x7b, 0x03, 0x49, 0x05, 0xcb, 0x04, 0x76, 0x02, 0x06, 0x02, + 0x7d, 0x02, 0xd1, 0x03, 0xdb, 0x02, 0x8b, 0xff, 0x54, 0xfd, 0x25, 0xfc, + 0xf1, 0xfc, 0x1c, 0xfd, 0x64, 0xfa, 0x0d, 0xf6, 0x66, 0xf5, 0x76, 0xf6, + 0xa7, 0xf4, 0x41, 0xf2, 0x43, 0xf1, 0x76, 0xf2, 0x14, 0xf2, 0x7c, 0xf0, + 0x42, 0xf0, 0x1d, 0xf0, 0xaf, 0xee, 0x87, 0xed, 0xa0, 0xed, 0xa1, 0xee, + 0x8d, 0xf1, 0x2d, 0xf4, 0xac, 0xf5, 0x01, 0xf6, 0x64, 0xf6, 0x75, 0xf9, + 0x60, 0xfd, 0x27, 0xff, 0xad, 0xfd, 0x88, 0xfb, 0x25, 0xfc, 0xe5, 0xff, + 0x9b, 0x01, 0x84, 0xff, 0x75, 0xfd, 0x6c, 0xfc, 0x78, 0xfd, 0xa7, 0x00, + 0xdd, 0x01, 0xea, 0x00, 0xa7, 0xfe, 0xd5, 0xfb, 0x47, 0xfb, 0x8a, 0xfc, + 0xb8, 0xfd, 0xce, 0xfd, 0x73, 0xfe, 0x44, 0xfe, 0xa7, 0xfe, 0xb9, 0x01, + 0x43, 0x03, 0x9c, 0x03, 0x20, 0x03, 0xb2, 0x02, 0x58, 0x04, 0xba, 0x04, + 0xfe, 0x03, 0x8c, 0x04, 0x55, 0x04, 0x8b, 0x04, 0x36, 0x08, 0xc7, 0x0b, + 0x61, 0x0c, 0xfb, 0x09, 0x84, 0x08, 0xdd, 0x09, 0xcf, 0x0b, 0xde, 0x0d, + 0x88, 0x0e, 0x77, 0x0c, 0x68, 0x09, 0xe4, 0x06, 0xac, 0x05, 0x1e, 0x06, + 0xd2, 0x05, 0xd2, 0x04, 0xc1, 0x04, 0xb8, 0x04, 0x1b, 0x05, 0x73, 0x05, + 0x41, 0x07, 0x84, 0x08, 0x78, 0x06, 0x7b, 0x05, 0x29, 0x05, 0x2e, 0x04, + 0x54, 0x04, 0x27, 0x06, 0xf9, 0x08, 0x03, 0x0a, 0x78, 0x08, 0x2f, 0x08, + 0x1b, 0x09, 0x1e, 0x09, 0x36, 0x0b, 0x96, 0x0c, 0x36, 0x0e, 0xde, 0x11, + 0xa5, 0x12, 0x4c, 0x13, 0x3e, 0x12, 0xf4, 0x0e, 0x70, 0x0d, 0x98, 0x0c, + 0x42, 0x0c, 0xf5, 0x0a, 0xa5, 0x08, 0xb8, 0x05, 0xd5, 0x00, 0xba, 0xfb, + 0xb6, 0xf8, 0x76, 0xf6, 0xd4, 0xf3, 0xdc, 0xf2, 0xad, 0xf1, 0x06, 0xef, + 0xe3, 0xec, 0xf0, 0xed, 0xa4, 0xef, 0xd6, 0xef, 0xa7, 0xf2, 0x3b, 0xf4, + 0x68, 0xf3, 0x82, 0xf3, 0x68, 0xf3, 0xef, 0xf3, 0xf6, 0xf3, 0x9d, 0xf4, + 0xdc, 0xf6, 0xc7, 0xf7, 0x05, 0xfb, 0x42, 0x00, 0x98, 0x02, 0x85, 0x05, + 0x7f, 0x0a, 0x5b, 0x0f, 0x15, 0x12, 0x59, 0x10, 0xcd, 0x0c, 0x59, 0x0e, + 0x9c, 0x13, 0x55, 0x16, 0x06, 0x14, 0x5a, 0x0c, 0xf8, 0x07, 0x1f, 0x07, + 0xe9, 0x05, 0x22, 0x06, 0xe9, 0x00, 0x4f, 0xf9, 0xc4, 0xf5, 0x78, 0xf4, + 0x08, 0xf5, 0x79, 0xf6, 0x1a, 0xf7, 0x9f, 0xf4, 0x89, 0xf2, 0x1f, 0xf4, + 0xd3, 0xf8, 0x8c, 0xf9, 0x00, 0xf3, 0xd1, 0xec, 0x89, 0xe9, 0xb0, 0xea, + 0xbc, 0xed, 0xc0, 0xed, 0x33, 0xec, 0x04, 0xeb, 0xae, 0xeb, 0xa5, 0xef, + 0xdd, 0xf4, 0xbe, 0xf6, 0x30, 0xf6, 0xe0, 0xf6, 0x28, 0xf9, 0x25, 0xfa, + 0x00, 0xfa, 0xbe, 0xf8, 0x52, 0xf6, 0x67, 0xf3, 0xa7, 0xf0, 0x0b, 0xf1, + 0x06, 0xf1, 0x0c, 0xef, 0x70, 0xec, 0xda, 0xe8, 0xda, 0xe8, 0xb3, 0xeb, + 0xd9, 0xec, 0x2f, 0xec, 0x09, 0xe9, 0x91, 0xe5, 0x33, 0xe7, 0x92, 0xea, + 0x6f, 0xec, 0x2b, 0xee, 0x41, 0xef, 0x5a, 0xef, 0xe9, 0xed, 0x19, 0xed, + 0x72, 0xee, 0xa5, 0xf0, 0x71, 0xf1, 0xf9, 0xf0, 0xfa, 0xf1, 0xd3, 0xf4, + 0xea, 0xf9, 0x3f, 0xff, 0x1c, 0x01, 0xf1, 0x00, 0x0f, 0x00, 0x2b, 0xff, + 0x9c, 0xfe, 0xc1, 0xfa, 0xcc, 0xf7, 0xe3, 0xf8, 0xc8, 0xf8, 0x92, 0xf7, + 0x20, 0xf8, 0x3a, 0xfa, 0x95, 0xfc, 0xf8, 0xfd, 0x41, 0xfd, 0xc4, 0xfc, + 0x4e, 0xfb, 0x89, 0xf8, 0xcc, 0xf7, 0x3a, 0xf6, 0x11, 0xf5, 0x8d, 0xf6, + 0x72, 0xf7, 0x0d, 0xf7, 0x4c, 0xf6, 0x03, 0xf5, 0xa6, 0xf6, 0x08, 0xfa, + 0x60, 0xfa, 0x93, 0xfa, 0x33, 0xfb, 0x0a, 0xfb, 0x42, 0xfc, 0xf9, 0xfe, + 0xcd, 0x01, 0x42, 0x04, 0x61, 0x04, 0xb4, 0x01, 0xa0, 0x00, 0x16, 0x00, + 0x0a, 0x01, 0xcd, 0x03, 0xe1, 0x01, 0x56, 0x00, 0xc5, 0xff, 0xdd, 0xfb, + 0x42, 0xfb, 0x9e, 0xfb, 0xf1, 0xfa, 0x7d, 0xfb, 0xba, 0xfa, 0x71, 0xfa, + 0xc6, 0xfa, 0x75, 0xf9, 0x3c, 0xf9, 0x47, 0xfb, 0xfa, 0xfa, 0xf2, 0xfb, + 0x20, 0xfd, 0x8b, 0xfb, 0x18, 0xfe, 0xed, 0x00, 0x08, 0x03, 0x5c, 0x05, + 0xba, 0x06, 0xa4, 0x08, 0x44, 0x0a, 0x29, 0x0e, 0x66, 0x12, 0x6a, 0x15, + 0xe4, 0x16, 0x42, 0x16, 0x32, 0x15, 0xc0, 0x14, 0xb6, 0x14, 0x30, 0x13, + 0x4d, 0x10, 0xa5, 0x0f, 0x01, 0x12, 0x77, 0x11, 0xd1, 0x0e, 0x11, 0x0c, + 0x48, 0x0a, 0xbb, 0x0c, 0x7c, 0x0c, 0xef, 0x09, 0x0f, 0x0a, 0x1a, 0x09, + 0xb8, 0x06, 0x14, 0x05, 0xaf, 0x04, 0xc9, 0x06, 0x02, 0x07, 0xbc, 0x02, + 0xf1, 0x01, 0x31, 0x04, 0x64, 0x04, 0x13, 0x05, 0x63, 0x04, 0x70, 0x03, + 0xfb, 0x04, 0x0c, 0x05, 0x57, 0x04, 0xee, 0x02, 0xb6, 0x01, 0x94, 0x03, + 0xef, 0x03, 0xe2, 0x02, 0xa6, 0x01, 0xa1, 0xfe, 0xc5, 0xfa, 0xf9, 0xf8, + 0x30, 0xfb, 0x1f, 0x00, 0xb4, 0x04, 0x14, 0x03, 0x4a, 0xfe, 0xea, 0xfd, + 0x30, 0xff, 0x4a, 0x02, 0xa5, 0x05, 0x01, 0x04, 0xe1, 0x01, 0x5e, 0x02, + 0x45, 0x03, 0x49, 0x04, 0x90, 0x03, 0xe7, 0x00, 0xba, 0xfe, 0x23, 0xfd, + 0x6c, 0xfd, 0xd1, 0xff, 0xad, 0x00, 0x53, 0xfe, 0xa7, 0xfc, 0x6c, 0xfd, + 0xcb, 0xfe, 0x01, 0x01, 0xa8, 0x01, 0x9e, 0x00, 0xb6, 0xff, 0xa6, 0xfd, + 0x3c, 0xfc, 0x6e, 0xfb, 0xdf, 0xfb, 0xbb, 0xfe, 0x24, 0x00, 0x6f, 0x00, + 0x20, 0x02, 0x8c, 0x00, 0xf3, 0xfd, 0xda, 0xfe, 0x98, 0xfe, 0xb9, 0xfd, + 0x6e, 0xfc, 0x76, 0xfa, 0xe8, 0xf7, 0x31, 0xf6, 0xce, 0xf6, 0x9b, 0xf6, + 0x48, 0xf6, 0x99, 0xf4, 0x58, 0xf2, 0x39, 0xf0, 0xe7, 0xee, 0x3e, 0xee, + 0x67, 0xed, 0x24, 0xee, 0x1c, 0xed, 0x66, 0xeb, 0x68, 0xeb, 0x66, 0xec, + 0x1b, 0xec, 0x7e, 0xec, 0x11, 0xef, 0x46, 0xf0, 0x67, 0xf1, 0x4b, 0xf2, + 0xab, 0xf2, 0x9f, 0xf3, 0x7a, 0xf4, 0xd3, 0xf4, 0x69, 0xf5, 0xad, 0xf6, + 0xe1, 0xf7, 0xc8, 0xf8, 0x1c, 0xf7, 0xb3, 0xf6, 0x15, 0xfa, 0x3e, 0xfb, + 0x84, 0xfa, 0x47, 0xf9, 0x77, 0xf8, 0xc8, 0xfa, 0xa6, 0xfb, 0x49, 0xfa, + 0xf9, 0xf9, 0x62, 0xfa, 0x86, 0xf9, 0x3e, 0xf7, 0x8d, 0xf7, 0xba, 0xfa, + 0x3f, 0xfd, 0xb5, 0xfa, 0xda, 0xf5, 0xd3, 0xf3, 0xb7, 0xf4, 0x97, 0xf7, + 0x33, 0xf9, 0xb4, 0xf9, 0x57, 0xfb, 0x66, 0xfe, 0xcc, 0x00, 0x6a, 0x01, + 0x7b, 0x00, 0xba, 0xff, 0x96, 0x00, 0x59, 0x00, 0x4c, 0x00, 0xf3, 0x01, + 0xb6, 0x03, 0x7c, 0x03, 0xb5, 0x01, 0x71, 0x00, 0xac, 0x00, 0xf8, 0x01, + 0x11, 0x02, 0x7a, 0x01, 0xba, 0xff, 0x59, 0x00, 0xa0, 0x03, 0xf4, 0x03, + 0x91, 0x02, 0x8c, 0xff, 0x95, 0xfc, 0x16, 0xfc, 0xa4, 0xfb, 0x6c, 0xfb, + 0xe6, 0xfc, 0x63, 0xfc, 0x8c, 0xfb, 0xd6, 0xfc, 0xc3, 0xfc, 0x33, 0xfd, + 0xdd, 0xfe, 0x21, 0x00, 0xa1, 0x01, 0x7b, 0x03, 0xe3, 0x04, 0xa5, 0x06, + 0xfe, 0x08, 0x63, 0x09, 0x50, 0x08, 0x52, 0x08, 0xd4, 0x0b, 0x3b, 0x0e, + 0x9c, 0x0c, 0xbd, 0x0b, 0x18, 0x0b, 0x00, 0x0b, 0xef, 0x0b, 0x75, 0x0b, + 0xc0, 0x0a, 0x9f, 0x0a, 0x2c, 0x09, 0x79, 0x07, 0x43, 0x08, 0xc7, 0x09, + 0x1d, 0x09, 0x49, 0x06, 0x34, 0x03, 0xd6, 0x02, 0x32, 0x04, 0xcf, 0x04, + 0xfc, 0x04, 0x04, 0x04, 0x47, 0x03, 0x8e, 0x02, 0x10, 0x02, 0x12, 0x03, + 0xf4, 0x03, 0xa7, 0x05, 0x2e, 0x07, 0xe7, 0x07, 0x6a, 0x08, 0x66, 0x09, + 0x19, 0x0b, 0xcf, 0x0b, 0xb4, 0x0c, 0x6f, 0x0e, 0x68, 0x0f, 0xcb, 0x0d, + 0xc8, 0x09, 0x2f, 0x09, 0x60, 0x0b, 0x59, 0x0b, 0x2f, 0x08, 0x2a, 0x04, + 0x22, 0x01, 0x70, 0xff, 0x07, 0xfe, 0xda, 0xfa, 0x4c, 0xf9, 0x1d, 0xfa, + 0xf3, 0xf8, 0x7c, 0xf7, 0x6c, 0xf8, 0x74, 0xfa, 0x01, 0xfc, 0x6e, 0xfb, + 0xc6, 0xf9, 0x2e, 0xfd, 0x0f, 0x00, 0x2b, 0xff, 0xf3, 0xfe, 0xbf, 0xff, + 0xd7, 0x02, 0x68, 0x05, 0x8f, 0x06, 0x99, 0x07, 0x99, 0x08, 0xdf, 0x08, + 0x89, 0x09, 0xc4, 0x0c, 0x81, 0x0f, 0xc5, 0x11, 0x76, 0x12, 0xe0, 0x10, + 0x1b, 0x10, 0x37, 0x0f, 0x67, 0x0d, 0x8b, 0x0a, 0x4e, 0x07, 0x4b, 0x06, + 0x43, 0x05, 0x10, 0x04, 0x5c, 0x03, 0x75, 0x01, 0xa5, 0xff, 0xcf, 0xfe, + 0xe8, 0xfe, 0x86, 0xff, 0x14, 0x01, 0x1f, 0x03, 0x09, 0x03, 0x95, 0x02, + 0x46, 0x03, 0x18, 0x04, 0x46, 0x06, 0x5e, 0x09, 0x09, 0x09, 0x58, 0x08, + 0x18, 0x08, 0x76, 0x06, 0x8f, 0x07, 0x65, 0x09, 0xc6, 0x09, 0x89, 0x09, + 0x31, 0x07, 0x4e, 0x05, 0xc8, 0x06, 0x88, 0x08, 0x4e, 0x09, 0x42, 0x09, + 0x69, 0x06, 0x51, 0x04, 0x7f, 0x03, 0x39, 0x01, 0x8a, 0xfe, 0x8b, 0xfb, + 0x34, 0xf9, 0x41, 0xf8, 0x59, 0xf5, 0xf6, 0xf1, 0xac, 0xf2, 0xc9, 0xf4, + 0x8f, 0xf4, 0x50, 0xf2, 0x53, 0xf1, 0x5c, 0xf2, 0xe0, 0xf2, 0xe6, 0xf1, + 0x56, 0xf1, 0xca, 0xf2, 0xc6, 0xf2, 0x3b, 0xf1, 0x03, 0xf1, 0x06, 0xf2, + 0xa9, 0xf3, 0xf1, 0xf4, 0x56, 0xf5, 0xee, 0xf5, 0xdc, 0xf7, 0x54, 0xfb, + 0x06, 0xff, 0xd7, 0x00, 0xf3, 0x00, 0x1d, 0x00, 0xfa, 0x00, 0xb2, 0x01, + 0x0d, 0x00, 0xfe, 0xff, 0xad, 0x00, 0xd2, 0x01, 0x5f, 0x02, 0x6b, 0x02, + 0xd7, 0x01, 0xac, 0x00, 0xdf, 0x00, 0x32, 0x00, 0x99, 0x01, 0xc7, 0x03, + 0x37, 0x02, 0x22, 0x00, 0xdd, 0xfe, 0x17, 0xff, 0xad, 0x01, 0xa0, 0x04, + 0xbb, 0x05, 0x17, 0x04, 0xbf, 0x01, 0x9c, 0x01, 0x61, 0x03, 0x2b, 0x05, + 0xf3, 0x06, 0xe7, 0x07, 0xd5, 0x08, 0xbf, 0x0a, 0xf9, 0x0a, 0x92, 0x09, + 0x19, 0x0a, 0xaa, 0x0c, 0x1b, 0x0c, 0xcc, 0x0a, 0xec, 0x09, 0xa6, 0x08, + 0x56, 0x09, 0x30, 0x07, 0xe3, 0x05, 0x6d, 0x06, 0x0e, 0x05, 0xbd, 0x04, + 0x81, 0x05, 0xc3, 0x05, 0xc0, 0x04, 0x69, 0x04, 0x79, 0x04, 0x42, 0x04, + 0xed, 0x04, 0xd0, 0x04, 0x64, 0x05, 0xed, 0x05, 0x64, 0x04, 0x2f, 0x05, + 0xfd, 0x05, 0x11, 0x04, 0x2b, 0x02, 0x68, 0x00, 0x17, 0x01, 0xa6, 0x01, + 0x8a, 0xff, 0xab, 0xfd, 0x7c, 0xfc, 0xef, 0xfc, 0xb9, 0xfe, 0x62, 0xfe, + 0xaf, 0xfb, 0x6f, 0xf9, 0xb9, 0xf8, 0xd2, 0xf8, 0xdc, 0xfa, 0xa8, 0xfc, + 0xe9, 0xfa, 0x1b, 0xf9, 0x1b, 0xf7, 0xf7, 0xf6, 0x87, 0xf8, 0x33, 0xf7, + 0xcd, 0xf8, 0x5d, 0xfb, 0x5f, 0xfc, 0xd6, 0xfc, 0x6e, 0xfb, 0x3f, 0xfb, + 0xd7, 0xfc, 0x8a, 0xfd, 0x97, 0xfb, 0xe2, 0xfa, 0x30, 0xfb, 0xe2, 0xf9, + 0xaa, 0xf9, 0x40, 0xfb, 0xec, 0xfd, 0x8f, 0xff, 0x85, 0xfe, 0x2a, 0xfe, + 0xfc, 0x00, 0x3a, 0x02, 0x82, 0x00, 0x07, 0x00, 0x2c, 0x00, 0x09, 0x01, + 0xb6, 0x00, 0xef, 0xfe, 0xd9, 0xff, 0xe2, 0x00, 0xb3, 0x01, 0x5d, 0x03, + 0x40, 0x04, 0x12, 0x06, 0x7e, 0x07, 0x32, 0x06, 0xe4, 0x05, 0xba, 0x08, + 0x3e, 0x09, 0xfa, 0x08, 0x4f, 0x08, 0xf8, 0x05, 0xc7, 0x05, 0x47, 0x05, + 0xff, 0x04, 0x81, 0x04, 0x64, 0x02, 0x04, 0x02, 0x49, 0x02, 0x5b, 0x01, + 0xef, 0xff, 0x0a, 0xff, 0xb6, 0xfe, 0x5b, 0xfe, 0x8b, 0xfc, 0x63, 0xfa, + 0x55, 0xfa, 0xeb, 0xfc, 0xb0, 0xff, 0xa7, 0xff, 0x64, 0xff, 0xbd, 0x00, + 0xbf, 0x02, 0x58, 0x03, 0xcc, 0x02, 0x3d, 0x03, 0x64, 0x03, 0x60, 0x03, + 0x76, 0x03, 0x97, 0x04, 0x6f, 0x06, 0x06, 0x07, 0xd5, 0x07, 0xc1, 0x09, + 0x82, 0x0a, 0xcb, 0x0a, 0x3c, 0x0c, 0x9f, 0x0a, 0xc3, 0x06, 0x3f, 0x05, + 0x9b, 0x05, 0x48, 0x07, 0xc2, 0x06, 0xc2, 0x03, 0x20, 0x02, 0xfa, 0x01, + 0x2b, 0x02, 0xa7, 0x02, 0xec, 0x01, 0x33, 0x00, 0x6f, 0xfe, 0xc1, 0xfb, + 0x72, 0xfa, 0x1d, 0xfa, 0x6c, 0xfa, 0xf9, 0xfb, 0x13, 0xfb, 0x72, 0xf9, + 0x81, 0xfb, 0xd8, 0xfe, 0x49, 0x00, 0xa3, 0x02, 0xc1, 0x03, 0xcd, 0x01, + 0x48, 0x01, 0xe7, 0x01, 0x15, 0x04, 0xe2, 0x05, 0xe8, 0x04, 0xe1, 0x04, + 0xcb, 0x06, 0x79, 0x07, 0x0b, 0x08, 0x66, 0x09, 0xee, 0x09, 0xb1, 0x0a, + 0xac, 0x07, 0x15, 0x05, 0xd6, 0x06, 0x69, 0x06, 0x76, 0x04, 0x03, 0x01, + 0x8e, 0xff, 0x01, 0x01, 0x0c, 0x00, 0xe9, 0xfc, 0xa7, 0xfb, 0x2c, 0xfc, + 0x0f, 0xfb, 0x74, 0xfc, 0x11, 0xfe, 0x9c, 0xfc, 0x0c, 0xfc, 0xe2, 0xfa, + 0x6a, 0xfb, 0x79, 0xfe, 0x84, 0xff, 0x46, 0x00, 0xd7, 0x01, 0x11, 0x02, + 0x52, 0x03, 0xab, 0x06, 0x8b, 0x09, 0x87, 0x0a, 0x18, 0x09, 0x71, 0x07, + 0xda, 0x08, 0xa7, 0x0b, 0x14, 0x0c, 0x7d, 0x0c, 0x2f, 0x0d, 0x02, 0x0d, + 0x14, 0x0d, 0xed, 0x09, 0xdf, 0x06, 0xee, 0x05, 0xaa, 0x04, 0x11, 0x04, + 0xfc, 0x01, 0xf3, 0xfe, 0x83, 0xfd, 0xcc, 0xfc, 0x1a, 0xfb, 0x00, 0xfb, + 0xc1, 0xfa, 0x68, 0xf8, 0x8a, 0xf7, 0xc9, 0xf6, 0xf6, 0xf5, 0xaf, 0xf5, + 0xfb, 0xf3, 0x79, 0xf3, 0x02, 0xf4, 0x73, 0xf3, 0x24, 0xf4, 0xcd, 0xf4, + 0x73, 0xf4, 0x68, 0xf5, 0xf7, 0xf6, 0x53, 0xf9, 0x0e, 0xfa, 0x60, 0xf9, + 0x5e, 0xf8, 0x0e, 0xf7, 0xec, 0xf7, 0x4d, 0xfa, 0x1c, 0xfc, 0x3e, 0xfa, + 0x4c, 0xf8, 0x59, 0xf9, 0x67, 0xfa, 0x6f, 0xfb, 0x69, 0xfb, 0x55, 0xfb, + 0xc5, 0xfc, 0xfb, 0xfb, 0xce, 0xfa, 0xd2, 0xfc, 0xcc, 0xfd, 0x29, 0xfd, + 0x8a, 0xfc, 0xc6, 0xfd, 0x5b, 0x00, 0x34, 0x01, 0xdf, 0x01, 0xa8, 0x02, + 0x8a, 0x04, 0xbb, 0x05, 0x58, 0x05, 0x72, 0x05, 0x48, 0x06, 0x00, 0x09, + 0xa9, 0x09, 0x11, 0x0a, 0xad, 0x0a, 0x5d, 0x09, 0x5f, 0x08, 0x32, 0x08, + 0x0a, 0x0b, 0xd9, 0x0d, 0x8a, 0x0d, 0x4d, 0x0c, 0x69, 0x0b, 0x71, 0x0a, + 0x6d, 0x09, 0x6c, 0x08, 0xcb, 0x06, 0xbf, 0x05, 0x01, 0x05, 0xc5, 0x03, + 0x8b, 0x03, 0x65, 0x04, 0x41, 0x03, 0xf4, 0x02, 0xcb, 0x03, 0x34, 0x03, + 0x1f, 0x03, 0x00, 0x00, 0xb4, 0xfb, 0xee, 0xfa, 0x28, 0xfa, 0xa1, 0xf8, + 0x4a, 0xf6, 0x38, 0xf3, 0x90, 0xf3, 0x2a, 0xf6, 0xcd, 0xf7, 0xd2, 0xf8, + 0x3c, 0xf8, 0x29, 0xf7, 0xa1, 0xf7, 0x02, 0xf8, 0x74, 0xf6, 0xd4, 0xf6, + 0x4a, 0xf7, 0x23, 0xf8, 0x30, 0xfa, 0xa9, 0xf9, 0x48, 0xfb, 0x48, 0xfc, + 0xcb, 0xf9, 0xd5, 0xf9, 0x59, 0xfb, 0x96, 0xfb, 0xd5, 0xfa, 0x76, 0xf9, + 0xe0, 0xf7, 0x66, 0xf8, 0xd6, 0xfa, 0xf4, 0xfb, 0x80, 0xfd, 0x93, 0xff, + 0x3c, 0xff, 0xfd, 0xfe, 0x46, 0xfd, 0x7e, 0xfc, 0x98, 0xfe, 0xee, 0xfc, + 0xb4, 0xfb, 0x0a, 0xfc, 0x06, 0xfd, 0x4e, 0x00, 0xfe, 0x00, 0x6c, 0x00, + 0xdc, 0x01, 0xdd, 0x02, 0xe0, 0x02, 0x69, 0x03, 0x71, 0x04, 0xb7, 0x05, + 0xc9, 0x05, 0x7c, 0x04, 0x63, 0x04, 0x15, 0x06, 0x46, 0x06, 0x07, 0x07, + 0x0d, 0x08, 0xbf, 0x07, 0x6a, 0x09, 0x4e, 0x0a, 0xf0, 0x09, 0xc8, 0x08, + 0x36, 0x08, 0xa8, 0x08, 0x1b, 0x08, 0x36, 0x07, 0x56, 0x08, 0xcb, 0x0b, + 0x61, 0x0c, 0x76, 0x0a, 0x0b, 0x09, 0xd0, 0x08, 0xda, 0x08, 0x77, 0x06, + 0x9c, 0x03, 0xaf, 0x02, 0x33, 0x01, 0x8b, 0xff, 0xaa, 0xff, 0x02, 0xfe, + 0xdb, 0xfd, 0xc4, 0xfe, 0x85, 0xfc, 0xf8, 0xfb, 0x30, 0xfc, 0x5e, 0xfb, + 0x41, 0xfb, 0xd9, 0xfa, 0x96, 0xfa, 0x43, 0xfc, 0x87, 0xfd, 0x10, 0xfd, + 0x55, 0xfc, 0xd6, 0xfb, 0x4f, 0xfc, 0xa9, 0xfc, 0xdb, 0xfc, 0x06, 0xfd, + 0xdb, 0xfc, 0xb1, 0xfc, 0xd7, 0xfc, 0x87, 0xfd, 0xe8, 0xfc, 0x4a, 0xfc, + 0x61, 0xfc, 0xd2, 0xfb, 0xf8, 0xfb, 0xbe, 0xfb, 0x01, 0xfa, 0xdc, 0xf7, + 0xc8, 0xf5, 0x80, 0xf4, 0xd9, 0xf5, 0x0c, 0xf8, 0xc2, 0xf9, 0x50, 0xfc, + 0xd0, 0xfd, 0xbc, 0xff, 0xa7, 0x02, 0x70, 0x03, 0x47, 0x04, 0x0f, 0x05, + 0x29, 0x04, 0x1a, 0x03, 0x08, 0x03, 0x07, 0x04, 0xf9, 0x05, 0x26, 0x07, + 0x95, 0x06, 0x26, 0x07, 0x27, 0x07, 0x8a, 0x06, 0xc3, 0x06, 0xc6, 0x05, + 0x12, 0x05, 0x12, 0x03, 0xee, 0x00, 0x5f, 0x01, 0xc2, 0x00, 0xbc, 0x00, + 0x38, 0x01, 0xe6, 0xff, 0xd3, 0xff, 0xf4, 0xff, 0xd1, 0xfe, 0x36, 0xfe, + 0xb8, 0xfe, 0x02, 0xff, 0x75, 0xfe, 0x92, 0xfe, 0x63, 0xfd, 0x43, 0xfc, + 0x60, 0xfb, 0xfc, 0xf9, 0x0c, 0xfa, 0x8e, 0xf9, 0x90, 0xfa, 0xe4, 0xfc, + 0x95, 0xfd, 0xa8, 0xfd, 0x23, 0xfe, 0x68, 0xfe, 0x5a, 0xff, 0xf6, 0x00, + 0xbe, 0xff, 0x9f, 0x00, 0x90, 0x02, 0x3a, 0x04, 0x5b, 0x08, 0x3a, 0x09, + 0xcf, 0x08, 0x7b, 0x07, 0xef, 0x03, 0x9f, 0x01, 0xc5, 0x00, 0x79, 0x00, + 0xf2, 0x00, 0xcc, 0x02, 0xeb, 0x03, 0x1f, 0x04, 0x72, 0x04, 0x5a, 0x03, + 0x99, 0x01, 0x6b, 0x00, 0xec, 0xff, 0x7e, 0x00, 0x48, 0x00, 0x1f, 0xff, + 0x1d, 0xfe, 0x68, 0xfe, 0x33, 0xff, 0xcc, 0xff, 0x7e, 0x01, 0xf3, 0x01, + 0xcc, 0x01, 0xf0, 0x00, 0xf6, 0x00, 0xe3, 0x02, 0x72, 0x03, 0xbc, 0x03, + 0xba, 0x03, 0x6b, 0x04, 0xc5, 0x05, 0xce, 0x06, 0x6f, 0x07, 0xee, 0x06, + 0x8d, 0x05, 0x39, 0x04, 0x4e, 0x03, 0xbf, 0x01, 0xde, 0x00, 0x11, 0x00, + 0xaa, 0xfd, 0x3c, 0xfc, 0x8d, 0xfa, 0x66, 0xf7, 0x01, 0xf5, 0xff, 0xf2, + 0xec, 0xf0, 0x3c, 0xf0, 0xb5, 0xef, 0x65, 0xef, 0x1d, 0xf1, 0x23, 0xf3, + 0x33, 0xf4, 0x0b, 0xf6, 0x9e, 0xf7, 0x52, 0xfa, 0xd4, 0xfd, 0xdc, 0xfe, + 0x29, 0x00, 0x6d, 0x01, 0xfb, 0xff, 0xb6, 0xfe, 0x4a, 0xfc, 0x6a, 0xf8, + 0xae, 0xf6, 0x66, 0xf6, 0x34, 0xf7, 0x8a, 0xf7, 0x9c, 0xf8, 0xea, 0xfb, + 0xed, 0xfd, 0x63, 0xfe, 0x46, 0xfc, 0x49, 0xfa, 0x8e, 0xf9, 0x12, 0xf9, + 0xf4, 0xfa, 0xff, 0xfb, 0x32, 0xfe, 0x81, 0x00, 0x6f, 0x00, 0xe8, 0x02, + 0xad, 0x04, 0xe8, 0x06, 0x8c, 0x0a, 0xe5, 0x0c, 0x8f, 0x10, 0x09, 0x12, + 0x64, 0x11, 0x08, 0x10, 0x07, 0x0f, 0x66, 0x0e, 0xeb, 0x0b, 0x67, 0x09, + 0x67, 0x05, 0x09, 0x02, 0x04, 0xfd, 0x22, 0xf8, 0xa7, 0xf6, 0x5b, 0xf4, + 0x92, 0xf4, 0xeb, 0xf5, 0x28, 0xf7, 0x11, 0xf9, 0x28, 0xfa, 0x59, 0xfb, + 0xc0, 0xfc, 0xb2, 0xfc, 0x98, 0xfa, 0x7d, 0xf7, 0xa2, 0xf1, 0x18, 0xeb, + 0x1e, 0xe5, 0x5d, 0xe1, 0xf9, 0xde, 0x84, 0xde, 0x06, 0xe3, 0xea, 0xe8, + 0xe5, 0xef, 0xfe, 0xf6, 0xb4, 0xfc, 0xf1, 0xfe, 0x7d, 0xff, 0x9b, 0xff, + 0x82, 0xfe, 0x7e, 0x00, 0xf5, 0x01, 0xc5, 0x01, 0xff, 0x02, 0x7c, 0x05, + 0x86, 0x08, 0xb3, 0x0a, 0xd7, 0x0a, 0x61, 0x08, 0x09, 0x06, 0xf5, 0x03, + 0xaa, 0xff, 0xa3, 0xfa, 0x3e, 0xf6, 0x04, 0xf0, 0xdc, 0xeb, 0x0d, 0xe9, + 0x80, 0xe5, 0xac, 0xe4, 0xef, 0xe4, 0x53, 0xe7, 0x5c, 0xeb, 0xd4, 0xec, + 0xe5, 0xed, 0x72, 0xf1, 0x9c, 0xf3, 0x03, 0xf6, 0x2b, 0xf9, 0x3e, 0xfb, + 0xa9, 0xfd, 0x5b, 0x01, 0x11, 0x08, 0x42, 0x0e, 0x3d, 0x14, 0x89, 0x19, + 0x17, 0x1f, 0xdb, 0x23, 0x28, 0x24, 0x92, 0x24, 0x4c, 0x23, 0x5d, 0x20, + 0x85, 0x1d, 0xeb, 0x18, 0x56, 0x14, 0xc7, 0x11, 0x6e, 0x0f, 0x07, 0x0c, + 0x48, 0x09, 0xa9, 0x05, 0xfd, 0x00, 0x77, 0xfe, 0x35, 0xfd, 0xd7, 0xfb, + 0x7d, 0xfa, 0xab, 0xf8, 0xf8, 0xf8, 0x2e, 0xfa, 0xca, 0xfa, 0x42, 0xfa, + 0x4d, 0xf8, 0xaa, 0xf6, 0x8e, 0xf5, 0x4a, 0xf5, 0x27, 0xf5, 0x73, 0xf5, + 0x88, 0xf4, 0x8b, 0xf4, 0x5c, 0xf5, 0xae, 0xf5, 0xf7, 0xf5, 0x08, 0xf5, + 0xdb, 0xf4, 0xad, 0xf3, 0x3b, 0xf2, 0x31, 0xf0, 0x0e, 0xee, 0x48, 0xee, + 0xae, 0xef, 0x52, 0xf0, 0xbe, 0xef, 0x86, 0xf1, 0xf2, 0xf3, 0x8e, 0xf7, + 0xf7, 0xfc, 0x3d, 0x01, 0xb1, 0x04, 0xd1, 0x06, 0x1f, 0x07, 0x14, 0x06, + 0x1c, 0x04, 0xcd, 0x01, 0x68, 0x00, 0xdb, 0x00, 0xbe, 0x01, 0x64, 0x00, + 0x09, 0xff, 0x38, 0xff, 0xe2, 0x00, 0xe3, 0x01, 0x2d, 0x01, 0xf8, 0x02, + 0xc1, 0x03, 0xcb, 0x02, 0xb8, 0x02, 0x44, 0x00, 0x1c, 0xff, 0xbb, 0x02, + 0x7c, 0x05, 0x3b, 0x07, 0x50, 0x0a, 0x74, 0x0b, 0x69, 0x0b, 0x9d, 0x0b, + 0x93, 0x0a, 0x02, 0x0a, 0x73, 0x0a, 0xe4, 0x0b, 0xad, 0x0c, 0xb1, 0x09, + 0x27, 0x08, 0x42, 0x07, 0x2e, 0x03, 0xf1, 0x00, 0x5b, 0x00, 0x52, 0x00, + 0x4f, 0xff, 0x5f, 0xfd, 0x8f, 0xf9, 0xdf, 0xf3, 0x61, 0xf2, 0x9b, 0xf3, + 0xb7, 0xf4, 0x03, 0xf6, 0x01, 0xf7, 0x88, 0xf7, 0x7b, 0xf7, 0x1a, 0xf7, + 0xa0, 0xf7, 0x47, 0xf8, 0x18, 0xf8, 0xd0, 0xf9, 0x4b, 0xfb, 0x5e, 0xfc, + 0x73, 0xff, 0x35, 0x01, 0xc2, 0x02, 0xfa, 0x04, 0x16, 0x07, 0xb2, 0x07, + 0x4d, 0x08, 0x29, 0x0d, 0xd7, 0x0f, 0xf3, 0x11, 0x42, 0x16, 0x27, 0x16, + 0x41, 0x14, 0x12, 0x0d, 0x66, 0x00, 0x4f, 0xf5, 0xbe, 0xe8, 0x6c, 0xde, + 0x7b, 0xda, 0x04, 0xdd, 0xcc, 0xe4, 0x45, 0xeb, 0xd0, 0xf0, 0x0b, 0xf5, + 0xe9, 0xf8, 0x81, 0xff, 0x06, 0x03, 0x06, 0x05, 0x5f, 0x08, 0xd8, 0x09, + 0xd9, 0x09, 0xd4, 0x0c, 0x9f, 0x12, 0xe3, 0x15, 0x1a, 0x18, 0x6e, 0x1a, + 0xfb, 0x1c, 0xa7, 0x1c, 0x1c, 0x1a, 0xe6, 0x19, 0x76, 0x15, 0x80, 0x0f, + 0x11, 0x0a, 0x71, 0x03, 0x04, 0x01, 0xad, 0xfe, 0x68, 0xfc, 0x6b, 0xfc, + 0xa0, 0xfb, 0xbb, 0xf9, 0xfa, 0xf6, 0x9c, 0xf2, 0x6c, 0xed, 0x5a, 0xec, + 0xa0, 0xef, 0x78, 0xf3, 0xc2, 0xf9, 0x3c, 0x01, 0x99, 0x04, 0x30, 0x0a, + 0x51, 0x11, 0xce, 0x15, 0x41, 0x19, 0xa2, 0x17, 0x88, 0x15, 0x47, 0x14, + 0x5f, 0x12, 0xcd, 0x11, 0x1f, 0x11, 0x66, 0x0f, 0xa3, 0x0a, 0x0c, 0x02, + 0x1a, 0xf6, 0xfc, 0xeb, 0xd0, 0xe5, 0x18, 0xe2, 0x93, 0xe1, 0xf4, 0xe0, + 0x08, 0xe1, 0x37, 0xe8, 0xb6, 0xee, 0x9f, 0xeb, 0x5e, 0xe7, 0xe3, 0xe5, + 0x1b, 0xe8, 0x30, 0xec, 0x7b, 0xed, 0x0a, 0xf1, 0x4f, 0xf8, 0x61, 0x00, + 0x25, 0x09, 0x92, 0x0f, 0x39, 0x16, 0xd6, 0x1e, 0xf4, 0x20, 0x8d, 0x1e, + 0x4b, 0x1c, 0xec, 0x18, 0x48, 0x18, 0xb8, 0x16, 0xa7, 0x11, 0x9e, 0x0b, + 0x2d, 0x00, 0x89, 0xf3, 0x66, 0xed, 0xdf, 0xee, 0x80, 0xf4, 0x3b, 0xf3, + 0xb8, 0xec, 0x63, 0xe7, 0x68, 0xe7, 0xae, 0xef, 0x76, 0xf7, 0x26, 0xfb, + 0x5a, 0xfb, 0x68, 0xfc, 0xcc, 0xfe, 0x30, 0x01, 0x61, 0x04, 0x5c, 0x05, + 0xd7, 0x03, 0x0f, 0xfe, 0xec, 0xfb, 0x4c, 0xfb, 0xb0, 0xf8, 0xcd, 0xfb, + 0x0f, 0xff, 0x83, 0xfc, 0x22, 0xf4, 0xec, 0xea, 0x12, 0xe4, 0xab, 0xe1, + 0x61, 0xe1, 0x9c, 0xdf, 0xa8, 0xdc, 0x12, 0xdd, 0xab, 0xe5, 0xda, 0xea, + 0x12, 0xee, 0x59, 0xf4, 0xc3, 0xf9, 0x7b, 0x00, 0x1f, 0x07, 0x32, 0x0a, + 0x10, 0x0a, 0xdb, 0x0a, 0x16, 0x11, 0x73, 0x1a, 0xf2, 0x1d, 0xb4, 0x1b, + 0x43, 0x15, 0x2d, 0x13, 0x27, 0x18, 0x45, 0x17, 0x62, 0x12, 0x30, 0x0f, + 0xc3, 0x11, 0x61, 0x17, 0xbd, 0x15, 0xc5, 0x0a, 0xf1, 0xfe, 0x7c, 0xfb, + 0x57, 0x00, 0x5d, 0x04, 0x02, 0x02, 0x1b, 0xfc, 0x26, 0xf8, 0x97, 0xfb, + 0x0a, 0xff, 0x03, 0x00, 0x7e, 0xff, 0xce, 0x01, 0x89, 0x09, 0x62, 0x0c, + 0xd2, 0x07, 0xd2, 0x00, 0x3e, 0x00, 0xf9, 0x04, 0x3c, 0x08, 0x46, 0x06, + 0xea, 0x03, 0xa8, 0x06, 0x16, 0x08, 0xc9, 0x06, 0xd5, 0x05, 0x60, 0x07, + 0xc0, 0x08, 0x31, 0x0b, 0xeb, 0x0e, 0x69, 0x10, 0xfa, 0x0c, 0x8e, 0x07, + 0x52, 0x05, 0xe7, 0x05, 0x2e, 0x0b, 0x22, 0x0d, 0xcb, 0x04, 0xce, 0xf6, + 0xdc, 0xeb, 0x12, 0xe8, 0x0c, 0xe5, 0x84, 0xe0, 0x30, 0xdc, 0x55, 0xd8, + 0xef, 0xda, 0xcd, 0xe4, 0xd4, 0xec, 0xbe, 0xf3, 0xdb, 0xfc, 0x51, 0x03, + 0xae, 0x04, 0xc7, 0x04, 0x3a, 0x05, 0xab, 0x09, 0x3a, 0x0f, 0x38, 0x0f, + 0xaf, 0x0e, 0xfb, 0x12, 0x96, 0x1b, 0x0b, 0x1e, 0x8b, 0x1a, 0xde, 0x17, + 0x54, 0x16, 0x48, 0x13, 0x88, 0x0a, 0xf6, 0x03, 0x22, 0x01, 0x3a, 0xfe, + 0x76, 0xfb, 0x4d, 0xf6, 0x65, 0xf0, 0xc1, 0xef, 0x81, 0xf3, 0xfe, 0xf4, + 0x60, 0xf6, 0x90, 0xf5, 0x2c, 0xf3, 0xc9, 0xf3, 0xa7, 0xf0, 0x2f, 0xee, + 0xf1, 0xf2, 0x87, 0xfb, 0x08, 0x08, 0x6c, 0x10, 0xbf, 0x13, 0x3b, 0x15, + 0x46, 0x14, 0xed, 0x19, 0x53, 0x20, 0xf2, 0x21, 0x8a, 0x23, 0x3f, 0x23, + 0x90, 0x1f, 0x15, 0x19, 0x0b, 0x15, 0xc8, 0x13, 0x44, 0x13, 0xef, 0x14, + 0x74, 0x14, 0xae, 0x10, 0x09, 0x0e, 0x2b, 0x0c, 0x90, 0x0b, 0xd8, 0x0a, + 0xe2, 0x08, 0xcc, 0x06, 0xbd, 0xfe, 0x3d, 0xf4, 0x24, 0xeb, 0x92, 0xe1, + 0x07, 0xdb, 0x2a, 0xd7, 0x9a, 0xd8, 0x19, 0xde, 0x74, 0xe0, 0xee, 0xe0, + 0x55, 0xe3, 0x65, 0xe5, 0xf9, 0xe4, 0xcd, 0xe1, 0xc8, 0xd9, 0xc8, 0xd2, + 0x55, 0xd4, 0xa0, 0xd9, 0x94, 0xde, 0xc6, 0xe7, 0x08, 0xf1, 0x81, 0xf6, + 0x25, 0xfd, 0xba, 0x03, 0x59, 0x0b, 0x13, 0x15, 0x7f, 0x1c, 0x3b, 0x21, + 0xba, 0x23, 0x79, 0x24, 0x88, 0x27, 0x02, 0x2b, 0x76, 0x2e, 0xcc, 0x2f, + 0x4b, 0x29, 0xef, 0x20, 0x5c, 0x1d, 0x48, 0x1f, 0xa1, 0x21, 0xa0, 0x1a, + 0x0a, 0x0a, 0x67, 0xfb, 0xb3, 0xf4, 0xbe, 0xf4, 0x26, 0xf8, 0xab, 0xfd, + 0xe0, 0xfd, 0x9b, 0xec, 0x84, 0xde, 0x64, 0xe4, 0x36, 0xf2, 0xdc, 0xfa, + 0x5f, 0xf9, 0x35, 0xf4, 0xb8, 0xf2, 0x7b, 0xf8, 0xdd, 0xff, 0x56, 0x04, + 0x66, 0x03, 0xf9, 0xfd, 0xdd, 0xfb, 0xa1, 0x02, 0x30, 0x0a, 0xdb, 0x03, + 0xee, 0xf5, 0xb4, 0xf4, 0x83, 0x00, 0xe7, 0x03, 0x44, 0xfb, 0x3b, 0xed, + 0xf2, 0xe7, 0x3f, 0xf3, 0x5b, 0x00, 0xba, 0x02, 0xf0, 0xf7, 0x7d, 0xf3, + 0x3f, 0xf7, 0x49, 0xf8, 0x16, 0xfa, 0xfc, 0xfc, 0xb2, 0xfc, 0xb6, 0xf6, + 0xe9, 0xe9, 0xff, 0xe2, 0x6a, 0xed, 0x99, 0xf7, 0x0d, 0xfa, 0xe4, 0xf3, + 0x41, 0xf1, 0x32, 0xfb, 0x49, 0x02, 0x48, 0x02, 0x87, 0xfc, 0xad, 0xfc, + 0x7d, 0x07, 0x3d, 0x0b, 0xb0, 0x01, 0x99, 0xfc, 0xb2, 0x01, 0xf1, 0x11, + 0x4e, 0x1d, 0x39, 0x18, 0x27, 0x1a, 0x13, 0x29, 0x23, 0x3e, 0xe8, 0x40, + 0x6f, 0x33, 0x5c, 0x29, 0x1e, 0x24, 0xf3, 0x25, 0xf8, 0x21, 0xd8, 0x14, + 0xb8, 0x05, 0xdf, 0xfc, 0x34, 0xf6, 0xcf, 0xf3, 0xcd, 0xf5, 0xc3, 0xf1, + 0x33, 0xe3, 0x17, 0xd1, 0x1f, 0xd1, 0xd7, 0xd6, 0xca, 0xdc, 0x08, 0xe4, + 0xa3, 0xe2, 0x34, 0xe4, 0x3b, 0xed, 0x99, 0xfa, 0x0e, 0x06, 0xea, 0x09, + 0x1c, 0x07, 0x79, 0x03, 0x38, 0x0b, 0x77, 0x1a, 0x27, 0x1c, 0xa2, 0x14, + 0x02, 0x17, 0x17, 0x1c, 0xd4, 0x11, 0x38, 0x08, 0x35, 0x0c, 0x25, 0x0f, + 0x9b, 0x15, 0xba, 0x16, 0xcf, 0x09, 0x93, 0xfa, 0xd4, 0xe7, 0x40, 0xdb, + 0x0b, 0xde, 0xae, 0xdb, 0xfc, 0xcc, 0x8c, 0xc3, 0x29, 0xc1, 0x8e, 0xc4, + 0x04, 0xcc, 0x7d, 0xd6, 0x2a, 0xe7, 0x13, 0xf3, 0xa0, 0xf3, 0xb3, 0xf8, + 0x49, 0x02, 0x39, 0x06, 0x1e, 0x16, 0x7c, 0x26, 0x5d, 0x22, 0xfc, 0x19, + 0xa8, 0x22, 0x02, 0x32, 0x63, 0x33, 0x91, 0x37, 0xc7, 0x3d, 0x01, 0x3b, + 0x70, 0x31, 0xfd, 0x27, 0xbc, 0x31, 0x72, 0x37, 0xc3, 0x1e, 0x69, 0x0e, + 0x05, 0x1d, 0x58, 0x2a, 0xb5, 0x33, 0xf5, 0x3b, 0x36, 0x38, 0x0c, 0x2b, + 0x72, 0x0a, 0x02, 0xf3, 0x38, 0xfa, 0xec, 0xf8, 0x04, 0xec, 0x65, 0xf0, + 0x5b, 0xf2, 0x97, 0xdc, 0xf4, 0xd5, 0x08, 0xdf, 0x15, 0xe2, 0x3d, 0xe9, + 0x81, 0xe7, 0x7e, 0xe3, 0x0e, 0xdb, 0x6d, 0xcc, 0xd3, 0xcf, 0x3a, 0xda, + 0xa3, 0xce, 0x5b, 0xb6, 0x49, 0xb8, 0xa9, 0xbd, 0xe7, 0xbc, 0x8b, 0xd3, + 0x5c, 0xee, 0xb9, 0xf7, 0x38, 0xf2, 0x13, 0xe6, 0xd4, 0xdb, 0x56, 0xe5, + 0xd8, 0xf6, 0x6b, 0xfd, 0x35, 0xfd, 0xc5, 0xff, 0x2e, 0x0c, 0x27, 0x11, + 0x02, 0x15, 0x32, 0x1a, 0xf5, 0x14, 0x35, 0x26, 0x9a, 0x50, 0x30, 0x56, + 0xfc, 0x32, 0x46, 0x21, 0xbb, 0x20, 0x26, 0x19, 0x77, 0x14, 0xe7, 0x0c, + 0xe4, 0x07, 0x57, 0x0a, 0x88, 0xfc, 0xda, 0xfb, 0x58, 0x12, 0x0d, 0x27, + 0x5d, 0x32, 0xe5, 0x28, 0xc3, 0x25, 0x3b, 0x32, 0xd1, 0x3f, 0xa5, 0x42, + 0xc0, 0x39, 0xe0, 0x3d, 0xa4, 0x4c, 0x2b, 0x52, 0x36, 0x53, 0x73, 0x5a, + 0xb2, 0x57, 0xf0, 0x3e, 0x5c, 0x1b, 0xf8, 0x17, 0x2e, 0x30, 0x27, 0x26, + 0xfb, 0x0e, 0xeb, 0x12, 0x02, 0x0c, 0x2c, 0xf5, 0x0e, 0xfc, 0x50, 0xfd, + 0xa8, 0xe9, 0xd4, 0xe2, 0x4c, 0xdd, 0x50, 0xd6, 0x3c, 0xc9, 0x59, 0xc1, + 0xad, 0xc9, 0x83, 0xce, 0x9a, 0xc5, 0x85, 0xc5, 0xc8, 0xe0, 0xc7, 0xe8, + 0x32, 0xd2, 0xdb, 0xc1, 0x42, 0xc8, 0x22, 0xe6, 0x68, 0xf6, 0x8c, 0xf0, + 0x54, 0xfb, 0x4b, 0x14, 0xc3, 0x1c, 0xfd, 0x12, 0x63, 0x08, 0xb5, 0x0f, + 0xd0, 0x1d, 0x5c, 0x11, 0xe2, 0x04, 0xf7, 0x0f, 0x5d, 0x21, 0x59, 0x30, + 0x12, 0x2b, 0x31, 0x29, 0x33, 0x32, 0xea, 0x2c, 0x0d, 0x35, 0xc9, 0x4c, + 0xd9, 0x59, 0x6b, 0x5b, 0x5e, 0x4b, 0x33, 0x30, 0x53, 0x1f, 0x47, 0x19, + 0xfe, 0x18, 0x3f, 0x10, 0x75, 0xfd, 0x3e, 0xfe, 0xd2, 0x1d, 0x9b, 0x3d, + 0x32, 0x34, 0xd1, 0x15, 0x12, 0x0b, 0x29, 0x15, 0xa8, 0x1a, 0x2b, 0x09, + 0x22, 0x00, 0x3f, 0x08, 0x32, 0x05, 0xc5, 0x03, 0x80, 0x0d, 0x07, 0x0c, + 0xe7, 0x06, 0x5c, 0x04, 0x79, 0xff, 0xbd, 0x00, 0x9e, 0xf5, 0x19, 0xe2, + 0x8c, 0xdb, 0x72, 0xe3, 0xc3, 0xf4, 0x58, 0xf4, 0x29, 0xec, 0x0a, 0xf4, + 0xdb, 0xfc, 0xb8, 0x01, 0x8e, 0x04, 0x88, 0x08, 0xf8, 0x16, 0x66, 0x26, + 0xd2, 0x2e, 0xb3, 0x31, 0x74, 0x24, 0x2b, 0x13, 0x74, 0x19, 0x78, 0x2d, + 0xf8, 0x32, 0xe4, 0x2d, 0x9a, 0x2b, 0x45, 0x26, 0x97, 0x27, 0x39, 0x33, + 0xba, 0x3d, 0xbd, 0x3f, 0x93, 0x33, 0x19, 0x20, 0x1c, 0x0e, 0x50, 0x0d, + 0x79, 0x21, 0x5c, 0x3b, 0xf8, 0x3f, 0x89, 0x23, 0x4f, 0x01, 0xbb, 0xe2, + 0x19, 0xc1, 0xff, 0xa3, 0xc6, 0x95, 0x21, 0x94, 0xdf, 0xa7, 0xb0, 0xc9, + 0x62, 0xd6, 0x38, 0xd0, 0x3e, 0xc1, 0xeb, 0xbf, 0xdb, 0xd3, 0x15, 0xe1, + 0x0b, 0xd5, 0x31, 0xb4, 0x93, 0xa9, 0x2c, 0xba, 0xa2, 0xd1, 0x89, 0xe9, + 0x3a, 0x07, 0xc2, 0x28, 0x98, 0x28, 0x9a, 0x10, 0x5a, 0xf8, 0xc9, 0xe6, + 0xcf, 0xe1, 0x47, 0xeb, 0x06, 0x13, 0x17, 0x3b, 0x91, 0x3c, 0x01, 0x35, + 0x0f, 0x3f, 0x2c, 0x3e, 0xfc, 0x2e, 0x4a, 0x1c, 0xa1, 0x03, 0x42, 0x02, + 0xbc, 0x0b, 0x54, 0x0c, 0x44, 0x21, 0x21, 0x2e, 0x7c, 0x22, 0x6d, 0x24, + 0xcb, 0x27, 0x70, 0x1e, 0x4b, 0x1a, 0x3a, 0x16, 0x89, 0xff, 0x37, 0xec, + 0x40, 0xe6, 0xaa, 0xe1, 0x92, 0xea, 0x9b, 0xef, 0xc4, 0xe9, 0x46, 0xf8, + 0x7a, 0x20, 0xca, 0x44, 0x38, 0x57, 0xb3, 0x51, 0x15, 0x35, 0x5d, 0x12, + 0xb6, 0xe9, 0x19, 0xd9, 0x1d, 0xd9, 0x32, 0xb8, 0x94, 0x95, 0xe1, 0x92, + 0xe2, 0x99, 0xcf, 0xa9, 0x04, 0xc4, 0x16, 0xd3, 0x25, 0xd9, 0x98, 0xdd, + 0x75, 0xf1, 0x9a, 0x11, 0x45, 0x13, 0x61, 0xf9, 0x92, 0xe9, 0xbe, 0xe7, + 0xd6, 0xe1, 0xf9, 0xd7, 0xb5, 0xde, 0xbc, 0x03, 0xf1, 0x2c, 0xb1, 0x4b, + 0x08, 0x64, 0xff, 0x64, 0xe9, 0x45, 0x7c, 0x17, 0x42, 0xfe, 0xd7, 0x0f, + 0xc6, 0x3f, 0xd0, 0x4c, 0x05, 0x30, 0x76, 0x26, 0x60, 0x22, 0x17, 0x12, + 0xb1, 0xf9, 0x97, 0xf7, 0x29, 0x19, 0x8d, 0x2a, 0x39, 0x2c, 0x08, 0x32, + 0xdb, 0x3f, 0x1e, 0x50, 0xc6, 0x4e, 0x94, 0x48, 0x36, 0x49, 0x69, 0x3d, + 0x5f, 0x2f, 0x42, 0x35, 0x24, 0x3a, 0xf5, 0x39, 0x4f, 0x3b, 0x3f, 0x31, + 0xc2, 0x20, 0x64, 0x16, 0xea, 0x08, 0x76, 0xf8, 0xa7, 0xf1, 0x50, 0xf0, + 0x2a, 0xe7, 0x19, 0xd9, 0x9c, 0xe4, 0x4a, 0xe8, 0xd5, 0xc5, 0x0b, 0xb5, + 0xc1, 0xc4, 0x25, 0xda, 0x23, 0xe7, 0x5a, 0xe9, 0x97, 0xe6, 0x42, 0xe3, + 0x46, 0xd5, 0x46, 0xc8, 0x3d, 0xd7, 0x20, 0xf5, 0xa7, 0x06, 0xf4, 0x09, + 0x78, 0x13, 0x35, 0x22, 0xef, 0x1a, 0x38, 0xf6, 0xa0, 0xe2, 0x9c, 0xea, + 0x91, 0xde, 0xa8, 0xd1, 0xc5, 0xe2, 0x5e, 0xf3, 0xf5, 0xf2, 0x8b, 0xf0, + 0xb5, 0xdf, 0x8c, 0xc4, 0x7d, 0xc3, 0xe5, 0xd3, 0xd0, 0xdb, 0x19, 0xce, + 0xb4, 0xb8, 0x0e, 0xc6, 0x3b, 0xd9, 0xfb, 0xc7, 0x2e, 0xb7, 0x89, 0xbf, + 0x3e, 0xd6, 0x8c, 0xf0, 0xf0, 0x06, 0xc3, 0x08, 0x48, 0xfd, 0xbe, 0xf3, + 0x27, 0xf4, 0x3a, 0x02, 0x26, 0xfc, 0x9b, 0xf7, 0x02, 0xff, 0x7f, 0xff, + 0x72, 0x08, 0xd3, 0x0a, 0xda, 0xfc, 0xee, 0xec, 0x97, 0xf5, 0x38, 0x08, + 0xf4, 0xfc, 0x6f, 0xd8, 0x3f, 0xc9, 0xe3, 0xe3, 0x55, 0x0b, 0x72, 0x21, + 0x63, 0x1f, 0xa3, 0x19, 0xa6, 0x00, 0x3d, 0xf1, 0x8d, 0x04, 0xf7, 0x04, + 0x19, 0xf2, 0x66, 0xed, 0xaa, 0xf6, 0xfc, 0xf5, 0x10, 0xfb, 0xc9, 0x05, + 0x8e, 0xfd, 0x50, 0xdc, 0xe9, 0xb6, 0xfd, 0xba, 0x99, 0xd9, 0xdb, 0xe2, + 0x73, 0xe0, 0x3d, 0x0a, 0xff, 0x2b, 0x05, 0x1b, 0x8e, 0x02, 0xe7, 0xeb, + 0xe1, 0xef, 0x71, 0x0a, 0x2f, 0x29, 0xb7, 0x31, 0xa6, 0x1f, 0x37, 0x1a, + 0x7f, 0x30, 0xf3, 0x53, 0xfd, 0x56, 0x3a, 0x41, 0xf3, 0x39, 0xff, 0x3e, + 0xec, 0x36, 0x69, 0x13, 0x7a, 0xf8, 0x94, 0x07, 0x75, 0x1b, 0x67, 0x1d, + 0x40, 0x20, 0x2e, 0x1f, 0xf1, 0x11, 0xdb, 0xf7, 0x93, 0xd0, 0x02, 0xaf, + 0xa7, 0xad, 0xbb, 0xc1, 0xf0, 0xde, 0x04, 0xf1, 0xef, 0xee, 0xee, 0xde, + 0x91, 0xc2, 0x6f, 0xb8, 0xb4, 0xb7, 0x0f, 0xba, 0xa8, 0xb9, 0x13, 0xbb, + 0x68, 0xda, 0x50, 0xf0, 0x2f, 0xe6, 0xc8, 0xec, 0x80, 0x0e, 0xb7, 0x10, + 0x86, 0xfd, 0x97, 0xfc, 0x04, 0x07, 0x30, 0x18, 0xc5, 0x20, 0x46, 0x21, + 0x0e, 0x35, 0x3f, 0x46, 0x48, 0x44, 0x03, 0x5a, 0x1f, 0x61, 0x88, 0x47, + 0x2b, 0x44, 0x0e, 0x4b, 0xd2, 0x4a, 0xe2, 0x43, 0xba, 0x30, 0x77, 0x13, + 0xb6, 0x0c, 0x20, 0x27, 0xab, 0x2c, 0x63, 0x04, 0xa3, 0xd6, 0x26, 0xd3, + 0x68, 0xf0, 0xa9, 0x08, 0x59, 0x04, 0x8b, 0xfa, 0x83, 0x0e, 0xcb, 0x23, + 0x76, 0x29, 0x31, 0x14, 0x40, 0xfe, 0x21, 0x05, 0xd0, 0x0b, 0xde, 0x22, + 0x6d, 0x37, 0x19, 0x41, 0xf8, 0x53, 0x8c, 0x5b, 0x67, 0x56, 0x17, 0x52, + 0xac, 0x5d, 0xc7, 0x5a, 0xe4, 0x33, 0xc8, 0x15, 0x29, 0x1a, 0x1d, 0x14, + 0x12, 0xfe, 0x0d, 0xdd, 0x01, 0xb3, 0xee, 0xae, 0xf0, 0xbe, 0x3b, 0xc8, + 0xcd, 0xbf, 0x3b, 0xc3, 0x83, 0xe1, 0x7f, 0xf1, 0xa8, 0xf2, 0xe4, 0xe3, + 0x06, 0xd6, 0x9c, 0xe4, 0x6b, 0x0e, 0x2b, 0x27, 0x1b, 0x17, 0x3e, 0xf6, + 0xb1, 0xe2, 0x4b, 0xec, 0xcd, 0x06, 0x47, 0x1f, 0xa5, 0x1f, 0x60, 0x13, + 0x8b, 0x08, 0x63, 0x13, 0x09, 0x31, 0xce, 0x38, 0xa8, 0x26, 0xb8, 0x11, + 0x72, 0x13, 0xda, 0x1c, 0xe9, 0x14, 0xa9, 0xf8, 0x0d, 0xea, 0xd7, 0xfb, + 0x85, 0x06, 0x37, 0xed, 0x09, 0xc8, 0x3f, 0xcb, 0x2f, 0xe3, 0xa8, 0xf7, + 0xf8, 0x0b, 0x77, 0x16, 0x35, 0x2b, 0xa1, 0x33, 0x62, 0x26, 0x44, 0x2b, + 0x38, 0x23, 0x1c, 0x07, 0xef, 0x04, 0xcd, 0x0f, 0x82, 0x1b, 0x52, 0x37, + 0xb3, 0x56, 0x06, 0x54, 0xa8, 0x46, 0x5b, 0x5e, 0x71, 0x73, 0xa7, 0x74, + 0x3f, 0x70, 0xa0, 0x64, 0x0f, 0x57, 0x83, 0x2b, 0x63, 0xe5, 0x9d, 0xc6, + 0xcf, 0xdd, 0x87, 0xea, 0x8d, 0xd7, 0x03, 0xbd, 0xe7, 0xb9, 0xa8, 0xd9, + 0x79, 0xef, 0x47, 0xf0, 0x09, 0xeb, 0xd5, 0xef, 0xeb, 0xfd, 0xd3, 0xf3, + 0x63, 0xd3, 0x2a, 0xb5, 0x8a, 0xae, 0xe5, 0xc0, 0x15, 0xdd, 0xf7, 0xf0, + 0x9e, 0xe7, 0xba, 0xcb, 0x56, 0xc9, 0xdb, 0xe6, 0x1d, 0xfd, 0x39, 0xf8, + 0xcd, 0xea, 0x20, 0xf6, 0xb8, 0x0c, 0x77, 0x0b, 0xbb, 0x06, 0xa4, 0x15, + 0xd4, 0x1a, 0xa3, 0x0a, 0xf3, 0x02, 0x1b, 0x09, 0x28, 0x1c, 0xff, 0x2a, + 0x44, 0x1c, 0xa8, 0x11, 0x09, 0x22, 0x56, 0x3a, 0x41, 0x33, 0x55, 0x08, + 0xa5, 0xf5, 0xe4, 0xff, 0xe6, 0x0b, 0x27, 0x09, 0xbc, 0x03, 0x90, 0x27, + 0x8f, 0x3c, 0xa6, 0x23, 0x6c, 0x1d, 0x5b, 0x0b, 0xfd, 0xd9, 0xdb, 0xcc, + 0x06, 0xdf, 0x6d, 0xf0, 0x33, 0xf3, 0xa3, 0xec, 0xfd, 0x04, 0xdf, 0x2f, + 0x31, 0x43, 0x41, 0x35, 0x9e, 0x17, 0x04, 0xf9, 0xee, 0xe9, 0x22, 0xf1, + 0x02, 0xfe, 0xad, 0x08, 0x46, 0xf1, 0x19, 0xcd, 0xe2, 0xd2, 0x56, 0xe7, + 0x32, 0xf9, 0xd1, 0x03, 0x46, 0xfc, 0xba, 0xe8, 0xac, 0xd6, 0x96, 0xd8, + 0xd4, 0xe3, 0xf0, 0xf2, 0x19, 0xff, 0x95, 0xff, 0x64, 0xfc, 0xac, 0xf7, + 0xd5, 0xf4, 0xb7, 0x09, 0x60, 0x3c, 0x13, 0x5c, 0x54, 0x5c, 0xa1, 0x4f, + 0xac, 0x46, 0x5b, 0x3f, 0x73, 0x1c, 0xec, 0xf3, 0xba, 0xe5, 0x53, 0xf6, + 0x8b, 0x07, 0x4d, 0x03, 0xdb, 0xfd, 0x24, 0x05, 0x03, 0x1a, 0x0a, 0x2e, + 0x23, 0x2d, 0x32, 0x1a, 0xa8, 0x02, 0xe4, 0xe7, 0x0b, 0xd5, 0x19, 0xcc, + 0x8c, 0xd5, 0x7c, 0xe0, 0x0f, 0xdc, 0xcb, 0xe4, 0xa7, 0xe9, 0xc1, 0xe9, + 0x61, 0xe9, 0x1b, 0xde, 0x00, 0xe7, 0x30, 0xff, 0x33, 0xfe, 0x0d, 0xe2, + 0x04, 0xbe, 0xdb, 0xa6, 0xbd, 0xaa, 0x06, 0xb7, 0x2c, 0xc6, 0xea, 0xc8, + 0x45, 0xba, 0x55, 0xb1, 0x81, 0xb5, 0xc9, 0xcc, 0x82, 0xe5, 0x52, 0xf3, + 0x20, 0xf6, 0xf3, 0xfa, 0xb6, 0x06, 0x0b, 0x11, 0xf4, 0x21, 0xd3, 0x29, + 0xd2, 0x25, 0xb1, 0x22, 0xdd, 0x21, 0xee, 0x27, 0xb5, 0x2f, 0x00, 0x27, + 0x8a, 0x14, 0x4c, 0x0c, 0x20, 0x0c, 0xfd, 0x0e, 0xa2, 0x08, 0x0a, 0xf6, + 0xb7, 0xee, 0xa0, 0x0a, 0xca, 0x31, 0x10, 0x41, 0xe4, 0x41, 0x63, 0x38, + 0x6e, 0x26, 0x02, 0x20, 0x40, 0x1f, 0xec, 0x0e, 0x40, 0xfb, 0x59, 0xf0, + 0x48, 0xf2, 0x99, 0x0c, 0x70, 0x39, 0xbe, 0x5d, 0xab, 0x65, 0x6e, 0x5b, + 0x39, 0x4f, 0xea, 0x4c, 0x4e, 0x38, 0xec, 0x05, 0xfd, 0xe2, 0x00, 0xdc, + 0x59, 0xdf, 0x9c, 0xdc, 0x60, 0xd4, 0x29, 0xc2, 0xdf, 0xaa, 0xe0, 0x9e, + 0xa3, 0xa9, 0xf6, 0xc4, 0xc6, 0xc9, 0x62, 0xc4, 0x86, 0xc5, 0x1d, 0xc2, + 0xbf, 0xb6, 0x5e, 0xb7, 0x51, 0xda, 0x3c, 0xf5, 0xbf, 0xf5, 0xc7, 0xdc, + 0xaa, 0xcb, 0x33, 0xeb, 0x12, 0x0d, 0xbf, 0x1a, 0xe9, 0x1c, 0xdd, 0x25, + 0x4d, 0x38, 0x40, 0x36, 0xaf, 0x20, 0x98, 0x17, 0x82, 0x28, 0x55, 0x32, + 0x11, 0x23, 0x37, 0x14, 0xeb, 0x19, 0x35, 0x14, 0x81, 0x05, 0x20, 0x03, + 0xc7, 0xfd, 0x6b, 0x05, 0x1e, 0x1b, 0xa8, 0x34, 0x48, 0x36, 0x44, 0x1a, + 0xc1, 0x02, 0x4c, 0xff, 0xcb, 0x0f, 0x6f, 0x1a, 0x3b, 0x1d, 0xc4, 0x28, + 0xaa, 0x3a, 0x6b, 0x2b, 0x78, 0x02, 0x70, 0xf6, 0x75, 0x09, 0x3c, 0x1e, + 0xae, 0x16, 0x39, 0x00, 0xea, 0xed, 0x18, 0xe6, 0xe1, 0xe4, 0x98, 0xe2, + 0x60, 0xdf, 0x7c, 0xd2, 0xd1, 0xc4, 0x6b, 0xbf, 0x73, 0xbb, 0x6d, 0xb0, + 0xca, 0xb4, 0xb7, 0xbb, 0x75, 0xaf, 0xa0, 0xac, 0x5f, 0xb3, 0x30, 0xb7, + 0x9c, 0xba, 0x76, 0xbf, 0xab, 0xbb, 0x66, 0xcb, 0xba, 0xfe, 0x01, 0x20, + 0x81, 0x04, 0x76, 0xd6, 0x54, 0xdb, 0x5e, 0x05, 0x10, 0x22, 0xf8, 0x14, + 0x59, 0x0f, 0x30, 0x33, 0x46, 0x4a, 0x77, 0x4d, 0xf5, 0x4d, 0x1d, 0x41, + 0xe2, 0x34, 0xab, 0x2d, 0xca, 0x1e, 0xc8, 0x1f, 0x75, 0x22, 0x8e, 0x0c, + 0x10, 0xe4, 0x18, 0xcf, 0xa7, 0xdf, 0x6e, 0xdf, 0xed, 0xcc, 0xe3, 0xc1, + 0x0f, 0xbe, 0x80, 0xc3, 0x9e, 0xdb, 0xab, 0xfa, 0x7d, 0x04, 0xdf, 0xf0, + 0x78, 0xd4, 0xd2, 0xd1, 0xbf, 0xe8, 0xad, 0x00, 0x07, 0x06, 0x20, 0x06, + 0x47, 0xf7, 0x9b, 0xe7, 0x96, 0xed, 0x00, 0x0a, 0xaf, 0x3a, 0xa6, 0x3d, + 0x34, 0x18, 0x9f, 0xf6, 0xb5, 0xf9, 0x47, 0x17, 0x1d, 0x0f, 0xac, 0xed, + 0xb6, 0xda, 0x2d, 0xcc, 0xe4, 0xbe, 0x97, 0xc2, 0x91, 0xcb, 0x5e, 0xdc, + 0x29, 0xe0, 0x1e, 0xe6, 0xf9, 0xfd, 0x44, 0x07, 0x19, 0x0a, 0xde, 0x17, + 0x24, 0x2e, 0xdd, 0x30, 0xa1, 0x31, 0x33, 0x2d, 0x9b, 0x2a, 0xb2, 0x37, + 0x20, 0x40, 0xee, 0x48, 0xef, 0x3f, 0x97, 0x23, 0x5b, 0x07, 0xc9, 0x12, + 0x71, 0x34, 0x62, 0x48, 0x04, 0x3f, 0x37, 0x14, 0x2e, 0xfe, 0xec, 0x05, + 0xc0, 0x0a, 0xad, 0xf0, 0x0a, 0xd1, 0xfb, 0xc5, 0x21, 0xbe, 0x07, 0xc0, + 0xc3, 0xd4, 0xcb, 0xd8, 0x02, 0xc5, 0xd8, 0xbf, 0xfc, 0xc8, 0x56, 0xd3, + 0x32, 0xc8, 0x4a, 0xb3, 0xe2, 0xb8, 0x39, 0xd8, 0x1f, 0xf3, 0xa5, 0x00, + 0xcc, 0x0c, 0x94, 0x04, 0x32, 0xfc, 0x26, 0xfa, 0x47, 0xe9, 0x32, 0xdd, + 0x21, 0xd2, 0x0e, 0xc7, 0x59, 0xd6, 0xf8, 0x00, 0x71, 0x1f, 0x4d, 0x0a, + 0x2e, 0xdf, 0x24, 0xd6, 0x20, 0xef, 0xe2, 0x01, 0xfe, 0xfd, 0x93, 0xfd, + 0x73, 0x0d, 0xdf, 0x16, 0x0c, 0x0c, 0x34, 0xfd, 0x74, 0xfa, 0x2c, 0x0b, + 0x73, 0x1e, 0x24, 0x1e, 0xaa, 0x0c, 0xb1, 0xff, 0xf9, 0x09, 0xcb, 0x13, + 0x18, 0x12, 0x89, 0xfe, 0xc1, 0xd1, 0xe2, 0xb7, 0x62, 0xcc, 0x19, 0xe6, + 0x41, 0xe1, 0x29, 0xd0, 0x81, 0xc9, 0xb7, 0xd5, 0x2f, 0xe8, 0x69, 0xf5, + 0x27, 0x06, 0x11, 0x1c, 0xf4, 0x1e, 0xba, 0x18, 0x1f, 0x26, 0x61, 0x2f, + 0xff, 0x2b, 0xa6, 0x26, 0xb6, 0x28, 0x14, 0x35, 0xc4, 0x47, 0xc3, 0x50, + 0xe8, 0x44, 0x2f, 0x49, 0x3f, 0x5e, 0xf1, 0x4d, 0xe5, 0x20, 0x48, 0x12, + 0x69, 0x10, 0x29, 0x09, 0xc0, 0x0a, 0xf0, 0xf5, 0xfe, 0xd7, 0xef, 0xd0, + 0xe6, 0xcf, 0x5e, 0xc8, 0x51, 0xbb, 0xda, 0xb3, 0xe3, 0xbd, 0x75, 0xcf, + 0x8e, 0xd3, 0x87, 0xcb, 0xcc, 0xc3, 0xbd, 0xb8, 0x86, 0xb5, 0x14, 0xbd, + 0x94, 0xc6, 0x0a, 0xd0, 0xdf, 0xce, 0xd3, 0xc9, 0x58, 0xc8, 0x79, 0xc4, + 0x08, 0xc0, 0x10, 0xca, 0x39, 0xe0, 0x35, 0xed, 0x61, 0xfb, 0x79, 0x12, + 0x5d, 0x1c, 0xd4, 0x22, 0x4f, 0x2a, 0xe5, 0x26, 0xbe, 0x2b, 0xf4, 0x32, + 0x66, 0x31, 0x96, 0x2e, 0x55, 0x32, 0xed, 0x39, 0x23, 0x38, 0xd3, 0x2c, + 0x05, 0x2b, 0xe8, 0x40, 0x26, 0x52, 0xd9, 0x50, 0x18, 0x45, 0x8a, 0x45, + 0xab, 0x59, 0x0f, 0x64, 0x02, 0x54, 0x4a, 0x30, 0x20, 0x1d, 0x1c, 0x1d, + 0xe4, 0x1c, 0xfc, 0x14, 0x00, 0x0c, 0xb1, 0x0a, 0xd6, 0x0d, 0x1c, 0x19, + 0x5d, 0x1a, 0x60, 0x04, 0xb4, 0xee, 0x66, 0xf0, 0x0c, 0xf2, 0xca, 0xe2, + 0x27, 0xdb, 0xce, 0xe6, 0xb4, 0xeb, 0x5c, 0xd2, 0xbb, 0xb1, 0x0c, 0xab, + 0xf8, 0xcc, 0x40, 0xfb, 0x96, 0x06, 0x13, 0xf3, 0x95, 0xec, 0xd5, 0xfc, + 0x8b, 0x09, 0xdd, 0x0d, 0xd1, 0x20, 0xef, 0x3b, 0xe9, 0x48, 0xfa, 0x55, + 0x64, 0x52, 0x60, 0x37, 0x05, 0x1f, 0x57, 0x13, 0xd8, 0x14, 0x95, 0x0b, + 0xc0, 0xf1, 0xb5, 0xdd, 0xe5, 0xda, 0xcd, 0xda, 0x4d, 0xd2, 0xc0, 0xcb, + 0x66, 0xce, 0xb3, 0xcb, 0xe6, 0xc3, 0x1a, 0xd1, 0x72, 0xec, 0x3c, 0xf6, + 0x5e, 0xf2, 0xcd, 0x00, 0xf6, 0x16, 0xb6, 0x28, 0x81, 0x3a, 0x12, 0x3a, + 0x10, 0x26, 0x5e, 0x2b, 0x03, 0x4e, 0xd6, 0x58, 0x8b, 0x5d, 0x88, 0x6c, + 0xba, 0x73, 0xa6, 0x74, 0x6c, 0x71, 0xd7, 0x67, 0xce, 0x5e, 0x0c, 0x54, + 0xe7, 0x33, 0x37, 0x1a, 0x97, 0x0d, 0x96, 0x15, 0xc7, 0x1d, 0xf0, 0x01, + 0x5b, 0xe8, 0xe5, 0xd5, 0xf6, 0xdd, 0x8d, 0xfb, 0x7e, 0xfe, 0x0b, 0xeb, + 0x4e, 0xd9, 0x43, 0xd8, 0xf9, 0xe7, 0xaf, 0xf7, 0x21, 0xff, 0x73, 0x0d, + 0xdd, 0x16, 0xbd, 0x15, 0x5a, 0x0f, 0x27, 0x16, 0xe0, 0x21, 0xce, 0x1f, + 0x8c, 0x2f, 0xa9, 0x39, 0x2e, 0x33, 0x5a, 0x3f, 0x03, 0x58, 0x33, 0x5d, + 0x31, 0x51, 0x39, 0x42, 0xe1, 0x35, 0x01, 0x37, 0x9d, 0x33, 0x24, 0x2b, + 0x9a, 0x27, 0x5b, 0x24, 0x49, 0x1f, 0x85, 0x1f, 0x78, 0x1c, 0x25, 0x0e, + 0x9a, 0xfa, 0x97, 0xe8, 0xeb, 0xf3, 0x1c, 0x0c, 0xae, 0x18, 0xdf, 0x10, + 0x02, 0x00, 0x72, 0xfd, 0x32, 0xf5, 0xe8, 0xe8, 0xb8, 0xeb, 0xd1, 0xf8, + 0xc2, 0xf6, 0xf8, 0xe3, 0x98, 0xda, 0xe9, 0xec, 0xb0, 0x0b, 0xee, 0x0b, + 0x41, 0xf0, 0xa4, 0xe0, 0x3b, 0xe9, 0xbd, 0x03, 0xf4, 0x20, 0xc5, 0x1f, + 0x65, 0x08, 0x75, 0xf8, 0x39, 0xfa, 0x41, 0x0d, 0xeb, 0x25, 0x4c, 0x32, + 0x74, 0x20, 0xf0, 0x17, 0xab, 0x27, 0x7b, 0x1e, 0xdf, 0x0a, 0x1e, 0x15, + 0xec, 0x12, 0xc6, 0xec, 0xd1, 0xd4, 0xeb, 0xd4, 0x3c, 0xdb, 0xd0, 0xdf, + 0x58, 0xd7, 0x7d, 0xc0, 0xa2, 0xb6, 0xd3, 0xbb, 0x45, 0xc8, 0x3b, 0xdf, + 0x04, 0xde, 0xa6, 0xda, 0xc6, 0xf2, 0xb7, 0x13, 0x2b, 0x30, 0x7b, 0x31, + 0x72, 0x1d, 0x0d, 0x1d, 0xec, 0x3d, 0x47, 0x5e, 0xb8, 0x6e, 0xf1, 0x73, + 0x45, 0x76, 0xa3, 0x76, 0x51, 0x71, 0xc9, 0x6f, 0x79, 0x6b, 0xd0, 0x62, + 0x32, 0x5e, 0x14, 0x5e, 0x40, 0x55, 0x7b, 0x44, 0x7c, 0x38, 0x60, 0x39, + 0x91, 0x41, 0xc8, 0x3d, 0xc7, 0x33, 0xc6, 0x29, 0x8c, 0x12, 0xcd, 0xee, + 0xc0, 0xd9, 0x99, 0xcd, 0xcc, 0xc3, 0x22, 0xc2, 0x72, 0xbe, 0x3b, 0xc1, + 0xaf, 0xc0, 0x76, 0xbb, 0x2c, 0xbe, 0x89, 0xcc, 0x9e, 0xd9, 0xa8, 0xd9, + 0x11, 0xce, 0x5e, 0xc4, 0x37, 0xd2, 0x06, 0xe5, 0x67, 0xf2, 0x26, 0xf2, + 0x9e, 0xee, 0x27, 0xf3, 0xe0, 0xed, 0xb3, 0xf1, 0x8c, 0x04, 0xcd, 0x1b, + 0x0e, 0x35, 0x7f, 0x3e, 0xa9, 0x27, 0x5a, 0x0b, 0xcb, 0x09, 0x06, 0x23, + 0x4b, 0x3f, 0x88, 0x41, 0x11, 0x31, 0x4c, 0x2d, 0x99, 0x3d, 0x05, 0x3d, + 0x01, 0x28, 0x65, 0x1d, 0x87, 0x30, 0x9b, 0x45, 0x26, 0x3b, 0xd6, 0x34, + 0x98, 0x40, 0x40, 0x51, 0x47, 0x5a, 0xf1, 0x49, 0xe5, 0x33, 0x37, 0x26, + 0x44, 0x0c, 0x36, 0xf1, 0xf1, 0xe9, 0x9d, 0x02, 0xdb, 0x1f, 0xec, 0x0f, + 0x65, 0xf3, 0x7a, 0xe9, 0x1f, 0x04, 0xcf, 0x24, 0x74, 0x10, 0xd0, 0xf1, + 0x7e, 0xec, 0x5b, 0xf5, 0xe3, 0x01, 0x4b, 0xf9, 0x50, 0xe0, 0xdf, 0xdb, + 0x00, 0xe9, 0x8d, 0xf9, 0x14, 0xf5, 0x17, 0xdd, 0xf0, 0xcd, 0x50, 0xd1, + 0x59, 0xe3, 0x11, 0xdd, 0x74, 0xd8, 0x5f, 0xda, 0x42, 0xd1, 0xcd, 0xda, + 0x6d, 0xe4, 0x7d, 0xdf, 0x00, 0xe3, 0x1c, 0xf1, 0x05, 0xea, 0x6f, 0xdc, + 0x3d, 0xd9, 0x84, 0xde, 0x00, 0xe8, 0xc0, 0xea, 0xdd, 0xee, 0x74, 0xf3, + 0x19, 0xf3, 0x37, 0xe6, 0x2a, 0xf2, 0x13, 0x0f, 0x35, 0x10, 0x51, 0x0a, + 0xfc, 0x10, 0xa4, 0x1f, 0x24, 0x24, 0x82, 0x18, 0xab, 0x05, 0xa8, 0x0b, + 0x7a, 0x21, 0x2e, 0x21, 0xf7, 0x12, 0xfe, 0x03, 0x6c, 0x01, 0x04, 0xfc, + 0x62, 0xee, 0x49, 0xfa, 0x8d, 0x09, 0xd8, 0x03, 0xae, 0x08, 0xea, 0x03, + 0xc0, 0xe6, 0x88, 0xd2, 0x2c, 0xc9, 0x1f, 0xcb, 0xd7, 0xcd, 0x35, 0xc4, + 0x35, 0xb6, 0xa9, 0xaf, 0x85, 0xb4, 0x05, 0xb8, 0x71, 0xbd, 0xf5, 0xce, + 0x98, 0xdb, 0x4f, 0xcf, 0x22, 0xbf, 0xbc, 0xb9, 0xe7, 0xc2, 0xfa, 0xe0, + 0x8a, 0xf8, 0xf7, 0xff, 0x81, 0x06, 0x82, 0x1c, 0xad, 0x32, 0x04, 0x2a, + 0xf7, 0x1e, 0xee, 0x2c, 0x09, 0x38, 0x5c, 0x34, 0x6e, 0x31, 0x3f, 0x26, + 0x9f, 0x27, 0x65, 0x3c, 0x6f, 0x46, 0x2d, 0x3a, 0xf7, 0x1b, 0x8b, 0x0b, + 0xf7, 0xf7, 0xda, 0xe0, 0xf8, 0xe0, 0x5d, 0xe2, 0x15, 0xdf, 0x8b, 0xdd, + 0x0f, 0xe1, 0xf0, 0xe7, 0xdf, 0xe3, 0x8c, 0xd0, 0x80, 0xd2, 0xff, 0xe1, + 0xd9, 0xe8, 0x77, 0xef, 0xdf, 0xe3, 0xf0, 0xd4, 0x7a, 0xce, 0x4e, 0xd4, + 0xdc, 0xdf, 0x77, 0xe8, 0x3a, 0xf8, 0xa8, 0xfb, 0x38, 0xf2, 0x85, 0xf3, + 0x20, 0x14, 0x6e, 0x45, 0x72, 0x5c, 0x59, 0x48, 0x67, 0x31, 0x72, 0x34, + 0x9b, 0x32, 0x4b, 0x26, 0xbc, 0x18, 0xb2, 0x0f, 0x1e, 0x02, 0x28, 0xe9, + 0xf1, 0xee, 0x0f, 0x12, 0x3c, 0x19, 0x0d, 0xff, 0xb8, 0xe7, 0x38, 0xdb, + 0x43, 0xe7, 0x1d, 0x03, 0x92, 0x01, 0x0e, 0xeb, 0x18, 0xdd, 0x5f, 0xee, + 0xfb, 0x0b, 0x7b, 0x05, 0xc0, 0xef, 0x81, 0xf3, 0x55, 0x06, 0x52, 0x02, + 0xff, 0xf2, 0x44, 0xf1, 0x4e, 0xee, 0x89, 0xf4, 0x04, 0x0e, 0x66, 0x24, + 0xd2, 0x23, 0x71, 0x10, 0xb8, 0x0b, 0x99, 0x2b, 0x2e, 0x47, 0xab, 0x38, + 0x7f, 0x30, 0xac, 0x42, 0x04, 0x43, 0xdc, 0x39, 0x7f, 0x3a, 0x24, 0x44, + 0x2f, 0x50, 0x50, 0x4b, 0xc4, 0x44, 0x7b, 0x47, 0x0e, 0x43, 0x1a, 0x3a, + 0x88, 0x3c, 0x2e, 0x3c, 0x94, 0x37, 0x16, 0x36, 0x33, 0x1f, 0xea, 0xfd, + 0xe9, 0xe3, 0x4a, 0xdd, 0x54, 0xeb, 0xe9, 0xf3, 0x68, 0xe4, 0x3a, 0xcc, + 0x6a, 0xcc, 0xc7, 0xda, 0xc8, 0xef, 0xd6, 0xef, 0xdb, 0xd1, 0xc7, 0xc3, + 0xae, 0xcf, 0xd8, 0xe8, 0x1c, 0xf5, 0x71, 0xf7, 0x27, 0xfd, 0x7b, 0xf8, + 0x93, 0xf2, 0x8f, 0xf7, 0xa8, 0x00, 0x63, 0x01, 0x40, 0xf0, 0x8f, 0xe2, + 0x11, 0xf0, 0xf8, 0xfa, 0xb4, 0xf9, 0xbf, 0xfa, 0x86, 0xf5, 0xaa, 0xef, + 0x03, 0xea, 0x2d, 0xe9, 0x4a, 0xf3, 0xfe, 0xfe, 0x50, 0x06, 0x2d, 0x00, + 0x60, 0xf5, 0x70, 0xf4, 0x94, 0x05, 0xa4, 0x15, 0xab, 0x08, 0x4d, 0xf5, + 0xea, 0xf0, 0x76, 0xf8, 0x30, 0x09, 0xa7, 0x19, 0xdc, 0x0b, 0x66, 0xe6, + 0x82, 0xd2, 0x37, 0xda, 0x64, 0xee, 0xee, 0xf0, 0x72, 0xec, 0x65, 0xf5, + 0x7d, 0x0b, 0x93, 0x27, 0x03, 0x40, 0x55, 0x4b, 0x49, 0x35, 0x92, 0x23, + 0xfb, 0x2f, 0xbc, 0x3b, 0x06, 0x38, 0x67, 0x2d, 0x9b, 0x27, 0xda, 0x27, + 0x02, 0x1f, 0xb2, 0x03, 0x6a, 0xfa, 0x65, 0x06, 0xa2, 0x08, 0x9b, 0xf4, + 0xbe, 0xd4, 0x86, 0xc8, 0x73, 0xc5, 0xae, 0xbd, 0x04, 0xb8, 0x6b, 0xb5, + 0xa7, 0xb5, 0x47, 0xbc, 0x11, 0xcb, 0x25, 0xcb, 0x56, 0xc1, 0xdc, 0xc2, + 0xf4, 0xc5, 0x1d, 0xcd, 0x9a, 0xcf, 0xec, 0xc0, 0x4a, 0xb7, 0x12, 0xc0, + 0x8c, 0xd6, 0x96, 0xe7, 0x9b, 0xe4, 0x24, 0xda, 0xf8, 0xd9, 0x09, 0xed, + 0xbb, 0x11, 0x90, 0x29, 0xd0, 0x20, 0x55, 0x0f, 0xc0, 0x00, 0x6c, 0xf7, + 0xf7, 0xfa, 0x6c, 0x0c, 0x70, 0x14, 0xf8, 0x10, 0xa7, 0x19, 0xd4, 0x19, + 0xa0, 0x0e, 0x93, 0x04, 0xc6, 0xfb, 0x8d, 0xf4, 0xe5, 0xea, 0x36, 0xe3, + 0xe9, 0xd6, 0x88, 0xcf, 0x9a, 0xd8, 0xcb, 0xdd, 0x4e, 0xd9, 0x55, 0xdf, + 0x6e, 0xf1, 0xa1, 0xfd, 0x63, 0x05, 0xcc, 0x10, 0x38, 0x18, 0x0e, 0x21, + 0x90, 0x29, 0x7c, 0x2a, 0x1c, 0x2d, 0x26, 0x2c, 0xdf, 0x31, 0x48, 0x45, + 0x1e, 0x4c, 0xd1, 0x3f, 0x0c, 0x33, 0xc1, 0x30, 0xb6, 0x37, 0x62, 0x42, + 0x19, 0x47, 0x87, 0x42, 0x91, 0x2e, 0x47, 0x0d, 0xc2, 0xf8, 0x95, 0xff, + 0x54, 0x09, 0xa0, 0x02, 0x9a, 0xf9, 0x55, 0x07, 0x95, 0x16, 0x37, 0xff, + 0xb4, 0xf0, 0x9c, 0x02, 0x7d, 0x16, 0xf4, 0x29, 0x65, 0x32, 0x59, 0x2e, + 0xa9, 0x2d, 0xf0, 0x3b, 0x8a, 0x41, 0x91, 0x2c, 0x8f, 0x1c, 0xbe, 0x27, + 0x8e, 0x34, 0x81, 0x26, 0x70, 0x04, 0x5e, 0xe7, 0x77, 0xe3, 0xda, 0xeb, + 0x82, 0xeb, 0x37, 0xe7, 0xe7, 0xee, 0x60, 0xfe, 0xeb, 0xfc, 0x14, 0xef, + 0x5f, 0xea, 0xae, 0xea, 0x0a, 0xf8, 0xb2, 0x15, 0x36, 0x24, 0xc1, 0x1b, + 0x39, 0x10, 0x17, 0x14, 0xcf, 0x1e, 0x30, 0x25, 0xa2, 0x23, 0x32, 0x15, + 0x3e, 0x0c, 0x36, 0x0f, 0xa0, 0x0e, 0x17, 0x04, 0x22, 0x05, 0x54, 0x13, + 0x30, 0x14, 0x74, 0x01, 0xe1, 0xed, 0xd8, 0xf2, 0x11, 0x00, 0x53, 0xf7, + 0xe4, 0xd8, 0x27, 0xba, 0x5b, 0xad, 0x32, 0xb2, 0xd7, 0xc0, 0xf2, 0xcf, + 0xee, 0xd6, 0x6b, 0xd6, 0x42, 0xda, 0x98, 0xe0, 0x20, 0xe2, 0x06, 0xe8, + 0xbb, 0xf2, 0xe2, 0xf3, 0x06, 0xee, 0xd1, 0xe8, 0x97, 0xe8, 0xca, 0xec, + 0xd9, 0xf2, 0x13, 0x07, 0x43, 0x26, 0x9d, 0x48, 0xe5, 0x60, 0x5a, 0x66, + 0x32, 0x67, 0x86, 0x67, 0xc3, 0x69, 0x06, 0x6a, 0xe1, 0x65, 0x8b, 0x69, + 0x57, 0x69, 0x2a, 0x5d, 0xe9, 0x58, 0xbb, 0x55, 0x76, 0x52, 0x31, 0x5a, + 0x6e, 0x57, 0x8c, 0x45, 0xce, 0x2b, 0xa4, 0x15, 0xa7, 0x15, 0x53, 0x18, + 0x80, 0x0b, 0x89, 0xff, 0x6d, 0xf6, 0xd6, 0xe3, 0x50, 0xd3, 0xab, 0xce, + 0x90, 0xd5, 0x04, 0xdf, 0xad, 0xda, 0x96, 0xd0, 0xfc, 0xc3, 0x22, 0xbb, + 0x5d, 0xc4, 0x86, 0xd4, 0x28, 0xe2, 0x32, 0xe6, 0xd2, 0xe6, 0xbf, 0xf1, + 0xf2, 0x05, 0x47, 0x14, 0x89, 0x11, 0x22, 0x09, 0x03, 0x0a, 0xf6, 0x1b, + 0xbc, 0x31, 0x30, 0x3b, 0xae, 0x29, 0x1f, 0x12, 0x9b, 0x1c, 0x79, 0x32, + 0xd0, 0x40, 0xd8, 0x4c, 0x4e, 0x4a, 0x20, 0x3f, 0x95, 0x45, 0xc1, 0x51, + 0x32, 0x4f, 0x05, 0x4a, 0x0a, 0x47, 0x65, 0x49, 0x53, 0x52, 0xb6, 0x5c, + 0xf2, 0x5e, 0xf6, 0x52, 0x87, 0x3d, 0x59, 0x27, 0xc4, 0x1e, 0x45, 0x1d, + 0x63, 0x19, 0x4c, 0x16, 0x95, 0x16, 0x44, 0x15, 0x11, 0x15, 0x1f, 0x26, + 0x48, 0x31, 0x96, 0x29, 0xd3, 0x1d, 0x38, 0x14, 0xb9, 0x1a, 0x94, 0x26, + 0xca, 0x24, 0xdc, 0x0d, 0xc0, 0xf6, 0x4c, 0xf8, 0xb3, 0x0d, 0x96, 0x21, + 0x00, 0x14, 0xa0, 0xf6, 0x4b, 0xf6, 0xf1, 0x0f, 0xc8, 0x11, 0x67, 0xef, + 0x38, 0xdb, 0xb0, 0xef, 0xb6, 0x03, 0xad, 0xfc, 0xe9, 0xf3, 0xea, 0xf3, + 0x31, 0x03, 0x52, 0x08, 0x3e, 0xfc, 0x06, 0xf4, 0x3d, 0xdd, 0xa8, 0xca, + 0x33, 0xd1, 0x1a, 0xdf, 0xb2, 0xdd, 0x28, 0xc8, 0x92, 0xbd, 0x9b, 0xda, + 0xda, 0xfd, 0x60, 0xfb, 0x8c, 0xe5, 0x38, 0xe8, 0xa8, 0x0e, 0x5a, 0x30, + 0x9d, 0x2e, 0xb8, 0x16, 0xcb, 0x0b, 0xd1, 0x10, 0xb1, 0x0f, 0x45, 0x07, + 0x4f, 0xfc, 0xc4, 0x02, 0xd0, 0x18, 0x47, 0x1b, 0xe8, 0x05, 0x54, 0xf5, + 0xe9, 0xf5, 0x34, 0xff, 0x87, 0xf9, 0xfb, 0xd5, 0x38, 0xb5, 0x49, 0xb3, + 0x01, 0xc5, 0x4e, 0xdb, 0xc5, 0xdb, 0xdf, 0xbd, 0xa0, 0xad, 0x04, 0xc3, + 0xe6, 0xe4, 0xa7, 0xf0, 0x32, 0xe8, 0x04, 0xeb, 0x66, 0x0a, 0xf0, 0x30, + 0x42, 0x45, 0x25, 0x4c, 0xa2, 0x48, 0xc3, 0x4c, 0x1a, 0x53, 0x9c, 0x51, + 0x07, 0x59, 0x5e, 0x52, 0x1c, 0x39, 0xa8, 0x2a, 0xa2, 0x1d, 0xd5, 0x06, + 0xae, 0xfd, 0xf1, 0xfe, 0x0f, 0xfc, 0x00, 0xf9, 0x5f, 0xfb, 0x0c, 0xff, + 0x59, 0xfe, 0x47, 0x00, 0xbc, 0xff, 0xe5, 0xfb, 0xa6, 0xfe, 0x49, 0x0c, + 0x54, 0x12, 0x73, 0x06, 0xa0, 0xf7, 0xb5, 0xef, 0x48, 0xf5, 0xec, 0xf7, + 0x88, 0xf4, 0x1b, 0xf7, 0xc6, 0xf5, 0xe3, 0xf4, 0xae, 0xfd, 0xdc, 0x06, + 0xbc, 0x0a, 0x98, 0x02, 0xdb, 0xf9, 0xdb, 0x02, 0xfa, 0x12, 0x6d, 0x1b, + 0xad, 0x12, 0x9f, 0x06, 0x05, 0x00, 0x7a, 0xf5, 0x48, 0xe8, 0xaa, 0xdc, + 0x4e, 0xd2, 0xd0, 0xc5, 0x4d, 0xc0, 0x72, 0xc3, 0x39, 0xcb, 0x56, 0xcb, + 0x5c, 0xb9, 0x17, 0xb8, 0x97, 0xd0, 0xc5, 0xdf, 0x6b, 0xe1, 0x3f, 0xde, + 0x78, 0xde, 0xd1, 0xec, 0x78, 0xfc, 0x18, 0x08, 0x7c, 0x16, 0x4d, 0x18, + 0x62, 0x0f, 0x57, 0x12, 0xca, 0x20, 0x4c, 0x30, 0xb9, 0x2b, 0x77, 0x21, + 0x2d, 0x31, 0x28, 0x38, 0xc7, 0x23, 0x9a, 0x12, 0x9a, 0x18, 0xc7, 0x33, + 0xc9, 0x47, 0x04, 0x39, 0xcb, 0x23, 0x50, 0x26, 0x1c, 0x33, 0x6b, 0x38, + 0xe5, 0x25, 0x70, 0x10, 0x23, 0x10, 0xf9, 0x1c, 0xd9, 0x1f, 0x9a, 0x0d, + 0x44, 0x00, 0xc5, 0x00, 0x1e, 0x07, 0xe3, 0x09, 0xed, 0x0c, 0xb7, 0x18, + 0x1c, 0x13, 0x80, 0xfd, 0x00, 0xfd, 0xd2, 0xfe, 0x8a, 0xe8, 0x7a, 0xda, + 0xc8, 0xd5, 0xcb, 0xca, 0x17, 0xc3, 0x1a, 0xc5, 0xce, 0xd3, 0xec, 0xe0, + 0xe7, 0xe4, 0x62, 0xe8, 0xe0, 0xf0, 0x4c, 0xe9, 0x46, 0xdc, 0x24, 0xec, + 0xfc, 0xf5, 0x8f, 0xe7, 0x46, 0xce, 0x5d, 0xb5, 0xc9, 0xad, 0x03, 0xb9, + 0x05, 0xcb, 0xec, 0xca, 0xcd, 0xc5, 0x8f, 0xcc, 0x91, 0xd6, 0xed, 0xd8, + 0x19, 0xc9, 0x0c, 0xba, 0x52, 0xc3, 0xdd, 0xe2, 0xa1, 0xfc, 0x81, 0xf8, + 0x59, 0xdb, 0x85, 0xca, 0x2d, 0xd0, 0x79, 0xd5, 0x70, 0xd2, 0x86, 0xb9, + 0xe8, 0x9f, 0x92, 0xa0, 0x89, 0xb0, 0x68, 0xc2, 0x6f, 0xd1, 0x85, 0xd8, + 0x36, 0xd7, 0x36, 0xe6, 0xae, 0xff, 0x21, 0x09, 0x4f, 0x03, 0x50, 0xf5, + 0x5f, 0xee, 0x01, 0xfe, 0xc8, 0x18, 0x86, 0x2a, 0x1d, 0x38, 0x55, 0x44, + 0xf7, 0x49, 0x41, 0x55, 0xf5, 0x67, 0xc9, 0x72, 0xd3, 0x74, 0xa8, 0x71, + 0xf9, 0x67, 0x69, 0x5f, 0xd7, 0x58, 0x5c, 0x50, 0xfb, 0x3f, 0x7b, 0x1e, + 0x09, 0xf7, 0x6e, 0xdd, 0x82, 0xda, 0xfe, 0xde, 0x19, 0xd4, 0xda, 0xc3, + 0xc3, 0xc1, 0xa4, 0xcb, 0x63, 0xd5, 0x6b, 0xd4, 0x8f, 0xcb, 0x20, 0xce, + 0xde, 0xd1, 0xa7, 0xc9, 0xd2, 0xc5, 0x41, 0xca, 0x72, 0xd8, 0xb7, 0xd5, + 0x60, 0xc0, 0x4b, 0xc4, 0xc1, 0xcf, 0x95, 0xd4, 0xe0, 0xe2, 0x5a, 0xf1, + 0x74, 0xee, 0x36, 0xe5, 0x5d, 0xf2, 0xa6, 0xfd, 0x12, 0xf0, 0x6c, 0xe3, + 0x45, 0xdf, 0x3c, 0xe1, 0x71, 0xed, 0xa6, 0xef, 0x3e, 0xea, 0x22, 0xfc, + 0x51, 0x1b, 0x75, 0x38, 0xe7, 0x3d, 0x32, 0x24, 0xcf, 0x20, 0x6a, 0x32, + 0x06, 0x36, 0x07, 0x33, 0x0f, 0x30, 0xf8, 0x34, 0x42, 0x46, 0x79, 0x50, + 0xdc, 0x4d, 0x3a, 0x4f, 0x4e, 0x4f, 0x44, 0x4d, 0x19, 0x45, 0x7e, 0x32, + 0x1f, 0x28, 0x7e, 0x21, 0x59, 0x13, 0x5c, 0x06, 0x63, 0x03, 0x4b, 0x04, + 0x02, 0x07, 0x58, 0x08, 0x9c, 0x05, 0x92, 0x06, 0xe5, 0x10, 0x84, 0x13, + 0x34, 0xff, 0x1a, 0xfb, 0x97, 0x0f, 0xca, 0x1c, 0x76, 0x19, 0x6e, 0x07, + 0x1b, 0xfd, 0xc4, 0x09, 0xca, 0x17, 0x5e, 0x14, 0x00, 0x0b, 0x0a, 0x10, + 0xf8, 0x21, 0xbd, 0x1d, 0xbd, 0xfc, 0xca, 0xd5, 0xbf, 0xbe, 0xde, 0xb9, + 0x5b, 0xad, 0x35, 0x9b, 0xc4, 0x92, 0x10, 0x93, 0x4f, 0x9e, 0x1a, 0xb2, + 0x7b, 0xb5, 0xee, 0xb2, 0x12, 0xb8, 0xc8, 0xbb, 0xea, 0xc5, 0x92, 0xd0, + 0x69, 0xe2, 0x12, 0xf8, 0xb6, 0x00, 0x47, 0x02, 0x6e, 0x11, 0x89, 0x29, + 0xa2, 0x40, 0x70, 0x55, 0x44, 0x55, 0xec, 0x51, 0x9c, 0x50, 0x18, 0x4d, + 0x15, 0x58, 0x9a, 0x61, 0x15, 0x4c, 0xc0, 0x2d, 0x11, 0x1f, 0xce, 0x07, + 0x1a, 0xee, 0xbd, 0xd7, 0x34, 0xc6, 0x07, 0xc4, 0x8d, 0xc0, 0x58, 0xb8, + 0xe8, 0xc5, 0x3e, 0xde, 0x02, 0xd8, 0x1d, 0xc3, 0xb5, 0xaf, 0x2b, 0x9d, + 0x6c, 0xa1, 0x1b, 0xb4, 0xf2, 0xba, 0x47, 0xb5, 0xa2, 0xad, 0x3c, 0xb7, + 0xd0, 0xcc, 0x83, 0xe0, 0xed, 0xf3, 0x06, 0xfb, 0x6d, 0xfb, 0xf0, 0x00, + 0x13, 0x17, 0x55, 0x28, 0xac, 0x1e, 0x08, 0x16, 0x98, 0x1c, 0xe6, 0x1c, + 0x71, 0x0f, 0x39, 0x13, 0x83, 0x27, 0xe3, 0x3e, 0x79, 0x45, 0xdc, 0x33, + 0x29, 0x26, 0xd8, 0x1e, 0x27, 0x17, 0xf9, 0x08, 0xed, 0xf9, 0xa4, 0xef, + 0xb9, 0xeb, 0xbb, 0xe2, 0x84, 0xd2, 0xaa, 0xdd, 0x76, 0xf9, 0x06, 0xfc, + 0xae, 0xf0, 0xb3, 0xfa, 0xfe, 0x12, 0xf0, 0x27, 0x97, 0x38, 0x27, 0x40, + 0x27, 0x41, 0xab, 0x3f, 0x82, 0x35, 0x0d, 0x34, 0x8e, 0x3d, 0x36, 0x41, + 0x61, 0x4e, 0x34, 0x59, 0x8d, 0x51, 0x56, 0x46, 0x68, 0x3d, 0xfb, 0x3b, + 0xb1, 0x44, 0xb6, 0x4e, 0x85, 0x43, 0x5c, 0x1b, 0x7c, 0x01, 0x00, 0x04, + 0xf0, 0x0f, 0x65, 0x14, 0x1d, 0xfd, 0xb0, 0xeb, 0x00, 0xee, 0x57, 0xf8, + 0xff, 0x01, 0x82, 0xfa, 0x73, 0xf7, 0x3f, 0x07, 0xcf, 0x16, 0x2b, 0x18, + 0x1f, 0x0f, 0x90, 0x04, 0x40, 0x0a, 0x3a, 0x05, 0x20, 0xf0, 0x27, 0xe5, + 0x5c, 0xdc, 0x36, 0xe6, 0xf8, 0xf3, 0x66, 0xed, 0x01, 0xd7, 0x81, 0xc9, + 0xa0, 0xcd, 0x8b, 0xd5, 0x19, 0xe5, 0x69, 0xf5, 0xda, 0xff, 0x04, 0xfe, + 0x59, 0x01, 0xab, 0x18, 0x7e, 0x3d, 0x00, 0x5b, 0x09, 0x60, 0x35, 0x5c, + 0x8c, 0x5d, 0xa7, 0x66, 0xff, 0x6e, 0xda, 0x72, 0x54, 0x70, 0xe5, 0x6d, + 0x53, 0x6e, 0x82, 0x6b, 0xf9, 0x62, 0x5e, 0x55, 0x13, 0x47, 0x05, 0x3b, + 0x0d, 0x2f, 0x5f, 0x15, 0x07, 0xfc, 0x94, 0xf5, 0x16, 0xfb, 0xd5, 0xfb, + 0x27, 0xfb, 0xe1, 0x04, 0xfb, 0x0b, 0xae, 0x06, 0x7e, 0xf4, 0x94, 0xe6, + 0x27, 0xea, 0x94, 0xec, 0x4f, 0xe0, 0x72, 0xdb, 0x2b, 0xe0, 0x81, 0xec, + 0xf0, 0xfe, 0x2f, 0x00, 0x86, 0xf7, 0x67, 0xed, 0xb0, 0xe9, 0x6a, 0xe5, + 0x14, 0xda, 0x24, 0xcb, 0xca, 0xc1, 0xd9, 0xc6, 0x8c, 0xc1, 0x7b, 0xba, + 0xa3, 0xc3, 0xe2, 0xd6, 0x90, 0xe4, 0x14, 0xe2, 0xb1, 0xd6, 0x1f, 0xcf, + 0xa5, 0xcc, 0xaf, 0xd4, 0x66, 0xee, 0xdc, 0xf5, 0x16, 0xe8, 0x0b, 0xe7, + 0xa1, 0xf7, 0x7d, 0x04, 0xa9, 0x0a, 0x76, 0x11, 0xaf, 0x14, 0x3c, 0x1f, + 0xa9, 0x29, 0xee, 0x2e, 0x46, 0x33, 0xcc, 0x32, 0xa2, 0x2b, 0x94, 0x19, + 0x2e, 0x02, 0xdb, 0xef, 0xcd, 0xf2, 0xe7, 0x02, 0xec, 0xfe, 0xe1, 0xeb, + 0x93, 0xe0, 0x78, 0xe6, 0x1a, 0xfc, 0xef, 0x05, 0xd5, 0x00, 0x21, 0xf4, + 0xe2, 0xe5, 0xc5, 0xef, 0xd2, 0x09, 0xdb, 0x14, 0xa5, 0x09, 0x07, 0xff, + 0xe5, 0x02, 0x03, 0x10, 0x3a, 0x19, 0xb3, 0x1a, 0x27, 0x20, 0xcd, 0x25, + 0x87, 0x1e, 0xe3, 0x15, 0x4d, 0x1c, 0x82, 0x27, 0xbd, 0x29, 0x60, 0x19, + 0x8b, 0x0a, 0x72, 0x03, 0x07, 0xf3, 0x57, 0xec, 0xc8, 0xed, 0x29, 0xe6, + 0x7b, 0xe0, 0x5f, 0xde, 0xb8, 0xd9, 0xbe, 0xe5, 0x54, 0xfc, 0x76, 0x10, + 0x23, 0x29, 0xb3, 0x3c, 0xb9, 0x48, 0x37, 0x4a, 0x50, 0x3d, 0xdb, 0x2f, + 0xa5, 0x2f, 0x6d, 0x33, 0x71, 0x34, 0xf8, 0x37, 0xcf, 0x3a, 0x39, 0x38, + 0x19, 0x31, 0xf4, 0x2e, 0xe6, 0x31, 0x15, 0x2d, 0xf9, 0x19, 0xd6, 0xfe, + 0xb9, 0xe8, 0x54, 0xea, 0x90, 0xf4, 0xf0, 0xec, 0x51, 0xdd, 0xf4, 0xd7, + 0x27, 0xeb, 0x12, 0x01, 0x25, 0xfd, 0x60, 0xe8, 0x5d, 0xe4, 0xe7, 0xec, + 0x7f, 0xe7, 0x11, 0xe3, 0x66, 0xe9, 0xf4, 0x00, 0x76, 0x13, 0x84, 0x0f, + 0xd7, 0x03, 0xa1, 0xf3, 0xff, 0xfe, 0x04, 0x26, 0x7d, 0x42, 0xbe, 0x41, + 0xf8, 0x32, 0x9c, 0x3b, 0x9d, 0x44, 0x29, 0x39, 0x40, 0x34, 0x79, 0x28, + 0x27, 0x17, 0x84, 0x1e, 0x42, 0x1a, 0x9d, 0xfb, 0xe8, 0xec, 0x13, 0xf4, + 0x27, 0xff, 0x4d, 0xf8, 0x71, 0xe3, 0x8d, 0xd5, 0xea, 0xd0, 0xa0, 0xd0, + 0x8d, 0xcf, 0xbf, 0xd1, 0xe9, 0xd7, 0x46, 0xe6, 0x9e, 0xf7, 0x4a, 0x01, + 0xde, 0x0b, 0x54, 0x1a, 0x72, 0x2d, 0xc3, 0x44, 0x88, 0x57, 0xe5, 0x5c, + 0x8b, 0x52, 0xbf, 0x47, 0x8e, 0x50, 0x0e, 0x5e, 0x79, 0x5b, 0xb2, 0x48, + 0x55, 0x32, 0x7a, 0x2d, 0x62, 0x24, 0xcb, 0x02, 0x6e, 0xea, 0x01, 0xea, + 0x4c, 0xe6, 0x57, 0xde, 0x69, 0xd8, 0xb9, 0xd2, 0x7f, 0xdb, 0xe4, 0xe6, + 0x77, 0xef, 0x2c, 0xf9, 0x7c, 0xf7, 0x45, 0xea, 0x6e, 0xe1, 0x6e, 0xed, + 0x26, 0xfe, 0xf4, 0xfa, 0xd1, 0xe8, 0x36, 0xde, 0x80, 0xe2, 0xd7, 0xee, + 0xfc, 0xf7, 0xa6, 0xf3, 0x65, 0xf7, 0x2c, 0x05, 0x60, 0x05, 0x39, 0xf8, + 0xfa, 0xe4, 0x22, 0xe0, 0xcc, 0xe8, 0x23, 0xf5, 0xb0, 0xff, 0x23, 0xf7, + 0xdc, 0xea, 0xab, 0xdb, 0x89, 0xd5, 0x06, 0xe8, 0x5b, 0xf6, 0x79, 0xf4, + 0x68, 0xe7, 0x8c, 0xe8, 0x67, 0xf0, 0x18, 0xee, 0x23, 0xe9, 0x2f, 0xdd, + 0xcb, 0xd9, 0x18, 0xe7, 0xf3, 0xf7, 0x5f, 0xfc, 0xa2, 0xfb, 0x58, 0x04, + 0xda, 0x10, 0xca, 0x1b, 0xe1, 0x21, 0x36, 0x27, 0x5e, 0x35, 0x6c, 0x4d, + 0xa1, 0x5d, 0x65, 0x5d, 0x11, 0x57, 0xfd, 0x59, 0x4b, 0x65, 0x91, 0x6d, + 0x24, 0x72, 0x8f, 0x6a, 0x52, 0x5c, 0xc1, 0x58, 0x81, 0x5e, 0x52, 0x61, + 0xbb, 0x5b, 0xef, 0x4e, 0x81, 0x44, 0x34, 0x41, 0x42, 0x37, 0x27, 0x1e, + 0xd3, 0x01, 0x38, 0xf8, 0x84, 0xef, 0x75, 0xdc, 0x77, 0xd5, 0x7a, 0xd2, + 0xb3, 0xc9, 0x0c, 0xba, 0xc5, 0xb0, 0x69, 0xb8, 0x76, 0xba, 0xa8, 0xb3, + 0xab, 0xb2, 0xfe, 0xb8, 0xe6, 0xc1, 0x55, 0xc3, 0x1d, 0xbd, 0xc8, 0xb9, + 0xfe, 0xc0, 0x99, 0xd4, 0x4b, 0xda, 0x11, 0xcd, 0xa3, 0xd0, 0x5c, 0xec, + 0x00, 0x0d, 0x0b, 0x19, 0xd5, 0x0d, 0x20, 0x08, 0x0e, 0x07, 0xcb, 0xf8, + 0xf3, 0xec, 0x65, 0xeb, 0x52, 0xed, 0xae, 0xee, 0xf7, 0xe7, 0x22, 0xe5, + 0x78, 0xe9, 0x70, 0xeb, 0x24, 0xe1, 0x9a, 0xce, 0xaf, 0xbc, 0x2f, 0xb2, + 0x4a, 0xba, 0xfa, 0xc4, 0x3a, 0xc8, 0xdf, 0xc1, 0xa4, 0xbd, 0x72, 0xc8, + 0x44, 0xdd, 0xe2, 0xf3, 0xc6, 0xf8, 0x97, 0xf4, 0xff, 0xf7, 0x55, 0x0d, + 0xc3, 0x20, 0x48, 0x1a, 0x7d, 0x0c, 0x3b, 0x0c, 0x84, 0x17, 0xe0, 0x1d, + 0xee, 0x1b, 0x05, 0x08, 0x47, 0xf7, 0x5c, 0xfa, 0x75, 0x03, 0x73, 0x06, + 0xb9, 0xf8, 0xdf, 0xf0, 0xbb, 0xf1, 0xe2, 0xf5, 0xc1, 0xf5, 0xe4, 0xf4, + 0xec, 0xf9, 0x2d, 0xfe, 0x75, 0x09, 0xe5, 0x09, 0x8c, 0xf9, 0x47, 0xe4, + 0x5a, 0xdf, 0x46, 0xea, 0xc5, 0xeb, 0x25, 0xf0, 0xf9, 0x05, 0xe1, 0x13, + 0xb4, 0x08, 0xe6, 0xff, 0x1e, 0x01, 0x4b, 0x10, 0x33, 0x1a, 0x87, 0x09, + 0xed, 0xfe, 0x78, 0xfc, 0x2b, 0xff, 0xc6, 0x01, 0xc4, 0xf0, 0xeb, 0xdf, + 0xd3, 0xdb, 0xf0, 0xd5, 0x32, 0xd1, 0x55, 0xd1, 0xc6, 0xd4, 0x35, 0xe1, + 0x38, 0xf0, 0x8f, 0xfd, 0xcf, 0x09, 0xe1, 0x12, 0xc6, 0x17, 0x37, 0x19, + 0xd9, 0x19, 0xe6, 0x19, 0x12, 0x13, 0x80, 0x07, 0xda, 0x03, 0x1a, 0x06, + 0xc6, 0x00, 0x2e, 0xf4, 0x64, 0xf0, 0x86, 0xea, 0xdb, 0xd8, 0x03, 0xcc, + 0xfc, 0xc1, 0x7e, 0xb7, 0xbf, 0xb3, 0x56, 0xb9, 0xc6, 0xc3, 0x3c, 0xce, + 0xb7, 0xd8, 0x7c, 0xe7, 0x80, 0xf9, 0xcc, 0x03, 0x8f, 0x03, 0x62, 0x06, + 0xe3, 0x15, 0x61, 0x24, 0x47, 0x31, 0xb3, 0x38, 0x32, 0x2e, 0x96, 0x26, + 0x05, 0x26, 0x90, 0x27, 0x16, 0x29, 0xb6, 0x19, 0xfd, 0xfc, 0xfa, 0xeb, + 0xb2, 0xf6, 0x80, 0x03, 0x2c, 0xfd, 0xbf, 0xf1, 0xc9, 0xed, 0x8a, 0xf4, + 0x25, 0xfd, 0x19, 0x06, 0xc4, 0x0f, 0xf1, 0x1b, 0xc7, 0x35, 0x82, 0x4c, + 0xe6, 0x4f, 0x25, 0x48, 0x6b, 0x3c, 0xb7, 0x3a, 0x16, 0x44, 0xf6, 0x41, + 0x8a, 0x1c, 0xca, 0xdf, 0xd1, 0xbf, 0xfa, 0xc2, 0x9b, 0xcb, 0x07, 0xc9, + 0x03, 0xbf, 0x33, 0xc5, 0x75, 0xd1, 0xd0, 0xd3, 0xe2, 0xd5, 0x75, 0xdc, + 0x94, 0xec, 0xe5, 0xff, 0x0e, 0x03, 0x7f, 0xfb, 0x4e, 0xf5, 0x02, 0xe8, + 0x70, 0xd6, 0x02, 0xce, 0x62, 0xd1, 0xa3, 0xd5, 0x1f, 0xd2, 0x76, 0xce, + 0x80, 0xd3, 0x05, 0xe1, 0x19, 0xee, 0xca, 0xf5, 0x25, 0x04, 0xd0, 0x15, + 0x8c, 0x22, 0xef, 0x30, 0x70, 0x38, 0x6c, 0x3b, 0xac, 0x3b, 0xc1, 0x2c, + 0x47, 0x18, 0xf3, 0x09, 0x5b, 0xf3, 0x5c, 0xd0, 0x3c, 0xbc, 0xe3, 0xb5, + 0x7a, 0xb6, 0x59, 0xc6, 0x4b, 0xd0, 0x7a, 0xcc, 0x5b, 0xd2, 0x93, 0xe4, + 0xe1, 0xee, 0xdd, 0xf9, 0x7f, 0x0e, 0x70, 0x27, 0x44, 0x45, 0xc0, 0x57, + 0x8e, 0x5e, 0x79, 0x62, 0xed, 0x5f, 0x8b, 0x58, 0xd3, 0x54, 0x95, 0x57, + 0x87, 0x59, 0x00, 0x5c, 0x00, 0x58, 0x6f, 0x50, 0x2c, 0x54, 0x84, 0x56, + 0x6d, 0x4b, 0x89, 0x3c, 0xb5, 0x34, 0x0a, 0x35, 0xfa, 0x2d, 0x90, 0x13, + 0x0b, 0xf6, 0xe6, 0xe4, 0x5c, 0xe0, 0x35, 0xd7, 0x67, 0xbf, 0x09, 0xae, + 0xb7, 0xb4, 0xb4, 0xc4, 0x0c, 0xc4, 0xa4, 0xba, 0x45, 0xb0, 0xad, 0xb2, + 0x2d, 0xc3, 0x3e, 0xcb, 0x54, 0xcf, 0x37, 0xc9, 0xc4, 0xbd, 0xb5, 0xc0, + 0xf8, 0xcd, 0x78, 0xcf, 0x93, 0xd0, 0xdb, 0xe4, 0x45, 0x06, 0xde, 0x33, + 0xc5, 0x51, 0x18, 0x5c, 0xf6, 0x5d, 0x9c, 0x5a, 0xd4, 0x5b, 0x73, 0x63, + 0x95, 0x68, 0xd7, 0x5c, 0xbd, 0x47, 0xda, 0x2b, 0xc5, 0x22, 0xec, 0x30, + 0x05, 0x3d, 0xa2, 0x33, 0x51, 0x12, 0x1f, 0x03, 0x07, 0x07, 0xb0, 0x06, + 0xb4, 0xf6, 0x3b, 0xe5, 0xf4, 0xe3, 0xe1, 0xee, 0xcc, 0xf2, 0x57, 0xe5, + 0xfa, 0xe7, 0xe8, 0xf7, 0x94, 0x0b, 0xc6, 0x16, 0x99, 0x14, 0x02, 0x1b, + 0x95, 0x23, 0x3f, 0x2e, 0x02, 0x3a, 0x48, 0x4a, 0x1c, 0x58, 0x5f, 0x54, + 0xbb, 0x4f, 0x87, 0x51, 0x6b, 0x4f, 0x70, 0x46, 0xb4, 0x3c, 0x7b, 0x3a, + 0xb8, 0x39, 0x02, 0x2f, 0x1d, 0x2e, 0x20, 0x39, 0x53, 0x34, 0x11, 0x20, + 0x9a, 0x1c, 0xb7, 0x27, 0x30, 0x23, 0x90, 0x1b, 0xf9, 0x0e, 0x61, 0x04, + 0x2f, 0x0f, 0x56, 0x1f, 0xa2, 0x2c, 0xa0, 0x2b, 0x52, 0x22, 0x0b, 0x1b, + 0x5d, 0x19, 0xea, 0x22, 0x5c, 0x27, 0x3c, 0x1c, 0xa4, 0x0b, 0x8a, 0x01, + 0x41, 0xf1, 0xc6, 0xdf, 0x93, 0xd8, 0x7f, 0xdc, 0xd1, 0xf8, 0x44, 0x0e, + 0xdf, 0x0f, 0x96, 0x1c, 0x7f, 0x24, 0xa3, 0x17, 0xd2, 0x10, 0x5c, 0x0f, + 0x6b, 0x10, 0x61, 0x1a, 0x8e, 0x16, 0x76, 0x0b, 0x7a, 0x05, 0x98, 0x04, + 0x24, 0x08, 0x99, 0xfe, 0xb0, 0xe6, 0xed, 0xd1, 0x54, 0xc8, 0xc9, 0xc4, + 0xb8, 0xbf, 0x7e, 0xb1, 0x77, 0xab, 0x2e, 0xb5, 0x96, 0xbb, 0xa2, 0xbc, + 0x52, 0xbd, 0xdc, 0xc5, 0x96, 0xd8, 0x4b, 0xec, 0x32, 0xf4, 0xa8, 0xf2, + 0x3b, 0xfa, 0x85, 0x16, 0xfa, 0x27, 0xac, 0x1d, 0x40, 0x1f, 0xf4, 0x26, + 0x6d, 0x27, 0x4b, 0x30, 0x20, 0x41, 0x3d, 0x4b, 0xb2, 0x3e, 0xe2, 0x2b, + 0x5d, 0x2b, 0xb6, 0x37, 0x5d, 0x34, 0x4e, 0x21, 0x77, 0x12, 0xc3, 0x09, + 0x94, 0x07, 0x96, 0x05, 0x7f, 0x0c, 0x50, 0x18, 0xa7, 0x07, 0x15, 0xf0, + 0x9b, 0xf7, 0x5e, 0x06, 0xb9, 0x08, 0xbe, 0x02, 0x61, 0xf8, 0x57, 0xfb, + 0xaa, 0x0c, 0x6d, 0x14, 0x98, 0x0e, 0x0e, 0x0f, 0xaf, 0x1a, 0x47, 0x2f, + 0x6a, 0x44, 0x61, 0x4b, 0x68, 0x42, 0x6a, 0x31, 0x12, 0x35, 0x6a, 0x43, + 0x47, 0x3f, 0x46, 0x32, 0x90, 0x24, 0x82, 0x1c, 0xb6, 0x19, 0x5a, 0x10, + 0x65, 0xfe, 0xde, 0xf8, 0x2e, 0xff, 0xb7, 0xf9, 0xc4, 0xe5, 0x7e, 0xd5, + 0xc7, 0xda, 0x86, 0xe1, 0x1e, 0xdc, 0x72, 0xcf, 0x7a, 0xc5, 0x4c, 0xc8, + 0x79, 0xd2, 0x87, 0xde, 0xa2, 0xe6, 0x78, 0xeb, 0xde, 0xeb, 0xcf, 0xf5, + 0x4d, 0x08, 0xa9, 0x15, 0xcb, 0x21, 0x50, 0x1e, 0xca, 0x18, 0x7e, 0x26, + 0xee, 0x32, 0xdb, 0x2a, 0x3f, 0x1d, 0x6d, 0x1c, 0x08, 0x1a, 0x4e, 0x0f, + 0x1a, 0x0a, 0x51, 0x07, 0xbc, 0xff, 0xe6, 0xfb, 0x25, 0xfd, 0x13, 0xf8, + 0x55, 0xf6, 0x2a, 0x06, 0x4a, 0x14, 0xf8, 0x19, 0x3e, 0x19, 0xe9, 0x15, + 0xfd, 0x24, 0xda, 0x38, 0x48, 0x44, 0x56, 0x48, 0xfc, 0x42, 0xe0, 0x3d, + 0x3d, 0x41, 0x2e, 0x48, 0xf3, 0x3b, 0x5c, 0x2d, 0x19, 0x32, 0x60, 0x3a, + 0x41, 0x40, 0x7e, 0x37, 0x5f, 0x2a, 0xcf, 0x24, 0x56, 0x1c, 0x21, 0x13, + 0xf5, 0x00, 0x78, 0xf2, 0xb0, 0xf6, 0x3c, 0xfe, 0xde, 0x05, 0x72, 0x0f, + 0xea, 0x11, 0xed, 0x10, 0xf0, 0x14, 0xdb, 0x10, 0x49, 0x03, 0xac, 0xf0, + 0xa7, 0xdc, 0xad, 0xdd, 0x80, 0xe8, 0xd7, 0xdf, 0xf1, 0xc6, 0x23, 0xb3, + 0x3f, 0xad, 0xfa, 0xab, 0x19, 0xa5, 0xe9, 0x9b, 0xf2, 0x9d, 0x98, 0xa5, + 0x26, 0xaf, 0x0e, 0xbf, 0x82, 0xcd, 0x68, 0xd8, 0xb9, 0xe4, 0xb3, 0xed, + 0x66, 0xf0, 0x6d, 0xfa, 0xc7, 0x08, 0x7b, 0x20, 0x0f, 0x3d, 0x36, 0x43, + 0x90, 0x3b, 0x10, 0x3c, 0x74, 0x4f, 0xa0, 0x5a, 0x7e, 0x53, 0x9c, 0x52, + 0x0e, 0x4f, 0xd8, 0x3d, 0xd5, 0x30, 0x63, 0x2d, 0x7b, 0x26, 0x37, 0x1b, + 0x89, 0x05, 0x50, 0xf6, 0xa3, 0xf2, 0x8c, 0xef, 0x77, 0xf5, 0x10, 0xfb, + 0xe0, 0x01, 0x91, 0x04, 0xb1, 0x06, 0x27, 0x0e, 0x32, 0x07, 0x0d, 0x00, + 0x39, 0xff, 0x12, 0xf4, 0xa2, 0xee, 0x6d, 0xf4, 0x77, 0xfa, 0x3e, 0xfd, + 0xa2, 0xf4, 0xcd, 0xf4, 0xc1, 0x03, 0xb1, 0x0a, 0xcc, 0x0c, 0x0c, 0x0c, + 0x8e, 0x03, 0xf2, 0xfe, 0x8f, 0xff, 0x06, 0x05, 0x39, 0x0d, 0x42, 0x0d, + 0xac, 0x0e, 0xb7, 0x12, 0xaa, 0x14, 0x94, 0x11, 0x6e, 0x07, 0xd3, 0x04, + 0x09, 0x12, 0x76, 0x1c, 0x6b, 0x20, 0x2c, 0x2a, 0x6e, 0x2f, 0xc6, 0x2d, + 0x84, 0x21, 0x3b, 0x15, 0xe7, 0x18, 0x0c, 0x1e, 0x14, 0x1a, 0x68, 0x1c, + 0x39, 0x24, 0x51, 0x21, 0x3a, 0x22, 0x6e, 0x26, 0x14, 0x2b, 0x80, 0x27, + 0x3e, 0x12, 0x57, 0xfc, 0x1d, 0xf3, 0x9c, 0xee, 0xb8, 0xe5, 0x87, 0xe4, + 0x9c, 0xe1, 0x1a, 0xe3, 0xc6, 0xe8, 0xe8, 0xe5, 0xf9, 0xe9, 0x35, 0xef, + 0xf0, 0xed, 0x57, 0xee, 0x9b, 0xf1, 0x3c, 0xf3, 0x31, 0xec, 0x80, 0xe5, + 0x0a, 0xec, 0xf0, 0xee, 0x62, 0xef, 0x10, 0xeb, 0xb5, 0xe4, 0x0a, 0xe5, + 0x02, 0xe3, 0x45, 0xe8, 0x75, 0xee, 0x9f, 0xf1, 0x39, 0xe7, 0x17, 0xd2, + 0x24, 0xc3, 0x3b, 0xc3, 0xf3, 0xd3, 0x2a, 0xde, 0x25, 0xd8, 0x7a, 0xcd, + 0x96, 0xd3, 0x07, 0xdf, 0x67, 0xea, 0x52, 0xf6, 0xc3, 0xf6, 0xa9, 0xf0, + 0x85, 0xe2, 0x84, 0xde, 0x44, 0xe4, 0x90, 0xdc, 0x3e, 0xdf, 0xa9, 0xf0, + 0x07, 0xeb, 0x39, 0xdd, 0x87, 0xcc, 0x4e, 0xb9, 0xc5, 0xb7, 0x98, 0xc2, + 0xb8, 0xda, 0x28, 0xe9, 0xf0, 0xe5, 0x86, 0xdf, 0x98, 0xe3, 0x5e, 0xf7, + 0x91, 0x07, 0xa1, 0x0a, 0x94, 0x0d, 0xb0, 0x14, 0x20, 0x13, 0xd8, 0x16, + 0xc7, 0x11, 0xc3, 0x04, 0x71, 0x09, 0x81, 0x12, 0x31, 0x19, 0xc2, 0x0e, + 0x25, 0x07, 0x9f, 0x0f, 0xe0, 0x15, 0x8d, 0x1a, 0x6d, 0x18, 0x51, 0x16, + 0x9a, 0x12, 0xbd, 0x10, 0xd5, 0x0e, 0xdd, 0xff, 0x55, 0xeb, 0xc7, 0xdc, + 0xdc, 0xdd, 0xfa, 0xe3, 0x9f, 0xe5, 0x5c, 0xdf, 0xf2, 0xdf, 0xf2, 0xe9, + 0xce, 0xe9, 0xf5, 0xed, 0x84, 0xf0, 0x43, 0xf1, 0x42, 0xf8, 0xea, 0xf7, + 0x92, 0xf3, 0x95, 0xde, 0x76, 0xbf, 0x48, 0xaf, 0x1c, 0xae, 0x52, 0xba, + 0x4b, 0xc3, 0xc5, 0xbe, 0x5a, 0xb1, 0xbc, 0xb1, 0x99, 0xc9, 0xf3, 0xe2, + 0x11, 0xf2, 0x4f, 0xea, 0xb3, 0xe5, 0x52, 0xf0, 0x72, 0x01, 0x8e, 0x13, + 0x30, 0x16, 0x36, 0x1f, 0xd1, 0x2c, 0xe9, 0x36, 0xd7, 0x36, 0xee, 0x25, + 0x57, 0x15, 0x39, 0x12, 0x74, 0x19, 0xcd, 0x19, 0xf5, 0x16, 0xf1, 0x12, + 0xfa, 0x1d, 0x90, 0x2b, 0x57, 0x29, 0xdd, 0x28, 0x9d, 0x27, 0x15, 0x2f, + 0xdd, 0x41, 0x0a, 0x51, 0x96, 0x58, 0x50, 0x5c, 0xfa, 0x58, 0xed, 0x54, + 0x92, 0x56, 0x68, 0x5a, 0x69, 0x5d, 0x9a, 0x4d, 0xc1, 0x30, 0x72, 0x1e, + 0x77, 0x16, 0x86, 0x08, 0xb2, 0xef, 0xa7, 0xd0, 0x84, 0xba, 0x0b, 0xb3, + 0xf7, 0xb3, 0x85, 0xbb, 0x37, 0xc1, 0x27, 0xc7, 0x54, 0xc9, 0x0b, 0xc9, + 0x28, 0xcf, 0x58, 0xd6, 0x56, 0xde, 0x19, 0xe7, 0xdc, 0xef, 0x0b, 0xf9, + 0xa5, 0x05, 0xe0, 0x19, 0x09, 0x27, 0x4f, 0x25, 0x8e, 0x21, 0xec, 0x1d, + 0xe7, 0x19, 0x90, 0x0e, 0xdb, 0xfe, 0xda, 0xf3, 0x63, 0xec, 0x08, 0xe5, + 0x93, 0xd5, 0xea, 0xc0, 0x37, 0xb0, 0x84, 0xac, 0x02, 0xb2, 0x32, 0xb4, + 0xc3, 0xac, 0x13, 0xa4, 0x6d, 0xa3, 0x77, 0xaf, 0x76, 0xc4, 0x34, 0xd9, + 0xdb, 0xed, 0x04, 0xfd, 0xb5, 0x16, 0x75, 0x30, 0xa6, 0x3f, 0xef, 0x4c, + 0x72, 0x50, 0x5b, 0x4d, 0x82, 0x42, 0x01, 0x3c, 0x4c, 0x2c, 0xd8, 0x10, + 0x7d, 0xfc, 0xc9, 0xf3, 0x6e, 0xf1, 0xb3, 0xe5, 0x0a, 0xd7, 0xd8, 0xc9, + 0x87, 0xc9, 0x0e, 0xc2, 0x04, 0xb3, 0x60, 0xaf, 0xa2, 0xa8, 0xbe, 0xa4, + 0xa3, 0xa3, 0x7f, 0xa3, 0x22, 0xa6, 0x49, 0xb3, 0xcb, 0xc3, 0xd6, 0xd5, + 0x70, 0xea, 0x5e, 0xf7, 0xb8, 0x03, 0xb6, 0x14, 0xe8, 0x2e, 0x2f, 0x41, + 0x76, 0x44, 0x11, 0x39, 0x1d, 0x35, 0x12, 0x47, 0xde, 0x53, 0xc9, 0x55, + 0x6a, 0x58, 0x0d, 0x62, 0xc0, 0x63, 0x6f, 0x61, 0x1e, 0x55, 0xba, 0x40, + 0x04, 0x2f, 0x01, 0x18, 0x20, 0x06, 0x1a, 0xf8, 0xc6, 0xf0, 0x15, 0xe9, + 0x33, 0xdf, 0x8d, 0xdc, 0x3f, 0xe0, 0x76, 0xdd, 0xc2, 0xd9, 0xaa, 0xe4, + 0xdc, 0xe8, 0x71, 0xe5, 0xf9, 0xe2, 0x08, 0xe2, 0x53, 0xe2, 0xe9, 0xed, + 0x45, 0x02, 0x23, 0x11, 0x42, 0x15, 0xd4, 0x0c, 0xfb, 0x08, 0xf4, 0x0d, + 0x5a, 0x17, 0x26, 0x21, 0xac, 0x33, 0x92, 0x43, 0x50, 0x47, 0x6c, 0x42, + 0xa2, 0x39, 0xb3, 0x38, 0x52, 0x34, 0x04, 0x2e, 0x57, 0x1e, 0x7a, 0x19, + 0xce, 0x23, 0x1d, 0x22, 0x4d, 0x1b, 0xf8, 0x17, 0xdc, 0x1e, 0x7e, 0x2e, + 0xc9, 0x40, 0x15, 0x48, 0x7d, 0x50, 0xc0, 0x59, 0xaa, 0x5b, 0xf0, 0x58, + 0x6e, 0x50, 0xd8, 0x4b, 0x2e, 0x47, 0x92, 0x44, 0x15, 0x41, 0xf2, 0x39, + 0xaf, 0x2c, 0x6c, 0x2d, 0x77, 0x39, 0x88, 0x3b, 0xc9, 0x39, 0x21, 0x2e, + 0x8d, 0x26, 0xf6, 0x2a, 0x69, 0x3e, 0x0e, 0x4d, 0xe1, 0x47, 0xcf, 0x3e, + 0xb5, 0x38, 0x6d, 0x3d, 0xd6, 0x40, 0xdf, 0x3f, 0xcd, 0x40, 0xe9, 0x41, + 0xad, 0x39, 0xe2, 0x2d, 0xcd, 0x22, 0x58, 0x13, 0x90, 0x06, 0x28, 0xf8, + 0x50, 0xeb, 0x26, 0xe7, 0xe4, 0xe7, 0x83, 0xe4, 0x33, 0xe4, 0x17, 0xe5, + 0xb0, 0xeb, 0xc8, 0xfa, 0xd5, 0xf6, 0x3b, 0xeb, 0x2b, 0xe4, 0x90, 0xe7, + 0x31, 0xf7, 0x90, 0xfd, 0x91, 0xf7, 0x75, 0xeb, 0xb6, 0xe5, 0x7a, 0xe7, + 0xbf, 0xe5, 0xd5, 0xe1, 0xf6, 0xd6, 0x67, 0xd1, 0xf9, 0xd8, 0x3e, 0xd6, + 0xf5, 0xd2, 0x6c, 0xd4, 0x9b, 0xd5, 0xb5, 0xdb, 0xef, 0xe2, 0xff, 0xec, + 0xbb, 0xf6, 0x82, 0xff, 0x12, 0xfb, 0x15, 0xf9, 0x6a, 0x06, 0x38, 0x14, + 0x8f, 0x24, 0xa8, 0x2c, 0x9c, 0x27, 0x1c, 0x21, 0x1c, 0x18, 0x10, 0x08, + 0xfc, 0x01, 0xad, 0xfb, 0x42, 0xf6, 0xe5, 0xf8, 0x3b, 0xf6, 0xff, 0xf5, + 0x00, 0xf5, 0xdf, 0xfa, 0x38, 0x00, 0x3c, 0x07, 0xf8, 0x0f, 0xe8, 0x0d, + 0x96, 0x08, 0xb3, 0x03, 0x14, 0x07, 0xbc, 0x09, 0xd2, 0x11, 0x9a, 0x18, + 0xa9, 0x1c, 0xb2, 0x26, 0xe6, 0x2f, 0x3c, 0x36, 0xb0, 0x36, 0xf0, 0x33, + 0x29, 0x2d, 0x34, 0x2e, 0xb4, 0x31, 0xa7, 0x33, 0x20, 0x30, 0xd6, 0x28, + 0x83, 0x26, 0x70, 0x21, 0xaf, 0x15, 0xe1, 0xfe, 0x63, 0xf1, 0x64, 0xf4, + 0xfc, 0xfa, 0xb3, 0xf4, 0x14, 0xed, 0x53, 0xf5, 0xca, 0xfd, 0xf3, 0xfc, + 0x17, 0xf1, 0x3e, 0xe0, 0x68, 0xd0, 0x25, 0xd0, 0x15, 0xda, 0x0e, 0xe3, + 0x49, 0xe8, 0x5d, 0xe6, 0xf8, 0xe1, 0x65, 0xe5, 0x05, 0xf0, 0x34, 0xf0, + 0x1f, 0xf3, 0x28, 0xf9, 0x4b, 0x04, 0x96, 0x11, 0x9c, 0x0a, 0x3f, 0x00, + 0xbe, 0xfe, 0x92, 0x0b, 0xdb, 0x1e, 0xf1, 0x26, 0x9f, 0x2d, 0xd9, 0x3c, + 0x19, 0x52, 0xa0, 0x64, 0x49, 0x63, 0xef, 0x4d, 0x37, 0x38, 0x37, 0x2e, + 0x6b, 0x2b, 0xb5, 0x1f, 0x3d, 0x0e, 0x8a, 0x09, 0x11, 0x10, 0x30, 0x1b, + 0x09, 0x24, 0xd8, 0x21, 0xb6, 0x1b, 0x44, 0x13, 0x22, 0x0a, 0x27, 0x08, + 0x83, 0x0b, 0xab, 0x16, 0x82, 0x29, 0xe0, 0x36, 0x3e, 0x3d, 0xbb, 0x3d, + 0xd4, 0x37, 0x83, 0x2e, 0x13, 0x21, 0xec, 0x14, 0xb3, 0x02, 0xe0, 0xf6, + 0x65, 0xf7, 0x9c, 0xf5, 0xd2, 0xfb, 0x02, 0x0d, 0x5c, 0x24, 0x38, 0x37, + 0xd9, 0x3d, 0xbb, 0x38, 0xb6, 0x39, 0x2f, 0x3c, 0x96, 0x36, 0x3a, 0x34, + 0x33, 0x25, 0xd7, 0x17, 0x4b, 0x14, 0x79, 0x09, 0x3c, 0xf6, 0x6a, 0xe5, + 0xa6, 0xdc, 0x2b, 0xd9, 0xd0, 0xda, 0xdf, 0xcf, 0xfd, 0xc1, 0x45, 0xc4, + 0x3b, 0xce, 0x01, 0xd9, 0x91, 0xdc, 0x4f, 0xdc, 0xae, 0xe3, 0x57, 0xe8, + 0x3d, 0xef, 0x3f, 0x07, 0x46, 0x24, 0xa0, 0x3d, 0x37, 0x4c, 0xd1, 0x49, + 0xaa, 0x47, 0x38, 0x4d, 0x79, 0x47, 0xed, 0x39, 0xa7, 0x29, 0x17, 0x16, + 0x0c, 0x08, 0xf1, 0xf7, 0x4e, 0xdf, 0xa9, 0xc6, 0x3b, 0xbe, 0x2d, 0xc5, + 0x2c, 0xcd, 0x2b, 0xce, 0xe0, 0xcc, 0x25, 0xce, 0x25, 0xd4, 0x99, 0xdc, + 0xcc, 0xda, 0x75, 0xd6, 0x4f, 0xdc, 0x54, 0xe7, 0x3b, 0xf2, 0xa4, 0xf8, + 0x3a, 0xf9, 0xeb, 0xfb, 0xfb, 0xf7, 0xf3, 0xf5, 0xd9, 0xf5, 0xca, 0xe9, + 0xcf, 0xe8, 0x39, 0xe7, 0x42, 0xe3, 0x71, 0xe8, 0xcc, 0xe8, 0x37, 0xe8, + 0x03, 0xf5, 0x8e, 0x07, 0xb3, 0x0d, 0xde, 0x13, 0xa4, 0x0c, 0x0e, 0xf9, + 0x72, 0xef, 0x8c, 0xee, 0x23, 0xfd, 0xcd, 0x07, 0x5a, 0x04, 0xbc, 0xfe, + 0x8a, 0x01, 0x20, 0x0e, 0xe4, 0x12, 0xa3, 0x12, 0x49, 0x0c, 0xd7, 0x02, + 0x48, 0x05, 0x0f, 0x07, 0x2e, 0x03, 0xac, 0xff, 0x47, 0xfe, 0x45, 0x04, + 0x85, 0x0d, 0xb4, 0x10, 0xd5, 0x0f, 0xa7, 0x14, 0xe1, 0x18, 0x3b, 0x18, + 0x31, 0x14, 0xd3, 0x03, 0x07, 0xef, 0xda, 0xe6, 0x36, 0xeb, 0xbd, 0xf4, + 0xca, 0xfb, 0x86, 0x00, 0x89, 0x02, 0x18, 0xfd, 0x9f, 0xf9, 0xa3, 0xf3, + 0x25, 0xec, 0x3c, 0xec, 0x6a, 0xee, 0x4a, 0xf8, 0x15, 0xf9, 0xa2, 0xf2, + 0x55, 0xfb, 0x3b, 0x08, 0x4d, 0x0f, 0x32, 0x0c, 0x83, 0x0a, 0xaa, 0x0d, + 0x15, 0x07, 0x95, 0xf7, 0xe2, 0xe7, 0x7a, 0xe4, 0xc9, 0xed, 0xf1, 0xf4, + 0x46, 0xef, 0xe2, 0xd9, 0x93, 0xc9, 0xab, 0xd2, 0x25, 0xea, 0x3c, 0x00, + 0x69, 0x0a, 0x4f, 0x0f, 0x6c, 0x1a, 0x7c, 0x27, 0x7a, 0x2d, 0x62, 0x28, + 0xb4, 0x1d, 0x26, 0x16, 0x83, 0x11, 0x03, 0x0c, 0x86, 0x07, 0x74, 0xf9, + 0xd4, 0xe8, 0xa3, 0xe4, 0xce, 0xe5, 0xa6, 0xe1, 0x7c, 0xd5, 0xd4, 0xcf, + 0x4b, 0xcf, 0x8f, 0xce, 0x1a, 0xcd, 0x68, 0xcf, 0x7a, 0xd9, 0xcd, 0xe5, + 0x2f, 0xf4, 0xdc, 0xff, 0xbf, 0x04, 0xfb, 0x06, 0x8f, 0x17, 0x66, 0x2c, + 0x71, 0x2f, 0x00, 0x28, 0xa6, 0x1e, 0xdd, 0x11, 0xf4, 0x06, 0xa1, 0xfa, + 0xc9, 0xdf, 0x4a, 0xc3, 0xa1, 0xb6, 0xb3, 0xb2, 0x9c, 0xa7, 0xb6, 0x9e, + 0x5e, 0x9b, 0xbe, 0x9f, 0x07, 0xad, 0x15, 0xb2, 0xa3, 0xb2, 0xe4, 0xb3, + 0xa8, 0xbc, 0x01, 0xcc, 0x70, 0xe3, 0x67, 0xfc, 0x94, 0x10, 0xea, 0x21, + 0x72, 0x2e, 0x0e, 0x3f, 0x7c, 0x4a, 0xe4, 0x51, 0x39, 0x51, 0x62, 0x42, + 0x9b, 0x2b, 0xb3, 0x1c, 0x16, 0x1e, 0x2f, 0x1b, 0x46, 0x18, 0x98, 0x0b, + 0x92, 0xee, 0xf2, 0xd9, 0xe7, 0xd0, 0x5b, 0xc8, 0x23, 0xbe, 0x4f, 0xba, + 0x32, 0xc0, 0x5b, 0xcb, 0x8b, 0xd7, 0x35, 0xde, 0x6a, 0xe0, 0x00, 0xeb, + 0x16, 0xf6, 0x45, 0xf6, 0x4e, 0xf3, 0x1c, 0xf2, 0x96, 0xf5, 0x0e, 0x06, + 0xaa, 0x18, 0x3f, 0x18, 0x64, 0x13, 0xa4, 0x1a, 0xa4, 0x1f, 0x5b, 0x1a, + 0x25, 0x0f, 0xa5, 0x0b, 0xf4, 0x0f, 0x93, 0x0d, 0x95, 0x06, 0xc1, 0x02, + 0xe6, 0x07, 0x52, 0x0d, 0x16, 0x11, 0x4f, 0x12, 0x28, 0x10, 0xe1, 0x13, + 0x1a, 0x18, 0xa9, 0x1e, 0x7f, 0x1d, 0xb1, 0x12, 0x62, 0x11, 0xe8, 0x13, + 0x54, 0x12, 0x00, 0x13, 0xd7, 0x0b, 0xd0, 0xff, 0xec, 0xf5, 0x14, 0xeb, + 0xdb, 0xef, 0x2c, 0xf5, 0xbf, 0xfc, 0x2a, 0x0c, 0xcb, 0x10, 0x6b, 0x17, + 0x3b, 0x1c, 0xe4, 0x14, 0xcc, 0x0b, 0x3b, 0xfc, 0xe7, 0xed, 0x55, 0xf7, + 0xa5, 0xfa, 0x36, 0xea, 0x54, 0xd8, 0x31, 0xd2, 0x03, 0xdc, 0x63, 0xe4, + 0x0b, 0xec, 0x0b, 0xf1, 0xc1, 0xf2, 0x14, 0xf7, 0x6a, 0xf9, 0x84, 0xf8, + 0x68, 0xf5, 0xeb, 0xe5, 0x87, 0xd8, 0x00, 0xdb, 0xea, 0xe2, 0x7f, 0xea, + 0xce, 0xe7, 0xbc, 0xe7, 0x6a, 0xf2, 0x41, 0xfe, 0xf4, 0x00, 0xab, 0xfe, + 0x66, 0xf1, 0x50, 0xe5, 0x75, 0xe4, 0x36, 0xde, 0x5d, 0xe4, 0xbd, 0xe4, + 0x4c, 0xe0, 0xe3, 0xdd, 0x3e, 0xda, 0x1c, 0xe7, 0x92, 0xfb, 0x1b, 0x0e, + 0x27, 0x1e, 0x54, 0x2e, 0x03, 0x31, 0xe2, 0x2f, 0xf7, 0x2a, 0xec, 0x1f, + 0x40, 0x15, 0xac, 0x0a, 0xa2, 0x05, 0x9f, 0x09, 0xc7, 0x12, 0x8d, 0x0e, + 0xd9, 0x0a, 0x0c, 0x00, 0x5d, 0xf7, 0x60, 0xf4, 0x98, 0xea, 0x90, 0xe8, + 0xf0, 0xd9, 0x3b, 0xce, 0x7b, 0xce, 0x3b, 0xc9, 0xfa, 0xc0, 0x39, 0xbe, + 0x53, 0xc0, 0x65, 0xbd, 0x4d, 0xc4, 0x21, 0xd7, 0xab, 0xea, 0xd1, 0xfb, + 0x32, 0x02, 0x62, 0x07, 0x99, 0x16, 0x4d, 0x22, 0x92, 0x23, 0x67, 0x1a, + 0x92, 0x0c, 0x18, 0xfd, 0x5d, 0xf4, 0xa1, 0xf9, 0x54, 0x02, 0xae, 0x00, + 0x73, 0xed, 0xd4, 0xdc, 0x9c, 0xd9, 0x67, 0xe2, 0x87, 0xe5, 0x76, 0xd9, + 0x59, 0xce, 0x88, 0xcc, 0xe5, 0xd6, 0x05, 0xdf, 0xbb, 0xdf, 0xac, 0xd9, + 0xf2, 0xd7, 0xdf, 0xe2, 0xf8, 0xed, 0xf9, 0xf7, 0x08, 0x05, 0xc3, 0x11, + 0x1a, 0x1b, 0xfa, 0x27, 0xf7, 0x32, 0x9d, 0x39, 0x37, 0x3f, 0xd9, 0x44, + 0x8a, 0x4c, 0xaa, 0x4f, 0x43, 0x52, 0xb6, 0x48, 0x31, 0x32, 0xcd, 0x26, + 0x1b, 0x20, 0xea, 0x1b, 0x00, 0x1c, 0x5b, 0x1d, 0x16, 0x28, 0xc9, 0x3a, + 0xc3, 0x4f, 0xe3, 0x5c, 0x73, 0x5f, 0xbf, 0x59, 0x0c, 0x4b, 0xb5, 0x3a, + 0x98, 0x2d, 0x55, 0x23, 0x68, 0x14, 0xe0, 0x03, 0xb7, 0xfc, 0x22, 0xf5, + 0x93, 0xea, 0xe2, 0xe6, 0x33, 0xe3, 0x7c, 0xde, 0xe1, 0xd9, 0xbe, 0xd4, + 0x9e, 0xd8, 0xd2, 0xe1, 0xa9, 0xed, 0x40, 0x04, 0x56, 0x1f, 0xc8, 0x3e, + 0xe3, 0x61, 0x38, 0x73, 0x14, 0x77, 0x56, 0x78, 0x4d, 0x76, 0x0c, 0x76, + 0xc9, 0x75, 0xb2, 0x74, 0x23, 0x72, 0x38, 0x65, 0x3d, 0x48, 0xaf, 0x28, + 0xa0, 0x0a, 0xf8, 0xf2, 0x97, 0xe4, 0xe6, 0xdd, 0xf0, 0xdf, 0x64, 0xdf, + 0x74, 0xdf, 0x05, 0xe2, 0xf9, 0xeb, 0xea, 0xf2, 0x7d, 0xec, 0x42, 0xe4, + 0x78, 0xe1, 0x0b, 0xec, 0x5d, 0xfb, 0x1c, 0x0e, 0xb9, 0x22, 0x6b, 0x30, + 0x56, 0x3a, 0xd7, 0x3b, 0x7b, 0x37, 0x74, 0x3a, 0x57, 0x3f, 0x39, 0x45, + 0xb0, 0x48, 0x41, 0x43, 0xc2, 0x3e, 0x13, 0x3a, 0x6c, 0x34, 0x37, 0x2e, + 0xcb, 0x2d, 0x37, 0x2c, 0xf0, 0x24, 0x64, 0x1f, 0xdd, 0x16, 0xc8, 0x0f, + 0x8a, 0x09, 0x36, 0x07, 0xb1, 0xfa, 0x48, 0xe5, 0x0f, 0xd8, 0x8d, 0xc9, + 0x7d, 0xc4, 0xfc, 0xc9, 0xf3, 0xd0, 0x01, 0xde, 0x57, 0xe8, 0xca, 0xea, + 0xb6, 0xee, 0x0a, 0xf3, 0xfb, 0xfa, 0x8f, 0x0e, 0x9d, 0x20, 0x1c, 0x29, + 0x7b, 0x2f, 0x49, 0x35, 0xd6, 0x41, 0x1d, 0x4b, 0x0d, 0x3f, 0x87, 0x30, + 0xf8, 0x26, 0x55, 0x1a, 0x92, 0x08, 0x1d, 0xf8, 0x50, 0xf3, 0xa1, 0xf0, + 0xee, 0xed, 0x3f, 0xf2, 0xdc, 0xf3, 0x92, 0xf1, 0x30, 0xed, 0x16, 0xe6, + 0xfe, 0xe7, 0x0d, 0xed, 0xa0, 0xef, 0x31, 0xf1, 0x5f, 0xf4, 0x63, 0xfe, + 0x4c, 0x0c, 0x3a, 0x20, 0xe5, 0x31, 0xfd, 0x39, 0x14, 0x37, 0x85, 0x2c, + 0xd1, 0x24, 0x60, 0x22, 0x03, 0x1f, 0x42, 0x23, 0xa2, 0x34, 0xd6, 0x40, + 0x01, 0x3e, 0x7a, 0x35, 0x09, 0x33, 0xde, 0x34, 0x25, 0x35, 0x8b, 0x28, + 0x18, 0x18, 0x0c, 0x08, 0x4b, 0xf3, 0xfc, 0xe8, 0x9a, 0xdc, 0xbe, 0xd1, + 0xdd, 0xcc, 0x50, 0xc2, 0x71, 0xbd, 0xee, 0xbb, 0xc7, 0xb7, 0xaa, 0xb8, + 0xe0, 0xbe, 0x55, 0xc1, 0xab, 0xb8, 0xba, 0xac, 0x5d, 0xaf, 0xa5, 0xc6, + 0xf4, 0xdb, 0x3f, 0xe5, 0xb5, 0xf7, 0x89, 0x0f, 0x9c, 0x30, 0x9f, 0x4f, + 0xc0, 0x57, 0x2b, 0x61, 0x74, 0x6b, 0xe9, 0x6e, 0x56, 0x70, 0xb8, 0x6d, + 0x60, 0x62, 0xd1, 0x4c, 0x13, 0x32, 0x2e, 0x1f, 0x24, 0x0e, 0x80, 0xf4, + 0x8a, 0xe0, 0xb2, 0xcc, 0x39, 0xc1, 0xda, 0xb9, 0xed, 0xb0, 0x9c, 0xb4, + 0xf3, 0xc0, 0x50, 0xd2, 0x98, 0xda, 0xc9, 0xdf, 0x88, 0xe7, 0x32, 0xf3, + 0xa8, 0x05, 0x82, 0x10, 0x90, 0x14, 0x73, 0x1b, 0x09, 0x25, 0xd3, 0x2d, + 0xda, 0x34, 0xba, 0x34, 0xb9, 0x30, 0xad, 0x2f, 0x94, 0x34, 0xcc, 0x39, + 0x9b, 0x39, 0x44, 0x33, 0xc2, 0x2a, 0x2a, 0x29, 0x89, 0x26, 0x76, 0x25, + 0x41, 0x25, 0x4c, 0x25, 0x59, 0x2c, 0x68, 0x35, 0xd3, 0x37, 0xda, 0x33, + 0xc7, 0x34, 0x1d, 0x2d, 0xc5, 0x26, 0x8f, 0x2b, 0xa3, 0x23, 0x53, 0x17, + 0xa5, 0x0a, 0xed, 0xfb, 0x6f, 0xef, 0xa8, 0xe3, 0x10, 0xe3, 0x0f, 0xee, + 0xcc, 0xf3, 0x4e, 0xf0, 0xec, 0xec, 0x39, 0xe7, 0xbd, 0xe3, 0xfe, 0xe8, + 0xd0, 0xef, 0xfd, 0xf7, 0x93, 0xf9, 0xba, 0xf4, 0x58, 0xfb, 0x5f, 0x08, + 0x96, 0x15, 0x5b, 0x1c, 0xe6, 0x13, 0xb9, 0x0a, 0x72, 0x09, 0x02, 0x0c, + 0x17, 0x0e, 0x50, 0x13, 0x29, 0x17, 0xc7, 0x10, 0x26, 0x04, 0x40, 0xfc, + 0x7b, 0xfe, 0xbb, 0xf7, 0xd2, 0xea, 0x07, 0xe3, 0xdf, 0xe3, 0xae, 0xf1, + 0x53, 0xfb, 0xaa, 0xfc, 0x9a, 0xfd, 0x17, 0xfe, 0x70, 0xf9, 0x4b, 0xf5, + 0xf6, 0xfa, 0x2c, 0x0b, 0x70, 0x1c, 0xc1, 0x24, 0xa4, 0x2b, 0xf9, 0x2e, + 0x45, 0x32, 0xc2, 0x3a, 0x3f, 0x3e, 0x84, 0x44, 0x31, 0x4a, 0xcc, 0x43, + 0xb7, 0x35, 0xa0, 0x24, 0xa6, 0x1f, 0xf3, 0x1d, 0x98, 0x14, 0x61, 0x0b, + 0xd6, 0xfc, 0x17, 0xed, 0x63, 0xdb, 0x35, 0xcb, 0x75, 0xbf, 0xa4, 0xb0, + 0x4f, 0xa7, 0x4e, 0xa5, 0x0e, 0xa4, 0xcc, 0xa3, 0x7c, 0xa6, 0x46, 0xb1, + 0xc9, 0xc1, 0x19, 0xce, 0x8f, 0xe3, 0x4d, 0xfb, 0xaf, 0x0e, 0xe4, 0x20, + 0x62, 0x30, 0xbb, 0x43, 0x9d, 0x4b, 0xf3, 0x52, 0x0f, 0x5f, 0x5a, 0x6a, + 0xb9, 0x67, 0xef, 0x58, 0xb2, 0x4e, 0xdd, 0x3b, 0x3e, 0x2e, 0x35, 0x16, + 0x42, 0xfa, 0xd6, 0xe8, 0x80, 0xd6, 0x3b, 0xcd, 0x15, 0xc3, 0xde, 0xc0, + 0xed, 0xc2, 0x93, 0xc2, 0x66, 0xc6, 0xc1, 0xcf, 0x58, 0xd9, 0x26, 0xdd, + 0x32, 0xe5, 0x7b, 0xef, 0x12, 0xfc, 0x11, 0x04, 0x11, 0x05, 0xdb, 0x04, + 0xd4, 0x0c, 0xf1, 0x1b, 0xc9, 0x21, 0x7d, 0x20, 0x98, 0x23, 0xfe, 0x2c, + 0x1d, 0x23, 0x19, 0x14, 0xf6, 0x19, 0x57, 0x21, 0x05, 0x26, 0xb1, 0x21, + 0xa0, 0x1f, 0xdd, 0x2a, 0x7b, 0x33, 0x59, 0x35, 0xb1, 0x27, 0x57, 0x18, + 0xde, 0x16, 0xdf, 0x1c, 0xfd, 0x1b, 0x05, 0x0b, 0x6e, 0xfe, 0x33, 0xf4, + 0x74, 0xea, 0x9f, 0xe7, 0xb3, 0xe1, 0xd8, 0xd7, 0xf9, 0xcc, 0x11, 0xcb, + 0xe5, 0xd0, 0x38, 0xd9, 0x6f, 0xe1, 0xd6, 0xe7, 0xfb, 0xe7, 0x6e, 0xdc, + 0x63, 0xd5, 0xa5, 0xd3, 0xc6, 0xd5, 0xc4, 0xe3, 0x16, 0xee, 0xf2, 0xee, + 0xc2, 0xeb, 0xc1, 0xe6, 0x3d, 0xe5, 0x64, 0xe1, 0x01, 0xdb, 0x8a, 0xd5, + 0xe8, 0xd0, 0xc5, 0xce, 0x0f, 0xd1, 0xaa, 0xdd, 0x28, 0xef, 0xbe, 0x03, + 0x4a, 0x17, 0xe4, 0x22, 0xbb, 0x26, 0x3c, 0x22, 0x2e, 0x1b, 0x75, 0x10, + 0x92, 0x01, 0xe0, 0xf3, 0x85, 0xea, 0xa6, 0xe5, 0x4b, 0xeb, 0x3f, 0xef, + 0xb4, 0xea, 0x13, 0xea, 0xf5, 0xe8, 0x9c, 0xe4, 0xf5, 0xd9, 0x7f, 0xd6, + 0x69, 0xdb, 0x0b, 0xdf, 0x62, 0xde, 0x53, 0xd5, 0xf7, 0xd7, 0x0f, 0xdd, + 0x48, 0xe4, 0x55, 0xf4, 0xa0, 0xf8, 0x4b, 0xf8, 0x5c, 0xfe, 0x19, 0x06, + 0x9e, 0x08, 0x83, 0x04, 0x33, 0xfb, 0x49, 0xf1, 0x30, 0xe9, 0x02, 0xe8, + 0x92, 0xe4, 0x62, 0xd7, 0x7f, 0xd4, 0xad, 0xde, 0xb3, 0xe4, 0xc9, 0xe3, + 0xd1, 0xec, 0x44, 0xf5, 0x0f, 0xf5, 0x6d, 0xf3, 0x92, 0xef, 0xd8, 0x00, + 0x37, 0x1a, 0x25, 0x24, 0x3f, 0x2e, 0xc3, 0x30, 0x63, 0x23, 0x1b, 0x19, + 0xdd, 0x09, 0x6e, 0xf3, 0x32, 0xec, 0x36, 0xe2, 0x4b, 0xd4, 0xca, 0xcc, + 0xcf, 0xc7, 0x16, 0xd6, 0xee, 0xe0, 0x47, 0xe2, 0xba, 0xea, 0xa0, 0xea, + 0x40, 0xec, 0x8b, 0xef, 0x96, 0xe9, 0x2f, 0xe8, 0xb2, 0xea, 0xc6, 0xea, + 0x6f, 0xee, 0xf6, 0xf3, 0x54, 0xf0, 0x50, 0xee, 0x6c, 0xf9, 0x90, 0x0d, + 0xef, 0x17, 0xed, 0x0c, 0x53, 0xfc, 0x5b, 0xed, 0x7e, 0xe9, 0x2d, 0xea, + 0xd8, 0xe0, 0x6a, 0xd9, 0x97, 0xdc, 0x12, 0xe5, 0x2c, 0xe6, 0x5c, 0xe8, + 0xb8, 0xf0, 0x23, 0x01, 0x53, 0x15, 0x23, 0x1f, 0xaa, 0x27, 0x13, 0x29, + 0x5d, 0x21, 0x98, 0x19, 0x61, 0x13, 0xd1, 0x0e, 0xa0, 0x0b, 0x5a, 0x0a, + 0x2f, 0x05, 0x26, 0xfb, 0x76, 0xf0, 0xe0, 0xeb, 0x09, 0xe8, 0xdd, 0xde, + 0x61, 0xd4, 0x92, 0xcb, 0x0e, 0xc9, 0xa3, 0xcc, 0x62, 0xcf, 0xe7, 0xd0, + 0xba, 0xd6, 0x4d, 0xda, 0x06, 0xe0, 0xa3, 0xea, 0x01, 0xfc, 0x48, 0x13, + 0xed, 0x1f, 0x43, 0x2c, 0xfb, 0x37, 0xfc, 0x33, 0x0f, 0x27, 0x81, 0x18, + 0xe5, 0x0c, 0x57, 0x0a, 0x68, 0x0d, 0xe7, 0x0d, 0x99, 0x06, 0xfe, 0xf6, + 0xda, 0xef, 0xf0, 0xf1, 0x5f, 0xeb, 0x64, 0xdf, 0x99, 0xd8, 0xaf, 0xd6, + 0x8d, 0xd0, 0x43, 0xcc, 0x4a, 0xce, 0x4a, 0xd1, 0x28, 0xda, 0xb6, 0xd7, + 0x6b, 0xce, 0x1f, 0xcc, 0xeb, 0xc2, 0x2b, 0xc2, 0x63, 0xc8, 0xcc, 0xcc, + 0xbb, 0xd2, 0x34, 0xd9, 0x31, 0xe6, 0xdf, 0xf5, 0x19, 0x0c, 0x3a, 0x25, + 0x03, 0x30, 0xc2, 0x2c, 0xf6, 0x2f, 0x86, 0x2f, 0x6d, 0x20, 0xe6, 0x0f, + 0x30, 0xfd, 0x2a, 0xf2, 0xbd, 0xe9, 0x43, 0xe5, 0xa8, 0xe5, 0xa7, 0xe2, + 0x1e, 0xe5, 0x17, 0xe1, 0x23, 0xd8, 0x97, 0xd8, 0xe7, 0xe1, 0xcc, 0xed, + 0x2a, 0xfa, 0xfc, 0x03, 0x6c, 0x05, 0x0d, 0x0a, 0x65, 0x18, 0xf2, 0x2a, + 0xa9, 0x39, 0x7c, 0x40, 0xb4, 0x46, 0xa0, 0x4a, 0xa1, 0x51, 0xee, 0x5c, + 0x80, 0x5c, 0x63, 0x56, 0x1d, 0x51, 0x6a, 0x4f, 0x5b, 0x4d, 0x57, 0x48, + 0xcc, 0x43, 0x08, 0x3b, 0xcf, 0x3d, 0xc5, 0x49, 0x8e, 0x4f, 0xa3, 0x47, + 0xc4, 0x38, 0x0f, 0x34, 0x68, 0x37, 0xa3, 0x39, 0x8e, 0x2d, 0x3f, 0x23, + 0xcf, 0x1c, 0xa9, 0x12, 0xbe, 0x0c, 0xb7, 0x05, 0x8d, 0x06, 0xae, 0x04, + 0x5f, 0x00, 0xf3, 0xff, 0x1a, 0xfd, 0xe4, 0xfc, 0x94, 0xfb, 0xa1, 0xfa, + 0xbc, 0xf9, 0x46, 0xf9, 0x6a, 0xf6, 0x04, 0xfc, 0x39, 0x08, 0x65, 0x12, + 0x7d, 0x1f, 0xf5, 0x22, 0x97, 0x29, 0xd5, 0x2e, 0xc1, 0x2e, 0x5f, 0x37, + 0xe2, 0x3f, 0xd6, 0x47, 0x4c, 0x4e, 0x9f, 0x50, 0x45, 0x49, 0x66, 0x3f, + 0x17, 0x38, 0x48, 0x39, 0x8a, 0x44, 0xb9, 0x49, 0x0c, 0x4d, 0xc0, 0x46, + 0x65, 0x35, 0x59, 0x2d, 0x91, 0x28, 0x2f, 0x12, 0x80, 0xf4, 0x2a, 0xe2, + 0x9b, 0xdd, 0x2f, 0xe6, 0x4d, 0xe9, 0x32, 0xe5, 0x6b, 0xe2, 0xef, 0xe1, + 0x20, 0xea, 0xe2, 0xef, 0xc4, 0xf2, 0xe2, 0xff, 0x06, 0x0f, 0xbe, 0x1b, + 0x32, 0x30, 0xbf, 0x46, 0xc0, 0x52, 0x65, 0x52, 0x4b, 0x53, 0x02, 0x59, + 0xc3, 0x57, 0x39, 0x56, 0x6a, 0x57, 0x03, 0x58, 0x65, 0x53, 0x6b, 0x4a, + 0xb2, 0x41, 0x0b, 0x30, 0x15, 0x16, 0x6c, 0xf7, 0x52, 0xdf, 0x65, 0xd0, + 0xd8, 0xc7, 0x6f, 0xc7, 0xb6, 0xc7, 0xbf, 0xc6, 0x5a, 0xc6, 0xdf, 0xd1, + 0x66, 0xdc, 0xdd, 0xe8, 0x86, 0xfa, 0x75, 0x01, 0x38, 0x0c, 0xbb, 0x16, + 0x19, 0x17, 0x3c, 0x07, 0x46, 0xf9, 0x29, 0xf3, 0x5e, 0xe7, 0x23, 0xdb, + 0x13, 0xd1, 0x2f, 0xd2, 0x19, 0xd4, 0x8b, 0xd9, 0x06, 0xde, 0xd7, 0xe4, + 0x56, 0xed, 0x67, 0xed, 0x87, 0xf1, 0x2c, 0xea, 0x4e, 0xe6, 0xb7, 0xe7, + 0x4f, 0xed, 0x67, 0xfb, 0x8f, 0x06, 0x33, 0x0f, 0x59, 0x0f, 0x26, 0x1d, + 0x19, 0x2c, 0x13, 0x30, 0xc2, 0x2f, 0xce, 0x25, 0xf9, 0x1b, 0xb2, 0x17, + 0x9c, 0x16, 0xea, 0x15, 0xfa, 0x19, 0x4d, 0x19, 0x08, 0x1a, 0xe4, 0x14, + 0x3a, 0x0d, 0xc0, 0x10, 0x4a, 0x14, 0xef, 0x1a, 0x1f, 0x13, 0x04, 0x09, + 0x62, 0x0c, 0x5d, 0x13, 0xd8, 0x1b, 0x36, 0x20, 0xd5, 0x20, 0x37, 0x1b, + 0xdf, 0x13, 0x89, 0x0c, 0xb5, 0x0e, 0x25, 0x12, 0x79, 0x0f, 0x51, 0x0a, + 0x4c, 0x01, 0x33, 0x00, 0x11, 0xfc, 0x48, 0xf0, 0x62, 0xe4, 0xc2, 0xde, + 0xf3, 0xdf, 0xd6, 0xe1, 0xd9, 0xe1, 0x50, 0xe1, 0xb1, 0xe2, 0xac, 0xe3, + 0x4e, 0xea, 0x6f, 0xf5, 0x75, 0x02, 0x04, 0x07, 0x7c, 0x06, 0x58, 0x0c, + 0x37, 0x13, 0xd9, 0x17, 0x37, 0x17, 0xbe, 0x1e, 0xe5, 0x27, 0x85, 0x22, + 0xd3, 0x18, 0xfc, 0x11, 0x9a, 0x0e, 0xab, 0x09, 0x59, 0x03, 0xcb, 0x06, + 0xcb, 0x0f, 0xc6, 0x15, 0x78, 0x1c, 0xd7, 0x1e, 0x58, 0x16, 0xb7, 0x0b, + 0xc9, 0x0a, 0xd5, 0x06, 0x77, 0x04, 0x48, 0x0d, 0x57, 0x18, 0x81, 0x24, + 0x4f, 0x22, 0xd5, 0x1d, 0xd8, 0x1a, 0xa2, 0x12, 0xa4, 0x13, 0xce, 0x15, + 0x4e, 0x11, 0xf9, 0x12, 0x89, 0x1d, 0x27, 0x1d, 0x2a, 0x1b, 0xd5, 0x17, + 0xc9, 0x12, 0xf9, 0x1b, 0x0a, 0x1d, 0xf1, 0x12, 0xd7, 0x0a, 0x17, 0xfd, + 0x4d, 0xf1, 0xdd, 0xf5, 0x7a, 0x01, 0x20, 0x0d, 0xdf, 0x0d, 0xa1, 0x06, + 0x15, 0x06, 0x6f, 0x04, 0x66, 0xfe, 0x6f, 0xf3, 0x42, 0xf4, 0x0f, 0xfa, + 0x2b, 0xfb, 0x5a, 0xfb, 0x0d, 0xea, 0x9a, 0xe4, 0x5d, 0xf1, 0xef, 0xf6, + 0xe0, 0xfa, 0x6b, 0xf8, 0x5b, 0xeb, 0xb1, 0xe0, 0x1f, 0xde, 0x72, 0xd9, + 0x28, 0xd1, 0x73, 0xc9, 0xa2, 0xc5, 0xfc, 0xd1, 0x84, 0xdd, 0x96, 0xdd, + 0xf6, 0xe7, 0x0f, 0xf2, 0x70, 0xf8, 0x91, 0x00, 0xbf, 0x03, 0x75, 0x0b, + 0xca, 0x11, 0xeb, 0x1b, 0xae, 0x26, 0xb8, 0x26, 0x55, 0x29, 0xd1, 0x22, + 0xb6, 0x1b, 0xd9, 0x18, 0x7b, 0x03, 0x03, 0xed, 0xad, 0xe1, 0x9e, 0xd9, + 0xe2, 0xd4, 0x57, 0xd7, 0x15, 0xda, 0x3a, 0xdd, 0x67, 0xed, 0x19, 0xfa, + 0x73, 0x01, 0xbb, 0x05, 0x43, 0x08, 0xb6, 0x15, 0x07, 0x1d, 0x4b, 0x20, + 0x2b, 0x22, 0xe7, 0x27, 0xfa, 0x34, 0xb7, 0x3e, 0xb7, 0x4d, 0x0c, 0x4f, + 0xcd, 0x45, 0xfa, 0x42, 0x6e, 0x3f, 0x3d, 0x3c, 0xf2, 0x2f, 0x14, 0x1c, + 0xee, 0x0c, 0xda, 0x03, 0x5a, 0xf8, 0x5f, 0xec, 0x9f, 0xe0, 0xb9, 0xd3, + 0xcf, 0xca, 0xfa, 0xc2, 0x14, 0xbd, 0x23, 0xb9, 0x1d, 0xb6, 0xf8, 0xb3, + 0xe2, 0xb8, 0xad, 0xbf, 0x3a, 0xc3, 0x4d, 0xca, 0x27, 0xd2, 0x0c, 0xdd, + 0x5d, 0xe7, 0x58, 0xef, 0xec, 0xf9, 0xf0, 0x08, 0xca, 0x1d, 0x27, 0x2e, + 0x49, 0x2f, 0xf7, 0x30, 0x55, 0x38, 0x89, 0x38, 0x75, 0x35, 0xf5, 0x31, + 0x23, 0x36, 0x1d, 0x38, 0x9e, 0x34, 0x54, 0x2f, 0x42, 0x26, 0x5d, 0x1e, + 0x0b, 0x0c, 0xd1, 0xfd, 0xda, 0xf5, 0x90, 0xf3, 0xf8, 0xf9, 0x28, 0xfe, + 0x08, 0x09, 0x52, 0x0c, 0x3c, 0x04, 0x0e, 0xfc, 0xcb, 0xf1, 0x16, 0xea, + 0xdd, 0xea, 0x4e, 0xed, 0x1b, 0xee, 0x47, 0xef, 0xca, 0xec, 0x89, 0xec, + 0xa1, 0xef, 0x60, 0xf1, 0x4f, 0xed, 0xda, 0xe4, 0xc5, 0xe3, 0xc3, 0xef, + 0x48, 0xfc, 0x97, 0xfd, 0x70, 0xff, 0x30, 0x08, 0xad, 0x12, 0x62, 0x16, + 0xb8, 0x0b, 0x95, 0xff, 0x20, 0xfb, 0xfc, 0xf8, 0x1b, 0x00, 0x58, 0x00, + 0xcd, 0xf3, 0xec, 0xe7, 0xb8, 0xdc, 0x21, 0xea, 0x6c, 0xf8, 0xf8, 0x00, + 0x1c, 0x0a, 0xe2, 0xf8, 0x89, 0xf2, 0x46, 0xe7, 0x2e, 0xce, 0x0b, 0xc3, + 0x55, 0xb0, 0xd4, 0xa0, 0x0d, 0x99, 0xfa, 0x98, 0x4c, 0x9e, 0xb9, 0xa2, + 0x6c, 0xa7, 0x55, 0xa9, 0x05, 0xb1, 0x4a, 0xb5, 0xeb, 0xbc, 0x5c, 0xca, + 0x78, 0xd2, 0x23, 0xde, 0x3e, 0xe5, 0x2b, 0xe9, 0xe4, 0xf0, 0x11, 0xfb, + 0x4e, 0x0f, 0xae, 0x25, 0x8a, 0x44, 0x92, 0x65, 0x10, 0x6b, 0xc8, 0x69, + 0x85, 0x66, 0xba, 0x58, 0xc7, 0x44, 0x69, 0x22, 0x48, 0x0a, 0x70, 0xfc, + 0xc8, 0xe9, 0xc8, 0xdd, 0xfd, 0xd1, 0xde, 0xc8, 0xa2, 0xc7, 0xfd, 0xc8, + 0x77, 0xce, 0x93, 0xd6, 0x23, 0xde, 0xf2, 0xdc, 0x0f, 0xd9, 0x79, 0xda, + 0xb9, 0xdb, 0xfb, 0xe4, 0x9d, 0xf1, 0x2d, 0xf6, 0x12, 0xf2, 0x7e, 0xea, + 0xb0, 0xe9, 0x67, 0xef, 0x44, 0xf1, 0x53, 0xeb, 0x86, 0xe2, 0xbf, 0xda, + 0xf2, 0xe0, 0x06, 0xf2, 0xa1, 0xfa, 0x69, 0xfc, 0x46, 0x00, 0x5d, 0x08, + 0xa9, 0x16, 0x7c, 0x1a, 0x58, 0x10, 0x28, 0x09, 0x98, 0x01, 0x41, 0x04, + 0xa4, 0x07, 0x7a, 0x05, 0x19, 0x08, 0x85, 0x08, 0x00, 0x0c, 0xb9, 0x0a, + 0xaa, 0x0f, 0x28, 0x16, 0x3c, 0x0e, 0x08, 0x06, 0x1f, 0x01, 0x0d, 0x00, + 0x8c, 0xf6, 0xa4, 0xea, 0x35, 0xe7, 0xda, 0xe4, 0xf5, 0xe8, 0x63, 0xf1, + 0x6e, 0xfb, 0x19, 0x0b, 0x5c, 0x1b, 0x86, 0x28, 0x99, 0x31, 0xc7, 0x37, + 0x22, 0x37, 0x12, 0x2d, 0x34, 0x22, 0x8d, 0x16, 0x9f, 0x0d, 0x74, 0x0c, + 0x85, 0x0f, 0x0d, 0x12, 0x1f, 0x12, 0x04, 0x16, 0xe2, 0x1b, 0x8d, 0x20, + 0x95, 0x25, 0xd4, 0x27, 0x9c, 0x20, 0xf1, 0x0d, 0x8f, 0xfb, 0xc8, 0xf7, + 0x45, 0x00, 0xe3, 0x05, 0x85, 0x05, 0x7c, 0x05, 0x20, 0x0e, 0x13, 0x1f, + 0x7d, 0x26, 0x30, 0x20, 0xa3, 0x0d, 0x43, 0xf7, 0xa8, 0xe9, 0xcd, 0xdd, + 0xc2, 0xd0, 0xf6, 0xba, 0x91, 0xa8, 0x34, 0xb1, 0x5f, 0xc5, 0xdb, 0xd5, + 0xca, 0xe0, 0x73, 0xde, 0xd5, 0xd6, 0xb8, 0xd8, 0xb4, 0xd4, 0x7e, 0xc6, + 0xe8, 0xbe, 0xf7, 0xc3, 0x34, 0xc9, 0xbf, 0xcf, 0xc5, 0xe1, 0xe8, 0xef, + 0x91, 0xf7, 0xa5, 0xf4, 0x65, 0xee, 0xae, 0xeb, 0x65, 0xe1, 0x0c, 0xd9, + 0x7a, 0xd1, 0x0f, 0xc8, 0xcf, 0xc1, 0x05, 0xc2, 0x36, 0xca, 0x4d, 0xd1, + 0xbe, 0xd3, 0xd7, 0xdb, 0x29, 0xe4, 0x1c, 0xef, 0x96, 0xfd, 0xef, 0x03, + 0x54, 0x0a, 0xef, 0x0f, 0x04, 0x15, 0x96, 0x0c, 0xa5, 0xf9, 0x3a, 0xf2, + 0x82, 0xee, 0x6e, 0xee, 0x87, 0xf2, 0x57, 0xf3, 0x53, 0xef, 0x1e, 0xf2, + 0x86, 0xfa, 0x61, 0xfd, 0x4a, 0xff, 0x9e, 0xff, 0x0a, 0xfe, 0x35, 0x00, + 0xce, 0xff, 0x52, 0x03, 0x46, 0x10, 0xad, 0x1a, 0xa1, 0x28, 0x68, 0x2f, + 0x54, 0x2f, 0xe3, 0x2f, 0xcd, 0x2c, 0x41, 0x2c, 0xc2, 0x2f, 0x93, 0x39, + 0x36, 0x3d, 0x75, 0x3b, 0x50, 0x30, 0x6d, 0x26, 0x9d, 0x1e, 0x8b, 0x03, + 0xbc, 0xf2, 0xa3, 0xe8, 0x0c, 0xe1, 0x16, 0xdc, 0x30, 0xce, 0xff, 0xc8, + 0x54, 0xc9, 0x2f, 0xd3, 0xf3, 0xdc, 0x04, 0xe0, 0xb6, 0xed, 0x97, 0xfc, + 0x8f, 0x06, 0xbf, 0x07, 0xe1, 0x00, 0x19, 0x01, 0xc9, 0x0f, 0x83, 0x25, + 0x47, 0x3a, 0x96, 0x4c, 0x53, 0x56, 0x75, 0x5b, 0x51, 0x5e, 0x65, 0x5f, + 0x5f, 0x64, 0x40, 0x69, 0xe9, 0x6c, 0xd7, 0x6b, 0x30, 0x63, 0x2b, 0x53, + 0x6e, 0x43, 0x18, 0x40, 0x8b, 0x40, 0xba, 0x3a, 0x73, 0x34, 0x82, 0x32, + 0xd4, 0x33, 0xcf, 0x37, 0xeb, 0x36, 0xfb, 0x36, 0x39, 0x41, 0xc1, 0x3c, + 0x30, 0x2f, 0x08, 0x2c, 0xb3, 0x28, 0xc0, 0x27, 0x0c, 0x24, 0x78, 0x20, + 0x30, 0x22, 0xdf, 0x22, 0x25, 0x27, 0x2e, 0x2a, 0xd9, 0x2b, 0xa4, 0x26, + 0x44, 0x1e, 0x72, 0x1a, 0x29, 0x12, 0x18, 0x05, 0x3f, 0xee, 0x8f, 0xd9, + 0x1d, 0xd2, 0x0c, 0xd2, 0x2f, 0xdf, 0x95, 0xf6, 0x90, 0x10, 0x13, 0x21, + 0x04, 0x1e, 0x30, 0x17, 0x03, 0x13, 0x2f, 0x07, 0x54, 0xfa, 0x4e, 0xf4, + 0x1f, 0xf1, 0x30, 0xf0, 0x1e, 0xf4, 0xfd, 0xfc, 0xbd, 0x02, 0x1d, 0x01, + 0x0c, 0x00, 0xa4, 0xf6, 0xec, 0xe8, 0xa3, 0xdf, 0xc4, 0xd9, 0x82, 0xd8, + 0x26, 0xd1, 0x76, 0xd2, 0xbe, 0xd7, 0xbf, 0xda, 0xf7, 0xe0, 0x1a, 0xe2, + 0x89, 0xec, 0x73, 0xf7, 0x33, 0xfc, 0x54, 0x04, 0xcf, 0x10, 0x13, 0x1f, + 0xe0, 0x31, 0xcf, 0x45, 0x9c, 0x50, 0xb5, 0x55, 0xab, 0x54, 0x45, 0x57, + 0x83, 0x5b, 0xd3, 0x51, 0xab, 0x44, 0x22, 0x41, 0x16, 0x37, 0x51, 0x27, + 0xec, 0x18, 0x41, 0x0b, 0x8f, 0x09, 0x20, 0x05, 0xf5, 0xfd, 0x0a, 0xef, + 0x11, 0xda, 0x41, 0xd2, 0x08, 0xd4, 0x38, 0xd7, 0x03, 0xcd, 0x0f, 0xc0, + 0x90, 0xb9, 0x7d, 0xb7, 0x93, 0xbf, 0x34, 0xcf, 0x53, 0xe0, 0xea, 0xf3, + 0x79, 0x01, 0x6a, 0x10, 0xd8, 0x26, 0xf4, 0x2f, 0x7a, 0x34, 0x54, 0x33, + 0xfb, 0x31, 0xd2, 0x2c, 0x2a, 0x1f, 0x4c, 0x21, 0x43, 0x2a, 0xd5, 0x2b, + 0x9b, 0x20, 0x11, 0x15, 0x95, 0x0d, 0x58, 0x0e, 0x32, 0x10, 0x76, 0x00, + 0x67, 0xef, 0xff, 0xdf, 0x9d, 0xd7, 0x1d, 0xde, 0x0a, 0xe7, 0x92, 0xe6, + 0xb9, 0xe5, 0x42, 0xea, 0xef, 0xf0, 0x16, 0xfc, 0x5c, 0x01, 0x82, 0x02, + 0xa2, 0x0a, 0x4a, 0x1d, 0xda, 0x2b, 0x07, 0x32, 0x61, 0x35, 0xbf, 0x37, + 0xf1, 0x38, 0xb3, 0x31, 0xb5, 0x2d, 0x9d, 0x29, 0xce, 0x2c, 0xe2, 0x35, + 0x7d, 0x35, 0x6d, 0x36, 0xea, 0x2f, 0x13, 0x2d, 0xe6, 0x38, 0x09, 0x41, + 0x7f, 0x36, 0x0f, 0x26, 0xef, 0x20, 0x84, 0x1b, 0xf3, 0x1a, 0xf9, 0x1a, + 0x64, 0x16, 0xbd, 0x16, 0xdb, 0x0f, 0x93, 0x09, 0x73, 0x0c, 0x41, 0x0a, + 0xa4, 0x07, 0xa6, 0x04, 0x43, 0xfc, 0x7a, 0xf1, 0xe0, 0xe3, 0x2d, 0xdc, + 0x0f, 0xdb, 0x6b, 0xda, 0xe0, 0xe2, 0xfc, 0xf3, 0x3b, 0x01, 0x3d, 0x11, + 0xf1, 0x23, 0x6a, 0x33, 0x68, 0x37, 0xf3, 0x26, 0x99, 0x15, 0x29, 0x06, + 0x25, 0xfc, 0xab, 0xfa, 0x73, 0xf2, 0x57, 0xeb, 0xe5, 0xe6, 0x28, 0xdd, + 0x65, 0xda, 0xc3, 0xdc, 0x07, 0xde, 0x1f, 0xe5, 0xd7, 0xed, 0x05, 0xf4, + 0xc5, 0xed, 0xe0, 0xe6, 0x1f, 0xe7, 0x3e, 0xe6, 0xad, 0xe8, 0xa0, 0xe8, + 0x70, 0xf0, 0x35, 0xfd, 0x14, 0x05, 0x17, 0x15, 0x08, 0x26, 0xa6, 0x2c, + 0xf3, 0x31, 0x51, 0x2c, 0x04, 0x22, 0x69, 0x1b, 0x2f, 0x19, 0xda, 0x29, + 0x86, 0x33, 0x82, 0x31, 0x73, 0x27, 0xe4, 0x16, 0x94, 0x0d, 0x3b, 0x0d, + 0xd6, 0x11, 0x4b, 0x12, 0xe2, 0x14, 0x88, 0x12, 0x9f, 0x14, 0x21, 0x19, + 0xab, 0x17, 0x16, 0x17, 0xde, 0x0e, 0x68, 0x08, 0x91, 0x02, 0x31, 0xfa, + 0x9f, 0xf3, 0x4e, 0xe7, 0x70, 0xe4, 0x71, 0xf0, 0xe7, 0xf1, 0xde, 0xf1, + 0xcf, 0xf4, 0x7c, 0xf9, 0x67, 0x07, 0x93, 0x16, 0x36, 0x1b, 0xc4, 0x0c, + 0x7b, 0x02, 0x98, 0x04, 0x64, 0x0f, 0x39, 0x13, 0x8f, 0x09, 0xb4, 0x01, + 0xaf, 0xf9, 0x20, 0xf0, 0x84, 0xe2, 0xbb, 0xd7, 0x40, 0xd3, 0x54, 0xd3, + 0x74, 0xda, 0x7b, 0xe1, 0x39, 0xdd, 0xcc, 0xda, 0x3c, 0xd2, 0xfd, 0xc5, + 0x6d, 0xc4, 0xb5, 0xc0, 0x64, 0xc6, 0xaf, 0xc7, 0x6f, 0xce, 0x5d, 0xde, + 0xf4, 0xef, 0x5b, 0x0b, 0x17, 0x1f, 0xe2, 0x33, 0x1b, 0x43, 0x72, 0x4a, + 0x6d, 0x4f, 0x97, 0x4e, 0xde, 0x52, 0x46, 0x5c, 0xb3, 0x61, 0xd7, 0x62, + 0xec, 0x54, 0x95, 0x3e, 0xe1, 0x2c, 0x06, 0x1a, 0xb8, 0x0d, 0xa2, 0xfa, + 0x1a, 0xef, 0x5e, 0xea, 0x28, 0xe4, 0x06, 0xe5, 0x67, 0xd7, 0xcc, 0xca, + 0x08, 0xc5, 0xbc, 0xba, 0xd0, 0xa9, 0x61, 0x9b, 0x43, 0x96, 0xb9, 0x96, + 0xbc, 0x9c, 0xc8, 0xa3, 0x7a, 0xb1, 0x2b, 0xc7, 0xcf, 0xe3, 0xbf, 0x04, + 0x12, 0x15, 0xd7, 0x13, 0xf9, 0x18, 0x0a, 0x1b, 0xfa, 0x21, 0x94, 0x2e, + 0xd2, 0x37, 0x37, 0x4c, 0xaa, 0x5f, 0xd5, 0x6b, 0xdc, 0x6d, 0xe7, 0x6c, + 0x43, 0x5d, 0x9b, 0x41, 0x7a, 0x28, 0x42, 0x07, 0xb6, 0xe2, 0x70, 0xbd, + 0x54, 0xa7, 0xa7, 0x9b, 0xc0, 0x95, 0x8d, 0x96, 0x56, 0x9c, 0xc6, 0xa5, + 0xdc, 0xb0, 0xea, 0xbf, 0x43, 0xc4, 0x11, 0xc7, 0x86, 0xc9, 0x4a, 0xd0, + 0x61, 0xd7, 0x99, 0xdd, 0x4f, 0xee, 0x69, 0xfb, 0x85, 0x0a, 0x61, 0x20, + 0x93, 0x33, 0x34, 0x39, 0xdc, 0x3d, 0x4c, 0x42, 0xb4, 0x3f, 0x0d, 0x3e, + 0xd8, 0x3b, 0x24, 0x3a, 0xc1, 0x36, 0x4c, 0x36, 0xc7, 0x33, 0x1e, 0x2e, + 0xb1, 0x26, 0x07, 0x28, 0xe1, 0x2f, 0x4a, 0x2e, 0xda, 0x2a, 0x21, 0x2d, + 0x10, 0x32, 0x14, 0x29, 0xd9, 0x1b, 0x59, 0x0a, 0xfa, 0xf8, 0x32, 0xf2, + 0x7c, 0xe1, 0x4c, 0xd0, 0x2f, 0xc0, 0xf9, 0xb0, 0x78, 0xb3, 0x43, 0xbd, + 0x93, 0xbf, 0x72, 0xbf, 0xd0, 0xb9, 0x72, 0xb5, 0x21, 0xc1, 0x77, 0xcd, + 0xee, 0xce, 0xdc, 0xc7, 0x54, 0xc4, 0x8b, 0xc7, 0xf6, 0xcd, 0x9a, 0xe3, + 0x69, 0xfd, 0x86, 0x08, 0x25, 0x12, 0x5e, 0x22, 0x6b, 0x2f, 0x9c, 0x2e, + 0xc1, 0x25, 0x34, 0x25, 0x84, 0x21, 0xb5, 0x17, 0x5a, 0x0c, 0xd2, 0xfd, + 0x0c, 0xfd, 0x4c, 0x06, 0xf1, 0x08, 0xec, 0xfd, 0x8c, 0xed, 0x9b, 0xe8, + 0x60, 0xe4, 0xfd, 0xd9, 0xa9, 0xd4, 0xf2, 0xcd, 0xbc, 0xc4, 0x44, 0xc6, + 0x47, 0xd1, 0x3d, 0xe1, 0x49, 0xea, 0x2f, 0xe9, 0x31, 0xe9, 0xba, 0xe7, + 0x41, 0xe5, 0xfc, 0xdb, 0xec, 0xdd, 0xa6, 0xf1, 0x0f, 0xfe, 0xe8, 0x0c, + 0xd7, 0x17, 0xc3, 0x1a, 0x6c, 0x21, 0x5e, 0x2e, 0x37, 0x36, 0xa5, 0x33, + 0x73, 0x2b, 0x02, 0x14, 0x37, 0x03, 0x07, 0xf5, 0x39, 0xde, 0xf2, 0xc3, + 0x90, 0xab, 0x26, 0xa3, 0x72, 0x9e, 0xbd, 0xa1, 0xe1, 0xb5, 0xd0, 0xda, + 0xf5, 0xf6, 0xf2, 0x04, 0xcc, 0x0f, 0x90, 0x10, 0xd7, 0x13, 0x5a, 0x14, + 0xea, 0x1f, 0xad, 0x2a, 0x12, 0x23, 0x1c, 0x1a, 0xb1, 0x18, 0x58, 0x27, + 0x1e, 0x28, 0x28, 0x1b, 0xb1, 0x0a, 0x0a, 0xf2, 0x04, 0xdd, 0x16, 0xc4, + 0x22, 0xb2, 0x31, 0xaa, 0x09, 0xaa, 0x19, 0xb0, 0x3c, 0xb1, 0xe3, 0xb8, + 0xa4, 0xc4, 0x35, 0xcd, 0x73, 0xd5, 0xc2, 0xdf, 0x13, 0xe9, 0x24, 0xf2, + 0xf5, 0x00, 0xe9, 0x0b, 0xa7, 0x0a, 0x86, 0x01, 0x16, 0x01, 0xfe, 0x02, + 0xb9, 0x05, 0xba, 0x14, 0x05, 0x16, 0x32, 0x09, 0x4c, 0x02, 0x4b, 0x00, + 0x8a, 0xfa, 0x9b, 0xf3, 0x6f, 0xf2, 0x54, 0xfa, 0xe8, 0x0d, 0x41, 0x1c, + 0x1f, 0x2c, 0x82, 0x3b, 0x7c, 0x44, 0xf1, 0x4d, 0x62, 0x49, 0x53, 0x46, + 0x4d, 0x44, 0xf6, 0x3c, 0xfe, 0x35, 0x4d, 0x29, 0x28, 0x21, 0x82, 0x17, + 0xe4, 0x06, 0x9e, 0xfb, 0x98, 0xf7, 0x3f, 0xf0, 0x7a, 0xe1, 0xfa, 0xd0, + 0xd6, 0xc6, 0xa4, 0xc7, 0x2c, 0xca, 0x85, 0xc7, 0xb2, 0xc5, 0x28, 0xcb, + 0x57, 0xd7, 0x41, 0xe3, 0xec, 0xf0, 0xb9, 0x0a, 0xfa, 0x1b, 0x14, 0x27, + 0x52, 0x30, 0x19, 0x24, 0xb0, 0x1b, 0x08, 0x16, 0xf9, 0x0c, 0x5a, 0x11, + 0x58, 0x1c, 0x41, 0x21, 0xf1, 0x25, 0x42, 0x32, 0xa2, 0x3a, 0x91, 0x45, + 0x24, 0x47, 0xe3, 0x37, 0x88, 0x20, 0x1e, 0x00, 0xa1, 0xe8, 0x5a, 0xde, + 0xff, 0xd7, 0x50, 0xd0, 0x35, 0xd0, 0x87, 0xd8, 0xc1, 0xe0, 0xe4, 0xe5, + 0xfa, 0xed, 0x92, 0xfb, 0xe5, 0xfe, 0x83, 0xfc, 0x93, 0xf4, 0x18, 0xef, + 0xfa, 0xeb, 0x36, 0xe4, 0xda, 0xea, 0x9a, 0xfa, 0xe3, 0x0a, 0xcb, 0x16, + 0xe1, 0x1e, 0x43, 0x25, 0x07, 0x2b, 0x51, 0x30, 0x6d, 0x27, 0xf4, 0x12, + 0x14, 0xfe, 0x67, 0xf6, 0xa6, 0xfc, 0x86, 0x0b, 0xec, 0x1a, 0x96, 0x22, + 0x85, 0x2a, 0xec, 0x29, 0xf0, 0x23, 0x7c, 0x23, 0x08, 0x1e, 0x27, 0x21, + 0xc4, 0x2b, 0xcb, 0x25, 0x23, 0x1d, 0x7e, 0x16, 0x01, 0x18, 0xc2, 0x22, + 0x4d, 0x1e, 0x10, 0x15, 0x5c, 0x0f, 0x72, 0x05, 0x2d, 0xf2, 0xf2, 0xdb, + 0xaf, 0xcc, 0x03, 0xcc, 0xdc, 0xd8, 0x2f, 0xe0, 0xf5, 0xe6, 0x15, 0xee, + 0x6d, 0xf4, 0xc5, 0x01, 0x95, 0x13, 0xc0, 0x26, 0xc9, 0x35, 0x68, 0x3a, + 0x43, 0x35, 0xe0, 0x35, 0x44, 0x33, 0x48, 0x2d, 0x0d, 0x2f, 0x5b, 0x30, + 0xbb, 0x35, 0x34, 0x3c, 0x12, 0x40, 0x6d, 0x37, 0xc7, 0x2d, 0xaf, 0x28, + 0xd4, 0x16, 0x2d, 0x04, 0x1f, 0xee, 0x2d, 0xdd, 0xda, 0xd4, 0x1c, 0xd5, + 0x99, 0xe4, 0xd6, 0xf1, 0xf4, 0xff, 0x08, 0x0c, 0x7a, 0x17, 0xe9, 0x2b, + 0x13, 0x49, 0xd0, 0x63, 0x44, 0x6e, 0x74, 0x6f, 0xdd, 0x6e, 0xc0, 0x6f, + 0x24, 0x6e, 0x31, 0x69, 0x6f, 0x5f, 0xf3, 0x55, 0xd4, 0x4a, 0x75, 0x3c, + 0x9b, 0x2b, 0x3f, 0x17, 0xed, 0x15, 0xa2, 0x1a, 0x8c, 0x14, 0x7f, 0x06, + 0x6c, 0xf8, 0x65, 0xf2, 0xdc, 0xf0, 0xe6, 0xf3, 0x62, 0xef, 0x66, 0xef, + 0xee, 0xf8, 0x30, 0xfb, 0x7e, 0xf7, 0xec, 0xf5, 0x89, 0x03, 0xad, 0x1b, + 0x33, 0x30, 0xce, 0x3e, 0x85, 0x41, 0x1e, 0x38, 0x9d, 0x2e, 0x05, 0x28, + 0x7d, 0x23, 0x17, 0x24, 0x8a, 0x29, 0x66, 0x26, 0x63, 0x14, 0x0e, 0x02, + 0xcc, 0xfb, 0x51, 0xfd, 0xfd, 0xfe, 0x54, 0xfe, 0xf6, 0xf6, 0x88, 0xee, + 0xb5, 0xec, 0x71, 0xf3, 0x22, 0xf9, 0x41, 0x01, 0x09, 0x06, 0x7d, 0xfc, + 0x8b, 0xfb, 0xd5, 0xfa, 0xd2, 0xf5, 0xaf, 0xf9, 0xbe, 0x04, 0x95, 0x10, + 0x03, 0x19, 0x24, 0x1b, 0xd8, 0x17, 0x16, 0x1a, 0xe2, 0x1c, 0x4e, 0x1c, + 0xca, 0x0f, 0xa5, 0x04, 0x89, 0x02, 0x22, 0xfa, 0x46, 0xed, 0x01, 0xd9, + 0xa1, 0xc9, 0x04, 0xc5, 0x32, 0xc7, 0x9f, 0xca, 0xd7, 0xcc, 0xef, 0xd0, + 0xac, 0xd4, 0xb3, 0xd7, 0xb3, 0xdd, 0x4e, 0xf0, 0x18, 0x04, 0xab, 0x0c, + 0x66, 0x0b, 0x12, 0x01, 0x01, 0xf5, 0xb2, 0xf0, 0x43, 0xf5, 0x08, 0xfe, + 0xde, 0xfe, 0x2e, 0xfe, 0xd6, 0x0b, 0x87, 0x23, 0x4b, 0x35, 0xe1, 0x36, + 0x35, 0x35, 0xcd, 0x2c, 0xa5, 0x26, 0x6a, 0x25, 0xac, 0x24, 0x4d, 0x2c, + 0x83, 0x34, 0xa4, 0x43, 0xe8, 0x4b, 0xed, 0x4c, 0xa1, 0x44, 0xf3, 0x35, + 0x9b, 0x28, 0x0c, 0x16, 0xa6, 0x03, 0xe5, 0xe5, 0x91, 0xd2, 0x0c, 0xc9, + 0x34, 0xc7, 0x8a, 0xcf, 0x76, 0xce, 0xef, 0xd0, 0xf3, 0xd5, 0x78, 0xdb, + 0xdc, 0xd7, 0xe9, 0xc8, 0x6e, 0xbb, 0xac, 0xb7, 0xa1, 0xb6, 0x03, 0xae, + 0xce, 0xab, 0x75, 0xaf, 0xcd, 0xbf, 0x65, 0xd9, 0x9d, 0xf0, 0x61, 0x06, + 0x29, 0x15, 0x35, 0x20, 0xb5, 0x25, 0x07, 0x23, 0x7c, 0x22, 0x6f, 0x31, + 0x94, 0x45, 0x8e, 0x51, 0x2f, 0x5d, 0xb4, 0x66, 0xc4, 0x6b, 0xaa, 0x6d, + 0x4b, 0x6b, 0x4c, 0x69, 0xa6, 0x65, 0x54, 0x5b, 0xdb, 0x4f, 0x02, 0x42, + 0xde, 0x30, 0xaa, 0x24, 0x3f, 0x19, 0x63, 0x0d, 0x03, 0x08, 0x0a, 0x01, + 0xdc, 0xf1, 0xe8, 0xe4, 0x0c, 0xd9, 0x0f, 0xd0, 0x25, 0xd4, 0x29, 0xd9, + 0xb6, 0xd9, 0x99, 0xd7, 0x51, 0xe0, 0x3f, 0xf6, 0xe3, 0xff, 0x78, 0x0d, + 0x9c, 0x1d, 0xd6, 0x24, 0x07, 0x2f, 0x2a, 0x2d, 0xac, 0x31, 0x08, 0x3c, + 0xdb, 0x3e, 0x45, 0x4f, 0x76, 0x5f, 0x3d, 0x6b, 0xfb, 0x6f, 0x32, 0x6c, + 0xe8, 0x67, 0x7f, 0x5a, 0x19, 0x3f, 0x13, 0x19, 0xb4, 0xfc, 0x6c, 0xee, + 0x03, 0xea, 0x1e, 0xeb, 0xdb, 0xe6, 0x19, 0xde, 0xad, 0xd5, 0xea, 0xcf, + 0xfc, 0xcb, 0x21, 0xcd, 0x0e, 0xcd, 0x98, 0xc6, 0x19, 0xc0, 0xf7, 0xbf, + 0xe1, 0xc1, 0x24, 0xc8, 0x0d, 0xd5, 0x86, 0xde, 0x1d, 0xe5, 0x54, 0xe5, + 0x9c, 0xea, 0x6e, 0xf4, 0x0a, 0xfe, 0xc4, 0x13, 0xeb, 0x29, 0x37, 0x41, + 0x73, 0x56, 0x52, 0x5f, 0x53, 0x62, 0x85, 0x62, 0x1d, 0x64, 0xc7, 0x64, + 0x4c, 0x63, 0xf3, 0x5f, 0xbe, 0x57, 0x56, 0x44, 0x4e, 0x29, 0x28, 0x0f, + 0x07, 0xec, 0x1c, 0xcb, 0xa2, 0xb6, 0x6e, 0xaf, 0xd1, 0xb5, 0xcc, 0xba, + 0xaf, 0xc2, 0x00, 0xcb, 0x81, 0xcd, 0x13, 0xcc, 0x23, 0xcb, 0x1d, 0xcb, + 0xb3, 0xcc, 0x08, 0xd7, 0xd9, 0xde, 0xdb, 0xdf, 0x68, 0xe3, 0x5c, 0xf3, + 0xbc, 0x0b, 0x9f, 0x22, 0xd8, 0x2c, 0x70, 0x2e, 0x89, 0x2c, 0xcb, 0x23, + 0x61, 0x20, 0x15, 0x0e, 0xfb, 0xea, 0xc5, 0xd8, 0x8a, 0xd4, 0xe4, 0xca, + 0x6b, 0xc7, 0x86, 0xc9, 0x79, 0xc2, 0xe8, 0xbe, 0x31, 0xbc, 0x47, 0xb5, + 0x7c, 0xb2, 0x90, 0xb9, 0x7e, 0xc0, 0xd3, 0xc5, 0x63, 0xd2, 0x98, 0xe2, + 0x8c, 0xee, 0x9a, 0xf7, 0xd6, 0x01, 0xb0, 0xfb, 0x07, 0xf5, 0xb3, 0xf8, + 0x22, 0xf9, 0x6e, 0xf4, 0x30, 0xe6, 0x30, 0xdc, 0x93, 0xd5, 0x6d, 0xcd, + 0x7a, 0xd0, 0xf2, 0xd5, 0xac, 0xd9, 0xd3, 0xe5, 0x1a, 0xf2, 0x03, 0xf9, + 0x39, 0xfe, 0x81, 0x07, 0x23, 0x10, 0xe5, 0x14, 0x65, 0x16, 0xd8, 0x13, + 0x3b, 0x1e, 0x17, 0x2e, 0xb6, 0x3d, 0x80, 0x49, 0x08, 0x50, 0x30, 0x59, + 0xeb, 0x58, 0xaa, 0x53, 0x2a, 0x43, 0xca, 0x25, 0x14, 0x16, 0x9a, 0x0a, + 0x76, 0xf3, 0x24, 0xe4, 0x62, 0xd8, 0xe4, 0xd1, 0x77, 0xd8, 0x18, 0xdb, + 0x97, 0xdf, 0x9c, 0xe1, 0x09, 0xda, 0x54, 0xd5, 0x0c, 0xd9, 0x22, 0xdd, + 0x03, 0xe3, 0xfd, 0xec, 0xa5, 0xf9, 0x0c, 0x07, 0xba, 0x0e, 0x32, 0x1b, + 0xdc, 0x29, 0xdc, 0x33, 0x00, 0x34, 0x90, 0x2a, 0x36, 0x21, 0xf8, 0x13, + 0x62, 0xff, 0xf4, 0xe1, 0x58, 0xca, 0xa3, 0xbf, 0xf1, 0xb8, 0xe5, 0xb4, + 0x62, 0xb5, 0xee, 0xb2, 0xe0, 0xa7, 0x6c, 0xaa, 0x69, 0xb2, 0x92, 0xaf, + 0xbd, 0xaf, 0x0e, 0xb3, 0xf1, 0xbb, 0x0b, 0xce, 0x64, 0xe0, 0xb2, 0xeb, + 0x19, 0x00, 0xbd, 0x17, 0x65, 0x29, 0xb6, 0x3e, 0x11, 0x49, 0x96, 0x53, + 0x62, 0x59, 0x8a, 0x54, 0x2c, 0x52, 0x55, 0x4a, 0x77, 0x40, 0x06, 0x32, + 0xf1, 0x1e, 0xdf, 0x0c, 0x10, 0xf7, 0x26, 0xe4, 0xdf, 0xe2, 0xeb, 0xe5, + 0xb0, 0xef, 0x86, 0xf7, 0x01, 0xf1, 0x30, 0xf6, 0xf8, 0xfa, 0x28, 0x02, + 0x1d, 0x08, 0x09, 0x05, 0xfc, 0x0d, 0x29, 0x12, 0x0e, 0x0c, 0xd4, 0x08, + 0xd1, 0x07, 0x42, 0x0b, 0x3c, 0x0e, 0xfb, 0x18, 0x03, 0x2c, 0x69, 0x26, + 0x09, 0x14, 0x29, 0x02, 0x14, 0xfc, 0xf1, 0x00, 0x95, 0xf7, 0x9f, 0xe7, + 0x3b, 0xd4, 0x91, 0xc5, 0x5c, 0xb5, 0x57, 0xa9, 0xa1, 0xa3, 0xf4, 0xa0, + 0x9c, 0xa7, 0x70, 0xaa, 0x5c, 0xab, 0x47, 0xa7, 0x39, 0xab, 0x6c, 0xb9, + 0x57, 0xc7, 0x34, 0xcd, 0xae, 0xca, 0x74, 0xcb, 0x7e, 0xcc, 0x14, 0xd5, + 0x3b, 0xdf, 0xdd, 0xe8, 0x80, 0xf3, 0xf5, 0xfc, 0x71, 0x15, 0x61, 0x29, + 0xab, 0x2d, 0xad, 0x3a, 0x7a, 0x3a, 0xdb, 0x32, 0x12, 0x31, 0x17, 0x27, + 0x43, 0x27, 0x19, 0x25, 0x0e, 0x28, 0x28, 0x2d, 0x8d, 0x1d, 0x42, 0x0e, + 0x88, 0x00, 0xe8, 0xf6, 0x4d, 0xee, 0xb3, 0xe3, 0xdc, 0xe2, 0x30, 0xe5, + 0x44, 0xf0, 0x50, 0xfb, 0x95, 0xfa, 0xa1, 0xfb, 0xd8, 0xf6, 0x9f, 0xf6, + 0x1c, 0xf8, 0x20, 0xf5, 0x27, 0xf5, 0x97, 0xe9, 0xc5, 0xe2, 0x4e, 0xe4, + 0x75, 0xea, 0xdc, 0xef, 0x7b, 0xec, 0x4f, 0xee, 0x08, 0xf8, 0xbb, 0x09, + 0x99, 0x19, 0xfd, 0x17, 0x8b, 0x0c, 0x88, 0x03, 0xa5, 0xf8, 0xbb, 0xee, + 0x31, 0xe4, 0x42, 0xe9, 0x5b, 0xf4, 0x58, 0xf6, 0xa0, 0x00, 0xb9, 0xfc, + 0x12, 0xf8, 0xe6, 0xf2, 0xd0, 0xe8, 0xd7, 0xeb, 0xa3, 0xe7, 0x7a, 0xea, + 0x45, 0xee, 0x96, 0xe6, 0x15, 0xdb, 0x16, 0xca, 0x1a, 0xc9, 0xff, 0xd0, + 0x06, 0xd3, 0xae, 0xd0, 0xf0, 0xcb, 0x0c, 0xd9, 0x67, 0xee, 0x61, 0xf7, + 0xe3, 0xf7, 0xc0, 0xf9, 0xd9, 0x09, 0xbb, 0x1a, 0x61, 0x1b, 0x60, 0x11, + 0x47, 0xfb, 0xf6, 0xe2, 0xb8, 0xe0, 0x3f, 0xf4, 0x5b, 0x12, 0xb3, 0x2d, + 0xe2, 0x46, 0x71, 0x60, 0xe3, 0x6f, 0x09, 0x78, 0x9f, 0x76, 0x75, 0x72, + 0xd4, 0x69, 0x59, 0x61, 0xe2, 0x58, 0x0c, 0x42, 0x39, 0x34, 0x2b, 0x28, + 0x33, 0x1e, 0x96, 0x1d, 0x9c, 0x12, 0xd9, 0x03, 0xe5, 0xf1, 0xd5, 0xdd, + 0x33, 0xcf, 0xa8, 0xc5, 0xa4, 0xbc, 0xd9, 0xba, 0xf4, 0xbb, 0xc2, 0xba, + 0xfb, 0xc1, 0x3f, 0xcd, 0x59, 0xde, 0x4d, 0xe9, 0x74, 0xea, 0x3b, 0xf2, + 0xd0, 0xfa, 0x77, 0x00, 0x88, 0x05, 0xa6, 0x10, 0x53, 0x25, 0xbe, 0x3c, + 0x2b, 0x54, 0xa8, 0x60, 0x20, 0x5f, 0x0d, 0x5f, 0x76, 0x5f, 0x88, 0x5e, + 0xfe, 0x58, 0x82, 0x4a, 0xa2, 0x37, 0x64, 0x22, 0x70, 0x16, 0xde, 0x0c, + 0x8b, 0x05, 0xfe, 0x0c, 0x43, 0x0e, 0x84, 0x0d, 0xc1, 0x10, 0x41, 0x0f, + 0x5b, 0x14, 0x8c, 0x12, 0xc5, 0x0a, 0x52, 0x00, 0x7d, 0xec, 0x5a, 0xe5, + 0xec, 0xe3, 0xd3, 0xe5, 0x7a, 0xed, 0xfa, 0xf3, 0x8d, 0xfe, 0x44, 0x03, + 0xf3, 0x0a, 0xf3, 0x20, 0x1d, 0x3a, 0x5e, 0x4c, 0x11, 0x58, 0xbb, 0x57, + 0xa4, 0x52, 0xa8, 0x59, 0xb8, 0x5d, 0x66, 0x5f, 0xb7, 0x64, 0xc0, 0x69, + 0xcf, 0x6d, 0x13, 0x6a, 0xe4, 0x66, 0x3c, 0x62, 0xda, 0x5e, 0xf8, 0x61, + 0xa4, 0x61, 0x5d, 0x5c, 0x60, 0x4c, 0xc3, 0x2f, 0x0c, 0x12, 0x30, 0x0d, + 0x5c, 0x0f, 0xad, 0x05, 0x6e, 0x02, 0x97, 0xfe, 0x84, 0x05, 0x91, 0x12, + 0xe8, 0x19, 0x0e, 0x1d, 0x3e, 0x19, 0x4f, 0x1a, 0x77, 0x16, 0xb8, 0x0a, + 0x13, 0xfb, 0x3e, 0xeb, 0xee, 0xe0, 0x73, 0xe0, 0x71, 0xe1, 0x9e, 0xe1, + 0x6d, 0xe9, 0x25, 0xeb, 0xb0, 0xee, 0xcd, 0xf0, 0x40, 0xe8, 0xbf, 0xe4, + 0xbb, 0xeb, 0xf0, 0xf6, 0x74, 0x01, 0xaf, 0x0c, 0x20, 0x15, 0x13, 0x1f, + 0x5a, 0x28, 0xc5, 0x2b, 0x18, 0x2c, 0xc4, 0x28, 0xe4, 0x24, 0x71, 0x28, + 0xcd, 0x2a, 0xa9, 0x1e, 0x3e, 0x11, 0x46, 0x09, 0x32, 0x04, 0x8f, 0x01, + 0x1d, 0x02, 0x3c, 0x08, 0xb7, 0x0b, 0x37, 0x0f, 0x5c, 0x17, 0x0d, 0x26, + 0x1f, 0x37, 0x28, 0x3c, 0x68, 0x3a, 0x0d, 0x2e, 0xd3, 0x26, 0x20, 0x31, + 0xc0, 0x35, 0x43, 0x31, 0x96, 0x22, 0x1a, 0x1e, 0x4e, 0x1b, 0x21, 0x14, + 0x9c, 0x11, 0x9b, 0x01, 0x6b, 0xf7, 0x5d, 0xe0, 0xc6, 0xc4, 0x4b, 0xba, + 0xd9, 0xac, 0xa3, 0xa8, 0x4b, 0xa6, 0xfb, 0xab, 0xd1, 0xc1, 0xbf, 0xd4, + 0xd5, 0xd7, 0x6b, 0xdb, 0xa9, 0xe8, 0x50, 0xe9, 0x58, 0xea, 0xf9, 0xec, + 0x75, 0xe8, 0x73, 0xe8, 0x65, 0xe1, 0x86, 0xd7, 0x6d, 0xd6, 0x65, 0xdb, + 0x12, 0xe8, 0xe3, 0xf1, 0x3b, 0xfb, 0x8a, 0x01, 0x59, 0x04, 0x8d, 0x07, + 0xac, 0xfd, 0x08, 0xf9, 0x2c, 0xf7, 0x53, 0xfc, 0x90, 0x0d, 0x68, 0x17, + 0x6d, 0x22, 0x21, 0x24, 0x0b, 0x25, 0x08, 0x31, 0xba, 0x3f, 0xe1, 0x4a, + 0x69, 0x52, 0x7a, 0x57, 0xa0, 0x52, 0xbd, 0x4f, 0x11, 0x49, 0xa2, 0x3f, + 0xd4, 0x31, 0x5d, 0x1e, 0x66, 0x17, 0x9e, 0x11, 0x7a, 0x0c, 0xe0, 0x02, + 0x91, 0xf3, 0x15, 0xef, 0xb2, 0xee, 0xc3, 0xf5, 0x4c, 0xfb, 0x16, 0xf5, + 0xc6, 0xfa, 0x19, 0x07, 0xa2, 0x13, 0xd5, 0x20, 0x65, 0x22, 0x2a, 0x25, + 0x3f, 0x2e, 0x0d, 0x34, 0xee, 0x2c, 0xda, 0x22, 0x60, 0x24, 0xd5, 0x23, + 0x7b, 0x1c, 0xd6, 0x17, 0xa4, 0x15, 0xb8, 0x13, 0x68, 0x12, 0x28, 0x09, + 0x82, 0xfe, 0xe7, 0xf5, 0x43, 0xed, 0xc6, 0xe6, 0x7b, 0xd8, 0x27, 0xcd, + 0x8d, 0xcb, 0xa5, 0xd5, 0x2d, 0xe7, 0x51, 0xf5, 0x24, 0x06, 0xaf, 0x0c, + 0xd1, 0x0b, 0x17, 0x06, 0xc2, 0xf1, 0x6a, 0xe2, 0xf2, 0xdf, 0xba, 0xe4, + 0x00, 0xee, 0x89, 0xf4, 0x17, 0xf7, 0xaf, 0xf5, 0xdf, 0xea, 0x0b, 0xe1, + 0xb2, 0xdd, 0xf3, 0xe2, 0x7b, 0xf1, 0x57, 0xf4, 0x2f, 0xeb, 0x89, 0xe2, + 0xcf, 0xee, 0x76, 0x0a, 0x80, 0x19, 0x9a, 0x17, 0x13, 0x0a, 0xfc, 0x03, + 0x25, 0x0e, 0x26, 0x1e, 0xfb, 0x1b, 0x73, 0x12, 0x50, 0x18, 0x40, 0x28, + 0xfe, 0x39, 0xa4, 0x40, 0x96, 0x3d, 0xed, 0x31, 0xa2, 0x2f, 0x9d, 0x3e, + 0xc4, 0x4a, 0xb2, 0x45, 0x25, 0x32, 0xb0, 0x29, 0x5f, 0x2f, 0xfe, 0x2c, + 0x40, 0x1c, 0x55, 0x0e, 0x01, 0x0c, 0xaf, 0x16, 0x69, 0x1c, 0x4d, 0x18, + 0x75, 0x17, 0x6f, 0x13, 0xe7, 0x0d, 0x01, 0xff, 0xe6, 0xe5, 0x9c, 0xcd, + 0x9c, 0xc2, 0x34, 0xc0, 0xa9, 0xb7, 0x18, 0xb5, 0x68, 0xba, 0x40, 0xc3, + 0xf6, 0xcc, 0x46, 0xda, 0xb2, 0xe5, 0x46, 0xe7, 0x5c, 0xe9, 0x30, 0xe7, + 0xc9, 0xe8, 0xf2, 0xeb, 0x1c, 0xec, 0xc4, 0xf9, 0xa0, 0x04, 0x52, 0x06, + 0x3a, 0x08, 0xaa, 0x0d, 0xd4, 0x0e, 0x2d, 0x0a, 0xe5, 0xfe, 0x2a, 0xf3, + 0xd9, 0x04, 0x07, 0x16, 0x71, 0x19, 0xd7, 0x16, 0x73, 0x0f, 0x2a, 0x10, + 0x90, 0x0d, 0x57, 0x0d, 0xa9, 0x06, 0x26, 0xfe, 0xe2, 0xf6, 0x32, 0xed, + 0x90, 0xec, 0x12, 0xec, 0x33, 0xeb, 0x2b, 0xe8, 0xb2, 0xe4, 0xa0, 0xe2, + 0xb2, 0xe5, 0x55, 0xe8, 0x33, 0xe0, 0xf2, 0xd9, 0x4c, 0xdd, 0x22, 0xe7, + 0x1a, 0xf9, 0x31, 0x05, 0xc2, 0x00, 0xb8, 0xfd, 0x41, 0x03, 0xdf, 0x08, + 0x13, 0xfe, 0x1c, 0xf0, 0x8f, 0xf1, 0x46, 0xf8, 0x64, 0x00, 0x38, 0x01, + 0x8d, 0xf5, 0xfc, 0xe7, 0xd8, 0xe6, 0x91, 0xf0, 0x17, 0xf7, 0x0a, 0xfa, + 0x88, 0xfd, 0x36, 0xfc, 0xf1, 0xfe, 0x80, 0xfc, 0xa4, 0xea, 0xaf, 0xde, + 0x19, 0xd7, 0x9c, 0xd3, 0x2b, 0xd8, 0x81, 0xd8, 0x6f, 0xca, 0xfe, 0xbd, + 0x37, 0xbb, 0x65, 0xb5, 0x3e, 0xb1, 0x0a, 0xa6, 0xf4, 0x9d, 0x83, 0xa1, + 0x1c, 0xa3, 0x2b, 0xa3, 0xb0, 0xa1, 0x00, 0xb1, 0x33, 0xcb, 0xe7, 0xdb, + 0xa3, 0xe0, 0xd0, 0xda, 0x08, 0xdb, 0x18, 0xdf, 0xbf, 0xee, 0x7b, 0xfe, + 0xfc, 0xfe, 0x68, 0x01, 0xb8, 0xfe, 0xdc, 0x04, 0xcc, 0x0f, 0xb9, 0x1a, + 0xc3, 0x27, 0x33, 0x29, 0xe7, 0x35, 0x18, 0x40, 0x5c, 0x2e, 0xd6, 0x17, + 0x48, 0x0a, 0x38, 0x01, 0xca, 0xf7, 0x14, 0xe5, 0x12, 0xd9, 0x24, 0xd5, + 0xb4, 0xcd, 0x74, 0xcc, 0xcc, 0xcf, 0xeb, 0xcc, 0x35, 0xc3, 0x61, 0xc6, + 0x47, 0xcb, 0x0e, 0xd4, 0x9a, 0xe4, 0x93, 0xf4, 0x93, 0x0d, 0x77, 0x1f, + 0x3d, 0x33, 0x52, 0x48, 0xa6, 0x58, 0x3a, 0x66, 0xbd, 0x69, 0xa0, 0x6a, + 0xd0, 0x63, 0x21, 0x59, 0xa9, 0x4f, 0x78, 0x42, 0x8d, 0x38, 0xcd, 0x33, + 0x15, 0x2a, 0x1f, 0x21, 0x9c, 0x18, 0x1d, 0x06, 0x03, 0xea, 0xbe, 0xcd, + 0x7b, 0xbd, 0x67, 0xbd, 0xf1, 0xbe, 0x2a, 0xb5, 0x1a, 0xb3, 0x1b, 0xb4, + 0x80, 0xb3, 0x47, 0xb4, 0xc1, 0xb6, 0x16, 0xc1, 0xc3, 0xc5, 0x3e, 0xcc, + 0xb2, 0xd5, 0xb6, 0xd5, 0xc7, 0xd0, 0x6f, 0xd8, 0x96, 0xeb, 0x84, 0xff, + 0xfd, 0x07, 0x4d, 0x03, 0x80, 0x0b, 0x12, 0x22, 0x88, 0x47, 0x90, 0x63, + 0x80, 0x6b, 0x9f, 0x74, 0x77, 0x78, 0xf2, 0x79, 0xf5, 0x78, 0xcb, 0x78, + 0x7a, 0x75, 0x96, 0x6e, 0xc4, 0x5d, 0x05, 0x3c, 0xbb, 0x26, 0x3f, 0x19, + 0x93, 0x08, 0xe6, 0xf7, 0x05, 0xe2, 0xa1, 0xcb, 0xb1, 0xb6, 0x3d, 0xae, + 0x44, 0xb3, 0xb1, 0xb4, 0x47, 0xb9, 0xd4, 0xc1, 0x00, 0xc8, 0xeb, 0xd3, + 0x6e, 0xd8, 0x18, 0xd0, 0x38, 0xca, 0xc6, 0xc7, 0xde, 0xc6, 0xfc, 0xc3, + 0x4e, 0xcd, 0xa2, 0xef, 0x9a, 0x1c, 0xec, 0x4b, 0x70, 0x66, 0x25, 0x6b, + 0x2b, 0x67, 0xa3, 0x5a, 0x9c, 0x45, 0x03, 0x1b, 0x16, 0xf7, 0xd5, 0xe3, + 0x65, 0xe0, 0xe2, 0xeb, 0x1e, 0xec, 0x0d, 0xea, 0x0c, 0xe8, 0x39, 0xe3, + 0xde, 0xd7, 0x92, 0xce, 0x20, 0xc8, 0x21, 0xbd, 0x3f, 0xb6, 0x6a, 0xb0, + 0x99, 0xb0, 0x47, 0xad, 0xff, 0xa9, 0x3e, 0xb1, 0xff, 0xba, 0xca, 0xc7, + 0x26, 0xd3, 0x95, 0xd8, 0x18, 0xe6, 0x13, 0xf7, 0x53, 0xfc, 0x78, 0xff, + 0xb5, 0xfd, 0x3b, 0x02, 0x66, 0x0b, 0xe8, 0x0b, 0x7a, 0x10, 0x45, 0x15, + 0x59, 0x1a, 0x86, 0x1d, 0x06, 0x19, 0x02, 0x12, 0xea, 0x0c, 0x81, 0x10, + 0x76, 0x19, 0x71, 0x1b, 0x9d, 0x1a, 0x50, 0x19, 0x9d, 0x14, 0xac, 0x0c, + 0x41, 0xff, 0xa2, 0xf2, 0xbc, 0xe6, 0x75, 0xe3, 0x80, 0xe4, 0x33, 0xdd, + 0x48, 0xd7, 0xb0, 0xd5, 0x5c, 0xd7, 0x72, 0xd3, 0x77, 0xc9, 0x4c, 0xbb, + 0x32, 0xb3, 0xad, 0xc3, 0xf9, 0xd2, 0x53, 0xdb, 0xec, 0xe5, 0xef, 0xe7, + 0x1a, 0xed, 0xe0, 0xee, 0xf6, 0xe9, 0xe3, 0xf3, 0x5e, 0xff, 0x77, 0xfb, + 0xeb, 0xf5, 0xb1, 0xf3, 0x07, 0xfa, 0xe6, 0xfe, 0x0c, 0xf4, 0x6c, 0xf8, + 0xd6, 0x0b, 0x8f, 0x1d, 0x56, 0x29, 0x81, 0x34, 0x39, 0x4b, 0xe7, 0x4e, + 0xec, 0x37, 0x2a, 0x1a, 0x3b, 0x06, 0xf1, 0x10, 0xd6, 0x29, 0x3d, 0x34, + 0xb0, 0x37, 0x05, 0x36, 0x9d, 0x34, 0x85, 0x41, 0x3d, 0x4b, 0x3a, 0x47, + 0x36, 0x3a, 0x48, 0x2c, 0x8e, 0x16, 0x62, 0xff, 0x90, 0xfb, 0x21, 0xf8, + 0x13, 0xe6, 0x16, 0xd9, 0xdc, 0xdb, 0xa9, 0xf1, 0xab, 0x19, 0xae, 0x32, + 0x54, 0x40, 0x8e, 0x49, 0x62, 0x4e, 0x6f, 0x5a, 0xbe, 0x5f, 0xf3, 0x61, + 0x66, 0x5f, 0x1b, 0x5f, 0x46, 0x5e, 0xc2, 0x59, 0xb2, 0x58, 0xe4, 0x5a, + 0x10, 0x64, 0x0b, 0x65, 0x5e, 0x65, 0xec, 0x61, 0x4a, 0x51, 0xcf, 0x33, + 0xff, 0x19, 0xb3, 0x0d, 0xfb, 0xf6, 0x90, 0xe4, 0x8e, 0xe1, 0xcb, 0xe9, + 0xa7, 0xf7, 0x3d, 0xfc, 0x13, 0xf7, 0xcd, 0xfa, 0xc4, 0x01, 0xfd, 0xfe, + 0x2c, 0x01, 0x1f, 0xfa, 0xf9, 0xfa, 0xff, 0x09, 0xc7, 0x0f, 0x18, 0x19, + 0x6f, 0x1d, 0x43, 0x20, 0x1c, 0x25, 0x3e, 0x22, 0xa7, 0x1c, 0x67, 0x18, + 0x80, 0x18, 0x4f, 0x17, 0x97, 0x11, 0x4f, 0x0c, 0x08, 0x0d, 0x19, 0x14, + 0x45, 0x24, 0x1e, 0x30, 0x75, 0x34, 0x85, 0x40, 0x06, 0x47, 0xfc, 0x4f, + 0xde, 0x5a, 0x91, 0x56, 0x11, 0x46, 0x37, 0x2e, 0xe7, 0x1c, 0x03, 0x0d, + 0x9b, 0x0c, 0x4f, 0x19, 0x5e, 0x17, 0x60, 0x15, 0xfa, 0x17, 0xe5, 0x1d, + 0xf3, 0x1b, 0x7a, 0x0e, 0xe1, 0xfe, 0xf0, 0xf6, 0xa4, 0xfd, 0xa4, 0x02, + 0xe7, 0x03, 0xd5, 0xfb, 0xbd, 0xf5, 0x20, 0xfb, 0x38, 0x02, 0xf6, 0x05, + 0xea, 0x02, 0x21, 0x0a, 0x9f, 0x17, 0x77, 0x23, 0x39, 0x2a, 0x40, 0x2b, + 0x3d, 0x2b, 0x8a, 0x2c, 0xb2, 0x30, 0xce, 0x2d, 0x4e, 0x29, 0x05, 0x26, + 0x57, 0x23, 0x7a, 0x21, 0x7c, 0x1c, 0x86, 0x19, 0xb7, 0x18, 0x73, 0x13, + 0x63, 0x0f, 0x4b, 0x06, 0xc2, 0xfd, 0xbe, 0xfc, 0x87, 0xeb, 0x74, 0xdf, + 0x62, 0xd9, 0x31, 0xd2, 0xea, 0xd5, 0x7e, 0xd6, 0xe5, 0xe1, 0xc9, 0xf4, + 0xa4, 0x05, 0xd0, 0x16, 0xf2, 0x21, 0xe8, 0x26, 0x88, 0x2f, 0x5e, 0x38, + 0xfc, 0x38, 0xcd, 0x31, 0x2c, 0x18, 0x46, 0xff, 0x8c, 0xf6, 0xf9, 0xfa, + 0x3f, 0xff, 0xdb, 0xfd, 0x2d, 0xfe, 0xc6, 0xf9, 0xa8, 0xff, 0x9c, 0x06, + 0xc1, 0x06, 0x03, 0xfe, 0x1b, 0xed, 0x7e, 0xe8, 0xd7, 0xe8, 0x27, 0xef, + 0x50, 0xe9, 0x17, 0xe1, 0x19, 0xf0, 0x8f, 0xf7, 0x79, 0xf9, 0xbc, 0xfe, + 0xbb, 0xf9, 0x1b, 0xed, 0xa2, 0xe4, 0xa0, 0xd9, 0x04, 0xcf, 0x92, 0xc7, + 0x99, 0xc7, 0x8d, 0xdd, 0x86, 0xf1, 0xfa, 0x01, 0xf4, 0x07, 0x4f, 0x0c, + 0xca, 0x17, 0xfc, 0x1a, 0xca, 0x28, 0x32, 0x25, 0xac, 0x1b, 0x0c, 0x1c, + 0x2e, 0x19, 0x15, 0x21, 0x61, 0x18, 0x02, 0x09, 0x16, 0x00, 0xd1, 0xf1, + 0x4d, 0xe8, 0x81, 0xe0, 0x3c, 0xdb, 0x8e, 0xd2, 0x56, 0xba, 0x86, 0xa8, + 0xf0, 0xa1, 0xa4, 0xa5, 0x56, 0xb4, 0x41, 0xbb, 0xd8, 0xc8, 0x3e, 0xd5, + 0x95, 0xe3, 0xef, 0xf7, 0x4a, 0x05, 0xe3, 0x10, 0x33, 0x0e, 0x9d, 0x0f, + 0x1d, 0x16, 0x89, 0x1f, 0x50, 0x2a, 0x02, 0x32, 0x0c, 0x40, 0xc4, 0x48, + 0x88, 0x56, 0x74, 0x62, 0x98, 0x64, 0xa7, 0x5c, 0x6f, 0x4e, 0x93, 0x3b, + 0xdf, 0x28, 0xdf, 0x21, 0xab, 0x18, 0xfd, 0x16, 0x33, 0x13, 0x22, 0x0e, + 0x4e, 0x0f, 0x9c, 0x0d, 0x0f, 0x0d, 0xfa, 0x08, 0x06, 0x09, 0x28, 0x07, + 0x0f, 0x0a, 0x58, 0x13, 0xb0, 0x17, 0x89, 0x15, 0xd5, 0x07, 0xf5, 0xfe, + 0xec, 0x04, 0xf3, 0x0a, 0xd9, 0x05, 0x97, 0xfa, 0xe3, 0xee, 0xb2, 0xee, + 0x3b, 0xf1, 0x2e, 0xf1, 0xd5, 0xfa, 0xa4, 0x05, 0x19, 0x0f, 0x36, 0x13, + 0xf2, 0x13, 0x59, 0x19, 0xe6, 0x22, 0xbb, 0x28, 0x8f, 0x23, 0x14, 0x1a, + 0xc4, 0x15, 0x8e, 0x19, 0xde, 0x18, 0x28, 0x0e, 0x09, 0x03, 0xc9, 0xf8, + 0xb6, 0xf6, 0xa8, 0x07, 0xde, 0x14, 0xf0, 0x11, 0xd9, 0x11, 0x19, 0x13, + 0xbe, 0x13, 0xb1, 0x15, 0x4d, 0x0f, 0x26, 0x08, 0x60, 0xfc, 0x06, 0xf4, + 0xfb, 0x02, 0x0e, 0x16, 0x97, 0x27, 0x67, 0x2f, 0x9e, 0x29, 0x1a, 0x23, + 0x4d, 0x1b, 0x3f, 0x11, 0x05, 0x00, 0x6c, 0xf9, 0x35, 0xfa, 0x94, 0xee, + 0x71, 0xea, 0x69, 0xf4, 0x55, 0xfe, 0x9b, 0x12, 0x21, 0x2b, 0x57, 0x38, + 0x7d, 0x34, 0xb8, 0x1f, 0xdb, 0x12, 0xf3, 0x02, 0xd4, 0xf4, 0x0e, 0xea, + 0x89, 0xd7, 0xd4, 0xd9, 0x52, 0xdf, 0x9c, 0xdb, 0x4e, 0xd7, 0xcb, 0xd8, + 0x4b, 0xdf, 0x18, 0xe1, 0xb0, 0xe5, 0x13, 0xe4, 0x2f, 0xe1, 0xfc, 0xd8, + 0x5c, 0xce, 0x2e, 0xdd, 0xe9, 0xf0, 0x83, 0x07, 0x2b, 0x1e, 0x39, 0x22, + 0x80, 0x21, 0xd8, 0x1b, 0xa2, 0x19, 0x4e, 0x17, 0xa4, 0x1b, 0xfb, 0x16, + 0x4b, 0xf8, 0xf9, 0xec, 0x88, 0xf2, 0x2a, 0x00, 0x39, 0x05, 0xd6, 0xfb, + 0xe1, 0xf6, 0xbd, 0xf2, 0x97, 0xf3, 0x61, 0xe6, 0x90, 0xd3, 0x46, 0xc9, + 0xb5, 0xc1, 0xb9, 0xc1, 0xd4, 0xc0, 0x94, 0xbb, 0x0f, 0xbd, 0x5a, 0xc6, + 0xb7, 0xcb, 0xb0, 0xcc, 0x0f, 0xcb, 0x88, 0xc5, 0xb4, 0xb8, 0x6b, 0xac, + 0xf8, 0xa7, 0x99, 0xab, 0x2b, 0xc3, 0xc6, 0xe0, 0xdb, 0xf1, 0x61, 0xfb, + 0x54, 0x02, 0xbf, 0x0a, 0x3c, 0x12, 0xe4, 0x15, 0x29, 0x11, 0x4c, 0x08, + 0xf3, 0x01, 0x27, 0xfd, 0x0a, 0xff, 0xf7, 0xfc, 0x90, 0xfa, 0xe8, 0xf4, + 0xa6, 0xe3, 0x0e, 0xd8, 0x64, 0xce, 0xa4, 0xc8, 0x95, 0xcb, 0x7d, 0xd5, + 0xbf, 0xdb, 0x16, 0xd8, 0xa7, 0xda, 0xec, 0xe4, 0x31, 0xeb, 0x79, 0xe5, + 0xf9, 0xdf, 0xd9, 0xe0, 0x13, 0xe0, 0xee, 0xde, 0x99, 0xda, 0x29, 0xd7, + 0x69, 0xdb, 0xe7, 0xe0, 0x32, 0xe8, 0xa9, 0xef, 0x62, 0xf6, 0xf5, 0xfd, + 0xd5, 0x03, 0xa1, 0x09, 0x68, 0x09, 0x41, 0x09, 0x8c, 0x07, 0x54, 0x07, + 0x44, 0x12, 0xac, 0x1f, 0xbb, 0x32, 0x30, 0x41, 0x64, 0x46, 0xbc, 0x47, + 0xad, 0x3a, 0xb2, 0x2b, 0x2a, 0x25, 0xe6, 0x14, 0xae, 0x01, 0x1a, 0xf0, + 0x6b, 0xe0, 0xbe, 0xe1, 0x98, 0xe9, 0x7c, 0xf1, 0xf6, 0xf2, 0xef, 0xed, + 0xa6, 0xe3, 0x87, 0xd1, 0x50, 0xc1, 0x73, 0xb2, 0x41, 0xaf, 0x1e, 0xb6, + 0x14, 0xc1, 0xe1, 0xce, 0x7f, 0xd6, 0xce, 0xe4, 0xb4, 0xf3, 0x69, 0xf4, + 0xba, 0xef, 0x9d, 0xea, 0xbe, 0xe6, 0xba, 0xe4, 0x21, 0xe3, 0x3a, 0xe1, + 0x47, 0xeb, 0x43, 0xfd, 0xc0, 0x0c, 0xb7, 0x24, 0x92, 0x3a, 0xf5, 0x48, + 0x06, 0x4c, 0x81, 0x3f, 0x66, 0x31, 0x97, 0x20, 0x96, 0x09, 0xe9, 0xf5, + 0x3f, 0xe6, 0x8e, 0xd6, 0xcb, 0xd2, 0x54, 0xda, 0x13, 0xe7, 0x20, 0xf7, + 0x59, 0xff, 0xa1, 0x03, 0x75, 0x09, 0x2d, 0x00, 0x03, 0xee, 0xe8, 0xdc, + 0x02, 0xc6, 0x38, 0xb4, 0xba, 0xac, 0x62, 0xb8, 0x6b, 0xcb, 0x26, 0xe0, + 0x39, 0xfe, 0xfb, 0x12, 0xf5, 0x18, 0xdc, 0x11, 0x9f, 0x0d, 0x66, 0x0f, + 0x17, 0x12, 0x96, 0x14, 0x27, 0x0d, 0x13, 0x07, 0xb1, 0x0f, 0x23, 0x19, + 0x4a, 0x22, 0x94, 0x34, 0x82, 0x3c, 0x81, 0x3e, 0xf7, 0x3a, 0xfc, 0x2b, + 0x39, 0x1a, 0x22, 0xf6, 0x57, 0xce, 0x0b, 0xba, 0x10, 0xac, 0x19, 0xa4, + 0xeb, 0xa4, 0x5e, 0xaa, 0xae, 0xaf, 0x86, 0xb0, 0x11, 0xb0, 0x4d, 0xa5, + 0x93, 0xa0, 0x30, 0xa3, 0xab, 0xa5, 0xd0, 0xb4, 0xee, 0xc9, 0x39, 0xe5, + 0x6b, 0xfe, 0x7e, 0x1e, 0x16, 0x42, 0xc4, 0x59, 0xa8, 0x6a, 0xf1, 0x6f, + 0xd4, 0x6a, 0xbe, 0x61, 0x3a, 0x55, 0x7d, 0x44, 0x11, 0x36, 0xc4, 0x2f, + 0xd7, 0x30, 0x47, 0x2b, 0x45, 0x20, 0x7c, 0x13, 0x08, 0x07, 0x5e, 0xf9, + 0xa1, 0xea, 0x8f, 0xe0, 0xb5, 0xd0, 0x1d, 0xca, 0x54, 0xc6, 0xf6, 0xc3, + 0xa7, 0xc6, 0x53, 0xcd, 0x66, 0xd5, 0x2d, 0xd4, 0x0d, 0xdc, 0x2b, 0xe2, + 0x6b, 0xe6, 0xee, 0xeb, 0x16, 0xf5, 0x63, 0x02, 0x46, 0x0f, 0x84, 0x1c, + 0x11, 0x20, 0x50, 0x27, 0x37, 0x2c, 0x9c, 0x33, 0x4f, 0x40, 0x47, 0x48, + 0x2a, 0x4f, 0xaf, 0x54, 0xa0, 0x5b, 0x5e, 0x60, 0xbe, 0x60, 0x8d, 0x57, + 0x4e, 0x47, 0x65, 0x35, 0xe7, 0x24, 0x29, 0x15, 0x2d, 0x08, 0xfc, 0x01, + 0x19, 0xf8, 0x63, 0xed, 0xfe, 0xeb, 0xc6, 0xe6, 0x15, 0xd6, 0xe2, 0xc9, + 0x77, 0xbc, 0x81, 0xa9, 0x8b, 0xa0, 0x78, 0xa0, 0x98, 0xa6, 0x7d, 0xb3, + 0xd7, 0xc1, 0xe8, 0xc5, 0x30, 0xc3, 0xf4, 0xc2, 0x72, 0xbe, 0xbc, 0xc0, + 0x36, 0xca, 0x7f, 0xda, 0x1f, 0xed, 0x93, 0xf7, 0x06, 0x06, 0x25, 0x10, + 0xf8, 0x21, 0x99, 0x38, 0x35, 0x4e, 0x26, 0x61, 0xf5, 0x63, 0x35, 0x6a, + 0xb5, 0x68, 0xcc, 0x62, 0xae, 0x5b, 0x43, 0x4e, 0x15, 0x41, 0x8b, 0x30, + 0xb1, 0x21, 0xb7, 0x10, 0x00, 0x05, 0xac, 0x02, 0x81, 0x08, 0xd9, 0x14, + 0x4c, 0x27, 0x50, 0x31, 0x7f, 0x2e, 0x9c, 0x2c, 0x42, 0x29, 0xea, 0x29, + 0x3e, 0x2a, 0x33, 0x31, 0x20, 0x38, 0xc3, 0x33, 0xc3, 0x32, 0x81, 0x32, + 0x4b, 0x30, 0x44, 0x2a, 0x2b, 0x22, 0x74, 0x20, 0x6f, 0x1a, 0x50, 0x0d, + 0x0f, 0x03, 0x0f, 0x01, 0xa9, 0x0a, 0x66, 0x0d, 0x2a, 0x05, 0x88, 0xf9, + 0x19, 0xf3, 0x52, 0xf1, 0xed, 0xe2, 0xcf, 0xd9, 0xc1, 0xda, 0xf8, 0xe2, + 0xc5, 0xf0, 0x2c, 0xfa, 0x07, 0x02, 0x18, 0x04, 0x42, 0x07, 0x02, 0x08, + 0xf2, 0x07, 0x98, 0x0d, 0xf0, 0x0f, 0xc8, 0x15, 0xf9, 0x18, 0xd3, 0x12, + 0xd8, 0x14, 0x42, 0x21, 0xb4, 0x24, 0xc3, 0x2a, 0x93, 0x3f, 0xda, 0x48, + 0x3f, 0x4f, 0x82, 0x57, 0x3e, 0x55, 0x05, 0x59, 0x0c, 0x5d, 0xf2, 0x58, + 0x1c, 0x55, 0xce, 0x4f, 0x77, 0x49, 0x70, 0x40, 0x4c, 0x31, 0x0d, 0x2c, + 0x8e, 0x2c, 0x68, 0x26, 0x88, 0x18, 0xfc, 0x0a, 0x98, 0x07, 0x8d, 0x01, + 0xef, 0x05, 0xce, 0x07, 0xdb, 0xf6, 0x32, 0xea, 0xaa, 0xe5, 0x92, 0xe6, + 0x3b, 0xe5, 0x30, 0xe8, 0xe4, 0xec, 0x2e, 0xef, 0xd0, 0xf3, 0x51, 0xfa, + 0xb1, 0x02, 0x58, 0x0d, 0x77, 0x18, 0x73, 0x1d, 0x9e, 0x2c, 0x47, 0x41, + 0xaf, 0x4d, 0x9d, 0x55, 0xb4, 0x59, 0x38, 0x5a, 0xcc, 0x58, 0xcb, 0x52, + 0xdd, 0x4c, 0xb3, 0x4f, 0x00, 0x46, 0x76, 0x3d, 0x17, 0x3e, 0x61, 0x35, + 0xce, 0x2c, 0x20, 0x1a, 0x9b, 0x00, 0x4d, 0xee, 0x5f, 0xdf, 0x2f, 0xd0, + 0xa0, 0xc0, 0xd5, 0xb7, 0x8d, 0xbb, 0x1e, 0xc6, 0xfd, 0xcf, 0xc3, 0xd6, + 0xfe, 0xd5, 0x27, 0xd8, 0xcb, 0xe5, 0x47, 0xfa, 0x42, 0x0d, 0x4b, 0x15, + 0x14, 0x1c, 0x7b, 0x29, 0x5f, 0x3b, 0x64, 0x41, 0x84, 0x33, 0x97, 0x28, + 0x7b, 0x1a, 0x4e, 0x0e, 0x14, 0x10, 0x26, 0x15, 0x21, 0x23, 0xc3, 0x32, + 0xe7, 0x44, 0x72, 0x4c, 0xf7, 0x42, 0x19, 0x3a, 0x46, 0x2f, 0xe4, 0x24, + 0x4b, 0x16, 0x5f, 0x07, 0x90, 0xfa, 0x32, 0xf0, 0x80, 0xed, 0x18, 0xea, + 0x19, 0xe4, 0x11, 0xe3, 0x41, 0xe6, 0x7c, 0xe5, 0x3a, 0xe4, 0x11, 0xdb, + 0x20, 0xd2, 0x6f, 0xcc, 0x4f, 0xc5, 0x6c, 0xc8, 0x06, 0xc6, 0xf4, 0xc5, + 0x16, 0xcf, 0xbc, 0xda, 0x2c, 0xee, 0xd0, 0xfb, 0xd0, 0xff, 0x51, 0x03, + 0xce, 0x05, 0x1f, 0x08, 0x7a, 0x10, 0x82, 0x16, 0xaf, 0x1b, 0x92, 0x20, + 0x53, 0x1c, 0x75, 0x14, 0xe6, 0x09, 0xf5, 0x03, 0x7a, 0x01, 0x4f, 0xfe, + 0x03, 0xfa, 0x7e, 0xf1, 0x77, 0xec, 0x7c, 0xea, 0x62, 0xe8, 0x6a, 0xe2, + 0x3c, 0xe6, 0x45, 0xf8, 0x0a, 0x04, 0xee, 0x0d, 0x4b, 0x18, 0xcb, 0x1c, + 0xfb, 0x1d, 0x33, 0x1d, 0x16, 0x16, 0x6d, 0x05, 0xeb, 0xf8, 0x9c, 0xf2, + 0x32, 0xed, 0x82, 0xed, 0xf1, 0xf4, 0x08, 0x04, 0x40, 0x10, 0x72, 0x12, + 0x86, 0x16, 0xe8, 0x1b, 0x3b, 0x19, 0x06, 0x12, 0xcd, 0x09, 0xad, 0xfe, + 0x7f, 0xf7, 0xd4, 0xfa, 0xda, 0x05, 0x8c, 0x15, 0x1c, 0x24, 0x8f, 0x35, + 0x1c, 0x45, 0x7f, 0x4c, 0xd0, 0x53, 0xdd, 0x51, 0x5e, 0x48, 0xdf, 0x3b, + 0xd5, 0x2a, 0xfe, 0x1a, 0x47, 0x0e, 0xd7, 0x02, 0xf9, 0xf5, 0x1a, 0xf3, + 0xeb, 0xfa, 0x43, 0x02, 0x21, 0xff, 0xe3, 0xfb, 0x5d, 0xfd, 0x32, 0xf6, + 0x40, 0xf9, 0x74, 0xfa, 0x2f, 0xf2, 0x02, 0xed, 0xbf, 0xdd, 0xb2, 0xd7, + 0x14, 0xde, 0xcd, 0xdf, 0x2b, 0xe0, 0x16, 0xe5, 0x5a, 0xe9, 0x72, 0xe8, + 0xdc, 0xeb, 0x46, 0xee, 0xcf, 0xf4, 0xc7, 0xf9, 0x09, 0xf9, 0x82, 0xfd, + 0x03, 0xfa, 0x62, 0xf7, 0x00, 0xfb, 0x1d, 0x01, 0xd4, 0x03, 0x37, 0xff, + 0x50, 0xff, 0xc5, 0x07, 0xa8, 0x18, 0x6c, 0x23, 0x83, 0x26, 0xdb, 0x29, + 0x60, 0x2b, 0x03, 0x29, 0xd7, 0x28, 0xcf, 0x29, 0xe6, 0x24, 0x06, 0x23, + 0xbf, 0x21, 0x19, 0x26, 0xb5, 0x2d, 0x4a, 0x37, 0x47, 0x3c, 0x7a, 0x37, + 0xf8, 0x38, 0x85, 0x38, 0x9a, 0x37, 0x8b, 0x33, 0xdc, 0x32, 0x74, 0x38, + 0x11, 0x3a, 0x61, 0x3f, 0x4b, 0x3d, 0xed, 0x33, 0x68, 0x2b, 0xdf, 0x20, + 0x38, 0x11, 0x37, 0x02, 0x64, 0xee, 0x17, 0xd3, 0x4b, 0xc1, 0x39, 0xba, + 0x04, 0xbc, 0x70, 0xc1, 0x60, 0xc7, 0x30, 0xd1, 0xfc, 0xdd, 0x44, 0xe7, + 0xab, 0xe9, 0x47, 0xed, 0x29, 0xea, 0xf3, 0xda, 0xf9, 0xcf, 0x82, 0xc2, + 0x61, 0xb2, 0x83, 0xa9, 0x34, 0xa0, 0x20, 0x9d, 0x2d, 0x9e, 0xa5, 0xa4, + 0xc0, 0xae, 0x71, 0xbd, 0xea, 0xd7, 0x39, 0xe9, 0xdb, 0xf3, 0x2c, 0xfa, + 0xe6, 0xf4, 0xc3, 0xed, 0xa0, 0xef, 0x31, 0xf5, 0xb8, 0xf9, 0xb5, 0x06, + 0xe8, 0x1d, 0xe1, 0x3c, 0x26, 0x58, 0x41, 0x68, 0x90, 0x6c, 0x0b, 0x6a, + 0x7d, 0x63, 0xa0, 0x54, 0x80, 0x3e, 0x87, 0x2c, 0x37, 0x24, 0xf7, 0x15, + 0xd3, 0x04, 0x9e, 0xf7, 0x0a, 0xed, 0x4e, 0xe6, 0x9d, 0xe5, 0x53, 0xe5, + 0xfa, 0xe4, 0x9f, 0xe8, 0xa1, 0xe4, 0x5d, 0xe1, 0xca, 0xda, 0xd4, 0xcf, + 0xa3, 0xc5, 0x7b, 0xbe, 0x5f, 0xc6, 0xf8, 0xce, 0x9c, 0xd6, 0x9a, 0xda, + 0x7e, 0xda, 0xcc, 0xdb, 0x42, 0xdf, 0x63, 0xe7, 0xb1, 0xea, 0xc9, 0xeb, + 0x20, 0xe9, 0xfd, 0xe4, 0xbf, 0xe0, 0xd4, 0xd7, 0xe5, 0xd2, 0x21, 0xd6, + 0x4f, 0xdf, 0xae, 0xe6, 0xe5, 0xe8, 0x82, 0xe4, 0x5e, 0xdc, 0xb9, 0xd1, + 0x68, 0xc6, 0xeb, 0xc1, 0x37, 0xb9, 0x4d, 0xb3, 0x0a, 0xb7, 0x59, 0xb9, + 0x2e, 0xc1, 0xf6, 0xc4, 0xe3, 0xc7, 0xdb, 0xd5, 0x11, 0xe1, 0x75, 0xe6, + 0xb5, 0xe7, 0xfe, 0xe7, 0x3a, 0xe9, 0x76, 0xe7, 0x47, 0xe2, 0x20, 0xe0, + 0xa7, 0xe6, 0x62, 0xf6, 0x4c, 0x01, 0xfa, 0x06, 0x4c, 0x0b, 0xef, 0x09, + 0xf1, 0x14, 0x69, 0x1f, 0x4b, 0x1d, 0x2b, 0x0f, 0x79, 0x00, 0x56, 0xfa, + 0x62, 0xf1, 0x2d, 0xf1, 0xba, 0xed, 0x1f, 0xed, 0x26, 0xf0, 0x22, 0xf2, + 0x58, 0xff, 0x42, 0x07, 0xb5, 0x0b, 0x63, 0x13, 0x04, 0x21, 0x85, 0x26, + 0x40, 0x24, 0x87, 0x1e, 0x53, 0x14, 0x4d, 0x14, 0x0a, 0x17, 0x7a, 0x1d, + 0x89, 0x1f, 0x5d, 0x24, 0x34, 0x30, 0xf3, 0x33, 0xf6, 0x38, 0x2a, 0x32, + 0x24, 0x25, 0xf9, 0x23, 0xb4, 0x10, 0x64, 0xef, 0xbd, 0xd2, 0xdd, 0xb9, + 0x9b, 0xbc, 0xb0, 0xc1, 0xad, 0xb7, 0x99, 0xb3, 0x1d, 0xb3, 0x85, 0xb9, + 0x48, 0xc1, 0x32, 0xca, 0x4d, 0xcd, 0x2a, 0xcc, 0xa2, 0xce, 0xeb, 0xd0, + 0xc7, 0xd3, 0x4f, 0xd2, 0xe5, 0xd1, 0x4a, 0xd1, 0x05, 0xdc, 0xba, 0xec, + 0xc5, 0xf5, 0x6a, 0xff, 0xf4, 0xfd, 0x4f, 0xff, 0xf4, 0x03, 0xdd, 0x08, + 0x0b, 0x19, 0x67, 0x22, 0x5b, 0x26, 0x29, 0x27, 0xaa, 0x27, 0x59, 0x27, + 0x5f, 0x22, 0xfd, 0x21, 0x2d, 0x1a, 0xde, 0x0d, 0x1f, 0x05, 0x0a, 0x06, + 0xb6, 0x0c, 0xab, 0x09, 0x00, 0x02, 0xa4, 0xf8, 0xab, 0xf4, 0xae, 0xed, + 0xa7, 0xef, 0x11, 0xfd, 0xc3, 0xfc, 0x10, 0x03, 0x63, 0x09, 0xf5, 0x06, + 0x55, 0x07, 0xd4, 0x03, 0x08, 0x06, 0x20, 0x15, 0xf2, 0x24, 0xb5, 0x29, + 0xcb, 0x20, 0xea, 0x12, 0xe3, 0x0f, 0xe4, 0x08, 0xbd, 0xfb, 0xcc, 0xee, + 0x88, 0xda, 0x97, 0xce, 0x0a, 0xc3, 0x9f, 0xb8, 0xec, 0xb4, 0xc0, 0xb4, + 0xd0, 0xbb, 0x7c, 0xc0, 0x4b, 0xc7, 0x87, 0xca, 0xb4, 0xca, 0xd3, 0xcc, + 0x5f, 0xd4, 0x8b, 0xe0, 0x90, 0xe5, 0x1d, 0xeb, 0x7e, 0xeb, 0x98, 0xe8, + 0x83, 0xe5, 0x90, 0xe9, 0xb1, 0xf3, 0xe8, 0xf7, 0xa2, 0x04, 0x28, 0x0b, + 0x77, 0x0c, 0xb5, 0x0f, 0xa5, 0x0f, 0x18, 0x14, 0x2f, 0x16, 0xda, 0x14, + 0xbc, 0x13, 0xe8, 0x17, 0x74, 0x14, 0x14, 0x10, 0x8e, 0x11, 0x7b, 0x11, + 0xb6, 0x16, 0x59, 0x17, 0xf2, 0x1d, 0x8a, 0x23, 0xda, 0x1f, 0x25, 0x21, + 0x31, 0x1f, 0xf8, 0x1e, 0x18, 0x23, 0x38, 0x23, 0xcf, 0x1e, 0xde, 0x19, + 0x29, 0x14, 0xf7, 0x10, 0x5a, 0x0d, 0xed, 0x04, 0x28, 0xfe, 0x8b, 0xf8, + 0x1e, 0xf4, 0x82, 0xf0, 0x67, 0xf5, 0x9f, 0xfd, 0x23, 0x03, 0x05, 0x03, + 0xb5, 0xf5, 0x6f, 0xef, 0x20, 0xf2, 0x0b, 0xf6, 0x18, 0xf7, 0x0e, 0xfa, + 0x66, 0x0b, 0xf3, 0x1a, 0x6b, 0x27, 0xc5, 0x2e, 0x45, 0x29, 0x58, 0x1e, + 0xad, 0x1a, 0x1e, 0x23, 0x45, 0x1c, 0x28, 0x0a, 0x92, 0x00, 0x37, 0xf4, + 0x3f, 0xec, 0x0f, 0xed, 0x85, 0xea, 0xad, 0xea, 0x64, 0xec, 0x01, 0xe2, + 0xfc, 0xda, 0x59, 0xd9, 0xf2, 0xd0, 0x24, 0xd3, 0x7c, 0xd6, 0x14, 0xd7, + 0xeb, 0xe3, 0x20, 0xe9, 0x48, 0xee, 0xd4, 0x02, 0x71, 0x1d, 0xf8, 0x34, + 0x27, 0x41, 0x7a, 0x48, 0x86, 0x4f, 0x2e, 0x5c, 0xca, 0x69, 0xfb, 0x6b, + 0x75, 0x66, 0x45, 0x61, 0x46, 0x63, 0xf9, 0x68, 0x98, 0x6f, 0x7a, 0x73, + 0xaa, 0x73, 0x32, 0x73, 0x52, 0x6f, 0x95, 0x6a, 0x83, 0x64, 0x58, 0x59, + 0x1d, 0x48, 0xb9, 0x34, 0xbb, 0x20, 0x1c, 0x09, 0xd4, 0xf5, 0x27, 0xed, + 0x69, 0xe7, 0xe4, 0xe0, 0xac, 0xdf, 0x57, 0xe1, 0x13, 0xe6, 0x90, 0xed, + 0xd2, 0xed, 0x33, 0xf1, 0xfb, 0xfa, 0x67, 0x04, 0x14, 0x0b, 0x74, 0x0d, + 0x5f, 0x0b, 0x2a, 0x04, 0xc5, 0x07, 0x4e, 0x13, 0xf2, 0x1b, 0x1e, 0x1e, + 0xf5, 0x20, 0xa2, 0x29, 0x37, 0x31, 0x79, 0x3b, 0x01, 0x37, 0x9b, 0x2a, + 0xd4, 0x18, 0x6a, 0x03, 0x6e, 0xf5, 0x2d, 0xe4, 0x49, 0xe1, 0xe3, 0xe1, + 0x4c, 0xe8, 0x64, 0xf7, 0x52, 0x02, 0x22, 0x14, 0x2f, 0x1d, 0xa1, 0x1b, + 0xfe, 0x1c, 0xa2, 0x20, 0x11, 0x21, 0xb5, 0x23, 0xbd, 0x26, 0x5d, 0x29, + 0x2f, 0x2f, 0xfe, 0x2f, 0xc6, 0x37, 0xf4, 0x3d, 0x51, 0x35, 0xce, 0x2d, + 0x05, 0x2c, 0x13, 0x2e, 0xcc, 0x32, 0x8b, 0x35, 0x3f, 0x32, 0xad, 0x27, + 0xe1, 0x1e, 0xe6, 0x1a, 0x48, 0x1b, 0xd3, 0x1c, 0xfb, 0x18, 0x98, 0x18, + 0x77, 0x1d, 0x28, 0x21, 0x6e, 0x21, 0x5a, 0x25, 0x59, 0x2c, 0xc7, 0x2a, + 0xc5, 0x22, 0x84, 0x16, 0xf0, 0x0d, 0x9e, 0x08, 0x86, 0x03, 0x96, 0x00, + 0x1e, 0xf4, 0xa0, 0xe4, 0x38, 0xda, 0xe6, 0xcf, 0x50, 0xc7, 0x28, 0xc3, + 0x1a, 0xc5, 0x88, 0xcb, 0x50, 0xd1, 0xad, 0xd2, 0xd3, 0xdc, 0xc3, 0xec, + 0xfb, 0xf4, 0x16, 0xfd, 0xc9, 0xfe, 0xc3, 0xfd, 0x51, 0xff, 0x6e, 0xfe, + 0x6c, 0xfe, 0x9a, 0x02, 0x7e, 0x0d, 0x31, 0x1a, 0xb3, 0x29, 0x45, 0x33, + 0xeb, 0x38, 0x7f, 0x3d, 0x32, 0x39, 0xa4, 0x33, 0xd6, 0x2a, 0xca, 0x1f, + 0x93, 0x12, 0x47, 0x05, 0x60, 0xff, 0xc5, 0xfc, 0x9e, 0xfa, 0x86, 0xfa, + 0x81, 0xf8, 0x9d, 0xf1, 0xa2, 0xe9, 0x5d, 0xe6, 0x89, 0xe7, 0x27, 0xe2, + 0x48, 0xe0, 0x16, 0xeb, 0xc3, 0xfb, 0x25, 0x0f, 0xf2, 0x19, 0x23, 0x1d, + 0xc7, 0x21, 0x53, 0x22, 0xe5, 0x1d, 0x99, 0x15, 0xd1, 0x0c, 0x1b, 0x0b, + 0xa4, 0x06, 0xfe, 0x05, 0xfc, 0x0b, 0x16, 0x18, 0x00, 0x2e, 0x5e, 0x37, + 0x0b, 0x36, 0x95, 0x34, 0x48, 0x33, 0xb0, 0x31, 0x9a, 0x2a, 0x85, 0x20, + 0xd1, 0x16, 0x46, 0x08, 0xfe, 0xfa, 0x7d, 0xfd, 0xb8, 0x04, 0xd8, 0x0e, + 0x4a, 0x17, 0x35, 0x16, 0xb1, 0x1a, 0xd9, 0x1c, 0xfa, 0x14, 0xb7, 0x09, + 0xbb, 0xf7, 0x52, 0xe7, 0xd9, 0xde, 0xcf, 0xd8, 0x4e, 0xd1, 0xce, 0xc5, + 0x35, 0xc2, 0x6d, 0xc9, 0x3a, 0xd3, 0x1d, 0xe1, 0xd5, 0xe0, 0x03, 0xd9, + 0xce, 0xdc, 0xcd, 0xdc, 0xd5, 0xdf, 0xc5, 0xdc, 0xf6, 0xd2, 0x2d, 0xd5, + 0x6a, 0xda, 0xa0, 0xe8, 0x0b, 0xf2, 0x9e, 0xf7, 0x9d, 0xfd, 0x5b, 0x06, + 0x9c, 0x17, 0x24, 0x14, 0xdc, 0x08, 0x5c, 0x02, 0x91, 0x02, 0x32, 0x07, + 0x9f, 0x05, 0x58, 0x05, 0xcd, 0x10, 0xa3, 0x27, 0x15, 0x36, 0xce, 0x41, + 0x3e, 0x49, 0x66, 0x49, 0x48, 0x49, 0xbe, 0x4a, 0x37, 0x45, 0x80, 0x3a, + 0x74, 0x3f, 0x6b, 0x3e, 0x43, 0x36, 0xfb, 0x2d, 0xc7, 0x26, 0x22, 0x22, + 0x90, 0x18, 0x08, 0x12, 0x97, 0x02, 0x0d, 0xf9, 0x2c, 0xf9, 0x19, 0xf7, + 0x54, 0xf8, 0xbc, 0xf7, 0x94, 0xf9, 0x08, 0xfa, 0xe1, 0xff, 0x73, 0x03, + 0x88, 0xfb, 0x69, 0xf8, 0xcc, 0xf6, 0xfd, 0xf8, 0x66, 0xfd, 0x19, 0x00, + 0xf6, 0x08, 0xfb, 0x12, 0xb3, 0x16, 0xa5, 0x17, 0xb2, 0x1c, 0xfb, 0x21, + 0xcc, 0x20, 0x94, 0x1a, 0xbd, 0x0f, 0x82, 0x06, 0xa4, 0x03, 0x5f, 0xff, + 0xcd, 0xf4, 0xd1, 0xe5, 0x38, 0xdc, 0x09, 0xd6, 0x74, 0xd8, 0xf3, 0xe2, + 0xfc, 0xe3, 0xfc, 0xe8, 0xd3, 0xec, 0x2d, 0xed, 0x7d, 0xfa, 0x05, 0x08, + 0x45, 0x0f, 0x0e, 0x14, 0x4c, 0x0d, 0x80, 0x04, 0x02, 0x0c, 0xa2, 0x0b, + 0xac, 0xff, 0xaf, 0xef, 0x4d, 0xe0, 0x19, 0xe0, 0x1b, 0xe9, 0x42, 0xfa, + 0x6e, 0x08, 0xe5, 0x14, 0xe4, 0x1a, 0xa2, 0x1c, 0x2d, 0x26, 0xb1, 0x26, + 0x7f, 0x1f, 0x7c, 0x18, 0xc0, 0x18, 0xe9, 0x18, 0x9b, 0x17, 0xdc, 0x18, + 0xc0, 0x16, 0x9d, 0x1d, 0x11, 0x2a, 0xbe, 0x2b, 0x49, 0x25, 0x39, 0x1b, + 0xaa, 0x04, 0x3f, 0xf1, 0x3c, 0xe8, 0xeb, 0xdc, 0x2f, 0xd0, 0x17, 0xc2, + 0x3d, 0xc1, 0x87, 0xc5, 0xda, 0xc5, 0x40, 0xc6, 0xd2, 0xc3, 0x61, 0xc6, + 0x24, 0xbf, 0x7e, 0xb7, 0xb0, 0xb7, 0xe6, 0xb1, 0xfb, 0xb5, 0x2a, 0xbe, + 0x7b, 0xc9, 0x6d, 0xdd, 0x6a, 0xe8, 0x34, 0xea, 0xb7, 0xef, 0xe4, 0xf4, + 0xa1, 0xee, 0xe7, 0xe7, 0xa8, 0xea, 0x8c, 0xef, 0xc2, 0xf3, 0xc3, 0xf9, + 0xde, 0xfc, 0x61, 0x01, 0x14, 0x03, 0xb3, 0xff, 0xa4, 0xf6, 0xe0, 0xe2, + 0x35, 0xe2, 0x83, 0xe1, 0x75, 0xd9, 0xc1, 0xdf, 0xc4, 0xdb, 0x7f, 0xd6, + 0x65, 0xd5, 0xda, 0xd4, 0x1a, 0xda, 0x7d, 0xdf, 0x01, 0xdf, 0x63, 0xdb, + 0x47, 0xdd, 0x65, 0xdb, 0xe5, 0xd4, 0x4a, 0xd1, 0x20, 0xd7, 0x04, 0xe4, + 0x04, 0xf6, 0x0e, 0x07, 0x13, 0x10, 0xe5, 0x1a, 0x19, 0x1f, 0x97, 0x1d, + 0xc8, 0x21, 0xe8, 0x24, 0x45, 0x1d, 0xaf, 0x10, 0x06, 0xff, 0x30, 0xe7, + 0x85, 0xde, 0x50, 0xdd, 0xce, 0xdc, 0x7f, 0xd8, 0xaf, 0xca, 0xe7, 0xc3, + 0x6f, 0xbb, 0x66, 0xb6, 0x5d, 0xb9, 0xb8, 0xb6, 0xaa, 0xb3, 0x81, 0xb8, + 0x44, 0xc4, 0xbc, 0xcd, 0xd2, 0xd7, 0xbe, 0xe2, 0x0c, 0xe7, 0x55, 0xed, + 0x86, 0xfa, 0x81, 0x04, 0xdc, 0x0d, 0x96, 0x18, 0x3b, 0x20, 0xae, 0x24, + 0x2d, 0x23, 0xd9, 0x24, 0x94, 0x24, 0x43, 0x1b, 0xff, 0x0d, 0x79, 0xf9, + 0x5e, 0xea, 0x18, 0xef, 0x85, 0xfa, 0x46, 0x03, 0xdd, 0x0d, 0x2e, 0x10, + 0x7f, 0x13, 0x48, 0x15, 0xf2, 0x09, 0x82, 0xfa, 0x21, 0xe5, 0x59, 0xe0, + 0x5d, 0xec, 0xf1, 0xf8, 0xa0, 0x06, 0xc8, 0x0a, 0xd3, 0x08, 0xf8, 0x03, + 0x30, 0xfe, 0xb5, 0xf4, 0xf8, 0xe4, 0xe7, 0xe1, 0x9b, 0xe6, 0xa2, 0xe5, + 0x17, 0xf2, 0x72, 0x03, 0x7f, 0x0d, 0xa1, 0x20, 0xd4, 0x30, 0x0a, 0x38, + 0x96, 0x3b, 0x6c, 0x34, 0xed, 0x24, 0x54, 0x15, 0xe7, 0x11, 0x0b, 0x10, + 0x21, 0x06, 0x89, 0x01, 0xf9, 0xf8, 0x4f, 0xef, 0x2d, 0xf0, 0x7c, 0xef, + 0x33, 0xe4, 0x62, 0xd8, 0x6c, 0xd8, 0x63, 0xd9, 0xdc, 0xd6, 0xbf, 0xcb, + 0x43, 0xc7, 0x8b, 0xd0, 0x79, 0xd0, 0xc2, 0xd2, 0x88, 0xcf, 0x3b, 0xc9, + 0xbc, 0xca, 0x67, 0xd5, 0x4e, 0xea, 0x73, 0xf5, 0x76, 0x08, 0x1c, 0x19, + 0xe4, 0x1c, 0xb4, 0x1a, 0x24, 0x0b, 0x16, 0xff, 0x66, 0xf9, 0x10, 0xff, + 0x3e, 0x06, 0x09, 0x0c, 0xd1, 0x13, 0xcb, 0x13, 0x0c, 0x14, 0xe8, 0x06, + 0x46, 0xf5, 0xbc, 0xee, 0x12, 0xe1, 0xf7, 0xd4, 0x1a, 0xd1, 0x01, 0xd1, + 0xea, 0xda, 0xd9, 0xde, 0x73, 0xd7, 0xc3, 0xc9, 0x62, 0xbc, 0x43, 0xbb, + 0x52, 0xb5, 0x83, 0xb0, 0xad, 0xb4, 0xe8, 0xbd, 0xcd, 0xcb, 0x8e, 0xd6, + 0x1d, 0xe5, 0x3f, 0xf4, 0x81, 0x04, 0xab, 0x11, 0x6e, 0x18, 0xa6, 0x1b, + 0xa2, 0x16, 0x44, 0x16, 0x90, 0x1a, 0xd5, 0x1b, 0xa5, 0x20, 0x38, 0x21, + 0xff, 0x19, 0x30, 0x1e, 0x38, 0x1d, 0x15, 0x11, 0x59, 0x0d, 0xf1, 0xfe, + 0xc6, 0xed, 0xdd, 0xe7, 0x7c, 0xde, 0x13, 0xd1, 0xe3, 0xc4, 0xfd, 0xb8, + 0xd2, 0xac, 0x6e, 0xa9, 0x6a, 0xa9, 0xcf, 0xa6, 0xa1, 0xa9, 0x60, 0xad, + 0x46, 0xb2, 0xdd, 0xc3, 0x13, 0xde, 0x38, 0xf5, 0x66, 0x0c, 0xf0, 0x26, + 0x34, 0x40, 0x72, 0x52, 0xec, 0x59, 0x59, 0x5b, 0xcb, 0x61, 0x83, 0x69, + 0x1d, 0x6b, 0x0b, 0x6f, 0x30, 0x74, 0x13, 0x77, 0x06, 0x77, 0x18, 0x76, + 0xf1, 0x71, 0x69, 0x69, 0x0f, 0x62, 0xf3, 0x49, 0x7e, 0x32, 0x55, 0x26, + 0xe2, 0x11, 0x30, 0x06, 0x23, 0x01, 0x5c, 0xf9, 0xe1, 0xf6, 0x75, 0xfc, + 0x49, 0x00, 0x6f, 0x02, 0x5f, 0x07, 0x0b, 0x08, 0xb0, 0x0a, 0xbd, 0x0d, + 0xde, 0x13, 0x8b, 0x18, 0xe2, 0x18, 0x9d, 0x20, 0x6a, 0x25, 0x00, 0x26, + 0x9f, 0x24, 0xe0, 0x1b, 0x80, 0x0c, 0x41, 0x00, 0x61, 0xff, 0x9f, 0x09, + 0xea, 0x19, 0xe2, 0x28, 0xd8, 0x40, 0xcd, 0x50, 0xb2, 0x56, 0xe3, 0x62, + 0x3d, 0x5c, 0xe4, 0x4a, 0xc0, 0x33, 0x31, 0x14, 0xa8, 0x00, 0x00, 0xfa, + 0x15, 0xf3, 0x13, 0xe9, 0x6d, 0xe8, 0x43, 0xe4, 0x75, 0xe8, 0xbf, 0xf4, + 0x2a, 0xf0, 0x7c, 0xf3, 0x77, 0xf8, 0xb7, 0xf6, 0x6a, 0xfd, 0xa4, 0x02, + 0xae, 0x02, 0x85, 0x03, 0x27, 0x0a, 0x10, 0x1d, 0xc7, 0x34, 0x10, 0x43, + 0x54, 0x49, 0xd9, 0x4c, 0x10, 0x51, 0x38, 0x51, 0xb7, 0x4a, 0xd7, 0x42, + 0x05, 0x41, 0x63, 0x44, 0xc6, 0x43, 0x18, 0x42, 0xac, 0x3e, 0x0c, 0x3e, + 0xe7, 0x3e, 0x6f, 0x3d, 0x3c, 0x37, 0x54, 0x24, 0x3d, 0x14, 0xdd, 0x0b, + 0xfd, 0xfe, 0xd6, 0xe8, 0x01, 0xd7, 0xed, 0xc8, 0xcd, 0xba, 0x76, 0xb3, + 0xff, 0xa8, 0xd7, 0xa9, 0x67, 0xb4, 0x4c, 0xbf, 0x69, 0xc4, 0x9a, 0xc0, + 0xb6, 0xc3, 0x4c, 0xcd, 0xae, 0xe2, 0x5c, 0xfb, 0x49, 0x17, 0xe0, 0x30, + 0x0c, 0x47, 0x4b, 0x62, 0xda, 0x6f, 0xcd, 0x74, 0x77, 0x75, 0x29, 0x73, + 0xc0, 0x71, 0xb5, 0x73, 0x3c, 0x76, 0x5a, 0x75, 0x37, 0x73, 0x99, 0x6c, + 0xbc, 0x5f, 0x83, 0x4b, 0xb2, 0x37, 0x14, 0x25, 0xbd, 0x18, 0xdb, 0x0a, + 0xa0, 0xfd, 0xc1, 0xf5, 0xe2, 0xea, 0x8a, 0xe2, 0xe5, 0xd9, 0x4d, 0xd8, + 0x77, 0xd3, 0xe7, 0xcc, 0x00, 0xcb, 0x02, 0xc9, 0x09, 0xcf, 0x7b, 0xd0, + 0x89, 0xcf, 0xea, 0xd8, 0xe1, 0xea, 0x79, 0xfe, 0x89, 0x14, 0xb5, 0x24, + 0x30, 0x2d, 0x10, 0x3b, 0x66, 0x44, 0x92, 0x47, 0x29, 0x4d, 0xad, 0x54, + 0xb2, 0x61, 0x75, 0x6e, 0x70, 0x72, 0x1b, 0x73, 0x8c, 0x6f, 0x2d, 0x6c, + 0x15, 0x69, 0x2c, 0x5f, 0x64, 0x4f, 0x1a, 0x37, 0x64, 0x1e, 0x39, 0x04, + 0x85, 0xea, 0xcc, 0xdd, 0x89, 0xda, 0x78, 0xd8, 0xfe, 0xd2, 0x27, 0xcc, + 0x7f, 0xc6, 0x92, 0xc0, 0xf1, 0xbb, 0x04, 0xc3, 0xf0, 0xd0, 0xd2, 0xdb, + 0x21, 0xe4, 0x3c, 0xe9, 0x44, 0xf7, 0x6b, 0xfe, 0x24, 0xf8, 0x9f, 0xf9, + 0x41, 0xff, 0x1d, 0x09, 0xa4, 0x08, 0xc7, 0x02, 0x1a, 0x03, 0x6e, 0x05, + 0xe3, 0x0c, 0x3c, 0x0c, 0xac, 0x08, 0xdf, 0xff, 0x94, 0xff, 0xea, 0x0d, + 0xbc, 0x17, 0x14, 0x1d, 0xff, 0x17, 0xa5, 0x10, 0xec, 0x07, 0xac, 0x02, + 0x1f, 0xfb, 0x20, 0xea, 0xba, 0xe2, 0x22, 0xe3, 0x95, 0xe5, 0x8b, 0xea, + 0x09, 0xf3, 0x24, 0xfd, 0x2f, 0x0b, 0xb6, 0x18, 0xc1, 0x1c, 0xf3, 0x15, + 0x2b, 0x14, 0x59, 0x1f, 0x05, 0x1d, 0x16, 0x1a, 0x02, 0x21, 0x32, 0x1a, + 0xf5, 0x13, 0xc9, 0x15, 0x15, 0x18, 0xd2, 0x22, 0x8c, 0x2a, 0x3f, 0x28, + 0x08, 0x1f, 0xd7, 0x0d, 0x3d, 0xfa, 0xed, 0xea, 0x29, 0xdc, 0xa7, 0xc7, + 0x63, 0xbd, 0x5a, 0xb4, 0x19, 0xa6, 0xd2, 0xaa, 0xc4, 0xb7, 0xfb, 0xc0, + 0x53, 0xc9, 0x1c, 0xcd, 0xf3, 0xd0, 0x4f, 0xd6, 0x71, 0xd5, 0x93, 0xce, + 0xb6, 0xcb, 0xff, 0xd0, 0x39, 0xd5, 0x27, 0xe0, 0x05, 0xf1, 0x18, 0xfa, + 0x70, 0x0b, 0xe7, 0x1e, 0x03, 0x2a, 0x4b, 0x33, 0xf4, 0x39, 0xac, 0x3f, + 0xf7, 0x45, 0x6d, 0x4b, 0xf5, 0x48, 0xf2, 0x4a, 0x40, 0x4f, 0x31, 0x4c, + 0x4e, 0x4a, 0x89, 0x46, 0x30, 0x42, 0x99, 0x3b, 0x08, 0x39, 0x36, 0x3d, + 0x39, 0x3b, 0x87, 0x37, 0x2d, 0x2f, 0x96, 0x25, 0x6e, 0x1f, 0x51, 0x10, + 0xe2, 0x04, 0x1c, 0x01, 0x0b, 0xf7, 0x90, 0xed, 0x9f, 0xef, 0x90, 0xf6, + 0x2c, 0xfa, 0x40, 0xff, 0xc9, 0x06, 0xe7, 0x0b, 0xcf, 0x0b, 0x28, 0x08, + 0x6c, 0xfe, 0x4f, 0xf7, 0x8f, 0xf6, 0xb4, 0xf4, 0x15, 0xfd, 0x93, 0x09, + 0xf6, 0x13, 0x3c, 0x16, 0xe4, 0x10, 0x96, 0x17, 0x63, 0x23, 0x4b, 0x2d, + 0x81, 0x36, 0x0b, 0x35, 0x68, 0x2b, 0x50, 0x2d, 0x63, 0x31, 0x42, 0x32, + 0x3f, 0x30, 0x36, 0x22, 0xac, 0x13, 0xaa, 0x00, 0xa1, 0xf0, 0x0f, 0xe1, + 0x01, 0xcd, 0x33, 0xc6, 0x2e, 0xc9, 0x78, 0xc8, 0x38, 0xc1, 0x9b, 0xbc, + 0xbf, 0xb7, 0x08, 0xbb, 0xf3, 0xc5, 0x72, 0xd0, 0xb4, 0xda, 0x95, 0xe1, + 0xb3, 0xef, 0x87, 0xff, 0x34, 0x0a, 0x13, 0x0d, 0xcb, 0x0f, 0x9a, 0x16, + 0xeb, 0x18, 0x99, 0x17, 0xb2, 0x12, 0x25, 0x0f, 0xa2, 0x0a, 0x12, 0x0f, + 0x43, 0x17, 0xbd, 0x13, 0x34, 0x13, 0xc3, 0x14, 0x29, 0x14, 0x94, 0x14, + 0xbf, 0x0e, 0x46, 0xff, 0xd4, 0xe9, 0xa7, 0xd7, 0xec, 0xd0, 0x89, 0xc8, + 0x29, 0xbe, 0x80, 0xc0, 0x0e, 0xc4, 0xd7, 0xcb, 0x44, 0xda, 0xd1, 0xe8, + 0xc7, 0xf2, 0xe0, 0xf3, 0xe0, 0xf6, 0xa1, 0xf2, 0x5c, 0xea, 0x3d, 0xe7, + 0x54, 0xe7, 0xe2, 0xe8, 0x1e, 0xe9, 0xe1, 0xee, 0x91, 0xed, 0xd1, 0xea, + 0xe2, 0xea, 0x82, 0xe7, 0x36, 0xe9, 0xf0, 0xea, 0xb6, 0xe9, 0xe7, 0xe2, + 0x47, 0xda, 0xee, 0xcd, 0x07, 0xc6, 0x6a, 0xc9, 0xcd, 0xc9, 0x0b, 0xc9, + 0x1a, 0xc7, 0xc3, 0xc8, 0x85, 0xce, 0x4a, 0xd1, 0x66, 0xd5, 0xd2, 0xdd, + 0x3d, 0xe8, 0xf1, 0xf1, 0x30, 0xfe, 0x5a, 0x05, 0x22, 0x02, 0x88, 0xfe, + 0x73, 0x00, 0x7e, 0xff, 0x1c, 0xf3, 0x0a, 0xe2, 0xe8, 0xd6, 0x54, 0xd7, + 0x39, 0xda, 0x2b, 0xda, 0x0c, 0xe1, 0x96, 0xeb, 0x9f, 0xf5, 0x66, 0x05, + 0x5f, 0x18, 0x19, 0x25, 0x0f, 0x22, 0x1c, 0x14, 0x38, 0x0d, 0x3b, 0x0a, + 0x82, 0x05, 0xb8, 0x07, 0x75, 0x12, 0x0d, 0x1e, 0x28, 0x24, 0x6e, 0x27, + 0xae, 0x24, 0x99, 0x1b, 0x25, 0x12, 0x52, 0x07, 0xc2, 0xf6, 0xa5, 0xe3, + 0x17, 0xda, 0x19, 0xd4, 0x83, 0xd4, 0xd2, 0xe3, 0x05, 0xf0, 0x8b, 0xf4, + 0x9a, 0xf4, 0x1a, 0xec, 0x67, 0xe6, 0xf4, 0xe6, 0xda, 0xe0, 0x6e, 0xda, + 0x4c, 0xd7, 0x1c, 0xd0, 0x03, 0xd1, 0x6a, 0xd0, 0x48, 0xc4, 0x4b, 0xc4, + 0xce, 0xd2, 0x24, 0xe1, 0x1a, 0xed, 0x39, 0xf0, 0x99, 0xe4, 0x95, 0xd4, + 0xb3, 0xca, 0xaf, 0xc7, 0xa4, 0xc9, 0x0a, 0xd1, 0x29, 0xde, 0x4b, 0xec, + 0xe9, 0xfe, 0xfb, 0x0c, 0x8b, 0x07, 0xd1, 0xfb, 0xba, 0xee, 0x31, 0xe4, + 0x96, 0xe0, 0x00, 0xdd, 0xbd, 0xdd, 0x4e, 0xe4, 0x2e, 0xed, 0xbb, 0xf4, + 0x8e, 0x02, 0xb8, 0x0e, 0xbd, 0x0e, 0x9a, 0x12, 0x8e, 0x14, 0x51, 0x14, + 0x91, 0x1a, 0x7b, 0x23, 0xd0, 0x2d, 0x54, 0x32, 0x83, 0x2d, 0x61, 0x26, + 0x49, 0x24, 0x89, 0x1d, 0x78, 0x11, 0x06, 0x0a, 0x86, 0x0b, 0x4b, 0x18, + 0x7b, 0x25, 0xe5, 0x33, 0x7d, 0x3b, 0x06, 0x3c, 0xb2, 0x3e, 0xbf, 0x35, + 0x35, 0x25, 0xe5, 0x05, 0x08, 0xdd, 0x7f, 0xc4, 0xea, 0xbd, 0x02, 0xc7, + 0xac, 0xd3, 0xae, 0xde, 0x3c, 0xe9, 0xb9, 0xed, 0x1a, 0xf0, 0x7b, 0xf4, + 0x53, 0xf3, 0x5a, 0xee, 0xd7, 0xe6, 0xcb, 0xde, 0xae, 0xdb, 0xf6, 0xd8, + 0x8f, 0xde, 0xb3, 0xe4, 0x2c, 0xe4, 0x80, 0xde, 0xe8, 0xd8, 0x62, 0xd6, + 0x9b, 0xcf, 0xd1, 0xd4, 0xf1, 0xd7, 0x4a, 0xd5, 0xcc, 0xd9, 0x72, 0xdd, + 0x86, 0xdf, 0xe9, 0xe0, 0x2e, 0xe4, 0x6a, 0xe1, 0xbd, 0xe4, 0xf7, 0xeb, + 0xa8, 0xf2, 0xee, 0xfb, 0x51, 0x00, 0xab, 0x06, 0x80, 0x07, 0x85, 0x06, + 0x55, 0x00, 0x04, 0xf3, 0xc2, 0xe9, 0x02, 0xe9, 0x41, 0xf0, 0x27, 0xfb, + 0xd7, 0x05, 0xe1, 0x04, 0x1e, 0x05, 0x79, 0x0a, 0xa9, 0x11, 0x03, 0x15, + 0x00, 0x12, 0xab, 0x18, 0x1e, 0x29, 0xbd, 0x39, 0x08, 0x40, 0x8c, 0x40, + 0xe4, 0x36, 0xbb, 0x2e, 0xf2, 0x2b, 0xa4, 0x20, 0xb7, 0x16, 0x8d, 0x08, + 0xa3, 0xf6, 0x09, 0xe4, 0xc2, 0xd5, 0xfe, 0xc8, 0x94, 0xc0, 0xd5, 0xc2, + 0x20, 0xbe, 0x78, 0xba, 0x5c, 0xb5, 0x1c, 0xaf, 0xda, 0xb0, 0x28, 0xb1, + 0x33, 0xb4, 0xd4, 0xb8, 0xf7, 0xbb, 0x89, 0xc1, 0xcc, 0xca, 0xb3, 0xd8, + 0xe6, 0xe4, 0x7e, 0xeb, 0x7f, 0xf1, 0x78, 0xfd, 0xf3, 0x0b, 0x54, 0x15, + 0x2a, 0x1b, 0x5b, 0x20, 0x88, 0x2e, 0xec, 0x41, 0x99, 0x4c, 0x36, 0x50, + 0x64, 0x4f, 0xe5, 0x4d, 0x10, 0x4c, 0xa1, 0x47, 0x13, 0x43, 0x57, 0x48, + 0x19, 0x53, 0x5b, 0x58, 0x92, 0x58, 0x74, 0x52, 0xff, 0x44, 0x4f, 0x37, + 0xef, 0x31, 0x23, 0x29, 0x80, 0x1d, 0xce, 0x12, 0xab, 0x0c, 0xa6, 0x0e, + 0x21, 0x0b, 0x0f, 0x08, 0x6c, 0x04, 0x49, 0xff, 0x11, 0xfb, 0x00, 0x02, + 0x48, 0x0e, 0x25, 0x0c, 0xbc, 0x05, 0xbf, 0x01, 0x91, 0x04, 0x79, 0x03, + 0x84, 0x02, 0xfe, 0x05, 0x26, 0x0b, 0x2e, 0x16, 0x0b, 0x1d, 0x30, 0x24, + 0x4c, 0x25, 0xff, 0x2b, 0x0b, 0x35, 0x90, 0x3e, 0xfb, 0x52, 0x4a, 0x51, + 0x1d, 0x4e, 0xe7, 0x50, 0x65, 0x48, 0x75, 0x42, 0x52, 0x37, 0xe7, 0x36, + 0x08, 0x3e, 0xcd, 0x36, 0xb0, 0x2c, 0x0d, 0x24, 0xa9, 0x1e, 0xaf, 0x16, + 0x2d, 0x0f, 0x10, 0x09, 0xfc, 0xfd, 0xd7, 0xf5, 0xcc, 0xef, 0xd4, 0xed, + 0x81, 0xe8, 0x58, 0xe2, 0x54, 0xde, 0x2e, 0xdf, 0x07, 0xf0, 0x44, 0xfb, + 0x2a, 0x02, 0x9b, 0x04, 0x93, 0xf9, 0xc4, 0xf1, 0xec, 0xf1, 0x05, 0xf9, + 0xf9, 0x01, 0x43, 0x0a, 0x99, 0x15, 0x61, 0x24, 0x1a, 0x36, 0x95, 0x43, + 0x0d, 0x47, 0x33, 0x49, 0x56, 0x4d, 0x69, 0x50, 0xa8, 0x52, 0x52, 0x57, + 0x64, 0x5b, 0x6f, 0x5b, 0x7f, 0x58, 0x06, 0x50, 0xc5, 0x4f, 0x97, 0x4d, + 0xd8, 0x4a, 0xea, 0x4c, 0x9d, 0x42, 0x14, 0x39, 0xb5, 0x2e, 0x47, 0x25, + 0x18, 0x1b, 0x41, 0x0e, 0x9a, 0x05, 0x1e, 0x00, 0x86, 0x02, 0x4a, 0x06, + 0xef, 0x0d, 0x5c, 0x14, 0x5f, 0x17, 0x19, 0x18, 0xcd, 0x19, 0x60, 0x1c, + 0x25, 0x19, 0x23, 0x10, 0x23, 0x00, 0x88, 0xfc, 0xe4, 0xf9, 0xa8, 0xf2, + 0x22, 0xf5, 0xdf, 0xf9, 0x21, 0x00, 0x1f, 0x03, 0x9e, 0xff, 0x2a, 0xf5, + 0x6d, 0xe8, 0x46, 0xda, 0x60, 0xcf, 0xdb, 0xca, 0x82, 0xc7, 0xec, 0xc3, + 0x5b, 0xc5, 0x63, 0xd4, 0xfc, 0xe3, 0x43, 0xf7, 0x3b, 0x0e, 0x12, 0x1a, + 0xaf, 0x1c, 0xfe, 0x18, 0x04, 0x18, 0x73, 0x1d, 0x82, 0x27, 0x9a, 0x2c, + 0x72, 0x2e, 0x88, 0x34, 0x75, 0x3b, 0xf2, 0x42, 0x73, 0x43, 0xbe, 0x47, + 0x32, 0x46, 0x4c, 0x39, 0x1a, 0x34, 0xf5, 0x2a, 0x49, 0x25, 0x33, 0x1c, + 0x56, 0x11, 0x9b, 0x0d, 0xc8, 0x02, 0x8b, 0x00, 0xd0, 0x00, 0xf2, 0xff, + 0xdd, 0xfd, 0xac, 0xf8, 0x2e, 0xfb, 0x34, 0xfa, 0x9d, 0xf8, 0x2d, 0xf8, + 0x3d, 0xfd, 0x4c, 0x07, 0x06, 0x07, 0x32, 0x09, 0x22, 0x0a, 0x32, 0x04, + 0x92, 0x05, 0x52, 0x0e, 0x5b, 0x19, 0xdc, 0x1a, 0xd2, 0x1a, 0x31, 0x1e, + 0x92, 0x15, 0x61, 0x09, 0x3a, 0xff, 0x84, 0xef, 0x90, 0xda, 0xe8, 0xce, + 0x0d, 0xcb, 0x92, 0xbc, 0x34, 0xa8, 0x4d, 0x9b, 0xd5, 0x96, 0x03, 0x96, + 0xb3, 0x9e, 0xbf, 0xaa, 0x9f, 0xb5, 0xa2, 0xcb, 0xfa, 0xe0, 0xb6, 0xf1, + 0x2d, 0x07, 0xcc, 0x12, 0x06, 0x18, 0x39, 0x1b, 0x01, 0x1c, 0xe9, 0x29, + 0x74, 0x33, 0x6a, 0x2f, 0x7d, 0x2c, 0x16, 0x35, 0x7e, 0x44, 0xe5, 0x46, + 0x3e, 0x43, 0xf6, 0x39, 0xd8, 0x23, 0x03, 0x0e, 0x10, 0xf8, 0x27, 0xe0, + 0xd5, 0xcf, 0xd1, 0xc4, 0x2c, 0xc2, 0xea, 0xca, 0xab, 0xd3, 0x22, 0xd9, + 0x90, 0xe0, 0x2a, 0xea, 0x63, 0xf8, 0xad, 0x07, 0x3f, 0x0b, 0x37, 0x10, + 0xaa, 0x14, 0x5f, 0x12, 0x65, 0x13, 0x22, 0x13, 0x83, 0x17, 0x14, 0x1f, + 0xc0, 0x25, 0x4d, 0x2a, 0x22, 0x2d, 0x90, 0x35, 0xd0, 0x45, 0xcb, 0x4d, + 0xe2, 0x46, 0x93, 0x40, 0x5d, 0x3b, 0x3f, 0x3c, 0x31, 0x3a, 0x4f, 0x33, + 0x8b, 0x2b, 0x54, 0x20, 0x5f, 0x19, 0x16, 0x11, 0xf7, 0x0b, 0x5c, 0x04, + 0x50, 0xfd, 0xec, 0xf6, 0xf7, 0xe9, 0x26, 0xdf, 0xad, 0xd2, 0xda, 0xc9, + 0xf4, 0xc5, 0x0e, 0xbf, 0xd4, 0xb7, 0x97, 0xb8, 0xd8, 0xbe, 0x69, 0xcc, + 0x9c, 0xe2, 0xac, 0xf9, 0x6d, 0x14, 0x2b, 0x30, 0xb2, 0x43, 0x26, 0x4f, + 0x7d, 0x5d, 0x94, 0x68, 0xca, 0x6d, 0x2e, 0x70, 0xec, 0x6e, 0x35, 0x6e, + 0xdd, 0x68, 0xd2, 0x5d, 0xb7, 0x4e, 0x48, 0x43, 0xf5, 0x35, 0x1d, 0x25, + 0xf5, 0x15, 0x32, 0x04, 0x8a, 0xf7, 0xa6, 0xef, 0xd1, 0xea, 0x6f, 0xe5, + 0x72, 0xe1, 0x73, 0xe1, 0x28, 0xe3, 0x05, 0xec, 0x7f, 0xfa, 0x2d, 0x07, + 0xee, 0x13, 0x97, 0x27, 0xa0, 0x33, 0x50, 0x39, 0x11, 0x38, 0xc2, 0x26, + 0x63, 0x19, 0x2e, 0x0c, 0xcf, 0xfa, 0xab, 0xe9, 0x17, 0xd5, 0xaf, 0xc6, + 0x13, 0xc1, 0x8a, 0xc2, 0xa8, 0xc0, 0x70, 0xbc, 0x44, 0xbe, 0x8b, 0xc4, + 0xb8, 0xd9, 0xd0, 0xf2, 0x3c, 0xfe, 0xae, 0xfe, 0xaf, 0xfd, 0x5a, 0xfa, + 0xcc, 0xef, 0x2d, 0xe3, 0x67, 0xd0, 0x2b, 0xc3, 0xe4, 0xc0, 0xc0, 0xbd, + 0x9d, 0xbe, 0xe3, 0xc8, 0xf4, 0xd1, 0x9b, 0xd7, 0x26, 0xe1, 0xe1, 0xe1, + 0x46, 0xdd, 0xf9, 0xda, 0x97, 0xd5, 0x31, 0xd6, 0x23, 0xdb, 0x3c, 0xda, + 0xfe, 0xda, 0x39, 0xe4, 0x45, 0xf2, 0x70, 0x01, 0xd2, 0x10, 0x25, 0x1a, + 0x9f, 0x15, 0x7c, 0x0a, 0x55, 0xfe, 0x4c, 0xf9, 0xef, 0xf6, 0x99, 0xf0, + 0xea, 0xf0, 0xf3, 0xf4, 0xdc, 0xf7, 0xaf, 0xf7, 0x5f, 0xf6, 0xbc, 0xee, + 0xfd, 0xe6, 0x5b, 0xe4, 0x74, 0xde, 0x04, 0xdc, 0xf8, 0xdc, 0x31, 0xdf, + 0x47, 0xde, 0xc6, 0xdf, 0x5a, 0xe5, 0xc0, 0xe8, 0x29, 0xec, 0xaf, 0xe6, + 0x3c, 0xe4, 0xc6, 0xe3, 0xa2, 0xd7, 0xe9, 0xce, 0x11, 0xc3, 0xa3, 0xbe, + 0x3d, 0xc8, 0xa6, 0xca, 0xe7, 0xd4, 0x0c, 0xe0, 0x8f, 0xe6, 0xa6, 0xfa, + 0xa8, 0x0e, 0xba, 0x18, 0xed, 0x27, 0xdf, 0x34, 0x57, 0x37, 0x11, 0x3c, + 0x18, 0x34, 0x0b, 0x28, 0x3d, 0x1f, 0x0c, 0x11, 0xb2, 0x06, 0x06, 0xf5, + 0x89, 0xdd, 0x58, 0xd5, 0xbe, 0xdc, 0x71, 0xe4, 0x6c, 0xe7, 0xf8, 0xe0, + 0xd4, 0xda, 0x7c, 0xdc, 0x28, 0xda, 0x30, 0xcf, 0x89, 0xc4, 0x6c, 0xbc, + 0xff, 0xb8, 0x7f, 0xbf, 0xdb, 0xc0, 0xc4, 0xc3, 0x4d, 0xc9, 0x83, 0xd4, + 0x5e, 0xe0, 0xfe, 0xe6, 0xde, 0xf1, 0x4b, 0xee, 0x2e, 0xe8, 0xbb, 0xe1, + 0xe9, 0xe1, 0xad, 0xec, 0x36, 0xf9, 0x77, 0x0e, 0x7b, 0x1b, 0xc2, 0x1f, + 0xe7, 0x20, 0xf5, 0x20, 0xf1, 0x25, 0xaa, 0x34, 0x74, 0x3b, 0xcd, 0x3c, + 0x02, 0x43, 0x77, 0x39, 0x85, 0x29, 0x42, 0x1d, 0x80, 0x10, 0xa4, 0xfb, + 0x31, 0xee, 0xb5, 0xea, 0x82, 0xea, 0xb2, 0xf3, 0x3f, 0xf6, 0x92, 0xfe, + 0xd0, 0x04, 0x22, 0x06, 0xe6, 0x0b, 0x7a, 0x02, 0x9d, 0xf7, 0x4d, 0xed, + 0xed, 0xdf, 0xd8, 0xd3, 0xb6, 0xc4, 0xcf, 0xb7, 0x0c, 0xae, 0xf3, 0xa8, + 0xb9, 0xa7, 0xd0, 0xa9, 0xf7, 0xad, 0xc5, 0xb4, 0x71, 0xbc, 0x47, 0xbd, + 0x57, 0xbc, 0xd9, 0xc0, 0x9c, 0xbe, 0x1a, 0xb7, 0xdc, 0xbd, 0xa2, 0xc7, + 0x53, 0xd4, 0xf7, 0xe3, 0x70, 0xed, 0xce, 0xff, 0x62, 0x14, 0xee, 0x23, + 0xa5, 0x32, 0x4d, 0x3d, 0xdc, 0x3d, 0x09, 0x38, 0x10, 0x3d, 0xb4, 0x4a, + 0xff, 0x57, 0xdf, 0x63, 0x96, 0x6b, 0x6d, 0x70, 0x18, 0x72, 0x7d, 0x6c, + 0x17, 0x61, 0x43, 0x49, 0x6a, 0x25, 0xc8, 0x00, 0xff, 0xd9, 0x11, 0xbb, + 0xf9, 0xaf, 0x32, 0xb2, 0x2b, 0xb7, 0x97, 0xba, 0x51, 0xc0, 0xc1, 0xc7, + 0xab, 0xd5, 0x6a, 0xe9, 0x96, 0xf6, 0xf4, 0x02, 0x56, 0x0c, 0x4b, 0x17, + 0xf9, 0x23, 0xe7, 0x28, 0x81, 0x30, 0x33, 0x29, 0x03, 0x20, 0xbe, 0x24, + 0xef, 0x20, 0x25, 0x1f, 0x47, 0x1a, 0xb4, 0x0a, 0xe5, 0xf9, 0x35, 0xef, + 0xbe, 0xe8, 0xea, 0xe4, 0xd0, 0xe9, 0x15, 0xed, 0x7e, 0xf2, 0x8a, 0xf0, + 0xff, 0xe1, 0x71, 0xd4, 0x8f, 0xc8, 0x9b, 0xc9, 0x61, 0xd1, 0xe0, 0xdb, + 0x19, 0xea, 0x2c, 0xfa, 0x97, 0x06, 0x70, 0x07, 0xc8, 0x03, 0x41, 0xf4, + 0x37, 0xe4, 0xff, 0xe2, 0x62, 0xea, 0x36, 0xf3, 0x7a, 0x00, 0x22, 0x0f, + 0xeb, 0x15, 0x16, 0x1f, 0xfc, 0x28, 0x21, 0x2c, 0xde, 0x1f, 0x53, 0x17, + 0xa0, 0x1c, 0xdc, 0x1c, 0xfb, 0x1d, 0x46, 0x19, 0x03, 0x0c, 0x1d, 0x02, + 0x18, 0xff, 0xa8, 0xfb, 0x12, 0xfa, 0x23, 0xf8, 0x00, 0xf0, 0x0d, 0xed, + 0xfc, 0xeb, 0x9a, 0xe9, 0x8f, 0xe6, 0xa3, 0xe8, 0x13, 0xf2, 0x71, 0xfa, + 0x0b, 0xfc, 0xf8, 0xf7, 0x04, 0xf8, 0xa3, 0xf9, 0x42, 0xf6, 0x06, 0xf5, + 0xf4, 0xfa, 0x6f, 0x05, 0xbd, 0x0c, 0x35, 0x0e, 0xa7, 0x0c, 0x18, 0x02, + 0x15, 0xfc, 0x9d, 0x01, 0x04, 0x08, 0xb6, 0x11, 0xdb, 0x12, 0x53, 0x0c, + 0xaf, 0x09, 0xf4, 0x0a, 0x92, 0x10, 0x00, 0x14, 0xf5, 0x16, 0x58, 0x1b, + 0x83, 0x1d, 0x8b, 0x22, 0xee, 0x2b, 0xee, 0x2b, 0x99, 0x18, 0x0a, 0x03, + 0x63, 0xee, 0x5a, 0xd6, 0x76, 0xc8, 0xfd, 0xc0, 0x0d, 0xcb, 0x3d, 0xd8, + 0x79, 0xde, 0x93, 0xf3, 0x8b, 0xfd, 0x99, 0xfa, 0x79, 0xf6, 0x6b, 0xee, + 0x20, 0xf3, 0x6a, 0x00, 0xc6, 0x0c, 0x74, 0x1e, 0xdb, 0x32, 0x7a, 0x46, + 0xe3, 0x53, 0x7b, 0x59, 0x9f, 0x62, 0xcc, 0x63, 0x85, 0x60, 0xc0, 0x5e, + 0xb2, 0x54, 0xa0, 0x52, 0x95, 0x55, 0x95, 0x53, 0xb8, 0x4a, 0x07, 0x3a, + 0xd7, 0x2d, 0x13, 0x22, 0xe5, 0x12, 0x69, 0x06, 0xc8, 0xfc, 0xf7, 0xfe, + 0x30, 0x09, 0x3c, 0x11, 0x1e, 0x1a, 0x16, 0x24, 0x99, 0x29, 0x08, 0x2f, + 0x8e, 0x36, 0x97, 0x2f, 0x09, 0x2a, 0xe5, 0x2b, 0xa4, 0x2b, 0xa8, 0x31, + 0x75, 0x2f, 0x5f, 0x30, 0xcc, 0x31, 0xc9, 0x28, 0x47, 0x26, 0x62, 0x1e, + 0xc2, 0x14, 0x86, 0x0c, 0xe0, 0x03, 0x0b, 0x01, 0x33, 0xfb, 0xc4, 0xf6, + 0x15, 0xf9, 0x99, 0x00, 0xd0, 0x04, 0x8b, 0x0b, 0x2d, 0x14, 0xbe, 0x17, + 0xde, 0x24, 0xce, 0x31, 0xba, 0x3d, 0x39, 0x49, 0xdb, 0x4e, 0xe7, 0x54, + 0x7c, 0x55, 0xb2, 0x49, 0xb9, 0x35, 0xf3, 0x25, 0xbc, 0x18, 0x7a, 0x0e, + 0x37, 0x05, 0x3d, 0x04, 0x80, 0x0b, 0x96, 0x12, 0x6b, 0x1b, 0x3c, 0x1e, + 0x9d, 0x28, 0x53, 0x31, 0x65, 0x32, 0x78, 0x34, 0xbf, 0x30, 0x56, 0x30, + 0x4c, 0x2e, 0x49, 0x23, 0x84, 0x14, 0x1e, 0x0b, 0x4a, 0x07, 0x63, 0x05, + 0xc2, 0x04, 0xcd, 0x01, 0x85, 0xfa, 0xc6, 0xf6, 0x40, 0xf5, 0xcf, 0xee, + 0x5a, 0xe9, 0x6e, 0xe0, 0xc7, 0xdc, 0xce, 0xd8, 0x2c, 0xd4, 0xf3, 0xd6, + 0xb4, 0xd6, 0xaf, 0xdb, 0xab, 0xdb, 0x5a, 0xda, 0x9d, 0xe4, 0x99, 0xf6, + 0x8b, 0x0c, 0xaa, 0x1c, 0x62, 0x22, 0x47, 0x29, 0x47, 0x35, 0xb8, 0x33, + 0x02, 0x2a, 0x62, 0x19, 0x90, 0x01, 0x3b, 0xf3, 0xf8, 0xef, 0x7b, 0xed, + 0x49, 0xea, 0x84, 0xee, 0xa5, 0xee, 0xb2, 0xeb, 0xe1, 0xef, 0xb4, 0xf3, + 0xc2, 0xf4, 0x55, 0xf5, 0x5f, 0xef, 0xf1, 0xe9, 0x72, 0xef, 0x4a, 0xf5, + 0x38, 0xf4, 0xf4, 0xec, 0x89, 0xe0, 0xd2, 0xd5, 0x22, 0xd4, 0x4c, 0xd0, + 0x1b, 0xca, 0xf7, 0xd1, 0x05, 0xe8, 0x95, 0xfa, 0xcd, 0x0a, 0x59, 0x1f, + 0x6a, 0x2c, 0x66, 0x40, 0xc9, 0x51, 0x22, 0x54, 0xe8, 0x51, 0xaa, 0x49, + 0x54, 0x43, 0xed, 0x3d, 0x32, 0x3b, 0x88, 0x36, 0x23, 0x33, 0x02, 0x3c, + 0x88, 0x41, 0x15, 0x45, 0x05, 0x46, 0x0c, 0x38, 0x32, 0x27, 0x93, 0x16, + 0xd3, 0x04, 0x0c, 0xf4, 0xe7, 0xeb, 0xea, 0xef, 0xb5, 0xf4, 0xc6, 0xff, + 0x4d, 0x02, 0x66, 0xfe, 0xe8, 0x04, 0x38, 0x08, 0xd9, 0x0a, 0x21, 0x10, + 0x82, 0x0f, 0xd0, 0x08, 0xa3, 0x02, 0xd8, 0xf2, 0x98, 0xe3, 0xfb, 0xdc, + 0xce, 0xd2, 0x14, 0xce, 0x65, 0xcc, 0xea, 0xd0, 0x15, 0xe4, 0x16, 0xfa, + 0x53, 0x05, 0x95, 0x0e, 0x1b, 0x11, 0x83, 0x0d, 0xe3, 0x16, 0xbc, 0x19, + 0x3d, 0x14, 0x73, 0x13, 0x9d, 0x12, 0x83, 0x15, 0x5b, 0x20, 0x43, 0x29, + 0xe2, 0x2a, 0x2d, 0x2e, 0xa7, 0x2f, 0x9d, 0x31, 0xde, 0x2f, 0xc0, 0x21, + 0xf8, 0x11, 0x9c, 0xfe, 0xf6, 0xed, 0xbd, 0xe5, 0x6b, 0xe1, 0x4b, 0xe4, + 0x78, 0xe9, 0x01, 0xf0, 0x5e, 0xf7, 0x91, 0xfd, 0xdc, 0x01, 0x8b, 0x09, + 0x69, 0x11, 0x5b, 0x17, 0x26, 0x1d, 0x11, 0x18, 0x44, 0x15, 0xb2, 0x14, + 0x3e, 0x09, 0xba, 0xfb, 0x33, 0xef, 0x61, 0xe1, 0x9f, 0xd9, 0xfa, 0xd8, + 0x50, 0xd7, 0x6b, 0xda, 0x8b, 0xe3, 0x14, 0xf2, 0xc2, 0xfc, 0x3e, 0x01, + 0xfb, 0x08, 0xcc, 0x11, 0x27, 0x18, 0x54, 0x1b, 0x7b, 0x1e, 0xcb, 0x1b, + 0x80, 0x14, 0xbd, 0x0b, 0x88, 0xff, 0x1b, 0xf1, 0xf9, 0xe6, 0x47, 0xe4, + 0xd0, 0xee, 0x9b, 0x02, 0x08, 0x08, 0x36, 0x09, 0x82, 0x08, 0xa2, 0xff, + 0xd7, 0xf3, 0x26, 0xe6, 0x97, 0xdd, 0x5f, 0xdc, 0x39, 0xe1, 0x11, 0xe3, + 0xbf, 0xea, 0x0f, 0xfc, 0x6f, 0x09, 0x45, 0x0e, 0x18, 0x13, 0xb1, 0x18, + 0xdc, 0x11, 0x54, 0x0d, 0xac, 0x0b, 0x41, 0x05, 0xc8, 0x00, 0x97, 0xf8, + 0x85, 0xf7, 0x42, 0xfd, 0x86, 0xfd, 0x64, 0x06, 0xa1, 0x14, 0x35, 0x14, + 0xd8, 0x0a, 0x12, 0x07, 0x36, 0x03, 0x6e, 0xf9, 0x91, 0xf7, 0x0a, 0x01, + 0xc1, 0x06, 0x5d, 0x0b, 0x44, 0x15, 0xfc, 0x13, 0xc9, 0x0a, 0xc9, 0x00, + 0xdc, 0xf8, 0x36, 0xfb, 0x3a, 0x02, 0xd0, 0x10, 0xcc, 0x1d, 0x8e, 0x21, + 0xe2, 0x22, 0x70, 0x29, 0x45, 0x30, 0xae, 0x2d, 0xd5, 0x2d, 0xf9, 0x26, + 0xa4, 0x1e, 0x6f, 0x1f, 0xe0, 0x1c, 0x80, 0x19, 0x11, 0x13, 0x8d, 0x0a, + 0x01, 0xfe, 0x60, 0xf1, 0x98, 0xe3, 0x55, 0xcb, 0xdf, 0xb2, 0xc4, 0xa3, + 0x0b, 0xa4, 0x2c, 0xa7, 0xcc, 0xaa, 0x39, 0xb4, 0x28, 0xbd, 0xe5, 0xcc, + 0xe8, 0xd3, 0x4c, 0xd1, 0x34, 0xd3, 0x4b, 0xd7, 0xc8, 0xe7, 0xed, 0xf5, + 0x39, 0xfd, 0xf0, 0x06, 0x36, 0x0d, 0xd4, 0x15, 0x35, 0x1b, 0x1f, 0x20, + 0xd7, 0x1e, 0x6d, 0x14, 0xc2, 0x0f, 0x07, 0x0b, 0x6a, 0x08, 0xc2, 0x04, + 0xe0, 0xfe, 0x8a, 0xf4, 0x3e, 0xe8, 0x2b, 0xe4, 0x86, 0xd5, 0x7d, 0xc5, + 0x16, 0xc1, 0xac, 0xc2, 0xdf, 0xc7, 0x40, 0xd2, 0x15, 0xe2, 0x08, 0xeb, + 0xed, 0xfd, 0xa5, 0x0d, 0x87, 0x10, 0x06, 0x1c, 0xd5, 0x1b, 0xc0, 0x16, + 0x84, 0x15, 0xf2, 0x0c, 0x3b, 0x07, 0x53, 0x05, 0xf5, 0xf8, 0x52, 0xe7, + 0xa6, 0xdf, 0x2d, 0xd7, 0xab, 0xd5, 0x19, 0xdd, 0x15, 0xdd, 0xfa, 0xd5, + 0xe8, 0xcb, 0x4a, 0xc6, 0x00, 0xc5, 0x51, 0xc8, 0xd9, 0xc8, 0x22, 0xc0, + 0xa7, 0xb4, 0x81, 0xad, 0x31, 0xad, 0x20, 0xb6, 0x0d, 0xc6, 0xc4, 0xcf, + 0xf2, 0xd3, 0xfe, 0xd4, 0x82, 0xd4, 0x5e, 0xd9, 0x1d, 0xe6, 0xfb, 0xea, + 0x3e, 0xe6, 0xbd, 0xde, 0x96, 0xce, 0xfc, 0xc7, 0x33, 0xc9, 0x48, 0xcf, + 0x00, 0xdc, 0x4d, 0xe3, 0xa2, 0xec, 0x7a, 0xf9, 0x66, 0x02, 0x9b, 0xff, + 0x62, 0xf6, 0x3f, 0xeb, 0x76, 0xda, 0xa1, 0xd5, 0xe1, 0xdf, 0xfc, 0xe7, + 0x27, 0xf0, 0x54, 0xfb, 0xee, 0x05, 0xda, 0x16, 0xfb, 0x2a, 0xaf, 0x39, + 0xcc, 0x46, 0xdb, 0x4e, 0x31, 0x52, 0x4a, 0x4e, 0xa4, 0x44, 0x48, 0x3c, + 0xa3, 0x20, 0xc2, 0x04, 0xbe, 0xf7, 0x31, 0xe8, 0x2e, 0xdc, 0x25, 0xd0, + 0xf9, 0xc4, 0x9b, 0xb7, 0x27, 0xb2, 0x53, 0xb7, 0x75, 0xbb, 0x1e, 0xbe, + 0x88, 0xbf, 0x84, 0xc4, 0x70, 0xc4, 0xac, 0xc7, 0x71, 0xd1, 0xdc, 0xdc, + 0x01, 0xea, 0x1d, 0xf8, 0x83, 0x07, 0x51, 0x10, 0x5f, 0x19, 0x24, 0x20, + 0xc1, 0x24, 0x34, 0x2c, 0xbb, 0x2c, 0x52, 0x23, 0x0d, 0x1b, 0x89, 0x11, + 0x97, 0xff, 0xf7, 0xee, 0xca, 0xdd, 0x1f, 0xd0, 0x17, 0xc8, 0x5a, 0xc8, + 0xec, 0xd2, 0x3b, 0xe1, 0x04, 0xf2, 0xdd, 0xfe, 0x57, 0x0d, 0xc2, 0x17, + 0x94, 0x20, 0x6c, 0x22, 0x65, 0x1c, 0x81, 0x21, 0xf6, 0x22, 0xb5, 0x32, + 0x71, 0x42, 0x82, 0x42, 0x91, 0x49, 0x5a, 0x44, 0xa9, 0x3c, 0x59, 0x34, + 0x52, 0x1f, 0x8d, 0x05, 0x33, 0xf6, 0x30, 0xf3, 0xc6, 0xee, 0x0e, 0xe7, + 0x3a, 0xe3, 0xd5, 0xe5, 0x08, 0xe2, 0x49, 0xe8, 0x17, 0xf5, 0xb2, 0xff, + 0x5c, 0x06, 0xa4, 0x04, 0xe6, 0x09, 0x9f, 0x0c, 0x19, 0x0c, 0xec, 0x08, + 0xe4, 0x05, 0x4d, 0xfc, 0xf2, 0xee, 0xd1, 0xe3, 0x19, 0xd2, 0x51, 0xc3, + 0xb7, 0xb7, 0x8a, 0xb7, 0xd5, 0xbd, 0xf0, 0xc7, 0xf8, 0xd0, 0x84, 0xdd, + 0xbb, 0xe8, 0xc1, 0xe4, 0xfc, 0xe7, 0xd7, 0xea, 0xf5, 0xea, 0x66, 0xe5, + 0x66, 0xe0, 0xbd, 0xdd, 0x76, 0xdb, 0x5e, 0xe9, 0xd5, 0xf4, 0x01, 0xfb, + 0x77, 0xf9, 0x95, 0xf5, 0x2f, 0xf5, 0x02, 0xf2, 0x50, 0xf1, 0x58, 0xed, + 0x56, 0xe6, 0xcc, 0xdf, 0x35, 0xdb, 0xe3, 0xd9, 0x18, 0xdf, 0xc5, 0xe4, + 0xd6, 0xe7, 0x4b, 0xe8, 0x49, 0xeb, 0xc2, 0xf7, 0xa8, 0x03, 0x74, 0x10, + 0x9a, 0x1a, 0x13, 0x20, 0x34, 0x1e, 0xc9, 0x16, 0x2c, 0x13, 0x00, 0x0f, + 0x10, 0x11, 0xc1, 0x18, 0x32, 0x22, 0x3a, 0x22, 0x4e, 0x20, 0x6f, 0x28, + 0x0f, 0x29, 0x42, 0x2b, 0xa9, 0x2d, 0x7d, 0x31, 0xb9, 0x36, 0xa3, 0x37, + 0x3c, 0x3f, 0x15, 0x3f, 0x86, 0x3f, 0xb1, 0x4c, 0xf6, 0x55, 0xaa, 0x51, + 0x56, 0x45, 0x8b, 0x36, 0x7f, 0x25, 0xed, 0x17, 0x37, 0x0f, 0x29, 0x03, + 0x01, 0xee, 0xa9, 0xde, 0xb4, 0xd9, 0xe5, 0xd6, 0x25, 0xcf, 0xdf, 0xc7, + 0x25, 0xc3, 0x34, 0xbf, 0x22, 0xcb, 0x62, 0xd7, 0x1c, 0xdf, 0x3d, 0xe8, + 0x02, 0xf4, 0x8f, 0xff, 0xe5, 0x0a, 0x90, 0x1f, 0x50, 0x29, 0xd6, 0x34, + 0x16, 0x3f, 0x23, 0x3a, 0x70, 0x39, 0x4d, 0x3d, 0x0b, 0x46, 0x1d, 0x4d, + 0x2c, 0x4c, 0x87, 0x42, 0x73, 0x3f, 0x18, 0x47, 0x2b, 0x50, 0xb6, 0x53, + 0x2a, 0x4c, 0x27, 0x40, 0xe4, 0x2d, 0x4f, 0x22, 0x13, 0x1d, 0x8c, 0x18, + 0x9c, 0x1a, 0xe7, 0x27, 0x3d, 0x3f, 0xa1, 0x50, 0xff, 0x5f, 0x57, 0x68, + 0xd2, 0x6a, 0x07, 0x6b, 0x87, 0x63, 0xcd, 0x5b, 0x93, 0x51, 0x0f, 0x46, + 0x5f, 0x3b, 0x5a, 0x35, 0x49, 0x35, 0x01, 0x3b, 0xa7, 0x3d, 0xe1, 0x38, + 0x47, 0x2e, 0x8c, 0x13, 0xe7, 0xf7, 0xe8, 0xe2, 0xba, 0xd4, 0xec, 0xcf, + 0x00, 0xcb, 0x82, 0xcb, 0x1b, 0xd4, 0x6b, 0xdf, 0x25, 0xe9, 0x7e, 0xf0, + 0x1a, 0xf6, 0x4c, 0xfa, 0x7d, 0x00, 0x23, 0x0a, 0x4f, 0x13, 0xc0, 0x21, + 0x3f, 0x3f, 0x6a, 0x5d, 0xc7, 0x6e, 0x10, 0x76, 0x0f, 0x78, 0xd1, 0x76, + 0xc5, 0x71, 0x87, 0x68, 0x57, 0x56, 0xad, 0x39, 0x3d, 0x1e, 0x50, 0x09, + 0xf8, 0xf8, 0x3c, 0xef, 0x2e, 0xe5, 0x18, 0xdc, 0xa3, 0xd3, 0x29, 0xc6, + 0xa1, 0xba, 0x45, 0xb1, 0x64, 0xaa, 0xa7, 0xa6, 0x7c, 0xaa, 0xab, 0xb7, + 0x2f, 0xc3, 0x73, 0xce, 0x21, 0xda, 0x57, 0xea, 0x28, 0x05, 0x9d, 0x1e, + 0xbf, 0x33, 0xf4, 0x40, 0x90, 0x49, 0x8b, 0x59, 0xf1, 0x65, 0x4c, 0x6b, + 0x72, 0x6d, 0x44, 0x6f, 0x6b, 0x73, 0x7b, 0x74, 0x3d, 0x73, 0x6a, 0x6f, + 0x89, 0x68, 0x1f, 0x5a, 0xa3, 0x3d, 0x8a, 0x1c, 0xf2, 0xfe, 0x27, 0xe5, + 0xfa, 0xcf, 0xdf, 0xbf, 0x59, 0xb4, 0x7d, 0xab, 0xe0, 0xac, 0xe3, 0xb5, + 0x9c, 0xbc, 0x60, 0xbf, 0xd4, 0xb9, 0xff, 0xb3, 0xeb, 0xb0, 0x83, 0xaf, + 0x8b, 0xb0, 0x74, 0xaf, 0x4a, 0xb3, 0x05, 0xba, 0xc6, 0xc5, 0x3f, 0xd8, + 0x72, 0xe5, 0xcb, 0xf1, 0xed, 0x02, 0x24, 0x15, 0x63, 0x21, 0x13, 0x24, + 0xde, 0x25, 0xdf, 0x30, 0x25, 0x46, 0x34, 0x5b, 0x11, 0x65, 0xa1, 0x67, + 0xaf, 0x6b, 0x6d, 0x6d, 0x0d, 0x6c, 0xb3, 0x69, 0x99, 0x5f, 0xd8, 0x54, + 0xbf, 0x4b, 0x21, 0x3f, 0xc5, 0x30, 0x3c, 0x1d, 0x2b, 0x0a, 0x3c, 0xfa, + 0x17, 0xed, 0x63, 0xe0, 0x43, 0xd5, 0x4d, 0xcf, 0xb4, 0xcf, 0x30, 0xd9, + 0x56, 0xe0, 0xa1, 0xe7, 0xd6, 0xf0, 0x08, 0xf6, 0x94, 0x00, 0x9d, 0x11, + 0x22, 0x1a, 0x58, 0x14, 0x16, 0x11, 0x22, 0x18, 0x50, 0x20, 0x14, 0x25, + 0xea, 0x2a, 0x48, 0x2a, 0x75, 0x26, 0xf9, 0x21, 0x3b, 0x18, 0x4e, 0x11, + 0x78, 0x07, 0x84, 0x06, 0xe1, 0x06, 0x7b, 0x06, 0x6d, 0x11, 0x83, 0x14, + 0x20, 0x19, 0x0f, 0x24, 0xe4, 0x2d, 0x01, 0x32, 0x40, 0x32, 0x72, 0x35, + 0xdc, 0x34, 0xf9, 0x2b, 0xd6, 0x1f, 0x72, 0x1b, 0x9d, 0x14, 0x64, 0x0a, + 0xcb, 0x01, 0x5c, 0xfc, 0xac, 0xfa, 0x52, 0xf4, 0x07, 0xf1, 0xf4, 0xed, + 0x9f, 0xee, 0x47, 0xf1, 0x4c, 0xf2, 0xa3, 0xfb, 0x36, 0x02, 0x27, 0x02, + 0x92, 0xfe, 0x75, 0xf9, 0x63, 0xee, 0xe5, 0xe1, 0xfc, 0xda, 0xdd, 0xd6, + 0x45, 0xdd, 0x00, 0xea, 0x4c, 0xf8, 0xa0, 0x02, 0x00, 0x11, 0xd9, 0x20, + 0x58, 0x24, 0x57, 0x29, 0x92, 0x30, 0x60, 0x34, 0xf4, 0x2e, 0xf4, 0x27, + 0xe9, 0x23, 0x20, 0x25, 0xea, 0x23, 0x1c, 0x1b, 0x8a, 0x20, 0x05, 0x1c, + 0xda, 0x13, 0x2a, 0x12, 0x01, 0x06, 0x76, 0xfc, 0x09, 0xf4, 0xca, 0xeb, + 0x47, 0xe4, 0x29, 0xe6, 0x24, 0xe5, 0x75, 0xde, 0x5f, 0xdb, 0x90, 0xd4, + 0x39, 0xd3, 0x01, 0xcd, 0x64, 0xc7, 0xdb, 0xce, 0x94, 0xd9, 0x71, 0xe5, + 0x39, 0xf7, 0x1d, 0x0a, 0x94, 0x19, 0x5b, 0x29, 0xed, 0x2b, 0xc4, 0x27, + 0x86, 0x20, 0x40, 0x0f, 0xc6, 0x01, 0x97, 0xf3, 0x37, 0xe6, 0xf0, 0xe0, + 0x9b, 0xdd, 0x07, 0xde, 0x4d, 0xe1, 0xbf, 0xe5, 0xe9, 0xe2, 0xef, 0xdc, + 0xd1, 0xdf, 0x52, 0xe2, 0xeb, 0xe5, 0x79, 0xec, 0x49, 0xf8, 0x52, 0xfe, + 0xfc, 0xf6, 0x46, 0xf3, 0xef, 0xef, 0x06, 0xf2, 0xb4, 0xf7, 0xac, 0xf6, + 0x8a, 0xf8, 0xe3, 0xfd, 0x49, 0x04, 0x6f, 0x04, 0x69, 0x07, 0x61, 0x14, + 0x36, 0x17, 0x94, 0x18, 0xb3, 0x1b, 0xe3, 0x1a, 0x6a, 0x1a, 0x78, 0x15, + 0x09, 0x1a, 0xfc, 0x24, 0xb5, 0x2d, 0x44, 0x37, 0xa0, 0x3b, 0x0d, 0x3d, + 0xf8, 0x3a, 0x50, 0x36, 0x74, 0x35, 0x9b, 0x32, 0x6f, 0x2c, 0x40, 0x2c, + 0x3d, 0x2d, 0xb0, 0x27, 0x65, 0x1b, 0x69, 0x11, 0x95, 0x0a, 0x67, 0x05, + 0x27, 0x01, 0xb7, 0xf5, 0x23, 0xe9, 0x9a, 0xdb, 0x73, 0xd4, 0xe2, 0xcc, + 0x95, 0xbc, 0x2b, 0xae, 0x93, 0xa2, 0x25, 0x9f, 0x61, 0x9e, 0xda, 0x9f, + 0xd1, 0xa2, 0x45, 0xa0, 0xca, 0x9f, 0xdc, 0xa2, 0xc0, 0xa2, 0x79, 0xab, + 0x90, 0xbc, 0x18, 0xce, 0x31, 0xed, 0x82, 0x10, 0x28, 0x32, 0x24, 0x51, + 0x2d, 0x63, 0x13, 0x6b, 0xb0, 0x6d, 0x39, 0x6b, 0xfb, 0x68, 0x32, 0x64, + 0xf5, 0x53, 0x53, 0x3e, 0x84, 0x23, 0x1d, 0x10, 0x31, 0xfb, 0x27, 0xe1, + 0x53, 0xd3, 0x55, 0xbc, 0xdf, 0xa4, 0xea, 0x9a, 0x42, 0x97, 0x7e, 0x97, + 0xfb, 0x97, 0x79, 0x98, 0xf3, 0x96, 0x71, 0x9c, 0x01, 0xa2, 0xe0, 0xa6, + 0x68, 0xb0, 0x2a, 0xbd, 0x74, 0xd7, 0x47, 0xee, 0xdb, 0x06, 0x30, 0x25, + 0x7d, 0x37, 0xc3, 0x49, 0xa6, 0x57, 0x02, 0x61, 0xe1, 0x6b, 0xa5, 0x6e, + 0xa1, 0x6b, 0xe0, 0x66, 0x79, 0x57, 0xce, 0x42, 0xb7, 0x34, 0xb1, 0x1e, + 0x62, 0x01, 0x4b, 0xe8, 0xe3, 0xd7, 0x94, 0xcd, 0x16, 0xc7, 0xba, 0xc2, + 0x50, 0xbd, 0x84, 0xb9, 0x67, 0xb2, 0xe7, 0xb2, 0x2c, 0xb4, 0x87, 0xb0, + 0x36, 0xb3, 0xd4, 0xb3, 0x6b, 0xb5, 0x17, 0xbb, 0xd8, 0xc3, 0x1e, 0xd1, + 0x08, 0xe1, 0xbe, 0xe8, 0x8d, 0xea, 0xfc, 0xed, 0xe0, 0xf0, 0x7a, 0xf6, + 0xcb, 0xfa, 0x92, 0x00, 0xad, 0x06, 0x71, 0x13, 0xd0, 0x23, 0x63, 0x35, + 0x55, 0x4e, 0xb0, 0x57, 0x62, 0x58, 0x3e, 0x51, 0xb2, 0x3e, 0x4b, 0x2f, + 0x88, 0x1e, 0x1f, 0x11, 0xfb, 0x03, 0x3c, 0xfa, 0x2f, 0xf0, 0x7c, 0xe0, + 0x65, 0xda, 0x16, 0xd8, 0x7e, 0xd6, 0xf5, 0xd4, 0xae, 0xcd, 0x65, 0xcb, + 0x03, 0xd5, 0x41, 0xe2, 0x1d, 0xef, 0xc1, 0xfb, 0x7e, 0x05, 0x12, 0x0e, + 0x1a, 0x1e, 0xa1, 0x30, 0x74, 0x3a, 0xd3, 0x43, 0xd5, 0x42, 0x86, 0x39, + 0xaf, 0x32, 0x26, 0x1e, 0x4e, 0x03, 0xf2, 0xe5, 0x56, 0xc9, 0xdc, 0xbd, + 0x1b, 0xbe, 0xb3, 0xc0, 0x7b, 0xc3, 0x5a, 0xcd, 0x30, 0xdb, 0x17, 0xe7, + 0x90, 0xf2, 0x17, 0xf6, 0x14, 0xf6, 0x3b, 0xf5, 0xdc, 0xef, 0x60, 0xea, + 0xdb, 0xe5, 0xc0, 0xdd, 0xbf, 0xd4, 0xe1, 0xd8, 0x0e, 0xdc, 0x44, 0xd6, + 0xa5, 0xd6, 0x46, 0xd7, 0x80, 0xd6, 0xaa, 0xd9, 0x66, 0xe0, 0x26, 0xe4, + 0x72, 0xe4, 0xb7, 0xe2, 0x02, 0xe0, 0x95, 0xe3, 0xf6, 0xe8, 0x87, 0xf1, + 0x30, 0xfb, 0x8b, 0x06, 0x45, 0x17, 0xd0, 0x2b, 0x39, 0x38, 0x0b, 0x38, + 0xc6, 0x3b, 0xc1, 0x37, 0xdd, 0x32, 0x1f, 0x32, 0xbd, 0x2b, 0x11, 0x27, + 0x30, 0x21, 0x59, 0x18, 0xd4, 0x0a, 0xcc, 0xff, 0x22, 0xf0, 0xc6, 0xe1, + 0x0b, 0xdc, 0x61, 0xd5, 0x14, 0xd3, 0x6b, 0xd2, 0xc2, 0xd5, 0x75, 0xd7, + 0x8e, 0xda, 0xb6, 0xe6, 0x5a, 0xee, 0x3b, 0xea, 0x87, 0xe7, 0xe1, 0xeb, + 0x07, 0xf1, 0x8b, 0xf3, 0xbc, 0xf0, 0x86, 0xef, 0xb4, 0xeb, 0x5f, 0xeb, + 0x5e, 0xeb, 0xc8, 0xe5, 0x29, 0xe5, 0x83, 0xe2, 0xe3, 0xe2, 0xb2, 0xe5, + 0x99, 0xe8, 0xf6, 0xf1, 0x90, 0xfe, 0x83, 0x0e, 0x03, 0x21, 0x15, 0x2e, + 0x22, 0x32, 0x37, 0x31, 0xa2, 0x2d, 0x34, 0x23, 0xc2, 0x15, 0x11, 0x08, + 0x43, 0xfa, 0xa3, 0x00, 0x20, 0x14, 0xba, 0x29, 0x3e, 0x41, 0xa7, 0x4b, + 0xbc, 0x48, 0x8e, 0x47, 0xf9, 0x48, 0x16, 0x39, 0x83, 0x23, 0x2e, 0x11, + 0xa4, 0x00, 0xfb, 0xf7, 0xee, 0xec, 0xed, 0xde, 0x04, 0xd8, 0xd8, 0xd9, + 0xbe, 0xdd, 0x04, 0xe3, 0x73, 0xe6, 0x12, 0xe9, 0xa6, 0xeb, 0x60, 0xee, + 0x7c, 0xf6, 0x21, 0xff, 0xa1, 0x08, 0x25, 0x0c, 0x5d, 0x06, 0x95, 0x01, + 0x6d, 0xfb, 0x93, 0xf8, 0x58, 0x04, 0xb6, 0x19, 0x93, 0x30, 0x51, 0x4c, + 0x17, 0x65, 0x59, 0x6a, 0x17, 0x6a, 0x9e, 0x69, 0xf9, 0x64, 0x9d, 0x59, + 0xe4, 0x43, 0xf6, 0x32, 0x87, 0x27, 0x0b, 0x25, 0x16, 0x27, 0x5e, 0x1e, + 0xde, 0x08, 0xa2, 0xf6, 0x8d, 0xf0, 0x89, 0xe4, 0x6f, 0xd7, 0x13, 0xd0, + 0x10, 0xc6, 0xd2, 0xbf, 0x4f, 0xc2, 0x24, 0xc5, 0xb9, 0xcb, 0xba, 0xcd, + 0x6d, 0xcc, 0xf7, 0xd5, 0x6c, 0xdf, 0xe4, 0xe6, 0x8c, 0xeb, 0xac, 0xf5, + 0x87, 0x07, 0x94, 0x14, 0xec, 0x0f, 0x3f, 0x11, 0x0f, 0x23, 0x33, 0x2a, + 0xd7, 0x38, 0x1c, 0x46, 0x9d, 0x51, 0x16, 0x69, 0xd5, 0x74, 0x8e, 0x78, + 0x70, 0x7a, 0x8c, 0x79, 0x5c, 0x79, 0xf5, 0x75, 0xc3, 0x70, 0xba, 0x6c, + 0xf5, 0x67, 0x45, 0x65, 0x38, 0x67, 0xb4, 0x66, 0x3f, 0x58, 0x1e, 0x47, + 0x3e, 0x36, 0x32, 0x1e, 0x60, 0x02, 0x34, 0xe1, 0xd9, 0xc4, 0xd8, 0xb6, + 0x24, 0xbc, 0x89, 0xc5, 0xa3, 0xcd, 0x6b, 0xde, 0x90, 0xee, 0x21, 0x03, + 0x65, 0x16, 0xfd, 0x1d, 0x64, 0x28, 0xb5, 0x32, 0x51, 0x33, 0x7a, 0x37, + 0xc7, 0x3a, 0xfb, 0x3c, 0xa2, 0x41, 0x80, 0x3d, 0x60, 0x3a, 0xfb, 0x38, + 0x89, 0x37, 0xb7, 0x37, 0xca, 0x33, 0xbd, 0x29, 0xa2, 0x22, 0x2f, 0x21, + 0x4d, 0x15, 0xa9, 0x0c, 0x8c, 0x0c, 0x0e, 0x0c, 0x61, 0x0f, 0x05, 0x0a, + 0x5b, 0x01, 0x62, 0xf8, 0xd2, 0xf2, 0x77, 0xf7, 0xf3, 0xfe, 0x3a, 0x09, + 0x20, 0x10, 0x0f, 0x16, 0xb6, 0x16, 0x74, 0x1b, 0xaf, 0x1f, 0x6d, 0x17, + 0xf6, 0x0f, 0xf9, 0x04, 0x8d, 0xfe, 0x38, 0xfc, 0xa0, 0xf6, 0x61, 0xf0, + 0xee, 0xf1, 0xb4, 0xf3, 0x35, 0xf8, 0xa0, 0x01, 0x71, 0x07, 0xf7, 0x15, + 0x7c, 0x1d, 0xbd, 0x21, 0x0a, 0x1b, 0x4a, 0x0f, 0x87, 0x07, 0xfc, 0xf8, + 0xd3, 0xf2, 0x53, 0xe8, 0x3c, 0xe1, 0xa1, 0xdc, 0x88, 0xe1, 0x0d, 0xed, + 0x3f, 0xf4, 0x42, 0xfb, 0x38, 0xfa, 0x26, 0xff, 0x91, 0xfb, 0x91, 0xf7, + 0x3b, 0xf7, 0xe7, 0xf1, 0x8a, 0xed, 0x19, 0xe7, 0x29, 0xec, 0xc2, 0xf9, + 0xc6, 0x08, 0xbf, 0x14, 0x54, 0x1b, 0xc0, 0x1a, 0xce, 0x18, 0x20, 0x14, + 0x28, 0x0f, 0xbb, 0x10, 0x8f, 0x12, 0xa2, 0x17, 0x39, 0x0d, 0xe1, 0xf9, + 0x27, 0xe8, 0x46, 0xd5, 0x9e, 0xcb, 0xa6, 0xca, 0x8c, 0xd2, 0x54, 0xd7, + 0x95, 0xe2, 0x55, 0xf4, 0x86, 0x01, 0xeb, 0x02, 0x20, 0xf2, 0x30, 0xe5, + 0xee, 0xd7, 0x9f, 0xd1, 0xac, 0xd4, 0xb3, 0xd6, 0x88, 0xe1, 0x05, 0xea, + 0x62, 0xf7, 0x83, 0x08, 0x89, 0x0c, 0x31, 0x0a, 0x8e, 0x08, 0x2a, 0x09, + 0xc8, 0x0f, 0x29, 0x19, 0x69, 0x22, 0x56, 0x30, 0x92, 0x3f, 0x8d, 0x4f, + 0xdb, 0x54, 0x0b, 0x56, 0x86, 0x59, 0x30, 0x51, 0x09, 0x49, 0x3d, 0x3d, + 0xb7, 0x2f, 0x4b, 0x2a, 0xa2, 0x25, 0x62, 0x25, 0x7b, 0x24, 0x45, 0x20, + 0x61, 0x1d, 0x1b, 0x19, 0x43, 0x10, 0x9e, 0x01, 0xb7, 0xf4, 0x33, 0xec, + 0x57, 0xe7, 0x78, 0xe6, 0xdc, 0xe1, 0x8d, 0xda, 0xe9, 0xcc, 0x08, 0xc6, + 0xc5, 0xcb, 0xae, 0xcc, 0xd6, 0xd2, 0xab, 0xd8, 0x2a, 0xdc, 0x05, 0xe5, + 0xb8, 0xef, 0x92, 0xfa, 0xde, 0xfd, 0x49, 0x03, 0xac, 0x0d, 0x99, 0x18, + 0xfc, 0x22, 0xd7, 0x28, 0x3a, 0x2b, 0xb2, 0x2b, 0xa7, 0x2d, 0xdf, 0x33, + 0x84, 0x3c, 0xcc, 0x44, 0xbd, 0x4c, 0xb2, 0x56, 0xe2, 0x5e, 0x47, 0x60, + 0x32, 0x63, 0xd3, 0x5e, 0x1b, 0x55, 0xba, 0x4e, 0x62, 0x42, 0x29, 0x32, + 0x55, 0x20, 0xd3, 0x16, 0x7a, 0x0e, 0x23, 0x02, 0xb8, 0xf8, 0x77, 0xee, + 0x4d, 0xeb, 0xf0, 0xec, 0xfa, 0xed, 0xff, 0xee, 0xcf, 0xec, 0x8a, 0xe9, + 0x86, 0xe8, 0x46, 0xe2, 0xaf, 0xd7, 0xc1, 0xce, 0x63, 0xc9, 0x13, 0xc4, + 0x3f, 0xbd, 0xe7, 0xbb, 0x23, 0xbb, 0xbb, 0xbf, 0x3d, 0xca, 0x00, 0xdc, + 0x1a, 0xf4, 0x57, 0x09, 0x22, 0x18, 0x74, 0x21, 0x65, 0x2c, 0xf3, 0x2d, + 0xb8, 0x29, 0xfb, 0x24, 0x1a, 0x21, 0x25, 0x21, 0x99, 0x25, 0x07, 0x2f, + 0x23, 0x37, 0x6f, 0x3c, 0x95, 0x32, 0x8a, 0x22, 0xb5, 0x11, 0xb0, 0x08, + 0x06, 0x0a, 0x47, 0x02, 0x0e, 0xfd, 0x01, 0xf5, 0x37, 0xe8, 0x5a, 0xdf, + 0xde, 0xce, 0x76, 0xb7, 0xda, 0xaa, 0x00, 0xac, 0x37, 0xb2, 0xc2, 0xbb, + 0xe3, 0xc4, 0xf1, 0xd1, 0xdc, 0xe1, 0xaf, 0xf3, 0x91, 0x06, 0x29, 0x12, + 0xa7, 0x13, 0x72, 0x11, 0x8d, 0x12, 0x6d, 0x0e, 0x0e, 0x0e, 0x93, 0x15, + 0x3c, 0x1a, 0xaa, 0x1b, 0x15, 0x12, 0x70, 0x02, 0x36, 0xf1, 0x85, 0xde, + 0x53, 0xd2, 0x42, 0xcc, 0xf9, 0xcc, 0xef, 0xd2, 0x7e, 0xe0, 0xa1, 0xf1, + 0xe3, 0xfe, 0x21, 0x0a, 0xaa, 0x0c, 0x0c, 0x02, 0x75, 0xed, 0xc4, 0xda, + 0x3e, 0xd3, 0xb1, 0xd5, 0x67, 0xe1, 0xf6, 0xf5, 0x44, 0x0f, 0xe7, 0x22, + 0xd7, 0x28, 0x3b, 0x2c, 0x07, 0x29, 0x19, 0x13, 0x3a, 0xfb, 0x1c, 0xe1, + 0x67, 0xca, 0x06, 0xc2, 0x20, 0xc3, 0xab, 0xcf, 0xb4, 0xde, 0x0b, 0xf0, + 0xea, 0x00, 0x85, 0x0f, 0x74, 0x1d, 0x36, 0x27, 0xa1, 0x31, 0xec, 0x3a, + 0xe0, 0x3d, 0x9d, 0x2e, 0x6b, 0x14, 0x86, 0xf9, 0x78, 0xdd, 0xe4, 0xca, + 0x06, 0xbe, 0x12, 0xb5, 0xd8, 0xb1, 0x0c, 0xb5, 0x49, 0xc0, 0xc8, 0xc7, + 0x63, 0xca, 0xe9, 0xcd, 0x73, 0xd0, 0x21, 0xd4, 0x09, 0xdd, 0x8b, 0xe1, + 0xda, 0xe1, 0x15, 0xeb, 0xec, 0xf7, 0x2e, 0x02, 0x60, 0x0a, 0x79, 0x0f, + 0x80, 0x10, 0xfd, 0x11, 0xcb, 0x14, 0xe2, 0x14, 0xcf, 0x12, 0xcf, 0x0c, + 0x71, 0x03, 0x3a, 0xfb, 0x9b, 0xf9, 0xcd, 0xf3, 0x53, 0xe8, 0x45, 0xdd, + 0x1b, 0xd0, 0x95, 0xc5, 0xbb, 0xb9, 0xc8, 0xb4, 0x04, 0xb4, 0xd6, 0xb3, + 0xa3, 0xb9, 0x83, 0xbf, 0xda, 0xc8, 0x4b, 0xce, 0xac, 0xd1, 0x7a, 0xd5, + 0x05, 0xd6, 0x27, 0xd2, 0x71, 0xc7, 0x95, 0xc2, 0xec, 0xc2, 0xbf, 0xc5, + 0x3f, 0xcd, 0x21, 0xd4, 0x1e, 0xde, 0xa4, 0xe9, 0x33, 0xee, 0xe6, 0xf9, + 0xb0, 0x0a, 0xf6, 0x11, 0x95, 0x18, 0x82, 0x1d, 0x6a, 0x22, 0xc5, 0x21, + 0xf6, 0x18, 0x88, 0x15, 0x91, 0x0f, 0x27, 0x0a, 0xf5, 0x09, 0x3f, 0x0a, + 0x13, 0x10, 0x03, 0x17, 0x3e, 0x1c, 0xf8, 0x21, 0x9e, 0x22, 0xe4, 0x19, + 0x94, 0x0b, 0xfa, 0x00, 0x60, 0xfe, 0x7d, 0xfe, 0x81, 0xf6, 0x9e, 0xe8, + 0x7e, 0xe3, 0x1d, 0xe0, 0x79, 0xd6, 0x60, 0xd1, 0x28, 0xd7, 0x89, 0xdf, + 0x23, 0xe4, 0xd6, 0xef, 0x40, 0xf9, 0x83, 0xfb, 0x12, 0x00, 0x41, 0xff, + 0x6b, 0xfb, 0xb0, 0xf1, 0x19, 0xe6, 0x30, 0xe4, 0xe7, 0xe8, 0x1f, 0xf1, + 0x9c, 0xf4, 0x94, 0xf8, 0xd9, 0xfe, 0xa3, 0x03, 0x99, 0x11, 0xdc, 0x20, + 0xca, 0x23, 0x7e, 0x24, 0x8b, 0x22, 0x4a, 0x17, 0x9e, 0x0c, 0x88, 0xfb, + 0x15, 0xea, 0xce, 0xe4, 0x80, 0xec, 0x7c, 0x02, 0x10, 0x14, 0xe0, 0x1a, + 0x3d, 0x19, 0xfe, 0x19, 0x92, 0x1a, 0xef, 0x16, 0xd2, 0x19, 0xb0, 0x14, + 0xc0, 0x0e, 0x8b, 0x0a, 0xe1, 0x00, 0x48, 0xf8, 0x5a, 0xf4, 0xe0, 0xf6, + 0xbb, 0xf1, 0x6b, 0xe8, 0x84, 0xe0, 0xce, 0xd7, 0x11, 0xce, 0xfe, 0xc1, + 0xf8, 0xbb, 0x25, 0xba, 0x90, 0xb9, 0x0a, 0xb9, 0x11, 0xb9, 0xa9, 0xc6, + 0x7d, 0xd9, 0xd4, 0xe6, 0xc4, 0xf5, 0xe0, 0x01, 0x19, 0x0b, 0x7e, 0x0f, + 0xbf, 0x11, 0xec, 0x18, 0xa7, 0x22, 0xe2, 0x2b, 0x54, 0x36, 0xf6, 0x47, + 0x92, 0x4f, 0xaa, 0x52, 0x17, 0x55, 0x44, 0x46, 0x9d, 0x31, 0x55, 0x1b, + 0x94, 0x01, 0x0a, 0xe3, 0x2d, 0xce, 0x7d, 0xbc, 0xf1, 0xa2, 0xd1, 0x9a, + 0x1a, 0x9a, 0xda, 0x9c, 0x2a, 0xa7, 0x05, 0xb0, 0xf2, 0xb8, 0xf0, 0xbf, + 0xbb, 0xca, 0xe9, 0xd3, 0x6e, 0xd6, 0x63, 0xd5, 0xc2, 0xd9, 0x6e, 0xe4, + 0x55, 0xee, 0x07, 0xfc, 0x72, 0x08, 0xf0, 0x16, 0x8b, 0x22, 0xa8, 0x31, + 0x16, 0x48, 0xa1, 0x56, 0x25, 0x65, 0x33, 0x6b, 0xe5, 0x6b, 0xbc, 0x6d, + 0x92, 0x67, 0xaf, 0x5c, 0x92, 0x47, 0x6a, 0x31, 0x38, 0x22, 0x2e, 0x0a, + 0x86, 0xf2, 0xfa, 0xe1, 0xb3, 0xd3, 0xef, 0xd2, 0x2a, 0xd7, 0x7d, 0xd9, + 0x96, 0xdc, 0xbf, 0xe0, 0x8d, 0xdf, 0x36, 0xe0, 0xd8, 0xe1, 0x98, 0xd5, + 0x17, 0xcf, 0xc4, 0xcc, 0x06, 0xd1, 0x17, 0xdf, 0x04, 0xf0, 0xee, 0x0e, + 0xce, 0x31, 0x81, 0x4b, 0x5d, 0x5c, 0x91, 0x66, 0x7f, 0x65, 0x6f, 0x5c, + 0x37, 0x4d, 0x24, 0x42, 0xee, 0x3c, 0xdc, 0x3a, 0x90, 0x3d, 0xdd, 0x39, + 0xd5, 0x37, 0x29, 0x35, 0x8e, 0x31, 0x2b, 0x2d, 0xe2, 0x28, 0xd0, 0x28, + 0x84, 0x27, 0xab, 0x28, 0x6c, 0x2a, 0xeb, 0x28, 0x8f, 0x26, 0x85, 0x27, + 0x03, 0x24, 0xe8, 0x24, 0xe1, 0x2d, 0x33, 0x33, 0x1e, 0x34, 0x68, 0x32, + 0x84, 0x2b, 0xe2, 0x20, 0x9a, 0x20, 0xf5, 0x1e, 0x0b, 0x1a, 0x9d, 0x15, + 0xcf, 0x14, 0xc3, 0x16, 0xab, 0x0c, 0x2d, 0x0a, 0x52, 0x0a, 0xe6, 0x02, + 0x9a, 0x03, 0x38, 0x05, 0x61, 0x03, 0x33, 0x02, 0x78, 0xfe, 0x3e, 0xfb, + 0xa6, 0xff, 0x72, 0x0a, 0xa5, 0x16, 0x43, 0x23, 0xb2, 0x34, 0xb4, 0x45, + 0x22, 0x4a, 0x48, 0x43, 0x11, 0x36, 0xdf, 0x24, 0x58, 0x1b, 0x85, 0x18, + 0xa5, 0x12, 0xee, 0x0e, 0x2c, 0x12, 0x20, 0x19, 0x61, 0x20, 0x33, 0x2d, + 0xbe, 0x3a, 0x83, 0x3b, 0x35, 0x3d, 0xd9, 0x40, 0x33, 0x3d, 0x06, 0x42, + 0xc3, 0x44, 0xed, 0x43, 0x8e, 0x41, 0xbc, 0x31, 0xfe, 0x1f, 0xb9, 0x0b, + 0x7a, 0x00, 0x08, 0x00, 0x3a, 0xff, 0x42, 0x02, 0xb4, 0x04, 0x06, 0x0e, + 0x7d, 0x16, 0x74, 0x18, 0x2d, 0x1d, 0x16, 0x18, 0x44, 0x0c, 0x6a, 0x03, + 0xe4, 0xf6, 0xd8, 0xf1, 0x6e, 0xf3, 0x7c, 0xf6, 0x6a, 0x05, 0x3c, 0x18, + 0xd6, 0x24, 0x84, 0x25, 0x8f, 0x1d, 0xb0, 0x0f, 0x7f, 0xf4, 0x28, 0xd1, + 0x3e, 0xbb, 0x64, 0xb5, 0x3d, 0xb9, 0xb8, 0xc5, 0x22, 0xd2, 0x7f, 0xe3, + 0x4a, 0xf1, 0x5c, 0x02, 0xaf, 0x1d, 0x17, 0x34, 0xa8, 0x40, 0x41, 0x45, + 0x0b, 0x4b, 0xab, 0x44, 0xdd, 0x3f, 0xd1, 0x41, 0x7e, 0x3e, 0x11, 0x3b, + 0x29, 0x30, 0x4a, 0x27, 0x8f, 0x16, 0x1c, 0x01, 0x57, 0xec, 0x3b, 0xd2, + 0x59, 0xbf, 0x16, 0xaf, 0x1d, 0xa6, 0x13, 0xa6, 0x31, 0xa7, 0x1a, 0xa7, + 0xf3, 0xa8, 0x17, 0xac, 0xc4, 0xb6, 0x4e, 0xc8, 0xa4, 0xd8, 0x56, 0xf2, + 0xb7, 0x09, 0x65, 0x1f, 0x1e, 0x33, 0x69, 0x3f, 0x4d, 0x48, 0x32, 0x4b, + 0xa0, 0x52, 0xb3, 0x57, 0xf8, 0x58, 0x61, 0x4f, 0x61, 0x46, 0x61, 0x41, + 0xfb, 0x32, 0x2e, 0x31, 0xd1, 0x33, 0x9c, 0x3c, 0x3b, 0x43, 0x7f, 0x3f, + 0xdb, 0x3a, 0xd4, 0x2a, 0xb7, 0x1d, 0x75, 0x19, 0xfe, 0x16, 0x03, 0x11, + 0xdc, 0x11, 0xe6, 0x12, 0x5e, 0x0b, 0x37, 0x06, 0x4e, 0xf7, 0x60, 0xe2, + 0x25, 0xcd, 0xee, 0xb6, 0x8c, 0xa8, 0xf7, 0xa6, 0xc2, 0xa5, 0x87, 0xa6, + 0x93, 0xad, 0x1b, 0xb7, 0x86, 0xcc, 0x3e, 0xe3, 0xaf, 0xf6, 0xb4, 0x05, + 0x94, 0x13, 0x33, 0x22, 0x36, 0x34, 0xed, 0x3f, 0xdb, 0x38, 0xeb, 0x33, + 0x93, 0x2f, 0x37, 0x2f, 0x6b, 0x32, 0x57, 0x3a, 0x5e, 0x43, 0x0f, 0x42, + 0x39, 0x42, 0xad, 0x37, 0x36, 0x2a, 0x5b, 0x25, 0x14, 0x1e, 0x5d, 0x10, + 0x7a, 0xfe, 0xb9, 0xea, 0x8f, 0xd8, 0x8e, 0xce, 0xa0, 0xc9, 0x66, 0xc4, + 0x7d, 0xbd, 0x32, 0xc2, 0xf2, 0xd0, 0x80, 0xe4, 0x00, 0xfd, 0xc3, 0x14, + 0x8b, 0x2a, 0x7c, 0x3c, 0x68, 0x49, 0xf7, 0x4a, 0x08, 0x46, 0x3a, 0x3b, + 0x95, 0x2a, 0x24, 0x1f, 0x2c, 0x1b, 0xe4, 0x1f, 0x40, 0x28, 0x37, 0x2a, + 0x51, 0x23, 0xdb, 0x1a, 0x99, 0x18, 0x7d, 0x14, 0x55, 0x06, 0xd9, 0xf4, + 0xf3, 0xe1, 0x92, 0xd8, 0xf1, 0xd9, 0x3f, 0xdf, 0x16, 0xe8, 0x2b, 0xec, + 0x21, 0xf5, 0x26, 0x01, 0x72, 0x08, 0x99, 0x0a, 0x97, 0x09, 0x05, 0x0f, + 0x55, 0x15, 0x76, 0x1b, 0x51, 0x23, 0x70, 0x2a, 0x4b, 0x31, 0x95, 0x36, + 0xaf, 0x38, 0x14, 0x3b, 0xc6, 0x36, 0x0b, 0x25, 0x1b, 0x11, 0x28, 0xfb, + 0x4a, 0xe6, 0x8b, 0xd3, 0x30, 0xc6, 0x39, 0xc6, 0x67, 0xc5, 0x1f, 0xc9, + 0x98, 0xd2, 0xd2, 0xd7, 0x21, 0xdd, 0x1b, 0xdd, 0xbe, 0xe0, 0x63, 0xec, + 0x69, 0xf8, 0x66, 0x05, 0xf7, 0x10, 0x0a, 0x20, 0x9a, 0x2e, 0x8b, 0x36, + 0xd2, 0x3f, 0xf5, 0x46, 0xbc, 0x49, 0xb1, 0x4e, 0xc7, 0x55, 0x6a, 0x5f, + 0xcc, 0x65, 0xaf, 0x67, 0x81, 0x66, 0x35, 0x60, 0xfb, 0x4f, 0xe8, 0x31, + 0x94, 0x11, 0x77, 0xf1, 0xcd, 0xd3, 0x3a, 0xbf, 0xd8, 0xb6, 0x2f, 0xb9, + 0xa2, 0xba, 0x5e, 0xbd, 0x7b, 0xc3, 0x56, 0xca, 0x84, 0xd6, 0x8b, 0xe7, + 0xd5, 0xf9, 0x07, 0x05, 0x0f, 0x06, 0x68, 0x04, 0xaf, 0x02, 0x2f, 0x00, + 0x2e, 0xf8, 0xd3, 0xef, 0x66, 0xeb, 0xb2, 0xe4, 0x32, 0xdc, 0x94, 0xd1, + 0xa8, 0xc7, 0x49, 0xc0, 0x52, 0xbd, 0x78, 0xbc, 0x7e, 0xb9, 0xf7, 0xb9, + 0x94, 0xc1, 0xa2, 0xd1, 0x6a, 0xe1, 0x43, 0xec, 0x05, 0xfd, 0xb9, 0x18, + 0x42, 0x38, 0x81, 0x51, 0xaa, 0x5e, 0xc8, 0x65, 0x26, 0x67, 0x7a, 0x63, + 0x30, 0x59, 0x09, 0x43, 0xce, 0x28, 0xe4, 0x09, 0x7b, 0xf0, 0x75, 0xda, + 0x9f, 0xc2, 0xe8, 0xb0, 0x55, 0xa5, 0xf0, 0xa3, 0x2c, 0xa6, 0xab, 0xaa, + 0xc0, 0xab, 0x3d, 0xaa, 0x51, 0xad, 0x14, 0xb4, 0x8a, 0xbf, 0x5b, 0xcf, + 0x6d, 0xe0, 0x94, 0xf4, 0xd7, 0x14, 0x2e, 0x32, 0xa6, 0x43, 0xc6, 0x46, + 0x1b, 0x3a, 0xea, 0x29, 0x3c, 0x1a, 0x7b, 0x0d, 0x31, 0xfd, 0x2d, 0xea, + 0x4f, 0xe2, 0x5a, 0xe8, 0xbb, 0xef, 0xc1, 0xf5, 0x77, 0xf7, 0xaa, 0xed, + 0xe6, 0xe2, 0x44, 0xdc, 0x6a, 0xd6, 0x40, 0xd1, 0x3f, 0xcc, 0x0c, 0xcc, + 0xc0, 0xcf, 0x76, 0xce, 0xdf, 0xd3, 0x91, 0xd6, 0x81, 0xd2, 0x99, 0xd8, + 0xcd, 0xdd, 0x55, 0xe2, 0x91, 0xde, 0x2a, 0xd4, 0x8f, 0xce, 0x3f, 0xcc, + 0x9f, 0xd0, 0x7b, 0xd0, 0xf8, 0xd5, 0xff, 0xde, 0xaa, 0xe1, 0x26, 0xec, + 0xa9, 0xfb, 0xd2, 0x0d, 0xdb, 0x16, 0x05, 0x14, 0x4d, 0x10, 0x4c, 0x07, + 0x0a, 0xfd, 0xe7, 0xf9, 0xae, 0xf3, 0xcc, 0xea, 0xed, 0xec, 0xdd, 0xee, + 0x7e, 0xf3, 0x67, 0xfb, 0xa0, 0x02, 0x66, 0x06, 0xe0, 0x05, 0x6c, 0x0b, + 0x70, 0x0f, 0x75, 0x1d, 0x4e, 0x20, 0xcd, 0x19, 0x07, 0x1c, 0x13, 0x13, + 0x76, 0x0c, 0xb6, 0x04, 0x5f, 0xfd, 0x3b, 0xf2, 0xbe, 0xe8, 0x0c, 0xe8, + 0xa7, 0xe9, 0x74, 0xf3, 0xd8, 0xf7, 0x99, 0xfb, 0xf3, 0xf1, 0xd3, 0xd9, + 0x2f, 0xbb, 0x68, 0x9b, 0xe0, 0x90, 0xc6, 0x8f, 0x2b, 0x91, 0x55, 0x98, + 0xa0, 0xa7, 0x0b, 0xbe, 0xdb, 0xd8, 0x24, 0xf1, 0x88, 0xfd, 0xcb, 0x01, + 0xa5, 0xfe, 0x57, 0xfa, 0x37, 0xf6, 0xea, 0xf2, 0x05, 0xf7, 0x14, 0xfa, + 0xc7, 0xfc, 0xd8, 0x05, 0x86, 0x16, 0xea, 0x29, 0xa2, 0x2e, 0xa0, 0x30, + 0x78, 0x35, 0x4c, 0x31, 0x3d, 0x2e, 0x74, 0x2c, 0x81, 0x2a, 0xf0, 0x26, + 0xf7, 0x21, 0xf9, 0x1a, 0xc7, 0x0f, 0x2d, 0x09, 0xe9, 0xfd, 0x17, 0xee, + 0xbd, 0xe2, 0xb6, 0xd4, 0x4e, 0xcb, 0x6a, 0xc7, 0xf6, 0xc3, 0x85, 0xc4, + 0x1b, 0xc9, 0xea, 0xd4, 0x3d, 0xe1, 0xa3, 0xe8, 0x4d, 0xf0, 0x43, 0xfc, + 0x57, 0x0b, 0x55, 0x1a, 0x82, 0x23, 0x10, 0x22, 0x04, 0x1d, 0x7b, 0x1e, + 0xa7, 0x29, 0x6e, 0x36, 0x53, 0x47, 0x1c, 0x58, 0xeb, 0x62, 0x4f, 0x6a, + 0x15, 0x6a, 0xc9, 0x63, 0x0d, 0x52, 0x00, 0x3a, 0xa6, 0x1c, 0x5a, 0xff, + 0x1a, 0xe5, 0x94, 0xc8, 0xed, 0xb6, 0x09, 0xac, 0xf9, 0xa8, 0x9a, 0xaa, + 0x51, 0xac, 0xb9, 0xaf, 0x8e, 0xb3, 0xa4, 0xbb, 0x38, 0xba, 0x4e, 0xb6, + 0xee, 0xb8, 0xe1, 0xb9, 0x87, 0xbe, 0x63, 0xc6, 0x8c, 0xce, 0x2b, 0xd7, + 0xad, 0xdf, 0xd6, 0xf1, 0x0f, 0x0b, 0x7f, 0x24, 0x6c, 0x40, 0xed, 0x55, + 0x10, 0x64, 0x7d, 0x6d, 0xc4, 0x70, 0xce, 0x71, 0x45, 0x72, 0xc1, 0x6c, + 0x89, 0x57, 0x53, 0x3a, 0xab, 0x20, 0xd7, 0x08, 0x52, 0xf6, 0x4c, 0xf1, + 0xc3, 0xee, 0xf5, 0xe7, 0x21, 0xe6, 0x3c, 0xe5, 0xda, 0xe0, 0xec, 0xda, + 0x53, 0xdb, 0xb9, 0xda, 0xc0, 0xd4, 0x35, 0xd3, 0x9c, 0xcd, 0x01, 0xcd, + 0x04, 0xd0, 0xda, 0xd0, 0x52, 0xd9, 0x5c, 0xe1, 0xbe, 0xec, 0x68, 0xfd, + 0xa9, 0x0f, 0xa6, 0x22, 0xe5, 0x30, 0x2e, 0x39, 0x9f, 0x3f, 0xe7, 0x40, + 0xbb, 0x38, 0x7e, 0x30, 0x83, 0x23, 0x4f, 0x11, 0x84, 0x04, 0xeb, 0xff, + 0xfd, 0x00, 0x9a, 0x02, 0x9a, 0x06, 0x7e, 0x0a, 0x97, 0x08, 0x3b, 0x04, + 0x6e, 0x04, 0xaf, 0xfe, 0x1d, 0xf2, 0x2b, 0xe6, 0x65, 0xdb, 0x32, 0xde, + 0x9e, 0xe6, 0x01, 0xef, 0xc7, 0xfc, 0xe6, 0x0b, 0x3f, 0x1d, 0xd8, 0x2f, + 0x41, 0x41, 0x57, 0x4a, 0x1e, 0x46, 0xad, 0x3c, 0xf3, 0x2f, 0x6e, 0x1d, + 0xcf, 0x0e, 0xf9, 0x03, 0x80, 0xff, 0xc6, 0x04, 0x6c, 0x09, 0xad, 0x16, + 0x65, 0x25, 0xe6, 0x27, 0x48, 0x23, 0x59, 0x13, 0xda, 0x04, 0x3b, 0x00, + 0x27, 0x01, 0x2d, 0x05, 0xdd, 0x05, 0xc4, 0x07, 0x73, 0x0d, 0x7f, 0x17, + 0xad, 0x1d, 0xa1, 0x1e, 0xb5, 0x26, 0x9d, 0x2b, 0xee, 0x2f, 0x1d, 0x3b, + 0x6d, 0x45, 0x5e, 0x54, 0xf1, 0x5e, 0x20, 0x63, 0x93, 0x69, 0xfe, 0x69, + 0x3b, 0x6c, 0xdf, 0x6d, 0xc5, 0x6a, 0x37, 0x68, 0x29, 0x60, 0x0d, 0x5a, + 0x22, 0x4b, 0x01, 0x39, 0x5a, 0x2c, 0x7a, 0x1a, 0x2d, 0x10, 0xb9, 0x03, + 0x29, 0xf5, 0x96, 0xe7, 0x1a, 0xdf, 0xbb, 0xe3, 0xff, 0xe7, 0x96, 0xee, + 0x50, 0xee, 0x95, 0xeb, 0xdc, 0xee, 0x1d, 0xf2, 0x62, 0xf5, 0xdd, 0xf0, + 0x5f, 0xe9, 0x60, 0xe6, 0xe2, 0xec, 0x6c, 0xfd, 0x72, 0x0b, 0xad, 0x14, + 0x6b, 0x22, 0xaa, 0x31, 0xfc, 0x41, 0x7b, 0x4a, 0x85, 0x4b, 0x74, 0x53, + 0x69, 0x4c, 0xba, 0x44, 0xd7, 0x49, 0x1d, 0x4a, 0xb2, 0x50, 0xf8, 0x55, + 0x4e, 0x5a, 0xe9, 0x62, 0x06, 0x67, 0x51, 0x69, 0x0b, 0x64, 0x86, 0x5d, + 0x5a, 0x57, 0x04, 0x47, 0x3b, 0x33, 0x01, 0x1f, 0x0d, 0x0a, 0xf1, 0xf8, + 0xe4, 0xee, 0xe9, 0xdf, 0x90, 0xcc, 0x25, 0xc1, 0x16, 0xb8, 0xc4, 0xb3, + 0x82, 0xb2, 0x10, 0xb1, 0x78, 0xb2, 0x96, 0xb7, 0xb8, 0xc0, 0x6a, 0xca, + 0x0c, 0xd5, 0xd4, 0xe2, 0x2e, 0xf2, 0xab, 0xfc, 0x10, 0x0a, 0x45, 0x1f, + 0x5d, 0x32, 0xca, 0x42, 0x07, 0x54, 0x23, 0x5c, 0xd5, 0x58, 0x9d, 0x4e, + 0x25, 0x3c, 0xf4, 0x31, 0xbc, 0x2e, 0x8a, 0x2c, 0x3d, 0x2c, 0x8c, 0x22, + 0x05, 0x1b, 0x6e, 0x1d, 0xd6, 0x1e, 0xd9, 0x1d, 0xd6, 0x1c, 0x74, 0x1c, + 0x3b, 0x21, 0x80, 0x25, 0x4e, 0x28, 0xff, 0x2b, 0xb0, 0x2b, 0x05, 0x2c, + 0x30, 0x29, 0xe6, 0x23, 0x80, 0x22, 0x96, 0x1d, 0xa2, 0x14, 0x49, 0x02, + 0xf9, 0xe4, 0xba, 0xd0, 0xb8, 0xc5, 0xe0, 0xbb, 0x38, 0xb9, 0x35, 0xbb, + 0xc2, 0xbe, 0x92, 0xc7, 0x0b, 0xcc, 0x78, 0xcc, 0x6f, 0xd2, 0xae, 0xd4, + 0xa6, 0xd5, 0xc1, 0xd4, 0x40, 0xd5, 0x21, 0xdc, 0xe9, 0xe0, 0x29, 0xef, + 0x3d, 0x07, 0xb8, 0x1d, 0xa5, 0x2f, 0xb6, 0x39, 0x84, 0x3b, 0x4b, 0x3e, + 0xb0, 0x3e, 0xad, 0x38, 0x5e, 0x38, 0x08, 0x3a, 0xb8, 0x3c, 0x20, 0x3b, + 0x23, 0x32, 0x66, 0x29, 0x14, 0x21, 0xc3, 0x22, 0x2d, 0x29, 0xc2, 0x23, + 0x20, 0x1c, 0x78, 0x16, 0xd8, 0x10, 0x19, 0x0f, 0xfc, 0x06, 0xdb, 0xf5, + 0x96, 0xe2, 0xb8, 0xd6, 0xa8, 0xcd, 0x34, 0xbb, 0xb5, 0xab, 0xdf, 0xa3, + 0xb6, 0x9f, 0xa6, 0xa2, 0xae, 0xa9, 0xa0, 0xb1, 0xd9, 0xba, 0x5b, 0xc2, + 0x6e, 0xca, 0x73, 0xd4, 0x4e, 0xd8, 0x05, 0xd7, 0x41, 0xdd, 0xde, 0xef, + 0x31, 0x0c, 0xce, 0x26, 0x62, 0x41, 0xc1, 0x60, 0xd6, 0x70, 0x29, 0x74, + 0x8e, 0x76, 0xa0, 0x76, 0xce, 0x76, 0xda, 0x76, 0x06, 0x76, 0x4a, 0x74, + 0x61, 0x72, 0xf5, 0x6f, 0xd6, 0x6e, 0x0d, 0x68, 0xe9, 0x59, 0xc4, 0x4a, + 0x10, 0x3f, 0x63, 0x35, 0x08, 0x28, 0x38, 0x16, 0x95, 0x04, 0x8d, 0xfc, + 0x2a, 0xf7, 0x01, 0xea, 0x2e, 0xd0, 0xf5, 0xb8, 0xed, 0xaf, 0xb3, 0xad, + 0x20, 0xb1, 0xd9, 0xaf, 0xec, 0xb3, 0x88, 0xc2, 0x7c, 0xd1, 0x79, 0xe4, + 0x33, 0xf1, 0xe9, 0xf9, 0x36, 0x0a, 0x1c, 0x1a, 0x99, 0x28, 0x64, 0x39, + 0x1c, 0x47, 0x18, 0x52, 0xd0, 0x5d, 0xfd, 0x68, 0x29, 0x6d, 0xf1, 0x6b, + 0x4c, 0x68, 0x29, 0x61, 0xd2, 0x5b, 0x75, 0x55, 0xdb, 0x4a, 0xa7, 0x35, + 0x56, 0x1a, 0x89, 0x05, 0x46, 0xf4, 0xb9, 0xe7, 0x31, 0xdc, 0xc9, 0xcd, + 0x6a, 0xc2, 0xe8, 0xbd, 0x6d, 0xc3, 0x0d, 0xcc, 0x8c, 0xd5, 0xb5, 0xe0, + 0x56, 0xef, 0x20, 0xf8, 0x07, 0xf6, 0x84, 0xfb, 0x2b, 0xfe, 0x51, 0xf9, + 0x7c, 0xf8, 0x6c, 0xf7, 0x9a, 0xf7, 0x34, 0xf6, 0x71, 0xea, 0x85, 0xe7, + 0xb6, 0xf3, 0xb5, 0xf6, 0xb4, 0xfd, 0xa2, 0x0c, 0x60, 0x1a, 0x1b, 0x27, + 0x90, 0x30, 0x07, 0x37, 0x10, 0x33, 0x06, 0x32, 0x47, 0x36, 0x8b, 0x3a, + 0xbf, 0x37, 0xe4, 0x2e, 0x00, 0x27, 0x40, 0x1c, 0xee, 0x13, 0x95, 0x06, + 0x78, 0xfd, 0x0b, 0xf1, 0xb1, 0xe0, 0xa2, 0xd7, 0xa7, 0xc7, 0x9a, 0xba, + 0xa4, 0xad, 0x51, 0xa5, 0x97, 0xa6, 0x9a, 0xa7, 0x40, 0xb3, 0xf0, 0xc5, + 0x5a, 0xd2, 0xf6, 0xdd, 0x2e, 0xea, 0x0e, 0xf5, 0x10, 0x05, 0xdd, 0x11, + 0x23, 0x1c, 0x81, 0x26, 0xb5, 0x30, 0x0f, 0x42, 0x3d, 0x48, 0x93, 0x3f, + 0xd2, 0x31, 0x12, 0x19, 0x56, 0xfe, 0x20, 0xea, 0xe8, 0xd8, 0x33, 0xcf, + 0xff, 0xc9, 0xcb, 0xc8, 0x5a, 0xd6, 0x94, 0xe1, 0x6f, 0xe5, 0xc1, 0xe6, + 0x0e, 0xdb, 0xf8, 0xd3, 0x99, 0xd2, 0xa4, 0xce, 0xb0, 0xd0, 0x66, 0xd3, + 0xca, 0xd9, 0x20, 0xe6, 0x2a, 0xef, 0x19, 0xf4, 0x78, 0xf4, 0xb9, 0xee, + 0x60, 0xe8, 0x2c, 0xdc, 0x61, 0xce, 0xb1, 0xcb, 0xbe, 0xcf, 0x79, 0xdc, + 0xd2, 0xe7, 0xf0, 0xee, 0x9f, 0xf8, 0x52, 0x01, 0x31, 0x0f, 0xc1, 0x18, + 0xfe, 0x1b, 0xba, 0x20, 0x41, 0x25, 0xd1, 0x2d, 0x6b, 0x39, 0xc5, 0x44, + 0x0c, 0x48, 0x0d, 0x42, 0x2a, 0x35, 0x86, 0x20, 0xfd, 0x05, 0x0f, 0xe6, + 0x65, 0xcc, 0xf5, 0xbc, 0x91, 0xb9, 0x1b, 0xb8, 0x7e, 0xac, 0x43, 0xa9, + 0x2a, 0xaa, 0xfa, 0xa4, 0xc2, 0x9f, 0x79, 0x9b, 0x6c, 0x9b, 0xde, 0x9e, + 0x04, 0xa4, 0x73, 0xa8, 0x46, 0xad, 0x54, 0xb4, 0xb4, 0xbc, 0x65, 0xc9, + 0x05, 0xd7, 0x6b, 0xde, 0x61, 0xe7, 0x31, 0xf9, 0x5d, 0x0d, 0x0d, 0x23, + 0x5e, 0x3a, 0x0c, 0x46, 0x0d, 0x46, 0x47, 0x43, 0x7e, 0x3c, 0x3e, 0x3a, + 0x5b, 0x3f, 0xd5, 0x3e, 0x3a, 0x38, 0x49, 0x31, 0xb5, 0x26, 0x86, 0x1d, + 0x4b, 0x1a, 0x45, 0x18, 0xed, 0x11, 0xff, 0x06, 0x42, 0xfb, 0x48, 0xed, + 0x43, 0xe3, 0x14, 0xdb, 0xe2, 0xd4, 0xfe, 0xcd, 0x31, 0xc2, 0x2e, 0xbc, + 0x81, 0xba, 0x6a, 0xb7, 0x81, 0xb0, 0x70, 0xae, 0x5a, 0xb0, 0x74, 0xb3, + 0x50, 0xbc, 0x90, 0xc5, 0x24, 0xce, 0xd4, 0xd4, 0x9d, 0xe2, 0x1e, 0xf6, + 0xe0, 0x07, 0xcd, 0x14, 0x6b, 0x1b, 0x56, 0x25, 0xc5, 0x2a, 0x05, 0x30, + 0x92, 0x3c, 0xb8, 0x3d, 0x6b, 0x3b, 0xdc, 0x43, 0x42, 0x4f, 0xb8, 0x54, + 0xfc, 0x53, 0x11, 0x51, 0xa5, 0x46, 0xfa, 0x35, 0x21, 0x21, 0x80, 0x13, + 0x3d, 0x0c, 0x53, 0xfe, 0x61, 0xf3, 0xe7, 0xe5, 0xd0, 0xd2, 0xc2, 0xc5, + 0xba, 0xc0, 0x6a, 0xbb, 0x4c, 0xb5, 0x69, 0xaf, 0x21, 0xaa, 0x5d, 0xa7, + 0x60, 0xa6, 0x88, 0xae, 0x52, 0xbc, 0xd6, 0xc9, 0x4d, 0xd5, 0xf1, 0xe7, + 0x7c, 0xf9, 0x54, 0x05, 0x60, 0x15, 0xd6, 0x18, 0x65, 0x19, 0x8c, 0x1c, + 0x73, 0x20, 0x8a, 0x31, 0x1f, 0x43, 0x0a, 0x4a, 0x90, 0x53, 0x38, 0x55, + 0x2d, 0x43, 0xd4, 0x2f, 0x73, 0x17, 0xd8, 0x09, 0xf5, 0x09, 0xc6, 0x06, + 0x2c, 0x0d, 0x96, 0x0d, 0xaf, 0x00, 0xb7, 0xf4, 0x6b, 0xe4, 0xb7, 0xdb, + 0x4e, 0xe4, 0xe2, 0xea, 0xb3, 0xf8, 0x23, 0x0f, 0x38, 0x20, 0x3b, 0x31, + 0x89, 0x37, 0x43, 0x39, 0x02, 0x36, 0xcc, 0x20, 0xc9, 0x09, 0x02, 0xf2, + 0xa7, 0xd7, 0x08, 0xcb, 0x0f, 0xc4, 0xba, 0xbc, 0x15, 0xbc, 0x3b, 0xbd, + 0xa7, 0xc6, 0xd0, 0xd2, 0x3a, 0xe2, 0x52, 0xf8, 0x12, 0x03, 0x3b, 0x0b, + 0xd4, 0x0e, 0xd3, 0x08, 0xbb, 0x07, 0x44, 0x08, 0x82, 0x0a, 0x3b, 0x0e, + 0x60, 0x0d, 0x45, 0x14, 0x1b, 0x21, 0xdd, 0x28, 0xc7, 0x37, 0x07, 0x3f, + 0x2f, 0x38, 0xe0, 0x35, 0x07, 0x2f, 0x77, 0x23, 0x7e, 0x19, 0x50, 0x0a, + 0x94, 0xfe, 0x34, 0xfe, 0xf4, 0xfa, 0x78, 0xf8, 0x3d, 0xfa, 0x50, 0xf8, + 0x76, 0xf9, 0x13, 0xf6, 0xbf, 0xf1, 0xe2, 0xf4, 0x1f, 0xf4, 0xf2, 0xef, + 0xc8, 0xee, 0x24, 0xee, 0x35, 0xe6, 0x6f, 0xd6, 0x4d, 0xc6, 0x8a, 0xba, + 0x8f, 0xb3, 0xb3, 0xb4, 0xbe, 0xbf, 0xf6, 0xcb, 0x0f, 0xd7, 0x50, 0xe3, + 0xfa, 0xee, 0xb0, 0xfb, 0x0d, 0x07, 0xa5, 0x14, 0x97, 0x25, 0xbe, 0x37, + 0x70, 0x4b, 0x00, 0x57, 0x4e, 0x59, 0xd7, 0x57, 0x6e, 0x52, 0xc5, 0x4a, + 0x95, 0x40, 0xc5, 0x31, 0xa4, 0x24, 0x9c, 0x1e, 0xa3, 0x1c, 0x7b, 0x1d, + 0xc6, 0x1c, 0x71, 0x17, 0xd9, 0x0e, 0x0d, 0x0c, 0xa4, 0x0c, 0xe6, 0x05, + 0x35, 0xfe, 0x0e, 0xf8, 0x9a, 0xf7, 0xdf, 0xfc, 0xe4, 0x01, 0xd6, 0x0a, + 0x79, 0x17, 0x43, 0x29, 0x04, 0x39, 0x78, 0x3f, 0x6a, 0x40, 0x72, 0x39, + 0xa1, 0x32, 0xf5, 0x2d, 0x99, 0x21, 0xed, 0x15, 0xda, 0x11, 0xc8, 0x15, + 0xf2, 0x1e, 0x17, 0x28, 0xe9, 0x2b, 0xfe, 0x2c, 0x1f, 0x36, 0x37, 0x3e, + 0x6c, 0x43, 0x7f, 0x46, 0x3b, 0x43, 0x29, 0x42, 0xe7, 0x41, 0xbe, 0x40, + 0x4a, 0x3c, 0x03, 0x33, 0x96, 0x24, 0x1e, 0x14, 0x53, 0x0c, 0x06, 0x0a, + 0x78, 0x0a, 0x43, 0x0d, 0x53, 0x13, 0x12, 0x1b, 0x7b, 0x1c, 0xe8, 0x1a, + 0x28, 0x11, 0xc3, 0x07, 0x12, 0x05, 0x67, 0xfe, 0x01, 0xfd, 0x15, 0xff, + 0xc2, 0x08, 0xd4, 0x19, 0x4d, 0x29, 0xcc, 0x35, 0x97, 0x36, 0x49, 0x2f, + 0x6e, 0x1f, 0x7e, 0x14, 0xd5, 0x13, 0x96, 0x14, 0x7e, 0x1b, 0x6e, 0x26, + 0x9e, 0x33, 0xd6, 0x39, 0x36, 0x3a, 0x43, 0x39, 0x72, 0x36, 0xdd, 0x2f, + 0xf0, 0x23, 0x14, 0x21, 0x42, 0x24, 0x52, 0x2c, 0x19, 0x39, 0xfb, 0x36, + 0x89, 0x2b, 0x45, 0x1b, 0x10, 0x05, 0x98, 0xf4, 0xd1, 0xe5, 0x5e, 0xdf, + 0x20, 0xe5, 0xe3, 0xf3, 0xa9, 0x0a, 0x25, 0x19, 0x03, 0x1f, 0xcb, 0x1e, + 0x2d, 0x1a, 0x49, 0x1b, 0x16, 0x20, 0x9a, 0x22, 0x63, 0x2b, 0x1a, 0x3b, + 0xed, 0x45, 0x85, 0x50, 0xb4, 0x51, 0xba, 0x48, 0x60, 0x42, 0x8e, 0x31, + 0x22, 0x16, 0x66, 0xfa, 0xee, 0xe6, 0x68, 0xd3, 0xf1, 0xb7, 0xf5, 0xaa, + 0xfd, 0xa8, 0x80, 0xa7, 0xc4, 0xa9, 0xe8, 0xa9, 0x6b, 0xa7, 0xd6, 0xa7, + 0x65, 0xaf, 0xfb, 0xb9, 0x65, 0xc0, 0x45, 0xc5, 0x33, 0xd0, 0x98, 0xd9, + 0x84, 0xe1, 0x50, 0xea, 0x02, 0xf1, 0x39, 0xfb, 0x1d, 0x0e, 0xdc, 0x2e, + 0xc8, 0x4c, 0xd2, 0x5d, 0x42, 0x65, 0xe9, 0x5f, 0x00, 0x55, 0x2c, 0x45, + 0x43, 0x31, 0x63, 0x25, 0x6a, 0x1b, 0xf3, 0x0f, 0x8a, 0x08, 0x9b, 0xfc, + 0xb6, 0xf4, 0xd0, 0xe7, 0xc0, 0xd3, 0xe6, 0xca, 0xff, 0xc0, 0x02, 0xbc, + 0x89, 0xc2, 0x4b, 0xc7, 0xd5, 0xc9, 0x9f, 0xd1, 0xa5, 0xdb, 0xea, 0xe8, + 0xef, 0xf7, 0x75, 0x03, 0xf2, 0x0e, 0xe8, 0x13, 0xc2, 0x17, 0x8f, 0x20, + 0x4d, 0x2a, 0xfe, 0x2c, 0x2c, 0x32, 0x97, 0x45, 0x5a, 0x57, 0x6d, 0x63, + 0xae, 0x68, 0xe9, 0x6a, 0x4f, 0x67, 0xc2, 0x5a, 0xdb, 0x4b, 0x46, 0x3b, + 0xf6, 0x2f, 0xac, 0x24, 0x79, 0x18, 0xee, 0x07, 0x23, 0xf4, 0xcd, 0xe7, + 0x85, 0xdf, 0xe0, 0xda, 0x91, 0xd8, 0x85, 0xd6, 0x05, 0xd7, 0x2d, 0xe2, + 0xdf, 0xf3, 0x66, 0x03, 0x12, 0x13, 0xf9, 0x18, 0xdf, 0x15, 0xb1, 0x16, + 0x87, 0x12, 0xdd, 0x11, 0x57, 0x18, 0x71, 0x20, 0x90, 0x32, 0xfb, 0x41, + 0xe7, 0x4b, 0xc6, 0x45, 0x5e, 0x39, 0xbc, 0x39, 0x01, 0x3d, 0x92, 0x41, + 0xeb, 0x40, 0xff, 0x3b, 0x88, 0x37, 0xcf, 0x3b, 0x9b, 0x3a, 0x3c, 0x2d, + 0xd6, 0x18, 0x1f, 0x06, 0x48, 0x03, 0xe5, 0x06, 0x89, 0x16, 0xb9, 0x26, + 0xb6, 0x2f, 0xc8, 0x2f, 0x8c, 0x26, 0x7a, 0x1a, 0x30, 0x08, 0x17, 0xed, + 0x25, 0xcb, 0x44, 0xb1, 0xa9, 0xa5, 0xe8, 0xa9, 0xce, 0xb0, 0x31, 0xb9, + 0xc2, 0xb8, 0xf2, 0xad, 0x28, 0xac, 0x3d, 0xb5, 0x3b, 0xd9, 0xb9, 0x07, + 0x55, 0xfe, 0x60, 0xc3, 0x62, 0xd5, 0xf6, 0x38, 0x7a, 0x73, 0xc7, 0x76, + 0xfa, 0x76, 0xa7, 0x73, 0xf6, 0x6b, 0xe6, 0x6e, 0x0e, 0x74, 0x0d, 0x76, + 0xed, 0x70, 0xd7, 0x74, 0xd9, 0x4f, 0xf9, 0xe7, 0x94, 0xa7, 0x91, 0xb9, + 0x84, 0xdb, 0x83, 0xcf, 0x5b, 0xc3, 0x5f, 0xe6, 0xb5, 0xf9, 0xfc, 0xf8, + 0x0b, 0xf6, 0x24, 0xdb, 0x55, 0xbe, 0x0f, 0xa4, 0x8d, 0xa2, 0x1e, 0xa4, + 0xf5, 0x9c, 0xed, 0xa8, 0x00, 0xb5, 0x2c, 0xd4, 0x9d, 0xe4, 0x6f, 0xe4, + 0xa7, 0xeb, 0xe2, 0xfc, 0xcb, 0x1a, 0xb2, 0x25, 0xfc, 0x1d, 0xc4, 0x19, + 0x65, 0x38, 0x88, 0x4d, 0x11, 0x4f, 0xd7, 0x5b, 0xf8, 0x68, 0x12, 0x71, + 0x98, 0x6f, 0xcb, 0x72, 0x66, 0x71, 0xee, 0x6a, 0xef, 0x53, 0xc2, 0x27, + 0x2c, 0x09, 0x3d, 0xf2, 0x14, 0xcf, 0x0c, 0xbd, 0xa4, 0xbb, 0x67, 0xb0, + 0x3f, 0xa6, 0x59, 0xa4, 0x36, 0xb2, 0xae, 0xbd, 0xb0, 0xc4, 0x15, 0xd5, + 0x01, 0xdd, 0xa0, 0xd8, 0xe2, 0xd6, 0x00, 0xde, 0x0d, 0xea, 0x35, 0xed, + 0x52, 0xe4, 0x3f, 0xe9, 0xdc, 0xed, 0x14, 0xe4, 0x88, 0xda, 0xeb, 0xd6, + 0x90, 0xda, 0xd4, 0xd7, 0x01, 0xd2, 0x8b, 0xdb, 0x17, 0xfc, 0x9e, 0x1f, + 0xdb, 0x28, 0x2f, 0x24, 0xac, 0x1c, 0x08, 0x0a, 0x98, 0xfa, 0x25, 0xfd, + 0x2b, 0x10, 0x42, 0x1b, 0x87, 0x22, 0x00, 0x29, 0x6e, 0x26, 0x6c, 0x1e, + 0x34, 0x13, 0xf1, 0x17, 0x00, 0x0f, 0xc3, 0xf8, 0xde, 0xe9, 0x78, 0xec, + 0x78, 0xfe, 0x18, 0x04, 0x26, 0x00, 0xad, 0xf7, 0x48, 0xf6, 0x04, 0xf0, + 0xc9, 0xf7, 0x88, 0x0d, 0xd4, 0x1e, 0x12, 0x24, 0x30, 0x1b, 0x07, 0x0e, + 0x57, 0x05, 0xa4, 0x0a, 0x71, 0xed, 0x9b, 0xe9, 0xf5, 0xe1, 0x14, 0xea, + 0xb9, 0x39, 0x17, 0x38, 0xc8, 0x27, 0x52, 0x25, 0x30, 0x13, 0x04, 0x12, + 0xb5, 0x05, 0x36, 0x03, 0xb5, 0xfe, 0xe1, 0xfc, 0xe0, 0xf8, 0x13, 0xee, + 0x05, 0xe5, 0xe4, 0xe4, 0x3a, 0xe9, 0xfd, 0xee, 0xd6, 0xfc, 0x26, 0x05, + 0xf1, 0x0f, 0xdb, 0x14, 0x24, 0x19, 0x51, 0x1e, 0xe4, 0x1f, 0x20, 0x1e, + 0xf8, 0x1a, 0x91, 0x19, 0x29, 0x15, 0x08, 0x13, 0xc5, 0x0e, 0xc1, 0x0c, + 0x7a, 0x06, 0xe3, 0x05, 0xe8, 0x0c, 0x48, 0x0d, 0x35, 0x0a, 0x77, 0xff, + 0xfe, 0xf2, 0x25, 0xec, 0x0e, 0xe7, 0x0f, 0xe1, 0x93, 0xdf, 0x18, 0xde, + 0x83, 0xe0, 0xcd, 0xe3, 0xce, 0xe3, 0xe2, 0xe1, 0x0a, 0xdc, 0xf3, 0xd6, + 0x7e, 0xce, 0xe7, 0xc8, 0xa9, 0xc5, 0x8a, 0xc4, 0xa7, 0xc6, 0x14, 0xca, + 0xa4, 0xcd, 0x57, 0xd2, 0xd3, 0xd4, 0x6a, 0xd2, 0xf1, 0xd0, 0xc0, 0xca, + 0xf9, 0xc5, 0x00, 0xc0, 0xc9, 0xbe, 0x21, 0xc3, 0x01, 0xc6, 0x73, 0xcd, + 0x7b, 0xd4, 0xde, 0xdb, 0x9c, 0xe0, 0xe2, 0xe2, 0xa8, 0xe2, 0xb5, 0xe2, + 0x07, 0xe2, 0x01, 0xdf, 0xce, 0xdd, 0x42, 0xdc, 0xc5, 0xda, 0x52, 0xd8, + 0xe4, 0xd9, 0x8f, 0xdb, 0x6a, 0xda, 0x40, 0xdb, 0xeb, 0xdd, 0x77, 0xe3, + 0x0d, 0xe8, 0xd1, 0xe7, 0xa6, 0xe9, 0x76, 0xe9, 0xc4, 0xe1, 0xb6, 0xd8, + 0x03, 0xcc, 0xd4, 0xc1, 0x28, 0xba, 0xc5, 0xb3, 0x18, 0xb7, 0x33, 0xbc, + 0x3a, 0xbd, 0x64, 0xc2, 0xdf, 0xc7, 0xaf, 0xcd, 0x80, 0xd6, 0x15, 0xdc, + 0xe5, 0xe5, 0x25, 0xea, 0x05, 0xe7, 0xb8, 0xe8, 0x92, 0xea, 0x22, 0xeb, + 0x4b, 0xe9, 0x5d, 0xe4, 0x9e, 0xdf, 0x23, 0xda, 0xb6, 0xd0, 0x1a, 0xc9, + 0x37, 0xc4, 0xa3, 0xc3, 0x42, 0xc5, 0x72, 0xc3, 0xfc, 0xc1, 0x59, 0xc0, + 0xd5, 0xc5, 0x87, 0xd3, 0xd9, 0xde, 0xfb, 0xe6, 0x3f, 0xf4, 0xff, 0x08, + 0xe7, 0x1d, 0xd5, 0x2c, 0x24, 0x3b, 0x99, 0x48, 0x3a, 0x50, 0xea, 0x55, + 0xdf, 0x50, 0x72, 0x47, 0x8e, 0x40, 0x64, 0x35, 0x9e, 0x2e, 0x3d, 0x26, + 0x30, 0x14, 0x71, 0x07, 0x36, 0x03, 0x3d, 0x00, 0xa9, 0x01, 0x77, 0x02, + 0xdc, 0xfc, 0xec, 0xf5, 0x7b, 0xf4, 0x8c, 0xf6, 0x8d, 0xfa, 0x37, 0x07, + 0x70, 0x18, 0x4f, 0x2a, 0x02, 0x38, 0x9e, 0x42, 0x3e, 0x4e, 0x74, 0x4f, + 0xe9, 0x49, 0x80, 0x45, 0x0f, 0x44, 0xa7, 0x44, 0x55, 0x40, 0x99, 0x3c, + 0xb5, 0x3f, 0xb8, 0x45, 0x01, 0x4d, 0x80, 0x51, 0x2b, 0x4c, 0x00, 0x44, + 0x60, 0x3e, 0x97, 0x38, 0xa2, 0x33, 0x07, 0x2d, 0xd9, 0x24, 0xfa, 0x20, + 0x06, 0x22, 0x1f, 0x25, 0xbc, 0x2d, 0x64, 0x32, 0xc7, 0x31, 0x5a, 0x33, + 0x0d, 0x31, 0x54, 0x2f, 0x1b, 0x2a, 0x34, 0x22, 0x67, 0x1e, 0x95, 0x1d, + 0xf2, 0x1d, 0x0e, 0x1d, 0x03, 0x21, 0x4d, 0x23, 0xa3, 0x24, 0x2b, 0x2d, + 0x55, 0x3c, 0x0c, 0x4e, 0xe9, 0x55, 0xd6, 0x53, 0x1d, 0x50, 0x1f, 0x4c, + 0x85, 0x48, 0xa5, 0x44, 0x7b, 0x39, 0x79, 0x2d, 0x6a, 0x27, 0xe0, 0x24, + 0xc0, 0x26, 0x1d, 0x2b, 0x72, 0x2f, 0xa0, 0x32, 0x12, 0x38, 0xb3, 0x39, + 0x7a, 0x3b, 0xa3, 0x3f, 0xd0, 0x3b, 0xdf, 0x38, 0x3d, 0x35, 0x57, 0x30, + 0x44, 0x2c, 0x56, 0x26, 0xf8, 0x1e, 0xb0, 0x12, 0x6d, 0x09, 0x47, 0x06, + 0xe3, 0x06, 0x8f, 0x07, 0xa8, 0x09, 0x64, 0x09, 0x5b, 0xfe, 0x1e, 0xef, + 0x3c, 0xda, 0x5a, 0xc6, 0x3c, 0xbb, 0xbc, 0xb5, 0x58, 0xb7, 0xf6, 0xbc, + 0x09, 0xc3, 0xd5, 0xc8, 0xa1, 0xcf, 0x85, 0xd5, 0x8e, 0xd7, 0x75, 0xd9, + 0xbb, 0xdb, 0xa0, 0xdb, 0x6d, 0xda, 0xaf, 0xd9, 0x81, 0xda, 0xc5, 0xda, + 0xa2, 0xd8, 0x5f, 0xd7, 0x65, 0xd8, 0xbc, 0xd9, 0x82, 0xd9, 0x74, 0xda, + 0x64, 0xdb, 0x85, 0xda, 0xbf, 0xdb, 0x37, 0xdc, 0x25, 0xda, 0x1b, 0xdc, + 0xad, 0xde, 0x5e, 0xdc, 0xef, 0xda, 0x71, 0xd7, 0xc4, 0xd0, 0x3f, 0xcb, + 0x3a, 0xc3, 0x61, 0xb9, 0x8f, 0xb3, 0xf0, 0xae, 0x20, 0xa9, 0xfb, 0xa6, + 0x5f, 0xa8, 0xb2, 0xaa, 0x3e, 0xae, 0xf7, 0xb5, 0x0a, 0xc0, 0xf2, 0xc6, + 0x6c, 0xca, 0xa5, 0xca, 0x0d, 0xc9, 0x10, 0xc4, 0xba, 0xc1, 0x68, 0xc6, + 0x5d, 0xcd, 0x93, 0xda, 0x5c, 0xeb, 0x14, 0xf9, 0x76, 0x02, 0x99, 0x06, + 0x5f, 0x06, 0x17, 0x02, 0xce, 0xfc, 0xa1, 0xf5, 0x8c, 0xe7, 0xac, 0xd7, + 0x0c, 0xcb, 0xa5, 0xbf, 0x9f, 0xb6, 0xe0, 0xb1, 0x74, 0xb2, 0xf8, 0xb8, + 0x20, 0xc2, 0x0c, 0xcc, 0x0e, 0xd7, 0x08, 0xde, 0x49, 0xdc, 0xa8, 0xd7, + 0x73, 0xd4, 0x74, 0xd1, 0xfa, 0xcf, 0x43, 0xd1, 0x5c, 0xd3, 0x94, 0xd3, + 0x82, 0xd6, 0x66, 0xde, 0xa6, 0xe6, 0xfa, 0xf0, 0xd2, 0xf9, 0xf0, 0x00, + 0x22, 0x0e, 0x6a, 0x19, 0x38, 0x21, 0x29, 0x28, 0x47, 0x2a, 0x19, 0x28, + 0x29, 0x21, 0xc6, 0x1c, 0x08, 0x1b, 0x02, 0x18, 0xaf, 0x19, 0x7b, 0x20, + 0xe1, 0x23, 0xad, 0x26, 0xca, 0x2b, 0x2c, 0x2a, 0x93, 0x27, 0xe4, 0x26, + 0xe3, 0x26, 0xb5, 0x27, 0xb6, 0x23, 0x13, 0x1e, 0x9a, 0x18, 0x06, 0x15, + 0x25, 0x14, 0xe1, 0x12, 0x71, 0x11, 0x00, 0x11, 0x6e, 0x14, 0x34, 0x1f, + 0xf3, 0x2c, 0x14, 0x39, 0xe0, 0x42, 0x14, 0x49, 0x24, 0x4f, 0x4e, 0x54, + 0x8d, 0x55, 0x1b, 0x55, 0x71, 0x52, 0x50, 0x4c, 0xbe, 0x4a, 0xe5, 0x4f, + 0x09, 0x57, 0x52, 0x5e, 0x87, 0x64, 0x50, 0x68, 0xff, 0x67, 0x7c, 0x69, + 0x30, 0x6b, 0x09, 0x69, 0x66, 0x65, 0xea, 0x5c, 0x01, 0x56, 0x8c, 0x55, + 0xb8, 0x55, 0x0f, 0x58, 0x57, 0x5c, 0xc6, 0x5e, 0x46, 0x60, 0xf6, 0x60, + 0xd3, 0x63, 0xeb, 0x63, 0xf1, 0x5e, 0x4a, 0x57, 0xcd, 0x49, 0x18, 0x3d, + 0x95, 0x34, 0xf0, 0x2d, 0x8a, 0x2a, 0xd3, 0x2a, 0x60, 0x2e, 0xa3, 0x35, + 0x4d, 0x3b, 0x99, 0x3b, 0xf8, 0x35, 0xb9, 0x2f, 0xdc, 0x2e, 0x62, 0x2d, + 0xd2, 0x2d, 0xf6, 0x30, 0x74, 0x33, 0x3a, 0x36, 0xdb, 0x3c, 0x5f, 0x43, + 0xda, 0x41, 0x7c, 0x42, 0xe3, 0x47, 0xc3, 0x4e, 0x9e, 0x55, 0xd8, 0x58, + 0xd1, 0x59, 0x11, 0x5a, 0xdc, 0x56, 0xbe, 0x53, 0xa8, 0x53, 0xdb, 0x50, + 0x65, 0x4e, 0xd3, 0x49, 0x58, 0x43, 0xa6, 0x3b, 0x61, 0x32, 0x65, 0x2b, + 0xfb, 0x21, 0x75, 0x1d, 0x03, 0x19, 0x55, 0x13, 0x4b, 0x11, 0x07, 0x08, + 0xd7, 0xfc, 0x9e, 0xf3, 0xe9, 0xee, 0xd5, 0xec, 0x2f, 0xea, 0x85, 0xe9, + 0xe6, 0xe5, 0x07, 0xe6, 0xe3, 0xe6, 0xd9, 0xe6, 0xd5, 0xe5, 0xa3, 0xdb, + 0xf4, 0xd0, 0xd2, 0xca, 0xf6, 0xca, 0x08, 0xd2, 0x4d, 0xd7, 0x33, 0xdb, + 0x60, 0xe2, 0x6c, 0xea, 0x61, 0xf2, 0xa1, 0xf2, 0x5b, 0xef, 0x89, 0xec, + 0x37, 0xe4, 0x18, 0xe2, 0x74, 0xe2, 0x0f, 0xe1, 0x37, 0xe2, 0x06, 0xe4, + 0xcb, 0xe7, 0x3d, 0xe9, 0x57, 0xe7, 0x70, 0xe1, 0xd5, 0xd8, 0xb5, 0xd0, + 0xc8, 0xca, 0xee, 0xc4, 0xbf, 0xbb, 0x50, 0xb0, 0xa1, 0xa5, 0xf4, 0x9f, + 0x46, 0x9b, 0xec, 0x94, 0x64, 0x90, 0xf5, 0x8e, 0x60, 0x8e, 0x2c, 0x8e, + 0x60, 0x8e, 0x6c, 0x8d, 0xb3, 0x8d, 0x48, 0x8e, 0xd5, 0x90, 0xa5, 0x94, + 0x86, 0x97, 0xd8, 0x9d, 0x33, 0xa7, 0x57, 0xb1, 0xed, 0xbd, 0x30, 0xcc, + 0x18, 0xd6, 0xe0, 0xdd, 0x91, 0xe5, 0x2f, 0xe7, 0xa3, 0xe6, 0x5c, 0xe4, + 0xfa, 0xe2, 0x69, 0xe6, 0xe2, 0xe8, 0xde, 0xee, 0xe9, 0xf3, 0xea, 0xf1, + 0x56, 0xf1, 0x1f, 0xf1, 0x36, 0xec, 0x63, 0xe5, 0xd4, 0xdf, 0xa5, 0xde, + 0xa4, 0xe2, 0xee, 0xe3, 0x03, 0xe7, 0x80, 0xed, 0x87, 0xef, 0x3f, 0xf2, + 0xb0, 0xef, 0x60, 0xe6, 0x2d, 0xde, 0xc7, 0xd1, 0x7f, 0xc3, 0x8a, 0xb4, + 0xe3, 0xa5, 0x0f, 0x9e, 0x8d, 0x9b, 0x0c, 0x9c, 0xa3, 0x9e, 0x2c, 0xa6, + 0xc5, 0xb0, 0xdc, 0xbd, 0xc7, 0xca, 0xdd, 0xd5, 0xb5, 0xe3, 0x67, 0xec, + 0x69, 0xef, 0xec, 0xef, 0x98, 0xef, 0xde, 0xf0, 0xd1, 0xf4, 0x71, 0xff, + 0x8a, 0x0e, 0x60, 0x1c, 0xc0, 0x23, 0xe6, 0x28, 0x15, 0x2e, 0xa2, 0x35, + 0xb4, 0x3b, 0xc9, 0x3c, 0xfc, 0x3d, 0x54, 0x3b, 0x45, 0x35, 0x98, 0x29, + 0x3f, 0x21, 0x90, 0x1d, 0xe4, 0x1b, 0xd8, 0x24, 0x58, 0x2c, 0x25, 0x32, + 0x21, 0x37, 0x91, 0x38, 0x4b, 0x3c, 0xc8, 0x3b, 0x34, 0x37, 0x44, 0x31, + 0xfe, 0x29, 0x8f, 0x25, 0x8b, 0x1d, 0x3d, 0x10, 0x99, 0x05, 0x1d, 0x00, + 0xab, 0xff, 0xb3, 0x03, 0x1c, 0x0a, 0x46, 0x10, 0x2c, 0x18, 0x0a, 0x20, + 0x94, 0x26, 0x23, 0x2c, 0xac, 0x2c, 0x9f, 0x2c, 0x52, 0x31, 0xf2, 0x3a, + 0xf2, 0x47, 0x6b, 0x55, 0x39, 0x61, 0xb3, 0x6a, 0x00, 0x71, 0x70, 0x73, + 0xae, 0x74, 0xff, 0x74, 0x1c, 0x74, 0x3b, 0x72, 0x1a, 0x70, 0x20, 0x6f, + 0x5d, 0x6f, 0x7f, 0x70, 0xbb, 0x71, 0x75, 0x72, 0x93, 0x71, 0x51, 0x70, + 0x8d, 0x6e, 0xcb, 0x68, 0x29, 0x5e, 0xb8, 0x54, 0x50, 0x51, 0xaf, 0x52, + 0xf1, 0x53, 0x53, 0x4b, 0xff, 0x3a, 0xfe, 0x2b, 0x6b, 0x20, 0x39, 0x19, + 0xcf, 0x11, 0x85, 0x0a, 0x47, 0x0c, 0x54, 0x14, 0xbd, 0x1d, 0x72, 0x28, + 0x6b, 0x2d, 0x3c, 0x2f, 0x44, 0x34, 0x46, 0x39, 0x6b, 0x3e, 0x00, 0x41, + 0x63, 0x41, 0x1a, 0x44, 0x98, 0x4c, 0x7a, 0x58, 0xee, 0x60, 0x9d, 0x65, + 0xc8, 0x65, 0x18, 0x63, 0x82, 0x5e, 0x6b, 0x56, 0x65, 0x46, 0x6e, 0x30, + 0xd2, 0x1c, 0xad, 0x0b, 0x76, 0x03, 0x03, 0x03, 0x9b, 0x04, 0xf3, 0x04, + 0x51, 0x02, 0x36, 0x02, 0x56, 0x04, 0x08, 0x08, 0x77, 0x07, 0x83, 0x03, + 0x9c, 0x03, 0x53, 0x04, 0x03, 0x05, 0x8a, 0x05, 0x3e, 0x00, 0x91, 0xfb, + 0x2c, 0xfe, 0xd6, 0x00, 0x26, 0x03, 0x4d, 0x00, 0x2c, 0xf7, 0x92, 0xf5, + 0x36, 0xf5, 0x00, 0xed, 0xce, 0xe9, 0xa4, 0xf0, 0xb5, 0xf8, 0x81, 0x02, + 0x8b, 0x0c, 0x9d, 0x10, 0xc9, 0x15, 0xec, 0x1f, 0x4b, 0x2b, 0x5a, 0x32, + 0xa0, 0x31, 0x63, 0x33, 0x15, 0x36, 0x49, 0x31, 0x75, 0x25, 0xdb, 0x12, + 0xcc, 0x01, 0x3c, 0xf1, 0x5f, 0xdd, 0x66, 0xcc, 0x6c, 0xbc, 0x40, 0xab, + 0xe6, 0x9e, 0x28, 0x9b, 0x73, 0x9a, 0x09, 0x99, 0x5a, 0x99, 0x9e, 0x9a, + 0xc2, 0x9c, 0x1a, 0xa0, 0xde, 0xa3, 0x36, 0xac, 0xeb, 0xb6, 0x01, 0xc2, + 0x35, 0xd0, 0x59, 0xdf, 0xb1, 0xf3, 0xba, 0x0b, 0x32, 0x1b, 0xfc, 0x1e, + 0x03, 0x16, 0x97, 0x00, 0xdc, 0xed, 0x3b, 0xe0, 0x43, 0xd2, 0x50, 0xc5, + 0x98, 0xb4, 0xf3, 0xaa, 0x31, 0xac, 0x0c, 0xac, 0x48, 0xaa, 0xdb, 0xa5, + 0x29, 0x9f, 0x36, 0x9c, 0x2b, 0x9c, 0x7b, 0x9c, 0x11, 0xa0, 0xfd, 0xa4, + 0xfb, 0xae, 0xe6, 0xbd, 0x95, 0xca, 0x36, 0xd0, 0x56, 0xca, 0x46, 0xbf, + 0x99, 0xb0, 0xca, 0xa0, 0xe1, 0x96, 0x49, 0x94, 0x2b, 0x97, 0x65, 0x9d, + 0x2b, 0xa3, 0xfb, 0xa8, 0x59, 0xb4, 0x22, 0xc3, 0xc1, 0xd3, 0x1d, 0xe0, + 0x5e, 0xeb, 0x65, 0xf8, 0x8f, 0x04, 0x4f, 0x14, 0xaf, 0x23, 0xb7, 0x2f, + 0xda, 0x33, 0x1e, 0x2e, 0xef, 0x1d, 0xba, 0x02, 0x31, 0xe1, 0x98, 0xc4, + 0xfb, 0xb3, 0xbc, 0xaf, 0x29, 0xb9, 0x7e, 0xc1, 0xf4, 0xc3, 0xf2, 0xc7, + 0x36, 0xca, 0x11, 0xca, 0x6f, 0xc8, 0x65, 0xc2, 0x0f, 0xbd, 0x3d, 0xba, + 0xb1, 0xb6, 0xb2, 0xb6, 0x87, 0xb9, 0xf2, 0xbe, 0xe5, 0xc2, 0xdb, 0xc3, + 0x96, 0xc4, 0xa0, 0xc5, 0x7f, 0xcb, 0xa5, 0xd6, 0x42, 0xe3, 0xa8, 0xf2, + 0x39, 0x06, 0xb9, 0x13, 0xc0, 0x1d, 0xef, 0x23, 0xe8, 0x24, 0x7b, 0x27, + 0xc4, 0x29, 0xe2, 0x29, 0x64, 0x26, 0x57, 0x24, 0x0e, 0x24, 0x8b, 0x29, + 0x28, 0x33, 0x06, 0x36, 0xe7, 0x2d, 0x11, 0x1e, 0x07, 0x0e, 0x0e, 0x01, + 0xea, 0xfa, 0x84, 0xf9, 0xd9, 0xfb, 0xf5, 0x01, 0xc7, 0x0b, 0xa9, 0x16, + 0x98, 0x1d, 0x0b, 0x1d, 0xb9, 0x18, 0x3e, 0x16, 0x6d, 0x14, 0x65, 0x18, + 0xd9, 0x1e, 0x04, 0x26, 0xd6, 0x2b, 0xbf, 0x2f, 0x5a, 0x34, 0x83, 0x35, + 0xe4, 0x35, 0x40, 0x35, 0x3a, 0x37, 0x84, 0x3a, 0x91, 0x3c, 0xfb, 0x40, + 0xa6, 0x42, 0x3c, 0x3d, 0xab, 0x37, 0x33, 0x37, 0xe5, 0x37, 0xf5, 0x34, + 0xb3, 0x2f, 0x0d, 0x2e, 0xab, 0x2b, 0x0a, 0x29, 0x70, 0x29, 0xe9, 0x2a, + 0x5c, 0x2c, 0x06, 0x2b, 0x7e, 0x27, 0xd6, 0x22, 0x5d, 0x1c, 0x8b, 0x1a, + 0x28, 0x21, 0xf4, 0x23, 0xc4, 0x20, 0xae, 0x1b, 0xd3, 0x13, 0x1e, 0x0c, + 0xce, 0x07, 0x93, 0x07, 0xad, 0x0b, 0x82, 0x10, 0x0d, 0x18, 0x89, 0x28, + 0x40, 0x34, 0x06, 0x3c, 0x10, 0x45, 0xc6, 0x46, 0x26, 0x44, 0x18, 0x40, + 0x76, 0x41, 0x37, 0x4d, 0x9d, 0x57, 0x1d, 0x5b, 0x17, 0x62, 0x24, 0x63, + 0x44, 0x5f, 0x30, 0x5e, 0xb4, 0x55, 0x95, 0x51, 0xef, 0x4e, 0x79, 0x4a, + 0x7f, 0x4a, 0xf5, 0x42, 0xb3, 0x3a, 0xc0, 0x36, 0x8f, 0x32, 0x3b, 0x36, + 0x94, 0x3c, 0x91, 0x3f, 0xc9, 0x45, 0x20, 0x4d, 0xf1, 0x53, 0xd1, 0x59, + 0xab, 0x5b, 0x72, 0x5d, 0x26, 0x5b, 0x74, 0x51, 0x8a, 0x46, 0x28, 0x37, + 0x47, 0x25, 0x93, 0x17, 0x83, 0x08, 0x00, 0xfd, 0xd4, 0xf7, 0xd5, 0xf5, + 0x9e, 0xf9, 0x72, 0xff, 0x2e, 0x0b, 0x37, 0x16, 0x2e, 0x19, 0xde, 0x1a, + 0x3f, 0x19, 0xb3, 0x18, 0x75, 0x1c, 0xf2, 0x21, 0x86, 0x29, 0x0c, 0x2f, + 0x42, 0x34, 0x86, 0x3f, 0xbb, 0x48, 0xab, 0x4b, 0xea, 0x50, 0xfb, 0x4f, + 0x1c, 0x4b, 0x4f, 0x49, 0x37, 0x42, 0xd4, 0x37, 0xfb, 0x2b, 0x1a, 0x1e, + 0x7e, 0x14, 0x1f, 0x0f, 0xf5, 0x06, 0xe9, 0x03, 0x5a, 0x03, 0xe4, 0x01, + 0x77, 0x04, 0xfd, 0xff, 0x6a, 0xfc, 0x24, 0xfc, 0x97, 0xf7, 0xdc, 0xf3, + 0xd9, 0xef, 0x17, 0xe8, 0x68, 0xdd, 0xdd, 0xd3, 0x3b, 0xcd, 0x74, 0xcb, + 0xf7, 0xce, 0x22, 0xda, 0x7b, 0xe9, 0xf0, 0xf5, 0x1a, 0x02, 0xfb, 0x0c, + 0xad, 0x16, 0x21, 0x1c, 0x51, 0x1b, 0x67, 0x1e, 0xa8, 0x25, 0x4b, 0x2f, + 0x6e, 0x39, 0x0c, 0x3c, 0xae, 0x38, 0x7a, 0x32, 0x23, 0x2c, 0xab, 0x23, + 0x7e, 0x14, 0x61, 0x03, 0x35, 0xf8, 0x29, 0xf6, 0x07, 0xf6, 0x83, 0xef, + 0xb3, 0xe4, 0x0d, 0xd8, 0x16, 0xce, 0xc2, 0xc8, 0xf4, 0xc1, 0xf5, 0xb9, + 0xd5, 0xb1, 0x7d, 0xad, 0xa9, 0xac, 0xb6, 0xab, 0x4a, 0xac, 0x92, 0xad, + 0x8b, 0xb2, 0x18, 0xba, 0x25, 0xbd, 0x48, 0xbc, 0x9c, 0xba, 0xb4, 0xb5, + 0xe2, 0xb2, 0x0a, 0xb0, 0xea, 0xa8, 0x72, 0xa7, 0x33, 0xac, 0x9b, 0xb6, + 0x26, 0xc5, 0xe7, 0xd2, 0xb0, 0xd9, 0xa2, 0xde, 0xd7, 0xe3, 0xe3, 0xe4, + 0xce, 0xe4, 0x19, 0xde, 0xfa, 0xd7, 0xb7, 0xd1, 0x43, 0xcb, 0x2a, 0xcb, + 0x9d, 0xc9, 0x5f, 0xc4, 0x24, 0xbb, 0xed, 0xb2, 0x89, 0xac, 0xb5, 0xa8, + 0x96, 0xa8, 0xe8, 0xa8, 0x6e, 0xab, 0x0b, 0xac, 0x95, 0xa9, 0x15, 0xa6, + 0x80, 0x9f, 0x99, 0x9c, 0x30, 0x9b, 0xb7, 0x98, 0xaa, 0x98, 0xe6, 0x99, + 0x0b, 0xa2, 0x01, 0xac, 0x90, 0xb4, 0xc6, 0xb9, 0xce, 0xba, 0x5b, 0xb8, + 0xbe, 0xb1, 0x1a, 0xb1, 0xed, 0xb2, 0x10, 0xb7, 0xd5, 0xbf, 0x23, 0xcc, + 0xeb, 0xd9, 0x2d, 0xe1, 0x75, 0xe5, 0x1e, 0xe9, 0xa8, 0xe7, 0x48, 0xdd, + 0x5a, 0xce, 0xe8, 0xbe, 0x28, 0xb6, 0xbc, 0xc1, 0xa3, 0xd1, 0xdc, 0xce, + 0x37, 0xc3, 0x7a, 0xbe, 0xca, 0xc2, 0x8d, 0xc1, 0x48, 0xb4, 0x3f, 0xab, + 0xeb, 0xaa, 0x25, 0xb4, 0x6e, 0xc3, 0xf6, 0xca, 0x6c, 0xcd, 0x60, 0xd5, + 0xb0, 0xdd, 0x0e, 0xe0, 0x73, 0xdd, 0xe3, 0xd6, 0x4d, 0xd8, 0xcd, 0xdd, + 0x43, 0xdf, 0x64, 0xe8, 0x10, 0xf5, 0xad, 0xfc, 0x72, 0x00, 0x88, 0x00, + 0xb8, 0xf9, 0x01, 0xe9, 0xef, 0xdc, 0x8e, 0xd4, 0xe4, 0xc1, 0xb1, 0xb2, + 0x7d, 0xae, 0x87, 0xae, 0x62, 0xb1, 0xd6, 0xb5, 0xd7, 0xbb, 0x5f, 0xc6, + 0x01, 0xd3, 0x7c, 0xdc, 0x65, 0xe4, 0x3f, 0xeb, 0x77, 0xf2, 0xc9, 0xfb, + 0xf9, 0x05, 0xa4, 0x0b, 0xfa, 0x09, 0x5d, 0x0f, 0x33, 0x25, 0xde, 0x39, + 0x58, 0x41, 0xe5, 0x3d, 0xb8, 0x34, 0x54, 0x2b, 0xe2, 0x21, 0x2b, 0x1b, + 0x77, 0x12, 0x58, 0x0d, 0xc7, 0x11, 0x2e, 0x19, 0x64, 0x20, 0x67, 0x20, + 0x65, 0x1d, 0xaa, 0x18, 0x74, 0x14, 0xc3, 0x0e, 0xcf, 0x05, 0xcf, 0x01, + 0xff, 0xfd, 0x6d, 0xfd, 0x6d, 0x03, 0x47, 0x0f, 0xc7, 0x1e, 0x16, 0x30, + 0x00, 0x40, 0x72, 0x47, 0x46, 0x46, 0x89, 0x41, 0x69, 0x3e, 0x9b, 0x39, + 0xbb, 0x35, 0x62, 0x34, 0x43, 0x3a, 0x0c, 0x48, 0xe4, 0x56, 0xc9, 0x64, + 0x1c, 0x6b, 0x42, 0x6c, 0x5c, 0x69, 0x87, 0x66, 0x5a, 0x63, 0x12, 0x5d, + 0x31, 0x59, 0xb4, 0x54, 0x29, 0x52, 0xb7, 0x4f, 0x2e, 0x4c, 0x6d, 0x4a, + 0xf3, 0x44, 0x74, 0x3f, 0xd8, 0x40, 0x6b, 0x44, 0x69, 0x49, 0xaf, 0x50, + 0x99, 0x55, 0x43, 0x59, 0x72, 0x5d, 0xee, 0x5c, 0x27, 0x5a, 0x46, 0x56, + 0x55, 0x4d, 0x25, 0x49, 0xaf, 0x4a, 0xb4, 0x4d, 0x5c, 0x53, 0x33, 0x5d, + 0x60, 0x66, 0x45, 0x68, 0xe0, 0x68, 0x17, 0x69, 0xb7, 0x6b, 0xb7, 0x6d, + 0x31, 0x6e, 0x53, 0x6e, 0xeb, 0x6d, 0xf3, 0x70, 0x81, 0x72, 0xa4, 0x70, + 0x01, 0x68, 0x64, 0x5e, 0xe4, 0x56, 0xbf, 0x52, 0xd3, 0x50, 0xca, 0x4c, + 0x60, 0x4b, 0x74, 0x45, 0x9c, 0x3b, 0xbe, 0x33, 0x02, 0x28, 0xd9, 0x15, + 0x9e, 0x07, 0xd0, 0xfe, 0x07, 0xfc, 0x7d, 0xff, 0xc0, 0xff, 0xda, 0x00, + 0x19, 0x01, 0x60, 0x00, 0x89, 0x04, 0xa3, 0x08, 0xd0, 0x0d, 0xd1, 0x17, + 0x18, 0x1f, 0xf0, 0x29, 0x9b, 0x3d, 0x5a, 0x4f, 0x42, 0x5d, 0x98, 0x63, + 0xbc, 0x63, 0x42, 0x64, 0x81, 0x66, 0x2d, 0x65, 0x07, 0x5f, 0x8d, 0x54, + 0x3f, 0x48, 0x8f, 0x3e, 0x42, 0x31, 0xb4, 0x24, 0x4d, 0x1b, 0x83, 0x12, + 0xd3, 0x0b, 0x7e, 0x07, 0x25, 0x03, 0xbc, 0xfb, 0x77, 0xf1, 0xf4, 0xe6, + 0x3f, 0xe0, 0xd0, 0xd5, 0x34, 0xcc, 0x0a, 0xca, 0x14, 0xc9, 0x23, 0xcb, + 0x97, 0xd1, 0x27, 0xda, 0xb7, 0xe2, 0x26, 0xe8, 0x27, 0xed, 0x50, 0xf5, + 0x22, 0xfd, 0x48, 0x01, 0x6c, 0xfe, 0x7b, 0xf9, 0xe8, 0xf7, 0x8a, 0xf8, + 0x4b, 0xfa, 0x80, 0xff, 0x3b, 0x0d, 0x84, 0x1a, 0xfd, 0x23, 0xe0, 0x2d, + 0xda, 0x36, 0x2a, 0x3a, 0xa2, 0x39, 0x9e, 0x37, 0xad, 0x2b, 0xe9, 0x1b, + 0xa8, 0x0f, 0xe4, 0x00, 0xc0, 0xf4, 0xe9, 0xec, 0x9f, 0xe2, 0xd0, 0xde, + 0xe8, 0xdf, 0x04, 0xe0, 0x50, 0xdb, 0x01, 0xd4, 0x8b, 0xcf, 0x00, 0xc3, + 0xab, 0xb9, 0x80, 0xb7, 0x27, 0xb5, 0xe7, 0xb5, 0xdd, 0xb8, 0x83, 0xba, + 0x8b, 0xb8, 0xa9, 0xb8, 0xa9, 0xb5, 0xe9, 0xb2, 0x6e, 0xb2, 0xdf, 0xb1, + 0xe9, 0xb5, 0x8d, 0xbc, 0xae, 0xc6, 0x6a, 0xce, 0x55, 0xd2, 0x8e, 0xd7, + 0x29, 0xde, 0xcf, 0xdf, 0xf8, 0xdc, 0x3a, 0xdc, 0x11, 0xde, 0x19, 0xe3, + 0x5f, 0xe9, 0xa5, 0xf0, 0x61, 0xf8, 0x68, 0x00, 0x53, 0x08, 0x9c, 0x0b, + 0x31, 0x07, 0x96, 0x01, 0xb3, 0xf7, 0x6f, 0xea, 0x55, 0xe4, 0x4a, 0xde, + 0xf9, 0xd8, 0xde, 0xd5, 0xcf, 0xd3, 0x2c, 0xd4, 0x55, 0xd7, 0xf9, 0xda, + 0x71, 0xda, 0x91, 0xda, 0x60, 0xd8, 0x78, 0xd4, 0xa2, 0xd1, 0xd4, 0xce, + 0xd3, 0xd1, 0x51, 0xd6, 0xcd, 0xd5, 0x90, 0xd2, 0x3b, 0xce, 0x7a, 0xca, + 0xd7, 0xc6, 0xc3, 0xbf, 0x1d, 0xb8, 0x88, 0xb6, 0xe7, 0xb9, 0x84, 0xbe, + 0x91, 0xc5, 0x3c, 0xcd, 0x60, 0xd9, 0x0d, 0xe6, 0xe1, 0xea, 0xee, 0xed, + 0xa8, 0xec, 0xa4, 0xe9, 0x03, 0xea, 0xe9, 0xeb, 0x45, 0xee, 0x6e, 0xed, + 0xf1, 0xec, 0x1a, 0xec, 0x89, 0xe7, 0x1f, 0xe5, 0x3f, 0xe4, 0x09, 0xe2, + 0x84, 0xe0, 0xa4, 0xde, 0x25, 0xde, 0x43, 0xdf, 0xf8, 0xdf, 0x35, 0xde, + 0xb2, 0xe0, 0x61, 0xed, 0x5d, 0xfb, 0x92, 0xff, 0xde, 0xfd, 0xf0, 0x00, + 0x1a, 0x04, 0x77, 0x08, 0xd3, 0x08, 0xd6, 0x04, 0x63, 0x03, 0x8a, 0xfc, + 0xef, 0xf4, 0xf0, 0xed, 0x37, 0xe6, 0xd5, 0xda, 0xee, 0xca, 0xd8, 0xbc, + 0x78, 0xb4, 0xb8, 0xb3, 0x06, 0xb0, 0xda, 0xa5, 0xf2, 0x9a, 0xf1, 0x94, + 0xf0, 0x95, 0xa2, 0x99, 0x47, 0x9f, 0x90, 0xa7, 0xd0, 0xae, 0x0a, 0xb7, + 0xf3, 0xc2, 0x51, 0xcf, 0x93, 0xdb, 0x9d, 0xe3, 0xe2, 0xe8, 0xd0, 0xef, + 0x16, 0xfa, 0xef, 0x06, 0x22, 0x10, 0x1d, 0x16, 0x7b, 0x1a, 0x41, 0x21, + 0x8c, 0x29, 0x91, 0x2c, 0x22, 0x2e, 0xaf, 0x2f, 0x07, 0x35, 0x45, 0x3b, + 0x7e, 0x3a, 0x21, 0x3d, 0x67, 0x3e, 0x3f, 0x37, 0xb7, 0x2e, 0x98, 0x25, + 0xf3, 0x1b, 0xa5, 0x0e, 0x58, 0x00, 0xbc, 0xf4, 0x7a, 0xea, 0x45, 0xe0, + 0xfa, 0xd8, 0xe8, 0xd7, 0x51, 0xd9, 0x52, 0xdc, 0xcd, 0xdd, 0xc1, 0xda, + 0xc3, 0xda, 0xfc, 0xdb, 0x66, 0xdb, 0xfc, 0xde, 0x1b, 0xe1, 0xc5, 0xe1, + 0x67, 0xe0, 0x59, 0xdc, 0x43, 0xda, 0x18, 0xd6, 0x95, 0xd5, 0x30, 0xdb, + 0xf8, 0xe4, 0xb1, 0xf0, 0xc6, 0x00, 0xac, 0x11, 0xbc, 0x1c, 0x29, 0x26, + 0xd6, 0x26, 0x06, 0x23, 0xf1, 0x24, 0xba, 0x2e, 0x30, 0x3e, 0x71, 0x4f, + 0xad, 0x5e, 0x6f, 0x69, 0x2f, 0x70, 0xf8, 0x70, 0x51, 0x6f, 0xd1, 0x6a, + 0x33, 0x65, 0x14, 0x5a, 0x38, 0x4a, 0xc5, 0x3c, 0xbb, 0x31, 0x3e, 0x2a, + 0x48, 0x22, 0x94, 0x1b, 0x56, 0x16, 0x04, 0x17, 0xce, 0x1b, 0x6b, 0x1d, + 0x97, 0x20, 0x48, 0x26, 0x0a, 0x29, 0x92, 0x2a, 0xb6, 0x2e, 0xca, 0x2f, + 0x65, 0x32, 0xd2, 0x34, 0xdf, 0x39, 0x65, 0x43, 0x9d, 0x48, 0x5f, 0x4d, + 0x37, 0x53, 0xb6, 0x56, 0x8a, 0x56, 0x14, 0x5b, 0xe0, 0x61, 0x31, 0x65, + 0x7e, 0x65, 0x60, 0x65, 0x4b, 0x66, 0xd0, 0x65, 0x33, 0x63, 0x32, 0x5f, + 0x91, 0x60, 0xb3, 0x61, 0x98, 0x5f, 0x82, 0x5c, 0x83, 0x5b, 0xd9, 0x5b, + 0x7b, 0x5c, 0xd4, 0x61, 0xe8, 0x64, 0xd0, 0x64, 0x19, 0x60, 0xc7, 0x54, + 0x57, 0x48, 0xaf, 0x41, 0x48, 0x38, 0x3e, 0x28, 0x6f, 0x1b, 0x0d, 0x13, + 0x2d, 0x12, 0xea, 0x13, 0x1e, 0x15, 0x9e, 0x15, 0x9b, 0x12, 0xc4, 0x0e, + 0x11, 0x0e, 0xf9, 0x0f, 0x14, 0x14, 0x37, 0x1e, 0x48, 0x2b, 0x98, 0x38, + 0x90, 0x47, 0x2b, 0x57, 0x1c, 0x64, 0xe4, 0x6c, 0x42, 0x6e, 0x35, 0x6d, + 0x80, 0x70, 0x0f, 0x73, 0x2e, 0x74, 0x75, 0x75, 0xcb, 0x75, 0xb0, 0x75, + 0x78, 0x74, 0x81, 0x6f, 0x26, 0x65, 0x9f, 0x4f, 0x5a, 0x33, 0x8a, 0x1a, + 0x63, 0x06, 0xa9, 0xfa, 0xed, 0xf8, 0x1f, 0xfb, 0x8b, 0xff, 0x07, 0x05, + 0x37, 0x03, 0xd4, 0xfd, 0x11, 0xf9, 0xe4, 0xf7, 0x4c, 0xf9, 0xef, 0xfa, + 0x4b, 0x00, 0xf9, 0x03, 0xd6, 0x0a, 0x63, 0x13, 0xb9, 0x18, 0x25, 0x1c, + 0x2a, 0x1f, 0xc2, 0x27, 0x36, 0x30, 0x54, 0x39, 0xd1, 0x42, 0x75, 0x45, + 0x59, 0x44, 0x8b, 0x42, 0xaf, 0x3e, 0xd7, 0x36, 0x6d, 0x2b, 0xd9, 0x21, + 0xb2, 0x1d, 0x40, 0x1b, 0xf4, 0x15, 0xbd, 0x0f, 0x8b, 0x09, 0x17, 0x00, + 0xff, 0xf6, 0x45, 0xf0, 0x00, 0xeb, 0x90, 0xe6, 0xc8, 0xe1, 0x36, 0xe1, + 0x0f, 0xe2, 0x19, 0xdf, 0xd0, 0xdc, 0x4f, 0xda, 0x9c, 0xd8, 0xaf, 0xdd, + 0x8c, 0xe0, 0x96, 0xe2, 0x9b, 0xe7, 0xc6, 0xea, 0xd2, 0xf1, 0x0b, 0xf8, + 0xf9, 0xfc, 0x8c, 0x02, 0xfe, 0x04, 0x07, 0x0c, 0xb3, 0x16, 0x21, 0x1e, + 0x19, 0x23, 0x0e, 0x26, 0x85, 0x25, 0x3f, 0x22, 0x3d, 0x1b, 0xb3, 0x11, + 0x45, 0x08, 0x49, 0x02, 0xf8, 0xff, 0x03, 0xfd, 0x4b, 0xfb, 0x8b, 0xfb, + 0xfd, 0xfb, 0xbb, 0xf6, 0xa6, 0xe9, 0xec, 0xdd, 0xb1, 0xd8, 0xb8, 0xd1, + 0xd5, 0xc4, 0x0b, 0xbc, 0x36, 0xb7, 0x18, 0xb3, 0xbe, 0xb1, 0xfe, 0xb1, + 0xa3, 0xb4, 0x94, 0xb7, 0x42, 0xba, 0xd6, 0xc2, 0xea, 0xd1, 0x7c, 0xdf, + 0x63, 0xe9, 0x6e, 0xed, 0x38, 0xec, 0x4a, 0xea, 0x95, 0xe5, 0x38, 0xdf, + 0x7a, 0xdc, 0xce, 0xdd, 0xf8, 0xdc, 0x6f, 0xd5, 0x4a, 0xcc, 0x17, 0xc2, + 0x2d, 0xb1, 0x36, 0xa2, 0xde, 0x98, 0xf9, 0x90, 0x62, 0x8e, 0xdd, 0x8d, + 0x98, 0x8c, 0xec, 0x8c, 0xf7, 0x8e, 0x4b, 0x90, 0x6e, 0x8f, 0xdd, 0x8c, + 0x42, 0x8a, 0xb3, 0x8a, 0x6e, 0x8c, 0x31, 0x91, 0x34, 0x98, 0xb5, 0xa6, + 0x90, 0xbf, 0x41, 0xd5, 0x5f, 0xe4, 0xf9, 0xe6, 0x28, 0xe2, 0x2c, 0xde, + 0x32, 0xd4, 0xdf, 0xce, 0xe4, 0xcb, 0x87, 0xc8, 0x13, 0xce, 0x96, 0xd1, + 0x64, 0xd0, 0x0f, 0xcd, 0xb6, 0xc2, 0xf8, 0xb8, 0x44, 0xb8, 0x69, 0xb7, + 0x5a, 0xb3, 0x0e, 0xb0, 0x7e, 0xad, 0xa4, 0xb0, 0x35, 0xb1, 0x93, 0xac, + 0xb0, 0xa9, 0x97, 0xa2, 0x67, 0x9f, 0x90, 0xa2, 0x5b, 0xa0, 0xcb, 0xa3, + 0xe3, 0xad, 0xc3, 0xb7, 0x48, 0xc6, 0x78, 0xd1, 0x39, 0xda, 0xb0, 0xe1, + 0xfb, 0xe1, 0x04, 0xdf, 0x08, 0xdd, 0x53, 0xdb, 0x26, 0xd7, 0xbf, 0xcf, + 0xea, 0xc3, 0x10, 0xbb, 0x72, 0xb5, 0x6a, 0xb2, 0xba, 0xb9, 0x98, 0xbd, + 0x56, 0xbc, 0x15, 0xc0, 0x7f, 0xc5, 0xa9, 0xcb, 0x7e, 0xce, 0x59, 0xcf, + 0xd1, 0xd1, 0x72, 0xd2, 0x6c, 0xd3, 0x3b, 0xd5, 0x45, 0xd4, 0x12, 0xd2, + 0xeb, 0xd2, 0x24, 0xd5, 0x1e, 0xd5, 0x06, 0xcc, 0x6c, 0xbb, 0x73, 0xb6, + 0x50, 0xb9, 0xb4, 0xb8, 0x69, 0xb9, 0x84, 0xbc, 0x33, 0xc8, 0xbd, 0xd7, + 0x9f, 0xe2, 0x5b, 0xe7, 0x0e, 0xe4, 0x98, 0xdf, 0xd2, 0xdd, 0x17, 0xe3, + 0x9c, 0xed, 0x90, 0xfb, 0xce, 0x11, 0xb4, 0x27, 0xd8, 0x37, 0x10, 0x41, + 0x65, 0x40, 0x9c, 0x39, 0xfc, 0x32, 0xce, 0x28, 0xc2, 0x18, 0xc9, 0x0a, + 0xb8, 0x01, 0x7e, 0xfe, 0x3d, 0xfa, 0x18, 0xf2, 0x70, 0xe9, 0x9d, 0xe2, + 0x24, 0xe1, 0x59, 0xe0, 0xcc, 0xe1, 0xaa, 0xe2, 0xdf, 0xdf, 0xd7, 0xdf, + 0xc5, 0xe5, 0x8a, 0xeb, 0x8d, 0xea, 0x26, 0xec, 0x0b, 0xef, 0x3e, 0xf1, + 0x27, 0xf7, 0x75, 0xfb, 0x12, 0xfe, 0x47, 0xfd, 0x01, 0xf7, 0xed, 0xef, + 0xfc, 0xed, 0xca, 0xf0, 0x99, 0xf1, 0xad, 0xef, 0xdd, 0xf0, 0x04, 0xf8, + 0x63, 0x05, 0x50, 0x11, 0xaa, 0x14, 0x00, 0x15, 0xa9, 0x15, 0x9d, 0x16, + 0x80, 0x14, 0xce, 0x12, 0x66, 0x11, 0xca, 0x0e, 0x3a, 0x0f, 0x91, 0x0e, + 0xbd, 0x10, 0xc6, 0x10, 0x6a, 0x0c, 0xfb, 0x07, 0x07, 0x05, 0xbd, 0x06, + 0x85, 0x08, 0xe0, 0x0d, 0x65, 0x16, 0x2e, 0x22, 0x35, 0x28, 0x80, 0x22, + 0x78, 0x1c, 0x1d, 0x14, 0x78, 0x06, 0x86, 0xf6, 0x92, 0xe9, 0xc2, 0xde, + 0xeb, 0xd7, 0x02, 0xd9, 0x62, 0xdb, 0xa7, 0xdf, 0xdf, 0xe6, 0x89, 0xee, + 0x06, 0xf3, 0xb1, 0xf4, 0xd0, 0xf9, 0x46, 0xfd, 0x2c, 0xfe, 0x5a, 0xff, + 0x2f, 0xfd, 0xfb, 0x00, 0x17, 0x0a, 0xce, 0x12, 0x5a, 0x1b, 0xb7, 0x21, + 0x88, 0x2a, 0x6d, 0x30, 0x2e, 0x34, 0x8e, 0x39, 0xff, 0x3d, 0xfe, 0x44, + 0x5e, 0x48, 0x6f, 0x47, 0xe8, 0x47, 0x41, 0x46, 0xcc, 0x45, 0x96, 0x47, + 0x8c, 0x48, 0xbc, 0x4b, 0x4b, 0x4c, 0x19, 0x4f, 0xf6, 0x54, 0x1c, 0x57, + 0x6e, 0x59, 0xb9, 0x55, 0x02, 0x48, 0x7a, 0x35, 0xe6, 0x20, 0x47, 0x0d, + 0x96, 0x00, 0x8c, 0xfc, 0xbc, 0xff, 0x1b, 0x09, 0xc9, 0x15, 0xb7, 0x28, + 0x28, 0x3d, 0x86, 0x4d, 0xe7, 0x57, 0x69, 0x5c, 0x0a, 0x63, 0x99, 0x67, + 0x86, 0x64, 0x91, 0x5e, 0x2b, 0x57, 0x3e, 0x54, 0xd6, 0x53, 0x1f, 0x4d, + 0xd5, 0x41, 0x4e, 0x34, 0xed, 0x2c, 0x80, 0x2b, 0x73, 0x2d, 0xd8, 0x32, + 0xbb, 0x37, 0x10, 0x44, 0x28, 0x50, 0x91, 0x56, 0x0a, 0x5d, 0x41, 0x61, + 0xbb, 0x61, 0xaf, 0x61, 0xe0, 0x66, 0x3a, 0x69, 0x69, 0x6b, 0x01, 0x71, + 0xa7, 0x74, 0x38, 0x77, 0xf0, 0x75, 0x6c, 0x72, 0x5f, 0x6b, 0x97, 0x64, + 0x4f, 0x62, 0xc3, 0x5f, 0x7a, 0x5c, 0xb9, 0x5a, 0xa0, 0x5c, 0x43, 0x61, + 0xf2, 0x64, 0xd6, 0x65, 0x5f, 0x61, 0x38, 0x5a, 0x98, 0x58, 0x29, 0x57, + 0xde, 0x57, 0x53, 0x5b, 0x05, 0x57, 0x4e, 0x4d, 0x37, 0x43, 0x66, 0x3d, + 0x39, 0x39, 0x9c, 0x35, 0xfa, 0x32, 0x0d, 0x33, 0x10, 0x38, 0xc4, 0x3d, + 0x58, 0x45, 0xfc, 0x48, 0x6b, 0x46, 0x9e, 0x42, 0x8e, 0x43, 0x88, 0x4c, + 0x38, 0x57, 0xb2, 0x5e, 0x3f, 0x64, 0x23, 0x6a, 0x9f, 0x6b, 0xfc, 0x6a, + 0xad, 0x69, 0x67, 0x66, 0x5c, 0x62, 0x27, 0x59, 0x6c, 0x4c, 0x77, 0x3f, + 0x02, 0x3a, 0x69, 0x3f, 0x25, 0x42, 0x2b, 0x3d, 0xb6, 0x38, 0x97, 0x34, + 0xa0, 0x2f, 0xc8, 0x2b, 0x00, 0x24, 0x5a, 0x1b, 0x94, 0x16, 0x81, 0x13, + 0x1e, 0x12, 0xb7, 0x0f, 0xde, 0x09, 0x0a, 0x03, 0x0d, 0x02, 0x34, 0x02, + 0xb4, 0x01, 0xc1, 0x04, 0xd0, 0x07, 0xda, 0x11, 0x1c, 0x1d, 0x30, 0x26, + 0x81, 0x2d, 0x1d, 0x27, 0x42, 0x1e, 0xd6, 0x19, 0x0f, 0x1b, 0x91, 0x23, + 0x85, 0x28, 0x7f, 0x28, 0xc0, 0x26, 0x06, 0x23, 0x7f, 0x1b, 0xc9, 0x0e, + 0x9b, 0x01, 0xdc, 0xf4, 0x39, 0xea, 0x7a, 0xe4, 0x51, 0xe1, 0x4c, 0xe4, + 0x45, 0xe8, 0x79, 0xec, 0xd2, 0xf0, 0x87, 0xf4, 0xb9, 0xfc, 0xf9, 0x02, + 0x51, 0x0c, 0x48, 0x13, 0xdd, 0x14, 0x18, 0x14, 0x64, 0x0d, 0x18, 0x07, + 0x33, 0xfe, 0xd7, 0xf5, 0x90, 0xf0, 0x7e, 0xf3, 0xe2, 0xfa, 0x06, 0xfc, + 0x78, 0xf8, 0x3a, 0xf3, 0xf8, 0xf1, 0x5c, 0xf0, 0xe7, 0xee, 0x6f, 0xf0, + 0x83, 0xf5, 0xca, 0xfa, 0xa0, 0x02, 0x32, 0x0f, 0x4e, 0x14, 0x19, 0x15, + 0x45, 0x12, 0x66, 0x0a, 0xba, 0x04, 0xa8, 0x03, 0x37, 0x03, 0x7a, 0x03, + 0xcc, 0x02, 0x8a, 0xfd, 0xe6, 0xf7, 0xe7, 0xec, 0x3c, 0xdc, 0xf5, 0xc3, + 0x7f, 0xaa, 0xaa, 0x9e, 0xa8, 0x9e, 0x97, 0xa3, 0x60, 0xa8, 0xd2, 0xae, + 0xde, 0xb2, 0x93, 0xb7, 0x8e, 0xbd, 0x49, 0xbd, 0xb7, 0xb9, 0xb0, 0xba, + 0x16, 0xc9, 0x22, 0xde, 0xe1, 0xf7, 0xdb, 0x12, 0x55, 0x26, 0xd1, 0x38, + 0xe5, 0x49, 0x35, 0x54, 0xd3, 0x4f, 0x65, 0x42, 0x6d, 0x3e, 0x4b, 0x3e, + 0xf1, 0x3b, 0x85, 0x34, 0x3e, 0x21, 0x63, 0x0f, 0x52, 0x05, 0x7f, 0xf9, + 0x53, 0xe8, 0x43, 0xd0, 0x69, 0xb5, 0x79, 0xa3, 0xe6, 0x9b, 0xf3, 0x99, + 0x31, 0x9b, 0x5d, 0x9c, 0x09, 0x9f, 0xa4, 0xa2, 0xae, 0xa4, 0x35, 0xa6, + 0x65, 0xa8, 0x84, 0xa9, 0x37, 0xb0, 0x73, 0xb8, 0x6f, 0xb7, 0x68, 0xb9, + 0x69, 0xbf, 0xfa, 0xc8, 0xe5, 0xd1, 0x56, 0xd4, 0x90, 0xd5, 0x4d, 0xd4, + 0x94, 0xd5, 0x87, 0xd4, 0xf5, 0xce, 0x48, 0xcc, 0x1b, 0xd2, 0xfd, 0xdf, + 0x59, 0xf1, 0x1a, 0x04, 0xbb, 0x12, 0xce, 0x1d, 0xc7, 0x22, 0x33, 0x1d, + 0x0a, 0x0f, 0xbb, 0xfc, 0xbe, 0xea, 0x1c, 0xdc, 0xae, 0xcc, 0xc3, 0xba, + 0x96, 0xac, 0x3d, 0xa4, 0xc4, 0xa0, 0xf1, 0x9e, 0xb9, 0x9c, 0x9b, 0x97, + 0x23, 0x94, 0xc4, 0x93, 0x90, 0x92, 0xa1, 0x92, 0x19, 0x93, 0x05, 0x94, + 0xe5, 0x97, 0x39, 0xa1, 0x7d, 0xae, 0x4d, 0xc1, 0x9b, 0xdc, 0x08, 0xfc, + 0x60, 0x18, 0x43, 0x2c, 0xf9, 0x35, 0x08, 0x37, 0xb1, 0x2f, 0x20, 0x1d, + 0x50, 0x08, 0xa7, 0xf3, 0xb4, 0xe1, 0x7f, 0xd3, 0x7e, 0xc9, 0x54, 0xc8, + 0x57, 0xc7, 0x54, 0xcb, 0x57, 0xd1, 0xd8, 0xd7, 0x88, 0xde, 0x57, 0xde, + 0x41, 0xdf, 0xb2, 0xdc, 0xe4, 0xd7, 0x61, 0xd0, 0x63, 0xca, 0xf9, 0xc9, + 0x0f, 0xca, 0x0e, 0xd1, 0x9a, 0xd4, 0x98, 0xd4, 0xc9, 0xd9, 0x73, 0xde, + 0x25, 0xdf, 0x04, 0xdc, 0x73, 0xd7, 0xd8, 0xcd, 0x1a, 0xbf, 0x80, 0xb3, + 0xd1, 0xaa, 0x09, 0xa6, 0xf8, 0xa4, 0x5f, 0xa6, 0xc2, 0xad, 0x66, 0xb3, + 0xb3, 0xb5, 0x49, 0xb5, 0xd1, 0xb2, 0x9c, 0xb2, 0xea, 0xb7, 0x26, 0xc1, + 0x92, 0xc9, 0xe8, 0xd7, 0x68, 0xe5, 0x32, 0xf0, 0x17, 0xfa, 0x5c, 0xfc, + 0x52, 0xf9, 0x5e, 0xf3, 0xb8, 0xe8, 0x8a, 0xda, 0x94, 0xd4, 0x88, 0xd6, + 0xd0, 0xda, 0x16, 0xdb, 0x15, 0xd8, 0x78, 0xd6, 0x90, 0xd8, 0xe3, 0xdd, + 0x7f, 0xdb, 0x90, 0xd6, 0x40, 0xd1, 0x9a, 0xce, 0xb7, 0xd1, 0xc3, 0xd5, + 0x20, 0xde, 0xf5, 0xea, 0x11, 0xf6, 0x7d, 0x00, 0x4c, 0x07, 0x8a, 0x01, + 0x6f, 0xfb, 0xa0, 0xf2, 0x76, 0xe4, 0x4a, 0xda, 0x0d, 0xd4, 0xf2, 0xd8, + 0x2b, 0xe2, 0x72, 0xe7, 0x6a, 0xee, 0xc7, 0xf1, 0xd4, 0xef, 0xed, 0xf2, + 0xc8, 0xf0, 0xbb, 0xe7, 0x6e, 0xe2, 0xb1, 0xe1, 0x81, 0xe3, 0x01, 0xe6, + 0xd3, 0xeb, 0xc7, 0xee, 0x9e, 0xf1, 0x2a, 0xf3, 0xee, 0xef, 0x4f, 0xed, + 0xb2, 0xef, 0x51, 0xfa, 0xfa, 0x05, 0x01, 0x10, 0x30, 0x1a, 0x69, 0x25, + 0xdd, 0x2a, 0xc2, 0x2d, 0x81, 0x2e, 0x91, 0x25, 0x93, 0x1e, 0x59, 0x1a, + 0xa5, 0x15, 0x56, 0x13, 0x8b, 0x11, 0x1b, 0x11, 0x49, 0x12, 0x2c, 0x14, + 0x65, 0x19, 0x65, 0x1e, 0xdd, 0x1f, 0xa9, 0x23, 0xca, 0x28, 0x7b, 0x2b, + 0xc8, 0x2d, 0x93, 0x32, 0xde, 0x34, 0xa4, 0x32, 0xae, 0x32, 0x93, 0x34, + 0x9d, 0x35, 0x09, 0x34, 0x16, 0x30, 0xbb, 0x2d, 0xfa, 0x2c, 0x11, 0x2f, + 0x68, 0x35, 0x8f, 0x3c, 0x80, 0x3f, 0x3d, 0x3e, 0x65, 0x39, 0xf0, 0x31, + 0xc9, 0x2e, 0xe5, 0x2a, 0x9f, 0x22, 0x64, 0x1c, 0xec, 0x13, 0x7b, 0x0c, + 0x18, 0x0b, 0x0e, 0x0c, 0x53, 0x11, 0x78, 0x16, 0x67, 0x18, 0x8a, 0x1a, + 0x1a, 0x1d, 0x21, 0x22, 0x53, 0x22, 0x08, 0x1b, 0x90, 0x17, 0xfc, 0x18, + 0x5b, 0x1a, 0x34, 0x1a, 0x8c, 0x17, 0x5a, 0x15, 0xc6, 0x16, 0x8f, 0x1b, + 0xf1, 0x21, 0xe2, 0x27, 0x40, 0x32, 0xcf, 0x3a, 0x37, 0x3f, 0xf3, 0x42, + 0x68, 0x3f, 0x2d, 0x3d, 0xb7, 0x3f, 0x33, 0x40, 0x67, 0x3e, 0x0e, 0x38, + 0x06, 0x2e, 0xaa, 0x26, 0x68, 0x24, 0x41, 0x20, 0x95, 0x14, 0x17, 0x0a, + 0x93, 0x01, 0xe3, 0xf6, 0x9b, 0xf3, 0x39, 0xf3, 0x66, 0xf5, 0x97, 0x01, + 0xd0, 0x0f, 0x59, 0x19, 0x87, 0x1f, 0x96, 0x24, 0xd3, 0x27, 0x11, 0x2e, + 0x4f, 0x32, 0x99, 0x30, 0x9b, 0x2f, 0xdb, 0x2d, 0x95, 0x31, 0x3e, 0x42, + 0x1c, 0x4e, 0x25, 0x53, 0xcb, 0x5a, 0x33, 0x5f, 0x29, 0x61, 0x10, 0x5e, + 0x82, 0x55, 0xfa, 0x49, 0xaa, 0x42, 0xfa, 0x40, 0x6c, 0x3f, 0xcb, 0x3e, + 0x1a, 0x3e, 0x60, 0x41, 0x38, 0x45, 0xd1, 0x4e, 0x79, 0x55, 0xa6, 0x52, + 0xda, 0x50, 0x35, 0x4a, 0x11, 0x43, 0x5e, 0x39, 0xbd, 0x2d, 0xdb, 0x26, + 0x4c, 0x28, 0x8a, 0x2b, 0x69, 0x23, 0xf9, 0x1b, 0xc0, 0x1b, 0x8c, 0x22, + 0x56, 0x29, 0x12, 0x26, 0x5b, 0x21, 0xea, 0x23, 0xb8, 0x2c, 0xec, 0x31, + 0xa7, 0x38, 0xe6, 0x44, 0x0e, 0x4e, 0xda, 0x56, 0xed, 0x58, 0xb9, 0x4f, + 0x49, 0x41, 0xa8, 0x31, 0x29, 0x27, 0x74, 0x23, 0x2f, 0x21, 0xb5, 0x22, + 0x6d, 0x2c, 0x44, 0x37, 0x81, 0x3e, 0xcf, 0x3f, 0x7b, 0x3d, 0x03, 0x39, + 0xca, 0x32, 0xd5, 0x2d, 0x0d, 0x24, 0x27, 0x18, 0x11, 0x0c, 0x3f, 0x01, + 0x11, 0x01, 0xa3, 0x0a, 0x9c, 0x16, 0xbb, 0x1f, 0x9d, 0x27, 0xce, 0x2e, + 0x6e, 0x32, 0xcf, 0x2e, 0x9b, 0x22, 0xff, 0x13, 0x9d, 0x06, 0x41, 0xfb, + 0x4c, 0xf7, 0x01, 0xff, 0xe1, 0x0d, 0xe7, 0x19, 0x17, 0x23, 0xcd, 0x29, + 0x3b, 0x28, 0xc6, 0x25, 0xad, 0x24, 0x92, 0x22, 0x0f, 0x23, 0x9b, 0x1f, + 0x7c, 0x16, 0x04, 0x0f, 0x0f, 0x0e, 0x8f, 0x13, 0xbb, 0x1a, 0x6b, 0x23, + 0x17, 0x26, 0x89, 0x1e, 0xaf, 0x14, 0x42, 0x0b, 0x2c, 0x05, 0x2d, 0x00, + 0x2e, 0xf8, 0xda, 0xef, 0x86, 0xe9, 0x8d, 0xe4, 0xb7, 0xe2, 0x23, 0xe7, + 0x9e, 0xf0, 0x67, 0xfc, 0xd2, 0x06, 0xe1, 0x14, 0xe5, 0x24, 0x84, 0x31, + 0xe8, 0x3d, 0x0e, 0x43, 0xb4, 0x43, 0x3e, 0x43, 0xae, 0x3d, 0x09, 0x32, + 0xb4, 0x22, 0xe9, 0x16, 0x3f, 0x11, 0x46, 0x0e, 0x39, 0x07, 0x63, 0x02, + 0xcf, 0xfd, 0xdb, 0xef, 0x30, 0xe4, 0xe8, 0xdb, 0xc8, 0xd3, 0x7b, 0xd0, + 0xcd, 0xcd, 0xf0, 0xce, 0x2b, 0xd6, 0x63, 0xda, 0xd1, 0xe1, 0xd2, 0xf2, + 0x7f, 0x01, 0x9f, 0x0a, 0xb4, 0x15, 0x3f, 0x1f, 0xe0, 0x21, 0x8e, 0x22, + 0xcb, 0x1f, 0x50, 0x1d, 0x94, 0x23, 0xfd, 0x28, 0x7b, 0x28, 0x2b, 0x26, + 0xcd, 0x25, 0xe8, 0x26, 0x49, 0x20, 0x73, 0x14, 0xa3, 0x07, 0x53, 0xf9, + 0x79, 0xed, 0x1e, 0xe2, 0xd5, 0xdc, 0x14, 0xdf, 0x92, 0xdd, 0xc3, 0xd9, + 0x02, 0xda, 0x4e, 0xd9, 0x55, 0xd8, 0x21, 0xde, 0x9c, 0xe6, 0x83, 0xf5, + 0x34, 0x08, 0x99, 0x15, 0x44, 0x1f, 0xae, 0x1f, 0x0c, 0x1e, 0xbe, 0x19, + 0xc7, 0x10, 0x84, 0x0e, 0x79, 0x10, 0x88, 0x18, 0x2d, 0x1f, 0x1c, 0x22, + 0xb2, 0x25, 0xed, 0x25, 0x6b, 0x26, 0xb0, 0x24, 0x0f, 0x20, 0xfc, 0x13, + 0x52, 0x05, 0x38, 0xf8, 0x28, 0xe5, 0xe2, 0xd6, 0x3e, 0xce, 0xb2, 0xc8, + 0xb9, 0xca, 0x1c, 0xcc, 0x42, 0xc5, 0x07, 0xbc, 0x92, 0xb4, 0x70, 0xa9, + 0x47, 0x9e, 0xfb, 0x98, 0xd7, 0x99, 0xfe, 0x9c, 0x87, 0x9f, 0xbe, 0x9e, + 0xba, 0x9f, 0x3f, 0xaa, 0x87, 0xb9, 0xb1, 0xc8, 0x7e, 0xd5, 0x6e, 0xe0, + 0x56, 0xf1, 0x7e, 0x0a, 0x3e, 0x19, 0xe9, 0x1f, 0x9f, 0x28, 0x9b, 0x2c, + 0x82, 0x30, 0x81, 0x2e, 0x8d, 0x24, 0x7c, 0x16, 0x7e, 0x02, 0xf2, 0xf1, + 0x16, 0xe4, 0x92, 0xcd, 0x99, 0xb6, 0xdb, 0xaa, 0x3c, 0xa6, 0xd1, 0xa3, + 0x15, 0xa0, 0xc9, 0x9c, 0x8f, 0x99, 0x01, 0x97, 0x0f, 0x97, 0xc0, 0x95, + 0x0c, 0x94, 0x78, 0x97, 0x2f, 0xa1, 0x76, 0xac, 0x1d, 0xb9, 0x5e, 0xc5, + 0x83, 0xd0, 0x3c, 0xdc, 0x3b, 0xe4, 0x7a, 0xe6, 0x2d, 0xe5, 0x70, 0xe6, + 0xb6, 0xe8, 0x24, 0xf2, 0x32, 0x02, 0x64, 0x05, 0x97, 0x09, 0x20, 0x0e, + 0x7d, 0x06, 0x33, 0x00, 0xc9, 0xef, 0x63, 0xdc, 0xa9, 0xd1, 0x2f, 0xc9, + 0x99, 0xc8, 0x39, 0xcb, 0x73, 0xd1, 0xeb, 0xd5, 0x7c, 0xcd, 0xfe, 0xbd, + 0x07, 0xae, 0x18, 0x9f, 0x2d, 0x96, 0x91, 0x95, 0xcd, 0x97, 0x0e, 0x9f, + 0xdb, 0xaa, 0xd2, 0xb7, 0x90, 0xc3, 0x3a, 0xc6, 0xee, 0xcd, 0xcf, 0xd9, + 0xde, 0xdc, 0x1e, 0xde, 0x46, 0xdd, 0x68, 0xdd, 0xd8, 0xd7, 0xd2, 0xd3, + 0x2d, 0xd2, 0x9e, 0xc9, 0x16, 0xc7, 0xee, 0xc3, 0xf9, 0xc2, 0xa7, 0xc8, + 0x8a, 0xd4, 0x7b, 0xe3, 0xea, 0xef, 0x33, 0xf9, 0xd7, 0xfc, 0xf2, 0x01, + 0xc9, 0x02, 0x96, 0xfd, 0xf2, 0xf0, 0x1a, 0xdf, 0xf6, 0xd1, 0x7c, 0xcb, + 0x9e, 0xcd, 0x58, 0xd1, 0x1c, 0xd6, 0xc9, 0xdd, 0x4b, 0xe0, 0xd2, 0xdd, + 0xfe, 0xdb, 0xbc, 0xde, 0x51, 0xe7, 0x87, 0xee, 0x44, 0xf3, 0x77, 0xed, + 0x26, 0xe2, 0x3c, 0xe0, 0xdf, 0xdb, 0x06, 0xd3, 0x8f, 0xcc, 0x9d, 0xc5, + 0x91, 0xc2, 0x1d, 0xc9, 0xeb, 0xcc, 0xd2, 0xcb, 0x7a, 0xcb, 0xef, 0xcb, + 0x24, 0xd1, 0x20, 0xd5, 0x35, 0xd5, 0xcd, 0xd6, 0xe5, 0xdb, 0xa3, 0xe3, + 0xff, 0xee, 0x48, 0xf7, 0xc9, 0x00, 0x13, 0x08, 0x0b, 0x0b, 0x00, 0x11, + 0xa2, 0x10, 0xe0, 0x0f, 0xaf, 0x0d, 0xf4, 0x0b, 0x07, 0x09, 0x62, 0xfc, + 0xef, 0xea, 0xb4, 0xdc, 0xbe, 0xd8, 0x69, 0xda, 0x67, 0xe2, 0x31, 0xf0, + 0xfc, 0x00, 0xa9, 0x0c, 0xdd, 0x16, 0xc7, 0x1e, 0x11, 0x1d, 0xc8, 0x1d, + 0xf6, 0x1e, 0x6a, 0x21, 0x9b, 0x1e, 0x6a, 0x14, 0x85, 0x11, 0xbe, 0x0e, + 0x56, 0x08, 0x49, 0x02, 0x7a, 0xf7, 0x97, 0xe9, 0x8a, 0xdb, 0x89, 0xd2, + 0x1d, 0xd5, 0x10, 0xd7, 0x23, 0xd4, 0xab, 0xd7, 0x61, 0xd7, 0x58, 0xce, + 0x15, 0xcf, 0xf7, 0xd5, 0x4e, 0xd9, 0x5a, 0xdf, 0xd2, 0xea, 0x9c, 0xf5, + 0x8c, 0xfe, 0x7a, 0x04, 0x28, 0x09, 0xf6, 0x0e, 0xd7, 0x0c, 0x49, 0x09, + 0x01, 0x03, 0xbc, 0xf9, 0x57, 0xf5, 0xc9, 0xf7, 0xc1, 0x01, 0xe6, 0x0c, + 0x3b, 0x1d, 0x67, 0x2c, 0xde, 0x40, 0x63, 0x56, 0x4e, 0x60, 0xe5, 0x63, + 0x68, 0x5e, 0x7b, 0x55, 0xe1, 0x44, 0xa0, 0x2d, 0x82, 0x13, 0xb1, 0xff, + 0x44, 0xf2, 0xff, 0xe6, 0x9f, 0xe4, 0x5f, 0xe5, 0x27, 0xe9, 0xaa, 0xec, + 0xf7, 0xf4, 0x1e, 0xfc, 0x37, 0x01, 0xdd, 0x05, 0x06, 0x00, 0xe1, 0xff, + 0x96, 0x07, 0x43, 0x12, 0x83, 0x21, 0x77, 0x34, 0x3e, 0x45, 0x1d, 0x4f, + 0x2e, 0x55, 0x8f, 0x57, 0x7f, 0x57, 0x5b, 0x53, 0x7c, 0x49, 0x02, 0x39, + 0x01, 0x2a, 0xa4, 0x1f, 0xa9, 0x18, 0x10, 0x14, 0x82, 0x0b, 0x67, 0x04, + 0xd4, 0xfc, 0x09, 0xf3, 0x95, 0xeb, 0x63, 0xe7, 0x22, 0xea, 0x8d, 0xef, + 0xcf, 0xf3, 0xf5, 0xfb, 0x3b, 0x01, 0xc2, 0xff, 0xd9, 0xfb, 0x07, 0xf4, + 0xc0, 0xed, 0xe1, 0xec, 0xab, 0xf9, 0xd7, 0x12, 0xf9, 0x30, 0x10, 0x4a, + 0xa5, 0x4f, 0x86, 0x46, 0x0a, 0x39, 0x1e, 0x35, 0xda, 0x2e, 0x60, 0x22, + 0xcc, 0x18, 0x9d, 0x10, 0x29, 0x16, 0xe9, 0x21, 0xc9, 0x29, 0x79, 0x24, + 0xa3, 0x14, 0x66, 0x04, 0xa2, 0xf7, 0x50, 0xf2, 0xc1, 0xec, 0x17, 0xf0, + 0xc1, 0xf8, 0xdc, 0x01, 0xea, 0x0e, 0x2c, 0x1d, 0x70, 0x30, 0x5d, 0x42, + 0x9d, 0x4f, 0xc3, 0x52, 0x76, 0x49, 0x88, 0x3f, 0x39, 0x3d, 0xcf, 0x3c, + 0xed, 0x3c, 0xe3, 0x40, 0x1e, 0x48, 0xe0, 0x51, 0x14, 0x56, 0xf7, 0x54, + 0x8b, 0x4c, 0x24, 0x3e, 0x31, 0x2e, 0x64, 0x21, 0x2a, 0x19, 0xc9, 0x0c, + 0xc8, 0x03, 0xeb, 0xfe, 0x01, 0xfa, 0xae, 0xf5, 0x37, 0xf1, 0x01, 0xf2, + 0x58, 0xf7, 0x55, 0xf9, 0xa7, 0xf8, 0x25, 0xfd, 0x85, 0x05, 0x46, 0x14, + 0xa0, 0x25, 0x04, 0x31, 0x61, 0x35, 0x6a, 0x39, 0x6b, 0x3f, 0xdc, 0x42, + 0x27, 0x49, 0xa5, 0x4c, 0x6e, 0x51, 0x5d, 0x5e, 0x46, 0x68, 0x27, 0x6c, + 0x0b, 0x6d, 0x4d, 0x69, 0x71, 0x62, 0x12, 0x5c, 0xb3, 0x4f, 0x3e, 0x47, + 0xd1, 0x42, 0xfc, 0x3b, 0x45, 0x38, 0x35, 0x30, 0x43, 0x28, 0xde, 0x23, + 0xfe, 0x1c, 0xda, 0x13, 0xb2, 0x0e, 0x13, 0x09, 0x37, 0x03, 0x4b, 0x04, + 0x20, 0x04, 0x78, 0x02, 0xb1, 0x03, 0xa5, 0x0c, 0xd0, 0x16, 0x78, 0x1f, + 0xfc, 0x2f, 0xef, 0x43, 0x2b, 0x54, 0x81, 0x5c, 0x6e, 0x60, 0x82, 0x63, + 0x12, 0x67, 0x9f, 0x67, 0x1a, 0x67, 0xdf, 0x5f, 0x4f, 0x4e, 0x7c, 0x47, + 0xae, 0x43, 0x1b, 0x3d, 0xce, 0x39, 0x81, 0x31, 0x60, 0x24, 0xb9, 0x14, + 0x8d, 0x05, 0x20, 0xee, 0xaa, 0xd1, 0x5e, 0xc5, 0x72, 0xc8, 0x18, 0xd4, + 0xf7, 0xe1, 0x22, 0xee, 0x3b, 0xfd, 0xe9, 0x05, 0xda, 0x07, 0xeb, 0x0a, + 0xf8, 0x0c, 0x41, 0x11, 0x6e, 0x1a, 0xcd, 0x28, 0x90, 0x37, 0x88, 0x44, + 0x92, 0x4f, 0x20, 0x54, 0xcd, 0x54, 0xdb, 0x52, 0x9c, 0x4d, 0xb8, 0x49, + 0x8e, 0x47, 0x07, 0x44, 0xcf, 0x3c, 0x32, 0x2e, 0x06, 0x1f, 0x8f, 0x13, + 0xdf, 0x0a, 0x96, 0x04, 0xd8, 0xfa, 0x4e, 0xef, 0x14, 0xe7, 0xfa, 0xdf, + 0x2e, 0xd9, 0xeb, 0xd9, 0x40, 0xde, 0x54, 0xe4, 0x17, 0xea, 0x80, 0xec, + 0x80, 0xf1, 0x20, 0xf7, 0x52, 0xfe, 0xfe, 0x06, 0x10, 0x10, 0x82, 0x16, + 0xac, 0x1c, 0x58, 0x22, 0x40, 0x25, 0xbf, 0x26, 0xd9, 0x21, 0x82, 0x1f, + 0x41, 0x1f, 0xb7, 0x1c, 0x0e, 0x1e, 0xe9, 0x24, 0x22, 0x2b, 0xb1, 0x28, + 0x76, 0x21, 0xe1, 0x1b, 0x16, 0x19, 0x89, 0x1a, 0xe0, 0x21, 0x5e, 0x2e, + 0x77, 0x3e, 0x07, 0x4a, 0x6f, 0x4f, 0xb8, 0x4d, 0x52, 0x41, 0x09, 0x2c, + 0xd6, 0x15, 0x02, 0x04, 0xce, 0xf1, 0x4f, 0xe5, 0x8f, 0xe2, 0x22, 0xea, + 0xf5, 0xf5, 0x92, 0xff, 0x7b, 0x00, 0xe8, 0xf3, 0xdc, 0xe0, 0x4b, 0xd1, + 0x48, 0xcc, 0x1e, 0xc9, 0x39, 0xc8, 0x74, 0xca, 0xc2, 0xd5, 0x2f, 0xe9, + 0x55, 0xf9, 0x4a, 0x03, 0x9b, 0xfe, 0xf9, 0xf7, 0x3b, 0xf7, 0x6d, 0xfc, + 0xe5, 0x02, 0x58, 0x04, 0x59, 0x06, 0x30, 0x07, 0xd4, 0x09, 0xbc, 0x0e, + 0x69, 0x14, 0x63, 0x15, 0xa6, 0x12, 0x19, 0x0f, 0x75, 0x0b, 0xe1, 0x07, + 0x5c, 0x01, 0x8c, 0x01, 0x25, 0x01, 0x75, 0xfb, 0x66, 0xfa, 0xce, 0xfb, + 0xa0, 0xf7, 0xb0, 0xeb, 0xa4, 0xdd, 0xb5, 0xd3, 0xd5, 0xcb, 0x95, 0xc2, + 0xab, 0xc5, 0x20, 0xd4, 0xe2, 0xe2, 0x9c, 0xf8, 0xab, 0x0d, 0x3a, 0x15, + 0xe5, 0x13, 0x45, 0x09, 0x9e, 0xf7, 0x6f, 0xec, 0xad, 0xe3, 0x43, 0xde, + 0x50, 0xdf, 0x41, 0xe0, 0x29, 0xe2, 0x26, 0xe2, 0x4e, 0xe0, 0x8f, 0xde, + 0x2e, 0xdc, 0x23, 0xda, 0x4a, 0xd7, 0x51, 0xd0, 0x00, 0xcb, 0xdb, 0xc8, + 0x97, 0xca, 0x54, 0xd2, 0x5a, 0xdb, 0x31, 0xe7, 0x65, 0xee, 0x44, 0xf5, + 0xa9, 0xf9, 0xeb, 0xf5, 0x87, 0xf5, 0x48, 0xfa, 0xbf, 0xfb, 0xe3, 0xf2, + 0xde, 0xeb, 0x14, 0xe4, 0x57, 0xdd, 0xdc, 0xda, 0x92, 0xd8, 0xa8, 0xd8, + 0xc8, 0xd7, 0xbd, 0xda, 0x0e, 0xdd, 0x11, 0xdf, 0x52, 0xdf, 0xf3, 0xdf, + 0xb2, 0xdc, 0x7b, 0xd4, 0xaf, 0xd1, 0x0d, 0xce, 0xde, 0xcf, 0x9a, 0xd9, + 0x7a, 0xe8, 0xe5, 0xf2, 0x88, 0xf3, 0x92, 0xf0, 0xb3, 0xed, 0x36, 0xed, + 0x25, 0xe4, 0xa9, 0xd6, 0xf1, 0xd1, 0x29, 0xd9, 0xa2, 0xe5, 0xdc, 0xef, + 0xfe, 0xf4, 0x04, 0xf1, 0x41, 0xec, 0xa9, 0xee, 0x0f, 0xee, 0x17, 0xea, + 0x65, 0xed, 0xef, 0xf9, 0xcc, 0x0b, 0x2f, 0x13, 0x9d, 0x0e, 0x8d, 0x02, + 0x30, 0xed, 0x76, 0xd6, 0xe2, 0xc0, 0x48, 0xaf, 0xd0, 0xa7, 0x98, 0xad, + 0xca, 0xc1, 0x39, 0xd9, 0xc0, 0xe9, 0xd6, 0xf7, 0x39, 0x01, 0xbd, 0x03, + 0x3f, 0xff, 0x73, 0xf0, 0x93, 0xda, 0xa0, 0xc7, 0x49, 0xbe, 0x9f, 0xb9, + 0x6c, 0xba, 0x66, 0xbe, 0xd0, 0xc6, 0x38, 0xd9, 0xb8, 0xed, 0x7e, 0xfe, + 0xd2, 0x03, 0xd3, 0xfe, 0x6e, 0xfb, 0xc2, 0xfd, 0x1f, 0x04, 0x61, 0x0a, + 0xf5, 0x11, 0x34, 0x19, 0x29, 0x16, 0xa3, 0x0b, 0xa3, 0xfa, 0x9e, 0xde, + 0x59, 0xbe, 0x19, 0xa2, 0x1a, 0x93, 0x18, 0x90, 0xb8, 0x91, 0xbc, 0x94, + 0x9b, 0x98, 0x2e, 0x98, 0xa7, 0x92, 0x0a, 0x93, 0xfc, 0x95, 0x95, 0x9d, + 0x5b, 0xa7, 0x96, 0xaf, 0x67, 0xbf, 0x08, 0xd2, 0x60, 0xe8, 0xee, 0xfc, + 0xc0, 0x08, 0x2a, 0x0f, 0x10, 0x13, 0x05, 0x16, 0xc0, 0x12, 0x80, 0x11, + 0xb4, 0x13, 0x6c, 0x11, 0xdc, 0x0f, 0xc7, 0x0b, 0xb5, 0xff, 0x2b, 0xf5, + 0xa3, 0xe9, 0xb2, 0xdb, 0xcb, 0xd2, 0xd0, 0xc4, 0xce, 0xb8, 0x4e, 0xb2, + 0xc7, 0xa9, 0x69, 0xa8, 0x31, 0xa6, 0xfa, 0xa2, 0x9b, 0xa2, 0x25, 0xa4, + 0x4f, 0xad, 0xfa, 0xb1, 0x17, 0xb5, 0x4f, 0xba, 0x6d, 0xbd, 0xf0, 0xc4, + 0xc8, 0xcd, 0x4e, 0xda, 0x63, 0xe8, 0x8b, 0xf3, 0xb1, 0xf9, 0x70, 0xf8, + 0x3e, 0xf8, 0x65, 0xfc, 0x1f, 0xfe, 0x37, 0x00, 0x37, 0x06, 0x2e, 0x08, + 0x6f, 0x0c, 0x83, 0x0e, 0x90, 0x03, 0x25, 0xee, 0xb9, 0xd3, 0x77, 0xc0, + 0x61, 0xb3, 0xb2, 0xab, 0xad, 0xad, 0x5f, 0xb9, 0x34, 0xc0, 0x3d, 0xbd, + 0x7f, 0xbc, 0x52, 0xbb, 0xd4, 0xb6, 0xa0, 0xb4, 0xcf, 0xb7, 0xe2, 0xbc, + 0x40, 0xc5, 0x76, 0xd0, 0xa5, 0xdb, 0x49, 0xe4, 0x9f, 0xe9, 0x43, 0xed, + 0x1e, 0xf1, 0xbc, 0x00, 0xb7, 0x1b, 0x19, 0x3d, 0xec, 0x5c, 0x19, 0x6b, + 0x0d, 0x6c, 0xf0, 0x69, 0x3f, 0x65, 0x5f, 0x61, 0xdc, 0x5d, 0xcd, 0x56, + 0x5c, 0x4b, 0x1e, 0x42, 0x39, 0x3e, 0x04, 0x38, 0xa3, 0x2d, 0x9b, 0x1b, + 0xe7, 0x03, 0x18, 0xed, 0x72, 0xd7, 0xf7, 0xc7, 0xa9, 0xc4, 0xa1, 0xc8, + 0xfa, 0xcc, 0x69, 0xd5, 0x29, 0xe0, 0x4c, 0xeb, 0x33, 0xf8, 0x58, 0x02, + 0x1b, 0x00, 0xa4, 0xfa, 0xfb, 0xf8, 0x2a, 0xf5, 0x43, 0xf7, 0x34, 0xfb, + 0x06, 0x04, 0xbf, 0x15, 0x9f, 0x27, 0xc5, 0x38, 0xd5, 0x47, 0xf9, 0x54, + 0x9a, 0x5a, 0x9d, 0x55, 0xd8, 0x46, 0x34, 0x36, 0x0f, 0x2d, 0x73, 0x27, + 0xce, 0x29, 0x73, 0x33, 0xf0, 0x3a, 0x86, 0x3f, 0x04, 0x41, 0xa3, 0x40, + 0xc0, 0x38, 0x3d, 0x28, 0x0f, 0x12, 0x83, 0xff, 0xe4, 0xf7, 0x60, 0xf1, + 0xfd, 0xe6, 0x84, 0xd2, 0x1d, 0xc5, 0xd7, 0xc4, 0x48, 0xc6, 0x4c, 0xc9, + 0xbe, 0xc4, 0x18, 0xc3, 0x33, 0xc8, 0x69, 0xd3, 0xf3, 0xdf, 0x41, 0xe7, + 0x05, 0xed, 0x6b, 0xf2, 0xd9, 0xfb, 0xd5, 0xfd, 0x44, 0xfd, 0x31, 0xf9, + 0x79, 0xf0, 0x73, 0xef, 0x78, 0xf2, 0xf0, 0xfe, 0x7f, 0x10, 0x0f, 0x24, + 0xde, 0x36, 0x64, 0x41, 0x15, 0x46, 0xea, 0x46, 0xa9, 0x47, 0x58, 0x45, + 0x86, 0x43, 0x3b, 0x45, 0x0a, 0x4c, 0x79, 0x57, 0xde, 0x57, 0xed, 0x55, + 0xbc, 0x51, 0xa1, 0x42, 0x5c, 0x32, 0x48, 0x21, 0x30, 0x17, 0x9f, 0x0e, + 0xc2, 0x04, 0xd9, 0x01, 0x68, 0x06, 0x64, 0x0d, 0xbb, 0x0d, 0x6a, 0x10, + 0x44, 0x15, 0xe2, 0x19, 0x32, 0x17, 0x14, 0x0f, 0x30, 0x08, 0xbd, 0xfe, + 0x7e, 0xf5, 0xea, 0xe2, 0xc0, 0xd2, 0xd8, 0xc9, 0x4a, 0xca, 0xb0, 0xd6, + 0x02, 0xdf, 0xfe, 0xe4, 0x9e, 0xed, 0x9f, 0xfd, 0x17, 0x0a, 0xcc, 0x0b, + 0x3f, 0x03, 0xdb, 0xf7, 0xd3, 0xee, 0x8c, 0xe7, 0x6f, 0xef, 0x63, 0xff, + 0x98, 0x13, 0x04, 0x2f, 0xc8, 0x4a, 0x44, 0x5d, 0xc7, 0x66, 0xbc, 0x6d, + 0x1e, 0x6c, 0x84, 0x66, 0x55, 0x5f, 0x83, 0x56, 0xcc, 0x4e, 0xda, 0x41, + 0x6d, 0x37, 0x89, 0x34, 0x86, 0x31, 0xb7, 0x35, 0x4a, 0x3f, 0x48, 0x46, + 0x64, 0x4b, 0xe0, 0x4e, 0xb9, 0x4e, 0xc7, 0x4c, 0xfb, 0x4a, 0xc2, 0x42, + 0xa5, 0x3e, 0x67, 0x3c, 0x3d, 0x37, 0xc9, 0x34, 0xd4, 0x2a, 0xe2, 0x21, + 0xe0, 0x24, 0x96, 0x2c, 0xa1, 0x34, 0xbc, 0x37, 0xeb, 0x35, 0x03, 0x39, + 0x80, 0x3b, 0xb7, 0x3c, 0xe8, 0x3a, 0xd8, 0x2e, 0x5e, 0x22, 0x28, 0x19, + 0x5e, 0x11, 0x10, 0x01, 0x95, 0xe8, 0x31, 0xd3, 0x11, 0xc8, 0x8c, 0xc9, + 0x9a, 0xd1, 0x9f, 0xdf, 0x19, 0xee, 0x0f, 0xfb, 0x0a, 0x0b, 0xd2, 0x19, + 0x62, 0x22, 0x8a, 0x28, 0x1e, 0x2c, 0x0f, 0x31, 0x40, 0x40, 0x04, 0x54, + 0x3e, 0x62, 0x5a, 0x69, 0xda, 0x6c, 0xd0, 0x6a, 0xa5, 0x66, 0x6e, 0x61, + 0x3a, 0x5e, 0xed, 0x5b, 0x98, 0x55, 0xd4, 0x51, 0x72, 0x4d, 0x41, 0x45, + 0x47, 0x34, 0x05, 0x1c, 0xd6, 0x03, 0x86, 0xf1, 0x28, 0xeb, 0xe3, 0xeb, + 0x05, 0xed, 0x36, 0xef, 0x14, 0xf7, 0xfa, 0xfd, 0xc2, 0xff, 0xd2, 0xfc, + 0x5c, 0xf8, 0xb9, 0xf3, 0xcd, 0xee, 0x1d, 0xef, 0xbd, 0xf4, 0x0f, 0xff, + 0xeb, 0x09, 0xb2, 0x19, 0x4c, 0x2a, 0x9f, 0x32, 0x83, 0x35, 0x5a, 0x33, + 0x33, 0x34, 0x6a, 0x3d, 0xde, 0x46, 0x33, 0x4a, 0xe5, 0x4d, 0xc7, 0x50, + 0xc2, 0x54, 0x50, 0x55, 0x1e, 0x4a, 0x45, 0x3c, 0x5e, 0x2d, 0x41, 0x24, + 0xb4, 0x23, 0xcc, 0x28, 0x46, 0x30, 0x36, 0x3b, 0x1e, 0x46, 0x26, 0x47, + 0xe1, 0x41, 0x6e, 0x36, 0x94, 0x29, 0x61, 0x1e, 0x4c, 0x18, 0xb0, 0x16, + 0x74, 0x16, 0x46, 0x1a, 0xd8, 0x1a, 0xed, 0x19, 0x39, 0x19, 0xd1, 0x16, + 0xc1, 0x12, 0xa6, 0x0d, 0x94, 0x0d, 0x03, 0x0d, 0xf6, 0x08, 0xfa, 0x09, + 0xbf, 0x0c, 0x09, 0x0f, 0x42, 0x0b, 0x88, 0x06, 0xc9, 0x0a, 0xd2, 0x0a, + 0x1e, 0x0c, 0xf1, 0x0e, 0xef, 0x0c, 0x99, 0x08, 0x82, 0x02, 0xad, 0xfb, + 0xd4, 0xf7, 0xc9, 0xff, 0x49, 0x0a, 0xce, 0x13, 0x5f, 0x17, 0x63, 0x19, + 0x4c, 0x1f, 0x1b, 0x21, 0x21, 0x21, 0xc3, 0x19, 0x57, 0x11, 0x0b, 0x0e, + 0xe7, 0x12, 0xe2, 0x21, 0x36, 0x34, 0x8e, 0x3c, 0x6b, 0x31, 0x80, 0x21, + 0xd5, 0x0e, 0x91, 0xf3, 0x61, 0xd6, 0x6d, 0xc3, 0xa9, 0xc0, 0xd8, 0xcd, + 0xdb, 0xe3, 0xaf, 0xfb, 0x5b, 0x1a, 0xf2, 0x3b, 0x8c, 0x59, 0x90, 0x69, + 0x61, 0x6c, 0x6b, 0x69, 0x7b, 0x5a, 0xde, 0x44, 0x9c, 0x34, 0xbc, 0x27, + 0x33, 0x19, 0xeb, 0x0b, 0x9e, 0x01, 0x89, 0xfd, 0x0b, 0xfa, 0x9a, 0xf2, + 0x38, 0xea, 0x33, 0xde, 0xb5, 0xd5, 0xdb, 0xcf, 0x47, 0xca, 0x3f, 0xc9, + 0xfd, 0xcb, 0xa7, 0xd2, 0x1e, 0xd9, 0xf2, 0xe0, 0xab, 0xef, 0x2d, 0x02, + 0xa0, 0x17, 0x0a, 0x2f, 0x1d, 0x3c, 0x79, 0x3b, 0x1f, 0x2e, 0x97, 0x19, + 0x06, 0x07, 0x7d, 0xf9, 0xdb, 0xf8, 0xe1, 0xf6, 0xba, 0xf5, 0x67, 0x04, + 0x68, 0x13, 0xae, 0x1e, 0x22, 0x1f, 0xe7, 0x18, 0x39, 0x16, 0x26, 0x0d, + 0x27, 0x0c, 0x1b, 0x11, 0x9c, 0x15, 0xd5, 0x20, 0x8c, 0x21, 0x5c, 0x1e, + 0x3b, 0x13, 0xc9, 0xfd, 0x11, 0xf4, 0x00, 0xed, 0xfc, 0xe7, 0xca, 0xe9, + 0x95, 0xec, 0x76, 0xec, 0xc7, 0xe8, 0xe1, 0xe0, 0x67, 0xd8, 0xbe, 0xce, + 0x73, 0xc3, 0x00, 0xc4, 0x6d, 0xcc, 0x0f, 0xdc, 0xd9, 0xee, 0xf9, 0x02, + 0x3c, 0x16, 0x33, 0x22, 0x61, 0x2a, 0x4f, 0x27, 0x45, 0x23, 0xd7, 0x1b, + 0xaa, 0x16, 0x0d, 0x15, 0x2c, 0x11, 0x3e, 0x15, 0xab, 0x0f, 0x2c, 0x0b, + 0x48, 0x02, 0x15, 0xef, 0x68, 0xe0, 0x8b, 0xd6, 0xcd, 0xd9, 0x93, 0xd8, + 0x0e, 0xd6, 0x43, 0xd6, 0xf2, 0xd3, 0x62, 0xd2, 0x7c, 0xcf, 0xb4, 0xd4, + 0xbc, 0xe0, 0x2b, 0xf6, 0x5d, 0x0d, 0x02, 0x23, 0x43, 0x35, 0x10, 0x38, + 0x98, 0x32, 0x27, 0x28, 0x73, 0x1b, 0x2b, 0x0f, 0x79, 0x0a, 0x9d, 0x0e, + 0x3e, 0x14, 0x50, 0x1f, 0xe4, 0x27, 0x60, 0x22, 0xdf, 0x13, 0x50, 0x04, + 0x0d, 0xf2, 0xaa, 0xde, 0xba, 0xcd, 0x91, 0xc4, 0xc4, 0xc6, 0x79, 0xd0, + 0x75, 0xe6, 0x6e, 0xfc, 0xcf, 0x05, 0xed, 0x07, 0x95, 0x00, 0x0e, 0xf5, + 0x85, 0xe6, 0x0e, 0xd1, 0x61, 0xbb, 0xd3, 0xad, 0x2c, 0xaa, 0x39, 0xa9, + 0x3e, 0xab, 0xd6, 0xb1, 0x54, 0xbd, 0xa1, 0xc5, 0xb9, 0xc7, 0x54, 0xcf, + 0x3d, 0xd9, 0x24, 0xe6, 0xe7, 0xf1, 0x8c, 0xfb, 0xdc, 0x02, 0x4a, 0xfb, + 0xbe, 0xf0, 0xe7, 0xe9, 0x16, 0xe6, 0xe2, 0xe8, 0xb2, 0xec, 0xc8, 0xf1, + 0xff, 0xfe, 0xec, 0x0c, 0x7c, 0x12, 0xb6, 0x10, 0xf5, 0x08, 0x02, 0x02, + 0xe9, 0xf3, 0x3a, 0xe2, 0x9f, 0xd5, 0xd5, 0xc9, 0x0b, 0xc7, 0x63, 0xc8, + 0x9e, 0xc7, 0xcc, 0xc7, 0x00, 0xcb, 0xf2, 0xd4, 0xdf, 0xe5, 0xf7, 0xf3, + 0x2d, 0xf8, 0x45, 0xf8, 0xbb, 0xf6, 0x79, 0xec, 0xbe, 0xda, 0xc3, 0xc8, + 0xd1, 0xb4, 0x04, 0xac, 0x06, 0xab, 0xc8, 0xae, 0x7f, 0xb9, 0x1e, 0xc0, + 0xf6, 0xcb, 0x1d, 0xd4, 0x80, 0xd6, 0xca, 0xd2, 0xcb, 0xc8, 0x70, 0xc6, + 0x5c, 0xc6, 0x81, 0xce, 0x89, 0xd8, 0x7c, 0xe3, 0x54, 0xec, 0x30, 0xef, + 0x52, 0xf9, 0x5f, 0xfc, 0xd8, 0x01, 0xe7, 0x05, 0x1a, 0xff, 0x4b, 0xfe, + 0xbf, 0xf5, 0x2d, 0xe9, 0xb1, 0xd7, 0x75, 0xbb, 0x57, 0xa1, 0x8b, 0x92, + 0x5e, 0x90, 0x83, 0x90, 0xd7, 0x97, 0xe6, 0xa4, 0x5c, 0xbc, 0xd1, 0xd9, + 0x65, 0xef, 0x93, 0x00, 0x22, 0x06, 0x86, 0x03, 0x79, 0xf8, 0x6d, 0xeb, + 0xb5, 0xe1, 0xc2, 0xda, 0x04, 0xdb, 0xac, 0xdb, 0xde, 0xe0, 0x00, 0xe3, + 0x12, 0xe5, 0x39, 0xe6, 0x03, 0xdf, 0x6a, 0xda, 0x3e, 0xd5, 0x1e, 0xd3, + 0x34, 0xd8, 0x2a, 0xe6, 0xc7, 0xf0, 0x46, 0xf0, 0x7e, 0xec, 0xc6, 0xe9, + 0x1c, 0xf2, 0x4c, 0x02, 0xf5, 0x11, 0xfc, 0x1a, 0xdd, 0x26, 0x1d, 0x32, + 0x38, 0x33, 0x95, 0x2d, 0xb5, 0x1d, 0x90, 0x07, 0x1e, 0xee, 0x66, 0xdd, + 0x2e, 0xd3, 0x6f, 0xca, 0xb5, 0xbf, 0x64, 0xb5, 0x37, 0xaf, 0x5d, 0xa3, + 0x37, 0x98, 0x4d, 0x8e, 0xc1, 0x8b, 0x6c, 0x8b, 0x88, 0x8f, 0x4e, 0x96, + 0x96, 0x93, 0x49, 0x98, 0xf3, 0xa6, 0x3a, 0xbc, 0xb6, 0xd3, 0x8a, 0xe4, + 0xd1, 0xed, 0x85, 0xfc, 0x09, 0x08, 0x03, 0x1b, 0x02, 0x31, 0xb8, 0x30, + 0x56, 0x32, 0x20, 0x31, 0x59, 0x31, 0x8c, 0x2e, 0x0c, 0x22, 0x40, 0x15, + 0xfe, 0x0b, 0x5b, 0x0f, 0x4a, 0x13, 0x37, 0x19, 0xf6, 0x16, 0x2e, 0x15, + 0x26, 0x15, 0x78, 0x09, 0x52, 0xfc, 0x51, 0xee, 0xbe, 0xe2, 0x93, 0xd9, + 0x6e, 0xd6, 0x42, 0xd6, 0xcc, 0xd7, 0x25, 0xd9, 0x7d, 0xdc, 0x4d, 0xe1, + 0x51, 0xe0, 0x27, 0xde, 0xb8, 0xdc, 0xaf, 0xe0, 0x27, 0xe6, 0xb5, 0xec, + 0x1f, 0xf1, 0x75, 0xf5, 0x7e, 0xfb, 0x34, 0xff, 0xac, 0x06, 0xb5, 0x08, + 0x21, 0x0a, 0xc7, 0x0d, 0xef, 0x0d, 0x8d, 0x09, 0xd1, 0xfe, 0xa4, 0xf5, + 0xc7, 0xe8, 0xfd, 0xde, 0x4e, 0xd9, 0x2e, 0xd1, 0x99, 0xd4, 0xdd, 0xdb, + 0xad, 0xe5, 0xb5, 0xf3, 0x8b, 0xfe, 0x89, 0x08, 0x64, 0x0e, 0xac, 0x0f, + 0xf2, 0x10, 0x00, 0x13, 0x30, 0x12, 0x45, 0x17, 0x1c, 0x1d, 0x2e, 0x1b, + 0x31, 0x18, 0xa0, 0x13, 0x46, 0x11, 0x03, 0x0b, 0x2d, 0x01, 0x3e, 0xf9, + 0x0a, 0xf6, 0x48, 0xf4, 0xb8, 0xf1, 0x55, 0xf3, 0x75, 0xf2, 0xa2, 0xf2, + 0x00, 0xf7, 0x7d, 0x01, 0xc1, 0x0b, 0xec, 0x12, 0x3a, 0x1d, 0x06, 0x27, + 0xf7, 0x2a, 0x27, 0x1f, 0x0f, 0x0a, 0x1d, 0xf4, 0x3b, 0xe1, 0xa5, 0xd3, + 0x53, 0xca, 0xb5, 0xca, 0xd0, 0xd2, 0xfe, 0xdf, 0x5f, 0xee, 0xc3, 0xf3, + 0x94, 0xed, 0x01, 0xe2, 0x86, 0xd2, 0xdd, 0xc2, 0xb5, 0xb8, 0x4f, 0xb3, + 0x89, 0xb4, 0xb1, 0xb8, 0x7e, 0xbf, 0xf8, 0xcc, 0x47, 0xd9, 0xd8, 0xe3, + 0x3b, 0xec, 0xbc, 0xea, 0x77, 0xea, 0x50, 0xf2, 0xfa, 0xf7, 0x80, 0xfc, + 0x85, 0x03, 0x20, 0x07, 0xdf, 0x0a, 0xef, 0x13, 0xa7, 0x1d, 0xbb, 0x25, + 0x9f, 0x28, 0x19, 0x29, 0x8c, 0x2d, 0xe8, 0x31, 0x58, 0x30, 0x67, 0x2e, + 0x6c, 0x2e, 0x86, 0x2a, 0x55, 0x29, 0x36, 0x24, 0x01, 0x16, 0xaa, 0x0a, + 0x53, 0xff, 0xc8, 0xf6, 0x1a, 0xef, 0x09, 0xe4, 0x8b, 0xe2, 0x46, 0xe9, + 0xea, 0xf0, 0xa9, 0xf7, 0x87, 0xfb, 0xa1, 0xfd, 0x0a, 0xff, 0x4d, 0xfd, + 0x77, 0xf4, 0x6c, 0xe9, 0x11, 0xe0, 0xb8, 0xdc, 0x6c, 0xe1, 0x94, 0xe4, + 0xce, 0xe9, 0x5d, 0xf3, 0xa8, 0xfc, 0x63, 0x09, 0xb6, 0x13, 0xb4, 0x16, + 0xb7, 0x18, 0x0f, 0x1e, 0xf0, 0x22, 0xf1, 0x25, 0x82, 0x29, 0x06, 0x2d, + 0x6e, 0x38, 0xbe, 0x44, 0xf7, 0x4a, 0xa8, 0x51, 0x27, 0x50, 0xf3, 0x4a, + 0x55, 0x3e, 0xcb, 0x28, 0xbd, 0x1a, 0xdb, 0x10, 0xa8, 0x10, 0xa6, 0x19, + 0xf2, 0x24, 0xc2, 0x32, 0x76, 0x41, 0x95, 0x51, 0x97, 0x5b, 0xc9, 0x61, + 0x8f, 0x63, 0x0b, 0x62, 0xbf, 0x5f, 0x12, 0x57, 0xe3, 0x4c, 0x04, 0x41, + 0x41, 0x34, 0x1f, 0x29, 0xc5, 0x23, 0xf4, 0x22, 0x94, 0x25, 0x6a, 0x28, + 0x6f, 0x23, 0x90, 0x1e, 0x86, 0x15, 0xf3, 0x08, 0xb2, 0xfa, 0x78, 0xf1, + 0x4a, 0xf7, 0xdb, 0xff, 0x04, 0x0d, 0x43, 0x1d, 0x9a, 0x2c, 0x42, 0x3e, + 0x8c, 0x4f, 0xaf, 0x54, 0xb7, 0x4a, 0x1b, 0x3d, 0x71, 0x2f, 0x6a, 0x2b, + 0xf3, 0x2d, 0x4d, 0x33, 0xae, 0x3e, 0xb1, 0x45, 0xd6, 0x4a, 0xcf, 0x4d, + 0xe1, 0x44, 0xc5, 0x36, 0xe4, 0x2b, 0x40, 0x23, 0x0b, 0x1b, 0xcc, 0x13, + 0x33, 0x13, 0x6e, 0x17, 0xd9, 0x1a, 0xbe, 0x1d, 0x51, 0x1a, 0xcd, 0x10, + 0x09, 0x0e, 0x03, 0x0f, 0xef, 0x0d, 0x24, 0x0c, 0x97, 0x07, 0x23, 0x09, + 0x93, 0x0c, 0xdc, 0x0f, 0xd8, 0x11, 0x6f, 0x10, 0x35, 0x16, 0x75, 0x1b, + 0x61, 0x22, 0x68, 0x27, 0x55, 0x23, 0x4f, 0x20, 0x22, 0x1f, 0xa8, 0x1f, + 0x3a, 0x22, 0x4a, 0x25, 0x35, 0x1f, 0xfd, 0x16, 0xc0, 0x0b, 0xb7, 0xf7, + 0x11, 0xf2, 0xc4, 0xf1, 0x35, 0xf3, 0xa2, 0xfc, 0x6e, 0x05, 0x18, 0x13, + 0xb0, 0x1f, 0xd5, 0x2e, 0xee, 0x3c, 0x95, 0x43, 0x4d, 0x40, 0x31, 0x2c, + 0x0c, 0x15, 0x51, 0xfe, 0x4d, 0xf3, 0x24, 0xf3, 0x11, 0xf6, 0xbd, 0x00, + 0xbf, 0x0b, 0x45, 0x19, 0x0d, 0x24, 0x2e, 0x27, 0x29, 0x1f, 0x53, 0x12, + 0x8a, 0x03, 0xd2, 0xf1, 0x8a, 0xe6, 0x94, 0xde, 0x75, 0xe3, 0x26, 0xee, + 0x8f, 0xf4, 0x6b, 0xfc, 0xe3, 0x06, 0xd3, 0x0f, 0x9b, 0x13, 0xce, 0x18, + 0xa9, 0x1b, 0x4f, 0x1e, 0xc9, 0x22, 0xa7, 0x2a, 0xb7, 0x34, 0xd1, 0x36, + 0x3e, 0x35, 0x43, 0x35, 0x5d, 0x36, 0x3e, 0x35, 0xc1, 0x33, 0x87, 0x30, + 0x61, 0x30, 0x68, 0x34, 0xa6, 0x33, 0x9b, 0x35, 0xe7, 0x34, 0x6c, 0x2c, + 0x14, 0x26, 0x71, 0x1f, 0xcc, 0x13, 0x19, 0x0a, 0xb3, 0x05, 0x26, 0x09, + 0x83, 0x12, 0x73, 0x16, 0x56, 0x19, 0xba, 0x1c, 0x87, 0x1c, 0x7c, 0x1e, + 0xd0, 0x21, 0x40, 0x23, 0x01, 0x22, 0x71, 0x1f, 0xfc, 0x20, 0x51, 0x20, + 0x40, 0x17, 0x30, 0x0d, 0x5a, 0x06, 0xa4, 0x07, 0xb2, 0x16, 0x78, 0x29, + 0xc7, 0x34, 0xb8, 0x37, 0x50, 0x37, 0xd2, 0x35, 0x7a, 0x2d, 0x2c, 0x23, + 0x31, 0x19, 0x7c, 0x18, 0x7b, 0x24, 0x32, 0x33, 0x0b, 0x45, 0x93, 0x4e, + 0x93, 0x4e, 0xab, 0x4a, 0x3e, 0x47, 0x29, 0x42, 0xcb, 0x35, 0x07, 0x2c, + 0x08, 0x28, 0x6c, 0x29, 0xcf, 0x26, 0x8e, 0x28, 0x53, 0x31, 0x92, 0x32, + 0x78, 0x30, 0xe5, 0x27, 0xcc, 0x1f, 0x9a, 0x1c, 0x26, 0x11, 0xdf, 0x01, + 0xf0, 0xf6, 0x46, 0xed, 0x81, 0xe8, 0xa7, 0xe4, 0xb4, 0xdf, 0xc3, 0xe1, + 0x97, 0xe3, 0x8a, 0xe0, 0x21, 0xdd, 0xbd, 0xde, 0x45, 0xe4, 0xa4, 0xe9, + 0x8f, 0xed, 0xac, 0xf2, 0x69, 0xf8, 0x91, 0xfa, 0xb3, 0xf7, 0xc7, 0xef, + 0x5c, 0xe8, 0x31, 0xe3, 0xd9, 0xdf, 0xb5, 0xdb, 0x25, 0xd5, 0x83, 0xd5, + 0xee, 0xdd, 0x10, 0xe1, 0xa8, 0xdb, 0x8e, 0xda, 0x92, 0xe3, 0xe5, 0xef, + 0x2c, 0xfd, 0xcf, 0x0c, 0xfe, 0x1a, 0x3d, 0x2a, 0xf9, 0x38, 0xe2, 0x45, + 0x72, 0x50, 0x7d, 0x53, 0x4e, 0x57, 0x84, 0x5b, 0xfa, 0x5b, 0xa4, 0x5c, + 0xa7, 0x56, 0x23, 0x4a, 0xb6, 0x42, 0x3b, 0x3c, 0x40, 0x32, 0x59, 0x28, + 0x8b, 0x1d, 0x10, 0x11, 0xca, 0x00, 0xe4, 0xf0, 0xe2, 0xe6, 0x0c, 0xe6, + 0x91, 0xea, 0xcf, 0xee, 0x94, 0xf3, 0x86, 0xf8, 0xf0, 0xfc, 0x31, 0x00, + 0x44, 0xfc, 0x15, 0xec, 0xf4, 0xdf, 0x99, 0xd8, 0x7d, 0xd2, 0x75, 0xd2, + 0x6a, 0xd4, 0x0c, 0xe0, 0x87, 0xef, 0xbf, 0xfe, 0xfa, 0x10, 0x81, 0x21, + 0x7f, 0x2d, 0xdc, 0x36, 0x5d, 0x40, 0x28, 0x46, 0xb1, 0x47, 0xff, 0x42, + 0x62, 0x40, 0x00, 0x45, 0xa3, 0x45, 0x97, 0x40, 0x29, 0x3a, 0xb2, 0x30, + 0x38, 0x29, 0xf0, 0x25, 0x3f, 0x21, 0xbc, 0x1e, 0x60, 0x1b, 0x69, 0x15, + 0xaa, 0x10, 0x16, 0x0b, 0x05, 0x08, 0x91, 0x07, 0xef, 0x04, 0xe4, 0x02, + 0x7c, 0x01, 0xf0, 0xff, 0x17, 0x04, 0xb1, 0x09, 0x12, 0x0b, 0x6b, 0x05, + 0xec, 0xfd, 0x3a, 0xfb, 0x6a, 0xfd, 0xd9, 0x03, 0x80, 0x07, 0xdb, 0x0a, + 0x21, 0x0b, 0x68, 0x09, 0xf4, 0x08, 0x49, 0x04, 0x26, 0x03, 0x20, 0x02, + 0x51, 0xfe, 0xc6, 0xfe, 0x29, 0x02, 0xf0, 0x08, 0xc7, 0x0e, 0x34, 0x0f, + 0x2f, 0x0c, 0xb3, 0x05, 0x56, 0xf8, 0xd5, 0xe6, 0x63, 0xd4, 0x62, 0xbf, + 0xf9, 0xb3, 0xc2, 0xb4, 0x89, 0xb6, 0x72, 0xbd, 0x87, 0xc6, 0xca, 0xce, + 0x91, 0xdd, 0x8f, 0xed, 0x70, 0xfe, 0x5d, 0x13, 0x57, 0x21, 0x14, 0x26, + 0xaf, 0x25, 0x72, 0x1e, 0xd3, 0x17, 0xbf, 0x0d, 0xc3, 0x00, 0x97, 0xfd, + 0x25, 0xf9, 0x91, 0xf0, 0x2b, 0xec, 0x5e, 0xe3, 0x1e, 0xd8, 0x1e, 0xd8, + 0xb3, 0xd2, 0xa5, 0xc4, 0xc8, 0xbd, 0x94, 0xb5, 0x8b, 0xae, 0x01, 0xaa, + 0xb9, 0xa7, 0x73, 0xaa, 0xba, 0xad, 0xa5, 0xb1, 0x9b, 0xba, 0x8f, 0xc6, + 0x0c, 0xca, 0x19, 0xcb, 0x52, 0xc9, 0x3a, 0xca, 0x20, 0xd0, 0xa9, 0xc9, + 0x19, 0xc3, 0x77, 0xc1, 0xea, 0xc1, 0x35, 0xca, 0x55, 0xcf, 0x4f, 0xd3, + 0x16, 0xda, 0xdb, 0xde, 0x7e, 0xe7, 0x89, 0xf7, 0xf1, 0x09, 0x9f, 0x18, + 0x6b, 0x26, 0x3c, 0x2a, 0xe2, 0x24, 0x74, 0x20, 0x1a, 0x15, 0x01, 0x0c, + 0x3e, 0x06, 0x61, 0x02, 0x80, 0x04, 0x3e, 0x08, 0x99, 0x09, 0x1f, 0x01, + 0xea, 0xf5, 0x91, 0xeb, 0x29, 0xdf, 0xd2, 0xd1, 0xd0, 0xc8, 0xa8, 0xc5, + 0x20, 0xc6, 0xce, 0xc6, 0xf2, 0xc9, 0x66, 0xd0, 0xb8, 0xd1, 0x99, 0xd4, + 0x98, 0xd7, 0x5b, 0xdc, 0xed, 0xe1, 0x82, 0xe3, 0x72, 0xe5, 0x37, 0xe7, + 0x88, 0xed, 0xb4, 0xf4, 0x90, 0xfd, 0xa4, 0x05, 0x4e, 0x10, 0xea, 0x1d, + 0xe5, 0x24, 0xe9, 0x28, 0x6c, 0x27, 0x47, 0x24, 0xce, 0x19, 0x5d, 0x08, + 0xb1, 0xfc, 0x98, 0xf2, 0xe5, 0xee, 0xb5, 0xf6, 0xe0, 0xfc, 0x9b, 0xfc, + 0x38, 0x01, 0x83, 0x08, 0x21, 0x09, 0xcd, 0xfe, 0x37, 0xf0, 0x02, 0xe8, + 0xc4, 0xe5, 0x35, 0xe4, 0xe0, 0xdf, 0x54, 0xe3, 0x4c, 0xea, 0x2d, 0xe9, + 0x81, 0xe9, 0xca, 0xe9, 0x3b, 0xe6, 0x8e, 0xe5, 0xdc, 0xe7, 0xe5, 0xe7, + 0x35, 0xe6, 0xf9, 0xe4, 0xf6, 0xe2, 0x64, 0xe3, 0x93, 0xe6, 0xdc, 0xee, + 0x19, 0xfa, 0x49, 0x02, 0xf5, 0x09, 0x6b, 0x11, 0x10, 0x15, 0xd0, 0x0c, + 0x67, 0xfb, 0xe4, 0xec, 0x55, 0xe7, 0x4f, 0xea, 0xde, 0xee, 0x9f, 0xf2, + 0x10, 0xf8, 0xd3, 0xff, 0x9b, 0x02, 0x80, 0xfc, 0x57, 0xf2, 0x8c, 0xe5, + 0xaa, 0xdd, 0xf5, 0xd9, 0x66, 0xcc, 0x03, 0xbd, 0xd6, 0xb5, 0x90, 0xb1, + 0xf2, 0xb1, 0xec, 0xb0, 0xa7, 0xa9, 0x86, 0xa2, 0xc8, 0x9c, 0x97, 0x9d, + 0x48, 0xa5, 0x13, 0xa6, 0x4c, 0xa3, 0x50, 0xa8, 0x86, 0xb2, 0xb5, 0xc1, + 0xe5, 0xcf, 0x9e, 0xd6, 0x74, 0xdf, 0x27, 0xed, 0x30, 0xf8, 0xe5, 0xfd, + 0xf8, 0xfc, 0x09, 0xfd, 0xf1, 0x00, 0xeb, 0xfd, 0x44, 0xf3, 0x3e, 0xe4, + 0x0a, 0xd4, 0x9a, 0xc7, 0xed, 0xbb, 0x78, 0xad, 0x52, 0xa6, 0x30, 0xa6, + 0x35, 0xaa, 0xf8, 0xb5, 0x52, 0xc0, 0xec, 0xcc, 0x88, 0xd9, 0xb7, 0xe2, + 0x4e, 0xeb, 0x02, 0xee, 0xa2, 0xf0, 0x58, 0xf3, 0x7b, 0xf7, 0xb3, 0xfd, + 0x86, 0x02, 0x87, 0x05, 0x93, 0x02, 0x80, 0xfa, 0x3b, 0xf0, 0xbe, 0xe2, + 0x3c, 0xd5, 0xc6, 0xcb, 0x69, 0xc5, 0x8b, 0xc3, 0x07, 0xc7, 0xa1, 0xce, + 0x86, 0xd4, 0x24, 0xd8, 0x4b, 0xdf, 0xd9, 0xe4, 0xc1, 0xe6, 0xed, 0xe6, + 0xab, 0xe2, 0x3c, 0xdc, 0x53, 0xd6, 0x8f, 0xd3, 0xe8, 0xd1, 0x0b, 0xd0, + 0xe8, 0xd3, 0x50, 0xde, 0x36, 0xf0, 0xec, 0x02, 0xe2, 0x13, 0xbe, 0x1e, + 0xd3, 0x22, 0x09, 0x28, 0xcb, 0x25, 0x21, 0x23, 0x48, 0x23, 0x58, 0x27, + 0xd9, 0x2e, 0xef, 0x2f, 0x83, 0x2c, 0x22, 0x25, 0x62, 0x1f, 0xfc, 0x17, + 0x75, 0x14, 0x4c, 0x0f, 0x0d, 0x05, 0x43, 0x05, 0xff, 0x07, 0x11, 0x08, + 0xf1, 0x03, 0xff, 0x00, 0xee, 0x03, 0xf1, 0x09, 0x71, 0x0f, 0x33, 0x10, + 0x44, 0x0b, 0x84, 0x02, 0x04, 0xfb, 0xac, 0xf0, 0x9c, 0xe7, 0xc9, 0xe4, + 0x05, 0xe3, 0x64, 0xe0, 0x26, 0xdd, 0x53, 0xd6, 0x47, 0xcd, 0x97, 0xc0, + 0xe7, 0xb3, 0x8f, 0xaf, 0x8f, 0xb0, 0xa1, 0xba, 0x6c, 0xc8, 0x11, 0xd8, + 0x71, 0xe8, 0xa2, 0xf4, 0xfe, 0xf6, 0x2d, 0xee, 0xbb, 0xe9, 0x85, 0xe6, + 0x16, 0xe6, 0x03, 0xe8, 0x41, 0xeb, 0x9b, 0xf4, 0x61, 0xfd, 0xeb, 0x00, + 0x86, 0xfd, 0x96, 0x00, 0x30, 0x04, 0xfa, 0x06, 0x36, 0x12, 0x13, 0x1d, + 0x4e, 0x2c, 0x0a, 0x3a, 0x81, 0x3f, 0x10, 0x44, 0x80, 0x44, 0x75, 0x40, + 0x72, 0x3e, 0xb4, 0x3c, 0xcd, 0x37, 0x04, 0x30, 0x3b, 0x24, 0xcc, 0x16, + 0x48, 0x09, 0x30, 0xfd, 0x39, 0xf5, 0x7b, 0xe9, 0x5c, 0xda, 0x8d, 0xd0, + 0x4a, 0xcb, 0x28, 0xca, 0x3d, 0xc5, 0x49, 0xbc, 0x91, 0xb4, 0x15, 0xae, + 0xbd, 0xaa, 0x6e, 0xab, 0x77, 0xb3, 0xf2, 0xbd, 0x66, 0xcd, 0x12, 0xe2, + 0xe8, 0xf4, 0x79, 0x07, 0x97, 0x17, 0x9f, 0x20, 0xdb, 0x24, 0xcd, 0x27, + 0xb4, 0x22, 0xf6, 0x1f, 0xe0, 0x26, 0xed, 0x2e, 0x01, 0x39, 0x34, 0x41, + 0x8a, 0x46, 0x26, 0x4a, 0xf1, 0x4b, 0xb8, 0x4c, 0x82, 0x4d, 0x4f, 0x4a, + 0x40, 0x3f, 0xb8, 0x38, 0x54, 0x37, 0xd2, 0x33, 0x4c, 0x2c, 0x90, 0x20, + 0x21, 0x16, 0x25, 0x0c, 0x86, 0x03, 0x58, 0xfa, 0x76, 0xed, 0x99, 0xe2, + 0x2f, 0xdd, 0xb5, 0xde, 0x98, 0xe3, 0x98, 0xe8, 0xf8, 0xee, 0x35, 0xf9, + 0x1c, 0x04, 0xb0, 0x0e, 0x10, 0x17, 0x64, 0x1a, 0xcc, 0x21, 0xdf, 0x28, + 0x05, 0x2e, 0xd1, 0x36, 0xbf, 0x3c, 0xbe, 0x3b, 0xbc, 0x35, 0x47, 0x2d, + 0xf2, 0x20, 0x57, 0x13, 0xfe, 0x02, 0x3c, 0xef, 0x0c, 0xdd, 0x87, 0xcc, + 0xfc, 0xbf, 0x64, 0xbb, 0x6f, 0xbd, 0x87, 0xc2, 0x46, 0xcc, 0xc9, 0xd8, + 0x4f, 0xe8, 0xa2, 0xf9, 0x9f, 0x08, 0x42, 0x16, 0x4b, 0x1c, 0x10, 0x1f, + 0x12, 0x28, 0x46, 0x30, 0x2f, 0x33, 0x1e, 0x34, 0x91, 0x33, 0x4f, 0x33, + 0xfa, 0x31, 0xc7, 0x24, 0x70, 0x13, 0x74, 0x0a, 0x7a, 0x01, 0xc7, 0xff, + 0xc9, 0x06, 0x6d, 0x0b, 0x04, 0x12, 0x75, 0x17, 0x4a, 0x1a, 0x3e, 0x20, + 0x26, 0x25, 0x90, 0x28, 0x2a, 0x2e, 0xe3, 0x32, 0xb0, 0x36, 0x85, 0x3a, + 0xb6, 0x3a, 0x8d, 0x34, 0x0d, 0x2b, 0x8b, 0x27, 0xf8, 0x2a, 0xfc, 0x2f, + 0x67, 0x33, 0x85, 0x34, 0xd0, 0x35, 0xea, 0x33, 0x22, 0x2a, 0x36, 0x1f, + 0xb2, 0x14, 0x80, 0x0d, 0xc1, 0x0e, 0x45, 0x0d, 0x90, 0x0c, 0x1b, 0x0d, + 0xf1, 0x07, 0x4b, 0x05, 0xfb, 0x00, 0xc3, 0xf8, 0x9b, 0xf4, 0xac, 0xf1, + 0x8a, 0xec, 0x99, 0xe9, 0xde, 0xe9, 0x75, 0xed, 0xa0, 0xf2, 0x49, 0xf8, + 0xc2, 0xfd, 0xc3, 0x02, 0xe6, 0x0b, 0xd6, 0x1c, 0x43, 0x2f, 0xc1, 0x39, + 0xe0, 0x40, 0x5d, 0x45, 0xdd, 0x46, 0xee, 0x44, 0xab, 0x3e, 0x78, 0x3c, + 0x35, 0x3a, 0xcf, 0x3a, 0x46, 0x44, 0x7a, 0x4e, 0xe3, 0x58, 0xa1, 0x60, + 0xa9, 0x60, 0xbb, 0x5d, 0xe1, 0x59, 0xd3, 0x52, 0x54, 0x47, 0x83, 0x3c, + 0x28, 0x37, 0x47, 0x36, 0x9a, 0x36, 0x28, 0x33, 0x91, 0x2d, 0xce, 0x28, + 0xf8, 0x24, 0x88, 0x20, 0xe4, 0x19, 0x11, 0x12, 0x72, 0x0a, 0x0c, 0x02, + 0x51, 0xfc, 0x13, 0xfd, 0xba, 0xf9, 0xef, 0xf3, 0x3a, 0xf2, 0xda, 0xf4, + 0xe3, 0xfc, 0xce, 0x03, 0xe4, 0x0a, 0x71, 0x12, 0xb7, 0x19, 0xd5, 0x21, + 0x47, 0x23, 0xc6, 0x15, 0xf9, 0x00, 0x58, 0xf4, 0xa4, 0xf1, 0xfe, 0xf8, + 0xf1, 0xfd, 0x87, 0xfe, 0x83, 0x06, 0x2b, 0x0c, 0x24, 0x0b, 0x31, 0x05, + 0x34, 0xfe, 0x26, 0xfa, 0xd6, 0xfb, 0x3d, 0x07, 0xfd, 0x15, 0x1b, 0x26, + 0x27, 0x33, 0x54, 0x3e, 0xd1, 0x4c, 0x2b, 0x52, 0x51, 0x51, 0x62, 0x53, + 0x96, 0x54, 0xff, 0x55, 0xf6, 0x56, 0xff, 0x54, 0xd0, 0x51, 0xf0, 0x51, + 0x26, 0x50, 0x73, 0x4b, 0xd8, 0x45, 0xbd, 0x37, 0xf5, 0x24, 0x54, 0x12, + 0x71, 0x03, 0x59, 0xfb, 0x89, 0xf9, 0xad, 0xf8, 0xa1, 0xf7, 0xda, 0xf8, + 0x95, 0xf6, 0x2c, 0xf3, 0x91, 0xe9, 0x72, 0xdf, 0x93, 0xdc, 0xf0, 0xda, + 0x76, 0xdb, 0x79, 0xdf, 0x91, 0xea, 0x3b, 0xf4, 0x28, 0xfb, 0xc3, 0x03, + 0x68, 0x0a, 0xcf, 0x10, 0x1e, 0x14, 0x58, 0x13, 0x40, 0x10, 0x94, 0x0e, + 0x65, 0x10, 0x70, 0x12, 0xa5, 0x14, 0xf2, 0x15, 0x63, 0x12, 0xac, 0x12, + 0x2d, 0x19, 0x97, 0x1e, 0x9b, 0x20, 0xbc, 0x21, 0x0f, 0x2a, 0x19, 0x33, + 0xc4, 0x36, 0x97, 0x32, 0xc8, 0x2d, 0xa1, 0x2e, 0x67, 0x2a, 0x0b, 0x22, + 0xcf, 0x16, 0xc8, 0x0e, 0x5f, 0x09, 0xcd, 0x02, 0xe2, 0x02, 0xfb, 0x04, + 0xd6, 0x0b, 0xf4, 0x17, 0x8a, 0x21, 0x90, 0x23, 0x5f, 0x1b, 0x4a, 0x10, + 0xdf, 0x07, 0x88, 0x01, 0x85, 0xf9, 0x4e, 0xf4, 0xf2, 0xf7, 0x96, 0xfb, + 0x4a, 0xfa, 0xa7, 0xf8, 0x07, 0xf9, 0x10, 0xf8, 0x9c, 0xf2, 0xf9, 0xed, + 0x01, 0xf1, 0x63, 0xfc, 0xd2, 0x0b, 0x39, 0x1e, 0x03, 0x2d, 0xa3, 0x31, + 0xc1, 0x32, 0x94, 0x2f, 0xa4, 0x2a, 0xff, 0x28, 0x6b, 0x25, 0x08, 0x24, + 0xc6, 0x2a, 0xb0, 0x31, 0x3d, 0x30, 0x69, 0x24, 0x4e, 0x13, 0x18, 0x05, + 0x20, 0xfb, 0x18, 0xf7, 0x2c, 0xfd, 0x9d, 0x0a, 0x43, 0x1b, 0xbc, 0x2b, + 0xa5, 0x34, 0x3b, 0x37, 0x47, 0x36, 0x96, 0x2d, 0x1b, 0x23, 0xd3, 0x19, + 0x16, 0x12, 0x02, 0x0d, 0xe6, 0x08, 0xe1, 0x05, 0x0a, 0x01, 0x06, 0xfd, + 0x77, 0xf8, 0xe3, 0xf0, 0x72, 0xec, 0x14, 0xea, 0x8e, 0xe8, 0x11, 0xe8, + 0x94, 0xe2, 0xf6, 0xda, 0x27, 0xd9, 0x2c, 0xdb, 0xfd, 0xdf, 0xe4, 0xe5, + 0x56, 0xed, 0x1c, 0xf4, 0x24, 0xfa, 0x9d, 0x08, 0x6d, 0x12, 0xbe, 0x10, + 0x3f, 0x08, 0x26, 0xfc, 0x1d, 0xf3, 0x8c, 0xea, 0x92, 0xe3, 0x4f, 0xdf, + 0x29, 0xe4, 0x3d, 0xed, 0x83, 0xf8, 0x83, 0x08, 0x5f, 0x16, 0x0e, 0x22, + 0x21, 0x23, 0x50, 0x23, 0xb4, 0x21, 0x31, 0x18, 0xe1, 0x0d, 0x7e, 0x00, + 0x2a, 0xf9, 0x3d, 0xf4, 0x8e, 0xf3, 0xc8, 0xf7, 0x28, 0xfb, 0xad, 0xff, + 0x87, 0x05, 0x68, 0x10, 0xf3, 0x15, 0x7d, 0x18, 0xef, 0x1e, 0x06, 0x26, + 0xa6, 0x2e, 0x13, 0x36, 0x29, 0x3c, 0x7c, 0x40, 0xa7, 0x3e, 0x81, 0x3a, + 0x59, 0x34, 0x4a, 0x2a, 0xd1, 0x23, 0x12, 0x22, 0xf6, 0x25, 0x2b, 0x2c, + 0x3b, 0x2e, 0x4d, 0x2c, 0x1b, 0x2c, 0x9d, 0x29, 0xb7, 0x1e, 0x56, 0x12, + 0x20, 0x03, 0x5d, 0xf5, 0xfd, 0xef, 0xc8, 0xef, 0x57, 0xee, 0x59, 0xef, + 0x7f, 0xf8, 0x23, 0x06, 0x90, 0x13, 0x51, 0x1a, 0x1c, 0x1a, 0xe2, 0x15, + 0xc2, 0x10, 0x8e, 0x0a, 0xc0, 0x06, 0xeb, 0xfe, 0x9a, 0xf1, 0x9c, 0xea, + 0x9c, 0xe6, 0x63, 0xe2, 0x02, 0xdd, 0xd5, 0xdc, 0x8b, 0xe2, 0xf3, 0xe7, + 0x3a, 0xea, 0xfd, 0xec, 0xc2, 0xf4, 0x08, 0xfa, 0xd7, 0xf8, 0xaf, 0xf6, + 0x24, 0xfb, 0x05, 0x02, 0xe8, 0x0a, 0xdc, 0x16, 0x3c, 0x20, 0x6b, 0x29, + 0x5a, 0x2d, 0x30, 0x24, 0xf5, 0x18, 0x57, 0x0c, 0xdb, 0xf9, 0xe7, 0xec, + 0x9b, 0xe4, 0x1f, 0xdf, 0xed, 0xd8, 0xf5, 0xd5, 0x0b, 0xd6, 0xf3, 0xd4, + 0x3f, 0xd4, 0x84, 0xd0, 0x46, 0xd7, 0xc1, 0xdd, 0x2b, 0xdd, 0xa6, 0xdc, + 0xda, 0xd8, 0x0b, 0xd7, 0xb2, 0xd5, 0x7a, 0xd6, 0x8c, 0xde, 0x83, 0xeb, + 0x28, 0xf5, 0xf8, 0xfc, 0x62, 0x04, 0xad, 0x07, 0xa9, 0x04, 0xb4, 0xf7, + 0xa0, 0xe7, 0x2f, 0xdd, 0xd2, 0xd8, 0xe1, 0xda, 0x40, 0xe2, 0xb8, 0xe4, + 0x63, 0xe5, 0xd3, 0xe7, 0xa9, 0xea, 0x50, 0xf0, 0x22, 0xf1, 0x79, 0xf1, + 0x27, 0xf2, 0xf1, 0xf2, 0xf4, 0xf5, 0xe3, 0xf6, 0xee, 0xfd, 0xa2, 0x04, + 0x49, 0x08, 0x90, 0x0d, 0xdd, 0x0c, 0x69, 0x0c, 0xc9, 0x06, 0xf2, 0xfc, + 0xfe, 0xf2, 0x92, 0xde, 0xc8, 0xca, 0x0b, 0xbc, 0xa7, 0xb2, 0xb6, 0xb0, + 0x12, 0xb3, 0x4e, 0xb9, 0xb7, 0xc2, 0x65, 0xcf, 0x4c, 0xda, 0x87, 0xe5, + 0x73, 0xec, 0x4e, 0xeb, 0xaa, 0xe8, 0xc6, 0xe5, 0x50, 0xe2, 0xa6, 0xdc, + 0x79, 0xd9, 0xc5, 0xdc, 0x0e, 0xe1, 0xd7, 0xe4, 0x50, 0xec, 0xd6, 0xf7, + 0xde, 0x05, 0x5f, 0x11, 0xdf, 0x16, 0x8a, 0x17, 0xf8, 0x16, 0x85, 0x17, + 0x6b, 0x16, 0x53, 0x16, 0x72, 0x1a, 0xdb, 0x21, 0xb6, 0x25, 0x0b, 0x24, + 0xc0, 0x20, 0xab, 0x17, 0xa4, 0x08, 0xb6, 0xfc, 0xe8, 0xf6, 0xe2, 0xf1, + 0x8e, 0xf2, 0xb7, 0xf9, 0xb8, 0xff, 0xe3, 0x04, 0xa7, 0x08, 0x70, 0x0d, + 0xe8, 0x10, 0x7d, 0x0f, 0xd7, 0x11, 0xe9, 0x0f, 0x96, 0x07, 0x32, 0x02, + 0x1e, 0xf5, 0xb6, 0xe3, 0x86, 0xd3, 0x12, 0xca, 0x62, 0xc7, 0x85, 0xc2, + 0x5e, 0xc0, 0x37, 0xc1, 0x76, 0xc5, 0x9a, 0xc7, 0x70, 0xca, 0x4e, 0xcd, + 0x33, 0xcc, 0x8f, 0xcc, 0x2c, 0xcb, 0x93, 0xcb, 0x94, 0xcb, 0x8e, 0xc7, + 0x35, 0xca, 0x2e, 0xd6, 0x54, 0xdd, 0x87, 0xe4, 0x21, 0xeb, 0xd0, 0xe7, + 0x82, 0xde, 0x12, 0xd0, 0x90, 0xc1, 0xa4, 0xb3, 0xc8, 0xac, 0x28, 0xaf, + 0xe1, 0xba, 0x60, 0xcd, 0xe3, 0xe0, 0x29, 0xf2, 0xcc, 0x02, 0x6c, 0x11, + 0xb8, 0x14, 0x83, 0x14, 0xa1, 0x12, 0x43, 0x19, 0xad, 0x22, 0x4f, 0x2a, + 0xaf, 0x35, 0xc0, 0x36, 0xd5, 0x31, 0x4c, 0x28, 0x6f, 0x1c, 0x33, 0x0f, + 0x77, 0x05, 0x97, 0x00, 0x22, 0x00, 0xcf, 0x02, 0x0b, 0x04, 0xaa, 0x08, + 0x83, 0x06, 0x20, 0xfe, 0x30, 0xf2, 0x16, 0xe7, 0x52, 0xdf, 0xbe, 0xd7, + 0x9f, 0xd3, 0xf8, 0xd1, 0xc8, 0xd3, 0xd1, 0xd7, 0x07, 0xe1, 0x30, 0xe7, + 0xcb, 0xe5, 0x8d, 0xe2, 0x82, 0xdb, 0x50, 0xd6, 0x78, 0xd7, 0x97, 0xd7, + 0x6f, 0xd0, 0x5e, 0xc8, 0xee, 0xc4, 0xd0, 0xc2, 0xa8, 0xc0, 0x45, 0xbf, + 0x72, 0xc0, 0x95, 0xc2, 0xd7, 0xbe, 0x52, 0xba, 0x8d, 0xbb, 0x2f, 0xc3, + 0x51, 0xcf, 0x37, 0xda, 0xfe, 0xe0, 0x1f, 0xe9, 0x45, 0xf2, 0x44, 0xf7, + 0xce, 0xf8, 0xec, 0xf1, 0xb2, 0xea, 0x4d, 0xe9, 0xb3, 0xeb, 0xcb, 0xf1, + 0x87, 0xf7, 0xd5, 0xf9, 0xa5, 0xf8, 0xa8, 0xf8, 0xc2, 0xf7, 0xf6, 0xf8, + 0x9f, 0xf7, 0x88, 0xf5, 0x4e, 0xf9, 0x0f, 0xfb, 0x06, 0xfb, 0x90, 0xf9, + 0x6c, 0xf7, 0x8f, 0xf4, 0x53, 0xf0, 0x3a, 0xed, 0xeb, 0xf0, 0x40, 0xf9, + 0x12, 0x04, 0x8d, 0x0e, 0xfe, 0x10, 0xc2, 0x0c, 0xdf, 0x06, 0x4e, 0x02, + 0x92, 0xfd, 0xb1, 0xf8, 0xb5, 0xf1, 0xb5, 0xed, 0x8f, 0xeb, 0xdb, 0xe4, + 0xd1, 0xdf, 0x3d, 0xde, 0x8d, 0xd9, 0x06, 0xd3, 0x94, 0xce, 0xf8, 0xcc, + 0x9d, 0xd3, 0x05, 0xd8, 0x11, 0xda, 0xe2, 0xda, 0x04, 0xd7, 0xb7, 0xd4, + 0xd4, 0xd2, 0x66, 0xd3, 0x75, 0xd3, 0x0e, 0xd7, 0x89, 0xdf, 0xa6, 0xe9, + 0x24, 0xed, 0xc5, 0xea, 0x5d, 0xee, 0x67, 0xed, 0xde, 0xe5, 0x1e, 0xdb, + 0x07, 0xda, 0x60, 0xe4, 0xec, 0xeb, 0xfd, 0xf4, 0xd3, 0xfe, 0xca, 0x07, + 0x97, 0x0d, 0x02, 0x0c, 0x4c, 0x06, 0x81, 0xf9, 0xd7, 0xea, 0x98, 0xe1, + 0x1b, 0xdc, 0x7c, 0xdb, 0xc2, 0xdf, 0x2b, 0xeb, 0x4c, 0xf8, 0xcd, 0x03, + 0xe4, 0x11, 0xb2, 0x1c, 0x30, 0x1f, 0xce, 0x19, 0x9b, 0x12, 0xb8, 0x05, + 0xe7, 0xf3, 0xe9, 0xe7, 0x85, 0xe1, 0xa5, 0xdd, 0xb5, 0xdc, 0xa5, 0xe0, + 0x2f, 0xe5, 0x50, 0xec, 0x64, 0xf9, 0x47, 0x07, 0x98, 0x13, 0x04, 0x1c, + 0x48, 0x1e, 0x76, 0x15, 0x94, 0x07, 0xd4, 0xff, 0x3c, 0xfa, 0x50, 0xf9, + 0x6b, 0xff, 0x63, 0x07, 0xd5, 0x11, 0x61, 0x1a, 0xde, 0x21, 0x2f, 0x29, + 0x07, 0x29, 0xea, 0x22, 0xad, 0x1c, 0x96, 0x18, 0x33, 0x15, 0x24, 0x13, + 0x28, 0x14, 0x13, 0x16, 0x6a, 0x15, 0xdc, 0x12, 0x8d, 0x12, 0xb3, 0x12, + 0x2e, 0x0f, 0x0e, 0x06, 0xf3, 0xfe, 0x03, 0x00, 0x29, 0x01, 0x0e, 0xfc, + 0x76, 0xf3, 0x1a, 0xef, 0xbe, 0xeb, 0xfe, 0xe8, 0x02, 0xed, 0xf9, 0xf3, + 0x36, 0xfd, 0x5b, 0x02, 0xb7, 0x01, 0xbe, 0xfd, 0xfd, 0xf5, 0x4d, 0xed, + 0xbd, 0xe3, 0xb2, 0xde, 0x97, 0xe2, 0x03, 0xef, 0x05, 0x00, 0x70, 0x10, + 0x0d, 0x19, 0xce, 0x18, 0x68, 0x14, 0x08, 0x0c, 0x46, 0xff, 0xf2, 0xf1, + 0xa0, 0xe7, 0x77, 0xdb, 0x1e, 0xd4, 0x80, 0xd5, 0xb6, 0xdf, 0xf0, 0xed, + 0x5c, 0xf6, 0x7a, 0x03, 0xa8, 0x14, 0x24, 0x24, 0x3b, 0x2c, 0xe9, 0x2b, + 0x8f, 0x2b, 0xc6, 0x2e, 0xe7, 0x30, 0xca, 0x2a, 0x5b, 0x26, 0x3f, 0x24, + 0xa6, 0x20, 0x53, 0x1a, 0x99, 0x15, 0x7d, 0x12, 0xe4, 0x0a, 0x70, 0x02, + 0xe0, 0xf4, 0x96, 0xeb, 0xf8, 0xe2, 0xa3, 0xd6, 0x58, 0xd2, 0x94, 0xd1, + 0x33, 0xd4, 0xe2, 0xd4, 0x83, 0xd5, 0x3b, 0xe0, 0x98, 0xed, 0xa6, 0xf6, + 0xd8, 0xff, 0x63, 0x07, 0x23, 0x08, 0x86, 0x07, 0x01, 0x07, 0x51, 0x07, + 0x51, 0x0b, 0x43, 0x11, 0x7a, 0x15, 0xb5, 0x20, 0xf0, 0x2d, 0xea, 0x29, + 0x49, 0x20, 0x06, 0x1e, 0xfd, 0x1f, 0xf4, 0x1a, 0x21, 0x13, 0x31, 0x13, + 0xfa, 0x0d, 0x96, 0x07, 0x79, 0x04, 0xcf, 0x01, 0xf5, 0x04, 0x49, 0x06, + 0x72, 0x03, 0xca, 0x04, 0x4d, 0x0b, 0x32, 0x0d, 0x1e, 0x0c, 0xe1, 0x0f, + 0x45, 0x15, 0x6b, 0x16, 0xca, 0x13, 0x17, 0x15, 0x13, 0x17, 0x87, 0x16, + 0x0e, 0x13, 0xc3, 0x0c, 0xd0, 0x0d, 0xb9, 0x0e, 0x88, 0x08, 0xf1, 0x03, + 0xae, 0x02, 0x06, 0x05, 0x05, 0x0c, 0x84, 0x14, 0x4b, 0x15, 0xcf, 0x12, + 0xce, 0x12, 0x83, 0x0d, 0xf3, 0x08, 0xca, 0x08, 0x82, 0x08, 0x18, 0x0d, + 0x0e, 0x16, 0xca, 0x22, 0xf6, 0x2f, 0x80, 0x36, 0xed, 0x3a, 0x73, 0x3b, + 0x46, 0x31, 0xdf, 0x24, 0x6d, 0x18, 0xf2, 0x0c, 0x61, 0x08, 0xb0, 0x02, + 0x5a, 0xf9, 0x35, 0xf5, 0x97, 0xf8, 0x88, 0xfc, 0xfe, 0xfb, 0x1e, 0x01, + 0xd0, 0x0c, 0xa4, 0x13, 0x2b, 0x14, 0xfa, 0x13, 0xcb, 0x12, 0xb5, 0x0d, + 0xaf, 0x06, 0x47, 0xfd, 0xad, 0xf5, 0x31, 0xf5, 0x07, 0xfe, 0x05, 0x13, + 0x54, 0x2b, 0x74, 0x42, 0x1a, 0x55, 0x4b, 0x5d, 0x28, 0x5d, 0x46, 0x50, + 0x34, 0x3c, 0x0d, 0x2c, 0x83, 0x21, 0x8c, 0x1c, 0xca, 0x1b, 0x6f, 0x19, + 0x84, 0x0f, 0xaa, 0x06, 0x5c, 0x07, 0x67, 0x11, 0xf2, 0x19, 0x8a, 0x1f, + 0x2b, 0x2c, 0xb1, 0x3a, 0x2a, 0x47, 0x87, 0x4f, 0x3e, 0x56, 0x02, 0x5a, + 0x7e, 0x57, 0x1c, 0x50, 0x9b, 0x42, 0xa7, 0x31, 0xac, 0x1e, 0x18, 0x0e, + 0x8c, 0x00, 0xa6, 0xf9, 0x1c, 0xfb, 0x5d, 0xfa, 0xd6, 0xf4, 0xb9, 0xed, + 0x82, 0xea, 0x6c, 0xeb, 0x67, 0xed, 0x92, 0xef, 0x96, 0xf2, 0x5e, 0xf8, + 0x2b, 0x00, 0xc4, 0x07, 0x99, 0x0f, 0x98, 0x19, 0x16, 0x27, 0x0a, 0x35, + 0x1a, 0x3b, 0x3d, 0x37, 0xc8, 0x2d, 0xe9, 0x22, 0x8b, 0x14, 0xd0, 0x06, + 0x3e, 0xff, 0xb5, 0xfb, 0x3b, 0xff, 0xa5, 0x08, 0x18, 0x18, 0x54, 0x2a, + 0x87, 0x38, 0xa4, 0x41, 0x27, 0x46, 0xcc, 0x46, 0xd0, 0x40, 0xdb, 0x38, + 0xc6, 0x36, 0x22, 0x38, 0xd9, 0x36, 0x63, 0x35, 0x55, 0x35, 0xf9, 0x2f, + 0xbe, 0x26, 0x83, 0x1f, 0x04, 0x16, 0xc9, 0x07, 0xed, 0xff, 0x7f, 0x00, + 0x86, 0x05, 0xd2, 0x09, 0xbd, 0x06, 0xbc, 0x04, 0x96, 0x07, 0xcd, 0x0c, + 0xaf, 0x13, 0x69, 0x1c, 0xc9, 0x22, 0x74, 0x20, 0xc5, 0x1d, 0xec, 0x19, + 0x45, 0x0f, 0x14, 0x04, 0x4a, 0xf7, 0xfc, 0xe8, 0x96, 0xe1, 0x5a, 0xe2, + 0x3e, 0xe6, 0xf8, 0xe6, 0x3a, 0xe5, 0xdf, 0xe8, 0x19, 0xf1, 0x5d, 0xf7, + 0x5a, 0xf8, 0x18, 0xf7, 0x56, 0xf7, 0xf1, 0xfb, 0x94, 0x00, 0x18, 0x06, + 0x6c, 0x14, 0x91, 0x19, 0x23, 0x15, 0x34, 0x11, 0xaa, 0x04, 0x4c, 0xf6, + 0x68, 0xed, 0x72, 0xe8, 0x82, 0xe5, 0x9f, 0xe6, 0x50, 0xec, 0x73, 0xf0, + 0x37, 0xef, 0x22, 0xed, 0xae, 0xef, 0x27, 0xf4, 0xbd, 0xf9, 0x16, 0x01, + 0x0c, 0x0a, 0xe7, 0x14, 0x76, 0x20, 0x0a, 0x28, 0xaf, 0x25, 0xe7, 0x1b, + 0x26, 0x15, 0x81, 0x10, 0x04, 0x0b, 0xce, 0x0b, 0x81, 0x14, 0xdb, 0x1f, + 0x3b, 0x2c, 0x36, 0x3b, 0xa0, 0x44, 0xf0, 0x44, 0xd8, 0x3f, 0x99, 0x37, + 0x6d, 0x30, 0x48, 0x2b, 0x3f, 0x2e, 0xdb, 0x32, 0xcf, 0x2c, 0x73, 0x23, + 0xe7, 0x1b, 0xec, 0x13, 0xb2, 0x0f, 0xe4, 0x11, 0xd4, 0x1a, 0xf8, 0x24, + 0xf5, 0x2f, 0x65, 0x38, 0xf0, 0x37, 0x36, 0x35, 0x6e, 0x2d, 0xa3, 0x25, + 0xc9, 0x20, 0x20, 0x1e, 0x3a, 0x20, 0x97, 0x1f, 0x40, 0x1c, 0x6d, 0x12, + 0x3d, 0x08, 0xbc, 0xfe, 0xbd, 0xf0, 0x83, 0xe0, 0x44, 0xd1, 0x5f, 0xce, + 0xfd, 0xd0, 0x08, 0xd4, 0x78, 0xdb, 0x2c, 0xe3, 0xc2, 0xed, 0x05, 0xf9, + 0x4b, 0xfe, 0x16, 0x00, 0x79, 0x01, 0xe0, 0x02, 0xcf, 0x03, 0xcb, 0x04, + 0xe5, 0x06, 0x85, 0x0c, 0x5f, 0x12, 0x34, 0x19, 0xba, 0x24, 0x37, 0x2b, + 0x5b, 0x2d, 0xc4, 0x2a, 0x94, 0x23, 0x1a, 0x21, 0x76, 0x1e, 0x9b, 0x17, + 0xe0, 0x12, 0x12, 0x15, 0xec, 0x1a, 0x1b, 0x1f, 0xb3, 0x1b, 0x14, 0x19, + 0x27, 0x20, 0xb2, 0x27, 0x3b, 0x29, 0x6d, 0x2a, 0x39, 0x29, 0xc4, 0x21, + 0x0e, 0x1b, 0x86, 0x11, 0x85, 0x0b, 0xff, 0x03, 0x80, 0xf5, 0x6e, 0xef, + 0xae, 0xea, 0x40, 0xe4, 0x2b, 0xe1, 0x07, 0xe2, 0xc6, 0xe5, 0x3d, 0xec, + 0x45, 0xf2, 0xe3, 0xf3, 0x8d, 0xf5, 0x42, 0xf4, 0x99, 0xf2, 0xe1, 0xf0, + 0xd1, 0xeb, 0x7b, 0xea, 0x28, 0xed, 0x4b, 0xf6, 0xfc, 0x08, 0x88, 0x19, + 0x84, 0x24, 0xe3, 0x2d, 0x34, 0x31, 0xee, 0x2a, 0xeb, 0x1d, 0xc4, 0x0e, + 0x94, 0xfc, 0xfc, 0xec, 0x4f, 0xe9, 0x25, 0xf1, 0xe4, 0xfe, 0xc7, 0x10, + 0x1f, 0x24, 0x9e, 0x36, 0x89, 0x47, 0x2a, 0x4f, 0x10, 0x4c, 0xe7, 0x3e, + 0xd9, 0x29, 0xe4, 0x12, 0xb1, 0xfe, 0xc1, 0xee, 0x16, 0xe5, 0xdb, 0xe5, + 0x54, 0xeb, 0x8c, 0xf2, 0x85, 0xf8, 0xbe, 0xf8, 0xb9, 0xf5, 0x3a, 0xf0, + 0x93, 0xeb, 0x0c, 0xe7, 0xf6, 0xde, 0xc9, 0xd7, 0x71, 0xd4, 0x2f, 0xd4, + 0xee, 0xd5, 0x07, 0xd9, 0xc9, 0xe1, 0xe1, 0xe9, 0xc3, 0xf0, 0xbd, 0xf9, + 0x64, 0xfe, 0x60, 0x01, 0x81, 0xff, 0xf6, 0xfc, 0xb3, 0xfe, 0x95, 0xff, + 0x28, 0x05, 0xf9, 0x0b, 0x2d, 0x13, 0xd1, 0x18, 0x3f, 0x1b, 0xcd, 0x1c, + 0xdd, 0x1a, 0xe3, 0x19, 0x48, 0x17, 0x6d, 0x17, 0x87, 0x1c, 0x07, 0x1f, + 0xcb, 0x22, 0x9a, 0x27, 0xcd, 0x2b, 0x93, 0x2c, 0x8f, 0x2a, 0x0a, 0x25, + 0x74, 0x1b, 0x4c, 0x0f, 0xcb, 0xfd, 0x45, 0xed, 0x44, 0xdf, 0x02, 0xd8, + 0xd5, 0xd9, 0xdd, 0xdc, 0x7e, 0xe0, 0xd9, 0xe3, 0x4f, 0xe9, 0xe7, 0xf0, + 0x25, 0xf3, 0x2a, 0xf1, 0x24, 0xef, 0xb0, 0xe9, 0x04, 0xe1, 0xaf, 0xd8, + 0x27, 0xd0, 0xb8, 0xc9, 0x2e, 0xc8, 0x2c, 0xcb, 0xb9, 0xd0, 0xac, 0xd7, + 0x77, 0xe1, 0x58, 0xec, 0x90, 0xf3, 0xe6, 0xfa, 0xb9, 0x01, 0xb5, 0x01, + 0x7a, 0x02, 0xaf, 0x07, 0xad, 0x0d, 0x11, 0x12, 0xff, 0x13, 0x06, 0x18, + 0xc1, 0x1c, 0xbe, 0x1e, 0x01, 0x21, 0x92, 0x24, 0x44, 0x25, 0x4b, 0x22, + 0x4b, 0x23, 0xd9, 0x28, 0x9a, 0x27, 0x5b, 0x1e, 0xdf, 0x10, 0xd5, 0x03, + 0x0c, 0xfd, 0xb2, 0xf9, 0xd1, 0xfb, 0x78, 0x02, 0x4e, 0x0d, 0x6d, 0x1d, + 0x12, 0x29, 0x49, 0x2b, 0xc9, 0x23, 0x9b, 0x16, 0x46, 0x07, 0xc9, 0xf9, + 0xe6, 0xea, 0x35, 0xda, 0x53, 0xca, 0x16, 0xba, 0x94, 0xb3, 0xd5, 0xb2, + 0x96, 0xb5, 0xd5, 0xbd, 0x7e, 0xc8, 0xf5, 0xd5, 0xc6, 0xe1, 0xf0, 0xea, + 0x54, 0xeb, 0x08, 0xe2, 0xb2, 0xd1, 0x29, 0xc3, 0x14, 0xbf, 0xd0, 0xbf, + 0xb7, 0xc1, 0xb5, 0xc5, 0x5e, 0xcb, 0x21, 0xd1, 0x84, 0xd9, 0x6d, 0xde, + 0x57, 0xe0, 0x2a, 0xdf, 0x01, 0xdb, 0xda, 0xdb, 0x15, 0xdb, 0xc1, 0xdb, + 0x22, 0xe3, 0x53, 0xe9, 0xbb, 0xf0, 0xc2, 0xff, 0xbe, 0x0e, 0x66, 0x1a, + 0x54, 0x24, 0x1d, 0x28, 0x59, 0x2a, 0x01, 0x2e, 0x74, 0x28, 0x10, 0x1b, + 0x48, 0x11, 0xb5, 0x09, 0xc1, 0x0a, 0xaf, 0x0e, 0x66, 0x0f, 0xe1, 0x0f, + 0x25, 0x0b, 0xed, 0x02, 0x10, 0xf7, 0xd1, 0xec, 0x1c, 0xe1, 0x44, 0xda, + 0x64, 0xdb, 0xaa, 0xe0, 0xa7, 0xea, 0x87, 0xef, 0xae, 0xf6, 0x68, 0xf9, + 0x99, 0xf6, 0x0d, 0xf3, 0x14, 0xed, 0xd8, 0xeb, 0x1a, 0xec, 0x0e, 0xea, + 0xbe, 0xe4, 0x4c, 0xe4, 0xc5, 0xe4, 0x9f, 0xe3, 0x7c, 0xe3, 0x05, 0xe3, + 0xc5, 0xe5, 0x87, 0xe8, 0x21, 0xea, 0x3c, 0xe8, 0xb2, 0xe5, 0x98, 0xe2, + 0xdd, 0xde, 0x96, 0xdb, 0xd9, 0xd4, 0x90, 0xd1, 0x57, 0xd2, 0xb5, 0xd6, + 0x04, 0xde, 0x35, 0xe6, 0x7a, 0xf2, 0x4a, 0x00, 0x7b, 0x0a, 0xac, 0x13, + 0x9b, 0x1b, 0x8d, 0x1e, 0xb9, 0x1e, 0x65, 0x1a, 0xed, 0x11, 0x09, 0x07, + 0xf7, 0xfa, 0xf9, 0xf3, 0x65, 0xf2, 0x1b, 0xf3, 0x74, 0xfa, 0x38, 0x06, + 0x8d, 0x0c, 0x3a, 0x0f, 0xe0, 0x0f, 0xa2, 0x0a, 0xb9, 0x00, 0x53, 0xf9, + 0x8c, 0xf7, 0x4f, 0xfa, 0xc5, 0xfe, 0xbe, 0x03, 0x25, 0x0a, 0xc8, 0x0d, + 0xa7, 0x0e, 0xc6, 0x0c, 0xc9, 0x08, 0x64, 0x04, 0x3c, 0xfe, 0x97, 0xf4, + 0x7d, 0xe8, 0x3e, 0xe0, 0xc0, 0xda, 0xf4, 0xd8, 0xac, 0xda, 0xb0, 0xd8, + 0xbf, 0xd1, 0x59, 0xc6, 0x1c, 0xbc, 0x39, 0xb7, 0x0e, 0xb6, 0x12, 0xbc, + 0x55, 0xc7, 0x77, 0xd1, 0xaa, 0xda, 0x54, 0xe4, 0xa8, 0xe9, 0x50, 0xe5, + 0x3d, 0xda, 0xf4, 0xc8, 0x24, 0xb9, 0x9d, 0xad, 0x15, 0xa6, 0x82, 0xa6, + 0x70, 0xa6, 0x05, 0xab, 0x08, 0xb5, 0xc5, 0xc0, 0xcd, 0xcf, 0x1d, 0xdd, + 0xa5, 0xe4, 0xaf, 0xe7, 0x47, 0xe9, 0xc5, 0xe4, 0x63, 0xdf, 0x6f, 0xda, + 0xd3, 0xd5, 0x13, 0xd6, 0x94, 0xd7, 0x64, 0xd6, 0x1c, 0xd8, 0x2a, 0xde, + 0x77, 0xe0, 0xdd, 0xe2, 0x3c, 0xe6, 0xe8, 0xef, 0x99, 0xf9, 0x27, 0xfb, + 0xf7, 0xfc, 0xa4, 0xfe, 0xab, 0xff, 0xab, 0xfd, 0x00, 0xfd, 0xab, 0xfe, + 0x67, 0x01, 0x63, 0x02, 0xd0, 0xff, 0x7b, 0x00, 0xf1, 0xff, 0x13, 0xfc, + 0x51, 0xfa, 0xae, 0xfa, 0xf3, 0xfb, 0x00, 0x03, 0x8b, 0x08, 0xb0, 0x0e, + 0x7c, 0x14, 0x68, 0x13, 0x89, 0x14, 0x73, 0x10, 0xb1, 0x0b, 0x3a, 0x0a, + 0xf6, 0x0c, 0xf4, 0x16, 0x8d, 0x1f, 0xa2, 0x28, 0x0c, 0x2f, 0x03, 0x32, + 0x7d, 0x2d, 0x83, 0x22, 0xbf, 0x17, 0xcd, 0x06, 0xc3, 0xf4, 0xf3, 0xe6, + 0xe9, 0xdf, 0xdb, 0xe0, 0x53, 0xe1, 0xf7, 0xe1, 0xa5, 0xe6, 0x1f, 0xec, + 0xec, 0xee, 0x84, 0xec, 0xfb, 0xe5, 0x77, 0xe4, 0x6c, 0xea, 0x33, 0xf1, + 0xdd, 0xf7, 0x48, 0xf9, 0x09, 0xf5, 0xcc, 0xf0, 0x2c, 0xec, 0x01, 0xe4, + 0xbd, 0xd6, 0x40, 0xcc, 0x95, 0xcb, 0xc4, 0xd4, 0x0b, 0xe2, 0x21, 0xf0, + 0xce, 0xff, 0xe3, 0x0e, 0x62, 0x19, 0xd3, 0x1c, 0xe7, 0x1b, 0x93, 0x15, + 0xfa, 0x0b, 0x24, 0x07, 0x7b, 0x03, 0x56, 0xfb, 0x11, 0xf3, 0x68, 0xf2, + 0x04, 0xf6, 0x6e, 0xf7, 0xb8, 0xfc, 0x0a, 0x05, 0xfd, 0x09, 0xd7, 0x0a, + 0x95, 0x08, 0x19, 0x05, 0x32, 0xfd, 0x8d, 0xf3, 0xa9, 0xed, 0x8b, 0xea, + 0xad, 0xe8, 0x5e, 0xea, 0x63, 0xf1, 0x39, 0xfb, 0x03, 0x07, 0xcb, 0x0e, + 0x7b, 0x10, 0xc5, 0x0f, 0x77, 0x0a, 0x19, 0xfe, 0xf6, 0xef, 0xa9, 0xe4, + 0x6b, 0xdd, 0xc1, 0xd9, 0x66, 0xdb, 0x6c, 0xe7, 0xd0, 0xf3, 0xcc, 0xfb, + 0x27, 0x02, 0x4d, 0x04, 0x20, 0x01, 0x46, 0xfb, 0x77, 0xf2, 0x73, 0xe4, + 0xb5, 0xdc, 0xf8, 0xdc, 0x84, 0xdd, 0xf9, 0xda, 0x28, 0xd9, 0xec, 0xdd, + 0xab, 0xe5, 0xd7, 0xef, 0x2a, 0xfa, 0xd2, 0x02, 0x6b, 0x04, 0xd6, 0x00, + 0x1b, 0xfb, 0xcb, 0xf1, 0x2a, 0xe9, 0x72, 0xe0, 0x02, 0xda, 0x2f, 0xd5, + 0x4c, 0xd2, 0x03, 0xcf, 0x2a, 0xca, 0x9b, 0xc8, 0x1f, 0xcb, 0xb8, 0xd1, + 0x27, 0xd9, 0x9a, 0xe3, 0x91, 0xef, 0xe6, 0xfc, 0x6a, 0x0b, 0x7b, 0x14, + 0x2e, 0x18, 0x07, 0x18, 0x16, 0x16, 0x60, 0x11, 0x8c, 0x0a, 0x85, 0x07, + 0x4d, 0x09, 0xd6, 0x09, 0x98, 0x07, 0x2b, 0x07, 0x07, 0x08, 0x1d, 0x0b, + 0x46, 0x0f, 0xbc, 0x0d, 0x97, 0x0c, 0xb0, 0x11, 0x6d, 0x19, 0xaf, 0x26, + 0x0d, 0x35, 0xa6, 0x3f, 0xbd, 0x47, 0x0d, 0x4b, 0x28, 0x4b, 0x1f, 0x49, + 0xce, 0x44, 0x52, 0x3e, 0xaa, 0x38, 0x7b, 0x30, 0xee, 0x1f, 0x40, 0x0d, + 0x77, 0xfc, 0xb6, 0xef, 0x01, 0xe8, 0xff, 0xe0, 0x1a, 0xdd, 0xef, 0xde, + 0xde, 0xdf, 0x71, 0xe0, 0xd2, 0xe3, 0x41, 0xea, 0x86, 0xf5, 0x9c, 0x01, + 0x06, 0x0b, 0x53, 0x13, 0xf1, 0x17, 0xcd, 0x11, 0x75, 0x05, 0x32, 0xfa, + 0x32, 0xeb, 0xd4, 0xd8, 0x33, 0xcb, 0x28, 0xc6, 0xfe, 0xc8, 0x5d, 0xd1, + 0xc8, 0xde, 0xf4, 0xee, 0xf1, 0xfa, 0x5d, 0x05, 0xab, 0x0f, 0xc6, 0x15, + 0xfb, 0x18, 0xeb, 0x1a, 0x94, 0x1e, 0xa2, 0x23, 0xb4, 0x26, 0xeb, 0x24, + 0xd1, 0x1f, 0xb8, 0x1a, 0x42, 0x16, 0xbc, 0x17, 0xc1, 0x1c, 0x73, 0x20, + 0x0a, 0x26, 0x50, 0x2f, 0xc9, 0x39, 0x02, 0x40, 0x01, 0x42, 0x54, 0x45, + 0xa6, 0x48, 0x82, 0x45, 0xf2, 0x3d, 0xfd, 0x33, 0xaf, 0x29, 0xb3, 0x25, + 0xe4, 0x23, 0x08, 0x24, 0xfc, 0x26, 0xb4, 0x26, 0xf2, 0x22, 0x30, 0x19, + 0x1e, 0x0b, 0x70, 0xfb, 0xf1, 0xec, 0x0e, 0xe4, 0xd8, 0xe2, 0x4a, 0xe9, + 0x24, 0xf0, 0x25, 0xf4, 0x99, 0xf5, 0x34, 0xf6, 0x76, 0xf5, 0x8a, 0xf1, + 0x59, 0xed, 0x29, 0xe9, 0xad, 0xe8, 0x98, 0xe6, 0x2f, 0xe1, 0x1c, 0xe0, + 0xe2, 0xe0, 0xcb, 0xe1, 0xe2, 0xe1, 0x62, 0xe4, 0x81, 0xec, 0xe8, 0xf4, + 0xab, 0xfb, 0x21, 0x03, 0x66, 0x0c, 0x95, 0x16, 0xcb, 0x1d, 0xe4, 0x23, + 0x49, 0x2a, 0xbd, 0x2d, 0x20, 0x32, 0x5a, 0x32, 0x34, 0x2d, 0x02, 0x29, + 0x74, 0x1e, 0x17, 0x16, 0x76, 0x16, 0x9c, 0x15, 0x55, 0x19, 0xfa, 0x22, + 0x68, 0x2c, 0x94, 0x35, 0xe4, 0x39, 0xcb, 0x38, 0x9a, 0x35, 0xd1, 0x31, + 0xdc, 0x2f, 0x73, 0x2a, 0xea, 0x22, 0xc4, 0x20, 0xd4, 0x24, 0x2f, 0x2a, + 0xdf, 0x2d, 0x84, 0x34, 0x36, 0x39, 0x74, 0x39, 0x62, 0x35, 0xe3, 0x2f, + 0xfd, 0x32, 0xe8, 0x36, 0x73, 0x35, 0x05, 0x33, 0x04, 0x31, 0xb9, 0x2c, + 0x6e, 0x28, 0x57, 0x28, 0x6d, 0x2a, 0x93, 0x2e, 0xe4, 0x2e, 0x0b, 0x2d, + 0xe3, 0x2d, 0xbe, 0x29, 0x11, 0x20, 0x09, 0x1a, 0xa5, 0x14, 0xb0, 0x09, + 0xe1, 0xfe, 0xc8, 0xf6, 0xb1, 0xf0, 0xf7, 0xec, 0xa5, 0xee, 0xff, 0xf3, + 0xa4, 0xf6, 0x3e, 0xf6, 0x9f, 0xf3, 0x08, 0xee, 0xf4, 0xe5, 0x38, 0xe2, + 0x2b, 0xe3, 0x7f, 0xe6, 0x93, 0xec, 0xe2, 0xf4, 0x38, 0x00, 0x21, 0x06, + 0x95, 0x08, 0xa6, 0x0c, 0x8f, 0x0a, 0xbc, 0x01, 0x82, 0xf7, 0x3c, 0xed, + 0x1e, 0xe3, 0x15, 0xe0, 0x3d, 0xe3, 0x5e, 0xe9, 0x46, 0xf9, 0x3c, 0x0b, + 0x7f, 0x1a, 0x32, 0x2a, 0x2a, 0x33, 0x98, 0x36, 0x08, 0x35, 0x3f, 0x2d, + 0x06, 0x26, 0xa4, 0x1e, 0xae, 0x15, 0xa4, 0x0e, 0x20, 0x0c, 0x8d, 0x0d, + 0x2e, 0x11, 0x47, 0x15, 0xf3, 0x16, 0x47, 0x19, 0x17, 0x1b, 0xcc, 0x19, + 0x30, 0x18, 0xab, 0x14, 0xd5, 0x11, 0x6f, 0x11, 0x53, 0x0f, 0xee, 0x09, + 0x24, 0x02, 0x5d, 0xfb, 0xfe, 0xf7, 0xb4, 0xf7, 0x09, 0xf8, 0xc0, 0xf6, + 0xf9, 0xf5, 0xea, 0xf6, 0x79, 0xf4, 0x23, 0xef, 0x54, 0xed, 0x5c, 0xef, + 0xb1, 0xf2, 0xc8, 0xf7, 0x19, 0xfd, 0x5c, 0x01, 0xdf, 0x06, 0xde, 0x0a, + 0xcd, 0x0f, 0x75, 0x18, 0x32, 0x1d, 0xbc, 0x1e, 0x7e, 0x1d, 0x9e, 0x12, + 0x16, 0x04, 0x20, 0xf9, 0x5f, 0xf2, 0xe5, 0xf1, 0x21, 0xf2, 0xe7, 0xf7, + 0x5b, 0x04, 0x30, 0x0c, 0xe2, 0x11, 0x1f, 0x17, 0x1e, 0x20, 0x83, 0x2b, + 0x22, 0x31, 0xf2, 0x34, 0x14, 0x37, 0xe8, 0x37, 0x8e, 0x3a, 0x51, 0x3a, + 0x78, 0x38, 0x2d, 0x38, 0x60, 0x34, 0x52, 0x2d, 0x11, 0x29, 0xeb, 0x27, + 0x8f, 0x28, 0x92, 0x2a, 0xfd, 0x2c, 0x59, 0x2e, 0x47, 0x2f, 0x73, 0x33, + 0xb0, 0x35, 0x72, 0x32, 0x81, 0x2b, 0x6d, 0x22, 0xbd, 0x1e, 0xe0, 0x1c, + 0xed, 0x1a, 0xfc, 0x1b, 0x9d, 0x1c, 0xd5, 0x1f, 0xd3, 0x1f, 0x85, 0x18, + 0xd1, 0x11, 0xc2, 0x0e, 0x80, 0x0e, 0x39, 0x0d, 0xec, 0x0c, 0xdd, 0x0f, + 0x71, 0x12, 0x0d, 0x12, 0x03, 0x10, 0x4b, 0x0f, 0x71, 0x0a, 0x8f, 0x04, + 0x34, 0x02, 0x7a, 0xff, 0xec, 0xfa, 0x41, 0xf6, 0x1d, 0xf5, 0x32, 0xf5, + 0x28, 0xf6, 0x75, 0xf3, 0xcd, 0xf2, 0x8f, 0xf6, 0x0d, 0xf5, 0x59, 0xf4, + 0xcf, 0xf3, 0xe2, 0xf4, 0x69, 0xf6, 0x2a, 0xf1, 0xeb, 0xed, 0x71, 0xf1, + 0xf0, 0xf1, 0x9b, 0xf0, 0x7d, 0xf4, 0x4f, 0xf8, 0x6b, 0xfa, 0x2b, 0xf9, + 0xd2, 0xf7, 0x9f, 0xf9, 0xca, 0xf9, 0xf0, 0xf8, 0x22, 0xfb, 0x80, 0x00, + 0x32, 0x07, 0x05, 0x10, 0x78, 0x17, 0x37, 0x1d, 0x90, 0x21, 0x6a, 0x24, + 0xad, 0x24, 0x19, 0x20, 0xe9, 0x18, 0xec, 0x13, 0xe7, 0x0e, 0x81, 0x07, + 0x39, 0x05, 0x85, 0x06, 0x8a, 0x08, 0x53, 0x0b, 0x0e, 0x0d, 0x7b, 0x0f, + 0x83, 0x11, 0xb9, 0x11, 0xde, 0x14, 0x29, 0x1b, 0x1d, 0x1d, 0xc9, 0x18, + 0x3d, 0x0d, 0x60, 0x00, 0xba, 0xf8, 0x98, 0xf4, 0x46, 0xf5, 0x1f, 0xfb, + 0x13, 0x03, 0xba, 0x08, 0x13, 0x0b, 0x83, 0x0b, 0x6f, 0x0a, 0x84, 0x07, + 0x63, 0x00, 0x8f, 0xf7, 0x16, 0xf3, 0x41, 0xef, 0x07, 0xef, 0xa5, 0xf4, + 0xca, 0xfa, 0xcc, 0x02, 0x5b, 0x0a, 0xdd, 0x11, 0xbb, 0x18, 0x2f, 0x1b, + 0xf7, 0x18, 0x15, 0x16, 0xa3, 0x11, 0xbe, 0x0d, 0x93, 0x0d, 0x9d, 0x09, + 0x70, 0x04, 0x39, 0x01, 0xf4, 0xff, 0xc7, 0xfe, 0x8d, 0xf9, 0x9b, 0xf6, + 0xa8, 0xf7, 0xb3, 0xf7, 0xd5, 0xf6, 0xd0, 0xf9, 0x01, 0x01, 0xf2, 0x05, + 0x71, 0x09, 0xa4, 0x0d, 0x95, 0x10, 0x73, 0x11, 0x78, 0x0d, 0x7f, 0x08, + 0xb5, 0xfe, 0xba, 0xf2, 0x6f, 0xef, 0x5a, 0xf0, 0x4c, 0xf5, 0x99, 0xfc, + 0x08, 0x02, 0x04, 0x05, 0xfa, 0x03, 0x63, 0xfd, 0xd8, 0xf4, 0xc3, 0xf1, + 0x9c, 0xf2, 0xb4, 0xf4, 0xb8, 0xf9, 0xe6, 0xff, 0x1c, 0x07, 0x9b, 0x0e, + 0x31, 0x12, 0x99, 0x12, 0x9f, 0x0e, 0xab, 0x07, 0x2e, 0x01, 0xa5, 0xfb, + 0x03, 0xf7, 0x96, 0xf7, 0x35, 0xfe, 0xbf, 0x02, 0x15, 0x07, 0x87, 0x0a, + 0x04, 0x0e, 0xa5, 0x10, 0xdd, 0x0b, 0x52, 0x04, 0xec, 0xfb, 0xc9, 0xf3, + 0xd6, 0xed, 0x71, 0xea, 0x0f, 0xec, 0x25, 0xf3, 0xb9, 0xf8, 0xe1, 0xfe, + 0x51, 0x0b, 0x3d, 0x16, 0xf3, 0x19, 0xfa, 0x16, 0x53, 0x12, 0xd6, 0x0d, + 0xf2, 0x05, 0x25, 0xfb, 0xc3, 0xf5, 0x60, 0xf6, 0x52, 0xf8, 0x9f, 0xfc, + 0xd2, 0xfc, 0x41, 0xf9, 0x81, 0xf7, 0x01, 0xf7, 0x41, 0xfa, 0x64, 0xfc, + 0xbf, 0xf8, 0x10, 0xf4, 0xe3, 0xf0, 0xcf, 0xf0, 0x86, 0xf0, 0x7b, 0xee, + 0xf6, 0xeb, 0x84, 0xeb, 0xe9, 0xed, 0x9a, 0xed, 0xd3, 0xec, 0x11, 0xee, + 0x1c, 0xf2, 0xb0, 0xf8, 0xf9, 0xfd, 0x30, 0xff, 0x09, 0xfd, 0x02, 0xf9, + 0x81, 0xf5, 0x6d, 0xf4, 0xe7, 0xf3, 0x43, 0xf7, 0x07, 0xfa, 0xa0, 0xfc, + 0x7c, 0xfe, 0x37, 0xfb, 0x01, 0xf8, 0x59, 0xf5, 0xb8, 0xf7, 0x45, 0xfa, + 0x7d, 0xfa, 0x88, 0xfe, 0x33, 0x04, 0xdb, 0x09, 0x16, 0x0a, 0xf7, 0x09, + 0x28, 0x0d, 0x3c, 0x08, 0x44, 0xfc, 0xae, 0xf4, 0xa3, 0xf6, 0x98, 0xff, + 0xba, 0x08, 0x0d, 0x11, 0x56, 0x17, 0x97, 0x18, 0xd7, 0x11, 0x8f, 0x08, + 0x44, 0x07, 0xbf, 0x07, 0x03, 0x06, 0xf0, 0x04, 0x2f, 0x05, 0x91, 0x04, + 0x48, 0x01, 0xa9, 0xff, 0x40, 0xff, 0x12, 0xff, 0x29, 0x00, 0x6b, 0x04, + 0x78, 0x0b, 0x95, 0x11, 0xd8, 0x14, 0x56, 0x15, 0xad, 0x12, 0x99, 0x0a, + 0xec, 0xfe, 0xc3, 0xf2, 0x33, 0xe5, 0xd1, 0xd7, 0x5b, 0xd0, 0xd2, 0xd1, + 0xc5, 0xd6, 0xf4, 0xd9, 0xdb, 0xdb, 0x0e, 0xde, 0xfa, 0xe0, 0xf4, 0xdf, + 0xe1, 0xda, 0xda, 0xd7, 0x1f, 0xd8, 0x62, 0xda, 0x0f, 0xde, 0x31, 0xe1, + 0x8d, 0xe2, 0x1f, 0xe5, 0x2d, 0xea, 0x69, 0xec, 0x9c, 0xe9, 0x17, 0xe5, + 0x69, 0xe0, 0x38, 0xdc, 0x3d, 0xdb, 0x5b, 0xdb, 0x06, 0xdb, 0x79, 0xdd, + 0x78, 0xe1, 0x85, 0xe4, 0x24, 0xe8, 0x1d, 0xec, 0x60, 0xf0, 0x47, 0xf3, + 0xce, 0xf1, 0xfa, 0xf0, 0xa7, 0xf2, 0x33, 0xf5, 0x20, 0xf7, 0x45, 0xf4, + 0x6c, 0xef, 0x98, 0xec, 0x70, 0xe9, 0x17, 0xe5, 0x08, 0xe3, 0x90, 0xe5, + 0x0d, 0xeb, 0x6d, 0xf0, 0xaa, 0xf1, 0x01, 0xf1, 0xd8, 0xf0, 0x90, 0xf0, + 0x8c, 0xf2, 0x72, 0xee, 0x91, 0xe3, 0x4f, 0xdf, 0xc9, 0xdd, 0x33, 0xdc, + 0x3d, 0xde, 0xa5, 0xe1, 0xed, 0xe9, 0xc1, 0xf2, 0xb9, 0xf5, 0xaa, 0xf3, + 0x98, 0xec, 0x48, 0xe5, 0x35, 0xdf, 0x9f, 0xd8, 0xd2, 0xd3, 0x14, 0xd2, + 0x6a, 0xd2, 0x31, 0xd2, 0x62, 0xd2, 0x96, 0xd4, 0x3b, 0xd7, 0x9b, 0xd9, + 0xb3, 0xdd, 0xd6, 0xe2, 0x4e, 0xe7, 0x63, 0xec, 0xb0, 0xf2, 0xa2, 0xf7, + 0x95, 0xfb, 0x0e, 0x00, 0x24, 0x01, 0xb8, 0xfd, 0x8e, 0xf8, 0xed, 0xf2, + 0x23, 0xef, 0x09, 0xee, 0x12, 0xed, 0x4c, 0xee, 0xc3, 0xf2, 0xe6, 0xf5, + 0x59, 0xf8, 0x72, 0xfb, 0x61, 0x00, 0xba, 0x04, 0x51, 0x05, 0xd4, 0x07, + 0xb1, 0x09, 0x60, 0x06, 0x19, 0x01, 0xd3, 0xfe, 0x48, 0xff, 0x2a, 0x00, + 0xeb, 0x05, 0x48, 0x0f, 0x96, 0x19, 0xad, 0x1f, 0xd0, 0x1c, 0x9d, 0x18, + 0x06, 0x13, 0x76, 0x09, 0x0b, 0x01, 0xa3, 0xfb, 0x5d, 0xf8, 0xad, 0xf6, + 0xc2, 0xf8, 0x89, 0xfd, 0x78, 0x01, 0xcf, 0x03, 0x25, 0x05, 0xb4, 0x04, + 0x87, 0xfe, 0xe3, 0xf4, 0x82, 0xeb, 0x0a, 0xe1, 0x0f, 0xd7, 0x64, 0xd0, + 0x89, 0xce, 0xd6, 0xd2, 0x44, 0xdb, 0x48, 0xe4, 0x31, 0xef, 0x40, 0xfa, + 0xdf, 0x00, 0x1c, 0x01, 0x56, 0xfa, 0x72, 0xf2, 0x46, 0xeb, 0x8c, 0xe2, + 0xd8, 0xdc, 0x3a, 0xd8, 0x59, 0xd4, 0x36, 0xd5, 0x5f, 0xd4, 0x03, 0xd3, + 0xfe, 0xd4, 0xc7, 0xd5, 0x6d, 0xd4, 0xce, 0xd4, 0x6c, 0xd9, 0xa6, 0xe1, + 0x3a, 0xef, 0x25, 0xfd, 0xd1, 0x04, 0x42, 0x05, 0xef, 0x00, 0xe3, 0xfd, + 0x49, 0xfb, 0xf2, 0xf3, 0xe1, 0xeb, 0xcd, 0xeb, 0x13, 0xee, 0x95, 0xeb, + 0x15, 0xe8, 0x14, 0xe7, 0xe6, 0xe9, 0x20, 0xee, 0x03, 0xf1, 0x29, 0xf0, + 0xe3, 0xed, 0xd8, 0xee, 0xd3, 0xf0, 0xff, 0xf2, 0x1c, 0xf5, 0x06, 0xf8, + 0x81, 0xfe, 0x2a, 0x06, 0xc6, 0x0a, 0xd7, 0x09, 0xdc, 0x06, 0x4f, 0x05, + 0xf9, 0x04, 0xe1, 0x05, 0xdd, 0x04, 0x5a, 0x00, 0xf5, 0xf8, 0xfb, 0xf0, + 0x08, 0xed, 0xf7, 0xeb, 0x83, 0xea, 0x75, 0xeb, 0x27, 0xf0, 0x89, 0xf4, + 0x8b, 0xf6, 0xe5, 0xf7, 0xf3, 0xfa, 0xe4, 0xfd, 0x23, 0xfb, 0x62, 0xf4, + 0xdc, 0xee, 0xa6, 0xe7, 0xa3, 0xde, 0xaf, 0xd8, 0x53, 0xd6, 0x76, 0xd6, + 0x89, 0xd8, 0xd8, 0xd9, 0x76, 0xdb, 0xc1, 0xe1, 0x13, 0xe7, 0x4e, 0xea, + 0xed, 0xed, 0x1c, 0xee, 0x87, 0xe8, 0x01, 0xe1, 0x5d, 0xde, 0x9d, 0xda, + 0x3f, 0xd3, 0x2c, 0xcd, 0x1f, 0xca, 0x3a, 0xcb, 0xa4, 0xcb, 0xe4, 0xcd, + 0xde, 0xd5, 0xa0, 0xe1, 0x8e, 0xee, 0xfc, 0xfa, 0x07, 0x09, 0x9f, 0x0e, + 0xcf, 0x07, 0xce, 0xfc, 0xc6, 0xf0, 0x09, 0xe8, 0xa4, 0xe0, 0x01, 0xdb, + 0x51, 0xdd, 0x7d, 0xe6, 0x8f, 0xf4, 0xe7, 0x04, 0xa5, 0x16, 0xf4, 0x28, + 0x40, 0x34, 0xc8, 0x33, 0xae, 0x2f, 0x04, 0x29, 0xf2, 0x19, 0x3b, 0x0f, + 0x53, 0x0e, 0x4f, 0x10, 0x67, 0x16, 0x01, 0x1c, 0xca, 0x1b, 0x35, 0x19, + 0xd4, 0x13, 0x1f, 0x0c, 0x46, 0x07, 0x34, 0x02, 0xae, 0xfb, 0x7d, 0xf9, + 0x16, 0xf7, 0x22, 0xf6, 0xe2, 0xfb, 0x20, 0x03, 0xef, 0x09, 0xad, 0x0f, + 0xc5, 0x15, 0x8e, 0x18, 0x36, 0x15, 0xe1, 0x0d, 0x4c, 0x04, 0x38, 0xfd, + 0xc3, 0xf6, 0x2a, 0xf1, 0xcd, 0xed, 0xb5, 0xea, 0x00, 0xea, 0xec, 0xed, + 0xe1, 0xf2, 0x1a, 0xf8, 0xe9, 0xfd, 0xfb, 0xff, 0x04, 0x02, 0x4f, 0x04, + 0x30, 0x08, 0x8e, 0x0b, 0xa4, 0x0c, 0x82, 0x13, 0xb5, 0x17, 0xda, 0x14, + 0xbb, 0x0d, 0x0a, 0x06, 0x0d, 0x02, 0x12, 0xfd, 0xdb, 0xf7, 0x22, 0xf4, + 0x99, 0xf4, 0x27, 0xfa, 0xa5, 0x01, 0x6b, 0x0b, 0x4a, 0x15, 0x18, 0x1a, + 0xef, 0x17, 0x89, 0x12, 0xbb, 0x0c, 0x5b, 0x09, 0x9c, 0x06, 0x42, 0x03, + 0x3e, 0xff, 0xe2, 0xfa, 0xe4, 0xf9, 0xf6, 0xf8, 0x2b, 0xf8, 0x68, 0xf7, + 0x3d, 0xf6, 0xd9, 0xf7, 0xa3, 0xf8, 0xa7, 0xf9, 0xa9, 0xfd, 0x30, 0x02, + 0x18, 0x04, 0x23, 0x06, 0xcf, 0x06, 0xdf, 0x01, 0x40, 0xfd, 0x5e, 0xf5, + 0x15, 0xee, 0x93, 0xed, 0x95, 0xec, 0x2e, 0xee, 0x5a, 0xf6, 0xb4, 0x00, + 0xf9, 0x08, 0xda, 0x0b, 0x23, 0x09, 0x68, 0x05, 0x93, 0x00, 0x8b, 0xfb, + 0x0e, 0xfb, 0x02, 0xfc, 0x1b, 0xff, 0x6b, 0x03, 0x7d, 0x04, 0x97, 0x05, + 0x0e, 0x09, 0x67, 0x0b, 0x55, 0x0a, 0x70, 0x06, 0x7e, 0x04, 0xca, 0x06, + 0xc1, 0x06, 0xe6, 0x05, 0xdd, 0x05, 0x7e, 0x03, 0xff, 0x00, 0x07, 0xff, + 0x4a, 0xfc, 0x23, 0xf8, 0xf9, 0xf6, 0xeb, 0xfd, 0x0a, 0x0b, 0x10, 0x19, + 0x3d, 0x26, 0x66, 0x33, 0xce, 0x3c, 0xc8, 0x3e, 0x8a, 0x3a, 0x4d, 0x32, + 0x98, 0x27, 0x6f, 0x1b, 0x1c, 0x11, 0xf1, 0x0c, 0xea, 0x0f, 0x56, 0x18, + 0x57, 0x22, 0xe7, 0x2a, 0x8d, 0x32, 0x6f, 0x38, 0x96, 0x3a, 0x0f, 0x3a, + 0x54, 0x38, 0xeb, 0x31, 0x1d, 0x28, 0x36, 0x21, 0x65, 0x19, 0x5c, 0x12, + 0xfa, 0x10, 0xed, 0x10, 0xa1, 0x11, 0x46, 0x10, 0xfd, 0x0b, 0x9a, 0x04, + 0x90, 0xfb, 0x3a, 0xf8, 0xf0, 0xf9, 0xf4, 0xfd, 0x25, 0x02, 0x94, 0x08, + 0x7e, 0x0f, 0xa6, 0x10, 0xf7, 0x0f, 0xd6, 0x0b, 0x01, 0x04, 0x6a, 0xfd, + 0x68, 0xf6, 0xa1, 0xf1, 0x08, 0xef, 0x7f, 0xef, 0x74, 0xf4, 0x18, 0xfa, + 0x89, 0x02, 0x61, 0x0d, 0xcf, 0x14, 0x41, 0x17, 0xb4, 0x14, 0x81, 0x0f, + 0xcb, 0x0b, 0x97, 0x06, 0x7c, 0x04, 0xe3, 0x08, 0x3b, 0x0a, 0x28, 0x0a, + 0xb7, 0x09, 0x60, 0x09, 0x78, 0x09, 0x70, 0x09, 0x07, 0x0d, 0x74, 0x12, + 0xda, 0x18, 0x05, 0x1b, 0x98, 0x19, 0x5a, 0x19, 0xb7, 0x18, 0x3d, 0x18, + 0x3a, 0x1b, 0x37, 0x20, 0x68, 0x22, 0xb6, 0x20, 0xa9, 0x1a, 0xae, 0x15, + 0xd5, 0x11, 0x7c, 0x0c, 0x5e, 0x0b, 0x6d, 0x0b, 0x43, 0x0a, 0xf3, 0x0e, + 0x60, 0x18, 0x96, 0x21, 0xca, 0x27, 0x96, 0x26, 0xcf, 0x22, 0xee, 0x21, + 0xea, 0x1c, 0xa8, 0x14, 0x6c, 0x11, 0xe2, 0x0f, 0x93, 0x0f, 0x8a, 0x0e, + 0x90, 0x0a, 0x1f, 0x08, 0x40, 0x04, 0xc2, 0xfd, 0x4e, 0xfa, 0x5f, 0xfa, + 0xc0, 0xf8, 0x03, 0xf6, 0x4f, 0xf2, 0xe6, 0xec, 0xd5, 0xe9, 0x6b, 0xea, + 0xdd, 0xf0, 0x7f, 0xf9, 0x4d, 0x02, 0xe8, 0x0e, 0x1b, 0x19, 0xb1, 0x1c, + 0xe9, 0x1b, 0xce, 0x18, 0x8f, 0x19, 0xc2, 0x17, 0x07, 0x0c, 0x61, 0xff, + 0x1a, 0xf4, 0x69, 0xeb, 0x6e, 0xe8, 0xdb, 0xeb, 0xca, 0xf3, 0xfb, 0xfe, + 0x5f, 0x0a, 0x55, 0x11, 0xec, 0x17, 0xb9, 0x1d, 0x9c, 0x1d, 0x7f, 0x19, + 0xf2, 0x16, 0x39, 0x15, 0x5e, 0x12, 0x34, 0x10, 0xa0, 0x10, 0x15, 0x14, + 0x85, 0x17, 0x54, 0x18, 0x41, 0x1a, 0xa1, 0x1e, 0x1d, 0x22, 0x2c, 0x26, + 0xd0, 0x27, 0x72, 0x28, 0x9c, 0x29, 0xd9, 0x25, 0x5c, 0x21, 0x00, 0x1d, + 0x7d, 0x18, 0x53, 0x17, 0xaf, 0x19, 0x8e, 0x1f, 0xf2, 0x25, 0x7b, 0x28, + 0xaf, 0x27, 0xab, 0x22, 0xbe, 0x19, 0x3e, 0x14, 0xd4, 0x12, 0xe6, 0x11, + 0xfd, 0x12, 0x40, 0x14, 0x32, 0x15, 0xa7, 0x16, 0xac, 0x15, 0xfb, 0x14, + 0x85, 0x14, 0x47, 0x0f, 0xc9, 0x06, 0x5d, 0x00, 0x20, 0xfb, 0x79, 0xf8, + 0x59, 0xfb, 0x52, 0x01, 0xc0, 0x0b, 0x2c, 0x16, 0x30, 0x1c, 0x69, 0x1d, + 0x1a, 0x19, 0x60, 0x15, 0x07, 0x12, 0x69, 0x0c, 0xfe, 0x0a, 0x1a, 0x0d, + 0x53, 0x0b, 0x50, 0x08, 0x1c, 0x07, 0x48, 0x07, 0xf5, 0x07, 0x08, 0x09, + 0x2c, 0x09, 0x63, 0x07, 0xb6, 0x08, 0xfa, 0x0a, 0x31, 0x0c, 0x32, 0x0f, + 0x97, 0x14, 0xcc, 0x18, 0x16, 0x19, 0xdf, 0x1a, 0x37, 0x1e, 0xab, 0x1c, + 0xdd, 0x15, 0x07, 0x11, 0x7a, 0x10, 0xb5, 0x11, 0xc9, 0x12, 0xbb, 0x12, + 0x9b, 0x15, 0x8b, 0x1c, 0x54, 0x1f, 0x7a, 0x1c, 0x32, 0x1d, 0x9e, 0x22, + 0xd0, 0x25, 0x44, 0x25, 0xbf, 0x24, 0xbc, 0x26, 0x5c, 0x27, 0xdb, 0x22, + 0x84, 0x1d, 0xe7, 0x17, 0xdd, 0x12, 0x50, 0x10, 0x90, 0x0c, 0x7e, 0x0b, + 0xba, 0x0a, 0xc2, 0x06, 0xa3, 0x04, 0x39, 0x04, 0xa4, 0x04, 0x0b, 0x07, + 0xf6, 0x08, 0x6c, 0x08, 0x97, 0x05, 0x1c, 0x00, 0x23, 0xfb, 0x6b, 0xf5, + 0xe6, 0xf0, 0x84, 0xef, 0xca, 0xec, 0xd0, 0xe9, 0xeb, 0xe5, 0x7a, 0xe2, + 0x00, 0xe0, 0xc7, 0xdd, 0xda, 0xdd, 0x6c, 0xe3, 0xf8, 0xea, 0x25, 0xec, + 0xf8, 0xeb, 0x3d, 0xea, 0x1d, 0xe5, 0xce, 0xe1, 0x52, 0xde, 0x4a, 0xd9, + 0xa3, 0xd5, 0xb2, 0xd6, 0x32, 0xdc, 0xf3, 0xe4, 0x91, 0xed, 0x33, 0xf6, + 0xaf, 0x01, 0x28, 0x09, 0x99, 0x09, 0xcf, 0x03, 0x6e, 0xfb, 0xa2, 0xf7, + 0x4c, 0xf4, 0xb1, 0xef, 0x44, 0xee, 0xd3, 0xee, 0xef, 0xf1, 0xd3, 0xf8, + 0xde, 0x01, 0xb5, 0x0d, 0xf6, 0x1b, 0x4e, 0x25, 0x2a, 0x28, 0xc3, 0x25, + 0x57, 0x20, 0x0a, 0x1b, 0x62, 0x0e, 0x2d, 0x00, 0x7b, 0xfb, 0x26, 0xf9, + 0xd1, 0xf4, 0x55, 0xf5, 0xda, 0xfc, 0xe1, 0x03, 0x54, 0x0a, 0xa4, 0x12, + 0x88, 0x18, 0x93, 0x1a, 0x9b, 0x19, 0x92, 0x15, 0x78, 0x0d, 0xd4, 0x03, + 0x26, 0xfc, 0xd6, 0xf4, 0x27, 0xef, 0xbc, 0xef, 0x65, 0xf4, 0x7d, 0xf7, + 0xf0, 0xf7, 0xec, 0xf7, 0x44, 0xf9, 0xbd, 0xfc, 0xef, 0xfe, 0x54, 0xff, + 0x17, 0x01, 0xf1, 0x03, 0x77, 0x07, 0x0b, 0x0b, 0x47, 0x0c, 0xba, 0x09, + 0x8b, 0x05, 0x40, 0x02, 0xbe, 0x01, 0x7a, 0xff, 0xc6, 0xf7, 0xfc, 0xf4, + 0x4a, 0xf5, 0x70, 0xf4, 0xd1, 0xf9, 0x5e, 0x05, 0x10, 0x10, 0x9b, 0x15, + 0x84, 0x1a, 0xca, 0x21, 0xf2, 0x26, 0x49, 0x25, 0x2a, 0x23, 0x33, 0x23, + 0xba, 0x1b, 0x51, 0x11, 0x9f, 0x08, 0xdd, 0x01, 0x38, 0x00, 0x1f, 0xfe, + 0xfc, 0xfc, 0xfa, 0xff, 0x0c, 0xfe, 0xda, 0xfa, 0xf8, 0xfc, 0x71, 0xfe, + 0x35, 0xfd, 0xd7, 0xfa, 0x3e, 0xfb, 0xc0, 0x00, 0xfc, 0x05, 0x19, 0x05, + 0x8f, 0x04, 0x25, 0x05, 0xac, 0x01, 0xcb, 0xfd, 0x67, 0xfa, 0xfd, 0xfc, + 0x63, 0x03, 0xd9, 0x05, 0x2c, 0x07, 0x4c, 0x03, 0x42, 0xfb, 0x92, 0xf6, + 0x49, 0xf7, 0x8d, 0xfa, 0x0e, 0xfe, 0xb9, 0x01, 0x67, 0x01, 0xcb, 0x02, + 0x89, 0x07, 0x6b, 0x08, 0x6e, 0x07, 0x2b, 0x03, 0x7a, 0xfc, 0xab, 0xf7, + 0x8f, 0xf4, 0x8b, 0xef, 0xfc, 0xe7, 0x9f, 0xe4, 0x62, 0xe9, 0xbb, 0xf4, + 0x20, 0xfe, 0x56, 0x00, 0x50, 0xff, 0x53, 0xff, 0x6c, 0xff, 0x2e, 0xfc, + 0x96, 0xf7, 0x31, 0xf4, 0x3a, 0xf0, 0x32, 0xeb, 0x7d, 0xe6, 0x84, 0xdb, + 0xd3, 0xce, 0x7a, 0xcd, 0xcc, 0xd4, 0xc9, 0xe0, 0xb1, 0xee, 0x8e, 0xfa, + 0x23, 0x06, 0x51, 0x0b, 0x0f, 0x08, 0x5e, 0x07, 0x02, 0x04, 0xa3, 0xfd, + 0xf7, 0xff, 0xa3, 0x08, 0x60, 0x0e, 0x39, 0x0b, 0x24, 0x09, 0x33, 0x0f, + 0xd3, 0x15, 0x2c, 0x15, 0x01, 0x13, 0xe1, 0x12, 0xa4, 0x11, 0x81, 0x10, + 0xca, 0x09, 0x65, 0x02, 0x17, 0xff, 0x90, 0xfe, 0x67, 0x05, 0xae, 0x10, + 0xbb, 0x14, 0x90, 0x0f, 0x52, 0x0a, 0x23, 0x0a, 0xde, 0x0e, 0xa4, 0x0f, + 0x02, 0x0a, 0xb0, 0x04, 0x68, 0x04, 0x2c, 0x05, 0xf0, 0x00, 0xbe, 0xfb, + 0x40, 0xfc, 0xf0, 0xfe, 0x4c, 0xfb, 0x20, 0xf5, 0x6a, 0xeb, 0x41, 0xe4, + 0x28, 0xe8, 0xb5, 0xea, 0x4b, 0xe8, 0xb7, 0xea, 0xc4, 0xf1, 0xf1, 0xf6, + 0x1e, 0xf9, 0xc3, 0xf5, 0xf5, 0xf2, 0x23, 0xf3, 0x27, 0xee, 0x24, 0xea, + 0x57, 0xe8, 0x31, 0xe5, 0xf7, 0xe7, 0xae, 0xeb, 0x25, 0xf1, 0xdb, 0xf6, + 0xc0, 0xf5, 0xe3, 0xf8, 0xe5, 0xfa, 0x74, 0xfc, 0xe0, 0xfd, 0x90, 0xfe, + 0xea, 0x04, 0x3f, 0x05, 0x10, 0x08, 0x1d, 0x0c, 0xcf, 0x0d, 0xb9, 0x0d, + 0x1f, 0x06, 0x2c, 0x03, 0xde, 0x04, 0x1e, 0x04, 0xb1, 0x02, 0xbd, 0x00, + 0x9a, 0xfa, 0xf6, 0xf8, 0xef, 0xfc, 0xc9, 0x01, 0x5d, 0x04, 0xe8, 0xfb, + 0x45, 0xec, 0x54, 0xd9, 0x50, 0xcd, 0x28, 0xcb, 0x97, 0xca, 0x2e, 0xc7, + 0x34, 0xc6, 0x0e, 0xcd, 0x6b, 0xd2, 0x7a, 0xd3, 0xee, 0xd0, 0xf6, 0xce, + 0x94, 0xd0, 0x3c, 0xd7, 0x83, 0xe2, 0x43, 0xed, 0x18, 0xf8, 0x75, 0x02, + 0x50, 0x07, 0x5f, 0x07, 0x88, 0x07, 0x8f, 0x02, 0x56, 0xf9, 0x02, 0xf3, + 0xdc, 0xf3, 0x24, 0xf9, 0x05, 0xfe, 0xd7, 0x00, 0xb8, 0xf8, 0xad, 0xee, + 0xd9, 0xea, 0x66, 0xe7, 0x8b, 0xe5, 0x1d, 0xe5, 0x28, 0xe6, 0x36, 0xea, + 0x4b, 0xec, 0xdd, 0xe8, 0x91, 0xe5, 0x71, 0xe5, 0x67, 0xe8, 0x25, 0xec, + 0x96, 0xec, 0x4f, 0xec, 0xbd, 0xeb, 0x7a, 0xe6, 0x4f, 0xe0, 0x2e, 0xdb, + 0xff, 0xd7, 0xd2, 0xd8, 0x0a, 0xd9, 0xe6, 0xd9, 0xc5, 0xdb, 0xe2, 0xdd, + 0x82, 0xe2, 0xec, 0xe6, 0x5c, 0xe6, 0xc9, 0xe5, 0x93, 0xe9, 0xbe, 0xee, + 0x0a, 0xf3, 0xf4, 0xf1, 0x49, 0xf0, 0xe3, 0xf1, 0x16, 0xf5, 0x8d, 0xfa, + 0xe4, 0x00, 0xcf, 0x03, 0x7c, 0x02, 0x20, 0x01, 0xd1, 0xff, 0x90, 0x01, + 0x7b, 0x05, 0x69, 0x07, 0x70, 0x06, 0x6c, 0x00, 0x30, 0xf8, 0x4e, 0xf3, + 0xe8, 0xf2, 0x6e, 0xf8, 0x76, 0x00, 0xb5, 0x06, 0x54, 0x0d, 0x47, 0x10, + 0x22, 0x13, 0xf4, 0x17, 0x23, 0x1a, 0x71, 0x1a, 0x3d, 0x19, 0x75, 0x15, + 0xf5, 0x0d, 0x39, 0x05, 0xf4, 0xfb, 0xd5, 0xf8, 0xf5, 0xfb, 0xb2, 0xfb, + 0x06, 0xfb, 0x07, 0xfc, 0x2a, 0xfb, 0x2a, 0xfd, 0x80, 0x02, 0x64, 0x04, + 0x11, 0x03, 0x8c, 0xfe, 0xb8, 0xf8, 0x79, 0xf1, 0x83, 0xea, 0xd8, 0xe6, + 0x89, 0xe6, 0x11, 0xeb, 0xb6, 0xf1, 0x58, 0xf9, 0x9f, 0xfc, 0x20, 0xfd, + 0x63, 0xfe, 0x22, 0xfe, 0xe0, 0xff, 0xa1, 0x00, 0x27, 0x00, 0xe1, 0x00, + 0x49, 0x01, 0xf6, 0x00, 0x1c, 0x01, 0xc3, 0x02, 0x2f, 0x04, 0xb6, 0x05, + 0x34, 0x06, 0x41, 0x05, 0x8d, 0x02, 0x9c, 0xff, 0x4c, 0x00, 0x32, 0x01, + 0x5d, 0x01, 0x2b, 0x00, 0x0f, 0xfb, 0x3c, 0xf0, 0x71, 0xe5, 0xab, 0xdf, + 0x33, 0xdc, 0x43, 0xdd, 0x78, 0xe1, 0x8f, 0xe6, 0xd5, 0xea, 0x4b, 0xea, + 0xbb, 0xe4, 0x51, 0xdf, 0x11, 0xdd, 0xa3, 0xdc, 0xb1, 0xde, 0x55, 0xe1, + 0xc1, 0xe6, 0xc8, 0xed, 0xe3, 0xf2, 0xbf, 0xf5, 0x62, 0xf6, 0x25, 0xf7, + 0xf7, 0xf7, 0x62, 0xf6, 0x1c, 0xf3, 0x57, 0xf2, 0x4b, 0xf1, 0xca, 0xf1, + 0x64, 0xf1, 0x93, 0xec, 0x99, 0xe6, 0xd6, 0xdd, 0x8a, 0xd8, 0x79, 0xd9, + 0x29, 0xdb, 0x23, 0xdb, 0x09, 0xde, 0x08, 0xe3, 0x4c, 0xe4, 0x4d, 0xe1, + 0xee, 0xda, 0x02, 0xd7, 0x3b, 0xd8, 0x69, 0xd9, 0xab, 0xd8, 0x4d, 0xd9, + 0xda, 0xdc, 0xdc, 0xe2, 0x0a, 0xe6, 0xa5, 0xe6, 0xbd, 0xe7, 0xc5, 0xe6, + 0x50, 0xe3, 0xcb, 0xdf, 0x3b, 0xdf, 0x19, 0xe2, 0x0a, 0xe8, 0x2d, 0xef, + 0x08, 0xf6, 0x49, 0xf7, 0xba, 0xf3, 0xd6, 0xef, 0xe2, 0xe8, 0x83, 0xe4, + 0x72, 0xe5, 0x6b, 0xe9, 0xbf, 0xee, 0xe2, 0xf3, 0x87, 0xf8, 0x49, 0xfd, + 0xd4, 0xff, 0x88, 0xfe, 0x63, 0xfd, 0x31, 0xfd, 0xf2, 0xfb, 0x36, 0xf6, + 0x2b, 0xee, 0x7c, 0xe7, 0xd2, 0xe5, 0xb5, 0xea, 0x0b, 0xf0, 0x3e, 0xf7, + 0x93, 0x00, 0x9f, 0x07, 0xd0, 0x0b, 0x4c, 0x0b, 0xa5, 0x09, 0x88, 0x0c, + 0xb3, 0x11, 0x8e, 0x17, 0x0a, 0x1d, 0xc9, 0x1c, 0x2d, 0x16, 0x83, 0x10, + 0x38, 0x0e, 0x77, 0x0b, 0x3b, 0x08, 0x20, 0x06, 0x0f, 0x07, 0x01, 0x09, + 0x5d, 0x06, 0x20, 0x01, 0x41, 0xfe, 0x49, 0xff, 0x2b, 0x02, 0x2f, 0x04, + 0x49, 0x07, 0x80, 0x09, 0x2c, 0x06, 0x6b, 0x00, 0xa4, 0xfa, 0x9c, 0xf5, + 0x00, 0xf3, 0x33, 0xf4, 0x98, 0xf5, 0xad, 0xf3, 0xf1, 0xf3, 0x0c, 0xf7, + 0x54, 0xfb, 0xd8, 0xfc, 0x87, 0xfc, 0x02, 0x00, 0xec, 0xff, 0xed, 0xff, + 0x0a, 0x01, 0xdb, 0xfd, 0x85, 0xfe, 0x4f, 0x04, 0xd3, 0x0a, 0x2c, 0x0d, + 0x54, 0x08, 0x1c, 0x02, 0x13, 0xfe, 0x26, 0xfa, 0x13, 0xf9, 0xc3, 0xfc, + 0x7f, 0xff, 0xb6, 0x01, 0x70, 0x06, 0x48, 0x09, 0x76, 0x0a, 0x4b, 0x0d, + 0x64, 0x10, 0x2f, 0x14, 0x66, 0x14, 0x20, 0x12, 0x4b, 0x14, 0x34, 0x15, + 0x20, 0x13, 0xbf, 0x10, 0xb8, 0x0d, 0x8b, 0x0a, 0x4d, 0x08, 0x57, 0x09, + 0xef, 0x0b, 0xa5, 0x0e, 0x93, 0x13, 0xb5, 0x1d, 0x1b, 0x28, 0x62, 0x2c, + 0xed, 0x2c, 0x07, 0x2a, 0xb1, 0x24, 0xf9, 0x1f, 0xb5, 0x18, 0x32, 0x11, + 0xe2, 0x0b, 0x51, 0x07, 0xa0, 0x05, 0xc0, 0x04, 0x8d, 0x01, 0xd0, 0xfc, + 0x43, 0xf8, 0xcc, 0xf5, 0x1b, 0xf8, 0x4f, 0xfc, 0xc8, 0xfe, 0x7a, 0x03, + 0xf1, 0x06, 0x01, 0x07, 0x41, 0x06, 0x46, 0x03, 0x76, 0xff, 0x3d, 0xfc, + 0x31, 0xf7, 0xf4, 0xf0, 0x76, 0xed, 0x9e, 0xec, 0xcc, 0xef, 0x97, 0xf5, + 0x03, 0xf8, 0x4e, 0xf9, 0x97, 0xfa, 0x82, 0xfb, 0x07, 0xfe, 0x06, 0xff, + 0x72, 0xff, 0xe6, 0x01, 0x54, 0x01, 0x64, 0xfd, 0x98, 0xfa, 0x17, 0xf9, + 0x0b, 0xfa, 0x9a, 0xfa, 0x38, 0xf9, 0x7d, 0xfa, 0xfd, 0xf9, 0xaf, 0xf6, + 0xd2, 0xf5, 0x42, 0xf7, 0xb4, 0xf9, 0xe8, 0xf9, 0x6a, 0xf9, 0xa8, 0xfa, + 0x11, 0xfd, 0x79, 0x01, 0x2d, 0x07, 0x15, 0x0c, 0x96, 0x0d, 0x8b, 0x0b, + 0x23, 0x09, 0x25, 0x05, 0x7c, 0x00, 0xa2, 0xfd, 0x19, 0xfb, 0xf1, 0xfb, + 0x72, 0xff, 0x6c, 0x03, 0x3f, 0x09, 0xd6, 0x0b, 0x40, 0x0d, 0x70, 0x10, + 0x57, 0x12, 0x20, 0x15, 0x08, 0x16, 0x73, 0x10, 0x0e, 0x08, 0x98, 0x00, + 0xb7, 0xfa, 0x0e, 0xf9, 0x37, 0xfb, 0xd6, 0xfb, 0x37, 0xfa, 0x64, 0xfa, + 0xd8, 0xfd, 0x67, 0x04, 0x7f, 0x09, 0x1b, 0x0a, 0x36, 0x0a, 0xce, 0x08, + 0x0b, 0x04, 0xf7, 0xfe, 0x95, 0xfa, 0xb6, 0xf9, 0x5c, 0xfc, 0xcd, 0xff, + 0x79, 0x02, 0x24, 0x02, 0xf1, 0x00, 0x55, 0x00, 0x9f, 0xfd, 0x2b, 0xfc, + 0x45, 0x00, 0x7f, 0x03, 0xe2, 0x03, 0x83, 0x05, 0x4d, 0x05, 0xa0, 0x04, + 0x1e, 0x05, 0x71, 0x05, 0x9a, 0x05, 0x90, 0x04, 0x33, 0x01, 0x22, 0xfc, + 0x94, 0xf9, 0xf3, 0xfc, 0x68, 0x06, 0xf7, 0x11, 0x85, 0x18, 0x0b, 0x17, + 0x9b, 0x0f, 0xa2, 0x05, 0x64, 0xfc, 0x8a, 0xf5, 0x70, 0xf3, 0xa1, 0xf7, + 0x4e, 0xfc, 0xbc, 0x02, 0xe2, 0x0c, 0xa7, 0x15, 0xe1, 0x1e, 0xb2, 0x25, + 0xb5, 0x28, 0x16, 0x2a, 0x3f, 0x27, 0xb4, 0x21, 0x22, 0x1c, 0xd7, 0x17, + 0x2a, 0x16, 0xd3, 0x16, 0x87, 0x17, 0xea, 0x18, 0x3d, 0x1a, 0xb5, 0x1d, + 0xde, 0x25, 0xda, 0x2a, 0x6b, 0x2c, 0xf6, 0x2f, 0x35, 0x32, 0x9d, 0x31, + 0x45, 0x32, 0xd9, 0x33, 0xd8, 0x33, 0xa1, 0x34, 0xfb, 0x36, 0xe4, 0x38, + 0x51, 0x37, 0x59, 0x32, 0x43, 0x2f, 0xbb, 0x2d, 0xb6, 0x29, 0xec, 0x26, + 0xe5, 0x23, 0x35, 0x1e, 0x80, 0x19, 0xa2, 0x17, 0x88, 0x1d, 0xb5, 0x27, + 0xa5, 0x2d, 0x68, 0x2e, 0x93, 0x2b, 0x61, 0x25, 0x50, 0x1d, 0xb3, 0x16, + 0x85, 0x11, 0xae, 0x0f, 0xbc, 0x0f, 0x69, 0x0f, 0xd5, 0x10, 0xec, 0x0f, + 0x37, 0x0e, 0x5e, 0x12, 0x17, 0x17, 0x87, 0x1a, 0xa3, 0x1d, 0xcf, 0x19, + 0x92, 0x10, 0xd6, 0x09, 0x4a, 0x07, 0x2e, 0x07, 0x02, 0x08, 0x53, 0x0a, + 0x51, 0x11, 0x88, 0x15, 0x8e, 0x15, 0x39, 0x17, 0xf6, 0x15, 0xc7, 0x14, + 0x31, 0x15, 0x20, 0x11, 0x2a, 0x0a, 0x88, 0x06, 0xc4, 0x05, 0xaf, 0x05, + 0x85, 0x05, 0xd8, 0x03, 0xd3, 0x06, 0xa7, 0x09, 0x7f, 0x07, 0x36, 0x04, + 0x7b, 0xff, 0x21, 0xfa, 0x08, 0xf6, 0x81, 0xf5, 0xd8, 0xf6, 0xb3, 0xf7, + 0x0a, 0xf8, 0xf6, 0xf8, 0x97, 0xf9, 0xc8, 0xf6, 0xfc, 0xf4, 0x0e, 0xf6, + 0xd2, 0xf6, 0xb3, 0xf9, 0x50, 0xfc, 0x10, 0xf9, 0xd4, 0xf6, 0x87, 0xfa, + 0x8a, 0xff, 0xd9, 0x01, 0x91, 0x01, 0xe9, 0x01, 0x40, 0x03, 0x27, 0x03, + 0x0d, 0x03, 0xac, 0x02, 0xf8, 0x00, 0x52, 0x02, 0x0a, 0x04, 0xea, 0x05, + 0x14, 0x0a, 0xb0, 0x0c, 0x7a, 0x0b, 0x56, 0x0a, 0xcf, 0x0b, 0x5f, 0x0a, + 0x6e, 0x09, 0xdc, 0x08, 0x16, 0x04, 0x25, 0x00, 0xcb, 0xfe, 0xd8, 0xff, + 0x1a, 0x03, 0x67, 0x06, 0xba, 0x08, 0xc7, 0x07, 0xc8, 0x02, 0x9d, 0xff, + 0x25, 0xfe, 0x4b, 0xfc, 0xc1, 0xfa, 0x3e, 0xf8, 0x43, 0xf7, 0xcf, 0xf7, + 0x2c, 0xf6, 0x90, 0xf4, 0x34, 0xf3, 0x82, 0xee, 0x35, 0xef, 0x63, 0xf2, + 0x65, 0xf1, 0xbb, 0xf3, 0xe9, 0xf7, 0x20, 0xfd, 0x7d, 0x02, 0xe1, 0x05, + 0xee, 0x06, 0xe6, 0x05, 0x17, 0x03, 0xff, 0xff, 0x7e, 0x00, 0x76, 0x00, + 0x03, 0x02, 0xd5, 0x07, 0xd2, 0x0b, 0x87, 0x0d, 0xb1, 0x0e, 0x9c, 0x0d, + 0x8f, 0x0a, 0xd3, 0x07, 0xe8, 0x06, 0x3a, 0x0a, 0xa5, 0x0d, 0x59, 0x0e, + 0x05, 0x10, 0x2f, 0x13, 0x24, 0x18, 0x77, 0x1c, 0x9e, 0x1d, 0xa1, 0x1d, + 0x8e, 0x1d, 0xee, 0x1c, 0xb2, 0x1c, 0x9a, 0x1a, 0x57, 0x16, 0x6f, 0x16, + 0xd6, 0x18, 0xca, 0x18, 0x6e, 0x18, 0x40, 0x15, 0x40, 0x11, 0xfd, 0x10, + 0x70, 0x12, 0xdd, 0x14, 0x56, 0x16, 0x94, 0x16, 0x78, 0x19, 0x8b, 0x1c, + 0xc1, 0x1b, 0x6a, 0x19, 0xa5, 0x17, 0x58, 0x16, 0xa8, 0x17, 0xfe, 0x19, + 0xba, 0x17, 0xd8, 0x0f, 0x0e, 0x06, 0xe8, 0xff, 0x49, 0x00, 0xc5, 0x02, + 0x5a, 0x04, 0x96, 0x05, 0xd7, 0x06, 0x28, 0x0a, 0x23, 0x0d, 0x72, 0x0e, + 0xbd, 0x11, 0x13, 0x14, 0x30, 0x12, 0x3e, 0x0f, 0xea, 0x0c, 0x32, 0x0a, + 0x8c, 0x06, 0x7e, 0x04, 0xd2, 0x03, 0xf6, 0x01, 0x71, 0x00, 0x1d, 0xff, + 0x6b, 0xfe, 0xaf, 0xff, 0x12, 0x03, 0xf5, 0x06, 0x1b, 0x0a, 0x66, 0x0e, + 0xdc, 0x0e, 0x9a, 0x0a, 0x84, 0x07, 0x8d, 0x04, 0xfc, 0x02, 0xc5, 0x02, + 0x5f, 0xff, 0xf7, 0xfa, 0x07, 0xfa, 0x8a, 0xf9, 0x22, 0xf8, 0xe5, 0xf7, + 0xcd, 0xf6, 0x58, 0xf6, 0x33, 0xf6, 0x70, 0xf5, 0xbb, 0xf5, 0xcb, 0xf4, + 0x20, 0xf5, 0x6e, 0xfa, 0xc5, 0x01, 0xa4, 0x08, 0xd3, 0x0b, 0xa7, 0x09, + 0x79, 0x07, 0xfe, 0x09, 0x6d, 0x0e, 0x9b, 0x12, 0x5d, 0x15, 0x4b, 0x15, + 0x7e, 0x14, 0x19, 0x11, 0x66, 0x0b, 0x0a, 0x07, 0xf8, 0x03, 0x4f, 0x04, + 0x47, 0x05, 0xcf, 0x03, 0xac, 0x05, 0xe0, 0x0b, 0x11, 0x0f, 0xe8, 0x10, + 0x67, 0x12, 0x2b, 0x11, 0xe4, 0x0f, 0xfe, 0x0e, 0xb8, 0x0d, 0xae, 0x0a, + 0x13, 0x07, 0xcb, 0x04, 0xa3, 0x02, 0x44, 0x00, 0x73, 0xff, 0x2e, 0xfe, + 0x5c, 0xfb, 0x07, 0xfb, 0xe6, 0xfa, 0x7a, 0xf9, 0x8b, 0xf6, 0x6d, 0xf3, + 0xd2, 0xf1, 0x4c, 0xf1, 0xfb, 0xf0, 0x85, 0xef, 0xcc, 0xee, 0xa6, 0xec, + 0x07, 0xeb, 0x1f, 0xed, 0xc3, 0xf1, 0x02, 0xf5, 0xe4, 0xf3, 0x79, 0xf2, + 0x69, 0xf0, 0x9d, 0xec, 0xbe, 0xe7, 0x05, 0xe3, 0xda, 0xdf, 0xc4, 0xe0, + 0xc5, 0xe4, 0xea, 0xe5, 0x29, 0xe7, 0x72, 0xe8, 0x5c, 0xe7, 0xd5, 0xe5, + 0x7a, 0xe6, 0x41, 0xe6, 0xaa, 0xe4, 0xe4, 0xe3, 0x70, 0xe4, 0xff, 0xe8, + 0xc1, 0xeb, 0x25, 0xec, 0xd2, 0xed, 0x22, 0xef, 0x33, 0xee, 0x9f, 0xec, + 0x81, 0xec, 0x5a, 0xed, 0xee, 0xef, 0xbd, 0xf0, 0x9e, 0xf2, 0x21, 0xf6, + 0xb6, 0xf6, 0x02, 0xf8, 0xbe, 0xf8, 0x4c, 0xf8, 0x50, 0xf9, 0x25, 0xfa, + 0x5e, 0xfa, 0xe8, 0xfa, 0x60, 0xfa, 0xdd, 0xf8, 0x42, 0xf7, 0xfa, 0xf3, + 0x7f, 0xf1, 0x93, 0xf2, 0xfb, 0xf3, 0xb7, 0xf4, 0xbe, 0xf3, 0xb5, 0xee, + 0xb9, 0xeb, 0xb4, 0xed, 0x2c, 0xf1, 0x78, 0xf5, 0x42, 0xf9, 0x49, 0xfc, + 0xf3, 0x01, 0x03, 0x09, 0xdf, 0x10, 0x06, 0x1a, 0xc0, 0x1f, 0x07, 0x20, + 0x11, 0x1d, 0x0a, 0x1a, 0xaa, 0x17, 0x47, 0x15, 0x01, 0x10, 0x23, 0x0b, + 0xe1, 0x0a, 0x7e, 0x0a, 0xa2, 0x09, 0x4f, 0x07, 0xce, 0x04, 0x15, 0x04, + 0x5e, 0x01, 0x69, 0xff, 0xbb, 0xff, 0xa1, 0xfe, 0xa1, 0xfd, 0x6e, 0xff, + 0xfd, 0x01, 0x89, 0x02, 0xdb, 0x00, 0xfa, 0xfd, 0xa3, 0xfa, 0xdc, 0xf9, + 0x66, 0xf9, 0x83, 0xf9, 0xde, 0xf9, 0xd0, 0xf7, 0xee, 0xf6, 0x68, 0xf6, + 0xd9, 0xf7, 0xcf, 0xfb, 0xe6, 0xfd, 0x5c, 0xfc, 0xdf, 0xf7, 0x35, 0xf3, + 0xd9, 0xf0, 0x07, 0xef, 0xc9, 0xec, 0x9c, 0xef, 0xb8, 0xf4, 0xc4, 0xf8, + 0xf4, 0xfd, 0x9c, 0x01, 0xd6, 0x02, 0x09, 0x03, 0x16, 0x01, 0x65, 0xfe, + 0x0f, 0xfd, 0x21, 0xfb, 0xc6, 0xf9, 0xdf, 0xf6, 0x4b, 0xf4, 0x2d, 0xf7, + 0xee, 0xfa, 0xe8, 0xfe, 0x21, 0x02, 0x7c, 0x02, 0x08, 0x02, 0x4a, 0x01, + 0x52, 0x00, 0xbc, 0xff, 0x33, 0x00, 0x0a, 0xff, 0x50, 0xfd, 0x9d, 0xfe, + 0x30, 0xff, 0xf2, 0xfe, 0xb3, 0xfd, 0xff, 0xfb, 0x44, 0xfd, 0x0e, 0xfd, + 0x57, 0xfb, 0x6d, 0xfa, 0x22, 0xfa, 0x1e, 0xfd, 0xd7, 0x01, 0x36, 0x05, + 0xbd, 0x06, 0x86, 0x07, 0xec, 0x05, 0xe7, 0x03, 0xcb, 0x01, 0xd8, 0xfc, + 0x74, 0xf8, 0x8b, 0xf2, 0x88, 0xec, 0x1e, 0xeb, 0x0f, 0xe9, 0x82, 0xe7, + 0xf0, 0xe8, 0xf0, 0xe9, 0x4c, 0xeb, 0xba, 0xeb, 0x47, 0xea, 0xa8, 0xe9, + 0x89, 0xeb, 0xa8, 0xed, 0x97, 0xf0, 0x7e, 0xf4, 0x3f, 0xf5, 0x77, 0xf6, + 0x96, 0xf7, 0x2e, 0xf6, 0x1c, 0xf4, 0xeb, 0xf0, 0x03, 0xef, 0x71, 0xef, + 0x9e, 0xef, 0x1e, 0xed, 0xed, 0xea, 0xd8, 0xe9, 0x23, 0xea, 0xd9, 0xea, + 0xf6, 0xe8, 0xe7, 0xe9, 0xda, 0xe8, 0xf9, 0xe5, 0x18, 0xe9, 0x55, 0xeb, + 0xa1, 0xea, 0x2f, 0xe9, 0x47, 0xe6, 0x43, 0xe2, 0x64, 0xde, 0xf2, 0xda, + 0x77, 0xd8, 0x3d, 0xd7, 0xa3, 0xd5, 0x41, 0xd8, 0x7f, 0xdd, 0xae, 0xe0, + 0xe7, 0xe5, 0xa6, 0xea, 0xdf, 0xec, 0x73, 0xf0, 0x52, 0xf1, 0x73, 0xef, + 0x7d, 0xee, 0x64, 0xec, 0x06, 0xed, 0x0c, 0xef, 0x65, 0xee, 0xf6, 0xed, + 0x9b, 0xee, 0x6a, 0xef, 0xcd, 0xf1, 0x3d, 0xf1, 0x00, 0xed, 0x8c, 0xeb, + 0x30, 0xe9, 0x80, 0xe7, 0x8d, 0xe8, 0xe1, 0xe9, 0x29, 0xec, 0xb0, 0xed, + 0x6d, 0xec, 0x52, 0xe8, 0x87, 0xe6, 0xcd, 0xe3, 0xe0, 0xe0, 0x13, 0xe1, + 0xf8, 0xdf, 0x67, 0xe1, 0xf2, 0xe2, 0xd6, 0xe2, 0x7f, 0xe5, 0x0f, 0xe9, + 0x41, 0xec, 0xd4, 0xef, 0xdd, 0xee, 0xbc, 0xea, 0x70, 0xea, 0xf9, 0xea, + 0x48, 0xec, 0x3e, 0xef, 0xd4, 0xee, 0x04, 0xed, 0x0d, 0xec, 0xc1, 0xea, + 0x8d, 0xea, 0x4d, 0xeb, 0x30, 0xec, 0x6a, 0xed, 0x94, 0xee, 0xa9, 0xf0, + 0xbc, 0xf4, 0x4c, 0xf7, 0x79, 0xf9, 0x4d, 0xfc, 0xf4, 0xfb, 0xcb, 0xfc, + 0xe8, 0xff, 0xa5, 0x01, 0x95, 0x02, 0xc3, 0x03, 0x4e, 0x03, 0x2b, 0x02, + 0xe1, 0x02, 0xea, 0x02, 0xd5, 0x04, 0x3d, 0x07, 0x1f, 0x08, 0x92, 0x09, + 0xba, 0x0a, 0xc2, 0x0a, 0xba, 0x0a, 0x07, 0x0d, 0x10, 0x10, 0x0e, 0x14, + 0x8f, 0x16, 0x6a, 0x17, 0xd6, 0x16, 0xfd, 0x11, 0x80, 0x0c, 0x05, 0x0a, + 0x02, 0x0a, 0x27, 0x0a, 0x43, 0x0a, 0x40, 0x07, 0xfa, 0x03, 0xca, 0x04, + 0x93, 0x07, 0x01, 0x0b, 0x4a, 0x0b, 0x22, 0x0a, 0x10, 0x0a, 0x98, 0x09, + 0x2d, 0x0b, 0x15, 0x0f, 0x5e, 0x11, 0x7d, 0x12, 0x3e, 0x11, 0x92, 0x0d, + 0xba, 0x09, 0x06, 0x04, 0x04, 0xfd, 0x54, 0xf6, 0x76, 0xf1, 0x0d, 0xef, + 0x8c, 0xf0, 0x1f, 0xf1, 0xc2, 0xef, 0xdd, 0xf0, 0xe4, 0xf1, 0x5b, 0xf3, + 0x7f, 0xf4, 0x05, 0xf6, 0x5d, 0xf8, 0xca, 0xfc, 0x15, 0x03, 0x49, 0x06, + 0x25, 0x06, 0x6f, 0x04, 0x36, 0x03, 0x90, 0xff, 0xc3, 0xfa, 0x19, 0xf5, + 0x5a, 0xef, 0x03, 0xf1, 0xd5, 0xf4, 0x2f, 0xf8, 0xa4, 0xfc, 0x3f, 0xfd, + 0x84, 0xfa, 0xbe, 0xf7, 0x47, 0xf5, 0xfa, 0xf4, 0x9e, 0xf4, 0x24, 0xf3, + 0x43, 0xf3, 0x2f, 0xf5, 0x87, 0xf6, 0x68, 0xf6, 0x88, 0xf7, 0x50, 0xf7, + 0x52, 0xf5, 0x83, 0xf2, 0x85, 0xee, 0xe9, 0xeb, 0x6b, 0xe9, 0xd3, 0xe7, + 0x4c, 0xea, 0xd1, 0xee, 0xca, 0xf1, 0x44, 0xf2, 0xdc, 0xf0, 0x3a, 0xef, + 0xfc, 0xed, 0xb8, 0xec, 0x73, 0xec, 0xab, 0xed, 0x4d, 0xf0, 0xc3, 0xf2, + 0xa4, 0xf2, 0xe5, 0xf3, 0xd3, 0xf9, 0xc4, 0xfe, 0x17, 0x01, 0xba, 0x00, + 0xc3, 0xfd, 0x52, 0xfb, 0x1f, 0xf9, 0x09, 0xf6, 0x93, 0xf4, 0xee, 0xf3, + 0x8a, 0xf1, 0xfd, 0xf0, 0xd0, 0xef, 0xff, 0xee, 0xfd, 0xf3, 0x6c, 0xfa, + 0xd2, 0xff, 0x03, 0x04, 0x04, 0x06, 0xeb, 0x05, 0xa6, 0x03, 0x9a, 0xff, + 0xaa, 0xfb, 0x85, 0xfa, 0x25, 0xf8, 0x3f, 0xf6, 0x12, 0xf7, 0x0e, 0xf9, + 0x15, 0xff, 0x15, 0x04, 0xfc, 0x07, 0xeb, 0x09, 0xcc, 0x08, 0x27, 0x0a, + 0xa7, 0x0a, 0xa4, 0x0a, 0xf3, 0x07, 0xd3, 0x03, 0x03, 0x01, 0x9a, 0xfd, + 0xc0, 0xfc, 0x4e, 0xfa, 0x37, 0xf9, 0x15, 0xfa, 0xa6, 0xfa, 0x6b, 0xfe, + 0x61, 0x02, 0xfc, 0x06, 0x75, 0x0b, 0xff, 0x0d, 0x0e, 0x10, 0xa7, 0x12, + 0xd6, 0x12, 0xc8, 0x0f, 0xfd, 0x0c, 0x2b, 0x08, 0xff, 0x02, 0x93, 0x01, + 0x76, 0x00, 0x6f, 0xff, 0xe6, 0xfe, 0xc8, 0xfb, 0x25, 0xfb, 0x14, 0xfe, + 0xe0, 0x02, 0xb3, 0x07, 0x63, 0x08, 0x2f, 0x07, 0xb6, 0x07, 0x3b, 0x09, + 0x59, 0x08, 0xbf, 0x07, 0xa7, 0x06, 0x8a, 0x05, 0x5b, 0x08, 0xa9, 0x08, + 0xc1, 0x05, 0xf3, 0x01, 0x18, 0xff, 0xe8, 0xfd, 0x46, 0xfc, 0xa1, 0xfa, + 0x43, 0xfa, 0x7f, 0xfb, 0x2d, 0xfb, 0xf8, 0xf9, 0x23, 0xfa, 0xbe, 0xfb, + 0xa4, 0xfc, 0x30, 0xfa, 0x36, 0xf6, 0x14, 0xf2, 0x96, 0xee, 0xd1, 0xed, + 0x5f, 0xee, 0x2d, 0xef, 0x1e, 0xf1, 0x81, 0xf1, 0xbc, 0xf3, 0xd2, 0xf7, + 0x70, 0xf8, 0x45, 0xfa, 0x11, 0xfe, 0x56, 0x01, 0x69, 0x05, 0x85, 0x08, + 0xa6, 0x09, 0x0f, 0x0b, 0x0f, 0x0c, 0xf1, 0x0c, 0x1d, 0x10, 0x15, 0x11, + 0x1b, 0x11, 0xc8, 0x15, 0xef, 0x1a, 0x93, 0x1b, 0xc0, 0x19, 0x24, 0x18, + 0x45, 0x1a, 0x26, 0x1c, 0x63, 0x19, 0xc9, 0x18, 0xc5, 0x18, 0x8b, 0x19, + 0xc9, 0x1b, 0x44, 0x1b, 0xad, 0x18, 0xa9, 0x15, 0xa9, 0x15, 0x1f, 0x16, + 0xbb, 0x16, 0x42, 0x18, 0xd9, 0x1b, 0xd8, 0x20, 0x9b, 0x23, 0x62, 0x25, + 0xa3, 0x25, 0xa8, 0x25, 0x31, 0x23, 0x2d, 0x1d, 0x62, 0x17, 0xe8, 0x10, + 0x34, 0x0d, 0x74, 0x0c, 0x9d, 0x0e, 0xbb, 0x10, 0x76, 0x10, 0x69, 0x13, + 0xb9, 0x16, 0x5b, 0x19, 0xdb, 0x1a, 0xbc, 0x18, 0x7f, 0x18, 0xcf, 0x19, + 0x5b, 0x1a, 0xb6, 0x1a, 0xba, 0x1b, 0x79, 0x1c, 0x74, 0x1b, 0x04, 0x19, + 0x14, 0x17, 0xee, 0x15, 0xf4, 0x10, 0xb6, 0x0b, 0xb6, 0x09, 0xd7, 0x07, + 0xb0, 0x05, 0x84, 0x04, 0xa6, 0x03, 0x8b, 0x04, 0xee, 0x06, 0xb0, 0x05, + 0x84, 0x04, 0xfa, 0x05, 0xb3, 0x06, 0x83, 0x07, 0x23, 0x09, 0x70, 0x09, + 0x8a, 0x0a, 0x89, 0x0b, 0x4b, 0x08, 0x63, 0x05, 0x06, 0x04, 0x8b, 0x04, + 0xfd, 0x04, 0x52, 0x03, 0xa9, 0x02, 0x36, 0x02, 0x5a, 0x02, 0x65, 0x02, + 0x38, 0x02, 0x09, 0x05, 0x6f, 0x08, 0xef, 0x08, 0xfb, 0x07, 0x78, 0x06, + 0x83, 0x05, 0x65, 0x05, 0xea, 0x05, 0xe8, 0x05, 0xc7, 0x04, 0x9b, 0x04, + 0xa7, 0x04, 0xbe, 0x08, 0x7d, 0x0d, 0x66, 0x0e, 0xef, 0x0f, 0x70, 0x0f, + 0x61, 0x0e, 0x85, 0x0f, 0xf1, 0x0f, 0x01, 0x10, 0x62, 0x10, 0xe7, 0x0e, + 0x44, 0x0e, 0xb3, 0x0d, 0x78, 0x09, 0xe2, 0x06, 0xb2, 0x05, 0xac, 0x02, + 0x53, 0x00, 0x19, 0xfe, 0x32, 0xfe, 0x39, 0x01, 0xa4, 0x03, 0xee, 0x05, + 0x33, 0x08, 0x5f, 0x0a, 0x37, 0x0b, 0x78, 0x0a, 0x31, 0x07, 0x8d, 0x03, + 0xa4, 0x02, 0x26, 0x00, 0x33, 0xfd, 0x3b, 0xfc, 0xcb, 0xfb, 0x5f, 0xfb, + 0x36, 0xfb, 0xb8, 0xfb, 0xbc, 0xfd, 0xe9, 0xfe, 0xbb, 0xfe, 0xa5, 0xff, + 0x94, 0xfd, 0xd8, 0xfa, 0x70, 0xf9, 0xd3, 0xf7, 0xfa, 0xf7, 0x4c, 0xf8, + 0x5b, 0xf7, 0x08, 0xf7, 0x93, 0xf9, 0xe7, 0xfd, 0x36, 0x03, 0x7c, 0x08, + 0xdb, 0x0b, 0x88, 0x0c, 0xb0, 0x0a, 0x51, 0x07, 0xbe, 0x03, 0x5c, 0x01, + 0xea, 0x02, 0xf6, 0x07, 0xfe, 0x0a, 0xbf, 0x0b, 0xed, 0x0b, 0x49, 0x0c, + 0x4a, 0x0f, 0xc4, 0x10, 0x75, 0x0f, 0xfb, 0x0e, 0x7a, 0x0e, 0xe0, 0x0e, + 0x4a, 0x10, 0x2f, 0x11, 0x76, 0x13, 0xf1, 0x15, 0x69, 0x17, 0x5a, 0x19, + 0x15, 0x19, 0x01, 0x17, 0x11, 0x16, 0xc9, 0x14, 0x70, 0x13, 0xe7, 0x11, + 0x37, 0x10, 0xa0, 0x0d, 0x4b, 0x0c, 0x0f, 0x0b, 0x5c, 0x09, 0x56, 0x0a, + 0xbe, 0x08, 0x9f, 0x09, 0xc9, 0x0b, 0x06, 0x0c, 0x0a, 0x10, 0xa6, 0x13, + 0xcf, 0x16, 0xa3, 0x19, 0xe4, 0x1b, 0x6e, 0x1d, 0x9e, 0x1e, 0x06, 0x1f, + 0x70, 0x1d, 0x6a, 0x1c, 0x80, 0x1c, 0xe1, 0x1c, 0x66, 0x1d, 0x8f, 0x1e, + 0xd0, 0x1e, 0xa2, 0x1d, 0x6a, 0x1a, 0x63, 0x18, 0x6b, 0x17, 0x5d, 0x15, + 0x4a, 0x15, 0x56, 0x16, 0x15, 0x17, 0x6d, 0x17, 0x8d, 0x18, 0x46, 0x18, + 0xbe, 0x14, 0xfc, 0x0c, 0x6a, 0x06, 0x96, 0x03, 0x37, 0xff, 0x7a, 0xfc, + 0xd3, 0xfb, 0xb4, 0xfd, 0xc0, 0x02, 0xd0, 0x07, 0xa1, 0x0b, 0xb7, 0x0e, + 0xf7, 0x0c, 0x7b, 0x09, 0x1b, 0x0b, 0x6e, 0x0c, 0xe5, 0x0b, 0xef, 0x0a, + 0xeb, 0x09, 0xb8, 0x0a, 0x06, 0x0d, 0x54, 0x0d, 0xff, 0x0c, 0x2e, 0x0d, + 0x4a, 0x0d, 0x42, 0x0e, 0xe3, 0x0e, 0xea, 0x0e, 0x58, 0x0d, 0x77, 0x0b, + 0xdf, 0x08, 0x4e, 0x07, 0xf4, 0x04, 0xe4, 0x02, 0x15, 0x04, 0x02, 0x03, + 0xf5, 0x03, 0x1b, 0x06, 0xea, 0x06, 0xd3, 0x08, 0xfb, 0x08, 0x04, 0x0a, + 0xe9, 0x0b, 0x1c, 0x0b, 0xc9, 0x09, 0xaf, 0x07, 0xdf, 0x04, 0xaa, 0x04, + 0x80, 0x06, 0xec, 0x06, 0x34, 0x06, 0x04, 0x05, 0xee, 0x02, 0x1e, 0x01, + 0x3d, 0xff, 0xed, 0xfe, 0x2a, 0xff, 0x20, 0xfe, 0x29, 0xfe, 0x67, 0xfe, + 0x8c, 0xfc, 0xd5, 0xfa, 0x0d, 0xf9, 0xa8, 0xf5, 0x9e, 0xf6, 0x66, 0xfa, + 0xed, 0xf9, 0xa6, 0xf5, 0xe9, 0xf1, 0xbf, 0xf1, 0x8b, 0xf2, 0x20, 0xf2, + 0xa9, 0xf1, 0x76, 0xf2, 0xc0, 0xf2, 0x0f, 0xf4, 0x06, 0xf5, 0xbb, 0xf4, + 0x74, 0xf4, 0x55, 0xf4, 0xb1, 0xf6, 0x15, 0xfa, 0x32, 0xfc, 0xff, 0xf9, + 0xd3, 0xf8, 0x10, 0xfa, 0x0a, 0xf9, 0xe4, 0xf7, 0x28, 0xf8, 0xbb, 0xf8, + 0x7f, 0xf7, 0xda, 0xf6, 0xd9, 0xf6, 0xb4, 0xf7, 0x31, 0xf8, 0x3a, 0xf9, + 0x43, 0xfa, 0xfd, 0xf8, 0x55, 0xf8, 0xa9, 0xf6, 0x0e, 0xf7, 0xc0, 0xf9, + 0xcb, 0xfa, 0xda, 0xf9, 0x53, 0xf7, 0x01, 0xf6, 0xde, 0xf5, 0x9e, 0xf6, + 0xd7, 0xf5, 0x9f, 0xf2, 0x9a, 0xf2, 0x18, 0xf4, 0x50, 0xf5, 0x16, 0xf7, + 0x20, 0xf7, 0xbe, 0xf9, 0x1b, 0xfc, 0xef, 0xfc, 0xe5, 0xfe, 0x4c, 0xfe, + 0xd6, 0xfd, 0x76, 0xfe, 0x26, 0xfd, 0xf4, 0xf9, 0x27, 0xf9, 0x50, 0xfb, + 0x75, 0x00, 0x8b, 0x07, 0xeb, 0x0a, 0x7f, 0x0c, 0xb1, 0x0d, 0xbc, 0x0c, + 0x62, 0x0b, 0x73, 0x08, 0x36, 0x04, 0xc6, 0x02, 0xae, 0x02, 0x3b, 0x03, + 0xb4, 0x04, 0x55, 0x03, 0xb7, 0x01, 0xaf, 0x03, 0x96, 0x05, 0xa3, 0x06, + 0xf4, 0x05, 0xfa, 0x02, 0xc3, 0x02, 0x28, 0x04, 0x8a, 0x03, 0x20, 0x04, + 0xad, 0x07, 0xc0, 0x0b, 0x6b, 0x10, 0x3b, 0x13, 0x30, 0x11, 0x76, 0x0e, + 0x12, 0x0c, 0x36, 0x0b, 0x12, 0x0d, 0x79, 0x0d, 0xe3, 0x0c, 0x95, 0x0c, + 0x07, 0x0a, 0x32, 0x06, 0xc0, 0x03, 0x50, 0x01, 0x92, 0x00, 0xe5, 0x02, + 0x77, 0x04, 0xf8, 0x04, 0x7c, 0x05, 0x2a, 0x07, 0x96, 0x0a, 0x6f, 0x0e, + 0x57, 0x11, 0x1f, 0x14, 0xde, 0x14, 0x71, 0x14, 0xd8, 0x15, 0x13, 0x14, + 0x82, 0x10, 0x7e, 0x0d, 0xf4, 0x08, 0x3f, 0x08, 0xf9, 0x0a, 0x52, 0x0e, + 0x2c, 0x12, 0xf4, 0x14, 0x9c, 0x18, 0xdd, 0x1b, 0xd4, 0x18, 0x83, 0x11, + 0x8f, 0x0b, 0x6f, 0x06, 0x72, 0x03, 0x33, 0x00, 0x6b, 0xfb, 0x66, 0xfa, + 0x72, 0xfb, 0x80, 0xfb, 0x54, 0xfa, 0x85, 0xf8, 0xe9, 0xf7, 0x9b, 0xf9, + 0x70, 0xfa, 0x97, 0xf9, 0x14, 0xfb, 0xb5, 0xfb, 0x26, 0xfb, 0xa7, 0xfa, + 0x3e, 0xf8, 0xe3, 0xf5, 0xcb, 0xf2, 0x27, 0xef, 0x22, 0xee, 0xf2, 0xec, + 0x07, 0xeb, 0x82, 0xeb, 0x69, 0xeb, 0xd8, 0xeb, 0xb0, 0xee, 0x21, 0xef, + 0x68, 0xee, 0xdb, 0xee, 0x2c, 0xef, 0x7e, 0xf0, 0x08, 0xf1, 0x07, 0xf0, + 0xed, 0xef, 0x3b, 0xee, 0xfd, 0xec, 0x63, 0xf0, 0x55, 0xf3, 0x63, 0xf4, + 0x54, 0xf6, 0xc8, 0xf6, 0x21, 0xf6, 0x67, 0xf7, 0xab, 0xf6, 0xd5, 0xf2, + 0x2f, 0xef, 0x83, 0xea, 0xce, 0xe7, 0x12, 0xe9, 0xf6, 0xeb, 0x76, 0xef, + 0x19, 0xf2, 0x7e, 0xf5, 0x7e, 0xf9, 0x8b, 0xf9, 0xe1, 0xf8, 0x91, 0xfa, + 0xe4, 0xf8, 0xa4, 0xf5, 0x40, 0xf5, 0x4b, 0xf6, 0x22, 0xf8, 0x2e, 0xf9, + 0xcb, 0xf8, 0xcf, 0xf7, 0xc9, 0xf6, 0xd6, 0xf5, 0xd2, 0xf5, 0x83, 0xf4, + 0x43, 0xf2, 0x34, 0xf4, 0x46, 0xf5, 0x58, 0xf3, 0xa9, 0xf3, 0xfb, 0xf3, + 0xf5, 0xf3, 0x45, 0xf4, 0x8d, 0xf2, 0xab, 0xf1, 0x84, 0xf0, 0x68, 0xec, + 0x1d, 0xeb, 0x4b, 0xec, 0x85, 0xed, 0x0c, 0xf0, 0x21, 0xf2, 0xdf, 0xf2, + 0x8e, 0xf5, 0xea, 0xf8, 0xc2, 0xf9, 0x97, 0xfa, 0xd0, 0xf8, 0x73, 0xf6, + 0xe2, 0xf6, 0x6c, 0xf5, 0x42, 0xf4, 0xf3, 0xf4, 0xd9, 0xf4, 0x13, 0xf5, + 0xcd, 0xf4, 0x8e, 0xf2, 0x4b, 0xf1, 0x5f, 0xf1, 0xca, 0xf1, 0x69, 0xf2, + 0xf5, 0xee, 0x0d, 0xeb, 0x78, 0xec, 0x66, 0xed, 0x3f, 0xed, 0xd9, 0xed, + 0x87, 0xed, 0xe8, 0xed, 0x8d, 0xed, 0xf7, 0xeb, 0x81, 0xea, 0x3c, 0xe8, + 0x5a, 0xe5, 0xc5, 0xe4, 0x08, 0xe6, 0xac, 0xe7, 0xbe, 0xea, 0x26, 0xed, + 0xe7, 0xee, 0xcf, 0xef, 0xd6, 0xee, 0x02, 0xef, 0x8d, 0xf2, 0xd2, 0xf4, + 0xa3, 0xf5, 0x1d, 0xf7, 0xe2, 0xf7, 0xca, 0xfa, 0x01, 0xfa, 0x97, 0xf7, + 0xaf, 0xf8, 0x23, 0xf6, 0xe7, 0xf2, 0xc6, 0xf2, 0xee, 0xf2, 0x72, 0xf3, + 0x09, 0xf7, 0x99, 0xfa, 0xbd, 0xfa, 0xa5, 0xfa, 0x63, 0xfd, 0xf0, 0x03, + 0xdd, 0x05, 0xed, 0x04, 0x83, 0x08, 0xc7, 0x08, 0xd8, 0x08, 0xe5, 0x08, + 0xcb, 0x06, 0x13, 0x07, 0xb4, 0x06, 0x79, 0x06, 0xaf, 0x06, 0x45, 0x08, + 0xad, 0x07, 0x00, 0x08, 0xc4, 0x08, 0xa7, 0x04, 0xe9, 0x02, 0x21, 0x01, + 0x45, 0x00, 0x95, 0x00, 0xb8, 0xff, 0xeb, 0xff, 0x8a, 0x01, 0xd8, 0x01, + 0x13, 0x00, 0xc2, 0xff, 0x2c, 0xfe, 0x4a, 0xfe, 0x74, 0x00, 0x7e, 0xff, + 0x6e, 0xfd, 0xe7, 0xfd, 0x37, 0x01, 0x9d, 0x04, 0x24, 0x04, 0x44, 0x01, + 0x76, 0x00, 0xfc, 0xfc, 0xf9, 0xf8, 0xf7, 0xf6, 0x47, 0xf4, 0xa2, 0xf5, + 0xd6, 0xf8, 0x73, 0xf8, 0xfd, 0xf9, 0xb8, 0xfe, 0xbc, 0x00, 0x0d, 0x01, + 0x9e, 0xfd, 0x24, 0xf8, 0xc3, 0xf1, 0x82, 0xea, 0xa7, 0xe7, 0x74, 0xe6, + 0x2f, 0xe5, 0xff, 0xe4, 0x58, 0xe6, 0x99, 0xea, 0xc1, 0xee, 0x0c, 0xf1, + 0x34, 0xf5, 0xff, 0xf8, 0x41, 0xfb, 0xb7, 0xfd, 0xdb, 0x00, 0x93, 0x02, + 0xa7, 0x03, 0xa1, 0x06, 0x12, 0x04, 0xc4, 0x00, 0x24, 0x02, 0x7f, 0x00, + 0x90, 0xfc, 0x40, 0xf8, 0x7f, 0xf3, 0x15, 0xef, 0x25, 0xeb, 0xca, 0xe6, + 0xb3, 0xe2, 0x09, 0xe1, 0xca, 0xdf, 0x14, 0xde, 0x55, 0xdf, 0x49, 0xe2, + 0xe5, 0xe6, 0x03, 0xeb, 0x3a, 0xee, 0x69, 0xf3, 0xbf, 0xf6, 0x33, 0xfa, + 0x8c, 0xfd, 0x77, 0xfe, 0x19, 0xff, 0x70, 0xfe, 0x35, 0xfb, 0xc8, 0xf5, + 0x43, 0xf0, 0xd0, 0xeb, 0xce, 0xe9, 0x75, 0xe7, 0x06, 0xe6, 0x41, 0xe7, + 0x89, 0xe9, 0x11, 0xec, 0x0c, 0xef, 0x27, 0xf4, 0xdf, 0xf7, 0x92, 0xf9, + 0x71, 0xf9, 0xc2, 0xf9, 0x22, 0xfa, 0x10, 0xf9, 0x64, 0xfa, 0x05, 0xfa, + 0x16, 0xf7, 0xf8, 0xf4, 0xd2, 0xf0, 0xbf, 0xeb, 0xc3, 0xea, 0x9d, 0xea, + 0x1d, 0xea, 0x78, 0xea, 0x55, 0xea, 0x25, 0xeb, 0xda, 0xea, 0x11, 0xec, + 0xd4, 0xee, 0x3a, 0xf0, 0xb3, 0xf1, 0x7c, 0xf3, 0x11, 0xf5, 0x92, 0xf3, + 0xf6, 0xf0, 0xde, 0xef, 0x09, 0xed, 0x5c, 0xea, 0x79, 0xea, 0xdc, 0xea, + 0x67, 0xea, 0xd6, 0xe9, 0xc8, 0xeb, 0x6f, 0xed, 0x9d, 0xed, 0x4e, 0xf2, + 0xc7, 0xf6, 0xae, 0xf8, 0xa4, 0xfb, 0x37, 0xfe, 0xf1, 0xfe, 0x6d, 0xff, + 0x0c, 0xff, 0xeb, 0xfe, 0x1d, 0x00, 0xbb, 0xfe, 0x69, 0xfd, 0x20, 0xfe, + 0x02, 0xfe, 0x4d, 0xfe, 0xf2, 0xfe, 0x3e, 0xfd, 0xb4, 0xfd, 0xff, 0xff, + 0xa9, 0x01, 0x2b, 0x03, 0x22, 0x02, 0x77, 0x01, 0x97, 0x00, 0x97, 0xfe, + 0xcc, 0xfc, 0xb0, 0xf9, 0x22, 0xf7, 0xd4, 0xf6, 0xd9, 0xf6, 0x62, 0xf8, + 0xe7, 0xfc, 0x74, 0xfe, 0x6c, 0xfd, 0x60, 0xfd, 0xf6, 0xfd, 0xac, 0xfd, + 0x4e, 0xfd, 0x00, 0xff, 0xe6, 0xff, 0xa5, 0xff, 0xac, 0xff, 0x22, 0x00, + 0xc3, 0xff, 0xda, 0xff, 0x74, 0x00, 0x04, 0x00, 0x19, 0x02, 0xba, 0x06, + 0x7a, 0x08, 0xa1, 0x06, 0x32, 0x05, 0xbd, 0x03, 0x0c, 0x01, 0xba, 0xff, + 0x58, 0x00, 0x7d, 0x00, 0x2f, 0x02, 0x0f, 0x04, 0xf5, 0x03, 0xc4, 0x04, + 0xc2, 0x03, 0xd3, 0x05, 0x25, 0x0b, 0x46, 0x0c, 0x7d, 0x0d, 0xbe, 0x0f, + 0x7a, 0x0f, 0x38, 0x0e, 0x5c, 0x0d, 0xe9, 0x0b, 0xaf, 0x0b, 0xfe, 0x0d, + 0x97, 0x10, 0x1c, 0x12, 0x5f, 0x11, 0x75, 0x11, 0xb2, 0x11, 0xd0, 0x0e, + 0x94, 0x0b, 0x43, 0x08, 0x4a, 0x05, 0x35, 0x05, 0x4a, 0x03, 0x64, 0x00, + 0xf7, 0x02, 0x6b, 0x05, 0xcd, 0x06, 0x35, 0x08, 0xf2, 0x04, 0x78, 0x01, + 0x9d, 0xff, 0x85, 0xff, 0x24, 0x03, 0x6a, 0x07, 0x6c, 0x08, 0xf9, 0x09, + 0xe0, 0x0d, 0xe9, 0x0e, 0x9e, 0x0f, 0xb4, 0x11, 0x5f, 0x13, 0x47, 0x12, + 0x50, 0x0e, 0x56, 0x0c, 0xa2, 0x0a, 0x22, 0x08, 0x52, 0x06, 0x75, 0x05, + 0x6a, 0x06, 0x56, 0x08, 0xd8, 0x07, 0x3e, 0x05, 0xbf, 0x03, 0xe5, 0x01, + 0x21, 0xfe, 0xd5, 0xfa, 0x5c, 0xf9, 0xab, 0xf7, 0x7d, 0xf6, 0x8a, 0xf7, + 0x82, 0xf8, 0x9f, 0xfa, 0xfe, 0xfb, 0xdd, 0xfb, 0x59, 0xfe, 0x8a, 0xfe, + 0xae, 0xfc, 0x5a, 0xfc, 0x9e, 0xfb, 0x46, 0xf9, 0x51, 0xf6, 0x4a, 0xf5, + 0xcc, 0xf2, 0x03, 0xf0, 0x5f, 0xef, 0x67, 0xee, 0x47, 0xed, 0x37, 0xee, + 0xe7, 0xf1, 0x28, 0xf3, 0x9f, 0xf3, 0x78, 0xf3, 0xd7, 0xf1, 0x11, 0xf3, + 0x5e, 0xf4, 0x36, 0xf5, 0x47, 0xf8, 0x4d, 0xfa, 0x69, 0xfa, 0x60, 0xfd, + 0x6a, 0xfe, 0x17, 0xff, 0x6b, 0x03, 0x20, 0x05, 0x64, 0x07, 0x12, 0x0a, + 0x99, 0x09, 0x14, 0x08, 0x3d, 0x06, 0xe6, 0x01, 0x97, 0xfc, 0x37, 0xfa, + 0x74, 0xfa, 0x95, 0xfc, 0xf3, 0xfe, 0x98, 0x01, 0x95, 0x02, 0x1c, 0x03, + 0x82, 0x05, 0x49, 0x07, 0xfa, 0x08, 0xc9, 0x0a, 0xf7, 0x0a, 0x8f, 0x06, + 0xaf, 0x02, 0xfa, 0x00, 0x75, 0xfe, 0x02, 0xfe, 0x96, 0xfd, 0xf9, 0xfc, + 0x49, 0xfd, 0x96, 0xfd, 0x2e, 0xff, 0xf0, 0x01, 0x36, 0x05, 0xd4, 0x07, + 0xc4, 0x08, 0xe6, 0x08, 0x87, 0x0a, 0x2c, 0x0c, 0x5f, 0x0a, 0x78, 0x0a, + 0x25, 0x0c, 0xb6, 0x0b, 0x68, 0x0c, 0x9e, 0x0c, 0x3a, 0x0e, 0x29, 0x12, + 0x3b, 0x15, 0x3e, 0x18, 0xf9, 0x1a, 0x84, 0x1c, 0x39, 0x1d, 0xa5, 0x1d, + 0x9c, 0x1d, 0x9d, 0x1f, 0x5d, 0x21, 0x74, 0x20, 0x68, 0x21, 0xe8, 0x21, + 0x4a, 0x21, 0xf9, 0x23, 0x26, 0x25, 0xff, 0x22, 0xc1, 0x20, 0xb1, 0x1d, + 0x02, 0x1b, 0xe4, 0x18, 0x30, 0x17, 0x22, 0x16, 0xdc, 0x14, 0x25, 0x14, + 0x14, 0x15, 0xb5, 0x14, 0xe3, 0x11, 0x1b, 0x11, 0xe2, 0x11, 0x9d, 0x12, + 0xb3, 0x12, 0xec, 0x10, 0x6a, 0x11, 0x49, 0x14, 0x17, 0x13, 0x90, 0x11, + 0x68, 0x11, 0x6c, 0x0f, 0x5e, 0x0e, 0x5d, 0x0b, 0xb6, 0x07, 0xc6, 0x07, + 0x14, 0x08, 0x1c, 0x08, 0xd9, 0x0a, 0xdc, 0x0d, 0x25, 0x10, 0xbd, 0x13, + 0x61, 0x15, 0xbc, 0x14, 0x22, 0x13, 0xf4, 0x0f, 0xf0, 0x0b, 0x2e, 0x06, + 0xe8, 0x00, 0xa5, 0xff, 0xb5, 0x00, 0x69, 0x02, 0x5d, 0x05, 0xd7, 0x06, + 0xbd, 0x06, 0xe6, 0x05, 0xd0, 0x03, 0x85, 0x03, 0x59, 0x03, 0x67, 0x01, + 0x8b, 0x00, 0x91, 0xff, 0x61, 0xfd, 0xf4, 0xfc, 0x1d, 0xfd, 0xd1, 0xfd, + 0xb2, 0x00, 0x5a, 0x01, 0x99, 0x00, 0x0a, 0x01, 0x72, 0xff, 0xe8, 0xfd, + 0x05, 0xfe, 0xf5, 0xfc, 0xfa, 0xfb, 0xd4, 0xfb, 0x68, 0xfb, 0xb2, 0xfb, + 0x9b, 0xfb, 0x4e, 0xfc, 0x41, 0xfe, 0xb8, 0xff, 0x72, 0x03, 0xc7, 0x09, + 0x49, 0x0d, 0xe8, 0x0f, 0xb0, 0x14, 0x8a, 0x16, 0x17, 0x17, 0xde, 0x18, + 0xd3, 0x18, 0x15, 0x18, 0x2e, 0x17, 0x1c, 0x15, 0xe6, 0x14, 0xa4, 0x16, + 0x42, 0x17, 0xbe, 0x18, 0x49, 0x18, 0x42, 0x16, 0x7e, 0x16, 0xf6, 0x14, + 0xb1, 0x13, 0x3f, 0x13, 0x48, 0x10, 0x5c, 0x10, 0x1c, 0x13, 0x3b, 0x13, + 0x14, 0x16, 0x25, 0x19, 0x8d, 0x17, 0x98, 0x16, 0x07, 0x16, 0xa6, 0x15, + 0x8f, 0x15, 0xf2, 0x11, 0x6b, 0x0c, 0x0d, 0x0a, 0x8c, 0x08, 0x05, 0x08, + 0x88, 0x0b, 0x18, 0x0d, 0xa9, 0x0d, 0x70, 0x0e, 0x78, 0x0c, 0x4b, 0x0a, + 0xa9, 0x09, 0x22, 0x08, 0xd8, 0x05, 0xc0, 0x04, 0x78, 0x03, 0xe3, 0x03, + 0xe4, 0x03, 0x76, 0x02, 0x25, 0x03, 0x67, 0x02, 0xbb, 0x01, 0xab, 0x03, + 0x1d, 0x04, 0x0d, 0x04, 0xef, 0x03, 0xf0, 0x01, 0xec, 0x01, 0x10, 0x02, + 0x66, 0x00, 0x8a, 0x00, 0x79, 0x00, 0xf4, 0x00, 0xb5, 0x02, 0xdd, 0x02, + 0x97, 0x01, 0xff, 0xfe, 0x23, 0xfb, 0x08, 0xf9, 0xa9, 0xf9, 0x66, 0xfa, + 0xdc, 0xfc, 0x9b, 0x00, 0x31, 0x02, 0xd0, 0x02, 0x23, 0x03, 0x4f, 0x03, + 0xde, 0x02, 0xe8, 0x00, 0x7a, 0xfe, 0x0c, 0xff, 0x7b, 0xff, 0xc1, 0xfe, + 0x3d, 0x00, 0x1a, 0x01, 0xc4, 0x01, 0x02, 0x01, 0xb9, 0xfd, 0xdd, 0xfb, + 0xd4, 0xfa, 0x42, 0xfa, 0x9b, 0xfb, 0x3f, 0xfc, 0x6a, 0xfd, 0xc8, 0x00, + 0x63, 0x02, 0x12, 0x04, 0xa3, 0x06, 0x33, 0x06, 0x5f, 0x04, 0x36, 0x03, + 0xb1, 0x00, 0x65, 0x00, 0x69, 0x02, 0x6b, 0x03, 0x33, 0x06, 0x0c, 0x09, + 0x1a, 0x0c, 0x0e, 0x10, 0xd6, 0x11, 0x8d, 0x12, 0x29, 0x14, 0xfe, 0x14, + 0xdc, 0x14, 0xc8, 0x14, 0x39, 0x13, 0x6a, 0x12, 0x89, 0x10, 0xb9, 0x0c, + 0x55, 0x0b, 0xe0, 0x0a, 0x34, 0x08, 0x49, 0x05, 0xf4, 0x03, 0x67, 0x03, + 0xba, 0x03, 0x62, 0x03, 0xee, 0x01, 0x27, 0x02, 0xc9, 0x01, 0x13, 0x01, + 0xa1, 0x02, 0x1b, 0x03, 0x9f, 0x03, 0xc6, 0x04, 0x76, 0x04, 0x50, 0x04, + 0xf8, 0x02, 0x13, 0x01, 0xff, 0xff, 0x99, 0xff, 0xa5, 0x00, 0x51, 0x03, + 0x87, 0x05, 0x7a, 0x06, 0x3a, 0x09, 0x88, 0x0b, 0x55, 0x0c, 0x5a, 0x0c, + 0x01, 0x0b, 0x05, 0x0b, 0xcb, 0x0a, 0xed, 0x09, 0x1b, 0x0a, 0x62, 0x0a, + 0x4b, 0x0a, 0x89, 0x0a, 0x43, 0x0a, 0x48, 0x08, 0xcf, 0x06, 0xca, 0x04, + 0x6f, 0x03, 0xf5, 0x04, 0x7c, 0x05, 0x37, 0x06, 0xfa, 0x06, 0x9d, 0x05, + 0xdd, 0x04, 0x4f, 0x04, 0x3c, 0x02, 0xde, 0x01, 0x11, 0x02, 0x19, 0x01, + 0xe2, 0x01, 0x19, 0x02, 0x43, 0x01, 0x29, 0x02, 0xfe, 0x02, 0x9e, 0x02, + 0x7a, 0x03, 0x3a, 0x04, 0x57, 0x04, 0x2b, 0x05, 0xae, 0x03, 0x74, 0x02, + 0xb1, 0x01, 0xfe, 0xfe, 0x91, 0xfc, 0x7e, 0xfb, 0x33, 0xfb, 0x61, 0xfc, + 0xbc, 0xfe, 0xbb, 0xff, 0xa5, 0x00, 0x72, 0x00, 0x26, 0x01, 0xe1, 0x02, + 0x69, 0x01, 0x42, 0x00, 0x8d, 0xff, 0x8a, 0xfd, 0xb4, 0xfc, 0xea, 0xfb, + 0x72, 0xfa, 0x3e, 0xfa, 0xde, 0xf8, 0x1f, 0xf6, 0x02, 0xf5, 0xb1, 0xf3, + 0xad, 0xf3, 0x51, 0xf5, 0xaf, 0xf4, 0xd6, 0xf3, 0x36, 0xf4, 0x99, 0xf3, + 0xef, 0xf3, 0x85, 0xf5, 0x00, 0xf6, 0x4b, 0xf7, 0x21, 0xf8, 0x33, 0xf7, + 0xc9, 0xf8, 0x3f, 0xf9, 0x12, 0xf8, 0xb9, 0xf8, 0x07, 0xf9, 0xee, 0xfa, + 0xda, 0xfd, 0xbf, 0xff, 0x8a, 0x03, 0xf2, 0x08, 0x03, 0x0c, 0x02, 0x0d, + 0xa7, 0x0c, 0x2c, 0x0c, 0xd1, 0x0d, 0xb5, 0x0c, 0xad, 0x09, 0xbd, 0x09, + 0xbf, 0x0a, 0xc5, 0x0a, 0x69, 0x0a, 0x71, 0x07, 0xc6, 0x03, 0xa6, 0x01, + 0x30, 0xfe, 0xe0, 0xfb, 0x3a, 0xfa, 0xc1, 0xf7, 0x5e, 0xf8, 0xfc, 0xfb, + 0x2a, 0xff, 0xa8, 0x00, 0x61, 0xfe, 0xa5, 0xf9, 0x74, 0xf7, 0x34, 0xf5, + 0x21, 0xf3, 0x1a, 0xf4, 0xb4, 0xf5, 0x39, 0xf8, 0xc6, 0xfb, 0xa0, 0xfe, + 0x08, 0x02, 0x47, 0x05, 0x6c, 0x05, 0xaf, 0x04, 0xd9, 0x01, 0x6e, 0xfd, + 0xf3, 0xfa, 0x07, 0xf8, 0xc9, 0xf5, 0x30, 0xf5, 0x90, 0xf3, 0x24, 0xf4, + 0xfe, 0xf6, 0x3d, 0xf8, 0x60, 0xfa, 0x3f, 0xfc, 0x5d, 0xfb, 0xaa, 0xfa, + 0x13, 0xfb, 0x1c, 0xfb, 0x34, 0xfb, 0xa7, 0xfa, 0x4a, 0xf9, 0x95, 0xf9, + 0x13, 0xfa, 0x80, 0xfb, 0xf1, 0xfc, 0x17, 0xfc, 0xd3, 0xfb, 0x5d, 0xfc, + 0xc4, 0xfb, 0xaf, 0xfa, 0xf0, 0xf9, 0x0a, 0xf9, 0xe0, 0xf8, 0xe1, 0xf7, + 0xcd, 0xf5, 0xd3, 0xf6, 0x81, 0xf7, 0x3d, 0xf7, 0x2b, 0xf9, 0xa3, 0xf9, + 0xfa, 0xf9, 0xc4, 0xfb, 0x07, 0xfe, 0xfb, 0x00, 0xa7, 0x02, 0x6c, 0x02, + 0x04, 0x03, 0x94, 0x03, 0x2b, 0x02, 0x96, 0x01, 0x09, 0x00, 0x38, 0xfd, + 0x12, 0xfd, 0x3a, 0xfd, 0x36, 0xfd, 0x2f, 0xfe, 0x77, 0xfe, 0x76, 0x00, + 0x1d, 0x03, 0x0e, 0x02, 0xdd, 0x00, 0x52, 0x00, 0xad, 0xfd, 0x38, 0xfb, + 0x19, 0xfa, 0x26, 0xfa, 0x9a, 0xfc, 0x82, 0xff, 0x9e, 0x00, 0x1b, 0x01, + 0x96, 0x00, 0xe7, 0x00, 0xe9, 0x01, 0xf4, 0x00, 0xba, 0x00, 0x41, 0x01, + 0x03, 0x01, 0x26, 0x01, 0xbf, 0x01, 0x10, 0x01, 0xc0, 0xff, 0xbc, 0xfc, + 0xd9, 0xf7, 0x7b, 0xf5, 0x60, 0xf4, 0x86, 0xf3, 0x27, 0xf4, 0xb6, 0xf3, + 0x45, 0xf3, 0xed, 0xf4, 0x32, 0xf5, 0xa3, 0xf5, 0x49, 0xf7, 0xfd, 0xf5, + 0x56, 0xf4, 0xba, 0xf2, 0xc5, 0xf0, 0x22, 0xf1, 0x83, 0xf1, 0xf4, 0xf0, + 0x77, 0xf1, 0xde, 0xf1, 0xc6, 0xf2, 0x56, 0xf5, 0xd4, 0xf6, 0xea, 0xf8, + 0xf8, 0xfb, 0xe5, 0xfc, 0xc8, 0xfd, 0xc2, 0xfe, 0x8a, 0xfd, 0x68, 0xfc, + 0x09, 0xfd, 0xce, 0xfc, 0x45, 0xfd, 0x57, 0xfd, 0x99, 0xfc, 0xb0, 0xfd, + 0x35, 0xfd, 0xe9, 0xfb, 0x66, 0xfc, 0x09, 0xfc, 0x48, 0xfb, 0x42, 0xfb, + 0x7c, 0xf9, 0xe9, 0xf7, 0x3f, 0xf6, 0x67, 0xf3, 0x12, 0xf2, 0xa8, 0xef, + 0xaa, 0xec, 0x49, 0xeb, 0x6c, 0xe9, 0xc2, 0xe8, 0x16, 0xea, 0x8d, 0xe9, + 0xdb, 0xe7, 0x63, 0xe7, 0xa9, 0xe6, 0x9e, 0xe6, 0x84, 0xe6, 0x25, 0xe5, + 0x61, 0xe5, 0xb1, 0xe7, 0x18, 0xea, 0xe3, 0xed, 0xc0, 0xf0, 0x3c, 0xf1, + 0xc2, 0xf1, 0x30, 0xf1, 0x64, 0xf0, 0x92, 0xf0, 0xca, 0xf0, 0x13, 0xf1, + 0x08, 0xf2, 0xc1, 0xf1, 0x15, 0xf1, 0x55, 0xf2, 0x0f, 0xf3, 0x16, 0xf4, + 0x3c, 0xf4, 0x4a, 0xf2, 0x84, 0xf2, 0x34, 0xf3, 0xc8, 0xf2, 0x2a, 0xf3, + 0x0a, 0xf2, 0xea, 0xf0, 0xd6, 0xf0, 0x3c, 0xee, 0x89, 0xec, 0x56, 0xec, + 0x80, 0xeb, 0xcd, 0xec, 0x41, 0xef, 0xe7, 0xef, 0x7f, 0xf0, 0xa4, 0xf0, + 0xab, 0xef, 0xc9, 0xef, 0xb0, 0xee, 0x7a, 0xed, 0xf4, 0xed, 0x47, 0xee, + 0x6a, 0xee, 0x41, 0xee, 0xa5, 0xed, 0xeb, 0xed, 0x5a, 0xee, 0x3b, 0xed, + 0xf4, 0xec, 0x63, 0xed, 0x16, 0xed, 0xbf, 0xed, 0x09, 0xee, 0x34, 0xee, + 0x02, 0xf0, 0x37, 0xf2, 0x73, 0xf4, 0x96, 0xf7, 0x6d, 0xf8, 0x3c, 0xf8, + 0x40, 0xf9, 0x35, 0xfa, 0x8f, 0xfb, 0x56, 0xfc, 0xab, 0xfb, 0x34, 0xfb, + 0x8d, 0xfc, 0xc1, 0xfd, 0xfa, 0xfe, 0xaf, 0xff, 0x98, 0xff, 0x84, 0x00, + 0x01, 0x00, 0x3a, 0xff, 0xed, 0xfe, 0x2f, 0xff, 0xa8, 0x00, 0xd6, 0x01, + 0x75, 0x01, 0x88, 0x00, 0x53, 0xff, 0x50, 0xfc, 0x06, 0xf9, 0xa6, 0xf4, + 0xd3, 0xf1, 0xad, 0xf2, 0x1c, 0xf4, 0xb3, 0xf5, 0x26, 0xf8, 0x06, 0xfc, + 0xed, 0x01, 0x53, 0x08, 0x35, 0x0a, 0x14, 0x0b, 0xd2, 0x0b, 0xa1, 0x08, + 0x4c, 0x05, 0x52, 0x02, 0x86, 0xff, 0x9f, 0xfe, 0xe8, 0xff, 0x27, 0x02, + 0x90, 0x04, 0xf8, 0x05, 0x57, 0x06, 0xe7, 0x06, 0x8b, 0x06, 0x1c, 0x06, + 0xa2, 0x04, 0x83, 0x01, 0x02, 0x00, 0x0a, 0x00, 0x93, 0xff, 0x33, 0x00, + 0x5d, 0x01, 0xca, 0x01, 0xf6, 0x03, 0x01, 0x05, 0x19, 0x04, 0x75, 0x03, + 0x6a, 0x01, 0x16, 0x00, 0xdf, 0x00, 0x7d, 0x01, 0x62, 0x03, 0xd0, 0x04, + 0xd9, 0x04, 0x87, 0x05, 0x80, 0x04, 0x93, 0x02, 0x16, 0x01, 0x78, 0xfd, + 0x78, 0xf8, 0x54, 0xf6, 0xc0, 0xf5, 0xf8, 0xf6, 0x26, 0xfb, 0x98, 0xfd, + 0xec, 0xfe, 0x8b, 0x00, 0x28, 0xff, 0xfc, 0xfa, 0xdb, 0xf6, 0x2f, 0xf2, + 0x31, 0xee, 0xa0, 0xe9, 0xaa, 0xe5, 0x96, 0xe5, 0xb1, 0xe6, 0x61, 0xe9, + 0xba, 0xec, 0xa3, 0xef, 0x95, 0xf2, 0x97, 0xf6, 0x69, 0xf8, 0x21, 0xf8, + 0xac, 0xf7, 0xf6, 0xf4, 0xb0, 0xf4, 0x74, 0xf4, 0x3b, 0xf3, 0x07, 0xf4, + 0x26, 0xf4, 0xc2, 0xf2, 0x42, 0xf2, 0xfb, 0xf1, 0x4a, 0xf0, 0x81, 0xef, + 0x61, 0xee, 0x43, 0xef, 0xba, 0xf1, 0x55, 0xf2, 0x3b, 0xf3, 0x82, 0xf4, + 0x63, 0xf5, 0xa6, 0xf6, 0x05, 0xf6, 0x77, 0xf3, 0xd2, 0xf1, 0x2f, 0xef, + 0x01, 0xee, 0xe1, 0xee, 0xc8, 0xed, 0xb3, 0xed, 0x38, 0xee, 0x42, 0xed, + 0x3a, 0xec, 0x00, 0xea, 0x85, 0xe6, 0x14, 0xe5, 0x4e, 0xe5, 0x5d, 0xe6, + 0x5a, 0xe8, 0x74, 0xe9, 0xf3, 0xea, 0xcf, 0xef, 0xca, 0xf3, 0x66, 0xf5, + 0x41, 0xf7, 0x4e, 0xf7, 0x81, 0xf7, 0x72, 0xf8, 0xbf, 0xf7, 0xdd, 0xf7, + 0xfd, 0xf8, 0x3c, 0xf9, 0xb1, 0xfa, 0x6e, 0xfb, 0x46, 0xfa, 0xc0, 0xfa, + 0x3f, 0xfb, 0xde, 0xfa, 0xfc, 0xfa, 0xeb, 0xfa, 0xfd, 0xfa, 0x0f, 0xfc, + 0x79, 0xfc, 0x2f, 0xfe, 0x0b, 0x00, 0xc4, 0xfe, 0xc6, 0xff, 0x58, 0x01, + 0x13, 0x01, 0xf6, 0x00, 0xc2, 0xff, 0x68, 0xfe, 0xe7, 0xfe, 0x51, 0xff, + 0x8d, 0xfe, 0x82, 0xfd, 0x74, 0xfa, 0x69, 0xf8, 0x47, 0xf8, 0x5b, 0xf7, + 0xad, 0xf6, 0x52, 0xf6, 0xbd, 0xf5, 0xdc, 0xf6, 0xdb, 0xf9, 0x99, 0xfb, + 0xfe, 0xfd, 0xf2, 0xff, 0x2c, 0x01, 0xf6, 0x03, 0x7b, 0x05, 0xb5, 0x06, + 0xe4, 0x08, 0x29, 0x0a, 0xe5, 0x0a, 0x3b, 0x0c, 0x9c, 0x0b, 0x60, 0x0c, + 0xee, 0x0c, 0x79, 0x0a, 0xb1, 0x08, 0x57, 0x05, 0x38, 0x02, 0x61, 0x02, + 0xe7, 0x03, 0x94, 0x05, 0x4f, 0x08, 0x35, 0x09, 0x81, 0x08, 0x6b, 0x09, + 0xb5, 0x08, 0x81, 0x08, 0xf5, 0x09, 0xbb, 0x0a, 0x9b, 0x0c, 0x15, 0x0f, + 0xc1, 0x0f, 0x36, 0x11, 0xf6, 0x11, 0x41, 0x11, 0x53, 0x12, 0x2c, 0x12, + 0xf7, 0x12, 0xc0, 0x14, 0x96, 0x13, 0xf7, 0x12, 0xad, 0x13, 0xfa, 0x12, + 0x6b, 0x13, 0xdf, 0x13, 0xac, 0x12, 0x0f, 0x13, 0x56, 0x12, 0x42, 0x10, + 0x05, 0x10, 0x21, 0x10, 0x09, 0x0f, 0x80, 0x0d, 0xaf, 0x09, 0x26, 0x06, + 0x0e, 0x05, 0x4d, 0x03, 0x9c, 0x02, 0x69, 0x02, 0x2b, 0x02, 0xd5, 0x03, + 0x15, 0x07, 0x19, 0x09, 0x4d, 0x0b, 0xe5, 0x0c, 0x19, 0x0d, 0xc9, 0x0f, + 0xce, 0x11, 0xca, 0x13, 0x03, 0x15, 0x21, 0x14, 0xfd, 0x13, 0xd7, 0x13, + 0x3f, 0x12, 0x5a, 0x11, 0xb8, 0x10, 0xd6, 0x0e, 0xe5, 0x0d, 0x56, 0x0c, + 0x58, 0x09, 0x05, 0x07, 0x42, 0x04, 0x2f, 0x00, 0x94, 0xfd, 0x37, 0xfb, + 0x2f, 0xf9, 0x45, 0xfb, 0x4e, 0xfc, 0x83, 0xfc, 0x94, 0xfe, 0xc5, 0x00, + 0x77, 0x04, 0x93, 0x07, 0x08, 0x07, 0x37, 0x06, 0xf0, 0x05, 0x30, 0x04, + 0xa1, 0x02, 0x60, 0xff, 0xdd, 0xfa, 0xc2, 0xf8, 0xb4, 0xf7, 0x8c, 0xf7, + 0xf3, 0xf8, 0x46, 0xfa, 0xcd, 0xfc, 0x3f, 0x00, 0x68, 0x01, 0xa3, 0x02, + 0x21, 0x03, 0xa6, 0x02, 0xf0, 0x03, 0x42, 0x05, 0x36, 0x06, 0x34, 0x07, + 0x4e, 0x07, 0xbd, 0x07, 0x32, 0x08, 0x00, 0x06, 0x3a, 0x03, 0xcd, 0x02, + 0x5b, 0x01, 0x2b, 0x00, 0x1a, 0x01, 0xf9, 0x00, 0x1b, 0x02, 0x87, 0x04, + 0x15, 0x05, 0x2c, 0x06, 0xc2, 0x06, 0xa4, 0x05, 0xab, 0x06, 0x57, 0x07, + 0xd2, 0x07, 0x37, 0x0a, 0xb8, 0x0a, 0x07, 0x0c, 0x89, 0x0e, 0xa4, 0x0e, + 0x12, 0x0f, 0x45, 0x0f, 0x71, 0x0c, 0xd3, 0x0a, 0x81, 0x09, 0x64, 0x05, + 0xc0, 0x02, 0xf8, 0x00, 0x49, 0x00, 0xec, 0x01, 0x2e, 0x03, 0xd1, 0x04, + 0x8e, 0x06, 0xb6, 0x05, 0x30, 0x04, 0x36, 0x03, 0x0d, 0x00, 0xa5, 0xfd, + 0xa0, 0xfc, 0x56, 0xfc, 0x8f, 0xfd, 0xc6, 0xfe, 0xb6, 0xff, 0xee, 0x01, + 0x74, 0x04, 0x10, 0x05, 0x0c, 0x07, 0x92, 0x07, 0x11, 0x07, 0x93, 0x08, + 0x0b, 0x08, 0x5f, 0x08, 0x68, 0x09, 0xc1, 0x08, 0x54, 0x09, 0xd5, 0x09, + 0x8d, 0x09, 0xb8, 0x0b, 0x92, 0x0e, 0x94, 0x10, 0x1a, 0x14, 0xe8, 0x16, + 0x40, 0x18, 0x5d, 0x19, 0xdd, 0x17, 0x14, 0x15, 0x74, 0x13, 0x8d, 0x10, + 0x99, 0x0e, 0xaf, 0x0e, 0xae, 0x0d, 0xf2, 0x0d, 0xe1, 0x0d, 0x44, 0x0c, + 0x50, 0x0c, 0x28, 0x0c, 0x05, 0x0c, 0xbc, 0x0e, 0xc7, 0x10, 0xb8, 0x11, + 0x2e, 0x13, 0x64, 0x12, 0xc7, 0x11, 0x91, 0x11, 0xf5, 0x0f, 0x5c, 0x0f, + 0x2f, 0x0f, 0xd6, 0x0d, 0x55, 0x0e, 0xb0, 0x0e, 0x6c, 0x0d, 0x49, 0x0e, + 0x78, 0x0e, 0xf5, 0x0d, 0x71, 0x0e, 0x64, 0x0d, 0x0c, 0x0d, 0x7c, 0x0e, + 0x98, 0x0e, 0xc4, 0x0e, 0x17, 0x0f, 0xa9, 0x0c, 0x35, 0x0b, 0xff, 0x09, + 0x52, 0x07, 0x24, 0x06, 0x98, 0x04, 0xa4, 0x02, 0xe7, 0x01, 0xeb, 0x00, + 0x38, 0x00, 0x32, 0x00, 0x94, 0xfe, 0xed, 0xfd, 0x45, 0xff, 0xdb, 0xfe, + 0xf0, 0xfe, 0xda, 0x00, 0xcc, 0x02, 0xf6, 0x05, 0xdb, 0x08, 0x53, 0x09, + 0x10, 0x0b, 0xef, 0x0b, 0xf2, 0x0a, 0xaf, 0x0b, 0xba, 0x0b, 0x2c, 0x0c, + 0xa7, 0x0d, 0x5d, 0x0d, 0x80, 0x0c, 0x36, 0x0c, 0x06, 0x0b, 0xba, 0x09, + 0x86, 0x08, 0xda, 0x06, 0x2d, 0x06, 0x3e, 0x05, 0x50, 0x04, 0x9a, 0x04, + 0x49, 0x04, 0xa8, 0x03, 0x9f, 0x04, 0xe9, 0x04, 0xb3, 0x04, 0x15, 0x05, + 0xdb, 0x03, 0xd5, 0x03, 0x67, 0x04, 0x66, 0x03, 0x9a, 0x04, 0x57, 0x06, + 0x26, 0x08, 0x76, 0x0b, 0xf0, 0x0d, 0xc8, 0x0f, 0xb4, 0x10, 0x1b, 0x10, + 0x1d, 0x0f, 0xd8, 0x0e, 0x3e, 0x0e, 0x9d, 0x0e, 0x96, 0x10, 0xaa, 0x10, + 0x9d, 0x11, 0xb0, 0x13, 0x7c, 0x14, 0x74, 0x16, 0x42, 0x17, 0x0a, 0x16, + 0x84, 0x16, 0x55, 0x16, 0xfd, 0x14, 0x2d, 0x15, 0x84, 0x14, 0x6b, 0x14, + 0x54, 0x15, 0x87, 0x13, 0x67, 0x12, 0x83, 0x12, 0xa8, 0x11, 0x4d, 0x11, + 0x9d, 0x10, 0xa9, 0x0e, 0x42, 0x0e, 0xfc, 0x0d, 0xb5, 0x0b, 0x19, 0x0a, + 0xa1, 0x07, 0xab, 0x03, 0x33, 0x02, 0xa4, 0x00, 0x5d, 0xfe, 0x13, 0xfe, + 0x0d, 0xfd, 0x48, 0xfd, 0x81, 0xff, 0xde, 0xff, 0x40, 0x01, 0x1d, 0x03, + 0xe2, 0x02, 0xe6, 0x03, 0x73, 0x04, 0x72, 0x03, 0x62, 0x04, 0xc0, 0x03, + 0x77, 0x02, 0x2a, 0x03, 0x70, 0x02, 0x9c, 0x02, 0x88, 0x04, 0x75, 0x05, + 0x5b, 0x06, 0x59, 0x07, 0x28, 0x07, 0xae, 0x08, 0x5d, 0x0b, 0x59, 0x0d, + 0x99, 0x0f, 0x53, 0x0f, 0x8a, 0x0e, 0x2d, 0x0e, 0x69, 0x0b, 0xc6, 0x07, + 0x18, 0x04, 0x37, 0x00, 0x28, 0xff, 0x9d, 0x00, 0xf3, 0x00, 0xb0, 0x02, + 0xab, 0x04, 0xc6, 0x04, 0x3a, 0x05, 0x4d, 0x04, 0xa3, 0x01, 0x1e, 0xff, + 0xf2, 0xfc, 0xcb, 0xfb, 0x90, 0xfc, 0x92, 0xfc, 0x15, 0xfc, 0x74, 0xfc, + 0xf0, 0xfa, 0x4c, 0xf9, 0xca, 0xf7, 0x5d, 0xf5, 0x78, 0xf4, 0xfe, 0xf3, + 0xac, 0xf2, 0x2d, 0xf3, 0x41, 0xf4, 0xf1, 0xf5, 0xe9, 0xf9, 0x09, 0xfc, + 0x80, 0xfb, 0x24, 0xfb, 0x02, 0xfa, 0xe9, 0xf9, 0x2b, 0xfb, 0x2e, 0xfa, + 0xe3, 0xf9, 0x8f, 0xfa, 0x73, 0xfa, 0x89, 0xfb, 0x7f, 0xfb, 0x1a, 0xfa, + 0x8d, 0xfa, 0xe0, 0xfa, 0xd3, 0xfa, 0x3e, 0xfc, 0x42, 0xfc, 0xb3, 0xfb, + 0xe2, 0xfb, 0x63, 0xfb, 0x57, 0xfc, 0x01, 0xfe, 0x14, 0xfe, 0x31, 0xfe, + 0x84, 0xfe, 0x91, 0xfc, 0x9f, 0xfb, 0xe2, 0xf9, 0x0f, 0xf6, 0x7b, 0xf5, + 0x8d, 0xf5, 0x12, 0xf6, 0xdc, 0xf8, 0x6a, 0xfa, 0x4f, 0xfc, 0x60, 0xff, + 0x16, 0x01, 0x1a, 0x03, 0xd7, 0x05, 0xeb, 0x07, 0x2b, 0x0a, 0xfe, 0x0b, + 0x17, 0x0d, 0x6f, 0x0f, 0xce, 0x10, 0xf4, 0x10, 0xa2, 0x12, 0xbb, 0x12, + 0x84, 0x11, 0xc2, 0x10, 0x8a, 0x0e, 0x18, 0x0d, 0x7d, 0x0c, 0x9f, 0x0a, + 0x9f, 0x09, 0xd2, 0x09, 0x75, 0x09, 0x0b, 0x0a, 0x14, 0x0b, 0xa0, 0x0a, + 0x7a, 0x0a, 0xd0, 0x09, 0x99, 0x08, 0x24, 0x0a, 0x61, 0x0b, 0x9d, 0x0c, + 0x38, 0x0f, 0x2a, 0x11, 0xf3, 0x13, 0x5e, 0x15, 0xca, 0x13, 0xbf, 0x12, + 0xd1, 0x11, 0xba, 0x10, 0xa5, 0x10, 0x16, 0x0f, 0x3c, 0x0c, 0x66, 0x0b, + 0x89, 0x09, 0xb9, 0x06, 0x60, 0x05, 0x41, 0x02, 0xa7, 0xff, 0x06, 0xfe, + 0x81, 0xfa, 0xfd, 0xf8, 0xc3, 0xf8, 0x84, 0xf7, 0x9b, 0xf7, 0x94, 0xf7, + 0x83, 0xf6, 0x04, 0xf7, 0x11, 0xf8, 0xf7, 0xf8, 0xac, 0xfa, 0xf6, 0xfa, + 0x2c, 0xfb, 0x08, 0xfd, 0xf9, 0xfd, 0x13, 0xff, 0x4a, 0xff, 0xd3, 0xfd, + 0xed, 0xfd, 0xdc, 0xfd, 0x25, 0xfd, 0xdc, 0xfd, 0x4d, 0xfe, 0x88, 0xfe, + 0xc5, 0x00, 0xad, 0x02, 0x5d, 0x03, 0xbd, 0x04, 0x37, 0x04, 0xb0, 0x02, + 0xd5, 0x01, 0xbc, 0xff, 0x16, 0xfe, 0xe2, 0xfc, 0xad, 0xf9, 0xe6, 0xf7, + 0x02, 0xf7, 0xcf, 0xf5, 0xf0, 0xf6, 0xc5, 0xf7, 0xe1, 0xf7, 0xaa, 0xf8, + 0x5c, 0xf8, 0x56, 0xf7, 0xfc, 0xf6, 0x0b, 0xf6, 0x61, 0xf5, 0xae, 0xf5, + 0x34, 0xf4, 0x94, 0xf2, 0xe0, 0xf1, 0x3d, 0xf0, 0xba, 0xee, 0x36, 0xec, + 0x3c, 0xe9, 0x9e, 0xe8, 0xc3, 0xe8, 0x7d, 0xe9, 0x53, 0xeb, 0xe1, 0xeb, + 0x00, 0xed, 0xb5, 0xef, 0xac, 0xf1, 0xf0, 0xf3, 0x7f, 0xf5, 0x24, 0xf5, + 0xaf, 0xf5, 0x59, 0xf6, 0x15, 0xf6, 0x2e, 0xf6, 0xa9, 0xf5, 0xa2, 0xf4, + 0x4b, 0xf4, 0xf9, 0xf2, 0x4b, 0xf1, 0x0f, 0xf1, 0xaf, 0xee, 0x59, 0xec, + 0xca, 0xeb, 0x74, 0xea, 0xcd, 0xea, 0x45, 0xec, 0xd2, 0xec, 0xc7, 0xed, + 0x8d, 0xed, 0x4b, 0xec, 0xe7, 0xec, 0xfd, 0xec, 0x47, 0xed, 0x5a, 0xef, + 0x53, 0xf0, 0xc7, 0xf1, 0xe1, 0xf3, 0xd5, 0xf4, 0x6a, 0xf5, 0x32, 0xf6, + 0xbb, 0xf5, 0x9e, 0xf5, 0xbf, 0xf5, 0x8a, 0xf4, 0x37, 0xf5, 0x54, 0xf6, + 0x02, 0xf7, 0x99, 0xf8, 0xc5, 0xf9, 0xee, 0xfb, 0x79, 0xff, 0xb4, 0x01, + 0x29, 0x03, 0x38, 0x04, 0xf1, 0x03, 0x14, 0x05, 0x0f, 0x06, 0xa8, 0x05, + 0x57, 0x06, 0xda, 0x06, 0x8f, 0x06, 0x6c, 0x06, 0x80, 0x05, 0x43, 0x03, + 0x45, 0x01, 0x9b, 0xfe, 0xf4, 0xfc, 0x7c, 0xfd, 0x7a, 0xfd, 0x97, 0xfd, + 0x53, 0xfe, 0x0c, 0x00, 0xa1, 0x03, 0xdd, 0x06, 0x2a, 0x08, 0xe1, 0x08, + 0x15, 0x08, 0xee, 0x05, 0xfc, 0x03, 0xd9, 0x00, 0x63, 0xfd, 0xd3, 0xfa, + 0xf7, 0xf7, 0xa8, 0xf7, 0x31, 0xf9, 0xb2, 0xf8, 0x73, 0xf8, 0x1e, 0xf9, + 0xae, 0xf8, 0x72, 0xf7, 0x24, 0xf6, 0xa2, 0xf4, 0xf2, 0xf4, 0x10, 0xf7, + 0x03, 0xf9, 0x0b, 0xfb, 0xa2, 0xfa, 0x60, 0xfa, 0xfd, 0xfa, 0x17, 0xf9, + 0x8b, 0xf7, 0xd5, 0xf5, 0x05, 0xf4, 0x10, 0xf4, 0x12, 0xf5, 0x36, 0xf5, + 0x9a, 0xf6, 0xee, 0xf8, 0x43, 0xf9, 0x69, 0xfa, 0x95, 0xf9, 0x79, 0xf6, + 0x5c, 0xf5, 0x97, 0xf3, 0xbd, 0xf2, 0xcc, 0xf3, 0x90, 0xf4, 0x7c, 0xf7, + 0xb4, 0xfb, 0x88, 0xfe, 0xaa, 0x01, 0xf8, 0x03, 0x3b, 0x04, 0x38, 0x05, + 0x92, 0x03, 0x9f, 0xff, 0x09, 0xfd, 0x9f, 0xf9, 0x83, 0xf7, 0x3b, 0xf7, + 0x94, 0xf5, 0xda, 0xf4, 0xe5, 0xf4, 0xa7, 0xf4, 0x66, 0xf5, 0x0b, 0xf6, + 0x35, 0xf5, 0x4d, 0xf5, 0x1f, 0xf6, 0x76, 0xf6, 0xb8, 0xf7, 0x17, 0xf8, + 0x74, 0xf7, 0x36, 0xf7, 0xc8, 0xf4, 0x7e, 0xf1, 0xb6, 0xef, 0x65, 0xed, + 0x1f, 0xec, 0xa1, 0xec, 0x1c, 0xed, 0x22, 0xf0, 0xa6, 0xf3, 0x5f, 0xf5, + 0x55, 0xf7, 0xe7, 0xf7, 0x43, 0xf8, 0x2d, 0xfa, 0x43, 0xfb, 0xb1, 0xfc, + 0x9d, 0xff, 0xec, 0x00, 0x71, 0x01, 0x1b, 0x02, 0x5f, 0x00, 0x41, 0xfe, + 0x16, 0xfc, 0x73, 0xf8, 0x26, 0xf5, 0x7a, 0xf1, 0x56, 0xed, 0xc2, 0xeb, + 0x90, 0xeb, 0x46, 0xeb, 0xe9, 0xec, 0x2e, 0xef, 0x1b, 0xf1, 0xf7, 0xf3, + 0x5e, 0xf5, 0x04, 0xf6, 0xba, 0xf6, 0x4f, 0xf5, 0x2b, 0xf4, 0xf0, 0xf2, + 0xfc, 0xef, 0xfb, 0xef, 0x62, 0xf1, 0x57, 0xf1, 0x10, 0xf2, 0xce, 0xf1, + 0x2b, 0xf1, 0x81, 0xf1, 0x24, 0xf0, 0x2e, 0xee, 0xe9, 0xed, 0x67, 0xed, + 0x5e, 0xee, 0x83, 0xf1, 0x4b, 0xf3, 0x57, 0xf5, 0xa3, 0xf7, 0x32, 0xf9, + 0x48, 0xfb, 0xce, 0xfb, 0x6f, 0xfa, 0xb8, 0xf9, 0xed, 0xf7, 0x63, 0xf6, + 0xf2, 0xf6, 0x62, 0xf6, 0x61, 0xf6, 0x86, 0xf7, 0xfb, 0xf7, 0x13, 0xf9, + 0x9d, 0xfa, 0xb8, 0xfa, 0xb3, 0xfa, 0xc3, 0xf9, 0x80, 0xf6, 0xf7, 0xf5, + 0xdc, 0xf4, 0x7e, 0xf2, 0x57, 0xf2, 0x91, 0xf1, 0x07, 0xf2, 0x82, 0xf3, + 0x70, 0xf4, 0x8e, 0xf5, 0x06, 0xf6, 0x98, 0xf4, 0x1d, 0xf4, 0xa1, 0xf4, + 0x03, 0xf4, 0xaa, 0xf4, 0x56, 0xf6, 0x8d, 0xf8, 0x38, 0xfc, 0x66, 0xff, + 0x27, 0x01, 0x15, 0x03, 0xa1, 0x03, 0x70, 0x03, 0x2d, 0x04, 0x5c, 0x03, + 0x90, 0x02, 0xb5, 0x01, 0xa8, 0xff, 0x31, 0xfe, 0xf0, 0xfc, 0xe5, 0xfa, + 0xc5, 0xfa, 0xb7, 0xfb, 0xfa, 0xfb, 0x29, 0xfe, 0x1c, 0xff, 0x6c, 0xff, + 0x7e, 0x01, 0x7f, 0x01, 0x6c, 0x01, 0x62, 0x02, 0x5e, 0x01, 0x39, 0x01, + 0x78, 0x01, 0xc7, 0xff, 0x74, 0xff, 0x46, 0xff, 0xaf, 0xfe, 0x06, 0x00, + 0x89, 0x01, 0x7c, 0x02, 0xb6, 0x04, 0xf9, 0x05, 0xcb, 0x06, 0x94, 0x08, + 0xdc, 0x07, 0xd4, 0x07, 0xd1, 0x08, 0x65, 0x08, 0x04, 0x09, 0x6c, 0x09, + 0xc6, 0x07, 0xa0, 0x06, 0x90, 0x06, 0x6c, 0x05, 0xbf, 0x05, 0x0d, 0x05, + 0x8a, 0x02, 0xe5, 0x01, 0x20, 0x01, 0x9a, 0x00, 0x92, 0x01, 0x70, 0x02, + 0x00, 0x05, 0xb9, 0x08, 0x54, 0x0a, 0xeb, 0x0b, 0x87, 0x0c, 0x2a, 0x0b, + 0x34, 0x0a, 0xfa, 0x07, 0x98, 0x04, 0x4c, 0x02, 0xdb, 0xff, 0x93, 0xfd, + 0xbb, 0xfd, 0x27, 0xfd, 0x19, 0xfd, 0x8f, 0xfe, 0x03, 0xff, 0x26, 0x00, + 0x6b, 0x01, 0x07, 0x02, 0x74, 0x03, 0x61, 0x04, 0xbe, 0x03, 0xbd, 0x04, + 0x25, 0x05, 0x61, 0x05, 0x1f, 0x07, 0x59, 0x06, 0x88, 0x04, 0xbf, 0x03, + 0x07, 0x02, 0x9a, 0x00, 0xc3, 0x00, 0x61, 0x00, 0x5f, 0x01, 0x0e, 0x03, + 0x27, 0x04, 0x68, 0x07, 0x98, 0x09, 0x43, 0x09, 0x35, 0x09, 0x9a, 0x07, + 0x0b, 0x05, 0x94, 0x04, 0xa7, 0x02, 0x54, 0x01, 0x38, 0x00, 0x6a, 0xfc, + 0x35, 0xfa, 0x18, 0xf9, 0x93, 0xf7, 0x87, 0xf7, 0xad, 0xf7, 0xa4, 0xf6, + 0xe8, 0xf6, 0xa4, 0xf7, 0x00, 0xf8, 0xd7, 0xf8, 0x44, 0xf8, 0xe8, 0xf7, + 0x88, 0xf9, 0x4f, 0xfb, 0xb3, 0xfc, 0x34, 0xfe, 0x63, 0xfd, 0x5c, 0xfd, + 0xf2, 0xfd, 0xa3, 0xfd, 0x26, 0xff, 0xc4, 0xff, 0x66, 0xfe, 0x9a, 0xfe, + 0x85, 0xfd, 0x57, 0xfa, 0x2b, 0xf9, 0x43, 0xf7, 0x90, 0xf5, 0x19, 0xf6, + 0xd8, 0xf4, 0xea, 0xf4, 0xe4, 0xf7, 0x98, 0xf9, 0xad, 0xfc, 0xd8, 0x00, + 0xb3, 0x02, 0xb2, 0x05, 0x31, 0x07, 0x86, 0x06, 0x4f, 0x06, 0x79, 0x04, + 0x9c, 0x02, 0x2f, 0x02, 0xd8, 0x01, 0x9c, 0x02, 0x8a, 0x04, 0x92, 0x04, + 0xe8, 0x04, 0xda, 0x05, 0xf1, 0x04, 0x72, 0x05, 0x96, 0x06, 0xe4, 0x05, + 0x10, 0x06, 0xf4, 0x04, 0xdf, 0x02, 0x14, 0x04, 0x39, 0x03, 0x7e, 0x01, + 0x2e, 0x02, 0xb9, 0x00, 0x05, 0x00, 0x43, 0x01, 0x4a, 0x00, 0xc4, 0xff, + 0x2b, 0xff, 0x1f, 0xfd, 0x82, 0xfd, 0xcd, 0xfd, 0xc6, 0xfd, 0x61, 0xff, + 0x71, 0x00, 0x23, 0x00, 0xb9, 0x00, 0x39, 0x00, 0x23, 0xff, 0xdc, 0xff, + 0xf7, 0xff, 0x15, 0x01, 0x41, 0x03, 0x5e, 0x04, 0x07, 0x07, 0x8b, 0x09, + 0x49, 0x09, 0x4a, 0x0a, 0x18, 0x0c, 0x3e, 0x0c, 0x55, 0x0d, 0xaa, 0x0c, + 0xde, 0x0a, 0xae, 0x0a, 0xa0, 0x09, 0x9b, 0x09, 0x2e, 0x0b, 0x04, 0x0b, + 0x29, 0x0c, 0x99, 0x0d, 0x14, 0x0d, 0x1d, 0x0e, 0x98, 0x0e, 0x22, 0x0d, + 0x9c, 0x0c, 0xd5, 0x0a, 0xb0, 0x07, 0x11, 0x07, 0x26, 0x05, 0x15, 0x02, + 0x07, 0x01, 0x9a, 0xfe, 0x7c, 0xfd, 0x09, 0xfe, 0xcb, 0xfd, 0xd1, 0xfe, + 0x5e, 0x00, 0x37, 0x00, 0x67, 0x01, 0x6e, 0x02, 0xc3, 0x01, 0x8d, 0x03, + 0x5e, 0x04, 0xd5, 0x04, 0x24, 0x08, 0x9a, 0x0a, 0xa1, 0x0c, 0xea, 0x0e, + 0x1d, 0x0f, 0xe4, 0x0e, 0x0d, 0x0f, 0xed, 0x0c, 0xe7, 0x0b, 0x03, 0x0c, + 0xcb, 0x0a, 0x8f, 0x0b, 0x39, 0x0c, 0xc4, 0x0b, 0x2f, 0x0d, 0x5a, 0x0d, + 0x88, 0x0c, 0x86, 0x0c, 0xf3, 0x0a, 0x3d, 0x09, 0x9e, 0x08, 0xd5, 0x07, + 0xdb, 0x07, 0x30, 0x09, 0xba, 0x09, 0x2c, 0x0b, 0x52, 0x0d, 0x3e, 0x0d, + 0x5a, 0x0e, 0x62, 0x0e, 0xf0, 0x0c, 0x38, 0x0e, 0x5e, 0x0d, 0xc2, 0x0b, + 0x0c, 0x0c, 0xf8, 0x09, 0x90, 0x08, 0x9f, 0x08, 0xf0, 0x07, 0x52, 0x08, + 0xf7, 0x08, 0xf0, 0x08, 0x7a, 0x0a, 0x10, 0x0d, 0xa2, 0x0d, 0x3b, 0x0e, + 0x8a, 0x0e, 0x57, 0x0e, 0xf8, 0x0f, 0x3e, 0x10, 0x39, 0x10, 0xa9, 0x11, + 0x99, 0x10, 0x60, 0x10, 0x67, 0x11, 0xb9, 0x10, 0xc7, 0x11, 0x0d, 0x12, + 0x87, 0x10, 0xcb, 0x10, 0x63, 0x11, 0xc3, 0x10, 0xee, 0x10, 0x19, 0x11, + 0xb9, 0x10, 0x7d, 0x12, 0xa5, 0x12, 0x0e, 0x12, 0x64, 0x12, 0x36, 0x10, + 0xe5, 0x0e, 0xf3, 0x0e, 0x6b, 0x0d, 0xdd, 0x0c, 0xbf, 0x0c, 0xfd, 0x0b, + 0x31, 0x0d, 0x16, 0x0d, 0xb7, 0x0b, 0xb1, 0x0b, 0x52, 0x0a, 0x33, 0x09, + 0x97, 0x08, 0x0f, 0x06, 0xf4, 0x03, 0x70, 0x03, 0x4d, 0x01, 0x07, 0x00, + 0x1f, 0x00, 0xa5, 0xfe, 0x1c, 0xff, 0xea, 0xff, 0xdb, 0xff, 0xfe, 0x00, + 0x8f, 0x01, 0x69, 0x01, 0xf9, 0x01, 0xac, 0x01, 0x8d, 0x01, 0x12, 0x02, + 0xcf, 0x00, 0x66, 0x00, 0xaf, 0x00, 0x2e, 0xff, 0xd7, 0xfe, 0x71, 0xfe, + 0x6d, 0xfc, 0xe8, 0xfb, 0x6e, 0xfb, 0x7c, 0xfa, 0xea, 0xfb, 0x76, 0xfc, + 0x1b, 0xfc, 0x8a, 0xfd, 0x7f, 0xfe, 0x80, 0xff, 0xb7, 0x01, 0x45, 0x02, + 0x36, 0x03, 0x2d, 0x05, 0x9f, 0x04, 0x46, 0x04, 0x93, 0x03, 0xf2, 0x01, + 0x7c, 0x02, 0x6f, 0x02, 0x1b, 0x01, 0x65, 0x01, 0x6e, 0x01, 0xbc, 0x00, + 0x16, 0x01, 0xd1, 0x00, 0x21, 0x02, 0x6a, 0x04, 0x25, 0x03, 0xa7, 0x02, + 0x74, 0x02, 0x09, 0x00, 0xbc, 0xfe, 0xc5, 0xfc, 0x2f, 0xfa, 0x53, 0xf9, + 0x41, 0xf8, 0xb2, 0xf7, 0xf3, 0xf8, 0xf0, 0xf9, 0xce, 0xfa, 0xd2, 0xfc, + 0x14, 0xfe, 0xee, 0xff, 0x0e, 0x03, 0x81, 0x03, 0x39, 0x04, 0x1c, 0x05, + 0x03, 0x04, 0x9f, 0x04, 0x77, 0x04, 0xf6, 0x03, 0xac, 0x05, 0x75, 0x06, + 0x57, 0x07, 0x02, 0x08, 0x99, 0x06, 0xcb, 0x06, 0x3d, 0x08, 0xa6, 0x06, + 0x7b, 0x05, 0x96, 0x06, 0x5c, 0x06, 0x41, 0x07, 0x57, 0x07, 0x04, 0x06, + 0xbb, 0x06, 0x6c, 0x06, 0x21, 0x05, 0xb5, 0x04, 0x7c, 0x03, 0xd4, 0x01, + 0x48, 0x01, 0x9c, 0xff, 0x01, 0xfe, 0xc6, 0xfd, 0xf5, 0xfc, 0xbe, 0xfd, + 0x59, 0xfe, 0x2d, 0xfe, 0x35, 0xff, 0xd7, 0xff, 0xfb, 0xff, 0x7a, 0x01, + 0x1b, 0x02, 0x6e, 0x01, 0xf4, 0x01, 0x11, 0x02, 0xb0, 0x02, 0x95, 0x03, + 0xa5, 0x03, 0x4f, 0x05, 0x5e, 0x07, 0xcd, 0x08, 0x5c, 0x0b, 0x24, 0x0e, + 0xce, 0x0f, 0x99, 0x11, 0xf8, 0x11, 0x0b, 0x11, 0x04, 0x11, 0x86, 0x0f, + 0x8b, 0x0d, 0xd4, 0x0d, 0x97, 0x0d, 0x57, 0x0d, 0x05, 0x0e, 0xca, 0x0c, + 0xbf, 0x0b, 0x5d, 0x0b, 0xe7, 0x0a, 0x26, 0x0b, 0xc5, 0x0a, 0xb4, 0x09, + 0xd1, 0x09, 0x54, 0x09, 0x4f, 0x08, 0x04, 0x08, 0x00, 0x06, 0xfb, 0x04, + 0x20, 0x05, 0xd3, 0x03, 0x0d, 0x04, 0x2e, 0x05, 0xbd, 0x04, 0xf4, 0x04, + 0xa9, 0x05, 0x5e, 0x05, 0xd8, 0x05, 0x5e, 0x04, 0xaf, 0x02, 0x3b, 0x03, + 0xba, 0x02, 0x3f, 0x02, 0x54, 0x02, 0x3a, 0x01, 0x3e, 0x01, 0x59, 0x01, + 0x0f, 0xff, 0xaf, 0xfd, 0x07, 0xfc, 0x85, 0xf9, 0xf1, 0xf8, 0x38, 0xf8, + 0xef, 0xf7, 0x7e, 0xf9, 0x16, 0xfa, 0x25, 0xfa, 0x7f, 0xfb, 0x4c, 0xfb, + 0x7e, 0xfa, 0x67, 0xfb, 0x2b, 0xfb, 0xa7, 0xfb, 0xc4, 0xfc, 0x1c, 0xfc, + 0x37, 0xfd, 0xa5, 0xfe, 0x43, 0xfe, 0xca, 0xff, 0x12, 0x01, 0x13, 0x01, + 0x79, 0x02, 0xaf, 0x02, 0x37, 0x02, 0x3f, 0x03, 0x8e, 0x02, 0xc4, 0x00, + 0xe8, 0xff, 0x38, 0xfe, 0xce, 0xfd, 0xb0, 0xfd, 0x59, 0xfc, 0x70, 0xfc, + 0xc0, 0xfb, 0x90, 0xfa, 0x30, 0xfb, 0xa0, 0xfa, 0x8d, 0xf9, 0x45, 0xfa, + 0x12, 0xfb, 0x6c, 0xfc, 0x20, 0xff, 0x5f, 0x00, 0x02, 0x01, 0xc9, 0x01, + 0x8c, 0x01, 0x44, 0x01, 0xb3, 0xff, 0x56, 0xfd, 0xac, 0xfc, 0xf5, 0xfb, + 0x47, 0xfa, 0x4b, 0xfa, 0xee, 0xf9, 0x56, 0xf9, 0x50, 0xfb, 0xfe, 0xfc, + 0x21, 0xff, 0xfd, 0x01, 0xd3, 0x03, 0xca, 0x05, 0x16, 0x07, 0x22, 0x06, + 0x6a, 0x05, 0xb2, 0x04, 0x50, 0x03, 0xdf, 0x03, 0xb1, 0x02, 0x24, 0x00, + 0xa9, 0xff, 0x21, 0xfe, 0xbd, 0xfb, 0x6b, 0xfb, 0x0a, 0xfb, 0xa4, 0xfa, + 0x79, 0xfb, 0xfd, 0xfa, 0xa6, 0xfc, 0x71, 0xfe, 0xce, 0xfd, 0x4c, 0xfe, + 0xdc, 0xfd, 0xfd, 0xfb, 0x6b, 0xfb, 0x13, 0xfb, 0xcd, 0xfa, 0x2d, 0xfc, + 0xf3, 0xfb, 0xeb, 0xfb, 0xec, 0xfc, 0x27, 0xfc, 0xcc, 0xfb, 0x6c, 0xfb, + 0x56, 0xfa, 0x03, 0xfa, 0xeb, 0xf9, 0x0b, 0xfa, 0x39, 0xfb, 0xa7, 0xfb, + 0xed, 0xfb, 0x09, 0xfe, 0x3c, 0x00, 0xef, 0x01, 0x84, 0x04, 0x84, 0x06, + 0x77, 0x08, 0x34, 0x0a, 0xd7, 0x08, 0xee, 0x07, 0x01, 0x07, 0x9c, 0x04, + 0x2b, 0x04, 0x47, 0x03, 0xf3, 0x01, 0x22, 0x03, 0xcb, 0x03, 0x46, 0x03, + 0x9c, 0x03, 0x52, 0x03, 0x6b, 0x03, 0x43, 0x04, 0xe5, 0x03, 0x31, 0x03, + 0x19, 0x03, 0xd5, 0x01, 0xee, 0x00, 0xf4, 0x00, 0x45, 0xff, 0x41, 0xff, + 0xda, 0xfe, 0x13, 0xfd, 0x71, 0xfd, 0xa0, 0xfc, 0xb8, 0xfb, 0xda, 0xfc, + 0x70, 0xfc, 0xa4, 0xfb, 0xbc, 0xfc, 0x24, 0xfc, 0xaa, 0xfb, 0x94, 0xfc, + 0x85, 0xfc, 0x23, 0xfd, 0x0a, 0xfe, 0xa4, 0xfd, 0x75, 0xfe, 0xff, 0xfe, + 0x05, 0xff, 0x74, 0x00, 0x5b, 0x00, 0x75, 0x00, 0x4c, 0x01, 0xf4, 0xff, + 0xa3, 0xfe, 0xbc, 0xfd, 0x1c, 0xfc, 0x85, 0xfb, 0x89, 0xfa, 0x1c, 0xf8, + 0x8b, 0xf7, 0xcc, 0xf6, 0x5c, 0xf5, 0xda, 0xf5, 0xcf, 0xf6, 0xea, 0xf6, + 0xe6, 0xf7, 0x72, 0xf8, 0xf5, 0xf8, 0x36, 0xfb, 0x5d, 0xfb, 0xf3, 0xfb, + 0xbb, 0xfd, 0xfb, 0xfd, 0x6b, 0xff, 0x0d, 0x00, 0xc6, 0xff, 0x50, 0x01, + 0x71, 0x02, 0xa7, 0x02, 0xdb, 0x03, 0x41, 0x03, 0x4f, 0x01, 0xc5, 0x00, + 0x5b, 0xff, 0x43, 0xfe, 0x48, 0xfe, 0xb9, 0xfb, 0xe0, 0xf9, 0x1a, 0xfa, + 0x26, 0xf9, 0x27, 0xf9, 0x43, 0xf8, 0x1f, 0xf5, 0x34, 0xf4, 0xe3, 0xf3, + 0x19, 0xf3, 0x25, 0xf4, 0xf5, 0xf3, 0x19, 0xf4, 0xcb, 0xf5, 0x9d, 0xf5, + 0x04, 0xf6, 0xb9, 0xf6, 0x35, 0xf5, 0xf7, 0xf4, 0xf4, 0xf5, 0x08, 0xf5, + 0x50, 0xf5, 0xa2, 0xf6, 0x12, 0xf7, 0x1c, 0xf8, 0x17, 0xf8, 0x3e, 0xf8, + 0x3b, 0xf9, 0x3b, 0xf8, 0xe1, 0xf6, 0xb3, 0xf6, 0x2b, 0xf6, 0x4e, 0xf7, + 0x23, 0xf8, 0x2a, 0xf6, 0xc4, 0xf5, 0x0f, 0xf5, 0x21, 0xf3, 0xf9, 0xf2, + 0xea, 0xf1, 0x22, 0xf1, 0x2a, 0xf3, 0xf3, 0xf3, 0xb9, 0xf4, 0xff, 0xf6, + 0x59, 0xf7, 0xfe, 0xf7, 0x7e, 0xf8, 0x44, 0xf7, 0x28, 0xf6, 0x4b, 0xf5, + 0x87, 0xf3, 0x1c, 0xf2, 0x7e, 0xf1, 0xa1, 0xf0, 0xb4, 0xf1, 0xf8, 0xf2, + 0x79, 0xf3, 0x7a, 0xf5, 0xb1, 0xf5, 0x74, 0xf5, 0xf6, 0xf5, 0x19, 0xf5, + 0x99, 0xf5, 0x7a, 0xf6, 0x7a, 0xf6, 0x5a, 0xf8, 0x72, 0xfa, 0xb8, 0xfb, + 0x49, 0xfd, 0x9f, 0xfc, 0x98, 0xfa, 0x1c, 0xfa, 0x64, 0xf9, 0xbe, 0xf7, + 0x8a, 0xf6, 0xb4, 0xf4, 0xd4, 0xf3, 0xd0, 0xf4, 0x2f, 0xf4, 0xe6, 0xf4, + 0x29, 0xf7, 0x68, 0xf7, 0xd2, 0xf8, 0xa3, 0xf9, 0xd2, 0xf9, 0xca, 0xfb, + 0xe8, 0xfc, 0x11, 0xfc, 0x54, 0xfc, 0x99, 0xfc, 0xb9, 0xfb, 0xca, 0xfb, + 0x12, 0xfa, 0xf6, 0xf8, 0xc3, 0xf9, 0x5f, 0xf9, 0x5d, 0xf9, 0xf7, 0xf9, + 0x35, 0xf9, 0xd4, 0xf9, 0x13, 0xfc, 0x9b, 0xfc, 0xd1, 0xfe, 0x9c, 0xfe, + 0x79, 0xfb, 0x33, 0xfa, 0x00, 0xf8, 0x79, 0xf6, 0x87, 0xf5, 0x4c, 0xf3, + 0x39, 0xf3, 0xda, 0xf3, 0xe1, 0xf2, 0xb2, 0xf3, 0x50, 0xf5, 0x66, 0xf6, + 0xad, 0xf8, 0x62, 0xfa, 0xdd, 0xfa, 0x38, 0xfd, 0xde, 0xfe, 0x74, 0xfe, + 0xeb, 0xff, 0xb9, 0xff, 0x68, 0xff, 0x77, 0xff, 0xfd, 0xfc, 0x9b, 0xfb, + 0xbd, 0xf9, 0xa6, 0xf6, 0x18, 0xf5, 0xbe, 0xf4, 0xc7, 0xf3, 0x4e, 0xf4, + 0x44, 0xf5, 0xbe, 0xf5, 0xe3, 0xf8, 0xc4, 0xfb, 0x9a, 0xfe, 0x54, 0x03, + 0x0d, 0x06, 0x80, 0x08, 0x88, 0x0b, 0x26, 0x0b, 0x78, 0x0a, 0xe8, 0x08, + 0x25, 0x05, 0xb8, 0x03, 0x47, 0x02, 0xbe, 0x00, 0x3c, 0x01, 0xbd, 0x00, + 0x9d, 0xff, 0xbf, 0xff, 0x84, 0xfe, 0x02, 0xfd, 0x6a, 0xfc, 0x7b, 0xfa, + 0xb1, 0xf9, 0x81, 0xfa, 0x57, 0xfa, 0xc4, 0xfa, 0xa6, 0xfb, 0xf2, 0xfa, + 0xfb, 0xfb, 0xa6, 0xfc, 0x4c, 0xfa, 0x7d, 0xf9, 0x13, 0xf8, 0xdf, 0xf5, + 0x65, 0xf5, 0xe3, 0xf3, 0xc1, 0xf3, 0x8f, 0xf6, 0xe0, 0xf7, 0x87, 0xfa, + 0x0b, 0xfe, 0x89, 0xfe, 0xa4, 0xff, 0xcf, 0xfe, 0xe8, 0xfb, 0x5f, 0xfb, + 0x42, 0xfa, 0xbe, 0xf8, 0xd5, 0xf8, 0x62, 0xf8, 0x78, 0xf8, 0x62, 0xf9, + 0x50, 0xf8, 0x8f, 0xf7, 0xec, 0xf7, 0xfb, 0xf6, 0xbd, 0xf7, 0xee, 0xf9, + 0x10, 0xfb, 0x67, 0xfc, 0x6d, 0xfd, 0xaa, 0xfd, 0x85, 0xfe, 0x40, 0xfe, + 0x98, 0xfc, 0xbe, 0xfc, 0x30, 0xfc, 0x2f, 0xfb, 0x43, 0xfc, 0xf0, 0xfb, + 0x7e, 0xfb, 0xa1, 0xfb, 0x34, 0xfa, 0xc9, 0xf9, 0x02, 0xf9, 0x61, 0xf6, + 0x74, 0xf5, 0xf3, 0xf3, 0x28, 0xf2, 0x62, 0xf1, 0x6a, 0xef, 0x6a, 0xee, + 0x08, 0xef, 0x2a, 0xef, 0x2d, 0xf0, 0x0e, 0xf2, 0x56, 0xf2, 0x7b, 0xf3, + 0xbf, 0xf5, 0x96, 0xf6, 0xe5, 0xf7, 0xf0, 0xf8, 0x99, 0xf8, 0x45, 0xf9, + 0xe9, 0xf8, 0x85, 0xf7, 0xf3, 0xf8, 0xec, 0xf9, 0x6b, 0xfa, 0x6e, 0xfb, + 0x6d, 0xfb, 0xb9, 0xfc, 0xe8, 0xfd, 0x9f, 0xfc, 0x51, 0xfb, 0x8a, 0xfb, + 0x86, 0xfa, 0x40, 0xfa, 0xc7, 0xf9, 0x95, 0xf7, 0x40, 0xf7, 0x54, 0xf7, + 0x53, 0xf7, 0x21, 0xf8, 0xe5, 0xf7, 0xba, 0xf7, 0xa6, 0xf7, 0xdd, 0xf4, + 0x99, 0xf3, 0xd1, 0xf3, 0xbd, 0xf2, 0xf6, 0xf3, 0x7c, 0xf4, 0x69, 0xf4, + 0x17, 0xf6, 0x3c, 0xf6, 0x1d, 0xf5, 0xfd, 0xf4, 0xa0, 0xf3, 0x5d, 0xf2, + 0x57, 0xf3, 0xe3, 0xf3, 0x7f, 0xf4, 0x6d, 0xf5, 0x95, 0xf4, 0xba, 0xf4, + 0x6d, 0xf5, 0x2b, 0xf4, 0x90, 0xf4, 0x2e, 0xf5, 0x7e, 0xf5, 0x0a, 0xf7, + 0x40, 0xf7, 0xb0, 0xf7, 0x36, 0xf9, 0x6d, 0xf9, 0xec, 0xf8, 0x19, 0xf9, + 0xea, 0xf7, 0xf0, 0xf8, 0x1d, 0xfb, 0x9d, 0xfb, 0xb1, 0xfe, 0x56, 0x02, + 0xd1, 0x04, 0x49, 0x08, 0x68, 0x0b, 0x08, 0x0d, 0xdb, 0x0e, 0x04, 0x0f, + 0xc3, 0x0d, 0xb2, 0x0d, 0x32, 0x0b, 0xdd, 0x07, 0xa6, 0x05, 0xfe, 0x02, + 0x13, 0x01, 0x0c, 0x00, 0x9c, 0xfe, 0xb3, 0xfe, 0xce, 0xff, 0x55, 0x00, + 0x08, 0x02, 0x32, 0x03, 0x68, 0x03, 0x36, 0x04, 0xc2, 0x03, 0x45, 0x03, + 0xe3, 0x03, 0x86, 0x03, 0xf2, 0x04, 0xa2, 0x08, 0x7a, 0x0a, 0x0f, 0x0c, + 0xcc, 0x0c, 0x36, 0x0b, 0x9e, 0x0a, 0x98, 0x09, 0xed, 0x07, 0xe1, 0x08, + 0x08, 0x09, 0xdb, 0x08, 0x79, 0x0a, 0xd3, 0x0a, 0x2c, 0x0b, 0xb3, 0x0b, + 0x0c, 0x0a, 0x32, 0x08, 0x8a, 0x07, 0x09, 0x07, 0x1d, 0x07, 0x04, 0x07, + 0x2f, 0x06, 0x33, 0x07, 0x1d, 0x09, 0xb5, 0x09, 0x6b, 0x0b, 0x91, 0x0c, + 0x64, 0x0d, 0xf0, 0x0f, 0xe4, 0x0f, 0x6a, 0x0f, 0x2b, 0x10, 0x34, 0x0f, + 0x38, 0x0e, 0x9f, 0x0c, 0x36, 0x0a, 0xc3, 0x08, 0x3e, 0x07, 0x28, 0x05, + 0xad, 0x03, 0xc2, 0x02, 0x58, 0x01, 0xc1, 0x00, 0x72, 0xff, 0x5e, 0xfd, + 0xf9, 0xfc, 0xf4, 0xfb, 0x3b, 0xfc, 0xf5, 0xfd, 0x95, 0xfd, 0x68, 0xfe, + 0x74, 0xff, 0xec, 0xff, 0xf1, 0x01, 0xf3, 0x02, 0x9a, 0x04, 0x10, 0x07, + 0xc3, 0x07, 0x32, 0x08, 0xbd, 0x08, 0xe4, 0x07, 0xfa, 0x06, 0xe5, 0x06, + 0x66, 0x05, 0x9a, 0x03, 0xbf, 0x03, 0xbc, 0x02, 0xd8, 0x01, 0xbc, 0x01, + 0x2d, 0x01, 0xab, 0x02, 0xe1, 0x02, 0x05, 0x02, 0x8d, 0x03, 0x8e, 0x04, + 0xf4, 0x04, 0x19, 0x06, 0x37, 0x06, 0xe8, 0x05, 0xce, 0x05, 0x8d, 0x03, + 0x36, 0x01, 0x70, 0xff, 0xfb, 0xfc, 0xdd, 0xfc, 0x03, 0xfd, 0xbc, 0xfc, + 0x53, 0xfe, 0x09, 0xff, 0x8f, 0xfe, 0x7c, 0xff, 0xa3, 0xff, 0xcf, 0xff, + 0xbc, 0x00, 0x14, 0x00, 0x9b, 0x00, 0xbf, 0x00, 0x66, 0xff, 0xde, 0xfe, + 0x9c, 0xfe, 0xd3, 0xfe, 0x02, 0x00, 0xb2, 0xff, 0x31, 0xfe, 0x79, 0xfe, + 0x54, 0xfe, 0x7a, 0xfd, 0x71, 0xfe, 0xa7, 0xfe, 0x23, 0xff, 0x20, 0x01, + 0xe7, 0x01, 0x57, 0x03, 0x8c, 0x04, 0xf1, 0x03, 0xc4, 0x04, 0x8d, 0x05, + 0x6b, 0x05, 0x2e, 0x06, 0xaf, 0x06, 0x76, 0x06, 0x06, 0x06, 0x84, 0x04, + 0x19, 0x04, 0xd5, 0x04, 0xc4, 0x03, 0xae, 0x03, 0x2c, 0x03, 0xb8, 0x01, + 0x78, 0x02, 0x2a, 0x04, 0xbf, 0x04, 0x64, 0x05, 0x13, 0x06, 0x2a, 0x05, + 0x27, 0x05, 0x0d, 0x05, 0xfe, 0x03, 0xe6, 0x04, 0x60, 0x05, 0xba, 0x05, + 0xf6, 0x07, 0xc5, 0x08, 0x60, 0x09, 0x61, 0x0a, 0xa5, 0x08, 0x4c, 0x07, + 0xeb, 0x05, 0x23, 0x04, 0xce, 0x03, 0xbd, 0x02, 0xd2, 0x01, 0x79, 0x02, + 0x66, 0x03, 0x1f, 0x04, 0xfc, 0x04, 0x39, 0x04, 0x5d, 0x03, 0x8c, 0x02, + 0x3b, 0x01, 0x3f, 0x02, 0x60, 0x04, 0x5b, 0x06, 0xbf, 0x08, 0x0e, 0x0b, + 0xa1, 0x0c, 0xa1, 0x0e, 0xf4, 0x0f, 0xb4, 0x0f, 0x95, 0x0f, 0x43, 0x0e, + 0x86, 0x0c, 0xee, 0x0b, 0x0e, 0x0b, 0xea, 0x0a, 0xf9, 0x0a, 0x96, 0x09, + 0xa7, 0x09, 0x3f, 0x0a, 0x6e, 0x09, 0x14, 0x0a, 0xf1, 0x09, 0x9d, 0x08, + 0x8c, 0x09, 0xfe, 0x09, 0xd3, 0x09, 0xeb, 0x0a, 0x8b, 0x0a, 0x98, 0x09, + 0x75, 0x09, 0x2f, 0x09, 0x08, 0x0a, 0x52, 0x0a, 0xed, 0x08, 0x48, 0x09, + 0x29, 0x0a, 0x68, 0x09, 0x0b, 0x09, 0x1e, 0x08, 0x2d, 0x07, 0x3d, 0x07, + 0x54, 0x06, 0x69, 0x06, 0xd4, 0x07, 0x30, 0x08, 0xa4, 0x08, 0x86, 0x08, + 0x75, 0x07, 0x86, 0x07, 0xfa, 0x07, 0x78, 0x07, 0xda, 0x07, 0x6e, 0x08, + 0xd6, 0x07, 0x0a, 0x09, 0xea, 0x08, 0x3c, 0x07, 0x3c, 0x07, 0xf8, 0x05, + 0xf6, 0x04, 0x7a, 0x05, 0xcd, 0x04, 0x72, 0x04, 0x45, 0x05, 0x3d, 0x05, + 0x7b, 0x06, 0x93, 0x07, 0x49, 0x07, 0x40, 0x08, 0x46, 0x08, 0xa1, 0x07, + 0x19, 0x08, 0x94, 0x08, 0x2b, 0x08, 0x87, 0x08, 0x98, 0x08, 0xaf, 0x08, + 0x52, 0x09, 0xf0, 0x07, 0xf9, 0x07, 0xca, 0x08, 0x52, 0x08, 0x69, 0x08, + 0xa9, 0x07, 0x9b, 0x06, 0x5b, 0x08, 0x52, 0x09, 0xe8, 0x07, 0x85, 0x08, + 0x72, 0x08, 0xfb, 0x07, 0x4a, 0x08, 0xc1, 0x06, 0xc4, 0x05, 0x24, 0x05, + 0xea, 0x02, 0x30, 0x01, 0x07, 0x00, 0x24, 0xfe, 0x52, 0xfd, 0x19, 0xfc, + 0xb5, 0xfa, 0x59, 0xfb, 0xb8, 0xfa, 0xfc, 0xf9, 0xc9, 0xfa, 0xbe, 0xfa, + 0x42, 0xfb, 0x36, 0xfc, 0xcd, 0xfb, 0x77, 0xfc, 0x30, 0xfd, 0xc5, 0xfc, + 0x65, 0xfe, 0xc0, 0xff, 0xbc, 0xff, 0x80, 0x01, 0xf6, 0x02, 0x75, 0x03, + 0xf7, 0x04, 0x4c, 0x05, 0x6b, 0x04, 0x1c, 0x05, 0xbc, 0x05, 0x34, 0x06, + 0x77, 0x07, 0x8a, 0x07, 0xfb, 0x07, 0xf3, 0x07, 0x66, 0x06, 0x62, 0x05, + 0xf0, 0x03, 0x19, 0x02, 0x59, 0x01, 0x95, 0x00, 0x50, 0xff, 0xe0, 0xfe, + 0xb5, 0xfd, 0xf5, 0xfb, 0x42, 0xfb, 0xc3, 0xf9, 0x9b, 0xf9, 0xc4, 0xf9, + 0xb9, 0xf8, 0x02, 0xfa, 0x4f, 0xfb, 0x9e, 0xfb, 0x8e, 0xfd, 0x30, 0xff, + 0x28, 0x00, 0xb3, 0x01, 0x51, 0x01, 0xf5, 0x00, 0xa5, 0x01, 0x2a, 0x01, + 0x60, 0x01, 0x0b, 0x02, 0xf7, 0x00, 0xcf, 0x00, 0xfb, 0x01, 0x0d, 0x02, + 0x5d, 0x03, 0xe6, 0x03, 0x72, 0x02, 0xa2, 0x03, 0x35, 0x05, 0x70, 0x05, + 0xca, 0x05, 0xe8, 0x04, 0xe5, 0x04, 0x0f, 0x06, 0x47, 0x05, 0x35, 0x06, + 0x3e, 0x08, 0x58, 0x08, 0x5d, 0x09, 0x06, 0x0a, 0x0f, 0x09, 0x19, 0x0a, + 0x33, 0x0a, 0x81, 0x07, 0xd6, 0x06, 0x26, 0x05, 0xe2, 0x02, 0x75, 0x02, + 0x6c, 0x00, 0x68, 0xff, 0xc4, 0xfe, 0xfa, 0xfb, 0x06, 0xfb, 0xd0, 0xfb, + 0x95, 0xfb, 0xce, 0xfb, 0x6e, 0xfb, 0x44, 0xfa, 0x7b, 0xfa, 0xa0, 0xf9, + 0x46, 0xf8, 0xf7, 0xf8, 0x4b, 0xf9, 0xa6, 0xf9, 0xda, 0xfc, 0xda, 0xff, + 0x47, 0x03, 0xe2, 0x06, 0x19, 0x07, 0x21, 0x08, 0x74, 0x09, 0x7c, 0x08, + 0xbf, 0x08, 0x40, 0x08, 0x67, 0x06, 0xc5, 0x06, 0xc0, 0x05, 0x31, 0x04, + 0xa9, 0x05, 0x9f, 0x05, 0x3f, 0x06, 0xd5, 0x08, 0x29, 0x09, 0x24, 0x0a, + 0x01, 0x0c, 0xa3, 0x0b, 0xeb, 0x0b, 0x74, 0x0b, 0x5e, 0x08, 0x3e, 0x07, + 0x11, 0x06, 0x4d, 0x04, 0x1a, 0x05, 0xec, 0x04, 0xb6, 0x05, 0x2f, 0x09, + 0x5c, 0x0a, 0x19, 0x0a, 0xe5, 0x08, 0xf0, 0x06, 0x11, 0x07, 0x16, 0x08, + 0x46, 0x07, 0xf2, 0x06, 0x6f, 0x07, 0x70, 0x05, 0x91, 0x04, 0x4f, 0x04, + 0xed, 0x02, 0x5b, 0x02, 0x26, 0x00, 0xe4, 0xfe, 0x83, 0xff, 0xe8, 0xfd, + 0x21, 0xfd, 0xa9, 0xfd, 0x35, 0xfc, 0x38, 0xfc, 0xd8, 0xfb, 0xa0, 0xfa, + 0xfa, 0xfa, 0x88, 0xf9, 0x8b, 0xf7, 0x70, 0xf7, 0x8d, 0xf7, 0x37, 0xf7, + 0x01, 0xf8, 0x43, 0xf8, 0x21, 0xf9, 0x8c, 0xfb, 0x53, 0xfc, 0xe3, 0xfc, + 0x65, 0xfd, 0x4c, 0xfd, 0xa0, 0xfe, 0xd7, 0xfe, 0xd9, 0xfc, 0x5b, 0xfc, + 0xcc, 0xfb, 0x4e, 0xfa, 0x66, 0xfb, 0xb3, 0xfc, 0x60, 0xfd, 0xb4, 0xff, + 0xd8, 0xff, 0x09, 0xff, 0x01, 0xff, 0xdd, 0xfb, 0x25, 0xfb, 0xb9, 0xfc, + 0x7b, 0xfc, 0xe2, 0xfd, 0x4b, 0xfe, 0xd0, 0xfc, 0xfa, 0xfb, 0x12, 0xfa, + 0x0a, 0xf8, 0x99, 0xf7, 0xa6, 0xf5, 0x70, 0xf3, 0x3f, 0xf3, 0x55, 0xf2, + 0x99, 0xf2, 0xb8, 0xf3, 0x05, 0xf3, 0xb6, 0xf2, 0x2a, 0xf2, 0x08, 0xf0, + 0x1c, 0xef, 0xfb, 0xed, 0xdf, 0xec, 0x1c, 0xef, 0x44, 0xf1, 0xed, 0xf2, + 0x0a, 0xf5, 0x5e, 0xf4, 0x4e, 0xf4, 0x31, 0xf6, 0xe2, 0xf5, 0xa9, 0xf5, + 0x1c, 0xf6, 0x9b, 0xf5, 0x16, 0xf6, 0x2f, 0xf6, 0x6f, 0xf5, 0x2e, 0xf7, + 0x9a, 0xf9, 0x8e, 0xfa, 0x49, 0xfc, 0x68, 0xfd, 0x10, 0xfd, 0xb8, 0xfd, + 0xbd, 0xfc, 0x37, 0xfb, 0x3d, 0xfb, 0x7c, 0xf8, 0xc6, 0xf6, 0xdd, 0xf6, + 0x82, 0xf4, 0xac, 0xf3, 0xb9, 0xf3, 0xf8, 0xf2, 0xf3, 0xf3, 0xf1, 0xf4, + 0xf9, 0xf4, 0x07, 0xf6, 0x54, 0xf5, 0xdd, 0xf3, 0x52, 0xf5, 0xa1, 0xf5, + 0x35, 0xf6, 0xcf, 0xf8, 0x32, 0xf9, 0x0c, 0xfa, 0x59, 0xfa, 0x3a, 0xf8, + 0x3c, 0xf9, 0xba, 0xf9, 0x9c, 0xf8, 0xd2, 0xfa, 0x5d, 0xfc, 0xd1, 0xfd, + 0xf2, 0xff, 0x00, 0x00, 0xe3, 0xff, 0x86, 0xff, 0x3d, 0xfd, 0xfc, 0xfa, + 0xb6, 0xf9, 0x18, 0xf7, 0x43, 0xf6, 0xea, 0xf6, 0x5f, 0xf6, 0xc4, 0xf8, + 0x2d, 0xfa, 0x57, 0xf9, 0x87, 0xfa, 0x86, 0xfa, 0xa4, 0xfa, 0x40, 0xfc, + 0x77, 0xfb, 0xd5, 0xfa, 0xbb, 0xfc, 0x2f, 0xfd, 0xb5, 0xfc, 0xea, 0xfc, + 0x4a, 0xfb, 0xe0, 0xfa, 0xc6, 0xfb, 0x30, 0xfb, 0xab, 0xfb, 0x1b, 0xfa, + 0x06, 0xf9, 0x98, 0xfa, 0x86, 0xf9, 0xa4, 0xf9, 0x9d, 0xfa, 0x2c, 0xfa, + 0xbb, 0xfa, 0x19, 0xfb, 0xa0, 0xfa, 0x7f, 0xfa, 0xc5, 0xf9, 0x40, 0xf8, + 0x49, 0xf8, 0x1b, 0xf8, 0x2f, 0xf8, 0x7d, 0xf9, 0x8b, 0xf8, 0xda, 0xf8, + 0x78, 0xfa, 0xdd, 0xf9, 0xbf, 0xf8, 0x09, 0xf7, 0x99, 0xf6, 0x56, 0xf7, + 0xaa, 0xf7, 0x74, 0xf8, 0xc7, 0xf9, 0x7d, 0xfb, 0xed, 0xfa, 0x72, 0xfb, + 0x96, 0xfe, 0xaa, 0xfe, 0x19, 0xff, 0xdf, 0xff, 0x86, 0xff, 0x17, 0x01, + 0x13, 0x02, 0x72, 0x03, 0x0f, 0x05, 0x5d, 0x04, 0xf7, 0x03, 0xce, 0x03, + 0xd3, 0x02, 0xce, 0x02, 0x0f, 0x04, 0x1f, 0x03, 0x11, 0x02, 0x08, 0x01, + 0x1c, 0xfd, 0xd0, 0xfb, 0x47, 0xfa, 0x50, 0xf9, 0x75, 0xfb, 0x61, 0xfa, + 0x10, 0xfb, 0x57, 0xfd, 0xc2, 0xfd, 0x05, 0xff, 0xdc, 0xfe, 0xab, 0xfd, + 0x26, 0xfc, 0x34, 0xfa, 0xd9, 0xf8, 0xde, 0xf8, 0xc9, 0xf8, 0xab, 0xf7, + 0x47, 0xf8, 0x63, 0xf7, 0x9b, 0xf5, 0x5b, 0xf6, 0xdb, 0xf5, 0x85, 0xf6, + 0x72, 0xf9, 0xf7, 0xfb, 0x05, 0xff, 0xf9, 0x00, 0xad, 0x00, 0x5a, 0x00, + 0xed, 0x00, 0x7f, 0x00, 0x55, 0xff, 0x3b, 0xfe, 0xf9, 0xfc, 0x1d, 0xfd, + 0x2e, 0xfb, 0x13, 0xf9, 0xa3, 0xfa, 0x65, 0xfa, 0x37, 0xfa, 0xcc, 0xfa, + 0xdf, 0xfa, 0x52, 0xfd, 0x49, 0xfe, 0xdb, 0xfe, 0xe1, 0xff, 0x03, 0x00, + 0x61, 0xff, 0xe4, 0xff, 0xf5, 0x00, 0x26, 0x00, 0x3d, 0xff, 0x5b, 0xfd, + 0xc0, 0xfb, 0x31, 0xfa, 0x0f, 0xf8, 0x31, 0xf6, 0xc6, 0xf4, 0x33, 0xf2, + 0x9a, 0xf5, 0x65, 0xfe, 0xbf, 0x01, 0xa2, 0x04, 0xd4, 0x04, 0xee, 0x00, + 0x1f, 0xff, 0xb6, 0x01, 0x1b, 0x06, 0x18, 0x06, 0xf3, 0x01, 0x3d, 0xfe, + 0x03, 0xfe, 0x25, 0x00, 0x27, 0x06, 0x1b, 0x07, 0x3a, 0x04, 0xd9, 0x05, + 0xe4, 0x01, 0xb1, 0xff, 0x32, 0x05, 0x55, 0x04, 0x77, 0x01, 0x12, 0x01, + 0x2d, 0xfc, 0x4b, 0xfc, 0x55, 0xff, 0x0b, 0xfd, 0x61, 0xfc, 0x32, 0xfd, + 0x94, 0xf8, 0x01, 0xf4, 0x13, 0xf4, 0x35, 0xf8, 0xe7, 0x02, 0x6c, 0x06, + 0x7b, 0x01, 0x25, 0xf7, 0x52, 0xef, 0x21, 0xf9, 0xf4, 0x05, 0x32, 0x0b, + 0x01, 0x05, 0x3e, 0xfd, 0x95, 0xff, 0x5d, 0x03, 0x8b, 0x07, 0xa0, 0x0e, + 0x5f, 0x0d, 0x42, 0x00, 0xbf, 0xf7, 0x59, 0xf6, 0x78, 0xf9, 0xa0, 0x05, + 0xc7, 0x10, 0x1e, 0x0c, 0x61, 0x01, 0x5d, 0x00, 0x9e, 0xfd, 0x48, 0xfa, + 0xa2, 0xff, 0x27, 0x03, 0xf3, 0x04, 0xf1, 0x06, 0x99, 0x01, 0x4a, 0xfe, + 0xb5, 0x03, 0x97, 0x05, 0x78, 0x04, 0x20, 0x04, 0x69, 0x04, 0x2f, 0x06, + 0x4b, 0x07, 0xeb, 0x0a, 0xba, 0x09, 0x09, 0x05, 0x30, 0x05, 0x0d, 0x08, + 0x63, 0x0b, 0x66, 0x0e, 0x03, 0x11, 0x47, 0x0d, 0x35, 0x09, 0x56, 0x08, + 0x4e, 0x09, 0x62, 0x0d, 0xbc, 0x10, 0xc9, 0x0f, 0xb9, 0x09, 0x07, 0x05, + 0x58, 0x03, 0x8d, 0x08, 0x76, 0x10, 0xe4, 0x13, 0x79, 0x10, 0x1f, 0x0c, + 0xed, 0x06, 0x12, 0xfe, 0xc1, 0x01, 0x4f, 0x09, 0x58, 0x10, 0x4a, 0x13, + 0x7b, 0x0d, 0xbb, 0x07, 0x47, 0x04, 0xc9, 0x08, 0x48, 0x0d, 0x4a, 0x0f, + 0x42, 0x0d, 0xac, 0x07, 0xcd, 0x02, 0xcf, 0xfe, 0x1e, 0xfd, 0x8f, 0xfb, + 0x8b, 0xfa, 0xf3, 0xf8, 0x32, 0xf9, 0x01, 0xfa, 0x59, 0xfa, 0x0f, 0xfc, + 0x10, 0xfe, 0x75, 0x00, 0xcc, 0x05, 0xa2, 0x07, 0xbf, 0x06, 0x7c, 0x05, + 0xc4, 0x01, 0xf3, 0x03, 0x8c, 0x02, 0x5a, 0x02, 0x3f, 0x02, 0xed, 0x00, + 0xcc, 0x00, 0x52, 0xfc, 0x1a, 0xfd, 0xbd, 0xfb, 0xe6, 0xfe, 0x46, 0x00, + 0x80, 0xfd, 0xee, 0xfb, 0x21, 0xf9, 0x2b, 0xfc, 0xe3, 0xfa, 0xdb, 0xf8, + 0x71, 0xf6, 0x84, 0xf4, 0x49, 0xf3, 0x62, 0xf4, 0xbe, 0xf4, 0x56, 0xf2, + 0xee, 0xf4, 0x64, 0xf5, 0x29, 0xf7, 0x2f, 0xf6, 0xf8, 0xf4, 0xe6, 0xf6, + 0xb9, 0xf8, 0x4a, 0xf9, 0xd5, 0xf7, 0xaa, 0xf4, 0x20, 0xf0, 0x04, 0xf3, + 0xa4, 0xf4, 0x8e, 0xf4, 0x06, 0xf3, 0x7d, 0xf1, 0x0a, 0xf1, 0x1b, 0xf0, + 0x4e, 0xf0, 0xe1, 0xed, 0xbf, 0xed, 0x2d, 0xeb, 0xe4, 0xea, 0x2a, 0xec, + 0xf6, 0xeb, 0xb5, 0xee, 0x74, 0xee, 0x4c, 0xed, 0x43, 0xee, 0xa0, 0xef, + 0xc9, 0xf0, 0x80, 0xf3, 0xf2, 0xf3, 0xef, 0xf3, 0xc1, 0xf3, 0x6c, 0xf3, + 0xda, 0xf3, 0xf9, 0xf3, 0xeb, 0xf3, 0xd9, 0xf2, 0x85, 0xf2, 0x53, 0xf2, + 0x1b, 0xf4, 0xba, 0xf4, 0x67, 0xf5, 0xc3, 0xf6, 0xba, 0xf5 +}; diff --git a/libraries/PWMAudio/examples/PlayStereo/PlayStereo.ino b/libraries/PWMAudio/examples/PlayStereo/PlayStereo.ino new file mode 100644 index 000000000..92f52d5b0 --- /dev/null +++ b/libraries/PWMAudio/examples/PlayStereo/PlayStereo.ino @@ -0,0 +1,68 @@ +/* + This example plays a tune that alternates between left and right channels using a simple sine wave. + + Released to the public domain by Earle F. Philhower, III +*/ + +#include + +PWMAudio pwm(0, true); // GP0 = left, GP1 = right + +const int freq = 48000; // Output frequency for PWM + +int16_t al = 0; +int16_t ar = 0; + +const int notes[] = { 784, 880, 698, 349, 523 }; +const int dly[] = { 400, 500, 700, 500, 1000 }; +const int noteCnt = sizeof(notes) / sizeof(notes[0]); + +int freqL = 1; +int freqR = 1; + +double sineTable[128]; // Precompute sine wave in 128 steps + +unsigned int cnt = 0; +void cb() { + while (pwm.availableForWrite()) { + double now = ((double)cnt) / (double)freq; + int fl = freqL << 7; // Prescale by 128 to avoid FP math later on + int fr = freqR << 7; // Prescale by 128 to avoid FP math later on + pwm.write((int16_t)(al * sineTable[(int)(now * fl) & 127])); + pwm.write((int16_t)(ar * sineTable[(int)(now * fr) & 127])); + cnt++; + } +} + +void setup() { + // Set up sine table for waveform generation + for (int i = 0; i < 128; i++) { + sineTable[i] = sin(i * 2.0 * 3.14159 / 128.0); + } + pwm.setBuffers(4, 32); // Give larger buffers since we're are 48khz sample rate + pwm.onTransmit(cb); + pwm.begin(freq); +} + +void loop() { + delay(1000); + + // Send it out on the LHS + ar = 0; + for (int i = 0; i < noteCnt; i++) { + freqL = notes[i]; + al = 5000; + delay(dly[i]); + } + al = 0; + delay(1000); + + // Hear reply on RHS + for (int i = 0; i < noteCnt; i++) { + freqR = notes[i] / 4; + ar = 15000; + delay(dly[i]); + } + ar = 0; + delay(3000); +} diff --git a/libraries/PWMAudio/keywords.txt b/libraries/PWMAudio/keywords.txt new file mode 100644 index 000000000..2354ae5a7 --- /dev/null +++ b/libraries/PWMAudio/keywords.txt @@ -0,0 +1,26 @@ +####################################### +# Syntax Coloring Map +####################################### + +####################################### +# Datatypes (KEYWORD1) +####################################### + +PWMAudio KEYWORD1 + +####################################### +# Methods and Functions (KEYWORD2) +####################################### +begin KEYWORD2 +end KEYWORD2 + +setPin KEYWORD2 +setFrequency KEYWORD2 +setBuffers KEYWORD2 +setStereo KEYWORD2 + +onTransmit KEYWORD2 + +####################################### +# Constants (LITERAL1) +####################################### diff --git a/libraries/PWMAudio/library.properties b/libraries/PWMAudio/library.properties new file mode 100644 index 000000000..446688a5a --- /dev/null +++ b/libraries/PWMAudio/library.properties @@ -0,0 +1,10 @@ +name=PWMAudio +version=1.0 +author=Earle F. Philhower, III +maintainer=Earle F. Philhower, III +sentence=Plays audio on a pin using the PWM hardware, no DAC required +paragraph=Plays audio on a pin using the PWM hardware, no DAC required +category=Communication +url=http://github.com/earlephilhower/arduino-pico +architectures=rp2040 +dot_a_linkage=true diff --git a/libraries/PWMAudio/src/PWMAudio.cpp b/libraries/PWMAudio/src/PWMAudio.cpp new file mode 100644 index 000000000..49cfa0cd9 --- /dev/null +++ b/libraries/PWMAudio/src/PWMAudio.cpp @@ -0,0 +1,211 @@ +/* + PWMAudio + Plays a 16b audio stream on a user defined pin using PWM + + Copyright (c) 2022 Earle F. Philhower, III + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ +#include +#include "PWMAudio.h" +#include + + +PWMAudio::PWMAudio(pin_size_t pin, bool stereo) { + _running = false; + _pin = pin; + _freq = 48000; + _arb = nullptr; + _cb = nullptr; + _buffers = 8; + _bufferWords = 0; + _stereo = stereo; +} + +PWMAudio::~PWMAudio() { + end(); +} + +bool PWMAudio::setBuffers(size_t buffers, size_t bufferWords) { + if (_running || (buffers < 3) || (bufferWords < 8)) { + return false; + } + _buffers = buffers; + _bufferWords = bufferWords; + return true; +} + +bool PWMAudio::setPin(pin_size_t pin) { + if (_running) { + return false; + } + _pin = pin; + return true; +} + +bool PWMAudio::setStereo(bool stereo) { + if (_running) { + return false; + } + _stereo = stereo; + return true; +} + +bool PWMAudio::setFrequency(int newFreq) { + _freq = newFreq; + + // Figure out the scale factor for PWM values + float fPWM = 65535.0 * _freq; // ideal + + if (fPWM > clock_get_hz(clk_sys)) { + // Need to downscale the range to hit the frequency target + float pwmMax = (float) clock_get_hz(clk_sys) / (float) _freq; + _pwmScale = pwmMax; + fPWM = clock_get_hz(clk_sys); + } else { + _pwmScale = 1 << 16; + } + + pwm_config c = pwm_get_default_config(); + pwm_config_set_clkdiv(&c, clock_get_hz(clk_sys) / fPWM); + pwm_config_set_wrap(&c, _pwmScale); + pwm_init(pwm_gpio_to_slice_num(_pin), &c, _running); + gpio_set_function(_pin, GPIO_FUNC_PWM); + pwm_set_gpio_level(_pin, (0x8000 * _pwmScale) >> 16); + if (_stereo) { + gpio_set_function(_pin + 1, GPIO_FUNC_PWM); + pwm_set_gpio_level(_pin + 1, (0x8000 * _pwmScale) >> 16); + } + + return true; +} + +void PWMAudio::onTransmit(void(*fn)(void)) { + _cb = fn; + if (_running) { + _arb->setCallback(_cb); + } +} + +bool PWMAudio::begin() { + if (_stereo && (_pin & 1)) { + // Illegal, need to have consecutive pins on the same PWM slice + Serial.printf("ERROR: PWMAudio stereo mode requires pin be even\n"); + return false; + } + + _running = true; + _wasHolding = false; + + if (!_bufferWords) { + _bufferWords = 16; + } + + setFrequency(_freq); + + uint32_t ccAddr = PWM_BASE + PWM_CH0_CC_OFFSET + pwm_gpio_to_slice_num(_pin) * 20; + + _arb = new AudioBufferManager(_buffers, _bufferWords, 0x80008000, OUTPUT, DMA_SIZE_32); + _arb->begin(pwm_get_dreq(pwm_gpio_to_slice_num(_pin)), (volatile void*)ccAddr); + _arb->setCallback(_cb); + + return true; +} + +void PWMAudio::end() { + if (_running) { + _running = false; + pinMode(_pin, OUTPUT); + if (_stereo) { + pinMode(_pin + 1, OUTPUT); + } + delete _arb; + _arb = nullptr; + } +} + +int PWMAudio::available() { + return availableForWrite(); // Do what I mean, not what I say +} + +int PWMAudio::read() { + return -1; +} + +int PWMAudio::peek() { + return -1; +} + +void PWMAudio::flush() { + if (_running) { + _arb->flush(); + } +} + +int PWMAudio::availableForWrite() { + if (!_running) { + return 0; + } + return _arb->available(); +} + +size_t PWMAudio::write(int16_t val, bool sync) { + if (!_running) { + return 0; + } + // Go from signed -32K...32K to unsigned 0...64K + uint32_t sample = (uint32_t)(val + 0x8000); + // Adjust to the real range + sample *= _pwmScale; + sample >>= 16; + if (!_stereo) { + // Duplicate sample since we don't care which PWM channel + sample = (sample & 0xffff) | (sample << 16); + return _arb->write(sample, sync); + } else { + if (_wasHolding) { + _holdWord = (_holdWord & 0xffff) | (sample << 16); + auto ret = _arb->write(_holdWord, sync); + if (ret) { + _wasHolding = false; + } + return ret; + } else { + _holdWord = sample; + _wasHolding = true; + return true; + } + } +} + +size_t PWMAudio::write(const uint8_t *buffer, size_t size) { + // We can only write 16-bit chunks here + if (size & 0x1) { + return 0; + } + size_t writtenSize = 0; + int16_t *p = (int16_t *)buffer; + while (size) { + if (!write((int16_t)*p)) { + // Blocked, stop write here + return writtenSize; + } else { + p++; + size -= 4; + writtenSize += 4; + } + } + return writtenSize; +} diff --git a/libraries/PWMAudio/src/PWMAudio.h b/libraries/PWMAudio/src/PWMAudio.h new file mode 100644 index 000000000..86e61e830 --- /dev/null +++ b/libraries/PWMAudio/src/PWMAudio.h @@ -0,0 +1,87 @@ +/* + PWMAudio + Plays a signed 16b audio stream on a user defined pin using PWM + + Copyright (c) 2022 Earle F. Philhower, III + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#pragma once +#include +#include "AudioBufferManager.h" + +class PWMAudio : public Stream { +public: + PWMAudio(pin_size_t pin = 0, bool stereo = false); + virtual ~PWMAudio(); + + bool setBuffers(size_t buffers, size_t bufferWords); + bool setFrequency(int newFreq); + bool setPin(pin_size_t pin); + bool setStereo(bool stereo = true); + + bool begin(long sampleRate) { + setFrequency(sampleRate); + return begin(); + } + + bool begin(); + void end(); + + // from Stream + virtual int available() override; + virtual int read() override; + virtual int peek() override; + virtual void flush() override; + + // from Print (see notes on write() methods below) + virtual size_t write(const uint8_t *buffer, size_t size) override; + virtual int availableForWrite() override; + + virtual size_t write(uint8_t x) override { + return write((int16_t) x, true); + } + + // Write 16 bit value to port, user responsible for packing/alignment, etc. + size_t write(int16_t val, bool sync = true); + size_t write(int val, bool sync = true) { + return write((int16_t) val, sync); + } + + // Note that these callback are called from **INTERRUPT CONTEXT** and hence + // should be in RAM, not FLASH, and should be quick to execute. + void onTransmit(void(*)(void)); + +private: + pin_size_t _pin; + bool _stereo; + + int _freq; + + size_t _buffers; + size_t _bufferWords; + + uint32_t _pwmScale; + + bool _running; + + bool _wasHolding; + uint32_t _holdWord; + + void (*_cb)(); + + AudioBufferManager *_arb; +}; diff --git a/libraries/PicoOTA/library.properties b/libraries/PicoOTA/library.properties index 7140b17eb..fc0086d3d 100644 --- a/libraries/PicoOTA/library.properties +++ b/libraries/PicoOTA/library.properties @@ -5,6 +5,6 @@ maintainer=Earle F. Philhower, III sentence=Configures requests for OTA bootloader paragraph=Example repository for Ethernet drivers category=Device Control -url=https://github.com/earlephilhower.arduino-pico +url=https://github.com/earlephilhower/arduino-pico architectures=rp2040 dot_a_linkage=true diff --git a/libraries/PicoOTA/src/PicoOTA.h b/libraries/PicoOTA/src/PicoOTA.h index fcfac4825..bfd7900b3 100644 --- a/libraries/PicoOTA/src/PicoOTA.h +++ b/libraries/PicoOTA/src/PicoOTA.h @@ -71,7 +71,7 @@ class PicoOTA { } _page = new OTACmdPage; memset(_page, 0, sizeof(*_page)); - memcpy(_page->sign, "Pico OTA Format\0", sizeof(_page->sign)); + memcpy(_page->sign, "Pico OTA", sizeof(_page->sign)); _page->count = 0; } diff --git a/libraries/SD/examples/Datalogger/Datalogger.ino b/libraries/SD/examples/Datalogger/Datalogger.ino index b6fabe436..bde1a08c2 100644 --- a/libraries/SD/examples/Datalogger/Datalogger.ino +++ b/libraries/SD/examples/Datalogger/Datalogger.ino @@ -7,10 +7,10 @@ The circuit: analog sensors on analog ins 0, 1, and 2 SD card attached to SPI bus as follows (Raspberry Pi Pico): - ** MISO - pin 0 - ** MOSI - pin 3 - ** CS - pin 1 - ** SCK - pin 2 + ** MISO - pin 4 + ** MOSI - pin 7 + ** CS - pin 5 + ** SCK - pin 6 created 24 Nov 2010 modified 9 Apr 2012 @@ -20,19 +20,32 @@ */ +// This are GP pins for SPI0 on the Raspberry Pi Pico board, and connect +// to different *board* level pinouts. Check the PCB while wiring. +// Only certain pins can be used by the SPI hardware, so if you change +// these be sure they are legal or the program will crash. +// See: https://datasheets.raspberrypi.com/picow/PicoW-A4-Pinout.pdf +const int _MISO = 4; +const int _MOSI = 7; +const int _CS = 5; +const int _SCK = 6; + #include #include -const int chipSelect = 4; - void setup() { // Open serial communications and wait for port to open: Serial.begin(115200); Serial.print("Initializing SD card..."); + // Ensure the SPI pinout the SD card is connected to is configured properly + SPI.setRX(_MISO); + SPI.setTX(_MOSI); + SPI.setSCK(_SCK); + // see if the card is present and can be initialized: - if (!SD.begin(chipSelect)) { + if (!SD.begin(_CS)) { Serial.println("Card failed, or not present"); // don't do anything more: return; diff --git a/libraries/SD/examples/DumpFile/DumpFile.ino b/libraries/SD/examples/DumpFile/DumpFile.ino index bbf13deaa..b06d5cfc3 100644 --- a/libraries/SD/examples/DumpFile/DumpFile.ino +++ b/libraries/SD/examples/DumpFile/DumpFile.ino @@ -6,10 +6,10 @@ The circuit: SD card attached to SPI bus as follows: - ** MISO - pin 0 - ** MOSI - pin 3 - ** CS - pin 1 - ** SCK - pin 2 + ** MISO - pin 4 + ** MOSI - pin 7 + ** CS - pin 5 + ** SCK - pin 6 created 22 December 2010 by Limor Fried @@ -20,19 +20,32 @@ */ +// This are GP pins for SPI0 on the Raspberry Pi Pico board, and connect +// to different *board* level pinouts. Check the PCB while wiring. +// Only certain pins can be used by the SPI hardware, so if you change +// these be sure they are legal or the program will crash. +// See: https://datasheets.raspberrypi.com/picow/PicoW-A4-Pinout.pdf +const int _MISO = 4; +const int _MOSI = 7; +const int _CS = 5; +const int _SCK = 6; + #include #include -const int chipSelect = 4; - void setup() { // Open serial communications and wait for port to open: Serial.begin(115200); Serial.print("Initializing SD card..."); + // Ensure the SPI pinout the SD card is connected to is configured properly + SPI.setRX(_MISO); + SPI.setTX(_MOSI); + SPI.setSCK(_SCK); + // see if the card is present and can be initialized: - if (!SD.begin(chipSelect)) { + if (!SD.begin(_CS)) { Serial.println("Card failed, or not present"); // don't do anything more: return; diff --git a/libraries/SD/examples/Files/Files.ino b/libraries/SD/examples/Files/Files.ino index 1ef251d6b..a4970e6e9 100644 --- a/libraries/SD/examples/Files/Files.ino +++ b/libraries/SD/examples/Files/Files.ino @@ -4,10 +4,10 @@ This example shows how to create and destroy an SD card file The circuit: SD card attached to SPI bus as follows: - ** MISO - pin 0 - ** MOSI - pin 3 - ** CS - pin 1 - ** SCK - pin 2 + ** MISO - pin 4 + ** MOSI - pin 7 + ** CS - pin 5 + ** SCK - pin 6 created Nov 2010 by David A. Mellis @@ -17,6 +17,17 @@ This example code is in the public domain. */ + +// This are GP pins for SPI0 on the Raspberry Pi Pico board, and connect +// to different *board* level pinouts. Check the PCB while wiring. +// Only certain pins can be used by the SPI hardware, so if you change +// these be sure they are legal or the program will crash. +// See: https://datasheets.raspberrypi.com/picow/PicoW-A4-Pinout.pdf +const int _MISO = 4; +const int _MOSI = 7; +const int _CS = 5; +const int _SCK = 6; + #include #include @@ -28,7 +39,12 @@ void setup() { Serial.print("Initializing SD card..."); - if (!SD.begin(4)) { + // Ensure the SPI pinout the SD card is connected to is configured properly + SPI.setRX(_MISO); + SPI.setTX(_MOSI); + SPI.setSCK(_SCK); + + if (!SD.begin(_CS)) { Serial.println("initialization failed!"); return; } diff --git a/libraries/SD/examples/ReadWrite/ReadWrite.ino b/libraries/SD/examples/ReadWrite/ReadWrite.ino index cbdb570c6..1de0377f8 100644 --- a/libraries/SD/examples/ReadWrite/ReadWrite.ino +++ b/libraries/SD/examples/ReadWrite/ReadWrite.ino @@ -4,10 +4,10 @@ This example shows how to read and write data to and from an SD card file The circuit: SD card attached to SPI bus as follows: - ** MISO - pin 0 - ** MOSI - pin 3 - ** CS - pin 1 - ** SCK - pin 2 + ** MISO - pin 4 + ** MOSI - pin 7 + ** CS - pin 5 + ** SCK - pin 6 created Nov 2010 by David A. Mellis @@ -18,6 +18,16 @@ */ +// This are GP pins for SPI0 on the Raspberry Pi Pico board, and connect +// to different *board* level pinouts. Check the PCB while wiring. +// Only certain pins can be used by the SPI hardware, so if you change +// these be sure they are legal or the program will crash. +// See: https://datasheets.raspberrypi.com/picow/PicoW-A4-Pinout.pdf +const int _MISO = 4; +const int _MOSI = 7; +const int _CS = 5; +const int _SCK = 6; + #include #include @@ -29,7 +39,12 @@ void setup() { Serial.print("Initializing SD card..."); - if (!SD.begin(4)) { + // Ensure the SPI pinout the SD card is connected to is configured properly + SPI.setRX(_MISO); + SPI.setTX(_MOSI); + SPI.setSCK(_SCK); + + if (!SD.begin(_CS)) { Serial.println("initialization failed!"); return; } diff --git a/libraries/SD/examples/listfiles/listfiles.ino b/libraries/SD/examples/listfiles/listfiles.ino index 1ac730915..188465155 100644 --- a/libraries/SD/examples/listfiles/listfiles.ino +++ b/libraries/SD/examples/listfiles/listfiles.ino @@ -6,10 +6,10 @@ The circuit: SD card attached to SPI bus as follows: - ** MISO - pin 0 - ** MOSI - pin 3 - ** CS - pin 1 - ** SCK - pin 2 + ** MISO - pin 4 + ** MOSI - pin 7 + ** CS - pin 5 + ** SCK - pin 6 created Nov 2010 by David A. Mellis @@ -21,6 +21,17 @@ This example code is in the public domain. */ + +// This are GP pins for SPI0 on the Raspberry Pi Pico board, and connect +// to different *board* level pinouts. Check the PCB while wiring. +// Only certain pins can be used by the SPI hardware, so if you change +// these be sure they are legal or the program will crash. +// See: https://datasheets.raspberrypi.com/picow/PicoW-A4-Pinout.pdf +const int _MISO = 4; +const int _MOSI = 7; +const int _CS = 5; +const int _SCK = 6; + #include #include @@ -32,7 +43,12 @@ void setup() { Serial.print("Initializing SD card..."); - if (!SD.begin(SS)) { + // Ensure the SPI pinout the SD card is connected to is configured properly + SPI.setRX(_MISO); + SPI.setTX(_MOSI); + SPI.setSCK(_SCK); + + if (!SD.begin(_CS)) { Serial.println("initialization failed!"); return; } diff --git a/libraries/SD/src/SD.h b/libraries/SD/src/SD.h index b5e0d12da..54f0dcc0f 100644 --- a/libraries/SD/src/SD.h +++ b/libraries/SD/src/SD.h @@ -17,8 +17,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ -#ifndef __SD_H__ -#define __SD_H__ +#pragma once #include #include @@ -27,13 +26,17 @@ #undef FILE_READ #define FILE_READ O_READ #undef FILE_WRITE -#define FILE_WRITE (O_READ | O_WRITE | O_CREAT | O_APPEND) +#define FILE_WRITE (O_RDWR | O_CREAT | O_APPEND) class SDClass { public: - boolean begin(uint8_t csPin, uint32_t cfg = SPI_HALF_SPEED) { - SDFS.setConfig(SDFSConfig(csPin, cfg)); + boolean begin(uint8_t csPin, HardwareSPI &spi) { + SDFS.setConfig(SDFSConfig(csPin, SPI_HALF_SPEED, spi)); + return (boolean)SDFS.begin(); + } + boolean begin(uint8_t csPin, uint32_t cfg = SPI_HALF_SPEED, HardwareSPI &spi = SPI) { + SDFS.setConfig(SDFSConfig(csPin, cfg, spi)); return (boolean)SDFS.begin(); } @@ -159,9 +162,23 @@ class SDClass { private: const char *getMode(uint8_t mode) { - bool read = (mode & O_READ) ? true : false; - bool write = (mode & O_WRITE) ? true : false; - bool append = (mode & O_APPEND) ? true : false; + bool read = false; + bool write = false; + + switch (mode & O_ACCMODE) { + case O_RDONLY: + read = true; + break; + case O_WRONLY: + write = true; + break; + case O_RDWR: + read = true; + write = true; + break; + } + const bool append = (mode & O_APPEND) > 0; + if (read & !write) { return "r"; } else if (!read & write & !append) { @@ -214,5 +231,3 @@ static inline uint8_t FAT_SECOND(uint16_t fatTime) { #if !defined(NO_GLOBAL_INSTANCES) && !defined(NO_GLOBAL_SD) extern SDClass SD; #endif - -#endif diff --git a/libraries/SDFS/src/SDFS.h b/libraries/SDFS/src/SDFS.h index aa05b2873..a83118554 100644 --- a/libraries/SDFS/src/SDFS.h +++ b/libraries/SDFS/src/SDFS.h @@ -1,6 +1,3 @@ -#ifndef SDFS_H -#define SDFS_H - /* SDFS.h - file system wrapper for SdLib Copyright (c) 2019 Earle F. Philhower, III. All rights reserved. @@ -27,6 +24,9 @@ License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ + +#pragma once + #include #include #include "FS.h" @@ -45,7 +45,7 @@ class SDFSConfig : public FSConfig { public: static constexpr uint32_t FSId = 0x53444653; - SDFSConfig(uint8_t csPin = 4, uint32_t spi = SD_SCK_MHZ(10)) : FSConfig(FSId, false), _csPin(csPin), _part(0), _spiSettings(spi) { } + SDFSConfig(uint8_t csPin = 4, uint32_t spi = SD_SCK_MHZ(10), HardwareSPI &port = SPI) : FSConfig(FSId, false), _csPin(csPin), _part(0), _spiSettings(spi), _spi(&port) { } SDFSConfig setAutoFormat(bool val = true) { _autoFormat = val; @@ -55,10 +55,14 @@ class SDFSConfig : public FSConfig { _csPin = pin; return *this; } - SDFSConfig setSPI(uint32_t spi) { + SDFSConfig setSPISpeed(uint32_t spi) { _spiSettings = spi; return *this; } + SDFSConfig setSPI(HardwareSPI &spi) { + _spi = &spi; + return true; + } SDFSConfig setPart(uint8_t part) { _part = part; return *this; @@ -68,6 +72,7 @@ class SDFSConfig : public FSConfig { uint8_t _csPin; uint8_t _part; uint32_t _spiSettings; + HardwareSPI *_spi; }; class SDFSImpl : public FSImpl { @@ -146,10 +151,11 @@ class SDFSImpl : public FSImpl { if (_mounted) { return true; } - _mounted = _fs.begin(_cfg._csPin, _cfg._spiSettings); + SdSpiConfig ssc(_cfg._csPin, SHARED_SPI, _cfg._spiSettings, _cfg._spi); + _mounted = _fs.begin(ssc); if (!_mounted && _cfg._autoFormat) { format(); - _mounted = _fs.begin(_cfg._csPin, _cfg._spiSettings); + _mounted = _fs.begin(ssc); } FsDateTime::setCallback(dateTimeCB); return _mounted; @@ -502,5 +508,3 @@ class SDFSDirImpl : public DirImpl { extern FS SDFS; using sdfs::SDFSConfig; #endif - -#endif // SDFS.h diff --git a/libraries/SPI/src/SPI.cpp b/libraries/SPI/src/SPI.cpp index 88932e868..689e30cd6 100644 --- a/libraries/SPI/src/SPI.cpp +++ b/libraries/SPI/src/SPI.cpp @@ -125,7 +125,7 @@ uint16_t SPIClassRP2040::transfer16(uint16_t data) { spi_set_format(_spi, 16, cpol(), cpha(), SPI_MSB_FIRST); DEBUGSPI("SPI::transfer16(%04x), cpol=%d, cpha=%d\n", data, cpol(), cpha()); spi_write16_read16_blocking(_spi, &data, &ret, 1); - ret = (_spis.getBitOrder() == MSBFIRST) ? ret : reverseByte(ret); + ret = (_spis.getBitOrder() == MSBFIRST) ? ret : reverse16Bit(ret); DEBUGSPI("SPI: read back %02x\n", ret); return ret; } @@ -135,30 +135,29 @@ void SPIClassRP2040::transfer(void *buf, size_t count) { uint8_t *buff = reinterpret_cast(buf); for (size_t i = 0; i < count; i++) { *buff = transfer(*buff); - *buff = (_spis.getBitOrder() == MSBFIRST) ? *buff : reverseByte(*buff); buff++; } DEBUGSPI("SPI::transfer completed\n"); } -void SPIClassRP2040::transfer(void *txbuf, void *rxbuf, size_t count) { +void SPIClassRP2040::transfer(const void *txbuf, void *rxbuf, size_t count) { if (!_initted) { return; } DEBUGSPI("SPI::transfer(%p, %p, %d)\n", txbuf, rxbuf, count); - uint8_t *txbuff = reinterpret_cast(txbuf); + const uint8_t *txbuff = reinterpret_cast(txbuf); uint8_t *rxbuff = reinterpret_cast(rxbuf); // MSB version is easy! if (_spis.getBitOrder() == MSBFIRST) { spi_set_format(_spi, 8, cpol(), cpha(), SPI_MSB_FIRST); - if (rxbuf == NULL) { // transmit only! + if (rxbuf == nullptr) { // transmit only! spi_write_blocking(_spi, txbuff, count); return; } - if (txbuf == NULL) { // receive only! + if (txbuf == nullptr) { // receive only! spi_read_blocking(_spi, 0xFF, rxbuff, count); return; } @@ -178,7 +177,7 @@ void SPIClassRP2040::transfer(void *txbuf, void *rxbuf, size_t count) { } void SPIClassRP2040::beginTransaction(SPISettings settings) { - DEBUGSPI("SPI::beginTransaction(clk=%d, bo=%s\n", _spis.getClockFreq(), (_spis.getBitOrder() == MSBFIRST) ? "MSB" : "LSB"); + DEBUGSPI("SPI::beginTransaction(clk=%lu, bo=%s\n", _spis.getClockFreq(), (_spis.getBitOrder() == MSBFIRST) ? "MSB" : "LSB"); if (_initted && settings == _spis) { DEBUGSPI("SPI: Reusing existing initted SPI\n"); } else { diff --git a/libraries/SPI/src/SPI.h b/libraries/SPI/src/SPI.h index 3dc1f78c9..44b1e8648 100644 --- a/libraries/SPI/src/SPI.h +++ b/libraries/SPI/src/SPI.h @@ -35,8 +35,8 @@ class SPIClassRP2040 : public arduino::HardwareSPI { // Sends buffer in 8 bit chunks. Overwrites buffer with read data void transfer(void *buf, size_t count) override; - // Sends one buffer and receives into another, much faster! can set rx or txbuf to NULL - void transfer(void *txbuf, void *rxbuf, size_t count); + // Sends one buffer and receives into another, much faster! can set rx or txbuf to nullptr + void transfer(const void *txbuf, void *rxbuf, size_t count) override; // Call before/after every complete transaction void beginTransaction(SPISettings settings) override; diff --git a/libraries/SerialBT/examples/BTSerialUppercase/BTSerialUppercase.ino b/libraries/SerialBT/examples/BTSerialUppercase/BTSerialUppercase.ino new file mode 100644 index 000000000..5a3337f01 --- /dev/null +++ b/libraries/SerialBT/examples/BTSerialUppercase/BTSerialUppercase.ino @@ -0,0 +1,33 @@ +// A very simple Serial-over-BT app that reads input from the host and CAPITALIZES it. +// Released to the public domain by Earle F. Philhower, III, in February 2023 + +// Under Linux to connect to the PicoW +// 1. Pair to the "PicoW Serial XX:XX..." device using your favorite GUI, entering a PIN of "0000" +// 2. Execute "sudo rfcomm bind 0 00:00:00:00:00:00" to make a `/dev/rfcomm0" device, replacing the "00:00.." with the MAC as listed in the device name +// 3. Run "minicom -D /dev/rfcomm0" and type away +// 4. To remove the virtual serial port, execute "sudo rfcomm release rfcomm0" + +// Under Windows to connect to the PicoW +// 1. Pair to the "PicoW Serial XX:XX..." device using the copntrol panel, ignoring any PIN it says to check for +// 2. At this point you will have a new COM: port. You may need to use the Device Manager to find it's number. +// 3. Open up COMX: in your favorite terminal application and type away + +// Under Mac to connect to the PicoW +// 1. Sorry, you're on your own. If you have a Mac and can update this demo with a Pull Request it would be appreciated! + + +#include + +void setup() { + SerialBT.begin(); +} + +void loop() { + while (SerialBT) { + while (SerialBT.available()) { + char c = SerialBT.read(); + c = toupper(c); + SerialBT.write(c); + } + } +} diff --git a/libraries/SerialBT/keywords.txt b/libraries/SerialBT/keywords.txt new file mode 100644 index 000000000..4579ea83b --- /dev/null +++ b/libraries/SerialBT/keywords.txt @@ -0,0 +1,18 @@ +####################################### +# Syntax Coloring Map +####################################### + +####################################### +# Datatypes (KEYWORD1) +####################################### + +SerialBT KEYWORD1 + +####################################### +# Methods and Functions (KEYWORD2) +####################################### + +####################################### +# Constants (LITERAL1) +####################################### + diff --git a/libraries/SerialBT/library.properties b/libraries/SerialBT/library.properties new file mode 100644 index 000000000..47158d37a --- /dev/null +++ b/libraries/SerialBT/library.properties @@ -0,0 +1,10 @@ +name=SerialBT +version=1.0.0 +author=Earle F. Philhower, III +maintainer=Earle F. Philhower, III +sentence=Serial-over-Bluetooth for the PicoW +paragraph=Serial-over-Bluetooth for the PicoW +category=Communications +url=https://github.com/earlephilhower/arduino-pico +architectures=rp2040 +dot_a_linkage=true diff --git a/libraries/SerialBT/src/SerialBT.cpp b/libraries/SerialBT/src/SerialBT.cpp new file mode 100644 index 000000000..c0d0c6321 --- /dev/null +++ b/libraries/SerialBT/src/SerialBT.cpp @@ -0,0 +1,253 @@ +/* + Serial-over-Bluetooth for the Raspberry Pi Pico RP2040 + + Copyright (c) 2023 Earle F. Philhower, III + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include "SerialBT.h" +#include + +bool SerialBT_::setFIFOSize(size_t size) { + if (!size || _running) { + return false; + } + _fifoSize = size + 1; // Always 1 unused entry + return true; +} + +SerialBT_::SerialBT_() { + mutex_init(&_mutex); +} + +void SerialBT_::begin(unsigned long baud, uint16_t config) { + if (_running) { + end(); + } + + (void) baud; + (void) config; + + _overflow = false; + + _queue = new uint8_t[_fifoSize]; + _writer = 0; + _reader = 0; + + // register for HCI events + _hci_event_callback_registration.callback = &SerialBT_::PacketHandlerWrapper; + hci_add_event_handler(&_hci_event_callback_registration); + + l2cap_init(); + +#ifdef ENABLE_BLE + // Initialize LE Security Manager. Needed for cross-transport key derivation + sm_init(); +#endif + + rfcomm_init(); + rfcomm_register_service(SerialBT_::PacketHandlerWrapper, RFCOMM_SERVER_CHANNEL, 0xffff); // reserved channel, mtu limited by l2cap + + // init SDP, create record for SPP and register with SDP + sdp_init(); + bzero(_spp_service_buffer, sizeof(_spp_service_buffer)); + spp_create_sdp_record(_spp_service_buffer, 0x10001, RFCOMM_SERVER_CHANNEL, "PicoW Serial"); + sdp_register_service(_spp_service_buffer); + + gap_discoverable_control(1); + gap_ssp_set_io_capability(SSP_IO_CAPABILITY_DISPLAY_YES_NO); + gap_set_local_name("PicoW Serial 00:00:00:00:00:00"); + + // Turn on! + hci_power_control(HCI_POWER_ON); + + _running = true; +} + +void SerialBT_::end() { + if (!_running) { + return; + } + _running = false; + + hci_power_control(HCI_POWER_OFF); + lockBluetooth(); + delete[] _queue; + unlockBluetooth(); +} + +int SerialBT_::peek() { + CoreMutex m(&_mutex); + if (!_running || !m) { + return -1; + } + if (_writer != _reader) { + return _queue[_reader]; + } + return -1; +} + +int SerialBT_::read() { + CoreMutex m(&_mutex); + if (!_running || !m) { + return -1; + } + if (_writer != _reader) { + auto ret = _queue[_reader]; + asm volatile("" ::: "memory"); // Ensure the value is read before advancing + auto next_reader = (_reader + 1) % _fifoSize; + asm volatile("" ::: "memory"); // Ensure the reader value is only written once, correctly + _reader = next_reader; + return ret; + } + return -1; +} + +bool SerialBT_::overflow() { + if (!_running) { + return false; + } + + lockBluetooth(); + bool ovf = _overflow; + _overflow = false; + unlockBluetooth(); + + return ovf; +} + +int SerialBT_::available() { + CoreMutex m(&_mutex); + if (!_running || !m) { + return 0; + } + return (_fifoSize + _writer - _reader) % _fifoSize; +} + +int SerialBT_::availableForWrite() { + CoreMutex m(&_mutex); + if (!_running || !m) { + return 0; + } + return _connected ? 1 : 0; +} + +void SerialBT_::flush() { + // We always send blocking +} + +size_t SerialBT_::write(uint8_t c) { + return write(&c, 1); +} + +size_t SerialBT_::write(const uint8_t *p, size_t len) { + CoreMutex m(&_mutex); + if (!_running || !m || !_connected || !len) { + return 0; + } + _writeBuff = p; + _writeLen = len; + lockBluetooth(); + rfcomm_request_can_send_now_event(_channelID); + unlockBluetooth(); + while (_connected && _writeLen) { + /* noop busy wait */ + } + return len; +} + +SerialBT_::operator bool() { + return _running; +} + +void SerialBT_::packetHandler(uint8_t type, uint16_t channel, uint8_t *packet, uint16_t size) { + UNUSED(channel); + bd_addr_t event_addr; + //uint8_t rfcomm_channel_nr; + //uint16_t mtu; + int i; + + switch (type) { + case HCI_EVENT_PACKET: + switch (hci_event_packet_get_type(packet)) { + case HCI_EVENT_PIN_CODE_REQUEST: + //Serial.printf("Pin code request - using '0000'\n"); + hci_event_pin_code_request_get_bd_addr(packet, event_addr); + gap_pin_code_response(event_addr, "0000"); + break; + + case HCI_EVENT_USER_CONFIRMATION_REQUEST: + // ssp: inform about user confirmation request + //Serial.printf("SSP User Confirmation Request with numeric value '%06" PRIu32 "'\n", little_endian_read_32(packet, 8)); + //Serial.printf("SSP User Confirmation Auto accept\n"); + break; + + case RFCOMM_EVENT_INCOMING_CONNECTION: + rfcomm_event_incoming_connection_get_bd_addr(packet, event_addr); + //rfcomm_channel_nr = rfcomm_event_incoming_connection_get_server_channel(packet); + _channelID = rfcomm_event_incoming_connection_get_rfcomm_cid(packet); + //Serial.printf("RFCOMM channel %u requested for %s\n", rfcomm_channel_nr, bd_addr_to_str(event_addr)); + rfcomm_accept_connection(_channelID); + break; + + case RFCOMM_EVENT_CHANNEL_OPENED: + if (rfcomm_event_channel_opened_get_status(packet)) { + //Serial.printf("RFCOMM channel open failed, status 0x%02x\n", rfcomm_event_channel_opened_get_status(packet)); + } else { + _channelID = rfcomm_event_channel_opened_get_rfcomm_cid(packet); + //mtu = rfcomm_event_channel_opened_get_max_frame_size(packet); + //Serial.printf("RFCOMM channel open succeeded. New RFCOMM Channel ID %u, max frame size %u\n", rfcomm_channel_id, mtu); + _connected = true; + } + break; + case RFCOMM_EVENT_CAN_SEND_NOW: + rfcomm_send(_channelID, (uint8_t *)_writeBuff, _writeLen); + _writeLen = 0; + break; + case RFCOMM_EVENT_CHANNEL_CLOSED: + //Serial.printf("RFCOMM channel closed\n"); + _channelID = 0; + _connected = false; + break; + + default: + break; + } + break; + + case RFCOMM_DATA_PACKET: + for (i = 0; i < size; i++) { + auto next_writer = _writer + 1; + if (next_writer == _fifoSize) { + next_writer = 0; + } + if (next_writer != _reader) { + _queue[_writer] = packet[i]; + asm volatile("" ::: "memory"); // Ensure the queue is written before the written count advances + // Avoid using division or mod because the HW divider could be in use + _writer = next_writer; + } else { + _overflow = true; + } + } + break; + + default: + break; + } +} + +SerialBT_ SerialBT; diff --git a/libraries/SerialBT/src/SerialBT.h b/libraries/SerialBT/src/SerialBT.h new file mode 100644 index 000000000..75e4b5c29 --- /dev/null +++ b/libraries/SerialBT/src/SerialBT.h @@ -0,0 +1,98 @@ +/* + Serial-over-Bluetooth for the Raspberry Pi Pico RP2040 + + Copyright (c) 2023 Earle F. Philhower, III + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#pragma once + +#include <_needsbt.h> +#include +#include +#include +#include +#include +#include +#include + +class SerialBT_; +extern SerialBT_ SerialBT; + +class SerialBT_ : public HardwareSerial { +public: + SerialBT_(); + + bool setFIFOSize(size_t size); + + void begin(unsigned long baud = 115200) override { + begin(baud, SERIAL_8N1); + }; + void begin(unsigned long baud, uint16_t config) override; + void end() override; + + virtual int peek() override; + virtual int read() override; + virtual int available() override; + virtual int availableForWrite() override; + virtual void flush() override; + virtual size_t write(uint8_t c) override; + virtual size_t write(const uint8_t *p, size_t len) override; + using Print::write; + bool overflow(); + operator bool() override; + + // ESP8266 compat + void setDebugOutput(bool unused) { + (void) unused; + } + + static void PacketHandlerWrapper(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t packet_size) { + SerialBT.packetHandler(packet_type, channel, packet, packet_size); + } + + void packetHandler(uint8_t type, uint16_t channel, uint8_t *packet, uint16_t size); + + static void lockBluetooth() { + async_context_acquire_lock_blocking(cyw43_arch_async_context()); + } + + static void unlockBluetooth() { + async_context_release_lock(cyw43_arch_async_context()); + } + +private: + bool _running = false; + mutex_t _mutex; + bool _overflow = false; + volatile bool _connected = false; + + + // Lockless, IRQ-handled circular queue + uint32_t _writer; + uint32_t _reader; + size_t _fifoSize = 32; + uint8_t *_queue; + + const int RFCOMM_SERVER_CHANNEL = 1; + + uint16_t _channelID; + uint8_t _spp_service_buffer[150]; + btstack_packet_callback_registration_t _hci_event_callback_registration; + + volatile int _writeLen = 0; + const void *_writeBuff; +}; diff --git a/libraries/Servo/src/Servo.h b/libraries/Servo/src/Servo.h index 0e389878c..4b1d1967c 100644 --- a/libraries/Servo/src/Servo.h +++ b/libraries/Servo/src/Servo.h @@ -37,8 +37,7 @@ detach() - Stops an attached servos from pulsing its i/o pin. */ -#ifndef Servo_h -#define Servo_h +#pragma once #include #include @@ -89,5 +88,3 @@ class Servo { }; - -#endif diff --git a/libraries/SingleFileDrive/examples/DataLoggerUSB/DataLoggerUSB.ino b/libraries/SingleFileDrive/examples/DataLoggerUSB/DataLoggerUSB.ino new file mode 100644 index 000000000..1ee6864c1 --- /dev/null +++ b/libraries/SingleFileDrive/examples/DataLoggerUSB/DataLoggerUSB.ino @@ -0,0 +1,92 @@ +// Simple logger with USB upload to PC +// Uses SingleFileDrive to export an onboard LittleFS file to the computer +// The PC can open/copy the file, and then the user can delete it to restart + +// Released to the public domain, 2022 - Earle F. Philhower, III + +#include +#include + +uint32_t cnt = 0; +bool okayToWrite = true; + +// Make the CSV file and give it a simple header +void headerCSV() { + File f = LittleFS.open("data.csv", "w"); + f.printf("sample,millis,temp,rand\n"); + f.close(); + cnt = 0; +} + +// Called when the USB stick connected to a PC and the drive opened +// Note this is from a USB IRQ so no printing to SerialUSB/etc. +void plug(uint32_t i) { + (void) i; + okayToWrite = false; +} + +// Called when the USB is ejected or removed from a PC +// Note this is from a USB IRQ so no printing to SerialUSB/etc. +void unplug(uint32_t i) { + (void) i; + okayToWrite = true; +} + +// Called when the PC tries to delete the single file +// Note this is from a USB IRQ so no printing to SerialUSB/etc. +void deleteCSV(uint32_t i) { + (void) i; + LittleFS.remove("data.csv"); + headerCSV(); +} + +void setup() { + Serial.begin(); + delay(5000); + + LittleFS.begin(); + + // Set up the USB disk share + singleFileDrive.onDelete(deleteCSV); + singleFileDrive.onPlug(plug); + singleFileDrive.onUnplug(unplug); + singleFileDrive.begin("data.csv", "Recorded data from the Raspberry Pi Pico.csv"); + + // Find the last written data + File f = LittleFS.open("data.csv", "r"); + if (!f || !f.size()) { + cnt = 1; + headerCSV(); + } else { + if (f.size() > 2048) { + f.seek(f.size() - 1024); + } + do { + String s = f.readStringUntil('\n'); + sscanf(s.c_str(), "%lu,", &cnt); + } while (f.available()); + f.close(); + cnt++; + } + + Serial.printf("Starting acquisition at %lu\n", cnt); +} + +void loop() { + float temp = analogReadTemp(); + uint32_t hwrand = rp2040.hwrand32(); + // Make sure the USB connect doesn't happen while we're writing! + noInterrupts(); + if (okayToWrite) { + Serial.printf("Sampling...%lu\n", cnt); + // Don't want the USB to connect during an update! + File f = LittleFS.open("data.csv", "a"); + if (f) { + f.printf("%lu,%lu,%f,%lu\n", cnt++, millis(), temp, hwrand); + f.close(); + } + } + interrupts(); + + delay(10000); +} diff --git a/libraries/SingleFileDrive/keywords.txt b/libraries/SingleFileDrive/keywords.txt new file mode 100644 index 000000000..ca1c16ddf --- /dev/null +++ b/libraries/SingleFileDrive/keywords.txt @@ -0,0 +1,22 @@ +####################################### +# Syntax Coloring Map +####################################### + +####################################### +# Datatypes (KEYWORD1) +####################################### + +SingleFileDrive KEYWORD1 + +####################################### +# Methods and Functions (KEYWORD2) +####################################### + +singleFileDrive KEYWORD1 +onDelete KEYWORD1 +onPlug KEYWORD1 +onUnplug KEYWORD1 + +####################################### +# Constants (LITERAL1) +####################################### diff --git a/libraries/SingleFileDrive/library.properties b/libraries/SingleFileDrive/library.properties new file mode 100644 index 000000000..ea30d2380 --- /dev/null +++ b/libraries/SingleFileDrive/library.properties @@ -0,0 +1,10 @@ +name=SingleFileDrive +version=1.0.0 +author=Earle F. Philhower, III +maintainer=Earle F. Philhower, III +sentence=Allows using USB MSC (USB stick) to transfer an onboard flash file to a PC +paragraph=Emulates a USB stick and presents a single file for users to copy over/erase +category=Device Control +url=https://github.com/earlephilhower/arduino-pico +architectures=rp2040 +dot_a_linkage=true diff --git a/libraries/SingleFileDrive/src/SingleFileDrive.cpp b/libraries/SingleFileDrive/src/SingleFileDrive.cpp new file mode 100644 index 000000000..379035cca --- /dev/null +++ b/libraries/SingleFileDrive/src/SingleFileDrive.cpp @@ -0,0 +1,395 @@ +/* + SingleFileDrive - Emulates a USB stick for easy data transfer + Copyright (c) 2022 Earle F. Philhower, III. All rights reserved. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include +#include +#include + +SingleFileDrive singleFileDrive; + +static const uint32_t _hddsize = (256 * 1024 * 1024); // 256MB +static const uint32_t _hddsects = _hddsize / 512; + +// Ensure we are logged in to the USB framework +void __USBInstallMassStorage() { + /* dummy */ +} + +SingleFileDrive::SingleFileDrive() { +} + +SingleFileDrive::~SingleFileDrive() { + end(); +} + +void SingleFileDrive::onDelete(void (*cb)(uint32_t), uint32_t cbData) { + _cbDelete = cb; + _cbDeleteData = cbData; +} + +void SingleFileDrive::onPlug(void (*cb)(uint32_t), uint32_t cbData) { + _cbPlug = cb; + _cbPlugData = cbData; +} + +void SingleFileDrive::onUnplug(void (*cb)(uint32_t), uint32_t cbData) { + _cbUnplug = cb; + _cbUnplugData = cbData; +} + +bool SingleFileDrive::begin(const char *localFile, const char *dosFile) { + if (_started) { + return false; + } + _localFile = strdup(localFile); + _dosFile = strdup(dosFile); + _started = true; + return true; +} + +void SingleFileDrive::end() { + _started = false; + free(_localFile); + free(_dosFile); + _localFile = nullptr; + _dosFile = nullptr; +} + +void SingleFileDrive::bootSector(char buff[512]) { + // 256MB FAT16 stolen from mkfs.fat + // dd if=/dev/zero of=/tmp/fat.bin bs=1M seek=255 count=1 + // mkfs.fat -F 16 -r 16 -n PICODISK -i 12345678 -s 128 -m ':(' /tmp/fat.bin + const uint8_t hdr[] = { + 0xeb, 0x3c, 0x90, 0x6d, 0x6b, 0x66, 0x73, 0x2e, 0x66, 0x61, 0x74, 0x00, + 0x02, 0x80, 0x80, 0x00, 0x02, 0x00, 0x08, 0x00, 0x00, 0xf8, 0x80, 0x00, + 0x20, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, + 0x80, 0x00, 0x29, 0x78, 0x56, 0x34, 0x12, 0x50, 0x49, 0x43, 0x4f, 0x44, + 0x49, 0x53, 0x4b, 0x20, 0x20, 0x20, 0x46, 0x41, 0x54, 0x31, 0x36, 0x20, + 0x20, 0x20, 0x0e, 0x1f, 0xbe, 0x5b, 0x7c, 0xac, 0x22, 0xc0, 0x74, 0x0b, + 0x56, 0xb4, 0x0e, 0xbb, 0x07, 0x00, 0xcd, 0x10, 0x5e, 0xeb, 0xf0, 0x32, + 0xe4, 0xcd, 0x16, 0xcd, 0x19, 0xeb, 0xfe, 0x3a, 0x28, 0x0d, 0x0a, 0x00 + }; + memset(buff, 0, 512); + memcpy(buff, hdr, sizeof(hdr)); + buff[0x1fe] = 0x55; + buff[0x1ff] = 0xff; +} + +static char _toLegalFATChar(char c) { + const char *odds = "!#$%&'()-@^_`{}~"; + c = toupper(c); + if (((c >= '0') && (c <= '9')) || ((c >= 'A') && (c <= 'Z')) || strchr(odds, c)) { + return c; + } else { + return '~'; + } +} + +void SingleFileDrive::directorySector(char buff[512]) { + const uint8_t lbl[] = { + 0x50, 0x49, 0x43, 0x4f, 0x44, 0x49, 0x53, 0x4b, 0x20, 0x20, 0x20, 0x08, 0x00, 0x00, 0xac, 0x56, + 0x82, 0x55, 0x82, 0x55, 0x00, 0x00, 0xac, 0x56, 0x82, 0x55 + }; //, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + memset(buff, 0, 512); + memcpy(buff, lbl, sizeof(lbl)); + buff += 32; // Skip the just-set label + + // Create a legal 11-char UPPERCASE FILENAME WITH 0x20 PAD + char SFN[11]; + memset(SFN, ' ', 11); + for (int i = 0; (i < 8) && _dosFile[i] && (_dosFile[i] != '.'); i++) { + SFN[i] = _toLegalFATChar(_dosFile[i]); + } + char *dot = _dosFile + strlen(_dosFile) - 1; + while ((dot >= _dosFile) && (*dot != '.')) { + dot--; + } + if (*dot == '.') { + dot++; + for (int i = 0; (i < 3) && dot[i]; i++) { + SFN[8 + i] = _toLegalFATChar(dot[i]); + } + } + uint8_t chksum = 0; // for LFN + for (int i = 0; i < 11; i++) { + chksum = (chksum >> 1) + (chksum << 7) + SFN[i]; + } + + // Create LFN structure + int entries = (strlen(_dosFile) + 12) / 13; // round up + for (int i = 0; i < entries; i++) { + *buff++ = (entries - i) | (i == 0 ? 0x40 : 0); + const char *partname = _dosFile + 13 * (entries - i - 1); + for (int j = 0; j < 13; j++) { + uint16_t u; + if (j > (int)strlen(partname)) { + u = 0xffff; + } else { + u = partname[j] & 0xff; + } + *buff++ = u & 0xff; + *buff++ = (u >> 8) & 0xff; + if (j == 4) { + *buff++ = 0x0f; // LFN ATTR + *buff++ = 0; + *buff++ = chksum; + } else if (j == 10) { + *buff++ = 0; + *buff++ = 0; + } + } + } + + // Create SFN + memset(buff, 0, 32); + for (int i = 0; i < 11; i++) { + buff[i] = SFN[i]; + } + buff[0x0b] = 0x20; // ATTR = Archive + // Ignore creation data/time, etc. + buff[0x1a] = 0x03; // Starting cluster 3 + File f = LittleFS.open(_localFile, "r"); + int size = f.size(); + f.close(); + buff[0x1c] = size & 255; + buff[0x1d] = (size >> 8) & 255; + buff[0x1e] = (size >> 16) & 255; // 16MB or smaller +} + +void SingleFileDrive::fatSector(char fat[512]) { + memset(fat, 0, 512); + fat[0x00] = 0xff; + fat[0x01] = 0xf8; + fat[0x02] = 0xff; + fat[0x03] = 0xff; + int cluster = 3; + File f = LittleFS.open(_localFile, "r"); + int size = f.size(); + f.close(); + while (size > 65536) { + fat[cluster * 2] = (cluster + 1) & 0xff; + fat[cluster * 2 + 1] = ((cluster + 1) >> 8) & 0xff; + cluster++; + size -= 65536; + } + fat[cluster * 2] = 0xff; + fat[cluster * 2 + 1] = 0xff; +} + +// Invoked to determine max LUN +extern "C" uint8_t tud_msc_get_maxlun_cb(void) { + return 1; +} + +// Invoked when received SCSI_CMD_INQUIRY +// Application fill vendor id, product id and revision with string up to 8, 16, 4 characters respectively +extern "C" void tud_msc_inquiry_cb(uint8_t lun, uint8_t vendor_id[8], uint8_t product_id[16], uint8_t product_rev[4]) { + (void) lun; + + const char vid[] = "PicoDisk"; + const char pid[] = "Mass Storage"; + const char rev[] = "1.0"; + + memcpy(vendor_id, vid, strlen(vid)); + memcpy(product_id, pid, strlen(pid)); + memcpy(product_rev, rev, strlen(rev)); +} + +bool SingleFileDrive::testUnitReady() { + return _started; +} + +// Invoked when received Test Unit Ready command. +// return true allowing host to read/write this LUN e.g SD card inserted +extern "C" bool tud_msc_test_unit_ready_cb(uint8_t lun) { + (void) lun; + + return singleFileDrive.testUnitReady(); +} + +// Invoked when received SCSI_CMD_READ_CAPACITY_10 and SCSI_CMD_READ_FORMAT_CAPACITY to determine the disk size +// Application update block count and block size +extern "C" void tud_msc_capacity_cb(uint8_t lun, uint32_t* block_count, uint16_t* block_size) { + (void) lun; + *block_count = _hddsects; + *block_size = 512; +} + + +// Callback invoked when received READ10 command. +// Copy disk's data to buffer (up to bufsize) and return number of copied bytes. +extern "C" int32_t tud_msc_read10_cb(uint8_t lun, uint32_t lba, uint32_t offset, void* buffer, uint32_t bufsize) { + (void) lun; + return singleFileDrive.read10(lba, offset, buffer, bufsize); +} + +int32_t SingleFileDrive::read10(uint32_t lba, uint32_t offset, void* buffer, uint32_t bufsize) { + if (!_started || (lba >= _hddsects)) { + return -1; + } + + uint32_t toread = bufsize; + uint8_t *curbuff = (uint8_t *)buffer; + + while (bufsize > 0) { + if (lba == 0) { + bootSector(_sectBuff); + } else if ((lba == 128) || (lba == 256)) { + fatSector(_sectBuff); + } else if (lba == 384) { + directorySector(_sectBuff); + } else if (lba >= 640) { + File f = LittleFS.open(_localFile, "r"); + f.seek((lba - 640) * 512); + f.read((uint8_t*)_sectBuff, 512); + f.close(); + } else { + memset(_sectBuff, 0, sizeof(_sectBuff)); + } + + uint32_t cplen = 512 - offset; + if (bufsize < cplen) { + cplen = bufsize; + } + memcpy(curbuff, _sectBuff + offset, cplen); + curbuff += cplen; + offset = 0; + lba++; + bufsize -= cplen; + } + + return toread; +} + +extern "C" bool tud_msc_is_writable_cb(uint8_t lun) { + (void) lun; + + return true; +} + +// Callback invoked when received WRITE10 command. +// Process data in buffer to disk's storage and return number of written bytes +extern "C" int32_t tud_msc_write10_cb(uint8_t lun, uint32_t lba, uint32_t offset, uint8_t* buffer, uint32_t bufsize) { + (void) lun; + return singleFileDrive.write10(lba, offset, buffer, bufsize); +} + +int32_t SingleFileDrive::write10(uint32_t lba, uint32_t offset, uint8_t* buffer, uint32_t bufsize) { + if (!_started || (lba >= _hddsects)) { + return -1; + } + + uint32_t addr = lba * 512 + offset; + uint32_t hotspot = 384 * 512 + 0x20; + if ((addr > hotspot) || (addr + bufsize < hotspot)) { + // Did not try and erase the file entry, ignore + return bufsize; + } + int off = hotspot - addr; + uint8_t *ptr = (uint8_t *)buffer; + ptr += off; + if (*ptr == 0xe5) { + if (_cbDelete) { + _cbDelete(_cbDeleteData); + } + } + + return bufsize; +} + +extern "C" bool tud_msc_set_sense(uint8_t lun, uint8_t sense_key, uint8_t add_sense_code, uint8_t add_sense_qualifier); + +// Callback invoked when received an SCSI command not in built-in list below +// - READ_CAPACITY10, READ_FORMAT_CAPACITY, INQUIRY, MODE_SENSE6, REQUEST_SENSE +// - READ10 and WRITE10 has their own callbacks +extern "C" int32_t tud_msc_scsi_cb(uint8_t lun, uint8_t const scsi_cmd[16], void* buffer, uint16_t bufsize) { + const int SCSI_CMD_PREVENT_ALLOW_MEDIUM_REMOVAL = 0x1E; + const int SCSI_CMD_START_STOP_UNIT = 0x1B; + const int SCSI_SENSE_ILLEGAL_REQUEST = 0x05; + + void const* response = NULL; + int32_t resplen = 0; + + // most scsi handled is input + bool in_xfer = true; + scsi_start_stop_unit_t const * start_stop = (scsi_start_stop_unit_t const *) scsi_cmd; + switch (scsi_cmd[0]) { + case SCSI_CMD_PREVENT_ALLOW_MEDIUM_REMOVAL: + // Host is about to read/write etc ... better not to disconnect disk + if (scsi_cmd[4] & 1) { + singleFileDrive.plug(); + } + resplen = 0; + break; + case SCSI_CMD_START_STOP_UNIT: + // Host try to eject/safe remove/poweroff us. We could safely disconnect with disk storage, or go into lower power + if (!start_stop->start && start_stop->load_eject) { + singleFileDrive.unplug(); + } else if (start_stop->start && start_stop->load_eject) { + singleFileDrive.plug(); + } + resplen = 0; + break; + default: + // Set Sense = Invalid Command Operation + tud_msc_set_sense(lun, SCSI_SENSE_ILLEGAL_REQUEST, 0x20, 0x00); + // negative means error -> tinyusb could stall and/or response with failed status + resplen = -1; + break; + } + + // return resplen must not larger than bufsize + if (resplen > bufsize) { + resplen = bufsize; + } + + if (response && (resplen > 0)) { + if (in_xfer) { + memcpy(buffer, response, resplen); + } else { + // SCSI output + } + } + + return resplen; +} + +void SingleFileDrive::plug() { + if (_started && _cbPlug) { + _cbPlug(_cbPlugData); + } +} + +void SingleFileDrive::unplug() { + if (_started && _cbUnplug) { + _cbUnplug(_cbUnplugData); + } +} + +// Callback invoked on start/stop +extern "C" bool tud_msc_start_stop_cb(uint8_t lun, uint8_t power_condition, bool start, bool load_eject) { + (void) lun; + (void) power_condition; + if (start && load_eject) { + singleFileDrive.plug(); + } else if (!start && load_eject) { + singleFileDrive.unplug(); + } + return true; +} diff --git a/libraries/SingleFileDrive/src/SingleFileDrive.h b/libraries/SingleFileDrive/src/SingleFileDrive.h new file mode 100644 index 000000000..ccc733a18 --- /dev/null +++ b/libraries/SingleFileDrive/src/SingleFileDrive.h @@ -0,0 +1,65 @@ +/* + SingleFileDrive - Emulates a USB stick for easy data transfer + Copyright (c) 2022 Earle F. Philhower, III. All rights reserved. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#pragma once + +#include + +class SingleFileDrive { +public: + SingleFileDrive(); + ~SingleFileDrive(); + + bool begin(const char *localFile, const char *dosFile); + void end(); + + void onDelete(void (*cb)(uint32_t), uint32_t cbData = 0); + void onPlug(void (*cb)(uint32_t), uint32_t cbData = 0); + void onUnplug(void (*cb)(uint32_t), uint32_t cbData = 0); + + // Only for internal TinyUSB callback use + bool testUnitReady(); + int32_t read10(uint32_t lba, uint32_t offset, void* buffer, uint32_t bufsize); + int32_t write10(uint32_t lba, uint32_t offset, uint8_t* buffer, uint32_t bufsize); + void plug();; + void unplug(); + +private: + void bootSector(char buff[512]); + void directorySector(char buff[512]); + void fatSector(char buff[512]); + +private: + bool _started = false; + char *_localFile = nullptr; + char *_dosFile = nullptr; + + char _sectBuff[512]; // Read sector region + + void (*_cbDelete)(uint32_t) = nullptr; + uint32_t _cbDeleteData = 0; + + void (*_cbPlug)(uint32_t) = nullptr; + uint32_t _cbPlugData = 0; + + void (*_cbUnplug)(uint32_t) = nullptr; + uint32_t _cbUnplugData = 0; +}; + +extern SingleFileDrive singleFileDrive; diff --git a/libraries/Updater/src/Updater.cpp b/libraries/Updater/src/Updater.cpp index 1d1e43629..237132b94 100644 --- a/libraries/Updater/src/Updater.cpp +++ b/libraries/Updater/src/Updater.cpp @@ -25,8 +25,6 @@ #include #include -#define DEBUG_UPDATER Serial - #include #ifndef ARDUINO_SIGNING #define ARDUINO_SIGNING 0 @@ -131,7 +129,7 @@ bool UpdaterClass::begin(size_t size, int command) { _command = command; #ifdef DEBUG_UPDATER - DEBUG_UPDATER.printf_P(PSTR("[begin] _startAddress: 0x%08X (%d)\n"), _startAddress, _startAddress); + DEBUG_UPDATER.printf_P(PSTR("[begin] _startAddress: 0x%08lX (%lu)\n"), _startAddress, _startAddress); DEBUG_UPDATER.printf_P(PSTR("[begin] _size: 0x%08zX (%zd)\n"), _size, _size); #endif @@ -190,7 +188,7 @@ bool UpdaterClass::end(bool evenIfRemaining) { _fp.read((uint8_t *)&sigLen, sizeof(uint32_t)); } #ifdef DEBUG_UPDATER - DEBUG_UPDATER.printf_P(PSTR("[Updater] sigLen: %d\n"), sigLen); + DEBUG_UPDATER.printf_P(PSTR("[Updater] sigLen: %lu\n"), sigLen); #endif if (sigLen != expectedSigLen) { _setError(UPDATE_ERROR_SIGN); @@ -200,7 +198,7 @@ bool UpdaterClass::end(bool evenIfRemaining) { int binSize = _size; if (expectedSigLen > 0) { - _size -= (sigLen + sizeof(uint32_t) /* The siglen word */); + binSize -= (sigLen + sizeof(uint32_t) /* The siglen word */); } _hash->begin(); #ifdef DEBUG_UPDATER @@ -278,7 +276,7 @@ bool UpdaterClass::end(bool evenIfRemaining) { picoOTA.addFile("firmware.bin"); picoOTA.commit(); #ifdef DEBUG_UPDATER - DEBUG_UPDATER.printf_P(PSTR("Staged: address:0x%08X, size:0x%08zX\n"), _startAddress, _size); + DEBUG_UPDATER.printf_P(PSTR("Staged: address:0x%08lX, size:0x%08zX\n"), _startAddress, _size); #endif } @@ -414,30 +412,37 @@ void UpdaterClass::_setError(int error) { } void UpdaterClass::printError(Print &out) { - out.printf_P(PSTR("ERROR[%u]: "), _error); + String err; + err = "ERROR["; + err += _error; + err += "]: "; if (_error == UPDATE_ERROR_OK) { - out.println(F("No Error")); + err += "No Error"; } else if (_error == UPDATE_ERROR_WRITE) { - out.println(F("Flash Write Failed")); + err += "Flash Write Failed"; } else if (_error == UPDATE_ERROR_ERASE) { - out.println(F("Flash Erase Failed")); + err += "Flash Erase Failed"; } else if (_error == UPDATE_ERROR_READ) { - out.println(F("Flash Read Failed")); + err += "Flash Read Failed"; } else if (_error == UPDATE_ERROR_SPACE) { - out.println(F("Not Enough Space")); + err += "Not Enough Space"; } else if (_error == UPDATE_ERROR_SIZE) { - out.println(F("Bad Size Given")); + err += "Bad Size Given"; } else if (_error == UPDATE_ERROR_STREAM) { - out.println(F("Stream Read Timeout")); + err += "Stream Read Timeout"; } else if (_error == UPDATE_ERROR_NO_DATA) { - out.println(F("No data supplied")); + err += "No data supplied"; } else if (_error == UPDATE_ERROR_MD5) { - out.printf_P(PSTR("MD5 Failed: expected:%s, calculated:%s\n"), _target_md5.c_str(), _md5.toString().c_str()); + err += "MD5 Failed: expected:"; + err += _target_md5.c_str(); + err += " calculated:"; + err += _md5.toString(); } else if (_error == UPDATE_ERROR_SIGN) { - out.println(F("Signature verification failed")); + err += "Signature verification failed"; } else { - out.println(F("UNKNOWN")); + err += "UNKNOWN"; } + out.println(err.c_str()); } UpdaterClass Update; diff --git a/libraries/WebServer/examples/AdvancedWebServer/AdvancedWebServer.ino b/libraries/WebServer/examples/AdvancedWebServer/AdvancedWebServer.ino new file mode 100644 index 000000000..e4de7c0c2 --- /dev/null +++ b/libraries/WebServer/examples/AdvancedWebServer/AdvancedWebServer.ino @@ -0,0 +1,153 @@ +/* + Copyright (c) 2015, Majenko Technologies + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + * * Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + * * Redistributions in binary form must reproduce the above copyright notice, this + list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + * * Neither the name of Majenko Technologies nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include +#include +#include +#include +#include + +#ifndef STASSID +#define STASSID "your-ssid" +#define STAPSK "your-password" +#endif + +const char *ssid = STASSID; +const char *password = STAPSK; + +WebServer server(80); + +const int led = LED_BUILTIN; + +void handleRoot() { + static int cnt = 0; + digitalWrite(led, 1); + int sec = millis() / 1000; + int min = sec / 60; + int hr = min / 60; + + StreamString temp; + temp.reserve(500); // Preallocate a large chunk to avoid memory fragmentation + temp.printf("\ + \ + \ + Pico-W Demo\ + \ + \ + \ +

Hello from the Pico W!

\ +

Uptime: %02d:%02d:%02d

\ +

Free Memory: %d

\ +

Page Count: %d

\ + \ + \ +", hr, min % 60, sec % 60, rp2040.getFreeHeap(), ++cnt); + server.send(200, "text/html", temp); + digitalWrite(led, 0); +} + +void handleNotFound() { + digitalWrite(led, 1); + String message = "File Not Found\n\n"; + message += "URI: "; + message += server.uri(); + message += "\nMethod: "; + message += (server.method() == HTTP_GET) ? "GET" : "POST"; + message += "\nArguments: "; + message += server.args(); + message += "\n"; + + for (uint8_t i = 0; i < server.args(); i++) { + message += " " + server.argName(i) + ": " + server.arg(i) + "\n"; + } + + server.send(404, "text/plain", message); + digitalWrite(led, 0); +} + +void drawGraph() { + String out; + out.reserve(2600); + char temp[70]; + out += "\n"; + out += "\n"; + out += "\n"; + int y = rand() % 130; + for (int x = 10; x < 390; x += 10) { + int y2 = rand() % 130; + sprintf(temp, "\n", x, 140 - y, x + 10, 140 - y2); + out += temp; + y = y2; + } + out += "\n\n"; + + server.send(200, "image/svg+xml", out); +} + +void setup(void) { + pinMode(led, OUTPUT); + digitalWrite(led, 0); + Serial.begin(115200); + WiFi.mode(WIFI_STA); + WiFi.begin(ssid, password); + Serial.println(""); + + // Wait for connection + while (WiFi.status() != WL_CONNECTED) { + delay(500); + Serial.print("."); + } + + Serial.println(""); + Serial.print("Connected to "); + Serial.println(ssid); + Serial.print("IP address: "); + Serial.println(WiFi.localIP()); + + if (MDNS.begin("picow")) { + Serial.println("MDNS responder started"); + } + + server.on("/", handleRoot); + server.on("/test.svg", drawGraph); + server.on("/inline", []() { + server.send(200, "text/plain", "this works as well"); + }); + server.onNotFound(handleNotFound); + server.begin(); + Serial.println("HTTP server started"); +} + +void loop(void) { + server.handleClient(); + MDNS.update(); +} diff --git a/libraries/WebServer/examples/FSBrowser/FSBrowser.ino b/libraries/WebServer/examples/FSBrowser/FSBrowser.ino new file mode 100644 index 000000000..53bd0f14f --- /dev/null +++ b/libraries/WebServer/examples/FSBrowser/FSBrowser.ino @@ -0,0 +1,634 @@ +/* + FSBrowser - A web-based FileSystem Browser for Pico filesystems + + Copyright (c) 2015 Hristo Gochkov. All rights reserved. + This file is part of the Pico WebServer library for Arduino environment. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + See readme.md for more information. +*/ + +//////////////////////////////// + +// Select the FileSystem by uncommenting one of the lines below + +//#define USE_SPIFFS +#define USE_LITTLEFS +//#define USE_SDFS + +// Uncomment the following line to embed a version of the web page in the code +// (program code will be larger, but no file will have to be written to the filesystem). +// Note: the source file "extras/index_htm.h" must have been generated by "extras/reduce_index.sh" + +#define INCLUDE_FALLBACK_INDEX_HTM + +//////////////////////////////// + +#include +#include +#include +#include +#include + +#ifdef INCLUDE_FALLBACK_INDEX_HTM +#include "extras/index_htm.h" +#endif + +#if defined USE_SPIFFS +#include +const char* fsName = "SPIFFS"; +FS* fileSystem = &SPIFFS; +SPIFFSConfig fileSystemConfig = SPIFFSConfig(); +#elif defined USE_LITTLEFS +#include +const char* fsName = "LittleFS"; +FS* fileSystem = &LittleFS; +LittleFSConfig fileSystemConfig = LittleFSConfig(); +#elif defined USE_SDFS +#include +const char* fsName = "SDFS"; +FS* fileSystem = &SDFS; +SDFSConfig fileSystemConfig = SDFSConfig(); +// fileSystemConfig.setCSPin(chipSelectPin); +#else +#error Please select a filesystem first by uncommenting one of the "#define USE_xxx" lines at the beginning of the sketch. +#endif + + +#define DBG_OUTPUT_PORT Serial + +#ifndef STASSID +#define STASSID "your-ssid" +#define STAPSK "your-password" +#endif + +const char* ssid = STASSID; +const char* password = STAPSK; +const char* host = "fsbrowser"; + +WebServer server(80); + +static bool fsOK; +String unsupportedFiles = String(); + +File uploadFile; + +static const char TEXT_PLAIN[] PROGMEM = "text/plain"; +static const char FS_INIT_ERROR[] PROGMEM = "FS INIT ERROR"; +static const char FILE_NOT_FOUND[] PROGMEM = "FileNotFound"; + +//////////////////////////////// +// Utils to return HTTP codes, and determine content-type + +void replyOK() { + server.send(200, FPSTR(TEXT_PLAIN), ""); +} + +void replyOKWithMsg(String msg) { + server.send(200, FPSTR(TEXT_PLAIN), msg); +} + +void replyNotFound(String msg) { + server.send(404, FPSTR(TEXT_PLAIN), msg); +} + +void replyBadRequest(String msg) { + DBG_OUTPUT_PORT.println(msg); + server.send(400, FPSTR(TEXT_PLAIN), msg + "\r\n"); +} + +void replyServerError(String msg) { + DBG_OUTPUT_PORT.println(msg); + server.send(500, FPSTR(TEXT_PLAIN), msg + "\r\n"); +} + +#ifdef USE_SPIFFS +/* + Checks filename for character combinations that are not supported by FSBrowser (alhtough valid on SPIFFS). + Returns an empty String if supported, or detail of error(s) if unsupported +*/ +String checkForUnsupportedPath(String filename) { + String error = String(); + if (!filename.startsWith("/")) { + error += F("!NO_LEADING_SLASH! "); + } + if (filename.indexOf("//") != -1) { + error += F("!DOUBLE_SLASH! "); + } + if (filename.endsWith("/")) { + error += F("!TRAILING_SLASH! "); + } + return error; +} +#endif + + +//////////////////////////////// +// Request handlers + +/* + Return the FS type, status and size info +*/ +void handleStatus() { + DBG_OUTPUT_PORT.println("handleStatus"); + FSInfo fs_info; + String json; + json.reserve(128); + + json = "{\"type\":\""; + json += fsName; + json += "\", \"isOk\":"; + if (fsOK) { + fileSystem->info(fs_info); + json += F("\"true\", \"totalBytes\":\""); + json += fs_info.totalBytes; + json += F("\", \"usedBytes\":\""); + json += fs_info.usedBytes; + json += "\""; + } else { + json += "\"false\""; + } + json += F(",\"unsupportedFiles\":\""); + json += unsupportedFiles; + json += "\"}"; + + server.send(200, "application/json", json); +} + + +/* + Return the list of files in the directory specified by the "dir" query string parameter. + Also demonstrates the use of chunked responses. +*/ +void handleFileList() { + if (!fsOK) { + return replyServerError(FPSTR(FS_INIT_ERROR)); + } + + if (!server.hasArg("dir")) { + return replyBadRequest(F("DIR ARG MISSING")); + } + + String path = server.arg("dir"); + if (path != "/" && !fileSystem->exists(path)) { + return replyBadRequest("BAD PATH"); + } + + DBG_OUTPUT_PORT.println(String("handleFileList: ") + path); + Dir dir = fileSystem->openDir(path); + path = ""; + + // use HTTP/1.1 Chunked response to avoid building a huge temporary string + if (!server.chunkedResponseModeStart(200, "text/json")) { + server.send(505, F("text/html"), F("HTTP1.1 required")); + return; + } + + // use the same string for every line + String output; + output.reserve(64); + while (dir.next()) { +#ifdef USE_SPIFFS + String error = checkForUnsupportedPath(dir.fileName()); + if (error.length() > 0) { + DBG_OUTPUT_PORT.println(String("Ignoring ") + error + dir.fileName()); + continue; + } +#endif + if (output.length()) { + // send string from previous iteration + // as an HTTP chunk + Serial.println(output); + server.sendContent(output); + output = ','; + } else { + output = '['; + } + + output += "{\"type\":\""; + if (dir.isDirectory()) { + output += "dir"; + } else { + output += F("file\",\"size\":\""); + output += dir.fileSize(); + } + + output += F("\",\"name\":\""); + // Always return names without leading "/" + if (dir.fileName()[0] == '/') { + output += &(dir.fileName()[1]); + } else { + output += dir.fileName(); + } + + output += "\"}"; + } + + // send last string + output += "]"; + server.sendContent(output); + server.chunkedResponseFinalize(); +} + + +/* + Read the given file from the filesystem and stream it back to the client +*/ +bool handleFileRead(String path) { + DBG_OUTPUT_PORT.println(String("handleFileRead: ") + path); + if (!fsOK) { + replyServerError(FPSTR(FS_INIT_ERROR)); + return true; + } + + if (path.endsWith("/")) { + path += "index.htm"; + } + + String contentType; + if (server.hasArg("download")) { + contentType = F("application/octet-stream"); + } else { + contentType = mime::getContentType(path); + } + + if (!fileSystem->exists(path)) { + // File not found, try gzip version + path = path + ".gz"; + } + if (fileSystem->exists(path)) { + File file = fileSystem->open(path, "r"); + if (server.streamFile(file, contentType) != file.size()) { + DBG_OUTPUT_PORT.println("Sent less data than expected!"); + } + file.close(); + return true; + } + + return false; +} + + +/* + As some FS (e.g. LittleFS) delete the parent folder when the last child has been removed, + return the path of the closest parent still existing +*/ +String lastExistingParent(String path) { + while (path != "" && !fileSystem->exists(path)) { + if (path.lastIndexOf('/') > 0) { + path = path.substring(0, path.lastIndexOf('/')); + } else { + path = String(); // No slash => the top folder does not exist + } + } + DBG_OUTPUT_PORT.println(String("Last existing parent: ") + path); + return path; +} + +/* + Handle the creation/rename of a new file + Operation | req.responseText + ---------------+-------------------------------------------------------------- + Create file | parent of created file + Create folder | parent of created folder + Rename file | parent of source file + Move file | parent of source file, or remaining ancestor + Rename folder | parent of source folder + Move folder | parent of source folder, or remaining ancestor +*/ +void handleFileCreate() { + if (!fsOK) { + return replyServerError(FPSTR(FS_INIT_ERROR)); + } + + String path = server.arg("path"); + if (path == "") { + return replyBadRequest(F("PATH ARG MISSING")); + } + +#ifdef USE_SPIFFS + if (checkForUnsupportedPath(path).length() > 0) { + return replyServerError(F("INVALID FILENAME")); + } +#endif + + if (path == "/") { + return replyBadRequest("BAD PATH"); + } + if (fileSystem->exists(path)) { + return replyBadRequest(F("PATH FILE EXISTS")); + } + + String src = server.arg("src"); + if (src == "") { + // No source specified: creation + DBG_OUTPUT_PORT.println(String("handleFileCreate: ") + path); + if (path.endsWith("/")) { + // Create a folder + path.remove(path.length() - 1); + if (!fileSystem->mkdir(path)) { + return replyServerError(F("MKDIR FAILED")); + } + } else { + // Create a file + File file = fileSystem->open(path, "w"); + if (file) { + file.write((const char*)0); + file.close(); + } else { + return replyServerError(F("CREATE FAILED")); + } + } + if (path.lastIndexOf('/') > -1) { + path = path.substring(0, path.lastIndexOf('/')); + } + replyOKWithMsg(path); + } else { + // Source specified: rename + if (src == "/") { + return replyBadRequest("BAD SRC"); + } + if (!fileSystem->exists(src)) { + return replyBadRequest(F("SRC FILE NOT FOUND")); + } + + DBG_OUTPUT_PORT.println(String("handleFileCreate: ") + path + " from " + src); + + if (path.endsWith("/")) { + path.remove(path.length() - 1); + } + if (src.endsWith("/")) { + src.remove(src.length() - 1); + } + if (!fileSystem->rename(src, path)) { + return replyServerError(F("RENAME FAILED")); + } + replyOKWithMsg(lastExistingParent(src)); + } +} + + +/* + Delete the file or folder designed by the given path. + If it's a file, delete it. + If it's a folder, delete all nested contents first then the folder itself + + IMPORTANT NOTE: using recursion is generally not recommended on embedded devices and can lead to crashes (stack overflow errors). + This use is just for demonstration purpose, and FSBrowser might crash in case of deeply nested filesystems. + Please don't do this on a production system. +*/ +void deleteRecursive(String path) { + File file = fileSystem->open(path, "r"); + bool isDir = file.isDirectory(); + file.close(); + + // If it's a plain file, delete it + if (!isDir) { + fileSystem->remove(path); + return; + } + + // Otherwise delete its contents first + Dir dir = fileSystem->openDir(path); + + while (dir.next()) { + deleteRecursive(path + '/' + dir.fileName()); + } + + // Then delete the folder itself + fileSystem->rmdir(path); +} + + +/* + Handle a file deletion request + Operation | req.responseText + ---------------+-------------------------------------------------------------- + Delete file | parent of deleted file, or remaining ancestor + Delete folder | parent of deleted folder, or remaining ancestor +*/ +void handleFileDelete() { + if (!fsOK) { + return replyServerError(FPSTR(FS_INIT_ERROR)); + } + + String path = server.arg(0); + if (path == "" || path == "/") { + return replyBadRequest("BAD PATH"); + } + + DBG_OUTPUT_PORT.println(String("handleFileDelete: ") + path); + if (!fileSystem->exists(path)) { + return replyNotFound(FPSTR(FILE_NOT_FOUND)); + } + deleteRecursive(path); + + replyOKWithMsg(lastExistingParent(path)); +} + +/* + Handle a file upload request +*/ +void handleFileUpload() { + if (!fsOK) { + return replyServerError(FPSTR(FS_INIT_ERROR)); + } + if (server.uri() != "/edit") { + return; + } + HTTPUpload& upload = server.upload(); + if (upload.status == UPLOAD_FILE_START) { + String filename = upload.filename; + // Make sure paths always start with "/" + if (!filename.startsWith("/")) { + filename = "/" + filename; + } + DBG_OUTPUT_PORT.println(String("handleFileUpload Name: ") + filename); + uploadFile = fileSystem->open(filename, "w"); + if (!uploadFile) { + return replyServerError(F("CREATE FAILED")); + } + DBG_OUTPUT_PORT.println(String("Upload: START, filename: ") + filename); + } else if (upload.status == UPLOAD_FILE_WRITE) { + if (uploadFile) { + size_t bytesWritten = uploadFile.write(upload.buf, upload.currentSize); + if (bytesWritten != upload.currentSize) { + return replyServerError(F("WRITE FAILED")); + } + } + DBG_OUTPUT_PORT.println(String("Upload: WRITE, Bytes: ") + upload.currentSize); + } else if (upload.status == UPLOAD_FILE_END) { + if (uploadFile) { + uploadFile.close(); + } + DBG_OUTPUT_PORT.println(String("Upload: END, Size: ") + upload.totalSize); + } +} + + +/* + The "Not Found" handler catches all URI not explicitly declared in code + First try to find and return the requested file from the filesystem, + and if it fails, return a 404 page with debug information +*/ +void handleNotFound() { + if (!fsOK) { + return replyServerError(FPSTR(FS_INIT_ERROR)); + } + + String uri = WebServer::urlDecode(server.uri()); // required to read paths with blanks + + if (handleFileRead(uri)) { + return; + } + + // Dump debug data + String message; + message.reserve(100); + message = F("Error: File not found\n\nURI: "); + message += uri; + message += F("\nMethod: "); + message += (server.method() == HTTP_GET) ? "GET" : "POST"; + message += F("\nArguments: "); + message += server.args(); + message += '\n'; + for (uint8_t i = 0; i < server.args(); i++) { + message += F(" NAME:"); + message += server.argName(i); + message += F("\n VALUE:"); + message += server.arg(i); + message += '\n'; + } + message += "path="; + message += server.arg("path"); + message += '\n'; + DBG_OUTPUT_PORT.print(message); + + return replyNotFound(message); +} + +/* + This specific handler returns the index.htm (or a gzipped version) from the /edit folder. + If the file is not present but the flag INCLUDE_FALLBACK_INDEX_HTM has been set, falls back to the version + embedded in the program code. + Otherwise, fails with a 404 page with debug information +*/ +void handleGetEdit() { + if (handleFileRead(F("/edit/index.htm"))) { + return; + } + +#ifdef INCLUDE_FALLBACK_INDEX_HTM + server.sendHeader(F("Content-Encoding"), "gzip"); + server.send(200, "text/html", index_htm_gz, index_htm_gz_len); +#else + replyNotFound(FPSTR(FILE_NOT_FOUND)); +#endif +} + +void setup(void) { + //////////////////////////////// + // SERIAL INIT + DBG_OUTPUT_PORT.begin(115200); + DBG_OUTPUT_PORT.print('\n'); + + //////////////////////////////// + // FILESYSTEM INIT + + fileSystemConfig.setAutoFormat(false); + fileSystem->setConfig(fileSystemConfig); + fsOK = fileSystem->begin(); + DBG_OUTPUT_PORT.println(fsOK ? F("Filesystem initialized.") : F("Filesystem init failed!")); + +#ifdef USE_SPIFFS + // Debug: dump on console contents of filesystem with no filter and check filenames validity + Dir dir = fileSystem->openDir(""); + DBG_OUTPUT_PORT.println(F("List of files at root of filesystem:")); + while (dir.next()) { + String error = checkForUnsupportedPath(dir.fileName()); + String fileInfo = dir.fileName() + (dir.isDirectory() ? " [DIR]" : String(" (") + dir.fileSize() + "b)"); + DBG_OUTPUT_PORT.println(error + fileInfo); + if (error.length() > 0) { + unsupportedFiles += error + fileInfo + '\n'; + } + } + DBG_OUTPUT_PORT.println(); + + // Keep the "unsupportedFiles" variable to show it, but clean it up + unsupportedFiles.replace("\n", "
"); + unsupportedFiles = unsupportedFiles.substring(0, unsupportedFiles.length() - 5); +#endif + + //////////////////////////////// + // WI-FI INIT + DBG_OUTPUT_PORT.printf("Connecting to %s\n", ssid); + WiFi.mode(WIFI_STA); + WiFi.begin(ssid, password); + // Wait for connection + while (WiFi.status() != WL_CONNECTED) { + delay(500); + DBG_OUTPUT_PORT.print("."); + } + DBG_OUTPUT_PORT.println(""); + DBG_OUTPUT_PORT.print(F("Connected! IP address: ")); + DBG_OUTPUT_PORT.println(WiFi.localIP()); + + //////////////////////////////// + // MDNS INIT + if (MDNS.begin(host)) { + MDNS.addService("http", "tcp", 80); + DBG_OUTPUT_PORT.print(F("Open http://")); + DBG_OUTPUT_PORT.print(host); + DBG_OUTPUT_PORT.println(F(".local/edit to open the FileSystem Browser")); + } + + //////////////////////////////// + // WEB SERVER INIT + + // Filesystem status + server.on("/status", HTTP_GET, handleStatus); + + // List directory + server.on("/list", HTTP_GET, handleFileList); + + // Load editor + server.on("/edit", HTTP_GET, handleGetEdit); + + // Create file + server.on("/edit", HTTP_PUT, handleFileCreate); + + // Delete file + server.on("/edit", HTTP_DELETE, handleFileDelete); + + // Upload file + // - first callback is called after the request has ended with all parsed arguments + // - second callback handles file upload at that location + server.on("/edit", HTTP_POST, replyOK, handleFileUpload); + + // Default handler for all URIs not defined above + // Use it to read files from filesystem + server.onNotFound(handleNotFound); + + // Start server + server.begin(); + DBG_OUTPUT_PORT.println("HTTP server started"); +} + + +void loop(void) { + server.handleClient(); + MDNS.update(); +} diff --git a/libraries/WebServer/examples/FSBrowser/data/dir1/file1.txt b/libraries/WebServer/examples/FSBrowser/data/dir1/file1.txt new file mode 100644 index 000000000..454174c77 --- /dev/null +++ b/libraries/WebServer/examples/FSBrowser/data/dir1/file1.txt @@ -0,0 +1 @@ +I am in a subdir diff --git a/libraries/WebServer/examples/FSBrowser/data/edit/index.htm b/libraries/WebServer/examples/FSBrowser/data/edit/index.htm new file mode 100644 index 000000000..f0ad56288 --- /dev/null +++ b/libraries/WebServer/examples/FSBrowser/data/edit/index.htm @@ -0,0 +1,1128 @@ + + + + + File manager + + + + + + + +
+
+ +

Loading...
+ + + diff --git a/libraries/WebServer/examples/FSBrowser/data/favicon.ico b/libraries/WebServer/examples/FSBrowser/data/favicon.ico new file mode 100644 index 000000000..71b25fe6e Binary files /dev/null and b/libraries/WebServer/examples/FSBrowser/data/favicon.ico differ diff --git a/libraries/WebServer/examples/FSBrowser/data/index.htm b/libraries/WebServer/examples/FSBrowser/data/index.htm new file mode 100644 index 000000000..254188ca5 --- /dev/null +++ b/libraries/WebServer/examples/FSBrowser/data/index.htm @@ -0,0 +1,22 @@ + + + + + Pico Index + + + + +

ESP8266 Pin Functions

+ + + diff --git a/libraries/WebServer/examples/FSBrowser/data/pins.png b/libraries/WebServer/examples/FSBrowser/data/pins.png new file mode 100644 index 000000000..f988bf45e Binary files /dev/null and b/libraries/WebServer/examples/FSBrowser/data/pins.png differ diff --git a/libraries/WebServer/examples/FSBrowser/extras/feathericons.png b/libraries/WebServer/examples/FSBrowser/extras/feathericons.png new file mode 100644 index 000000000..5bb2cf63d Binary files /dev/null and b/libraries/WebServer/examples/FSBrowser/extras/feathericons.png differ diff --git a/libraries/WebServer/examples/FSBrowser/extras/index.htm.gz b/libraries/WebServer/examples/FSBrowser/extras/index.htm.gz new file mode 100644 index 000000000..34797b058 Binary files /dev/null and b/libraries/WebServer/examples/FSBrowser/extras/index.htm.gz differ diff --git a/libraries/WebServer/examples/FSBrowser/extras/index_htm.h b/libraries/WebServer/examples/FSBrowser/extras/index_htm.h new file mode 100644 index 000000000..03830fe38 --- /dev/null +++ b/libraries/WebServer/examples/FSBrowser/extras/index_htm.h @@ -0,0 +1,529 @@ +// WARNING: Auto-generated file. Please do not modify by hand. +// This file is an embeddable version of the gzipped index.htm file. +// To update it, please rerun the `reduce_index.sh` script located in the `extras` subfolder +// then recompile the sketch after each change to the `index.html` file. +unsigned char index_htm_gz[] = { + 0x1f, 0x8b, 0x08, 0x08, 0x96, 0xc9, 0xa8, 0x5e, 0x00, 0x03, 0x69, 0x6e, + 0x64, 0x65, 0x78, 0x2e, 0x68, 0x74, 0x6d, 0x00, 0xdc, 0x3b, 0x89, 0x7b, + 0xda, 0xb8, 0x97, 0xff, 0x8a, 0xe3, 0xee, 0x24, 0xf6, 0x02, 0x06, 0x92, + 0xe6, 0x28, 0xc4, 0xc9, 0xe4, 0x4e, 0x9a, 0xb3, 0xb9, 0xd3, 0x6e, 0xf7, + 0xfb, 0x04, 0x16, 0xa0, 0xc4, 0xd8, 0xae, 0x2d, 0x07, 0x48, 0xca, 0xfe, + 0xed, 0xfb, 0x9e, 0xe4, 0x13, 0x4c, 0x32, 0xdd, 0x9d, 0xf9, 0xcd, 0xec, + 0xb6, 0xf3, 0x15, 0x5b, 0x96, 0x9e, 0xde, 0x7d, 0x49, 0xb3, 0x3e, 0xb7, + 0x7b, 0xbe, 0x73, 0xfd, 0x70, 0xb1, 0xa7, 0xf4, 0x78, 0xdf, 0x56, 0x2e, + 0x6e, 0xb6, 0x4f, 0x8e, 0x76, 0x14, 0xb5, 0x52, 0xad, 0xde, 0x2d, 0xed, + 0x54, 0xab, 0xbb, 0xd7, 0xbb, 0xca, 0xfd, 0xe1, 0xf5, 0xe9, 0x89, 0x52, + 0x37, 0x6a, 0xca, 0xb5, 0x4f, 0x9c, 0x80, 0x71, 0xe6, 0x3a, 0xc4, 0xae, + 0x56, 0xf7, 0xce, 0x54, 0x45, 0xed, 0x71, 0xee, 0x35, 0xaa, 0xd5, 0xc1, + 0x60, 0x60, 0x0c, 0x96, 0x0c, 0xd7, 0xef, 0x56, 0xaf, 0x2f, 0xab, 0x43, + 0x84, 0x55, 0xc7, 0xc5, 0xd1, 0x63, 0x85, 0x67, 0x56, 0x1a, 0x16, 0xb7, + 0xd4, 0x8d, 0x75, 0xb1, 0x9f, 0x4d, 0x9c, 0xae, 0x49, 0x9d, 0x8d, 0x75, + 0xce, 0xb8, 0x4d, 0x37, 0xf6, 0x99, 0x4d, 0x95, 0x3e, 0x71, 0x48, 0x97, + 0xfa, 0xeb, 0x55, 0x39, 0xb6, 0x1e, 0xf0, 0x11, 0x8e, 0x52, 0x8b, 0x11, + 0x33, 0x68, 0xfb, 0x14, 0xa6, 0xb7, 0x5c, 0x6b, 0xf4, 0xda, 0x71, 0x1d, + 0x5e, 0x09, 0xd8, 0x0b, 0x6d, 0xd4, 0x17, 0xbd, 0x61, 0x53, 0xbc, 0x76, + 0x48, 0x9f, 0xd9, 0xa3, 0xc6, 0x2d, 0xf5, 0x2d, 0x80, 0x52, 0xde, 0xf2, + 0x19, 0xb1, 0xcb, 0x57, 0xb0, 0x77, 0x25, 0xa0, 0x3e, 0xeb, 0x8c, 0x8d, + 0x36, 0xcc, 0xa2, 0x43, 0x7e, 0x4a, 0x9d, 0xf0, 0xf5, 0xa5, 0xc2, 0x1c, + 0x8b, 0x0e, 0x1b, 0x4b, 0xb5, 0x5a, 0xd3, 0x73, 0x25, 0x7a, 0x0d, 0xd2, + 0x0a, 0x5c, 0x3b, 0xe4, 0xb4, 0x69, 0xd3, 0x0e, 0x6f, 0x2c, 0x03, 0xe0, + 0x96, 0xeb, 0x5b, 0xd4, 0x6f, 0xd4, 0xbd, 0xa1, 0x02, 0x9f, 0x98, 0xa5, + 0x7c, 0xf8, 0xf8, 0xf1, 0x63, 0xb3, 0x45, 0xda, 0x4f, 0x5d, 0xdf, 0x0d, + 0x1d, 0xab, 0xd2, 0x76, 0x6d, 0xd7, 0x6f, 0x7c, 0xe8, 0x2c, 0xe3, 0xdf, + 0xa6, 0xc5, 0x02, 0xcf, 0x26, 0xa3, 0x86, 0xe3, 0x3a, 0x14, 0xd6, 0x0e, + 0x2b, 0x41, 0x8f, 0x58, 0xee, 0xa0, 0x51, 0x53, 0x6a, 0x4a, 0xbd, 0x06, + 0x40, 0xfc, 0x6e, 0x8b, 0x68, 0xb5, 0x32, 0xfe, 0x35, 0x3e, 0xea, 0xcd, + 0x0c, 0x19, 0xf5, 0x98, 0x8c, 0x01, 0x65, 0xdd, 0x1e, 0x6f, 0xac, 0xd6, + 0x6a, 0x39, 0x8c, 0x95, 0xd0, 0x7e, 0xb5, 0x59, 0x00, 0xd3, 0x91, 0x25, + 0x72, 0x07, 0xee, 0x7a, 0x8d, 0x9a, 0x44, 0xb6, 0xd6, 0xec, 0x13, 0xbf, + 0xcb, 0x1c, 0x78, 0xf0, 0x88, 0x65, 0x31, 0xa7, 0xdb, 0x98, 0x58, 0x6f, + 0xb3, 0xd7, 0x84, 0x50, 0x9f, 0xda, 0x84, 0xb3, 0x67, 0xda, 0xec, 0x33, + 0xa7, 0x32, 0x60, 0x16, 0xef, 0x35, 0x56, 0x00, 0xbd, 0x66, 0x3b, 0xf4, + 0x03, 0x20, 0xc7, 0x73, 0x19, 0xac, 0xf3, 0xf3, 0xeb, 0x03, 0x8f, 0x38, + 0xaf, 0x11, 0xb9, 0xc8, 0x84, 0x98, 0x56, 0xe6, 0xd8, 0xcc, 0xa1, 0x95, + 0x96, 0xed, 0xb6, 0x9f, 0x92, 0xbd, 0x57, 0xbc, 0xe1, 0xe4, 0xee, 0x8d, + 0x9e, 0xfb, 0x4c, 0xfd, 0xd7, 0x94, 0x77, 0x02, 0x4c, 0xf1, 0xac, 0xdc, + 0x66, 0x94, 0x52, 0x98, 0x15, 0x04, 0xa0, 0x48, 0x94, 0x3e, 0x33, 0x3a, + 0x80, 0x69, 0xe5, 0xfc, 0x00, 0xf0, 0x26, 0xa1, 0x3a, 0x65, 0xc4, 0x04, + 0xbb, 0x26, 0x80, 0x30, 0xc7, 0x0b, 0xf9, 0xeb, 0xb4, 0xec, 0x5d, 0x8f, + 0xb4, 0x19, 0x1f, 0x09, 0xf6, 0x65, 0xe6, 0xbf, 0x4e, 0xc8, 0xaa, 0xd2, + 0x77, 0x5f, 0x2a, 0x21, 0x68, 0x16, 0x68, 0x97, 0x4d, 0xdb, 0x5c, 0x4a, + 0x04, 0xa4, 0xd7, 0x7a, 0x62, 0x7c, 0xfa, 0xc3, 0xe4, 0xc0, 0x04, 0x32, + 0x59, 0x7a, 0x6b, 0xb5, 0xce, 0xb4, 0x20, 0x26, 0x27, 0x47, 0xdc, 0x44, + 0xce, 0x55, 0x2c, 0xda, 0x76, 0x7d, 0x22, 0xa8, 0x00, 0xb6, 0x52, 0x1f, + 0xe5, 0x51, 0x44, 0x6c, 0xc9, 0x26, 0x2d, 0x6a, 0x97, 0x80, 0x59, 0x31, + 0x8b, 0x14, 0xfc, 0xbb, 0xb8, 0x28, 0x84, 0x35, 0x35, 0xfd, 0xbf, 0x60, + 0x62, 0x56, 0xa1, 0x27, 0x85, 0x80, 0xc0, 0xca, 0x05, 0x63, 0x8d, 0x46, + 0x8b, 0x76, 0x5c, 0x9f, 0xbe, 0xbe, 0x49, 0x84, 0xd8, 0xa2, 0x01, 0xf0, + 0x49, 0xcb, 0xa6, 0x96, 0x44, 0x2d, 0x5e, 0x61, 0xd1, 0x0e, 0x09, 0x6d, + 0x9e, 0x88, 0xc2, 0x58, 0x29, 0x5c, 0xdc, 0xee, 0xd1, 0xf6, 0x13, 0xb5, + 0x00, 0x39, 0xae, 0x25, 0x90, 0xf4, 0x2c, 0xda, 0x42, 0x29, 0x7f, 0x15, + 0xef, 0x72, 0x81, 0x68, 0x32, 0x5a, 0x1b, 0xfa, 0xb6, 0x66, 0x11, 0x4e, + 0x1a, 0xac, 0x0f, 0xae, 0xaa, 0xea, 0x39, 0x5d, 0xf0, 0x07, 0x01, 0x5d, + 0xf9, 0x58, 0x66, 0xb7, 0xdb, 0xe7, 0x97, 0x83, 0xda, 0xf1, 0x41, 0xd7, + 0xdd, 0x82, 0x3f, 0x67, 0x57, 0x37, 0xbd, 0xbd, 0x9b, 0x2e, 0x3c, 0x6d, + 0xe3, 0xeb, 0x4e, 0x77, 0x67, 0xeb, 0x14, 0x1f, 0x46, 0xcb, 0xc3, 0x41, + 0x1f, 0x1f, 0x5a, 0xf5, 0xed, 0xd3, 0xdb, 0xbd, 0xdb, 0xc3, 0xf6, 0xde, + 0xe8, 0xae, 0xbf, 0xbc, 0x7c, 0x77, 0xb7, 0xb8, 0xb7, 0xf2, 0xe5, 0xc6, + 0xda, 0xfa, 0xb2, 0xb7, 0xcd, 0xc8, 0x41, 0xfd, 0x91, 0x1c, 0xac, 0x56, + 0xab, 0xd5, 0xb5, 0xe7, 0xb3, 0xc7, 0xa5, 0xe3, 0x97, 0xd3, 0xd5, 0x9d, + 0xe1, 0x69, 0xab, 0xbf, 0x1c, 0x76, 0x4e, 0x5f, 0xda, 0xd5, 0x87, 0x45, + 0xeb, 0xc7, 0x90, 0x9f, 0x90, 0x03, 0xe6, 0x2e, 0xaf, 0x75, 0x1f, 0xee, + 0x3e, 0x3f, 0x7e, 0xdd, 0xbf, 0xbc, 0xdd, 0xff, 0xfa, 0xf9, 0x7a, 0xaf, + 0x7a, 0xf2, 0xd2, 0x2e, 0x3d, 0x07, 0xad, 0x33, 0xeb, 0xfe, 0x76, 0xf5, + 0x63, 0xe9, 0xa2, 0xf7, 0x6c, 0x1d, 0xda, 0x41, 0xeb, 0x6e, 0xf1, 0xc9, + 0x5b, 0xf9, 0xb1, 0xfa, 0x7c, 0xf2, 0x32, 0x5a, 0x7b, 0x3e, 0x0d, 0xcf, + 0xae, 0x5f, 0x3a, 0x4b, 0x9f, 0x4a, 0x3d, 0x77, 0xe5, 0x66, 0x74, 0x7e, + 0xb3, 0xb3, 0xdf, 0x7b, 0xb8, 0xbb, 0xb1, 0x97, 0x9d, 0xe7, 0xd5, 0x52, + 0xd5, 0x5b, 0xa1, 0x4f, 0x5f, 0x58, 0xf5, 0xe0, 0x12, 0x71, 0xdc, 0xba, + 0xbf, 0xbc, 0xba, 0xb6, 0x4f, 0xb7, 0xbe, 0x9c, 0xb7, 0x1e, 0xbe, 0x22, + 0x2d, 0x57, 0x97, 0x9f, 0x2f, 0xf7, 0xf6, 0x6f, 0xae, 0x4e, 0x3b, 0xfc, + 0xe9, 0x13, 0x1f, 0x0d, 0xd8, 0xd6, 0x97, 0x9e, 0x7b, 0xb3, 0xd5, 0xbb, + 0xdd, 0x1a, 0x7c, 0xf6, 0x7e, 0xec, 0x5e, 0xfe, 0xe8, 0x90, 0xe7, 0xe7, + 0xb5, 0x17, 0x3b, 0x3c, 0x3b, 0x7e, 0x0a, 0xfd, 0xbd, 0x47, 0xff, 0x61, + 0xa9, 0x44, 0x57, 0x3f, 0x7e, 0x66, 0x2f, 0x27, 0xce, 0xe2, 0x5d, 0xbd, + 0xcf, 0xb6, 0x8e, 0x87, 0x5e, 0xef, 0x7c, 0xfb, 0x94, 0xde, 0x3c, 0xfc, + 0x58, 0x09, 0x0f, 0xab, 0x5b, 0x4b, 0x5b, 0x2b, 0x2b, 0x0f, 0xde, 0xe5, + 0xf6, 0xe5, 0x8f, 0xcf, 0x5f, 0xc9, 0xe9, 0xd1, 0x1a, 0x1b, 0x04, 0xb7, + 0xd5, 0x1d, 0xeb, 0x74, 0x65, 0x6b, 0x71, 0xf8, 0xb8, 0xec, 0x1c, 0xdd, + 0x04, 0xc7, 0xb5, 0x2a, 0xbb, 0xbe, 0xb9, 0xf0, 0x0f, 0xce, 0xfa, 0xb5, + 0xd3, 0x9b, 0xdd, 0xa3, 0x27, 0x7a, 0x50, 0xfd, 0xbc, 0xfc, 0x31, 0x3c, + 0x67, 0x4f, 0x41, 0xeb, 0x53, 0xef, 0xbe, 0xb7, 0xbc, 0x7c, 0xd1, 0x3b, + 0x3a, 0x7a, 0xec, 0x1c, 0x77, 0xad, 0xcf, 0xd7, 0x87, 0x57, 0x7b, 0xa3, + 0xc5, 0xea, 0xfe, 0x6e, 0x6d, 0xe5, 0xbe, 0xef, 0x5a, 0x6b, 0x67, 0xe7, + 0x03, 0xdf, 0x1f, 0xec, 0xdf, 0x04, 0x5f, 0xfa, 0xf7, 0x5f, 0x0f, 0xbf, + 0xf6, 0x7a, 0xf4, 0xe9, 0x70, 0x9b, 0x6d, 0x8f, 0x1e, 0x8e, 0x5c, 0x72, + 0xf4, 0x79, 0xeb, 0xf1, 0x62, 0xed, 0xe6, 0xea, 0x8e, 0xed, 0x6c, 0xad, + 0x1d, 0xf7, 0xf6, 0xee, 0xd6, 0x6e, 0x0e, 0xae, 0x57, 0x8f, 0x2f, 0xc8, + 0xd7, 0xbd, 0x61, 0x70, 0xde, 0x3a, 0x1c, 0xf9, 0x37, 0xdd, 0xeb, 0xa7, + 0xc7, 0xeb, 0x97, 0x35, 0x9b, 0x5d, 0xdc, 0x0f, 0x5e, 0x06, 0x7b, 0xdb, + 0xa5, 0xf3, 0x8b, 0xfd, 0xdb, 0xe1, 0xe1, 0xde, 0xda, 0xfd, 0x62, 0xfb, + 0xe9, 0x72, 0x7b, 0x74, 0x42, 0x6e, 0x47, 0xbd, 0xdb, 0xe3, 0xe1, 0xc5, + 0xe2, 0xea, 0xf1, 0x59, 0xc9, 0xd9, 0xe2, 0x87, 0xab, 0x97, 0xcf, 0xa1, + 0xbf, 0xb8, 0xeb, 0xaf, 0x2c, 0xd6, 0x39, 0x7d, 0x3a, 0xa5, 0x41, 0xe9, + 0x8e, 0x1d, 0xac, 0xad, 0x1c, 0xfa, 0x2b, 0x8f, 0xc7, 0x0f, 0x8f, 0xa5, + 0xd5, 0x2f, 0xf5, 0x63, 0xab, 0x76, 0xe1, 0x0d, 0x8f, 0x96, 0xd7, 0xce, + 0x82, 0x2f, 0xd6, 0x59, 0x75, 0x71, 0xf9, 0xc5, 0xfe, 0xb2, 0xfb, 0xc5, + 0x3a, 0x6e, 0x7d, 0xda, 0x72, 0x4e, 0x57, 0x3a, 0x87, 0x57, 0x07, 0x4f, + 0x17, 0xc1, 0x17, 0xf2, 0x99, 0xf4, 0x8f, 0xbc, 0x2f, 0x2f, 0x3b, 0xfe, + 0x68, 0xd0, 0xdb, 0xad, 0xb3, 0xeb, 0xc5, 0xfb, 0xa7, 0xe0, 0x64, 0x67, + 0x10, 0x54, 0x8f, 0xbe, 0x3e, 0xaf, 0x7d, 0x75, 0x3b, 0xab, 0x7c, 0x71, + 0xf9, 0xc1, 0x7e, 0x12, 0x62, 0xba, 0xba, 0xb9, 0x3d, 0xbf, 0x3c, 0x5e, + 0xde, 0x79, 0x38, 0x3a, 0x32, 0x75, 0xc5, 0x71, 0x2b, 0x3e, 0xf5, 0x28, + 0xe1, 0x7f, 0x82, 0xee, 0x17, 0x0c, 0x25, 0x16, 0x5e, 0x18, 0x03, 0x7a, + 0x32, 0x80, 0xd5, 0x21, 0x06, 0x34, 0xc5, 0x70, 0x76, 0x00, 0x9c, 0x16, + 0x67, 0x6d, 0x62, 0x57, 0x88, 0xcd, 0xba, 0x4e, 0xa3, 0xcf, 0x2c, 0xcb, + 0x2e, 0xf4, 0x2c, 0x19, 0x93, 0xab, 0x24, 0x4e, 0xba, 0xbe, 0x06, 0x31, + 0xb4, 0x56, 0xe4, 0x3b, 0x67, 0xce, 0xae, 0x7c, 0x5c, 0x9b, 0x72, 0x6f, + 0xb8, 0xc2, 0xe0, 0x43, 0xfe, 0xc6, 0xaa, 0x95, 0x8f, 0xc5, 0xab, 0x58, + 0xbf, 0xfb, 0xc6, 0xaa, 0xb5, 0xda, 0xd4, 0xaa, 0x09, 0x97, 0x88, 0xc1, + 0xce, 0xe1, 0x0d, 0x55, 0x6d, 0xca, 0xb0, 0x2b, 0x98, 0x92, 0xb8, 0x63, + 0x74, 0xc5, 0xe8, 0x93, 0x8b, 0xd9, 0xd4, 0x2c, 0xda, 0xb8, 0xa6, 0x54, + 0x96, 0xa6, 0x1d, 0x78, 0x4e, 0x4a, 0x7f, 0x70, 0xd3, 0xb7, 0x7c, 0x6c, + 0x29, 0x4f, 0xc6, 0x0c, 0x44, 0x10, 0xee, 0xf8, 0x77, 0x91, 0xad, 0x29, + 0x32, 0x5b, 0x53, 0x88, 0x63, 0x29, 0x5a, 0x1c, 0x15, 0x31, 0xdb, 0xb0, + 0x00, 0x7a, 0x9b, 0x56, 0x3c, 0x36, 0xa4, 0x76, 0x45, 0x44, 0xad, 0x46, + 0x4d, 0x7f, 0xcd, 0x87, 0xda, 0x78, 0x3e, 0x71, 0xc0, 0xc7, 0x0a, 0xe0, + 0xf1, 0x80, 0xf5, 0x48, 0xda, 0x40, 0x4a, 0x05, 0x02, 0x69, 0x1f, 0x7f, + 0x65, 0x44, 0x75, 0xfd, 0x4a, 0x2b, 0xec, 0x76, 0xd8, 0x10, 0x90, 0xee, + 0x30, 0x87, 0x71, 0xaa, 0xd4, 0x83, 0xf1, 0xef, 0x31, 0x98, 0x27, 0x3a, + 0xea, 0xf8, 0xa4, 0x4f, 0x03, 0xe5, 0x0f, 0x82, 0x79, 0xed, 0xf8, 0x6e, + 0x3f, 0xcd, 0x28, 0xc6, 0xdc, 0xcd, 0xbc, 0x8c, 0xc7, 0x1f, 0x7a, 0x94, + 0x40, 0x98, 0x2d, 0xc8, 0x1d, 0x64, 0x42, 0xe6, 0x0b, 0x75, 0x4f, 0x12, + 0xb3, 0x48, 0xfd, 0x17, 0x41, 0xa3, 0x92, 0xfc, 0x08, 0x13, 0xca, 0xba, + 0x60, 0x3b, 0xa6, 0x85, 0x05, 0x09, 0x25, 0x66, 0x58, 0x99, 0xfc, 0xe7, + 0x03, 0xf2, 0x66, 0xc6, 0x86, 0x8b, 0x32, 0x51, 0xe5, 0xdc, 0xed, 0xa7, + 0x9b, 0x4a, 0x41, 0x2f, 0xd6, 0x7e, 0x4b, 0xb6, 0x44, 0x33, 0xf8, 0x00, + 0xa2, 0x01, 0x32, 0xcb, 0x1f, 0x3c, 0x5f, 0x72, 0xfa, 0x0d, 0x88, 0x31, + 0x15, 0x79, 0xc8, 0x00, 0x71, 0x9c, 0xac, 0x9e, 0x46, 0x1b, 0x70, 0x4d, + 0x36, 0x5c, 0xc6, 0x0d, 0x03, 0x4e, 0x78, 0x18, 0xcc, 0xd8, 0x67, 0x29, + 0xd9, 0x46, 0x70, 0x21, 0x93, 0x61, 0x89, 0xb5, 0x9d, 0xe0, 0x94, 0x42, + 0xe2, 0xf0, 0x1a, 0x29, 0x6d, 0xad, 0x96, 0x32, 0xb0, 0x12, 0x61, 0x85, + 0x9a, 0xff, 0x61, 0x40, 0x7c, 0x07, 0xc6, 0x5e, 0x63, 0x3f, 0x53, 0x03, + 0xaa, 0xa7, 0x50, 0x83, 0x0c, 0xc9, 0xe9, 0xd2, 0x66, 0x92, 0x63, 0x81, + 0xba, 0x73, 0xd7, 0xb5, 0x39, 0xf3, 0x0a, 0x90, 0x8b, 0xab, 0x83, 0xc5, + 0x84, 0x0b, 0x82, 0x2d, 0x88, 0xc0, 0x33, 0x0b, 0x58, 0x8b, 0xd9, 0x98, + 0x96, 0xf4, 0xc0, 0x2a, 0xa9, 0x53, 0x54, 0x0d, 0x74, 0x3a, 0x99, 0x8d, + 0x9a, 0x22, 0x49, 0x93, 0x86, 0x8c, 0x5a, 0x47, 0xfd, 0x82, 0xb2, 0x02, + 0xe7, 0xc5, 0x8c, 0x5b, 0xca, 0xf3, 0xa2, 0x96, 0xa1, 0x31, 0x4a, 0x8f, + 0x13, 0xd4, 0x33, 0xd8, 0x88, 0x47, 0xf0, 0xa5, 0x1f, 0x6c, 0x97, 0x20, + 0x98, 0x19, 0x3c, 0xaf, 0x00, 0x7b, 0x9e, 0x7b, 0x79, 0x35, 0xc1, 0xa1, + 0x41, 0x33, 0x65, 0x1f, 0x7c, 0x8f, 0x39, 0x00, 0x6f, 0xd3, 0x04, 0x66, + 0xab, 0x98, 0x65, 0x3d, 0xcd, 0x98, 0x9b, 0x69, 0xa9, 0xd7, 0x88, 0x06, + 0x15, 0x63, 0x39, 0x50, 0x28, 0xe4, 0x47, 0x00, 0xaf, 0xe2, 0x86, 0x3c, + 0x41, 0xcf, 0x08, 0x7a, 0xee, 0xc0, 0x79, 0x95, 0x16, 0x13, 0x43, 0xa8, + 0x27, 0x9f, 0x2b, 0xfd, 0xa0, 0x5b, 0x1c, 0x5e, 0x66, 0x59, 0x9d, 0xac, + 0xd9, 0x40, 0xf4, 0x02, 0x09, 0x70, 0x53, 0xfd, 0x86, 0x78, 0x82, 0x4a, + 0x87, 0xde, 0x6b, 0x15, 0xf8, 0xa2, 0x37, 0x33, 0xf2, 0x49, 0x19, 0x2c, + 0xdc, 0xe7, 0xef, 0xa9, 0x93, 0x08, 0x3c, 0xe6, 0x38, 0x90, 0xad, 0xa3, + 0xf7, 0x79, 0xad, 0xfd, 0xf6, 0x9a, 0xc2, 0xf3, 0x5d, 0xd0, 0x66, 0xaa, + 0xd5, 0xf4, 0x31, 0xea, 0xd8, 0xf4, 0x87, 0xa5, 0x95, 0x9a, 0x45, 0xbb, + 0xfa, 0x78, 0x6c, 0x64, 0x61, 0xc8, 0xfc, 0xd4, 0xa7, 0x3f, 0x42, 0xe6, + 0x43, 0x7e, 0xfa, 0x0e, 0x55, 0x49, 0x69, 0x86, 0x54, 0x21, 0x39, 0x6f, + 0xd1, 0x25, 0xc8, 0x2a, 0x4b, 0xda, 0x52, 0x67, 0x99, 0xdd, 0x1c, 0x1c, + 0x61, 0xea, 0x14, 0x71, 0x3f, 0x92, 0x6a, 0xdf, 0x4a, 0xaa, 0x7e, 0x68, + 0xb7, 0x72, 0xb8, 0x22, 0x34, 0x3e, 0x12, 0xb4, 0xd8, 0xc8, 0x23, 0x3e, + 0x68, 0x6d, 0xf2, 0x19, 0xc4, 0x13, 0x06, 0x82, 0x69, 0xb2, 0xc2, 0x65, + 0x2f, 0xa8, 0x97, 0xd1, 0x57, 0x18, 0x69, 0xa2, 0x86, 0x76, 0x6c, 0xa8, + 0x7a, 0x23, 0xfb, 0x10, 0xea, 0x8f, 0xda, 0x04, 0x21, 0xa8, 0xf2, 0x09, + 0xfe, 0xc0, 0xca, 0xa8, 0xe6, 0x44, 0x97, 0x18, 0xa9, 0x9d, 0x08, 0xb8, + 0xeb, 0x55, 0x51, 0xae, 0x41, 0xdd, 0xdf, 0xf6, 0x99, 0xc7, 0x37, 0x9e, + 0x89, 0xaf, 0xa0, 0xe7, 0x2b, 0x77, 0x82, 0x23, 0xa7, 0xe3, 0x36, 0x3b, + 0xa1, 0xd3, 0x46, 0x12, 0x95, 0x80, 0xf2, 0x13, 0xa9, 0x28, 0x1a, 0x2d, + 0x73, 0xfd, 0x95, 0xcf, 0xcf, 0x43, 0x94, 0x03, 0x62, 0xa8, 0x61, 0xbb, + 0x5d, 0x8d, 0xeb, 0x65, 0xcb, 0x6d, 0x87, 0xe8, 0xdb, 0x8d, 0x2e, 0xe5, + 0x7b, 0xd2, 0xcd, 0x6f, 0x8f, 0x8e, 0x2c, 0x4d, 0xcd, 0x28, 0x98, 0xaa, + 0x1b, 0x82, 0x53, 0xd8, 0xe4, 0x30, 0xf9, 0xcf, 0x9f, 0xaa, 0x5a, 0xa6, + 0x9b, 0xef, 0x2d, 0x84, 0x45, 0x6d, 0x9b, 0x04, 0xc1, 0x09, 0x54, 0x97, + 0x06, 0x58, 0xac, 0xa6, 0x0a, 0x4d, 0x56, 0xf5, 0xc6, 0x2f, 0xad, 0xf4, + 0x69, 0x1f, 0x18, 0x95, 0x2c, 0x4e, 0xf1, 0xc5, 0xfe, 0x86, 0x21, 0xd8, + 0x60, 0xc8, 0x72, 0xc8, 0xa4, 0x9b, 0xea, 0x80, 0x30, 0xae, 0x36, 0xd4, + 0xa8, 0x30, 0x52, 0xc7, 0x09, 0x23, 0x7c, 0x08, 0x45, 0x58, 0xf7, 0x5c, + 0x81, 0x26, 0x6b, 0x54, 0x7f, 0x65, 0x1d, 0x8d, 0xae, 0xd7, 0x6b, 0x8b, + 0x1f, 0x75, 0x9f, 0xf2, 0xd0, 0x77, 0x14, 0x5a, 0x52, 0x95, 0x6d, 0x15, + 0xd4, 0xdd, 0xd7, 0x04, 0x37, 0xcd, 0x4a, 0xbd, 0xc9, 0x4b, 0xa5, 0x32, + 0xce, 0x59, 0xd7, 0x68, 0xd5, 0x14, 0x93, 0x9b, 0x7a, 0x33, 0x9e, 0x0f, + 0xbe, 0x65, 0x1f, 0x82, 0xb3, 0xa5, 0x2d, 0xea, 0xa5, 0x6f, 0xaa, 0x72, + 0xcc, 0xb6, 0xd5, 0xb2, 0xaa, 0x9c, 0xca, 0x9f, 0x03, 0xf9, 0x73, 0x2d, + 0x7e, 0x2e, 0xe0, 0xdf, 0xef, 0xdf, 0xf8, 0xf7, 0x2c, 0x36, 0x1d, 0x9f, + 0x06, 0xbd, 0x2b, 0xe1, 0xf4, 0x35, 0x50, 0xf5, 0x59, 0x1c, 0x91, 0x61, + 0x21, 0xc7, 0x7f, 0x55, 0x8b, 0x56, 0xa3, 0x73, 0x30, 0x0c, 0x5d, 0x6d, + 0x22, 0xbe, 0xae, 0xe9, 0x40, 0x2e, 0x72, 0x7f, 0x7a, 0x72, 0xc8, 0xb9, + 0x77, 0x09, 0x36, 0x44, 0x03, 0xa8, 0x0b, 0x0d, 0xd7, 0x41, 0x9e, 0x9a, + 0xf1, 0xc6, 0x9a, 0x20, 0x7c, 0xb1, 0x56, 0x9b, 0x33, 0x5d, 0x43, 0xc2, + 0xd6, 0x91, 0xb1, 0xb8, 0x68, 0xcf, 0xf7, 0x81, 0x76, 0x57, 0x6f, 0x52, + 0x3b, 0xa0, 0xaf, 0x08, 0x93, 0x9a, 0x9a, 0xd4, 0x27, 0xf3, 0xf3, 0xd5, + 0xf9, 0x99, 0x01, 0xfa, 0x1d, 0x50, 0xcd, 0x05, 0x89, 0x04, 0x1e, 0xe8, + 0x10, 0xbd, 0x06, 0x7d, 0xd5, 0x75, 0x83, 0x8f, 0x3c, 0xe4, 0x5d, 0x45, + 0x51, 0x9b, 0x00, 0x5b, 0x2e, 0x30, 0x58, 0x70, 0xfe, 0xa4, 0xbf, 0x4a, + 0x46, 0xd6, 0x4b, 0xa7, 0x84, 0xf7, 0x0c, 0xe1, 0x18, 0xb5, 0x4f, 0x9f, + 0xfe, 0x3d, 0x9a, 0x02, 0x95, 0xbe, 0xb5, 0x3d, 0xe2, 0x34, 0xa8, 0x46, + 0x03, 0x1c, 0x9c, 0x83, 0x2d, 0x46, 0xf4, 0xb2, 0x63, 0xe6, 0x04, 0x36, + 0x35, 0xa3, 0x32, 0x09, 0x44, 0x07, 0x14, 0x80, 0x2b, 0x54, 0x71, 0x3b, + 0x8a, 0x5a, 0x7a, 0x7b, 0x31, 0x90, 0x58, 0x32, 0xd5, 0xf5, 0x3e, 0x06, + 0x4d, 0x85, 0x59, 0xe6, 0x42, 0x14, 0x40, 0x17, 0x14, 0x48, 0xbc, 0xcc, + 0x85, 0xda, 0x82, 0xe2, 0x7a, 0x9c, 0xf5, 0xc3, 0x3e, 0x3e, 0x83, 0x81, + 0x9a, 0x0b, 0x9f, 0x60, 0xac, 0x07, 0xe6, 0x07, 0x4f, 0xcb, 0x30, 0x8b, + 0x0c, 0xcd, 0x05, 0xf0, 0x6c, 0x0b, 0xca, 0x33, 0xb1, 0x43, 0x6a, 0x2e, + 0xa8, 0x25, 0x5e, 0x52, 0x17, 0x14, 0xd1, 0x8b, 0xc3, 0x37, 0x07, 0xde, + 0x36, 0xc4, 0xcf, 0x7a, 0x55, 0xec, 0xb2, 0xa1, 0x96, 0x63, 0x84, 0x9d, + 0x20, 0xf4, 0x3c, 0xd7, 0xe7, 0xd4, 0xc2, 0x46, 0x5e, 0x30, 0x3f, 0xaf, + 0x21, 0x32, 0xca, 0x3a, 0x66, 0xa2, 0x02, 0x99, 0x28, 0x82, 0x2d, 0x6c, + 0xdc, 0x6d, 0x5d, 0x9e, 0x1d, 0x9d, 0x1d, 0xc8, 0x2f, 0xc2, 0x20, 0xcc, + 0x85, 0x28, 0x9e, 0x2d, 0x88, 0x2e, 0x60, 0x30, 0x0a, 0x38, 0xed, 0xcf, + 0x3b, 0xad, 0xc0, 0x6b, 0x62, 0xee, 0x4a, 0x98, 0x13, 0xc8, 0xb7, 0xcc, + 0x2e, 0x72, 0xa0, 0x03, 0xd3, 0x1d, 0xf4, 0xda, 0x8d, 0xf5, 0x96, 0x5f, + 0x05, 0xdc, 0x66, 0xa0, 0x83, 0x18, 0xe3, 0x7e, 0x1b, 0xd1, 0x8f, 0xaa, + 0x8f, 0x51, 0x1d, 0x14, 0xc1, 0x30, 0x81, 0x88, 0xb0, 0x38, 0x73, 0x61, + 0x3a, 0xd6, 0x51, 0x2b, 0x0a, 0x1b, 0x83, 0x1e, 0xf8, 0xd0, 0x5c, 0x8f, + 0xae, 0xe5, 0xda, 0xd6, 0xc2, 0xc6, 0xd1, 0xd9, 0xd1, 0xb5, 0xb2, 0x77, + 0x79, 0x79, 0x7e, 0xa9, 0xcc, 0xc5, 0xe0, 0x9b, 0xbf, 0xa2, 0xf9, 0xb4, + 0xac, 0x5e, 0x5d, 0x1c, 0xed, 0xef, 0x5f, 0xa9, 0x73, 0x66, 0x2c, 0x54, + 0x50, 0x3e, 0x60, 0xe1, 0x4c, 0x28, 0xfd, 0x27, 0x8b, 0xf9, 0x00, 0x44, + 0xfa, 0x89, 0x28, 0xa2, 0x98, 0xaa, 0x0c, 0x29, 0x40, 0xdc, 0xb8, 0x0c, + 0x36, 0xe2, 0x51, 0x47, 0x53, 0x0f, 0xf6, 0xae, 0xc1, 0x54, 0xab, 0xd1, + 0xb6, 0xe5, 0xb9, 0x9a, 0x0e, 0x9f, 0x02, 0x0a, 0x2a, 0xeb, 0x84, 0xb6, + 0xad, 0xa7, 0xb6, 0x9b, 0xb7, 0x17, 0x70, 0x25, 0xc4, 0x86, 0x22, 0x44, + 0x53, 0x05, 0x65, 0x0d, 0xe5, 0x9b, 0x5a, 0xa2, 0x91, 0x69, 0x95, 0xd4, + 0xef, 0x0a, 0xbe, 0xe5, 0x0c, 0x26, 0x05, 0xd4, 0x26, 0x0e, 0xfa, 0xe6, + 0x33, 0x3a, 0xd8, 0x91, 0x85, 0x07, 0x7a, 0x02, 0xe9, 0x5d, 0xe6, 0xe6, + 0x66, 0xf3, 0x85, 0x3c, 0xd3, 0x6d, 0x0e, 0x9e, 0xd0, 0x88, 0x3b, 0x39, + 0x3f, 0x7f, 0xce, 0xcd, 0x81, 0xf8, 0x3b, 0xcc, 0xef, 0x6b, 0xea, 0x4e, + 0x0f, 0xd3, 0xb7, 0x40, 0xe1, 0xae, 0x32, 0x72, 0x43, 0x5f, 0x89, 0xe1, + 0x28, 0x03, 0x66, 0xdb, 0x4a, 0x0b, 0x62, 0x9b, 0x1b, 0x70, 0x85, 0x75, + 0xf0, 0xab, 0x82, 0x4a, 0xc3, 0x9c, 0x10, 0x18, 0x81, 0x6a, 0xe8, 0x08, + 0x8b, 0x01, 0xf0, 0xbb, 0x2c, 0x68, 0x13, 0xdf, 0x82, 0x5d, 0x02, 0x6d, + 0xae, 0xae, 0x23, 0x2f, 0x52, 0xac, 0x8b, 0xa7, 0xd1, 0xb7, 0x7c, 0xd8, + 0x14, 0xc6, 0xe6, 0x1c, 0x9d, 0x1d, 0x77, 0xac, 0x04, 0x6c, 0x7e, 0x45, + 0x8a, 0x02, 0xac, 0xb8, 0x10, 0xb1, 0x76, 0x1f, 0xf4, 0x8a, 0x0a, 0x19, + 0x24, 0x4e, 0x19, 0x38, 0xef, 0xf3, 0xe0, 0x8e, 0xf1, 0x9e, 0xa6, 0x56, + 0x55, 0xfd, 0xe7, 0x4f, 0x8d, 0x9a, 0xf0, 0x50, 0xa2, 0x7a, 0x99, 0x1a, + 0x20, 0xcd, 0xf4, 0x13, 0x92, 0x6c, 0xc2, 0x02, 0x1b, 0xca, 0x2c, 0x48, + 0xd2, 0x2a, 0x75, 0x1d, 0xa7, 0x04, 0x61, 0x2b, 0xe0, 0x3e, 0xc6, 0xcb, + 0x1a, 0xbc, 0x81, 0xd1, 0xf1, 0x23, 0xcc, 0xef, 0xce, 0x3b, 0x62, 0x4d, + 0x56, 0x7a, 0xe0, 0x63, 0x38, 0x3d, 0x14, 0x15, 0x0e, 0xc4, 0x56, 0x07, + 0xa3, 0xab, 0x74, 0xc4, 0xb3, 0x28, 0x03, 0x14, 0x48, 0xfa, 0x51, 0xae, + 0x8f, 0xbe, 0x6b, 0xaa, 0xa8, 0x22, 0x55, 0xc8, 0x4e, 0x84, 0x4a, 0x9b, + 0x2a, 0x1a, 0xac, 0x5a, 0x26, 0x46, 0x3f, 0x44, 0x7b, 0x07, 0x8b, 0x9b, + 0xab, 0xc3, 0x1b, 0x9a, 0xb0, 0xa9, 0x62, 0x57, 0x4d, 0x05, 0xed, 0x24, + 0x1e, 0x68, 0xae, 0xb5, 0xd3, 0x63, 0xb6, 0xa5, 0x11, 0x5d, 0x84, 0x01, + 0xeb, 0xdd, 0x0d, 0x2c, 0x03, 0x9c, 0x8c, 0xea, 0x81, 0x47, 0x3e, 0x12, + 0x23, 0x65, 0x2b, 0xda, 0x11, 0xd3, 0x0f, 0x7c, 0x93, 0x7b, 0xe0, 0x04, + 0x7c, 0x8b, 0x22, 0xe9, 0xad, 0x70, 0x74, 0xc0, 0x82, 0x89, 0x6d, 0x2d, + 0xb9, 0xad, 0x3d, 0x73, 0xdb, 0x56, 0x08, 0xf5, 0x07, 0x48, 0xb2, 0x69, + 0x67, 0x43, 0xd8, 0x8d, 0x87, 0x61, 0x69, 0x12, 0x98, 0x2d, 0x81, 0xb1, + 0xf7, 0x81, 0x31, 0x41, 0x84, 0x34, 0xee, 0x32, 0x9b, 0xb4, 0x6e, 0x6c, + 0xc2, 0xe2, 0x70, 0x66, 0xc3, 0xd3, 0xa7, 0x5d, 0x9c, 0x9a, 0xdf, 0x8f, + 0xc9, 0xfd, 0x82, 0xf7, 0xf7, 0x0b, 0xf2, 0xb0, 0xf6, 0x85, 0x70, 0xf2, + 0xc0, 0x02, 0x09, 0xac, 0x3d, 0x13, 0x18, 0x3a, 0x3c, 0x00, 0xd5, 0x16, + 0xa8, 0xcb, 0xfa, 0x72, 0x5b, 0xc0, 0x07, 0x6f, 0xd3, 0x2e, 0x26, 0x21, + 0xbf, 0x43, 0x5b, 0xee, 0xe0, 0xbf, 0x8f, 0xae, 0x2f, 0xf6, 0x88, 0xed, + 0xae, 0xec, 0x67, 0xb1, 0x47, 0xcb, 0xc5, 0x21, 0xb9, 0xa1, 0x6c, 0x6e, + 0x9c, 0x40, 0xea, 0x6c, 0xaa, 0x4b, 0x50, 0x40, 0xe1, 0x97, 0xd4, 0xe6, + 0x6a, 0x80, 0x58, 0x16, 0x03, 0x5f, 0x62, 0xd0, 0x7f, 0x1f, 0x83, 0xbe, + 0xc0, 0x20, 0x63, 0xca, 0xe5, 0x7e, 0x16, 0x89, 0xc8, 0x75, 0xe0, 0xe8, + 0xec, 0xdd, 0xfa, 0x72, 0xb7, 0xf0, 0xfd, 0xdd, 0x42, 0xb1, 0x5b, 0x8f, + 0xda, 0x9e, 0xd8, 0x2a, 0xcc, 0x6e, 0xb5, 0xa9, 0x4e, 0x80, 0x0d, 0x25, + 0x58, 0xef, 0x3d, 0x41, 0x79, 0x92, 0x89, 0x51, 0x3c, 0xf0, 0x72, 0x19, + 0x58, 0x94, 0xa8, 0xea, 0x93, 0x22, 0xf2, 0xc0, 0xc4, 0x21, 0xe7, 0x6a, + 0x0b, 0x27, 0x9c, 0x66, 0x5d, 0x32, 0xdf, 0x84, 0xa4, 0xcb, 0x24, 0x06, + 0x1a, 0x76, 0x60, 0x40, 0x34, 0xee, 0xf2, 0x5e, 0x9c, 0x21, 0x45, 0xa3, + 0xdf, 0x6a, 0xdf, 0x85, 0xf5, 0x35, 0x9f, 0x5d, 0xa8, 0x35, 0x6a, 0x60, + 0x7d, 0x22, 0xbf, 0x28, 0xf0, 0x69, 0xd1, 0x17, 0xe1, 0xd9, 0xa2, 0x67, + 0x3d, 0x9e, 0x6e, 0x4e, 0xba, 0xc7, 0x78, 0x42, 0x09, 0x67, 0x73, 0x08, + 0x79, 0x36, 0xa2, 0x08, 0x6e, 0xef, 0x29, 0x87, 0xe1, 0x34, 0x7a, 0xf3, + 0xf3, 0x8e, 0x81, 0x67, 0x97, 0xd2, 0x5a, 0xb5, 0x14, 0xcb, 0x78, 0x2b, + 0x7d, 0x5c, 0x0e, 0x0a, 0x61, 0x49, 0xb2, 0x62, 0xfc, 0xc1, 0x9f, 0xf6, + 0x35, 0xbd, 0xa9, 0xaa, 0xa6, 0x69, 0xf2, 0xcd, 0x28, 0x5c, 0x6e, 0x29, + 0x71, 0x4e, 0xa2, 0xf4, 0x43, 0x08, 0x49, 0x10, 0x9a, 0xba, 0x50, 0xce, + 0x61, 0x7d, 0xc0, 0xf3, 0x8e, 0x3a, 0x5e, 0xb1, 0x1f, 0xe7, 0x30, 0x72, + 0x01, 0x54, 0x8b, 0x10, 0x8c, 0x2c, 0x08, 0x6c, 0xbc, 0xa7, 0x10, 0x65, + 0xa1, 0xba, 0xa0, 0x00, 0xdf, 0x7d, 0xd2, 0x86, 0x7c, 0x0b, 0x80, 0x48, + 0xd4, 0x77, 0x84, 0x68, 0xa1, 0xce, 0x19, 0x83, 0x3f, 0xf8, 0x9f, 0x63, + 0x2a, 0x18, 0xa9, 0x14, 0x22, 0xab, 0x4d, 0x60, 0x0b, 0xd2, 0xe1, 0x25, + 0x14, 0x0c, 0x24, 0xb1, 0x79, 0x14, 0x00, 0x07, 0xbf, 0x10, 0x07, 0x6e, + 0xa0, 0xa9, 0x6a, 0xf0, 0xbd, 0x3f, 0xe3, 0x7b, 0x64, 0x48, 0x38, 0x25, + 0x9c, 0x05, 0x02, 0xd2, 0x92, 0xab, 0x1e, 0x64, 0x72, 0xed, 0x10, 0x13, + 0x89, 0xf1, 0x64, 0xa4, 0xba, 0x86, 0xe4, 0x18, 0xe2, 0x14, 0x93, 0x24, + 0x3b, 0x33, 0xa3, 0x94, 0x1a, 0x35, 0xad, 0x00, 0x7f, 0x3e, 0xd3, 0x44, + 0x2c, 0xf6, 0x0c, 0x16, 0x92, 0xa6, 0x44, 0x6f, 0xc6, 0xff, 0x34, 0xd6, + 0xe8, 0x91, 0x86, 0xbe, 0x11, 0xfd, 0xa5, 0x63, 0x9c, 0xce, 0xd8, 0xa4, + 0x43, 0x7c, 0x67, 0x59, 0xec, 0x4f, 0x67, 0xac, 0x76, 0x26, 0x87, 0x45, + 0x4b, 0x01, 0xc7, 0x33, 0xb6, 0xbd, 0xce, 0xfa, 0x5d, 0x25, 0xf0, 0xdb, + 0x98, 0xc7, 0x53, 0xcc, 0xea, 0xa3, 0x84, 0x17, 0x92, 0xfe, 0x4a, 0xd2, + 0x05, 0xfa, 0xad, 0x89, 0x45, 0x40, 0x25, 0xdb, 0x48, 0x53, 0xa2, 0x3e, + 0x31, 0x09, 0xb9, 0xdb, 0x54, 0x72, 0x07, 0x6b, 0xcd, 0x05, 0x05, 0x52, + 0xee, 0x8c, 0x40, 0xfe, 0x3f, 0xb1, 0x2b, 0x5b, 0x14, 0xa4, 0x95, 0xc0, + 0xc2, 0xc6, 0x56, 0x1b, 0xaa, 0x06, 0xb1, 0x0d, 0xa4, 0x99, 0xa1, 0x6d, + 0x09, 0x7b, 0x15, 0xf9, 0x27, 0x64, 0x4c, 0x96, 0x82, 0x9d, 0x63, 0x85, + 0xf7, 0xa8, 0x22, 0xce, 0x3c, 0x1d, 0x8a, 0xf6, 0xec, 0xcb, 0xd1, 0x2a, + 0x2e, 0xab, 0x92, 0x36, 0x35, 0x1e, 0x03, 0xc5, 0x50, 0x76, 0x65, 0x06, + 0x02, 0xee, 0x16, 0x93, 0x5a, 0xcc, 0x52, 0x14, 0xd4, 0x4f, 0xea, 0x43, + 0xf1, 0x1b, 0x17, 0x2b, 0xa0, 0xb3, 0xa2, 0x76, 0xe2, 0x43, 0x1e, 0xe7, + 0xd2, 0x89, 0xe0, 0x92, 0x36, 0x8b, 0x22, 0x44, 0xb3, 0x00, 0xa5, 0x0d, + 0x4c, 0xdf, 0x90, 0x65, 0x33, 0x2f, 0x2a, 0x9b, 0x79, 0x41, 0xd9, 0x3c, + 0x93, 0x95, 0x99, 0x2d, 0x81, 0x91, 0x88, 0x5e, 0xf4, 0x6a, 0xf2, 0x1e, + 0x0b, 0x72, 0xb9, 0xff, 0xb8, 0xcc, 0xb3, 0xc5, 0x06, 0xb8, 0x6c, 0x2e, + 0x2b, 0x8c, 0x4c, 0x5a, 0xe9, 0xa7, 0x4e, 0xa9, 0xaa, 0x6d, 0x36, 0xfe, + 0xc3, 0xd0, 0xbe, 0xfd, 0xa7, 0xf1, 0xbd, 0xa4, 0xeb, 0x9b, 0xff, 0x56, + 0x35, 0xe8, 0x90, 0xa2, 0xee, 0x7c, 0xab, 0x7f, 0xc7, 0x52, 0x5b, 0x46, + 0x09, 0xf0, 0xda, 0x5c, 0x0f, 0xc0, 0x09, 0xb6, 0x7b, 0xe0, 0x8a, 0xb8, + 0x7b, 0xe2, 0x02, 0x6b, 0x76, 0x08, 0x54, 0xea, 0xba, 0xfe, 0xda, 0x86, + 0x5f, 0xc4, 0x50, 0x6d, 0x88, 0xa7, 0x1e, 0xef, 0xa7, 0x4f, 0x76, 0xf4, + 0xf8, 0x18, 0x24, 0x0f, 0x10, 0x4c, 0xe5, 0x63, 0x3b, 0x9e, 0x16, 0xbf, + 0x7b, 0x5e, 0xfc, 0x14, 0xc4, 0xd3, 0x87, 0x08, 0x21, 0xca, 0xbb, 0xeb, + 0x19, 0x77, 0xd3, 0xff, 0xf3, 0x29, 0xf0, 0x9c, 0x6e, 0x8c, 0xa3, 0x97, + 0x3e, 0xd1, 0xf8, 0xb1, 0xcb, 0x3a, 0xd1, 0x13, 0x6b, 0xbb, 0x85, 0x38, + 0x85, 0x9a, 0x53, 0x76, 0xf5, 0xa8, 0xa9, 0x31, 0xcb, 0xa9, 0x85, 0x36, + 0xf8, 0x34, 0x27, 0x17, 0xcf, 0xa9, 0x1e, 0x69, 0xc9, 0xac, 0x35, 0x36, + 0x83, 0x35, 0x34, 0xb7, 0x86, 0xeb, 0x65, 0x6c, 0xa3, 0x6c, 0xaa, 0x78, + 0xc7, 0xa0, 0x03, 0x65, 0xa6, 0x05, 0xd1, 0x04, 0x53, 0x6c, 0xb7, 0xa3, + 0x80, 0x52, 0x6f, 0x02, 0x8d, 0x93, 0xf6, 0xb3, 0x71, 0x0b, 0x0a, 0x1d, + 0x97, 0xc4, 0xa8, 0x24, 0x45, 0xe1, 0x79, 0x3d, 0xdf, 0xf9, 0x4a, 0xf5, + 0x30, 0xd8, 0x1e, 0xed, 0x60, 0x77, 0xe0, 0x0c, 0xc2, 0x93, 0xa6, 0x66, + 0xae, 0x89, 0x80, 0x3e, 0xc6, 0x81, 0x3c, 0xbf, 0x56, 0xf6, 0xd4, 0x24, + 0xba, 0x8e, 0x5e, 0x2e, 0x2a, 0x44, 0xe7, 0xe7, 0xdb, 0x40, 0xc4, 0x58, + 0xc4, 0xb7, 0x29, 0x74, 0xf7, 0xc0, 0x40, 0xff, 0x69, 0xe8, 0x32, 0x03, + 0x4d, 0xf6, 0xc6, 0xb7, 0x25, 0xda, 0x7d, 0xf8, 0x81, 0x0a, 0xaf, 0x00, + 0xf9, 0x0b, 0x19, 0xdf, 0xfe, 0x69, 0xf8, 0x07, 0x02, 0x6f, 0xa1, 0x6e, + 0xb3, 0xab, 0xc4, 0x02, 0x75, 0x23, 0x98, 0x72, 0x4e, 0x11, 0xb9, 0xeb, + 0x0e, 0x84, 0x0b, 0x4b, 0xa8, 0x24, 0xb3, 0xb3, 0x9f, 0xe6, 0x5f, 0x48, + 0x2b, 0x37, 0xdd, 0x37, 0x2a, 0xfd, 0x08, 0xc9, 0x8a, 0x38, 0x50, 0xc0, + 0x30, 0x04, 0x61, 0x97, 0x97, 0xd4, 0xcd, 0xf8, 0x83, 0xc9, 0xfd, 0x90, + 0xaa, 0xe3, 0x77, 0x2a, 0xdb, 0x02, 0xa6, 0x58, 0x98, 0x0d, 0x4f, 0x31, + 0xe5, 0x52, 0xa4, 0x8f, 0xd5, 0x53, 0x40, 0x30, 0xe1, 0x8b, 0xf5, 0x2f, + 0x96, 0x7e, 0xe4, 0x4f, 0x3c, 0x08, 0x74, 0x1e, 0xe0, 0x2e, 0x51, 0x52, + 0xd4, 0x92, 0x5b, 0x52, 0x21, 0xbc, 0x41, 0x3d, 0x01, 0x2e, 0x28, 0xb4, + 0xed, 0x39, 0x93, 0xcf, 0xcf, 0xf3, 0x39, 0xd3, 0x9d, 0x9f, 0x1f, 0x69, + 0x6e, 0x19, 0xf2, 0xd7, 0x77, 0xea, 0xec, 0x02, 0x26, 0xd8, 0x7a, 0xd9, + 0x2e, 0xd0, 0x0c, 0x6a, 0x53, 0x9e, 0xd2, 0x3f, 0xa3, 0x16, 0xf8, 0xeb, + 0x34, 0xa2, 0x8b, 0x7a, 0x9e, 0x7a, 0x66, 0x1b, 0xcf, 0x25, 0xca, 0xce, + 0x54, 0xef, 0xa4, 0x28, 0xe1, 0xcc, 0xb6, 0x4f, 0x64, 0xf7, 0xbf, 0xed, + 0xbb, 0xb6, 0x7d, 0xed, 0x7a, 0x9b, 0x33, 0xc6, 0xd3, 0xa3, 0x86, 0xf8, + 0x21, 0x82, 0x98, 0x4e, 0x29, 0x5b, 0x85, 0x40, 0xb1, 0x24, 0x2e, 0x84, + 0x8a, 0x1f, 0xde, 0x03, 0x8b, 0x73, 0xca, 0xb6, 0x49, 0x0d, 0xe0, 0x2c, + 0x8c, 0xde, 0x97, 0xac, 0x32, 0x4b, 0xde, 0x1e, 0x4a, 0xa4, 0xe9, 0xca, + 0x03, 0x8e, 0x33, 0xd1, 0x6a, 0xc9, 0x32, 0x11, 0x7b, 0x8e, 0x85, 0x49, + 0x57, 0x3c, 0x8e, 0xa7, 0x5c, 0xa6, 0x5d, 0x52, 0xb1, 0x54, 0x8f, 0xc7, + 0xb8, 0xeb, 0x99, 0x4c, 0x0e, 0x69, 0xce, 0x66, 0xd8, 0x48, 0x24, 0xf9, + 0xaf, 0x0c, 0x7a, 0x93, 0x9e, 0x6b, 0xc2, 0xd8, 0x5d, 0xdd, 0x68, 0xe3, + 0xcc, 0x33, 0xd7, 0x92, 0x85, 0x6e, 0x74, 0x61, 0xa2, 0xfc, 0x8e, 0x5d, + 0xe3, 0x39, 0xcd, 0xa4, 0x69, 0x13, 0x48, 0xc7, 0xa6, 0x15, 0x7b, 0x07, + 0x18, 0x4f, 0xbc, 0xe0, 0xef, 0x33, 0xed, 0x99, 0x8e, 0x6e, 0x16, 0xed, + 0xe6, 0x5c, 0xfd, 0x4f, 0x33, 0xeb, 0x4b, 0x79, 0x26, 0xf4, 0xf7, 0xd9, + 0x75, 0x4f, 0xd8, 0xb5, 0x38, 0x2c, 0x28, 0x10, 0xce, 0xde, 0x10, 0xfe, + 0xb5, 0xfe, 0x2f, 0x89, 0xa6, 0x26, 0x29, 0x7a, 0xa7, 0x23, 0x59, 0x20, + 0x1f, 0xa6, 0xe7, 0x5b, 0x8f, 0xb3, 0x63, 0x4f, 0x71, 0x47, 0xe2, 0x9f, + 0x1a, 0x7b, 0x66, 0xb7, 0x49, 0x0b, 0x98, 0x10, 0xe8, 0xe5, 0xe0, 0xdd, + 0xd8, 0x53, 0xdc, 0x3b, 0xfa, 0xcb, 0x63, 0x8f, 0x2e, 0x88, 0x9a, 0x38, + 0x48, 0xce, 0x22, 0xef, 0xc6, 0x7d, 0x61, 0xd7, 0x70, 0x3b, 0x9d, 0x80, + 0xf2, 0x3b, 0xac, 0xfb, 0xcb, 0xed, 0xe4, 0xfd, 0x50, 0xd4, 0xfd, 0xe2, + 0x78, 0xb5, 0xef, 0x86, 0x01, 0x75, 0x43, 0x9e, 0x23, 0x41, 0x4b, 0x3c, + 0xff, 0xba, 0xfd, 0xf3, 0x67, 0xf2, 0xb2, 0x61, 0x97, 0x82, 0xf4, 0xf5, + 0x61, 0x9d, 0x65, 0x5e, 0x36, 0x58, 0xa9, 0x0d, 0x59, 0xe0, 0x5f, 0x45, + 0x7c, 0x2e, 0xe6, 0x7a, 0x7f, 0x2c, 0xe6, 0x0a, 0xb1, 0xba, 0xd8, 0x05, + 0xc5, 0xc6, 0x96, 0x89, 0xc7, 0xeb, 0x6a, 0x23, 0x6e, 0x23, 0xbe, 0x93, + 0xa8, 0x46, 0x3d, 0xd4, 0xa8, 0x14, 0xf3, 0x21, 0x3e, 0x6c, 0x92, 0xc9, + 0xeb, 0x00, 0x58, 0x97, 0x62, 0xa2, 0xce, 0x81, 0xee, 0xa9, 0x8f, 0xac, + 0xdf, 0x55, 0xf3, 0x99, 0x2d, 0x24, 0x86, 0xca, 0x3a, 0xdb, 0xd0, 0x26, + 0x4e, 0x77, 0x1d, 0x40, 0x48, 0x5f, 0xaf, 0xb2, 0x8d, 0xe9, 0x13, 0x11, + 0x3c, 0xdb, 0x2b, 0x50, 0x30, 0xc2, 0x39, 0x05, 0x03, 0xc0, 0x1c, 0x5c, + 0x43, 0xf2, 0xf4, 0xb1, 0x9c, 0x28, 0x59, 0x0a, 0xf8, 0x87, 0xb9, 0xe9, + 0xd4, 0xc0, 0x8e, 0x18, 0x50, 0x15, 0x35, 0x22, 0x34, 0x71, 0x4c, 0x04, + 0x31, 0xf7, 0xc2, 0x77, 0x3d, 0xd2, 0x25, 0xb2, 0x41, 0x50, 0xc6, 0x44, + 0x06, 0xa1, 0x89, 0xd3, 0xb2, 0xb2, 0x9b, 0x72, 0xbb, 0xf3, 0xd7, 0x73, + 0x7b, 0xf2, 0xf0, 0x48, 0x38, 0xb1, 0x96, 0x0b, 0xf9, 0x40, 0x52, 0x61, + 0x3b, 0xf3, 0xf3, 0xf0, 0x9f, 0x46, 0xd2, 0x7e, 0xbb, 0x1a, 0x3f, 0xa9, + 0xfa, 0xaf, 0x9e, 0x25, 0x89, 0x4b, 0x8e, 0xa9, 0x78, 0xad, 0x7c, 0xdb, + 0x63, 0xea, 0x88, 0x68, 0x56, 0x4f, 0x9c, 0xc4, 0xde, 0x76, 0x7e, 0xbe, + 0x17, 0x4b, 0xa2, 0x38, 0x32, 0x24, 0x33, 0x37, 0x49, 0x26, 0x78, 0x36, + 0x34, 0x32, 0xe1, 0xaf, 0x11, 0xc6, 0x9f, 0x2d, 0xce, 0x7a, 0x5e, 0x9c, + 0x2e, 0x66, 0x55, 0x98, 0x82, 0x44, 0xc4, 0xe7, 0xaf, 0x56, 0x64, 0xee, + 0xdb, 0xe0, 0xc9, 0xa9, 0xb8, 0x69, 0xe1, 0x14, 0xdf, 0xb4, 0x70, 0x72, + 0x37, 0x2d, 0x66, 0x07, 0x28, 0x91, 0x02, 0xc5, 0x1d, 0x15, 0x79, 0x24, + 0x19, 0x4d, 0x10, 0xfc, 0x6d, 0x82, 0xb3, 0x56, 0x6f, 0x4e, 0xb0, 0xc7, + 0x60, 0x70, 0xd2, 0x45, 0xf7, 0x30, 0x3f, 0x4f, 0x73, 0xc6, 0x0f, 0x1e, + 0x7c, 0x2e, 0x65, 0x81, 0xb8, 0x06, 0x64, 0x04, 0xae, 0xcf, 0xb5, 0xfc, + 0x60, 0x7a, 0xb1, 0x05, 0x95, 0x08, 0xc1, 0xc1, 0xef, 0x26, 0x15, 0x47, + 0x12, 0x50, 0x5c, 0xb7, 0x89, 0x4d, 0x77, 0x20, 0x72, 0x10, 0x9f, 0x42, + 0x59, 0x8d, 0x83, 0x7a, 0x43, 0xce, 0x9d, 0xfa, 0x88, 0x83, 0x71, 0x31, + 0xeb, 0xbc, 0x9d, 0x7a, 0xce, 0x3e, 0x2c, 0xcd, 0x29, 0x91, 0xa3, 0x27, + 0x37, 0x73, 0x5c, 0xc0, 0x4c, 0x3a, 0x3c, 0xa8, 0x07, 0x6a, 0x4d, 0xb2, + 0xee, 0x36, 0x49, 0xa9, 0x24, 0x19, 0x64, 0x41, 0xd6, 0xcd, 0xbf, 0x91, + 0xef, 0x4d, 0x2b, 0x3a, 0x41, 0x35, 0x4d, 0xd3, 0x96, 0x74, 0xa0, 0xd3, + 0xb3, 0x05, 0xda, 0xf0, 0x83, 0xf7, 0xd9, 0xf4, 0x46, 0x27, 0x19, 0xc2, + 0x5e, 0x7d, 0x5e, 0x67, 0xc7, 0x63, 0x88, 0x12, 0x99, 0x6b, 0x2f, 0xce, + 0xc4, 0xb5, 0x97, 0xd4, 0xb2, 0x7e, 0x35, 0xb5, 0x78, 0xe3, 0xba, 0xc2, + 0x1b, 0xd9, 0x08, 0x18, 0x11, 0x7a, 0xc9, 0xc4, 0xd3, 0x83, 0x91, 0x8e, + 0x33, 0x2e, 0x9d, 0x68, 0xc2, 0xc5, 0xfc, 0x61, 0x9d, 0xe4, 0xc5, 0x3a, + 0xc9, 0xa5, 0x4e, 0x2a, 0xb0, 0xca, 0x89, 0x2b, 0x87, 0xc9, 0xe3, 0x24, + 0x10, 0x05, 0xcf, 0x31, 0x03, 0x92, 0x85, 0xdc, 0xfb, 0x9c, 0x09, 0x1a, + 0x18, 0xdd, 0x51, 0xba, 0x20, 0x1c, 0x9b, 0x7a, 0x39, 0xde, 0x95, 0xb3, + 0xdf, 0xf0, 0x50, 0x3c, 0xe3, 0x8f, 0x9d, 0xe8, 0xbe, 0xc9, 0x1b, 0xcb, + 0x9b, 0x13, 0x97, 0xa7, 0x32, 0x5c, 0xe8, 0x49, 0x45, 0xce, 0x12, 0x5c, + 0x2b, 0xab, 0x18, 0x54, 0xb0, 0x7b, 0x1c, 0x35, 0xf4, 0x0d, 0xc3, 0x00, + 0x8f, 0x37, 0xec, 0xdb, 0x48, 0x76, 0x41, 0xfb, 0x37, 0xfe, 0x14, 0x37, + 0x81, 0x5d, 0x2d, 0x1a, 0x28, 0x23, 0xf0, 0xf4, 0x6b, 0xf6, 0xd6, 0x08, + 0xfe, 0x1f, 0x54, 0x9b, 0x16, 0xf3, 0x4d, 0xd8, 0x42, 0x5c, 0x1d, 0x89, + 0x67, 0x15, 0x5d, 0x20, 0xb1, 0xb2, 0xe6, 0xec, 0xb9, 0x9e, 0xa6, 0xa3, + 0x0d, 0x03, 0x9d, 0x65, 0x9a, 0x99, 0x35, 0x2a, 0xa4, 0x45, 0xe4, 0x6c, + 0x19, 0x62, 0xb0, 0x25, 0x1e, 0x5d, 0x3f, 0x92, 0x74, 0xf1, 0x82, 0xd3, + 0x42, 0x2e, 0xce, 0x09, 0xf9, 0xaf, 0x10, 0x4d, 0x12, 0xa2, 0x79, 0x6c, + 0xc6, 0xb8, 0x68, 0xdf, 0xf5, 0xfb, 0xbb, 0x84, 0x93, 0xa4, 0x62, 0xd4, + 0xa2, 0x8b, 0x02, 0x3c, 0xb5, 0x20, 0x08, 0xfe, 0x7e, 0x5b, 0x74, 0xb7, + 0xf3, 0xac, 0xba, 0xb8, 0x11, 0xac, 0xc2, 0xe6, 0xbe, 0x3a, 0xc9, 0xa0, + 0x0c, 0xdd, 0x5d, 0xe4, 0xce, 0x04, 0xd5, 0x22, 0x6f, 0xfc, 0x5f, 0x88, + 0x30, 0xa1, 0x46, 0xcf, 0x34, 0xfd, 0x13, 0x5a, 0xf8, 0x04, 0x2d, 0x53, + 0x98, 0xef, 0xee, 0x9d, 0xec, 0x5d, 0xef, 0xcd, 0x42, 0x1e, 0xbc, 0x6b, + 0x64, 0x76, 0x3c, 0x57, 0xd5, 0x67, 0x2e, 0xea, 0x63, 0x93, 0x11, 0x0f, + 0x93, 0xab, 0xb3, 0x8f, 0x64, 0x26, 0xfc, 0x1d, 0xf0, 0x53, 0x1c, 0x1f, + 0xb4, 0x6d, 0x4a, 0xfc, 0x53, 0xc2, 0x9c, 0x0b, 0xe2, 0x50, 0xfb, 0x0f, + 0x1d, 0x48, 0xfc, 0xfd, 0x47, 0x42, 0x16, 0x7b, 0x8e, 0x0f, 0x5f, 0xa6, + 0xae, 0x74, 0x2f, 0x6c, 0x68, 0xe8, 0x98, 0xc5, 0x69, 0x50, 0x07, 0xaf, + 0x8f, 0x29, 0x78, 0xec, 0x03, 0xa2, 0x20, 0xf2, 0x44, 0x37, 0xb9, 0x8e, + 0x06, 0x39, 0x1d, 0xc0, 0xd9, 0x50, 0xc7, 0x92, 0x11, 0x19, 0x27, 0x91, + 0x0b, 0xe7, 0xd9, 0xdb, 0xac, 0xea, 0x96, 0x9c, 0x84, 0x9a, 0x82, 0x72, + 0xc7, 0xbb, 0x80, 0x39, 0x8d, 0xf9, 0xa5, 0x33, 0xb7, 0xe2, 0x36, 0xad, + 0x86, 0x07, 0x34, 0x33, 0x7b, 0xfb, 0x78, 0xb6, 0xd1, 0x48, 0x3b, 0xd1, + 0x14, 0xd3, 0x5b, 0x98, 0x8e, 0xe7, 0xa3, 0x8d, 0xbc, 0x28, 0x35, 0xcc, + 0x53, 0xa2, 0x13, 0xa2, 0xc4, 0xd5, 0x4d, 0xde, 0x18, 0x88, 0xaf, 0xbb, + 0x99, 0xd9, 0xeb, 0x6e, 0x7a, 0x8e, 0xe4, 0xcb, 0xe4, 0x2e, 0x28, 0x9e, + 0x80, 0x4b, 0x32, 0xa5, 0xe1, 0x27, 0x9e, 0x7c, 0xe6, 0xfc, 0x2c, 0x6b, + 0x2a, 0x75, 0xd3, 0x2c, 0xb8, 0xef, 0x94, 0x01, 0xf5, 0x9a, 0x5e, 0x8d, + 0xfd, 0xf6, 0xbd, 0xec, 0x98, 0xb4, 0x59, 0xa9, 0x63, 0x72, 0x33, 0xb9, + 0x66, 0x7e, 0x7e, 0xe6, 0xe5, 0x35, 0x08, 0x1d, 0x3a, 0x37, 0xbc, 0x30, + 0xe8, 0x61, 0x35, 0xe6, 0x14, 0x85, 0x16, 0x3c, 0x7a, 0x77, 0x36, 0xa3, + 0x49, 0x08, 0xae, 0x91, 0x2e, 0x10, 0xb6, 0x16, 0x71, 0x2d, 0xbd, 0x97, + 0x60, 0xe6, 0xb3, 0x98, 0x09, 0xd7, 0x21, 0xe7, 0x44, 0xe4, 0xfe, 0x8d, + 0x6e, 0x52, 0xde, 0xd9, 0x2a, 0x88, 0x20, 0x17, 0xff, 0xdd, 0xc9, 0xb5, + 0xf5, 0xb4, 0x0d, 0x43, 0xe1, 0xbf, 0x02, 0xd6, 0x54, 0x25, 0x23, 0x34, + 0x30, 0xed, 0x61, 0x4b, 0x49, 0x10, 0xa0, 0x49, 0x93, 0x36, 0xc4, 0xa4, + 0xb0, 0x27, 0x84, 0x50, 0x92, 0x06, 0x1a, 0x48, 0x63, 0xd4, 0x84, 0xb1, + 0xaa, 0xea, 0x7f, 0xdf, 0xb9, 0x38, 0xa9, 0xed, 0xa6, 0x65, 0xf4, 0xa5, + 0x4d, 0x63, 0xc7, 0xb1, 0x8f, 0x8f, 0xcf, 0xf5, 0x3b, 0xbd, 0x8a, 0xb7, + 0xc9, 0xc5, 0xd5, 0x6a, 0x19, 0x47, 0x60, 0xb0, 0x88, 0xb5, 0x56, 0xea, + 0xb1, 0xb6, 0xb3, 0x5b, 0x31, 0x71, 0xbb, 0x2c, 0x35, 0xdf, 0x4d, 0x8a, + 0x6e, 0x91, 0xff, 0x08, 0xcf, 0xe0, 0xb9, 0xd1, 0x72, 0x6d, 0xe8, 0xc2, + 0x37, 0x12, 0x4d, 0xec, 0x46, 0xb1, 0xed, 0xdd, 0xa7, 0x4b, 0x05, 0x48, + 0xa4, 0xa2, 0x02, 0x59, 0xf4, 0xff, 0x69, 0xc7, 0xaa, 0x4d, 0x3b, 0x56, + 0x7a, 0xaa, 0xb4, 0x1b, 0x6a, 0x94, 0xc2, 0xeb, 0x9f, 0x46, 0xab, 0xd4, + 0x29, 0xb4, 0x50, 0xe2, 0x54, 0x6f, 0xc0, 0xf4, 0x29, 0xdc, 0x7f, 0x4c, + 0xfe, 0x24, 0x0c, 0xc6, 0x37, 0x5a, 0x33, 0x3d, 0x81, 0x0a, 0xdd, 0xb2, + 0x3b, 0xbc, 0x32, 0x7a, 0x74, 0x09, 0xd5, 0x7a, 0x75, 0xf9, 0x3c, 0x79, + 0xee, 0x4b, 0xd4, 0x76, 0xf9, 0x59, 0xca, 0xbd, 0xc2, 0x06, 0x74, 0x9a, + 0x67, 0xc9, 0x6b, 0x42, 0xd8, 0x0a, 0x66, 0xbd, 0x60, 0x7b, 0xa9, 0x2c, + 0x65, 0x88, 0xd3, 0x6e, 0x6d, 0xd5, 0x90, 0xbc, 0x40, 0x07, 0x0c, 0x72, + 0x67, 0x65, 0xc0, 0xc2, 0x4d, 0x09, 0x37, 0x25, 0xe3, 0xff, 0x40, 0x0a, + 0xe7, 0x7a, 0xff, 0x04, 0x5d, 0x46, 0x6e, 0x02, 0x7e, 0xa9, 0x3c, 0x35, + 0x7f, 0x35, 0x52, 0xdb, 0xc2, 0xd4, 0x72, 0x5b, 0x28, 0x20, 0x9a, 0x3b, + 0x5e, 0x11, 0x62, 0x02, 0x1f, 0x37, 0x1b, 0xe3, 0xc9, 0x1a, 0x52, 0xc4, + 0xe4, 0xda, 0xd6, 0x1e, 0x2d, 0x95, 0x3d, 0x3a, 0x18, 0x98, 0x06, 0x69, + 0x09, 0x1c, 0x01, 0x4a, 0x54, 0x17, 0x92, 0x8e, 0x2d, 0x35, 0x70, 0x31, + 0xb6, 0x4d, 0xa8, 0x61, 0x2d, 0xd6, 0x5e, 0xf8, 0x36, 0xf2, 0x65, 0x27, + 0xd5, 0xb9, 0xfe, 0x98, 0x52, 0x8e, 0xbb, 0xaa, 0x5c, 0x05, 0x52, 0x46, + 0x02, 0x85, 0x1d, 0x81, 0x4e, 0x9d, 0x02, 0xce, 0x0c, 0xe3, 0x31, 0x9d, + 0xd2, 0x32, 0xac, 0x0b, 0xb6, 0x17, 0x62, 0xaa, 0xd2, 0x63, 0x3f, 0x76, + 0x23, 0xaa, 0x17, 0x04, 0x2b, 0x12, 0xd6, 0xd6, 0x4a, 0x16, 0x12, 0xc1, + 0x36, 0xa5, 0x57, 0xb2, 0x74, 0x25, 0x60, 0x9c, 0xb2, 0x47, 0x7c, 0xb8, + 0xad, 0xdc, 0xc8, 0x30, 0x14, 0xad, 0x81, 0x1e, 0xc8, 0x3c, 0x2e, 0x75, + 0xc3, 0x98, 0x79, 0x58, 0x9d, 0x39, 0x0e, 0x55, 0x14, 0x48, 0xab, 0x38, + 0xaf, 0x6b, 0x5a, 0x04, 0x2e, 0xf8, 0x12, 0x5c, 0x22, 0x47, 0x00, 0x4f, + 0xf9, 0x53, 0xb8, 0x42, 0x66, 0xc4, 0xe5, 0x42, 0xc3, 0xf5, 0x24, 0x9f, + 0xaa, 0x96, 0x06, 0x2f, 0xa1, 0x49, 0x62, 0xd3, 0x07, 0xa2, 0x7e, 0x4c, + 0xf9, 0x18, 0x98, 0x72, 0x78, 0xec, 0x1f, 0x79, 0xeb, 0xc3, 0xfe, 0xae, + 0xf3, 0x58, 0xde, 0x37, 0xd7, 0x49, 0x0a, 0x44, 0x39, 0x72, 0x7b, 0x7a, + 0x40, 0x13, 0xc5, 0x99, 0x3e, 0xa9, 0xf7, 0x7d, 0x2f, 0x1e, 0x26, 0x25, + 0x86, 0xff, 0xce, 0x32, 0x2c, 0x3f, 0xfa, 0x09, 0x5b, 0xa4, 0x9e, 0x84, + 0xc6, 0x18, 0x98, 0xf7, 0xd7, 0xac, 0xa8, 0x9a, 0x4b, 0x02, 0x03, 0x11, + 0xbb, 0xc1, 0xa6, 0xc8, 0xe9, 0x34, 0xa9, 0xc6, 0x35, 0x46, 0xb6, 0x2e, + 0xf8, 0xda, 0x59, 0xa0, 0xdb, 0x19, 0x10, 0x46, 0x53, 0x78, 0x29, 0x1c, + 0xd6, 0x1f, 0xf9, 0x3c, 0x58, 0xbc, 0x16, 0x55, 0x20, 0x2e, 0x9a, 0x59, + 0x79, 0x18, 0x0b, 0x6f, 0x9a, 0x64, 0xf0, 0x83, 0xfb, 0xc3, 0xef, 0xa5, + 0x87, 0x52, 0x2c, 0x30, 0x63, 0x19, 0x2d, 0x70, 0x0c, 0x43, 0x62, 0x57, + 0x55, 0x39, 0x0f, 0xf6, 0x8f, 0x97, 0x6f, 0xbd, 0x12, 0xe6, 0x08, 0x2f, + 0x4b, 0x25, 0x30, 0x43, 0x07, 0x18, 0xeb, 0x9d, 0xc3, 0x59, 0xd9, 0x1c, + 0x4e, 0xac, 0x79, 0xf0, 0xbd, 0xfe, 0xb9, 0xd8, 0x08, 0x34, 0x26, 0x0a, + 0xd1, 0x12, 0xb8, 0xc1, 0x11, 0x1c, 0x02, 0x12, 0x9e, 0xf1, 0x58, 0x3f, + 0x7f, 0x1e, 0xb9, 0xf4, 0xb4, 0x32, 0xa4, 0x0c, 0xa5, 0xf7, 0x2e, 0x23, + 0x6e, 0x33, 0xa8, 0x9d, 0xc4, 0x60, 0x48, 0x98, 0x6c, 0x4d, 0xbe, 0xbd, + 0x9f, 0x09, 0x67, 0x0a, 0x5c, 0x88, 0x3b, 0xa1, 0xdb, 0xe7, 0x9b, 0xdf, + 0xac, 0xdb, 0x2b, 0xe8, 0xb4, 0x5b, 0x67, 0x0c, 0x1e, 0x79, 0xe7, 0x11, + 0xab, 0xb5, 0x0a, 0xa0, 0x4e, 0x1f, 0x4b, 0xcb, 0xf4, 0xc0, 0xc6, 0xf3, + 0x52, 0xa6, 0xce, 0x4d, 0x73, 0xeb, 0x2d, 0xd0, 0x90, 0x0c, 0x2a, 0xa0, + 0x71, 0xee, 0x76, 0xe7, 0xd3, 0xb2, 0x44, 0xd4, 0x19, 0x95, 0xee, 0x12, + 0x3c, 0x53, 0xa2, 0x05, 0x0b, 0x1d, 0xf7, 0x40, 0x08, 0xd0, 0xc1, 0xb8, + 0x66, 0x05, 0x4b, 0x34, 0xca, 0x8b, 0x3a, 0xe3, 0xb7, 0xd9, 0x22, 0x7c, + 0x88, 0x60, 0x3a, 0xbb, 0xe8, 0x43, 0xa0, 0xe2, 0xa0, 0x7a, 0x86, 0x07, + 0x1a, 0x0b, 0x88, 0xfe, 0x52, 0x2a, 0xb2, 0xe3, 0x3e, 0x3d, 0x01, 0xef, + 0x02, 0xaf, 0x02, 0x8d, 0xee, 0xa6, 0x94, 0x32, 0x35, 0xb9, 0x10, 0x2b, + 0xf8, 0x38, 0x07, 0xd3, 0xcb, 0xe8, 0xc0, 0x97, 0x78, 0x5c, 0x70, 0x76, + 0x85, 0x16, 0xd4, 0xab, 0xce, 0xe5, 0x78, 0x4e, 0x11, 0x88, 0x36, 0x4e, + 0xbb, 0x58, 0x8e, 0xe0, 0x24, 0x8c, 0xe5, 0x2b, 0x45, 0xb7, 0xb0, 0xd7, + 0x70, 0x02, 0x5a, 0x06, 0x24, 0x2e, 0xf0, 0x48, 0x96, 0x3b, 0xfe, 0xcd, + 0xe9, 0xe0, 0xf6, 0x00, 0x8c, 0x8c, 0x10, 0xbe, 0xdc, 0x10, 0x2e, 0x06, + 0xb7, 0x1f, 0x5d, 0xff, 0xa1, 0x58, 0xdb, 0x5f, 0x09, 0x14, 0x07, 0x55, + 0x4d, 0x81, 0x3c, 0xcd, 0x71, 0xd8, 0xd7, 0x1c, 0x07, 0x97, 0x43, 0x2d, + 0x86, 0xb9, 0xd3, 0xaa, 0x15, 0x4f, 0x12, 0xee, 0x16, 0xbe, 0xf0, 0x8f, + 0x80, 0xe0, 0x8b, 0xc4, 0x9c, 0x3b, 0x32, 0x0a, 0x10, 0x04, 0x97, 0x5a, + 0x0b, 0xd2, 0x96, 0xa1, 0x86, 0xf8, 0x14, 0x78, 0x83, 0xac, 0xb1, 0x7c, + 0x5d, 0x4b, 0x9e, 0xf8, 0xaa, 0x7e, 0x50, 0xd5, 0x11, 0x12, 0xee, 0x11, + 0x6d, 0xcd, 0x3a, 0xf0, 0xfd, 0x6c, 0x5c, 0x3d, 0xa2, 0x03, 0x2a, 0x5f, + 0xc6, 0xf7, 0x25, 0xe8, 0x5b, 0x94, 0x29, 0x7e, 0xf2, 0x98, 0xfc, 0xf5, + 0xcb, 0x22, 0xad, 0x11, 0x9f, 0xe7, 0x1f, 0x0f, 0x3f, 0x0f, 0xbf, 0xb6, + 0x48, 0x3d, 0x04, 0xdf, 0x02, 0x2b, 0x87, 0x2f, 0xcd, 0xfd, 0xe1, 0x97, + 0xc8, 0x1e, 0x3a, 0x32, 0x17, 0xaf, 0x7b, 0x4d, 0x96, 0x13, 0x77, 0x91, + 0x54, 0xe8, 0x08, 0x92, 0x03, 0xa7, 0x86, 0xee, 0xc0, 0x82, 0xaf, 0x79, + 0xea, 0xed, 0x35, 0xb3, 0x39, 0x7b, 0x78, 0x59, 0x52, 0xee, 0x65, 0xf2, + 0x79, 0x2e, 0x54, 0xbe, 0x86, 0x5e, 0xb4, 0x39, 0x25, 0xc1, 0xd6, 0x99, + 0x3b, 0xe2, 0x0b, 0x02, 0x9b, 0x08, 0x1d, 0x6b, 0x28, 0x3c, 0xd5, 0x92, + 0xd4, 0xf3, 0x2a, 0xc3, 0x82, 0x8b, 0x6e, 0x28, 0xa4, 0xae, 0x99, 0xdf, + 0xa2, 0x9e, 0x3a, 0x05, 0x31, 0xe5, 0xb2, 0xd7, 0x86, 0x8c, 0x34, 0x76, + 0x8a, 0xc8, 0x1d, 0x06, 0xef, 0x9f, 0x77, 0x28, 0x62, 0xb7, 0xb6, 0xbd, + 0x89, 0xbb, 0x63, 0xdd, 0xe2, 0x6d, 0xb7, 0x6e, 0x2a, 0xd3, 0x44, 0xb9, + 0xd5, 0xfa, 0xbf, 0xcd, 0x58, 0x1d, 0x95, 0xb7, 0x13, 0x75, 0xf5, 0x64, + 0x5a, 0x19, 0x67, 0x5b, 0xd4, 0x75, 0x92, 0xce, 0xb8, 0x3f, 0x17, 0x95, + 0xe9, 0x65, 0xb0, 0x91, 0x92, 0x44, 0x84, 0xad, 0xa4, 0x71, 0xf9, 0xb3, + 0x20, 0x88, 0x0e, 0x8e, 0x67, 0x82, 0x76, 0xfa, 0x27, 0xc4, 0xbd, 0xa3, + 0x7f, 0xb9, 0xa1, 0x68, 0x0e, 0x38, 0x4b, 0x00, 0x00 +}; +unsigned int index_htm_gz_len = 6261; diff --git a/libraries/WebServer/examples/FSBrowser/extras/reduce_index.sh b/libraries/WebServer/examples/FSBrowser/extras/reduce_index.sh new file mode 100755 index 000000000..969f2a768 --- /dev/null +++ b/libraries/WebServer/examples/FSBrowser/extras/reduce_index.sh @@ -0,0 +1,60 @@ +#/bin/sh + +# Processing script to optionally reduce filesystem use by miniying, gzipping and preparing index.htm for embedding in code. +# Please see readme.md for more information. + +# Requires xdd which is part of the VIM package +# Requires npm +# sudo apt install npm +# ln -s /usr/bin/nodejs /usr/bin/node +# Requires html-minifier +# sudo npm install html-minifier -g + +html-minifier \ + --case-sensitive \ + --collapse-boolean-attributes \ + --collapse-whitespace \ + --minify-css true \ + --minify-js true \ + --process-conditional-comments \ + --remove-attribute-quotes \ + --remove-comments \ + --remove-empty-attributes \ + --remove-optional-tags \ + --remove-redundant-attributes \ + --remove-script-type-attributes \ + --remove-style-link-type-attributes \ + -o index.htm \ + ../data/edit/index.htm + +if [ $? -ne 0 ] +then + echo "Error minifying index.htm" + exit -1 +fi + +if [ -e index.htm.gz ] +then + rm index.htm.gz +fi + +gzip index.htm +if [ $? -ne 0 ] +then + echo "Error gzipping minified index.htm" + exit -1 +fi + +echo '// WARNING: Auto-generated file. Please do not modify by hand.' > index_htm.h +echo '// This file is an embeddable version of the gzipped index.htm file.' >> index_htm.h +echo '// To update it, please rerun the `reduce_index.sh` script located in the `extras` subfolder' >> index_htm.h +echo '// then recompile the sketch after each change to the `index.html` file.' >> index_htm.h +xxd -i index.htm.gz >> index_htm.h +if [ $? -ne 0 ] +then + echo "Error creating include file from index.htm.gz" + exit -1 +fi + +echo Reduce complete. + diff --git a/libraries/WebServer/examples/FSBrowser/readme.md b/libraries/WebServer/examples/FSBrowser/readme.md new file mode 100644 index 000000000..2d1418327 --- /dev/null +++ b/libraries/WebServer/examples/FSBrowser/readme.md @@ -0,0 +1,137 @@ +# FSBrowser readme + +## What is this sketch about ? + +This example is a FileSystem Browser for the Pico using http requests and a html/javascript frontend, +working for all of SPIFFS, LittleFS and SDFS. +This unified version is based on the previous examples named FSWebServer, FSBrowser and SDWebServer, Copyright (c) 2015 Hristo Gochkov. All rights reserved. + +## How to use it ? +1. Uncomment one of the `#define USE_xxx` directives in the sketch +2. Add the credentials of your WiFi network (search for `STASSID`) +3. Compile and upload the sketch to your Pico +4. For normal use, copy the contents of the `data` folder to the filesystem. To do so: +- for SDFS, copy that contents (not the data folder itself, just its contents) to the root of a FAT/FAT32-formated SD card connected to the SPI port of the Pico +- for LittleFS, please follow the instructions at https://arduino-pico.readthedocs.io/en/latest/fs.html#uploading-files-to-the-littlefs-file-system +5. Once the data and sketch have been uploaded, access the editor by pointing your browser to http://fsbrowser.local/edit + +## Options +If you need to free some space on the Pico filesystem, you can delete all the sample files at the root but also replace the `index.htm` file in the `data/edit` subfolder by the `index.htm.gz` file from the `extras` folder. That compressed version is not suited for learning or debugging, but will bring the total FS usage under 7KB. +If you want to use the browser on a an existing filesystem or don't want to perform step 4 above, you have two possibilities : +- either upload the `index.htm` file to the filesystem by opening a command shell in the `data` folder and running the following cURL command: +`curl -F file=@edit/index.htm;filename=/edit/index.htm fsbrowser.local/edit` +- or embed a version of the html page in the source code itself by uncommenting the following line in the sketch and rebuilding: +`#define INCLUDE_FALLBACK_INDEX_HTM` +That embedded version is functionally equivalent and will be returned if no `/edit/index.htm` or `/edit/index.htm.gz` file can be found on the filesystem, at the expense of a higher binary size. + +If you use the gzipped or `INCLUDE_FALLBACK_INDEX_HTM` options, please remember to rerun the `reduce_index.sh` script located in the `extras` subfolder and recompile the sketch after each change to the `index.html` file. + +## Dependency +The html page uses the [Ace.js](https://ace.c9.io/) (v1.4.9 at the time of writing) text editor which is loaded from a CDN. Consequently, internet access from your web browser is required for the FSBrowser editing feature to work as-is. + +If your browser has no web access (e.g. if you are connected to the Pico as an access-point), you can copy the `ace.js` file to the `edit` subfolder of the Pico filesystem, along with optional plugins etc. according to your needs. A typical set might be: +``` +ace.js +ext-keybinding_menu.js +ext-searchbox.js +mode-html.js +worker-html.js +worker-css.js +worker-javascript.js +mode-xml.js +worker-xml.js +mode-json.js +worker-json.js +``` +(see https://github.com/ajaxorg/ace-builds for a full list). + +If `ace.js` cannot be found on the Pico filesystem either, the page will default to a plain text viewer, with a warning message. + +## Notes +- See https://arduino-pico.readthedocs.io/en/latest/fs.html for more information on FileSystems supported by the Pico. +- For SDFS, if your card's CS pin is not connected to the default pin (4), uncomment the `fileSystemConfig.setCSPin(chipSelectPin);` line, specifying the GPIO the CS pin is connected to +- `index.htm` is the default index returned if your URL does not end with a filename (works on subfolders as well) +- Directories are supported on SDFS and LittleFS. +- The convention here is that the root of the filesystem is "/". On SPIFFS, paths not started with a slash are not supported +- For creation, the convention is that a path ending with a "/" means create a folder, while without a "/" we create a file. Having an extension or not does not matter. + +## Changelog since original FSBrowser + +### Fixes to work on LittleFS based on SDFS +- #define logic to select FS +- switched from SD to SDFS +- begin() does not support parameters > removed SS and added optional config +- LittleFS.open() second parametsr is mandatory > specified "r" where needed +- 'FILE_WRITE' was not declared in this scope > replaced by "w" + +### UI/usability improvements +- Never format filesystem, just return "FS INIT ERROR" when FS cannot be mounted +- Tree panel width is now proportional (20%) to see long names on big screens +- Added icons for files, and indented them to the same level as folders +- Changed file/folder icon set to use a lighter and more neutral one, and added specific "text" and "image" icons for formats recognized as such +- Items are now sorted (folders first, then plain files, each in alphabetic order) +- Added file size after each file name +- Added FS status information at the top right +- Made clear that an async operation is in progress by dimming screen and showing operation status +- Filled filename box in header with the name of the last clicked file +- Selecting a file for upload defaults to putting it in the same folder as the last clicked file +- Removed limitation to 8.3 lowercase filenames +- Support Filenames without extension, Dirnames with extension +- Improved recursive refresh of parts of the tree (e.g. refresh folder upon file delete, show last folder upon creating nested file) +- Added Save/Discard/Help buttons to ACE editor, discard confirmation on leave, and refresh tree and status upon save +- Removed "Upload" from context menu (which didn't work anyway) +- Added "Rename/Move" feature to context menu +- Sketch can be used on a preexisting filesystem by embedding the index.htm file in the program + +## TODO (maybe) +- ? How can we query the fatType of the SDFS (FAT16 or FAT32) to limit filenames to 8.3 on FAT16 ? +- ? Add a visible root node "/" (with no delete option) + add the FS type next to it, like LittleFS +- ? move "Mkdir" and "MkFile" to context menu, with prompt like for Rename/Move +- ? implement drag/drop for move + make "rename" only a local rename operation (no move) +- ? Optionally present SPIFFS as a hierarchical FS too +- ? Optionally mount several filesystems at the same time (SPIFFS + SDFS or LittleFS + SDFS) + +## Test suite +These tests are a checklist of operations to verify the FSBrowser behaviour. +### On SPIFFS +#### 8.3 filenames +- At root : MkFile '/1.txt' / List / Edit / Download / Delete / Upload '/1.png' / View image / Delete image +- In subdir : MkFile '/dir/2.txt' / List / Edit / Download / Delete / Upload '/dir/2.png' / View image +- Create nested file '/a/b.txt' and delete it +- Attempt creation of unsupported filenames +#### Long filenames +- At root : MkFile '/My text file 1.txt' / List / Edit / Download / Delete / Upload '/My image file 1.png' / View image / Delete image +- In subdir : MkFile '/My Directory/My text 2.txt' / List / Edit / Download / Delete / Upload '/My Directory/My image 2.png' / View image +- Create nested file '/My folder/My test file.txt' and delete it + +### On LittleFS +#### 8.3 filenames +- At root : MkFile '/1.txt' / List / Edit / Download / Delete / Upload '/1.png' / View image / Delete image / Mkdir '/dir' +- In subdir : MkFile '/dir/2.txt' / List / Edit / Download / Delete / Upload '/dir/2.png' / View image / Mkdir '/dir/sub' +- Delete root folder '/dir' +- Create nested file '/a/b.txt' and delete file 'b.txt' +#### Long filenames +- At root : MkFile '/My text file 1.txt' / List / Edit / Download / Delete / Upload '/My image file 1.png' / View image / Delete image / Mkdir '/My Directory' +- In subdir : MkFile '/My Directory/My text file 2.txt' / List / Edit / Download / Delete / Upload '/My Directory/My image file 2.png' / View image / Mkdir '/My Directory/My Subdirectory' +- Delete root folder '/My Directory' +- Create nested file '/My folder/My test file.txt' and delete file 'My test file.txt' + +### On SDFS +#### 8.3 filenames +- At root : MkFile '/1.txt' / List / Edit / Download / Delete / Upload '/1.png' / View image / Delete image / Mkdir '/dir' +- In subdir : MkFile '/dir/2.txt' / List / Edit / Download / Delete / Upload '/dir/2.png' / View image / Mkdir '/dir/sub' +- Delete root folder '/dir' +- Create nested file '/a/b.txt' and delete file 'b.txt', then delete '/a' +#### Long filenames +- At root : MkFile '/My text file 1.txt' / List / Edit / Download / Delete / Upload '/My image file 1.png' / View image / Delete image / Mkdir '/My Directory' +- In subdir : MkFile '/My Directory/My text file 2.txt' / List / Edit / Download / Delete / Upload '/My Directory/My image file 2.png' / View image / Mkdir '/My Directory/My Subdirectory' +- Delete root folder '/My Directory' +- Create nested file '/My folder/My test file.txt' and delete file 'My test file.txt' + +## Credits +- Original version of FSBrowser written by me-no-dev, contributions over time by various contributors +- Icons are from https://feathericons.com/ . The resulting PNG is passed first through https://compresspng.com/ before being converted to base64 using https://www.base64-image.de/ +- The spinner is based on https://github.com/jlong/css-spinners +- Minifiying of index.htm is done using the command line version of https://kangax.github.io/html-minifier/ +- Idea of embedding webpage in code borrowed from https://github.com/me-no-dev/ESPAsyncWebServer + diff --git a/libraries/WebServer/examples/HelloServer/HelloServer.ino b/libraries/WebServer/examples/HelloServer/HelloServer.ino new file mode 100644 index 000000000..bdd328ab0 --- /dev/null +++ b/libraries/WebServer/examples/HelloServer/HelloServer.ino @@ -0,0 +1,149 @@ +#include +#include +#include +#include + +#ifndef STASSID +#define STASSID "your-ssid" +#define STAPSK "your-password" +#endif + +const char* ssid = STASSID; +const char* password = STAPSK; + +WebServer server(80); + +const int led = LED_BUILTIN; + +void handleRoot() { + digitalWrite(led, 1); + server.send(200, "text/plain", "hello from pico w!\r\n"); + digitalWrite(led, 0); +} + +void handleNotFound() { + digitalWrite(led, 1); + String message = "File Not Found\n\n"; + message += "URI: "; + message += server.uri(); + message += "\nMethod: "; + message += (server.method() == HTTP_GET) ? "GET" : "POST"; + message += "\nArguments: "; + message += server.args(); + message += "\n"; + for (uint8_t i = 0; i < server.args(); i++) { + message += " " + server.argName(i) + ": " + server.arg(i) + "\n"; + } + server.send(404, "text/plain", message); + digitalWrite(led, 0); +} + +void setup(void) { + pinMode(led, OUTPUT); + digitalWrite(led, 0); + Serial.begin(115200); + WiFi.mode(WIFI_STA); + WiFi.begin(ssid, password); + Serial.println(""); + + // Wait for connection + while (WiFi.status() != WL_CONNECTED) { + delay(500); + Serial.print("."); + } + Serial.println(""); + Serial.print("Connected to "); + Serial.println(ssid); + Serial.print("IP address: "); + Serial.println(WiFi.localIP()); + + if (MDNS.begin("picow")) { + Serial.println("MDNS responder started"); + } + + server.on("/", handleRoot); + + server.on("/inline", []() { + server.send(200, "text/plain", "this works as well"); + }); + + server.on("/gif", []() { + static const uint8_t gif[] = { + 0x47, 0x49, 0x46, 0x38, 0x37, 0x61, 0x10, 0x00, 0x10, 0x00, 0x80, 0x01, + 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x2c, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x10, 0x00, 0x00, 0x02, 0x19, 0x8c, 0x8f, 0xa9, 0xcb, 0x9d, + 0x00, 0x5f, 0x74, 0xb4, 0x56, 0xb0, 0xb0, 0xd2, 0xf2, 0x35, 0x1e, 0x4c, + 0x0c, 0x24, 0x5a, 0xe6, 0x89, 0xa6, 0x4d, 0x01, 0x00, 0x3b + }; + char gif_colored[sizeof(gif)]; + memcpy_P(gif_colored, gif, sizeof(gif)); + // Set the background to a random set of colors + gif_colored[16] = millis() % 256; + gif_colored[17] = millis() % 256; + gif_colored[18] = millis() % 256; + server.send(200, "image/gif", gif_colored, sizeof(gif_colored)); + }); + + server.onNotFound(handleNotFound); + + ///////////////////////////////////////////////////////// + // Hook examples + + server.addHook([](const String & method, const String & url, WiFiClient * client, WebServer::ContentTypeFunction contentType) { + (void)method; // GET, PUT, ... + (void)url; // example: /root/myfile.html + (void)client; // the webserver tcp client connection + (void)contentType; // contentType(".html") => "text/html" + Serial.printf("A useless web hook has passed\n"); + return WebServer::CLIENT_REQUEST_CAN_CONTINUE; + }); + + server.addHook([](const String&, const String & url, WiFiClient*, WebServer::ContentTypeFunction) { + if (url.startsWith("/fail")) { + Serial.printf("An always failing web hook has been triggered\n"); + return WebServer::CLIENT_MUST_STOP; + } + return WebServer::CLIENT_REQUEST_CAN_CONTINUE; + }); + + server.addHook([](const String&, const String & url, WiFiClient * client, WebServer::ContentTypeFunction) { + if (url.startsWith("/dump")) { + Serial.printf("The dumper web hook is on the run\n"); + + // Here the request is not interpreted, so we cannot for sure + // swallow the exact amount matching the full request+content, + // hence the tcp connection cannot be handled anymore by the + auto last = millis(); + while ((millis() - last) < 500) { + char buf[32]; + size_t len = client->read((uint8_t*)buf, sizeof(buf)); + if (len > 0) { + Serial.printf("(<%d> chars)", (int)len); + Serial.write(buf, len); + last = millis(); + } + } + // Two choices: return MUST STOP and webserver will close it + // (we already have the example with '/fail' hook) + // or IS GIVEN and webserver will forget it + // trying with IS GIVEN and storing it on a dumb WiFiClient. + // check the client connection: it should not immediately be closed + // (make another '/dump' one to close the first) + Serial.printf("\nTelling server to forget this connection\n"); + static WiFiClient forgetme = *client; // stop previous one if present and transfer client refcounter + return WebServer::CLIENT_IS_GIVEN; + } + return WebServer::CLIENT_REQUEST_CAN_CONTINUE; + }); + + // Hook examples + ///////////////////////////////////////////////////////// + + server.begin(); + Serial.println("HTTP server started"); +} + +void loop(void) { + server.handleClient(); + MDNS.update(); +} diff --git a/libraries/WebServer/examples/HelloServerBearSSL/HelloServerBearSSL.ino b/libraries/WebServer/examples/HelloServerBearSSL/HelloServerBearSSL.ino new file mode 100644 index 000000000..6e4cf06a8 --- /dev/null +++ b/libraries/WebServer/examples/HelloServerBearSSL/HelloServerBearSSL.ino @@ -0,0 +1,148 @@ +/* + HelloServerBearSSL - Simple HTTPS server example + + This example demonstrates a basic WebServerSecure HTTPS server + that can serve "/" and "/inline" and generate detailed 404 (not found) + HTTP responses. Be sure to update the SSID and PASSWORD before running + to allow connection to your WiFi network. + + Adapted by Earle F. Philhower, III, from the HelloServer.ino example. + This example is released into the public domain. +*/ +#include +#include +#include +#include + +#ifndef STASSID +#define STASSID "your-ssid" +#define STAPSK "your-password" +#endif + +const char* ssid = STASSID; +const char* password = STAPSK; + +WebServerSecure server(443); +ServerSessions serverCache(5); + +static const char serverCert[] PROGMEM = R"EOF( +-----BEGIN CERTIFICATE----- +MIIDSzCCAjMCCQD2ahcfZAwXxDANBgkqhkiG9w0BAQsFADCBiTELMAkGA1UEBhMC +VVMxEzARBgNVBAgMCkNhbGlmb3JuaWExFjAUBgNVBAcMDU9yYW5nZSBDb3VudHkx +EDAOBgNVBAoMB1ByaXZhZG8xGjAYBgNVBAMMEXNlcnZlci56bGFiZWwuY29tMR8w +HQYJKoZIhvcNAQkBFhBlYXJsZUB6bGFiZWwuY29tMB4XDTE4MDMwNjA1NDg0NFoX +DTE5MDMwNjA1NDg0NFowRTELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3Rh +dGUxITAfBgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDCCASIwDQYJKoZI +hvcNAQEBBQADggEPADCCAQoCggEBAPVKBwbZ+KDSl40YCDkP6y8Sv4iNGvEOZg8Y +X7sGvf/xZH7UiCBWPFIRpNmDSaZ3yjsmFqm6sLiYSGSdrBCFqdt9NTp2r7hga6Sj +oASSZY4B9pf+GblDy5m10KDx90BFKXdPMCLT+o76Nx9PpCvw13A848wHNG3bpBgI +t+w/vJCX3bkRn8yEYAU6GdMbYe7v446hX3kY5UmgeJFr9xz1kq6AzYrMt/UHhNzO +S+QckJaY0OGWvmTNspY3xCbbFtIDkCdBS8CZAw+itnofvnWWKQEXlt6otPh5njwy ++O1t/Q+Z7OMDYQaH02IQx3188/kW3FzOY32knER1uzjmRO+jhA8CAwEAATANBgkq +hkiG9w0BAQsFAAOCAQEAnDrROGRETB0woIcI1+acY1yRq4yAcH2/hdq2MoM+DCyM +E8CJaOznGR9ND0ImWpTZqomHOUkOBpvu7u315blQZcLbL1LfHJGRTCHVhvVrcyEb +fWTnRtAQdlirUm/obwXIitoz64VSbIVzcqqfg9C6ZREB9JbEX98/9Wp2gVY+31oC +JfUvYadSYxh3nblvA4OL+iEZiW8NE3hbW6WPXxvS7Euge0uWMPc4uEcnsE0ZVG3m ++TGimzSdeWDvGBRWZHXczC2zD4aoE5vrl+GD2i++c6yjL/otHfYyUpzUfbI2hMAA +5tAF1D5vAAwA8nfPysumlLsIjohJZo4lgnhB++AlOg== +-----END CERTIFICATE----- +)EOF"; + +static const char serverKey[] PROGMEM = R"EOF( +-----BEGIN RSA PRIVATE KEY----- +MIIEpQIBAAKCAQEA9UoHBtn4oNKXjRgIOQ/rLxK/iI0a8Q5mDxhfuwa9//FkftSI +IFY8UhGk2YNJpnfKOyYWqbqwuJhIZJ2sEIWp2301OnavuGBrpKOgBJJljgH2l/4Z +uUPLmbXQoPH3QEUpd08wItP6jvo3H0+kK/DXcDzjzAc0bdukGAi37D+8kJfduRGf +zIRgBToZ0xth7u/jjqFfeRjlSaB4kWv3HPWSroDNisy39QeE3M5L5ByQlpjQ4Za+ +ZM2yljfEJtsW0gOQJ0FLwJkDD6K2eh++dZYpAReW3qi0+HmePDL47W39D5ns4wNh +BofTYhDHfXzz+RbcXM5jfaScRHW7OOZE76OEDwIDAQABAoIBAQDKov5NFbNFQNR8 +djcM1O7Is6dRaqiwLeH4ZH1pZ3d9QnFwKanPdQ5eCj9yhfhJMrr5xEyCqT0nMn7T +yEIGYDXjontfsf8WxWkH2TjvrfWBrHOIOx4LJEvFzyLsYxiMmtZXvy6YByD+Dw2M +q2GH/24rRdI2klkozIOyazluTXU8yOsSGxHr/aOa9/sZISgLmaGOOuKI/3Zqjdhr +eHeSqoQFt3xXa8jw01YubQUDw/4cv9rk2ytTdAoQUimiKtgtjsggpP1LTq4xcuqN +d4jWhTcnorWpbD2cVLxrEbnSR3VuBCJEZv5axg5ZPxLEnlcId8vMtvTRb5nzzszn +geYUWDPhAoGBAPyKVNqqwQl44oIeiuRM2FYenMt4voVaz3ExJX2JysrG0jtCPv+Y +84R6Cv3nfITz3EZDWp5sW3OwoGr77lF7Tv9tD6BptEmgBeuca3SHIdhG2MR+tLyx +/tkIAarxQcTGsZaSqra3gXOJCMz9h2P5dxpdU+0yeMmOEnAqgQ8qtNBfAoGBAPim +RAtnrd0WSlCgqVGYFCvDh1kD5QTNbZc+1PcBHbVV45EmJ2fLXnlDeplIZJdYxmzu +DMOxZBYgfeLY9exje00eZJNSj/csjJQqiRftrbvYY7m5njX1kM5K8x4HlynQTDkg +rtKO0YZJxxmjRTbFGMegh1SLlFLRIMtehNhOgipRAoGBAPnEEpJGCS9GGLfaX0HW +YqwiEK8Il12q57mqgsq7ag7NPwWOymHesxHV5mMh/Dw+NyBi4xAGWRh9mtrUmeqK +iyICik773Gxo0RIqnPgd4jJWN3N3YWeynzulOIkJnSNx5BforOCTc3uCD2s2YB5X +jx1LKoNQxLeLRN8cmpIWicf/AoGBANjRSsZTKwV9WWIDJoHyxav/vPb+8WYFp8lZ +zaRxQbGM6nn4NiZI7OF62N3uhWB/1c7IqTK/bVHqFTuJCrCNcsgld3gLZ2QWYaMV +kCPgaj1BjHw4AmB0+EcajfKilcqtSroJ6MfMJ6IclVOizkjbByeTsE4lxDmPCDSt +/9MKanBxAoGAY9xo741Pn9WUxDyRplww606ccdNf/ksHWNc/Y2B5SPwxxSnIq8nO +j01SmsCUYVFAgZVOTiiycakjYLzxlc6p8BxSVqy6LlJqn95N8OXoQ+bkwUux/ekg +gz5JWYhbD6c38khSzJb0pNXCo3EuYAVa36kDM96k1BtWuhRS10Q1VXk= +-----END RSA PRIVATE KEY----- +)EOF"; + + +const int led = LED_BUILTIN; + +void handleRoot() { + digitalWrite(led, 1); + server.send(200, "text/plain", "Hello from the Pico W over HTTPS!"); + digitalWrite(led, 0); +} + +void handleNotFound() { + digitalWrite(led, 1); + String message = "File Not Found\n\n"; + message += "URI: "; + message += server.uri(); + message += "\nMethod: "; + message += (server.method() == HTTP_GET) ? "GET" : "POST"; + message += "\nArguments: "; + message += server.args(); + message += "\n"; + for (uint8_t i = 0; i < server.args(); i++) { message += " " + server.argName(i) + ": " + server.arg(i) + "\n"; } + server.send(404, "text/plain", message); + digitalWrite(led, 0); +} + +void setup(void) { + pinMode(led, OUTPUT); + digitalWrite(led, 0); + Serial.begin(115200); + WiFi.begin(ssid, password); + Serial.println(""); + + // Wait for connection + while (WiFi.status() != WL_CONNECTED) { + delay(500); + Serial.print("."); + } + + configTime(3 * 3600, 0, "pool.ntp.org", "time.nist.gov"); + + Serial.println(""); + Serial.print("Connected to "); + Serial.println(ssid); + Serial.print("IP address: "); + Serial.println(WiFi.localIP()); + + if (MDNS.begin("picow")) { Serial.println("MDNS responder started"); } + + server.getServer().setRSACert(new BearSSL::X509List(serverCert), new BearSSL::PrivateKey(serverKey)); + + // Cache SSL sessions to accelerate the TLS handshake. + server.getServer().setCache(&serverCache); + + server.on("/", handleRoot); + + server.on("/inline", []() { + server.send(200, "text/plain", "this works as well"); + }); + + server.onNotFound(handleNotFound); + + server.begin(); + Serial.println("HTTPS server started"); +} + +void loop(void) { + server.handleClient(); + MDNS.update(); +} diff --git a/libraries/WebServer/examples/HttpAdvancedAuth/HttpAdvancedAuth.ino b/libraries/WebServer/examples/HttpAdvancedAuth/HttpAdvancedAuth.ino new file mode 100644 index 000000000..07c8b2c90 --- /dev/null +++ b/libraries/WebServer/examples/HttpAdvancedAuth/HttpAdvancedAuth.ino @@ -0,0 +1,64 @@ +/* + HTTP Advanced Authentication example + Created Mar 16, 2017 by Ahmed El-Sharnoby. + This example code is in the public domain. +*/ + +#include +#include +#include +#include + +#ifndef STASSID +#define STASSID "your-ssid" +#define STAPSK "your-password" +#endif + +const char* ssid = STASSID; +const char* password = STAPSK; + +WebServer server(80); + +const char* www_username = "admin"; +const char* www_password = "picow"; +// allows you to set the realm of authentication Default:"Login Required" +const char* www_realm = "Custom Auth Realm"; +// the Content of the HTML response in case of Unautherized Access Default:empty +String authFailResponse = "Authentication Failed"; + +void setup() { + Serial.begin(115200); + WiFi.mode(WIFI_STA); + WiFi.begin(ssid, password); + if (WiFi.waitForConnectResult() != WL_CONNECTED) { + Serial.println("WiFi Connect Failed! Rebooting..."); + delay(1000); + rp2040.restart(); + } + ArduinoOTA.begin(); + + server.on("/", []() { + if (!server.authenticate(www_username, www_password)) + // Basic Auth Method with Custom realm and Failure Response + // return server.requestAuthentication(BASIC_AUTH, www_realm, authFailResponse); + // Digest Auth Method with realm="Login Required" and empty Failure Response + // return server.requestAuthentication(DIGEST_AUTH); + // Digest Auth Method with Custom realm and empty Failure Response + // return server.requestAuthentication(DIGEST_AUTH, www_realm); + // Digest Auth Method with Custom realm and Failure Response + { + return server.requestAuthentication(DIGEST_AUTH, www_realm, authFailResponse); + } + server.send(200, "text/plain", "Login OK"); + }); + server.begin(); + + Serial.print("Open http://"); + Serial.print(WiFi.localIP()); + Serial.println("/ in your browser to see it working"); +} + +void loop() { + ArduinoOTA.handle(); + server.handleClient(); +} diff --git a/libraries/WebServer/examples/HttpBasicAuth/HttpBasicAuth.ino b/libraries/WebServer/examples/HttpBasicAuth/HttpBasicAuth.ino new file mode 100644 index 000000000..67c1bf859 --- /dev/null +++ b/libraries/WebServer/examples/HttpBasicAuth/HttpBasicAuth.ino @@ -0,0 +1,46 @@ +#include +#include +#include +#include + +#ifndef STASSID +#define STASSID "your-ssid" +#define STAPSK "your-password" +#endif + +const char* ssid = STASSID; +const char* password = STAPSK; + +WebServer server(80); + +const char* www_username = "admin"; +const char* www_password = "picow"; + +void setup() { + Serial.begin(115200); + WiFi.mode(WIFI_STA); + WiFi.begin(ssid, password); + if (WiFi.waitForConnectResult() != WL_CONNECTED) { + Serial.println("WiFi Connect Failed! Rebooting..."); + delay(1000); + rp2040.restart(); + } + ArduinoOTA.begin(); + + server.on("/", []() { + if (!server.authenticate(www_username, www_password)) { + return server.requestAuthentication(); + } + server.send(200, "text/plain", "Login OK"); + }); + server.begin(); + + Serial.print("Open http://"); + Serial.print(WiFi.localIP()); + Serial.println("/ in your browser to see it working"); +} + +void loop() { + ArduinoOTA.handle(); + server.handleClient(); +} diff --git a/libraries/WebServer/examples/PostServer/PostServer.ino b/libraries/WebServer/examples/PostServer/PostServer.ino new file mode 100644 index 000000000..7aff4a1de --- /dev/null +++ b/libraries/WebServer/examples/PostServer/PostServer.ino @@ -0,0 +1,126 @@ +#include +#include +#include +#include + +#ifndef STASSID +#define STASSID "your-ssid" +#define STAPSK "your-password" +#endif + +const char* ssid = STASSID; +const char* password = STAPSK; + +WebServer server(80); + +const int led = LED_BUILTIN; + +const String postForms = "\ + \ + Pico-W Web Server POST handling\ + \ + \ + \ +

POST plain text to /postplain/


\ +
\ +
\ + \ +
\ +

POST form data to /postform/


\ +
\ +
\ + \ +
\ + \ +"; + +void handleRoot() { + digitalWrite(led, 1); + server.send(200, "text/html", postForms); + digitalWrite(led, 0); +} + +void handlePlain() { + if (server.method() != HTTP_POST) { + digitalWrite(led, 1); + server.send(405, "text/plain", "Method Not Allowed"); + digitalWrite(led, 0); + } else { + digitalWrite(led, 1); + server.send(200, "text/plain", "POST body was:\n" + server.arg("plain")); + digitalWrite(led, 0); + } +} + +void handleForm() { + if (server.method() != HTTP_POST) { + digitalWrite(led, 1); + server.send(405, "text/plain", "Method Not Allowed"); + digitalWrite(led, 0); + } else { + digitalWrite(led, 1); + String message = "POST form was:\n"; + for (uint8_t i = 0; i < server.args(); i++) { + message += " " + server.argName(i) + ": " + server.arg(i) + "\n"; + } + server.send(200, "text/plain", message); + digitalWrite(led, 0); + } +} + +void handleNotFound() { + digitalWrite(led, 1); + String message = "File Not Found\n\n"; + message += "URI: "; + message += server.uri(); + message += "\nMethod: "; + message += (server.method() == HTTP_GET) ? "GET" : "POST"; + message += "\nArguments: "; + message += server.args(); + message += "\n"; + for (uint8_t i = 0; i < server.args(); i++) { + message += " " + server.argName(i) + ": " + server.arg(i) + "\n"; + } + server.send(404, "text/plain", message); + digitalWrite(led, 0); +} + +void setup(void) { + pinMode(led, OUTPUT); + digitalWrite(led, 0); + Serial.begin(115200); + WiFi.begin(ssid, password); + Serial.println(""); + + // Wait for connection + while (WiFi.status() != WL_CONNECTED) { + delay(500); + Serial.print("."); + } + Serial.println(""); + Serial.print("Connected to "); + Serial.println(ssid); + Serial.print("IP address: "); + Serial.println(WiFi.localIP()); + + if (MDNS.begin("picow")) { + Serial.println("MDNS responder started"); + } + + server.on("/", handleRoot); + + server.on("/postplain/", handlePlain); + + server.on("/postform/", handleForm); + + server.onNotFound(handleNotFound); + + server.begin(); + Serial.println("HTTP server started"); +} + +void loop(void) { + server.handleClient(); +} diff --git a/libraries/WebServer/examples/SimpleAuthentication/SimpleAuthentication.ino b/libraries/WebServer/examples/SimpleAuthentication/SimpleAuthentication.ino new file mode 100644 index 000000000..cc7025e9e --- /dev/null +++ b/libraries/WebServer/examples/SimpleAuthentication/SimpleAuthentication.ino @@ -0,0 +1,134 @@ +#include +#include +#include + +#ifndef STASSID +#define STASSID "your-ssid" +#define STAPSK "your-password" +#endif + +const char* ssid = STASSID; +const char* password = STAPSK; + +WebServer server(80); + +// Check if header is present and correct +bool is_authenticated() { + Serial.println("Enter is_authenticated"); + if (server.hasHeader("Cookie")) { + Serial.print("Found cookie: "); + String cookie = server.header("Cookie"); + Serial.println(cookie); + if (cookie.indexOf("PICOSESSIONID=1") != -1) { + Serial.println("Authentication Successful"); + return true; + } + } + Serial.println("Authentication Failed"); + return false; +} + +// login page, also called for disconnect +void handleLogin() { + String msg; + if (server.hasHeader("Cookie")) { + Serial.print("Found cookie: "); + String cookie = server.header("Cookie"); + Serial.println(cookie); + } + if (server.hasArg("DISCONNECT")) { + Serial.println("Disconnection"); + server.sendHeader("Location", "/login"); + server.sendHeader("Cache-Control", "no-cache"); + server.sendHeader("Set-Cookie", "PICOSESSIONID=0"); + server.send(301); + return; + } + if (server.hasArg("USERNAME") && server.hasArg("PASSWORD")) { + if (server.arg("USERNAME") == "admin" && server.arg("PASSWORD") == "admin") { + server.sendHeader("Location", "/"); + server.sendHeader("Cache-Control", "no-cache"); + server.sendHeader("Set-Cookie", "PICOSESSIONID=1"); + server.send(301); + Serial.println("Log in Successful"); + return; + } + msg = "Wrong username/password! try again."; + Serial.println("Log in Failed"); + } + String content = "
To log in, please use : admin/admin
"; + content += "User:
"; + content += "Password:
"; + content += "
" + msg + "
"; + content += "You also can go here"; + server.send(200, "text/html", content); +} + +// root page can be accessed only if authentication is ok +void handleRoot() { + Serial.println("Enter handleRoot"); + String header; + if (!is_authenticated()) { + server.sendHeader("Location", "/login"); + server.sendHeader("Cache-Control", "no-cache"); + server.send(301); + return; + } + String content = "

hello, you successfully connected to Pico W!


"; + if (server.hasHeader("User-Agent")) { + content += "the user agent used is : " + server.header("User-Agent") + "

"; + } + content += "You can access this page until you disconnect"; + server.send(200, "text/html", content); +} + +// no need authentication +void handleNotFound() { + String message = "File Not Found\n\n"; + message += "URI: "; + message += server.uri(); + message += "\nMethod: "; + message += (server.method() == HTTP_GET) ? "GET" : "POST"; + message += "\nArguments: "; + message += server.args(); + message += "\n"; + for (uint8_t i = 0; i < server.args(); i++) { + message += " " + server.argName(i) + ": " + server.arg(i) + "\n"; + } + server.send(404, "text/plain", message); +} + +void setup(void) { + Serial.begin(115200); + WiFi.mode(WIFI_STA); + WiFi.begin(ssid, password); + Serial.println(""); + + // Wait for connection + while (WiFi.status() != WL_CONNECTED) { + delay(500); + Serial.print("."); + } + Serial.println(""); + Serial.print("Connected to "); + Serial.println(ssid); + Serial.print("IP address: "); + Serial.println(WiFi.localIP()); + + + server.on("/", handleRoot); + server.on("/login", handleLogin); + server.on("/inline", []() { + server.send(200, "text/plain", "this works without need of authentication"); + }); + + server.onNotFound(handleNotFound); + // ask server to track these headers + server.collectHeaders("User-Agent", "Cookie"); + server.begin(); + Serial.println("HTTP server started"); +} + +void loop(void) { + server.handleClient(); +} diff --git a/libraries/WebServer/examples/WebUpdate/WebUpdate.ino b/libraries/WebServer/examples/WebUpdate/WebUpdate.ino new file mode 100644 index 000000000..eec5cf03e --- /dev/null +++ b/libraries/WebServer/examples/WebUpdate/WebUpdate.ino @@ -0,0 +1,77 @@ +/* + To upload through terminal you can use: curl -F "image=@firmware.bin" picow-webupdate.local/update +*/ + +#include +#include +#include +#include +#include + +#ifndef STASSID +#define STASSID "your-ssid" +#define STAPSK "your-password" +#endif + +const char* host = "picow-webupdate"; +const char* ssid = STASSID; +const char* password = STAPSK; + +WebServer server(80); +const char* serverIndex = "
"; + +void setup(void) { + Serial.begin(115200); + Serial.println(); + Serial.println("Booting Sketch..."); + WiFi.mode(WIFI_STA); + WiFi.begin(ssid, password); + if (WiFi.waitForConnectResult() == WL_CONNECTED) { + MDNS.begin(host); + server.on("/", HTTP_GET, []() { + server.sendHeader("Connection", "close"); + server.send(200, "text/html", serverIndex); + }); + server.on( + "/update", HTTP_POST, []() { + server.sendHeader("Connection", "close"); + server.send(200, "text/plain", (Update.hasError()) ? "FAIL" : "OK"); + rp2040.restart(); + }, + []() { + HTTPUpload& upload = server.upload(); + if (upload.status == UPLOAD_FILE_START) { + WiFiUDP::stopAll(); + Serial.printf("Update: %s\n", upload.filename.c_str()); + FSInfo64 i; + LittleFS.begin(); + LittleFS.info64(i); + uint32_t maxSketchSpace = i.totalBytes - i.usedBytes; + if (!Update.begin(maxSketchSpace)) { // start with max available size + Update.printError(Serial); + } + } else if (upload.status == UPLOAD_FILE_WRITE) { + if (Update.write(upload.buf, upload.currentSize) != upload.currentSize) { + Update.printError(Serial); + } + } else if (upload.status == UPLOAD_FILE_END) { + if (Update.end(true)) { // true to set the size to the current progress + Serial.printf("Update Success: %u\nRebooting...\n", upload.totalSize); + } else { + Update.printError(Serial); + } + } + }); + server.begin(); + MDNS.addService("http", "tcp", 80); + + Serial.printf("Ready! Open http://%s.local in your browser\n", host); + } else { + Serial.println("WiFi Failed"); + } +} + +void loop(void) { + server.handleClient(); + MDNS.update(); +} diff --git a/libraries/WebServer/keywords.txt b/libraries/WebServer/keywords.txt new file mode 100644 index 000000000..65082f7ee --- /dev/null +++ b/libraries/WebServer/keywords.txt @@ -0,0 +1,39 @@ +####################################### +# Syntax Coloring Map For Ultrasound +####################################### + +####################################### +# Datatypes (KEYWORD1) +####################################### + +WebServer KEYWORD1 +WebServerSecure KEYWORD1 +HTTPServer KEYWORD1 +HTTPMethod KEYWORD1 + +####################################### +# Methods and Functions (KEYWORD2) +####################################### + +begin KEYWORD2 +handleClient KEYWORD2 +on KEYWORD2 +addHandler KEYWORD2 +uri KEYWORD2 +method KEYWORD2 +client KEYWORD2 +send KEYWORD2 +arg KEYWORD2 +argName KEYWORD2 +args KEYWORD2 +hasArg KEYWORD2 +onNotFound KEYWORD2 + +####################################### +# Constants (LITERAL1) +####################################### + +HTTP_GET LITERAL1 +HTTP_POST LITERAL1 +HTTP_ANY LITERAL1 +CONTENT_LENGTH_UNKNOWN LITERAL1 diff --git a/libraries/WebServer/library.properties b/libraries/WebServer/library.properties new file mode 100644 index 000000000..5724d79b8 --- /dev/null +++ b/libraries/WebServer/library.properties @@ -0,0 +1,10 @@ +name=WebServer +version=2.0.0 +author=Ivan Grokhotkov +maintainer=Earle F. Philhower, III +sentence=Simple web server library +paragraph=The library supports HTTP(S) GET and POST requests, provides argument parsing, handles one client at a time. +category=Communication +url=https://github.com/earlephilhower/arduino-pico +architectures=rp2040 +dot_a_linkage=true diff --git a/libraries/WebServer/src/ESP8266WebServer.h b/libraries/WebServer/src/ESP8266WebServer.h new file mode 100644 index 000000000..4fe66a029 --- /dev/null +++ b/libraries/WebServer/src/ESP8266WebServer.h @@ -0,0 +1,4 @@ +// Since things may just work, we'll redirect for now +#include "WebServer.h" + +using ESP8266WebServer = WebServer; diff --git a/libraries/WebServer/src/HTTPServer.cpp b/libraries/WebServer/src/HTTPServer.cpp new file mode 100644 index 000000000..cf03f29fb --- /dev/null +++ b/libraries/WebServer/src/HTTPServer.cpp @@ -0,0 +1,677 @@ +/* + HTTPServer.cpp - Dead simple web-server. + Supports only one simultaneous client, knows how to handle GET and POST. + + Copyright (c) 2014 Ivan Grokhotkov. All rights reserved. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + Modified 8 May 2015 by Hristo Gochkov (proper post and file upload handling) +*/ + +#include +#include +#include "WiFiServer.h" +#include "WiFiClient.h" +#include "HTTPServer.h" +#include "FS.h" +#include "detail/RequestHandlersImpl.h" +#include + +#ifndef log_e +#define log_e(...) +#define log_w(...) +#define log_v(...) +#endif + +static const char AUTHORIZATION_HEADER[] = "Authorization"; +static const char qop_auth[] PROGMEM = "qop=auth"; +static const char qop_auth_quoted[] PROGMEM = "qop=\"auth\""; +static const char WWW_Authenticate[] = "WWW-Authenticate"; +static const char Content_Length[] = "Content-Length"; + +HTTPServer::HTTPServer() + : _corsEnabled(false) + , _currentClient(nullptr) + , _currentMethod(HTTP_ANY) + , _currentVersion(0) + , _currentStatus(HC_NONE) + , _statusChange(0) + , _nullDelay(true) + , _currentHandler(nullptr) + , _firstHandler(nullptr) + , _lastHandler(nullptr) + , _currentArgCount(0) + , _currentArgs(nullptr) + , _postArgsLen(0) + , _postArgs(nullptr) + , _headerKeysCount(0) + , _currentHeaders(nullptr) + , _contentLength(0) + , _clientContentLength(0) + , _chunked(false) { + log_v("HTTPServer::HTTPServer()"); +} + +HTTPServer::~HTTPServer() { + if (_currentHeaders) { + delete[]_currentHeaders; + } + RequestHandler* handler = _firstHandler; + while (handler) { + RequestHandler* next = handler->next(); + delete handler; + handler = next; + } +} + +String HTTPServer::_extractParam(String& authReq, const String& param, const char delimit) { + int _begin = authReq.indexOf(param); + if (_begin == -1) { + return ""; + } + return authReq.substring(_begin + param.length(), authReq.indexOf(delimit, _begin + param.length())); +} + +static String md5str(String &in) { + char out[33] = {0}; + MD5Builder _ctx; + uint8_t i; + uint8_t _buf[16]; + memset(_buf, 0x00, 16); + _ctx.begin(); + _ctx.add((const uint8_t *)in.c_str(), in.length()); + _ctx.calculate(); + _ctx.getBytes((uint8_t *)_buf); + for (i = 0; i < 16; i++) { + sprintf(out + (i * 2), "%02x", _buf[i]); + } + out[32] = 0; + return String(out); +} + +bool HTTPServer::authenticate(const char * username, const char * password) { + if (hasHeader(FPSTR(AUTHORIZATION_HEADER))) { + String authReq = header(FPSTR(AUTHORIZATION_HEADER)); + if (authReq.startsWith(F("Basic"))) { + authReq = authReq.substring(6); + authReq.trim(); + char toencodeLen = strlen(username) + strlen(password) + 1; + char *toencode = new char[toencodeLen + 1]; + if (toencode == nullptr) { + return false; + } + char *encoded = new char[base64_encode_expected_len(toencodeLen) + 1]; + if (encoded == nullptr) { + delete[] toencode; + return false; + } + sprintf(toencode, "%s:%s", username, password); + if (base64_encode_chars(toencode, toencodeLen, encoded) > 0 && authReq == encoded) { + delete[] toencode; + delete[] encoded; + return true; + } + delete[] toencode; + delete[] encoded; + } else if (authReq.startsWith(F("Digest"))) { + authReq = authReq.substring(7); + log_v("%s", authReq.c_str()); + String _username = _extractParam(authReq, F("username=\""), '\"'); + if (!_username.length() || _username != String(username)) { + return false; + } + // extracting required parameters for RFC 2069 simpler Digest + String _realm = _extractParam(authReq, F("realm=\""), '\"'); + String _nonce = _extractParam(authReq, F("nonce=\""), '\"'); + String _uri = _extractParam(authReq, F("uri=\""), '\"'); + String _response = _extractParam(authReq, F("response=\""), '\"'); + String _opaque = _extractParam(authReq, F("opaque=\""), '\"'); + + if ((!_realm.length()) || (!_nonce.length()) || (!_uri.length()) || (!_response.length()) || (!_opaque.length())) { + return false; + } + if ((_opaque != _sopaque) || (_nonce != _snonce) || (_realm != _srealm)) { + return false; + } + // parameters for the RFC 2617 newer Digest + String _nc, _cnonce; + if (authReq.indexOf(FPSTR(qop_auth)) != -1 || authReq.indexOf(FPSTR(qop_auth_quoted)) != -1) { + _nc = _extractParam(authReq, F("nc="), ','); + _cnonce = _extractParam(authReq, F("cnonce=\""), '\"'); + } + String _H1 = md5str(String(username) + ':' + _realm + ':' + String(password)); + log_v("Hash of user:realm:pass=%s", _H1.c_str()); + String _H2 = ""; + if (_currentMethod == HTTP_GET) { + _H2 = md5str(String(F("GET:")) + _uri); + } else if (_currentMethod == HTTP_POST) { + _H2 = md5str(String(F("POST:")) + _uri); + } else if (_currentMethod == HTTP_PUT) { + _H2 = md5str(String(F("PUT:")) + _uri); + } else if (_currentMethod == HTTP_DELETE) { + _H2 = md5str(String(F("DELETE:")) + _uri); + } else { + _H2 = md5str(String(F("GET:")) + _uri); + } + log_v("Hash of GET:uri=%s", _H2.c_str()); + String _responsecheck = ""; + if (authReq.indexOf(FPSTR(qop_auth)) != -1 || authReq.indexOf(FPSTR(qop_auth_quoted)) != -1) { + _responsecheck = md5str(_H1 + ':' + _nonce + ':' + _nc + ':' + _cnonce + F(":auth:") + _H2); + } else { + _responsecheck = md5str(_H1 + ':' + _nonce + ':' + _H2); + } + log_v("The Proper response=%s", _responsecheck.c_str()); + if (_response == _responsecheck) { + return true; + } + } + } + return false; +} + +String HTTPServer::_getRandomHexString() { + char buffer[33]; // buffer to hold 32 Hex Digit + /0 + int i; + for (i = 0; i < 4; i++) { + sprintf(buffer + (i * 8), "%08lx", rp2040.hwrand32()); + } + return String(buffer); +} + +void HTTPServer::requestAuthentication(HTTPAuthMethod mode, const char* realm, const String& authFailMsg) { + if (realm == nullptr) { + _srealm = String(F("Login Required")); + } else { + _srealm = String(realm); + } + if (mode == BASIC_AUTH) { + sendHeader(String(FPSTR(WWW_Authenticate)), String(F("Basic realm=\"")) + _srealm + String(F("\""))); + } else { + _snonce = _getRandomHexString(); + _sopaque = _getRandomHexString(); + sendHeader(String(FPSTR(WWW_Authenticate)), String(F("Digest realm=\"")) + _srealm + String(F("\", qop=\"auth\", nonce=\"")) + _snonce + String(F("\", opaque=\"")) + _sopaque + String(F("\""))); + } + using namespace mime; + send(401, String(FPSTR(mimeTable[html].mimeType)), authFailMsg); +} + +void HTTPServer::on(const Uri &uri, HTTPServer::THandlerFunction handler) { + on(uri, HTTP_ANY, handler); +} + +void HTTPServer::on(const Uri &uri, HTTPMethod method, HTTPServer::THandlerFunction fn) { + on(uri, method, fn, _fileUploadHandler); +} + +void HTTPServer::on(const Uri &uri, HTTPMethod method, HTTPServer::THandlerFunction fn, HTTPServer::THandlerFunction ufn) { + _addRequestHandler(new FunctionRequestHandler(fn, ufn, uri, method)); +} + +void HTTPServer::addHandler(RequestHandler* handler) { + _addRequestHandler(handler); +} + +void HTTPServer::_addRequestHandler(RequestHandler* handler) { + if (!_lastHandler) { + _firstHandler = handler; + _lastHandler = handler; + } else { + _lastHandler->next(handler); + _lastHandler = handler; + } +} + +void HTTPServer::serveStatic(const char* uri, FS& fs, const char* path, const char* cache_header) { + _addRequestHandler(new StaticRequestHandler(fs, path, uri, cache_header)); +} + +void HTTPServer::httpHandleClient() { + bool keepCurrentClient = false; + bool callYield = false; + + if (_currentClient->connected()) { + switch (_currentStatus) { + case HC_NONE: + // No-op to avoid C++ compiler warning + break; + case HC_WAIT_READ: + // Wait for data from client to become available + if (_currentClient->available()) { + switch (_parseRequest(_currentClient)) { + case CLIENT_REQUEST_CAN_CONTINUE: + // Because HTTP_MAX_SEND_WAIT is expressed in milliseconds, it must be divided by 1000 + _currentClient->setTimeout(HTTP_MAX_SEND_WAIT / 1000); + _contentLength = CONTENT_LENGTH_NOT_SET; + _handleRequest(); + /* fallthrough */ + case CLIENT_REQUEST_IS_HANDLED: + if (_currentClient->connected() || _currentClient->available()) { + _currentStatus = HC_WAIT_CLOSE; + _statusChange = millis(); + keepCurrentClient = true; + } else { + log_v("webserver: peer has closed after served\n"); + } + break; + case CLIENT_MUST_STOP: + log_v("Close client\n"); + _currentClient->stop(); + break; + case CLIENT_IS_GIVEN: + // client must not be stopped but must not be handled here anymore + // (example: tcp connection given to websocket) + log_v("Give client\n"); + break; + } // switch _parseRequest() + } else { // !_currentClient->available() + if (millis() - _statusChange <= HTTP_MAX_DATA_WAIT) { + keepCurrentClient = true; + } + callYield = true; + } + break; + case HC_WAIT_CLOSE: + // Wait for client to close the connection + if (millis() - _statusChange <= HTTP_MAX_CLOSE_WAIT) { + keepCurrentClient = true; + callYield = true; + } + } + } + + if (!keepCurrentClient) { + if (_currentClient) { + delete _currentClient; + _currentClient = nullptr; + } + _currentStatus = HC_NONE; + _currentUpload.reset(); + } + + if (callYield) { + yield(); + } +} + +void HTTPServer::httpClose() { + _currentStatus = HC_NONE; + if (!_headerKeysCount) { + collectHeaders(0, 0); + } +} + +void HTTPServer::sendHeader(const String& name, const String& value, bool first) { + String headerLine = name; + headerLine += F(": "); + headerLine += value; + headerLine += "\r\n"; + + if (first) { + _responseHeaders = headerLine + _responseHeaders; + } else { + _responseHeaders += headerLine; + } +} + +void HTTPServer::setContentLength(const size_t contentLength) { + _contentLength = contentLength; +} + +void HTTPServer::enableDelay(boolean value) { + _nullDelay = value; +} + +void HTTPServer::enableCORS(boolean value) { + _corsEnabled = value; +} + +void HTTPServer::enableCrossOrigin(boolean value) { + enableCORS(value); +} + +void HTTPServer::_prepareHeader(String& response, int code, const char* content_type, size_t contentLength) { + response = String(F("HTTP/1.")) + String(_currentVersion) + ' '; + response += String(code); + response += ' '; + response += _responseCodeToString(code); + response += "\r\n"; + + using namespace mime; + if (!content_type) { + content_type = mimeTable[html].mimeType; + } + + sendHeader(String(F("Content-Type")), String(FPSTR(content_type)), true); + if (_contentLength == CONTENT_LENGTH_NOT_SET) { + sendHeader(String(FPSTR(Content_Length)), String(contentLength)); + } else if (_contentLength != CONTENT_LENGTH_UNKNOWN) { + sendHeader(String(FPSTR(Content_Length)), String(_contentLength)); + } else if (_contentLength == CONTENT_LENGTH_UNKNOWN && _currentVersion) { //HTTP/1.1 or above client + //let's do chunked + _chunked = true; + sendHeader(String(F("Accept-Ranges")), String(F("none"))); + sendHeader(String(F("Transfer-Encoding")), String(F("chunked"))); + } + if (_corsEnabled) { + sendHeader(String(FPSTR("Access-Control-Allow-Origin")), String("*")); + sendHeader(String(FPSTR("Access-Control-Allow-Methods")), String("*")); + sendHeader(String(FPSTR("Access-Control-Allow-Headers")), String("*")); + } + sendHeader(String(F("Connection")), String(F("close"))); + + response += _responseHeaders; + response += "\r\n"; + _responseHeaders = ""; +} + +void HTTPServer::send(int code, const char* content_type, const String& content) { + String header; + // Can we assume the following? + //if(code == 200 && content.length() == 0 && _contentLength == CONTENT_LENGTH_NOT_SET) + // _contentLength = CONTENT_LENGTH_UNKNOWN; + if (content.length() == 0) { + log_w("content length is zero"); + } + _prepareHeader(header, code, content_type, content.length()); + _currentClientWrite(header.c_str(), header.length()); + if (content.length()) { + sendContent(content); + } +} + +void HTTPServer::send(int code, char* content_type, const String& content) { + send(code, (const char*)content_type, content); +} + +void HTTPServer::send(int code, const String& content_type, const String& content) { + send(code, (const char*)content_type.c_str(), content); +} + +void HTTPServer::send(int code, const char* content_type, const char* content) { + send(code, content_type, content, content ? strlen(content) : 0); +} + +void HTTPServer::send(int code, const char* content_type, const char* content, size_t contentLength) { + String header; + _prepareHeader(header, code, content_type, contentLength); + _currentClientWrite(header.c_str(), header.length()); + if (contentLength) { + sendContent(content, contentLength); + } +} + +void HTTPServer::send_P(int code, PGM_P content_type, PGM_P content) { + size_t contentLength = 0; + + if (content != nullptr) { + contentLength = strlen_P(content); + } + + String header; + _prepareHeader(header, code, content_type, contentLength); + _currentClientWrite(header.c_str(), header.length()); + sendContent_P(content); +} + +void HTTPServer::send_P(int code, PGM_P content_type, PGM_P content, size_t contentLength) { + String header; + _prepareHeader(header, code, content_type, contentLength); + sendContent(header); + sendContent_P(content, contentLength); +} + +void HTTPServer::sendContent(const String& content) { + sendContent(content.c_str(), content.length()); +} + +void HTTPServer::sendContent(const char* content, size_t contentLength) { + const char * footer = "\r\n"; + if (_chunked) { + char chunkSize[11]; + sprintf(chunkSize, "%x%s", (unsigned int)contentLength, footer); + _currentClientWrite(chunkSize, strlen(chunkSize)); + } + _currentClientWrite(content, contentLength); + if (_chunked) { + _currentClient->write(footer, 2); + if (contentLength == 0) { + _chunked = false; + } + } +} + +void HTTPServer::sendContent_P(PGM_P content) { + sendContent_P(content, strlen_P(content)); +} + +void HTTPServer::sendContent_P(PGM_P content, size_t size) { + const char * footer = "\r\n"; + if (_chunked) { + char chunkSize[11]; + sprintf(chunkSize, "%x%s", (unsigned int)size, footer); + _currentClientWrite(chunkSize, strlen(chunkSize)); + } + _currentClientWrite_P(content, size); + if (_chunked) { + _currentClient->write(footer, 2); + if (size == 0) { + _chunked = false; + } + } +} + + +void HTTPServer::_streamFileCore(const size_t fileSize, const String & fileName, const String & contentType, const int code) { + using namespace mime; + setContentLength(fileSize); + if (fileName.endsWith(String(FPSTR(mimeTable[gz].endsWith))) && + contentType != String(FPSTR(mimeTable[gz].mimeType)) && + contentType != String(FPSTR(mimeTable[none].mimeType))) { + sendHeader(F("Content-Encoding"), F("gzip")); + } + send(code, contentType, ""); +} + +String HTTPServer::pathArg(unsigned int i) { + if (_currentHandler != nullptr) { + return _currentHandler->pathArg(i); + } + return ""; +} + +String HTTPServer::arg(String name) { + for (int j = 0; j < _postArgsLen; ++j) { + if (_postArgs[j].key == name) { + return _postArgs[j].value; + } + } + for (int i = 0; i < _currentArgCount; ++i) { + if (_currentArgs[i].key == name) { + return _currentArgs[i].value; + } + } + return ""; +} + +String HTTPServer::arg(int i) { + if (i < _currentArgCount) { + return _currentArgs[i].value; + } + return ""; +} + +String HTTPServer::argName(int i) { + if (i < _currentArgCount) { + return _currentArgs[i].key; + } + return ""; +} + +int HTTPServer::args() { + return _currentArgCount; +} + +bool HTTPServer::hasArg(String name) { + for (int j = 0; j < _postArgsLen; ++j) { + if (_postArgs[j].key == name) { + return true; + } + } + for (int i = 0; i < _currentArgCount; ++i) { + if (_currentArgs[i].key == name) { + return true; + } + } + return false; +} + + +String HTTPServer::header(String name) { + for (int i = 0; i < _headerKeysCount; ++i) { + if (_currentHeaders[i].key.equalsIgnoreCase(name)) { + return _currentHeaders[i].value; + } + } + return ""; +} + +void HTTPServer::collectHeaders(const char* headerKeys[], const size_t headerKeysCount) { + _headerKeysCount = headerKeysCount + 1; + if (_currentHeaders) { + delete[]_currentHeaders; + } + _currentHeaders = new RequestArgument[_headerKeysCount]; + _currentHeaders[0].key = FPSTR(AUTHORIZATION_HEADER); + for (int i = 1; i < _headerKeysCount; i++) { + _currentHeaders[i].key = headerKeys[i - 1]; + } +} + +String HTTPServer::header(int i) { + if (i < _headerKeysCount) { + return _currentHeaders[i].value; + } + return ""; +} + +String HTTPServer::headerName(int i) { + if (i < _headerKeysCount) { + return _currentHeaders[i].key; + } + return ""; +} + +int HTTPServer::headers() { + return _headerKeysCount; +} + +bool HTTPServer::hasHeader(String name) { + for (int i = 0; i < _headerKeysCount; ++i) { + if ((_currentHeaders[i].key.equalsIgnoreCase(name)) && (_currentHeaders[i].value.length() > 0)) { + return true; + } + } + return false; +} + +String HTTPServer::hostHeader() { + return _hostHeader; +} + +void HTTPServer::onFileUpload(THandlerFunction fn) { + _fileUploadHandler = fn; +} + +void HTTPServer::onNotFound(THandlerFunction fn) { + _notFoundHandler = fn; +} + +void HTTPServer::_handleRequest() { + bool handled = false; + if (!_currentHandler) { + log_e("request handler not found"); + } else { + handled = _currentHandler->handle(*this, _currentMethod, _currentUri); + if (!handled) { + log_e("request handler failed to handle request"); + } + } + if (!handled && _notFoundHandler) { + _notFoundHandler(); + handled = true; + } + if (!handled) { + using namespace mime; + send(404, String(FPSTR(mimeTable[html].mimeType)), String(F("Not found: ")) + _currentUri); + handled = true; + } + if (handled) { + _finalizeResponse(); + } + _currentUri = ""; +} + + +void HTTPServer::_finalizeResponse() { + if (_chunked) { + sendContent(""); + } +} + +String HTTPServer::_responseCodeToString(int code) { + switch (code) { + case 100: return F("Continue"); + case 101: return F("Switching Protocols"); + case 200: return F("OK"); + case 201: return F("Created"); + case 202: return F("Accepted"); + case 203: return F("Non-Authoritative Information"); + case 204: return F("No Content"); + case 205: return F("Reset Content"); + case 206: return F("Partial Content"); + case 300: return F("Multiple Choices"); + case 301: return F("Moved Permanently"); + case 302: return F("Found"); + case 303: return F("See Other"); + case 304: return F("Not Modified"); + case 305: return F("Use Proxy"); + case 307: return F("Temporary Redirect"); + case 400: return F("Bad Request"); + case 401: return F("Unauthorized"); + case 402: return F("Payment Required"); + case 403: return F("Forbidden"); + case 404: return F("Not Found"); + case 405: return F("Method Not Allowed"); + case 406: return F("Not Acceptable"); + case 407: return F("Proxy Authentication Required"); + case 408: return F("Request Time-out"); + case 409: return F("Conflict"); + case 410: return F("Gone"); + case 411: return F("Length Required"); + case 412: return F("Precondition Failed"); + case 413: return F("Request Entity Too Large"); + case 414: return F("Request-URI Too Large"); + case 415: return F("Unsupported Media Type"); + case 416: return F("Requested range not satisfiable"); + case 417: return F("Expectation Failed"); + case 500: return F("Internal Server Error"); + case 501: return F("Not Implemented"); + case 502: return F("Bad Gateway"); + case 503: return F("Service Unavailable"); + case 504: return F("Gateway Time-out"); + case 505: return F("HTTP Version not supported"); + default: return F(""); + } +} diff --git a/libraries/WebServer/src/HTTPServer.h b/libraries/WebServer/src/HTTPServer.h new file mode 100644 index 000000000..f71dd503e --- /dev/null +++ b/libraries/WebServer/src/HTTPServer.h @@ -0,0 +1,275 @@ +/* + HTTPServer.h - Dead simple web-server. + Supports only one simultaneous client, knows how to handle GET and POST. + + Copyright (c) 2014 Ivan Grokhotkov. All rights reserved. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + Modified 8 May 2015 by Hristo Gochkov (proper post and file upload handling) +*/ + +#pragma once + +#include +#include +#include +#include "HTTP_Method.h" +#include "Uri.h" + +enum HTTPUploadStatus { UPLOAD_FILE_START, UPLOAD_FILE_WRITE, UPLOAD_FILE_END, + UPLOAD_FILE_ABORTED + }; +enum HTTPClientStatus { HC_NONE, HC_WAIT_READ, HC_WAIT_CLOSE }; +enum HTTPAuthMethod { BASIC_AUTH, DIGEST_AUTH }; + +#define HTTP_DOWNLOAD_UNIT_SIZE 1436 + +#ifndef HTTP_UPLOAD_BUFLEN +#define HTTP_UPLOAD_BUFLEN 1436 +#endif + +#define HTTP_MAX_DATA_WAIT 5000 //ms to wait for the client to send the request +#define HTTP_MAX_POST_WAIT 5000 //ms to wait for POST data to arrive +#define HTTP_MAX_SEND_WAIT 5000 //ms to wait for data chunk to be ACKed +#define HTTP_MAX_CLOSE_WAIT 2000 //ms to wait for the client to close the connection + +#define CONTENT_LENGTH_UNKNOWN ((size_t) -1) +#define CONTENT_LENGTH_NOT_SET ((size_t) -2) + +#define WEBSERVER_HAS_HOOK 1 + +class HTTPServer; + +typedef struct { + HTTPUploadStatus status; + String filename; + String name; + String type; + size_t totalSize; // file size + size_t currentSize; // size of data currently in buf + uint8_t buf[HTTP_UPLOAD_BUFLEN]; +} HTTPUpload; + +#include "detail/RequestHandler.h" + +namespace fs { +class FS; +} + +class HTTPServer { +public: + HTTPServer(); + virtual ~HTTPServer(); + + virtual void httpClose(); + virtual void httpHandleClient(); + + bool authenticate(const char * username, const char * password); + void requestAuthentication(HTTPAuthMethod mode = BASIC_AUTH, const char* realm = nullptr, const String& authFailMsg = String("")); + + typedef std::function THandlerFunction; + void on(const Uri &uri, THandlerFunction fn); + void on(const Uri &uri, HTTPMethod method, THandlerFunction fn); + void on(const Uri &uri, HTTPMethod method, THandlerFunction fn, THandlerFunction ufn); //ufn handles file uploads + void addHandler(RequestHandler* handler); + void serveStatic(const char* uri, fs::FS& fs, const char* path, const char* cache_header = nullptr); + void onNotFound(THandlerFunction fn); //called when handler is not assigned + void onFileUpload(THandlerFunction ufn); //handle file uploads + + String uri() { + return _currentUri; + } + HTTPMethod method() { + return _currentMethod; + } + HTTPUpload& upload() { + return *_currentUpload; + } + + String pathArg(unsigned int i); // get request path argument by number + String arg(String name); // get request argument value by name + String arg(int i); // get request argument value by number + String argName(int i); // get request argument name by number + int args(); // get arguments count + bool hasArg(String name); // check if argument exists + void collectHeaders(const char* headerKeys[], const size_t headerKeysCount); // set the request headers to collect + template + void collectHeaders(const Args&... args) { // set the request headers to collect (variadic template version) + if (_currentHeaders) { + delete[] _currentHeaders; + } + _headerKeysCount = sizeof...(args) + 1; + _currentHeaders = new RequestArgument[_headerKeysCount] { + { .key = "Authorization", .value = "" }, + { .key = String(args), .value = "" } ... + }; + } + + String header(String name); // get request header value by name + String header(int i); // get request header value by number + String headerName(int i); // get request header name by number + int headers(); // get header count + bool hasHeader(String name); // check if header exists + + int clientContentLength() { + return _clientContentLength; // return "content-length" of incoming HTTP header from "_currentClient" + } + + String hostHeader(); // get request host header if available or empty String if not + + // send response to the client + // code - HTTP response code, can be 200 or 404 + // content_type - HTTP content type, like "text/plain" or "image/png" + // content - actual content body + void send(int code, const char* content_type = nullptr, const String& content = String("")); + void send(int code, char* content_type, const String& content); + void send(int code, const String& content_type, const String& content); + void send(int code, const char* content_type, const char* content); + void send(int code, const char* content_type, const char* content, size_t contentLength); + + void send_P(int code, PGM_P content_type, PGM_P content); + void send_P(int code, PGM_P content_type, PGM_P content, size_t contentLength); + template + void send(int code, PGM_P content_type, TypeName content, size_t contentLength) { + send(code, content_type, (const char *)content, contentLength); + } + + void enableDelay(boolean value); + void enableCORS(boolean value = true); + void enableCrossOrigin(boolean value = true); + + void setContentLength(const size_t contentLength); + void sendHeader(const String& name, const String& value, bool first = false); + void sendContent(const String& content); + void sendContent(const char* content, size_t contentLength); + void sendContent_P(PGM_P content); + void sendContent_P(PGM_P content, size_t size); + + bool chunkedResponseModeStart_P(int code, PGM_P content_type) { + if (_currentVersion == 0) + // no chunk mode in HTTP/1.0 + { + return false; + } + setContentLength(CONTENT_LENGTH_UNKNOWN); + send(code, content_type, ""); + return true; + } + bool chunkedResponseModeStart(int code, const char* content_type) { + return chunkedResponseModeStart_P(code, content_type); + } + bool chunkedResponseModeStart(int code, const String& content_type) { + return chunkedResponseModeStart_P(code, content_type.c_str()); + } + void chunkedResponseFinalize() { + sendContent(""); + } + + static String urlDecode(const String& text); + + template + size_t streamFile(T &file, const String& contentType, const int code = 200) { + _streamFileCore(file.size(), file.name(), contentType, code); + return _currentClient->write(file); + } + + // Hook + enum ClientFuture { CLIENT_REQUEST_CAN_CONTINUE, CLIENT_REQUEST_IS_HANDLED, CLIENT_MUST_STOP, CLIENT_IS_GIVEN }; + typedef String(*ContentTypeFunction)(const String&); + using HookFunction = std::function; + void addHook(HookFunction hook) { + if (_hook) { + auto previousHook = _hook; + _hook = [previousHook, hook](const String & method, const String & url, WiFiClient * client, ContentTypeFunction contentType) { + auto whatNow = previousHook(method, url, client, contentType); + if (whatNow == CLIENT_REQUEST_CAN_CONTINUE) { + return hook(method, url, client, contentType); + } + return whatNow; + }; + } else { + _hook = hook; + } + } + +protected: + virtual size_t _currentClientWrite(const char* b, size_t l) { + return _currentClient->write(b, l); + } + virtual size_t _currentClientWrite_P(PGM_P b, size_t l) { + return _currentClient->write(b, l); + } + void _addRequestHandler(RequestHandler* handler); + void _handleRequest(); + void _finalizeResponse(); + ClientFuture _parseRequest(WiFiClient* client); + void _parseArguments(String data); + static String _responseCodeToString(int code); + bool _parseForm(WiFiClient* client, String boundary, uint32_t len); + bool _parseFormUploadAborted(); + void _uploadWriteByte(uint8_t b); + int _uploadReadByte(WiFiClient* client); + void _prepareHeader(String& response, int code, const char* content_type, size_t contentLength); + bool _collectHeader(const char* headerName, const char* headerValue); + + void _streamFileCore(const size_t fileSize, const String & fileName, const String & contentType, const int code = 200); + + String _getRandomHexString(); + // for extracting Auth parameters + String _extractParam(String& authReq, const String& param, const char delimit = '"'); + + struct RequestArgument { + String key; + String value; + }; + + boolean _corsEnabled; + + WiFiClient *_currentClient; + HTTPMethod _currentMethod; + String _currentUri; + uint8_t _currentVersion; + HTTPClientStatus _currentStatus; + unsigned long _statusChange; + boolean _nullDelay; + + RequestHandler* _currentHandler; + RequestHandler* _firstHandler; + RequestHandler* _lastHandler; + THandlerFunction _notFoundHandler; + THandlerFunction _fileUploadHandler; + + int _currentArgCount; + RequestArgument* _currentArgs; + int _postArgsLen; + RequestArgument* _postArgs; + + std::unique_ptr _currentUpload; + + int _headerKeysCount; + RequestArgument* _currentHeaders; + size_t _contentLength; + int _clientContentLength; // "Content-Length" from header of incoming POST or GET request + String _responseHeaders; + + String _hostHeader; + bool _chunked; + + String _snonce; // Store noance and opaque for future comparison + String _sopaque; + String _srealm; // Store the Auth realm between Calls + + HookFunction _hook; +}; diff --git a/libraries/WebServer/src/HTTP_Method.h b/libraries/WebServer/src/HTTP_Method.h new file mode 100644 index 000000000..d60406004 --- /dev/null +++ b/libraries/WebServer/src/HTTP_Method.h @@ -0,0 +1,6 @@ +#pragma once + +#include "http_parser.h" + +typedef enum http_method HTTPMethod; +#define HTTP_ANY (HTTPMethod)(255) diff --git a/libraries/WebServer/src/Parsing.cpp b/libraries/WebServer/src/Parsing.cpp new file mode 100644 index 000000000..b6fabdfde --- /dev/null +++ b/libraries/WebServer/src/Parsing.cpp @@ -0,0 +1,629 @@ +/* + Parsing.cpp - HTTP request parsing. + + Copyright (c) 2015 Ivan Grokhotkov. All rights reserved. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + Modified 8 May 2015 by Hristo Gochkov (proper post and file upload handling) +*/ + +#include +#include "WiFiServer.h" +#include "WiFiClient.h" +#include "HTTPServer.h" +#include "detail/mimetable.h" + +#ifndef log_e +#define log_e(...) +#define log_w(...) +#define log_v(...) +#endif + +#ifndef WEBSERVER_MAX_POST_ARGS +#define WEBSERVER_MAX_POST_ARGS 32 +#endif + +#define __STR(a) #a +#define _STR(a) __STR(a) +const char * _http_method_str[] = { +#define XX(num, name, string) _STR(name), + HTTP_METHOD_MAP(XX) +#undef XX +}; + +static const char Content_Type[] PROGMEM = "Content-Type"; +static const char filename[] PROGMEM = "filename"; + +static char* readBytesWithTimeout(WiFiClient* client, size_t maxLength, size_t& dataLength, int timeout_ms) { + char *buf = nullptr; + dataLength = 0; + while (dataLength < maxLength) { + int tries = timeout_ms; + size_t newLength; + while (!(newLength = client->available()) && tries--) { + delay(1); + } + if (!newLength) { + break; + } + if (!buf) { + buf = (char *) malloc(newLength + 1); + if (!buf) { + return nullptr; + } + } else { + char* newBuf = (char *) realloc(buf, dataLength + newLength + 1); + if (!newBuf) { + free(buf); + return nullptr; + } + buf = newBuf; + } + client->readBytes(buf + dataLength, newLength); + dataLength += newLength; + buf[dataLength] = '\0'; + } + return buf; +} + +HTTPServer::ClientFuture HTTPServer::_parseRequest(WiFiClient* client) { + // Read the first line of HTTP request + String req = client->readStringUntil('\r'); + client->readStringUntil('\n'); + //reset header value + for (int i = 0; i < _headerKeysCount; ++i) { + _currentHeaders[i].value = String(); + } + + // First line of HTTP request looks like "GET /path HTTP/1.1" + // Retrieve the "/path" part by finding the spaces + int addr_start = req.indexOf(' '); + int addr_end = req.indexOf(' ', addr_start + 1); + if (addr_start == -1 || addr_end == -1) { + log_e("Invalid request: %s", req.c_str()); + return CLIENT_MUST_STOP; + } + + String methodStr = req.substring(0, addr_start); + String url = req.substring(addr_start + 1, addr_end); + String versionEnd = req.substring(addr_end + 8); + _currentVersion = atoi(versionEnd.c_str()); + String searchStr = ""; + int hasSearch = url.indexOf('?'); + if (hasSearch != -1) { + searchStr = url.substring(hasSearch + 1); + url = url.substring(0, hasSearch); + } + _currentUri = url; + _chunked = false; + _clientContentLength = 0; // not known yet, or invalid + + if (_hook) { + auto whatNow = _hook(methodStr, url, client, mime::getContentType); + if (whatNow != CLIENT_REQUEST_CAN_CONTINUE) { + return whatNow; + } + } + + HTTPMethod method = HTTP_ANY; + size_t num_methods = sizeof(_http_method_str) / sizeof(const char *); + for (size_t i = 0; i < num_methods; i++) { + if (methodStr == _http_method_str[i]) { + method = (HTTPMethod)i; + break; + } + } + if (method == HTTP_ANY) { + log_e("Unknown HTTP Method: %s", methodStr.c_str()); + return CLIENT_MUST_STOP; + } + _currentMethod = method; + + log_v("method: %s url: %s search: %s", methodStr.c_str(), url.c_str(), searchStr.c_str()); + + //attach handler + RequestHandler* handler; + for (handler = _firstHandler; handler; handler = handler->next()) { + if (handler->canHandle(_currentMethod, _currentUri)) { + break; + } + } + _currentHandler = handler; + + String formData; + // below is needed only when POST type request + if (method == HTTP_POST || method == HTTP_PUT || method == HTTP_PATCH || method == HTTP_DELETE) { + String boundaryStr; + String headerName; + String headerValue; + bool isForm = false; + bool isEncoded = false; + //parse headers + while (1) { + req = client->readStringUntil('\r'); + client->readStringUntil('\n'); + if (req == "") { + break; //no moar headers + } + int headerDiv = req.indexOf(':'); + if (headerDiv == -1) { + break; + } + headerName = req.substring(0, headerDiv); + headerValue = req.substring(headerDiv + 1); + headerValue.trim(); + _collectHeader(headerName.c_str(), headerValue.c_str()); + + log_v("headerName: %s", headerName.c_str()); + log_v("headerValue: %s", headerValue.c_str()); + + if (headerName.equalsIgnoreCase(FPSTR(Content_Type))) { + using namespace mime; + if (headerValue.startsWith(FPSTR(mimeTable[txt].mimeType))) { + isForm = false; + } else if (headerValue.startsWith(F("application/x-www-form-urlencoded"))) { + isForm = false; + isEncoded = true; + } else if (headerValue.startsWith(F("multipart/"))) { + boundaryStr = headerValue.substring(headerValue.indexOf('=') + 1); + boundaryStr.replace("\"", ""); + isForm = true; + } + } else if (headerName.equalsIgnoreCase(F("Content-Length"))) { + _clientContentLength = headerValue.toInt(); + } else if (headerName.equalsIgnoreCase(F("Host"))) { + _hostHeader = headerValue; + } + } + + if (!isForm) { + size_t plainLength; + char* plainBuf = readBytesWithTimeout(client, _clientContentLength, plainLength, HTTP_MAX_POST_WAIT); + if ((int)plainLength < (int)_clientContentLength) { + free(plainBuf); + return CLIENT_MUST_STOP; + } + if (_clientContentLength > 0) { + if (isEncoded) { + //url encoded form + if (searchStr != "") { + searchStr += '&'; + } + searchStr += plainBuf; + } + _parseArguments(searchStr); + if (!isEncoded) { + //plain post json or other data + RequestArgument& arg = _currentArgs[_currentArgCount++]; + arg.key = F("plain"); + arg.value = String(plainBuf); + } + + log_v("Plain: %s", plainBuf); + free(plainBuf); + } else { + // No content - but we can still have arguments in the URL. + _parseArguments(searchStr); + } + } else { + // it IS a form + _parseArguments(searchStr); + if (!_parseForm(client, boundaryStr, _clientContentLength)) { + return CLIENT_MUST_STOP; + } + } + } else { + String headerName; + String headerValue; + //parse headers + while (1) { + req = client->readStringUntil('\r'); + client->readStringUntil('\n'); + if (req == "") { + break; //no moar headers + } + int headerDiv = req.indexOf(':'); + if (headerDiv == -1) { + break; + } + headerName = req.substring(0, headerDiv); + headerValue = req.substring(headerDiv + 2); + _collectHeader(headerName.c_str(), headerValue.c_str()); + + log_v("headerName: %s", headerName.c_str()); + log_v("headerValue: %s", headerValue.c_str()); + + if (headerName.equalsIgnoreCase("Host")) { + _hostHeader = headerValue; + } + } + _parseArguments(searchStr); + } + client->flush(); + + log_v("Request: %s", url.c_str()); + log_v(" Arguments: %s", searchStr.c_str()); + + return CLIENT_REQUEST_CAN_CONTINUE; +} + +bool HTTPServer::_collectHeader(const char* headerName, const char* headerValue) { + for (int i = 0; i < _headerKeysCount; i++) { + if (_currentHeaders[i].key.equalsIgnoreCase(headerName)) { + _currentHeaders[i].value = headerValue; + return true; + } + } + return false; +} + +void HTTPServer::_parseArguments(String data) { + log_v("args: %s", data.c_str()); + if (_currentArgs) { + delete[] _currentArgs; + } + _currentArgs = 0; + if (data.length() == 0) { + _currentArgCount = 0; + _currentArgs = new RequestArgument[1]; + return; + } + _currentArgCount = 1; + + for (int i = 0; i < (int)data.length();) { + i = data.indexOf('&', i); + if (i == -1) { + break; + } + ++i; + ++_currentArgCount; + } + log_v("args count: %d", _currentArgCount); + + _currentArgs = new RequestArgument[_currentArgCount + 1]; + int pos = 0; + int iarg; + for (iarg = 0; iarg < _currentArgCount;) { + int equal_sign_index = data.indexOf('=', pos); + int next_arg_index = data.indexOf('&', pos); + log_v("pos %d =@%d &@%d", pos, equal_sign_index, next_arg_index); + if ((equal_sign_index == -1) || ((equal_sign_index > next_arg_index) && (next_arg_index != -1))) { + log_e("arg missing value: %d", iarg); + if (next_arg_index == -1) { + break; + } + pos = next_arg_index + 1; + continue; + } + RequestArgument& arg = _currentArgs[iarg]; + arg.key = urlDecode(data.substring(pos, equal_sign_index)); + arg.value = urlDecode(data.substring(equal_sign_index + 1, next_arg_index)); + log_v("arg %d key: %s value: %s", iarg, arg.key.c_str(), arg.value.c_str()); + ++iarg; + if (next_arg_index == -1) { + break; + } + pos = next_arg_index + 1; + } + _currentArgCount = iarg; + log_v("args count: %d", _currentArgCount); + +} + +void HTTPServer::_uploadWriteByte(uint8_t b) { + if (_currentUpload->currentSize == HTTP_UPLOAD_BUFLEN) { + if (_currentHandler && _currentHandler->canUpload(_currentUri)) { + _currentHandler->upload(*this, _currentUri, *_currentUpload); + } + _currentUpload->totalSize += _currentUpload->currentSize; + _currentUpload->currentSize = 0; + } + _currentUpload->buf[_currentUpload->currentSize++] = b; +} + +int HTTPServer::_uploadReadByte(WiFiClient* client) { + int res = client->read(); + if (res < 0) { + // keep trying until you either read a valid byte or timeout + unsigned long startMillis = millis(); + unsigned long timeoutIntervalMillis = client->getTimeout(); + boolean timedOut = false; + for (;;) { + if (!client->connected()) { + return -1; + } + // loosely modeled after blinkWithoutDelay pattern + while (!timedOut && !client->available() && client->connected()) { + delay(2); + timedOut = millis() - startMillis >= timeoutIntervalMillis; + } + + res = client->read(); + if (res >= 0) { + return res; // exit on a valid read + } + // NOTE: it is possible to get here and have all of the following + // assertions hold true + // + // -- client->available() > 0 + // -- client->connected == true + // -- res == -1 + // + // a simple retry strategy overcomes this which is to say the + // assertion is not permanent, but the reason that this works + // is elusive, and possibly indicative of a more subtle underlying + // issue + + timedOut = millis() - startMillis >= timeoutIntervalMillis; + if (timedOut) { + return res; // exit on a timeout + } + } + } + + return res; +} + +bool HTTPServer::_parseForm(WiFiClient* client, String boundary, uint32_t len) { + (void) len; + log_v("Parse Form: Boundary: %s Length: %d", boundary.c_str(), len); + String line; + int retry = 0; + do { + line = client->readStringUntil('\r'); + ++retry; + } while (line.length() == 0 && retry < 3); + + client->readStringUntil('\n'); + //start reading the form + if (line == ("--" + boundary)) { + if (_postArgs) { + delete[] _postArgs; + } + _postArgs = new RequestArgument[WEBSERVER_MAX_POST_ARGS]; + _postArgsLen = 0; + while (1) { + String argName; + String argValue; + String argType; + String argFilename; + bool argIsFile = false; + + line = client->readStringUntil('\r'); + client->readStringUntil('\n'); + if (line.length() > 19 && line.substring(0, 19).equalsIgnoreCase(F("Content-Disposition"))) { + int nameStart = line.indexOf('='); + if (nameStart != -1) { + argName = line.substring(nameStart + 2); + nameStart = argName.indexOf('='); + if (nameStart == -1) { + argName = argName.substring(0, argName.length() - 1); + } else { + argFilename = argName.substring(nameStart + 2, argName.length() - 1); + argName = argName.substring(0, argName.indexOf('"')); + argIsFile = true; + log_v("PostArg FileName: %s", argFilename.c_str()); + //use GET to set the filename if uploading using blob + if (argFilename == F("blob") && hasArg(FPSTR(filename))) { + argFilename = arg(FPSTR(filename)); + } + } + log_v("PostArg Name: %s", argName.c_str()); + using namespace mime; + argType = FPSTR(mimeTable[txt].mimeType); + line = client->readStringUntil('\r'); + client->readStringUntil('\n'); + if (line.length() > 12 && line.substring(0, 12).equalsIgnoreCase(FPSTR(Content_Type))) { + argType = line.substring(line.indexOf(':') + 2); + //skip next line + client->readStringUntil('\r'); + client->readStringUntil('\n'); + } + log_v("PostArg Type: %s", argType.c_str()); + if (!argIsFile) { + while (1) { + line = client->readStringUntil('\r'); + client->readStringUntil('\n'); + if (line.startsWith("--" + boundary)) { + break; + } + if (argValue.length() > 0) { + argValue += "\n"; + } + argValue += line; + } + log_v("PostArg Value: %s", argValue.c_str()); + + RequestArgument& arg = _postArgs[_postArgsLen++]; + arg.key = argName; + arg.value = argValue; + + if (line == ("--" + boundary + "--")) { + log_v("Done Parsing POST"); + break; + } else if (_postArgsLen >= WEBSERVER_MAX_POST_ARGS) { + log_e("Too many PostArgs (max: %d) in request.", WEBSERVER_MAX_POST_ARGS); + return false; + } + } else { + _currentUpload.reset(new HTTPUpload()); + _currentUpload->status = UPLOAD_FILE_START; + _currentUpload->name = argName; + _currentUpload->filename = argFilename; + _currentUpload->type = argType; + _currentUpload->totalSize = 0; + _currentUpload->currentSize = 0; + log_v("Start File: %s Type: %s", _currentUpload->filename.c_str(), _currentUpload->type.c_str()); + if (_currentHandler && _currentHandler->canUpload(_currentUri)) { + _currentHandler->upload(*this, _currentUri, *_currentUpload); + } + _currentUpload->status = UPLOAD_FILE_WRITE; + int argByte = _uploadReadByte(client); +readfile: + + while (argByte != 0x0D) { + if (argByte < 0) { + return _parseFormUploadAborted(); + } + _uploadWriteByte(argByte); + argByte = _uploadReadByte(client); + } + + argByte = _uploadReadByte(client); + if (argByte < 0) { + return _parseFormUploadAborted(); + } + if (argByte == 0x0A) { + argByte = _uploadReadByte(client); + if (argByte < 0) { + return _parseFormUploadAborted(); + } + if ((char)argByte != '-') { + //continue reading the file + _uploadWriteByte(0x0D); + _uploadWriteByte(0x0A); + goto readfile; + } else { + argByte = _uploadReadByte(client); + if (argByte < 0) { + return _parseFormUploadAborted(); + } + if ((char)argByte != '-') { + //continue reading the file + _uploadWriteByte(0x0D); + _uploadWriteByte(0x0A); + _uploadWriteByte((uint8_t)('-')); + goto readfile; + } + } + + uint8_t endBuf[boundary.length()]; + uint32_t i = 0; + while (i < boundary.length()) { + argByte = _uploadReadByte(client); + if (argByte < 0) { + return _parseFormUploadAborted(); + } + if ((char)argByte == 0x0D) { + _uploadWriteByte(0x0D); + _uploadWriteByte(0x0A); + _uploadWriteByte((uint8_t)('-')); + _uploadWriteByte((uint8_t)('-')); + for (uint32_t j = 0; j < i; j++) { + _uploadWriteByte(endBuf[j]); + } + goto readfile; + } + endBuf[i++] = (uint8_t)argByte; + } + + if (strstr((const char*)endBuf, boundary.c_str()) != nullptr) { + if (_currentHandler && _currentHandler->canUpload(_currentUri)) { + _currentHandler->upload(*this, _currentUri, *_currentUpload); + } + _currentUpload->totalSize += _currentUpload->currentSize; + _currentUpload->status = UPLOAD_FILE_END; + if (_currentHandler && _currentHandler->canUpload(_currentUri)) { + _currentHandler->upload(*this, _currentUri, *_currentUpload); + } + log_v("End File: %s Type: %s Size: %d", _currentUpload->filename.c_str(), _currentUpload->type.c_str(), _currentUpload->totalSize); + line = client->readStringUntil(0x0D); + client->readStringUntil(0x0A); + if (line == "--") { + log_v("Done Parsing POST"); + break; + } + continue; + } else { + _uploadWriteByte(0x0D); + _uploadWriteByte(0x0A); + _uploadWriteByte((uint8_t)('-')); + _uploadWriteByte((uint8_t)('-')); + for (uint32_t j = 0; j < boundary.length(); j++) { + _uploadWriteByte(endBuf[j]); + } + argByte = _uploadReadByte(client); + goto readfile; + } + } else { + _uploadWriteByte(0x0D); + goto readfile; + } + break; + } + } + } + } + + int iarg; + int totalArgs = ((WEBSERVER_MAX_POST_ARGS - _postArgsLen) < _currentArgCount) ? (WEBSERVER_MAX_POST_ARGS - _postArgsLen) : _currentArgCount; + for (iarg = 0; iarg < totalArgs; iarg++) { + RequestArgument& arg = _postArgs[_postArgsLen++]; + arg.key = _currentArgs[iarg].key; + arg.value = _currentArgs[iarg].value; + } + if (_currentArgs) { + delete[] _currentArgs; + } + _currentArgs = new RequestArgument[_postArgsLen]; + for (iarg = 0; iarg < _postArgsLen; iarg++) { + RequestArgument& arg = _currentArgs[iarg]; + arg.key = _postArgs[iarg].key; + arg.value = _postArgs[iarg].value; + } + _currentArgCount = iarg; + if (_postArgs) { + delete[] _postArgs; + _postArgs = nullptr; + _postArgsLen = 0; + } + return true; + } + log_e("Error: line: %s", line.c_str()); + return false; +} + +String HTTPServer::urlDecode(const String& text) { + String decoded = ""; + char temp[] = "0x00"; + unsigned int len = text.length(); + unsigned int i = 0; + while (i < len) { + char decodedChar; + char encodedChar = text.charAt(i++); + if ((encodedChar == '%') && (i + 1 < len)) { + temp[2] = text.charAt(i++); + temp[3] = text.charAt(i++); + + decodedChar = strtol(temp, nullptr, 16); + } else { + if (encodedChar == '+') { + decodedChar = ' '; + } else { + decodedChar = encodedChar; // normal ascii char + } + } + decoded += decodedChar; + } + return decoded; +} + +bool HTTPServer::_parseFormUploadAborted() { + _currentUpload->status = UPLOAD_FILE_ABORTED; + if (_currentHandler && _currentHandler->canUpload(_currentUri)) { + _currentHandler->upload(*this, _currentUri, *_currentUpload); + } + return false; +} diff --git a/libraries/WebServer/src/Uri.h b/libraries/WebServer/src/Uri.h new file mode 100644 index 000000000..919074554 --- /dev/null +++ b/libraries/WebServer/src/Uri.h @@ -0,0 +1,26 @@ +#pragma once + +#include +#include + +class Uri { + +protected: + const String _uri; + +public: + Uri(const char *uri) : _uri(uri) {} + Uri(const String &uri) : _uri(uri) {} + Uri(const __FlashStringHelper *uri) : _uri(String(uri)) {} + virtual ~Uri() {} + + virtual Uri* clone() const { + return new Uri(_uri); + }; + + virtual void initPathArgs(__attribute__((unused)) std::vector &pathArgs) {} + + virtual bool canHandle(const String &requestUri, __attribute__((unused)) std::vector &pathArgs) { + return _uri == requestUri; + } +}; diff --git a/libraries/WebServer/src/WebServer.h b/libraries/WebServer/src/WebServer.h new file mode 100644 index 000000000..e1843f61b --- /dev/null +++ b/libraries/WebServer/src/WebServer.h @@ -0,0 +1,26 @@ +/* + WebServer.h - Create a WebServer class + Copyright (c) 2022 Earle F. Philhower, III All rights reserved. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + Modified 8 May 2015 by Hristo Gochkov (proper post and file upload handling) +*/ + +#pragma once + +#include "WebServerTemplate.h" +#include "detail/mimetable.h" + +using WebServer = WebServerTemplate; diff --git a/libraries/WebServer/src/WebServerSecure.h b/libraries/WebServer/src/WebServerSecure.h new file mode 100644 index 000000000..1db854033 --- /dev/null +++ b/libraries/WebServer/src/WebServerSecure.h @@ -0,0 +1,25 @@ +/* + WebServerSecure - Create a WebServerSecure class + Copyright (c) 2022 Earle F. Philhower, III All rights reserved. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + Modified 8 May 2015 by Hristo Gochkov (proper post and file upload handling) +*/ + +#pragma once + +#include "WebServerTemplate.h" + +using WebServerSecure = WebServerTemplate; diff --git a/libraries/WebServer/src/WebServerTemplate.h b/libraries/WebServer/src/WebServerTemplate.h new file mode 100644 index 000000000..abea31242 --- /dev/null +++ b/libraries/WebServer/src/WebServerTemplate.h @@ -0,0 +1,117 @@ +/* + WebServerTemplate - Makes an actual Server class from a HTTPServer + Copyright (c) 2022 Earle F. Philhower, III All rights reserved. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + Modified 8 May 2015 by Hristo Gochkov (proper post and file upload handling) +*/ + +#pragma once + +#include "HTTPServer.h" + +template +class WebServerTemplate; + +template +class WebServerTemplate : public HTTPServer { +public: + using WebServerType = WebServerTemplate; + using ClientType = typename ServerType::ClientType; + + WebServerTemplate(IPAddress addr, int port = DefaultPort); + WebServerTemplate(int port = DefaultPort); + virtual ~WebServerTemplate(); + + virtual void begin(); + virtual void begin(uint16_t port); + virtual void handleClient(); + + virtual void close(); + virtual void stop(); + + ServerType &getServer() { + return _server; + } + + ClientType& client() { + // _currentClient is always a WiFiClient*, so we need to coerce to the proper type for SSL + return *(ClientType*)_currentClient; + } + +private: + ServerType _server; +}; + +template +WebServerTemplate::WebServerTemplate(IPAddress addr, int port) : HTTPServer(), _server(addr, port) { +} + +template +WebServerTemplate::WebServerTemplate(int port) : HTTPServer(), _server(port) { +} + +template +WebServerTemplate::~WebServerTemplate() { + _server.close(); +} + +template +void WebServerTemplate::begin() { + close(); + _server.begin(); + _server.setNoDelay(true); +} + +template +void WebServerTemplate::begin(uint16_t port) { + close(); + _server.begin(port); + _server.setNoDelay(true); +} + +template +void WebServerTemplate::handleClient() { + if (_currentStatus == HC_NONE) { + if (_currentClient) { + delete _currentClient; + _currentClient = nullptr; + } + + ClientType client = _server.available(); + if (!client) { + if (_nullDelay) { + delay(1); + } + return; + } + + _currentClient = new ClientType(client); + _currentStatus = HC_WAIT_READ; + _statusChange = millis(); + } + httpHandleClient(); +} + +template +void WebServerTemplate::close() { + _server.close(); + httpClose(); +} + +template +void WebServerTemplate::stop() { + close(); +} diff --git a/libraries/WebServer/src/detail/RequestHandler.h b/libraries/WebServer/src/detail/RequestHandler.h new file mode 100644 index 000000000..f816cf1c0 --- /dev/null +++ b/libraries/WebServer/src/detail/RequestHandler.h @@ -0,0 +1,48 @@ +#pragma once + +#include +#include + +class RequestHandler { +public: + virtual ~RequestHandler() { } + virtual bool canHandle(HTTPMethod method, String uri) { + (void) method; + (void) uri; + return false; + } + virtual bool canUpload(String uri) { + (void) uri; + return false; + } + virtual bool handle(HTTPServer& server, HTTPMethod requestMethod, String requestUri) { + (void) server; + (void) requestMethod; + (void) requestUri; + return false; + } + virtual void upload(HTTPServer& server, String requestUri, HTTPUpload& upload) { + (void) server; + (void) requestUri; + (void) upload; + } + + RequestHandler* next() { + return _next; + } + void next(RequestHandler* r) { + _next = r; + } + +private: + RequestHandler* _next = nullptr; + +protected: + std::vector pathArgs; + +public: + const String& pathArg(unsigned int i) { + assert(i < pathArgs.size()); + return pathArgs[i]; + } +}; diff --git a/libraries/WebServer/src/detail/RequestHandlersImpl.h b/libraries/WebServer/src/detail/RequestHandlersImpl.h new file mode 100644 index 000000000..43211737a --- /dev/null +++ b/libraries/WebServer/src/detail/RequestHandlersImpl.h @@ -0,0 +1,163 @@ +#pragma once + +#include "RequestHandler.h" +#include "mimetable.h" +#include +#include "Uri.h" + +#ifndef log_e +#define log_e(...) +#define log_w(...) +#define log_v(...) +#endif + +using namespace mime; + +class FunctionRequestHandler : public RequestHandler { +public: + FunctionRequestHandler(HTTPServer::THandlerFunction fn, HTTPServer::THandlerFunction ufn, const Uri &uri, HTTPMethod method) + : _fn(fn) + , _ufn(ufn) + , _uri(uri.clone()) + , _method(method) { + _uri->initPathArgs(pathArgs); + } + + ~FunctionRequestHandler() { + delete _uri; + } + + bool canHandle(HTTPMethod requestMethod, String requestUri) override { + if (_method != HTTP_ANY && _method != requestMethod) { + return false; + } + + return _uri->canHandle(requestUri, pathArgs); + } + + bool canUpload(String requestUri) override { + if (!_ufn || !canHandle(HTTP_POST, requestUri)) { + return false; + } + + return true; + } + + bool handle(HTTPServer& server, HTTPMethod requestMethod, String requestUri) override { + (void) server; + if (!canHandle(requestMethod, requestUri)) { + return false; + } + + _fn(); + return true; + } + + void upload(HTTPServer& server, String requestUri, HTTPUpload& upload) override { + (void) server; + (void) upload; + if (canUpload(requestUri)) { + _ufn(); + } + } + +protected: + HTTPServer::THandlerFunction _fn; + HTTPServer::THandlerFunction _ufn; + Uri *_uri; + HTTPMethod _method; +}; + +class StaticRequestHandler : public RequestHandler { +public: + StaticRequestHandler(FS& fs, const char* path, const char* uri, const char* cache_header) + : _fs(fs) + , _uri(uri) + , _path(path) + , _cache_header(cache_header) { + File f = fs.open(path, "r"); + _isFile = (f && (! f.isDirectory())); + log_v("StaticRequestHandler: path=%s uri=%s isFile=%d, cache_header=%s\r\n", path, uri, _isFile, cache_header ? cache_header : ""); // issue 5506 - cache_header can be nullptr + _baseUriLength = _uri.length(); + } + + bool canHandle(HTTPMethod requestMethod, String requestUri) override { + if (requestMethod != HTTP_GET) { + return false; + } + + if ((_isFile && requestUri != _uri) || !requestUri.startsWith(_uri)) { + return false; + } + + return true; + } + + bool handle(HTTPServer& server, HTTPMethod requestMethod, String requestUri) override { + if (!canHandle(requestMethod, requestUri)) { + return false; + } + + log_v("StaticRequestHandler::handle: request=%s _uri=%s\r\n", requestUri.c_str(), _uri.c_str()); + + String path(_path); + + if (!_isFile) { + // Base URI doesn't point to a file. + // If a directory is requested, look for index file. + if (requestUri.endsWith("/")) { + requestUri += "index.htm"; + } + + // Append whatever follows this URI in request to get the file path. + path += requestUri.substring(_baseUriLength); + } + log_v("StaticRequestHandler::handle: path=%s, isFile=%d\r\n", path.c_str(), _isFile); + + String contentType = getContentType(path); + + // look for gz file, only if the original specified path is not a gz. So part only works to send gzip via content encoding when a non compressed is asked for + // if you point the the path to gzip you will serve the gzip as content type "application/x-gzip", not text or javascript etc... + if (!path.endsWith(FPSTR(mimeTable[gz].endsWith)) && !_fs.exists(path)) { + String pathWithGz = path + FPSTR(mimeTable[gz].endsWith); + if (_fs.exists(pathWithGz)) { + path += FPSTR(mimeTable[gz].endsWith); + } + } + + File f = _fs.open(path, "r"); + if (!f || !f.available()) { + return false; + } + + if (_cache_header.length() != 0) { + server.sendHeader("Cache-Control", _cache_header); + } + + server.streamFile(f, contentType); + return true; + } + + static String getContentType(const String& path) { + char buff[sizeof(mimeTable[0].mimeType)]; + // Check all entries but last one for match, return if found + for (size_t i = 0; i < sizeof(mimeTable) / sizeof(mimeTable[0]) - 1; i++) { + strcpy_P(buff, mimeTable[i].endsWith); + if (path.endsWith(buff)) { + strcpy_P(buff, mimeTable[i].mimeType); + return String(buff); + } + } + // Fall-through and just return default type + strcpy_P(buff, mimeTable[sizeof(mimeTable) / sizeof(mimeTable[0]) - 1].mimeType); + return String(buff); + } + +protected: + FS _fs; + String _uri; + String _path; + String _cache_header; + bool _isFile; + size_t _baseUriLength; +}; diff --git a/libraries/WebServer/src/detail/mimetable.cpp b/libraries/WebServer/src/detail/mimetable.cpp new file mode 100644 index 000000000..c9d7ab476 --- /dev/null +++ b/libraries/WebServer/src/detail/mimetable.cpp @@ -0,0 +1,44 @@ +#include +#include "mimetable.h" +#include "pgmspace.h" + +namespace mime { + +// Table of extension->MIME strings stored in PROGMEM, needs to be global due to GCC section typing rules +const Entry mimeTable[maxType] = { + { ".html", "text/html" }, + { ".htm", "text/html" }, + { ".css", "text/css" }, + { ".txt", "text/plain" }, + { ".js", "application/javascript" }, + { ".json", "application/json" }, + { ".png", "image/png" }, + { ".gif", "image/gif" }, + { ".jpg", "image/jpeg" }, + { ".ico", "image/x-icon" }, + { ".svg", "image/svg+xml" }, + { ".ttf", "application/x-font-ttf" }, + { ".otf", "application/x-font-opentype" }, + { ".woff", "application/font-woff" }, + { ".woff2", "application/font-woff2" }, + { ".eot", "application/vnd.ms-fontobject" }, + { ".sfnt", "application/font-sfnt" }, + { ".xml", "text/xml" }, + { ".pdf", "application/pdf" }, + { ".zip", "application/zip" }, + { ".gz", "application/x-gzip" }, + { ".appcache", "text/cache-manifest" }, + { "", "application/octet-stream" } +}; + + +arduino::String getContentType(const arduino::String& path) { + for (size_t i = 0; i < maxType; i++) { + if (path.endsWith(FPSTR(mimeTable[i].endsWith))) { + return arduino::String(FPSTR(mimeTable[i].mimeType)); + } + } + // Fall-through and just return default type + return arduino::String(FPSTR(mimeTable[none].mimeType)); +} +} diff --git a/libraries/WebServer/src/detail/mimetable.h b/libraries/WebServer/src/detail/mimetable.h new file mode 100644 index 000000000..a078aa5cb --- /dev/null +++ b/libraries/WebServer/src/detail/mimetable.h @@ -0,0 +1,43 @@ +#pragma once + +#include + +namespace mime { + +enum type { + html, + htm, + css, + txt, + js, + json, + png, + gif, + jpg, + ico, + svg, + ttf, + otf, + woff, + woff2, + eot, + sfnt, + xml, + pdf, + zip, + gz, + appcache, + none, + maxType +}; + +struct Entry { + const char *endsWith; + const char *mimeType; +}; + +extern const Entry mimeTable[maxType]; + +arduino::String getContentType(const arduino::String& path); + +} diff --git a/libraries/WebServer/src/uri/UriBraces.h b/libraries/WebServer/src/uri/UriBraces.h new file mode 100644 index 000000000..f1dce66ef --- /dev/null +++ b/libraries/WebServer/src/uri/UriBraces.h @@ -0,0 +1,65 @@ +#pragma once + +#include "Uri.h" + +class UriBraces : public Uri { + +public: + explicit UriBraces(const char *uri) : Uri(uri) {}; + explicit UriBraces(const String &uri) : Uri(uri) {}; + + Uri* clone() const override final { + return new UriBraces(_uri); + }; + + void initPathArgs(std::vector &pathArgs) override final { + int numParams = 0, start = 0; + do { + start = _uri.indexOf("{}", start); + if (start > 0) { + numParams++; + start += 2; + } + } while (start > 0); + pathArgs.resize(numParams); + } + + bool canHandle(const String &requestUri, std::vector &pathArgs) override final { + if (Uri::canHandle(requestUri, pathArgs)) { + return true; + } + + size_t uriLength = _uri.length(); + unsigned int pathArgIndex = 0; + unsigned int requestUriIndex = 0; + for (unsigned int i = 0; i < uriLength; i++, requestUriIndex++) { + char uriChar = _uri[i]; + char requestUriChar = requestUri[requestUriIndex]; + + if (uriChar == requestUriChar) { + continue; + } + if (uriChar != '{') { + return false; + } + + i += 2; // index of char after '}' + if (i >= uriLength) { + // there is no char after '}' + pathArgs[pathArgIndex] = requestUri.substring(requestUriIndex); + return pathArgs[pathArgIndex].indexOf("/") == -1; // path argument may not contain a '/' + } else { + char charEnd = _uri[i]; + int uriIndex = requestUri.indexOf(charEnd, requestUriIndex); + if (uriIndex < 0) { + return false; + } + pathArgs[pathArgIndex] = requestUri.substring(requestUriIndex, uriIndex); + requestUriIndex = (unsigned int) uriIndex; + } + pathArgIndex++; + } + + return requestUriIndex >= requestUri.length(); + } +}; diff --git a/libraries/WebServer/src/uri/UriGlob.h b/libraries/WebServer/src/uri/UriGlob.h new file mode 100644 index 000000000..d3c3f42fb --- /dev/null +++ b/libraries/WebServer/src/uri/UriGlob.h @@ -0,0 +1,19 @@ +#pragma once + +#include "Uri.h" +#include + +class UriGlob : public Uri { + +public: + explicit UriGlob(const char *uri) : Uri(uri) {}; + explicit UriGlob(const String &uri) : Uri(uri) {}; + + Uri* clone() const override final { + return new UriGlob(_uri); + }; + + bool canHandle(const String &requestUri, __attribute__((unused)) std::vector &pathArgs) override final { + return fnmatch(_uri.c_str(), requestUri.c_str(), 0) == 0; + } +}; diff --git a/libraries/WebServer/src/uri/UriRegex.h b/libraries/WebServer/src/uri/UriRegex.h new file mode 100644 index 000000000..fa1bc2703 --- /dev/null +++ b/libraries/WebServer/src/uri/UriRegex.h @@ -0,0 +1,42 @@ +#pragma once + +#include "Uri.h" +#include + +class UriRegex : public Uri { + +public: + explicit UriRegex(const char *uri) : Uri(uri) {}; + explicit UriRegex(const String &uri) : Uri(uri) {}; + + Uri* clone() const override final { + return new UriRegex(_uri); + }; + + void initPathArgs(std::vector &pathArgs) override final { + std::regex rgx((_uri + "|").c_str()); + std::smatch matches; + std::string s{""}; + std::regex_search(s, matches, rgx); + pathArgs.resize(matches.size() - 1); + } + + bool canHandle(const String &requestUri, std::vector &pathArgs) override final { + if (Uri::canHandle(requestUri, pathArgs)) { + return true; + } + + unsigned int pathArgIndex = 0; + std::regex rgx(_uri.c_str()); + std::smatch matches; + std::string s(requestUri.c_str()); + if (std::regex_search(s, matches, rgx)) { + for (size_t i = 1; i < matches.size(); ++i) { // skip first + pathArgs[pathArgIndex] = String(matches[i].str().c_str()); + pathArgIndex++; + } + return true; + } + return false; + } +}; diff --git a/libraries/WiFi/examples/BearSSL_CertStore/certs-from-mozilla.py b/libraries/WiFi/examples/BearSSL_CertStore/certs-from-mozilla.py index 1f35a9985..80dbc4838 100755 --- a/libraries/WiFi/examples/BearSSL_CertStore/certs-from-mozilla.py +++ b/libraries/WiFi/examples/BearSSL_CertStore/certs-from-mozilla.py @@ -47,7 +47,6 @@ if item.startswith("'-----BEGIN CERTIFICATE-----"): pems.append(item) del names[0] # Remove headers -del pems[0] # Remove headers # Try and make ./data, skip if present try: diff --git a/libraries/WiFi/examples/BearSSL_Sessions/BearSSL_Sessions.ino b/libraries/WiFi/examples/BearSSL_Sessions/BearSSL_Sessions.ino index 16322fdaa..338e45a93 100644 --- a/libraries/WiFi/examples/BearSSL_Sessions/BearSSL_Sessions.ino +++ b/libraries/WiFi/examples/BearSSL_Sessions/BearSSL_Sessions.ino @@ -113,7 +113,7 @@ void loop() { client.setTrustAnchors(&cert); fetchURL(&client, host, port, path); finish = millis(); - Serial.printf("Total time: %dms\n", finish - start); + Serial.printf("Total time: %lums\n", finish - start); BearSSL::Session session; client.setSession(&session); @@ -122,21 +122,21 @@ void loop() { client.setTrustAnchors(&cert); fetchURL(&client, host, port, path); finish = millis(); - Serial.printf("Total time: %dms\n", finish - start); + Serial.printf("Total time: %lums\n", finish - start); Serial.printf("Connecting with the just initialized session..."); start = millis(); client.setTrustAnchors(&cert); fetchURL(&client, host, port, path); finish = millis(); - Serial.printf("Total time: %dms\n", finish - start); + Serial.printf("Total time: %lums\n", finish - start); Serial.printf("Connecting again with the initialized session..."); start = millis(); client.setTrustAnchors(&cert); fetchURL(&client, host, port, path); finish = millis(); - Serial.printf("Total time: %dms\n", finish - start); + Serial.printf("Total time: %lums\n", finish - start); delay(10000); // Avoid DDOSing github } diff --git a/libraries/WiFi/examples/BearSSL_Validation/BearSSL_Validation.ino b/libraries/WiFi/examples/BearSSL_Validation/BearSSL_Validation.ino index 7b435524c..c39fe107a 100644 --- a/libraries/WiFi/examples/BearSSL_Validation/BearSSL_Validation.ino +++ b/libraries/WiFi/examples/BearSSL_Validation/BearSSL_Validation.ino @@ -76,7 +76,7 @@ void fetchURL(BearSSL::WiFiClientSecure *client, const char *host, const uint16_ } while (millis() < to); } client->stop(); - Serial.printf("BSSL stack used: %d\n-------\n\n", stack_thunk_get_max_usage()); + Serial.printf("BSSL stack used: %lu\n-------\n\n", stack_thunk_get_max_usage()); } void fetchNoConfig() { diff --git a/libraries/WiFi/examples/ScanNetworks/ScanNetworks.ino b/libraries/WiFi/examples/ScanNetworks/ScanNetworks.ino index 1b3629cf4..baa6db090 100644 --- a/libraries/WiFi/examples/ScanNetworks/ScanNetworks.ino +++ b/libraries/WiFi/examples/ScanNetworks/ScanNetworks.ino @@ -24,7 +24,7 @@ const char *encToString(uint8_t enc) { void loop() { delay(5000); - Serial.printf("Beginning scan at %d\n", millis()); + Serial.printf("Beginning scan at %lu\n", millis()); auto cnt = WiFi.scanNetworks(); if (!cnt) { Serial.printf("No networks found\n"); @@ -34,7 +34,7 @@ void loop() { for (auto i = 0; i < cnt; i++) { uint8_t bssid[6]; WiFi.BSSID(i, bssid); - Serial.printf("%32s %5s %17s %2d %4d\n", WiFi.SSID(i), encToString(WiFi.encryptionType(i)), macToString(bssid), WiFi.channel(i), WiFi.RSSI(i)); + Serial.printf("%32s %5s %17s %2d %4ld\n", WiFi.SSID(i), encToString(WiFi.encryptionType(i)), macToString(bssid), WiFi.channel(i), WiFi.RSSI(i)); } } Serial.printf("\n--- Sleeping ---\n\n\n"); diff --git a/libraries/WiFi/examples/WiFiClient/WiFiClient.ino b/libraries/WiFi/examples/WiFiClient/WiFiClient.ino index 83f187b74..124332b93 100644 --- a/libraries/WiFi/examples/WiFiClient/WiFiClient.ino +++ b/libraries/WiFi/examples/WiFiClient/WiFiClient.ino @@ -16,6 +16,8 @@ const char* password = STAPSK; const char* host = "djxmmx.net"; const uint16_t port = 17; +WiFiMulti multi; + void setup() { Serial.begin(115200); @@ -26,11 +28,12 @@ void setup() { Serial.print("Connecting to "); Serial.println(ssid); - WiFi.begin(ssid, password); + multi.addAP(ssid, password); - while (WiFi.status() != WL_CONNECTED) { - delay(500); - Serial.print("."); + if (multi.run() != WL_CONNECTED) { + Serial.println("Unable to connect to network, rebooting in 10 seconds..."); + delay(10000); + rp2040.reboot(); } Serial.println(""); diff --git a/libraries/WiFi/keywords.txt b/libraries/WiFi/keywords.txt index 6303cafc6..6972f5c06 100644 --- a/libraries/WiFi/keywords.txt +++ b/libraries/WiFi/keywords.txt @@ -13,6 +13,7 @@ WiFiClient KEYWORD1 WiFiSSLClient KEYWORD1 WiFiServer KEYWORD1 WiFiUDP KEYWORD1 +WiFiMulti KEYWORD1 NTP KEYWORD1 @@ -41,6 +42,7 @@ gatewayIP KEYWORD2 SSID KEYWORD2 BSSID KEYWORD2 RSSI KEYWORD2 +channel KEYWORD2 encryptionType KEYWORD2 beginPacket KEYWORD2 endPacket KEYWORD2 @@ -48,19 +50,41 @@ parsePacket KEYWORD2 remoteIP KEYWORD2 remotePort KEYWORD2 mode KEYWORD2 +addAP KEYWORD2 beginAP KEYWORD2 beginEnterprise KEYWORD2 setHostname KEYWORD2 end KEYWORD2 getTime KEYWORD2 -lowPowerMode KEYWORD2 +aggressiveLowPowerMode KEYWORD2 +defaultLowPowerMode KEYWORD2 noLowPowerMode KEYWORD2 ping KEYWORD2 beginMulticast KEYWORD2 setTimeout KEYWORD2 waitSet KEYWORD2 +setSession KEYWORD2 +setInsecure KEYWORD2 +setKnownKey KEYWORD2 +setFingerprint KEYWORD2 +allowSelfSignedCerts KEYWORD2 +setTrustAnchors KEYWORD2 +setX509Time KEYWORD2 +setClientRSACert KEYWORD2 +setClientECCert KEYWORD2 +setBufferSizes KEYWORD2 +setCertStore KEYWORD2 +setCiphers KEYWORD2 +setCiphersLessSecure KEYWORD2 +setSSLVersion KEYWORD2 +setCACert KEYWORD2 +setCertificate KEYWORD2 +setPrivateKey KEYWORD2 +loadCACert KEYWORD2 +loadCertificate KEYWORD2 +loadPrivateKey KEYWORD2 ####################################### # Constants (LITERAL1) diff --git a/libraries/WiFi/src/BearSSLHelpers.cpp b/libraries/WiFi/src/BearSSLHelpers.cpp index 0def53b95..6755d7345 100644 --- a/libraries/WiFi/src/BearSSLHelpers.cpp +++ b/libraries/WiFi/src/BearSSLHelpers.cpp @@ -29,7 +29,8 @@ #include #include #include "StackThunk.h" -//#include + +#include #ifndef ARDUINO_SIGNING #define ARDUINO_SIGNING 0 #endif diff --git a/libraries/WiFi/src/ESP8266WiFiMulti.h b/libraries/WiFi/src/ESP8266WiFiMulti.h new file mode 100644 index 000000000..f00d14ff3 --- /dev/null +++ b/libraries/WiFi/src/ESP8266WiFiMulti.h @@ -0,0 +1,4 @@ +// Since things may just work, we'll redirect for now +#include "WiFiMulti.h" + +using ESP8266WiFiMulti = WiFiMulti; diff --git a/libraries/WiFi/src/WiFi.h b/libraries/WiFi/src/WiFi.h index 6da901ac8..206bf0a2e 100644 --- a/libraries/WiFi/src/WiFi.h +++ b/libraries/WiFi/src/WiFi.h @@ -3,8 +3,6 @@ #include "wl_definitions.h" #include "wl_types.h" -#include "LWIPMutex.h" - #include "WiFiClass.h" #include "WiFiClient.h" #include "WiFiServer.h" @@ -12,4 +10,6 @@ #include "WiFiServerSecure.h" #include "WiFiUdp.h" +#include "WiFiMulti.h" + #include "WiFiNTP.h" diff --git a/libraries/WiFi/src/WiFiClass.cpp b/libraries/WiFi/src/WiFiClass.cpp index f92282a40..c0fe792f6 100644 --- a/libraries/WiFi/src/WiFiClass.cpp +++ b/libraries/WiFi/src/WiFiClass.cpp @@ -44,17 +44,20 @@ const char* WiFiClass::firmwareVersion() { return PICO_SDK_VERSION_STRING; } -void WiFiClass::mode(_wifiModeESP m) { +void WiFiClass::mode(WiFiMode_t m) { _calledESP = true; switch (m) { - case WIFI_OFF: + case WiFiMode_t::WIFI_OFF: end(); break; - case WIFI_AP: - _modeESP = WIFI_AP; + case WiFiMode_t::WIFI_AP: + _modeESP = WiFiMode_t::WIFI_AP; break; - case WIFI_STA: - _modeESP = WIFI_STA; + case WiFiMode_t::WIFI_STA: + _modeESP = WiFiMode_t::WIFI_STA; + break; + case WiFiMode_t::WIFI_AP_STA: + _modeESP = WiFiMode_t::WIFI_STA; break; } } @@ -68,6 +71,10 @@ int WiFiClass::begin(const char* ssid) { return begin(ssid, nullptr); } +int WiFiClass::beginBSSID(const char* ssid, const uint8_t *bssid) { + return begin(ssid, nullptr, bssid); +} + #ifdef ARDUINO_RASPBERRY_PI_PICO_W /* Start WiFi connection with passphrase the most secure supported mode will be automatically selected @@ -76,7 +83,7 @@ int WiFiClass::begin(const char* ssid) { param passphrase: Passphrase. Valid characters in a passphrase must be between ASCII 32-126 (decimal). */ -int WiFiClass::begin(const char* ssid, const char *passphrase) { +int WiFiClass::begin(const char* ssid, const char *passphrase, const uint8_t *bssid) { // Simple ESP8266 compatibility hack if (_modeESP == WIFI_AP) { return beginAP(ssid, passphrase); @@ -86,7 +93,13 @@ int WiFiClass::begin(const char* ssid, const char *passphrase) { _ssid = ssid; _password = passphrase; - _wifi.setSSID(ssid); + if (bssid) { + memcpy(_bssid, bssid, sizeof(_bssid)); + } else { + bzero(_bssid, sizeof(_bssid)); + } + _wifi.setSSID(_ssid.c_str()); + _wifi.setBSSID(_bssid); _wifi.setPassword(passphrase); _wifi.setTimeout(_timeout); _wifi.setSTA(); @@ -96,6 +109,9 @@ int WiFiClass::begin(const char* ssid, const char *passphrase) { if (!_wifi.begin()) { return WL_IDLE_STATUS; } + noLowPowerMode(); + // Enable CYW43 event debugging (make sure Debug Port is set) + //cyw43_state.trace_flags = 0xffff; while (!_calledESP && ((millis() - start < (uint32_t)2 * _timeout)) && !connected()) { delay(10); } @@ -121,7 +137,7 @@ uint8_t WiFiClass::beginAP(const char *ssid, const char* passphrase) { _ssid = ssid; _password = passphrase; - _wifi.setSSID(ssid); + _wifi.setSSID(_ssid.c_str()); _wifi.setPassword(passphrase); _wifi.setTimeout(_timeout); _wifi.setAP(); @@ -129,6 +145,7 @@ uint8_t WiFiClass::beginAP(const char *ssid, const char* passphrase) { if (!_wifi.begin()) { return WL_IDLE_STATUS; } + noLowPowerMode(); IPAddress gw = _wifi.gatewayIP(); if (!gw.isSet()) { gw = IPAddress(192, 168, 42, 1); @@ -151,8 +168,24 @@ uint8_t WiFiClass::beginAP(const char *ssid, const char* passphrase) { } #endif +uint8_t WiFiClass::softAPgetStationNum() { + if (!_apMode || !_wifiHWInitted) { + return 0; + } + int m; + cyw43_wifi_ap_get_max_stas(&cyw43_state, &m); + uint8_t *macs = (uint8_t*)malloc(m * 6); + if (!macs) { + return 0; + } + cyw43_wifi_ap_get_stas(&cyw43_state, &m, macs); + free(macs); + return m; +} + + bool WiFiClass::connected() { - return (_apMode && _wifiHWInitted) || (_wifi.connected() && localIP().isSet()); + return (_apMode && _wifiHWInitted) || (_wifi.connected() && localIP().isSet() && (cyw43_wifi_link_status(&cyw43_state, _apMode ? 1 : 0) == CYW43_LINK_JOIN)); } /* Change Ip configuration settings disabling the dhcp client @@ -223,23 +256,26 @@ void WiFiClass::setDNS(IPAddress dns_server1, IPAddress dns_server2) { void WiFiClass::setHostname(const char* name) { _wifi.setHostname(name); } +const char *WiFiClass::getHostname() { + return _wifi.getHostname(); +} /* Disconnect from the network return: one value of wl_status_t enum */ -int WiFiClass::disconnect(void) { - if (_wifiHWInitted) { - cyw43_wifi_leave(&cyw43_state, _apMode ? 1 : 0); - } - _wifiHWInitted = false; +int WiFiClass::disconnect(bool wifi_off __unused) { if (_dhcpServer) { dhcp_server_deinit(_dhcpServer); free(_dhcpServer); _dhcpServer = nullptr; } - _wifi.end(); + if (_wifiHWInitted) { + _wifiHWInitted = false; + cyw43_wifi_leave(&cyw43_state, _apMode ? 1 : 0); + _wifi.end(); + } return WL_DISCONNECTED; } @@ -295,7 +331,7 @@ IPAddress WiFiClass::gatewayIP() { return: ssid string */ -const char* WiFiClass::SSID() { +const String &WiFiClass::SSID() { return _ssid; } @@ -306,11 +342,33 @@ const char* WiFiClass::SSID() { return: pointer to uint8_t array with length WL_MAC_ADDR_LENGTH */ uint8_t* WiFiClass::BSSID(uint8_t* bssid) { - // TODO - driver does not return this?! - memset(bssid, 0xee, WL_MAC_ADDR_LENGTH); +#ifndef CYW43_IOCTL_GET_BSSID +#define CYW43_IOCTL_GET_BSSID ( (uint32_t)23 * 2 ) +#endif + + if (_wifi.connected()) { + cyw43_ioctl(&cyw43_state, CYW43_IOCTL_GET_BSSID, WL_MAC_ADDR_LENGTH, bssid, CYW43_ITF_STA); + } else { + memset(bssid, 0, WL_MAC_ADDR_LENGTH); + } return bssid; } +int WiFiClass::channel() { +#ifndef CYW43_IOCTL_GET_CHANNEL +#define CYW43_IOCTL_GET_CHANNEL 0x3a +#endif + + int32_t channel; + if (_wifi.connected()) { + cyw43_ioctl(&cyw43_state, CYW43_IOCTL_GET_CHANNEL, sizeof channel, (uint8_t *)&channel, CYW43_ITF_STA); + } else { + channel = -1; + } + return channel; +} + + /* Return the current RSSI /Received Signal Strength in dBm) associated with the network @@ -318,8 +376,17 @@ uint8_t* WiFiClass::BSSID(uint8_t* bssid) { return: signed value */ int32_t WiFiClass::RSSI() { - // TODO - driver does not return this?! - return 0; +#ifndef CYW43_IOCTL_GET_RSSI +#define CYW43_IOCTL_GET_RSSI 0xFE +#endif + + int32_t rssi; + if (_wifi.connected()) { + cyw43_ioctl(&cyw43_state, CYW43_IOCTL_GET_RSSI, sizeof rssi, (uint8_t *)&rssi, CYW43_ITF_STA); + } else { + rssi = -255; + } + return rssi; } /* @@ -360,7 +427,7 @@ int WiFiClass::_scanCB(void *env, const cyw43_ev_scan_result_t *result) { return: Number of discovered networks */ -int8_t WiFiClass::scanNetworks() { +int8_t WiFiClass::scanNetworks(bool async) { cyw43_wifi_scan_options_t scan_options; memset(&scan_options, 0, sizeof(scan_options)); _scan.clear(); @@ -373,11 +440,27 @@ int8_t WiFiClass::scanNetworks() { if (err) { return 0; } - uint32_t now = millis(); - while (cyw43_wifi_scan_active(&cyw43_state) && (millis() - now < 10000)) { - delay(10); + if (!async) { + uint32_t now = millis(); + while (cyw43_wifi_scan_active(&cyw43_state) && (millis() - now < 10000)) { + delay(10); + } + return _scan.size(); + } else { + return -1; } - return _scan.size(); +} + +int8_t WiFiClass::scanComplete() { + if (cyw43_wifi_scan_active(&cyw43_state)) { + return -1; + } else { + return _scan.size(); + } +} + +void WiFiClass::scanDelete() { + _scan.clear(); } /* @@ -510,14 +593,19 @@ unsigned long WiFiClass::getTime() { return millis(); } -void WiFiClass::lowPowerMode() { +void WiFiClass::aggressiveLowPowerMode() { cyw43_wifi_pm(&cyw43_state, CYW43_AGGRESSIVE_PM); } -void WiFiClass::noLowPowerMode() { +void WiFiClass::defaultLowPowerMode() { cyw43_wifi_pm(&cyw43_state, CYW43_DEFAULT_PM); } +// The difference between the default CYW43_DEFAULT_PM (0xA11142) and not low power (0xA11140) is that it changed from "Powersave mode on specified interface with High throughput" to "No Powersave mode". All other parameters stayed the same. +void WiFiClass::noLowPowerMode() { + cyw43_wifi_pm(&cyw43_state, 0xA11140); +} + int WiFiClass::ping(const char* hostname, uint8_t ttl) { IPAddress ip; if (!hostByName(hostname, ip)) { diff --git a/libraries/WiFi/src/WiFiClass.h b/libraries/WiFi/src/WiFiClass.h index 6e1e86cc4..9d59b83a2 100644 --- a/libraries/WiFi/src/WiFiClass.h +++ b/libraries/WiFi/src/WiFiClass.h @@ -35,7 +35,7 @@ typedef void(*FeedHostProcessorWatchdogFuncPointer)(); -typedef enum { WIFI_STA, WIFI_AP, WIFI_OFF } _wifiModeESP; // For ESP8266 compatibility +typedef enum { WIFI_OFF = 0, WIFI_STA = 1, WIFI_AP = 2, WIFI_AP_STA = 3 } WiFiMode_t; // For ESP8266 compatibility class WiFiClass { public: @@ -46,13 +46,25 @@ class WiFiClass { */ static const char* firmwareVersion(); - void mode(_wifiModeESP m); // For ESP8266 compatibility + void mode(WiFiMode_t m); // For ESP8266 compatibility + + WiFiMode_t getMode() { + if (_wifiHWInitted) { + if (_apMode) { + return WiFiMode_t::WIFI_AP; + } else { + return WiFiMode_t::WIFI_STA; + } + } + return WiFiMode_t::WIFI_OFF; + }; /* Start WiFi connection for OPEN networks param ssid: Pointer to the SSID string. */ int begin(const char* ssid); + int beginBSSID(const char* ssid, const uint8_t *bssid); /* Start WiFi connection with WEP encryption. Configure a key into the device. The key type (WEP-40, WEP-104) @@ -71,10 +83,14 @@ class WiFiClass { param ssid: Pointer to the SSID string. param passphrase: Passphrase. Valid characters in a passphrase must be between ASCII 32-126 (decimal). + param bssid: If non-null, the BSSID associated w/the SSID to connect to */ - int begin(const char* ssid, const char *passphrase); + int begin(const char* ssid, const char *passphrase, const uint8_t *bssid = nullptr); bool connected(); + bool isConnected() { + return connected(); + } int8_t waitForConnectResult(unsigned long timeoutLength = 60000) { uint32_t now = millis(); while (millis() - now < timeoutLength) { @@ -91,6 +107,57 @@ class WiFiClass { uint8_t beginAP(const char *ssid, const char* passphrase); uint8_t beginAP(const char *ssid, const char* passphrase, uint8_t channel); + // ESP8266 compatible calls + bool softAP(const char* ssid, const char* psk = nullptr, int channel = 1, int ssid_hidden = 0, int max_connection = 4) { + (void) ssid_hidden; + (void) max_connection; + return beginAP(ssid, psk, channel) == WL_CONNECTED; + } + + bool softAP(const String& ssid, const String& psk = "", int channel = 1, int ssid_hidden = 0, int max_connection = 4) { + (void) ssid_hidden; + (void) max_connection; + if (psk != "") { + return beginAP(ssid.c_str(), psk.c_str(), channel) == WL_CONNECTED; + } else { + return beginAP(ssid.c_str(), channel) == WL_CONNECTED; + } + } + + bool softAPConfig(IPAddress local_ip, IPAddress gateway, IPAddress subnet) { + config(local_ip, local_ip, gateway, subnet); + return true; + } + + bool softAPdisconnect(bool wifioff = false) { + (void) wifioff; + disconnect(); + return true; + } + + uint8_t softAPgetStationNum(); + + IPAddress softAPIP() { + return localIP(); + } + + uint8_t* softAPmacAddress(uint8_t* mac) { + return macAddress(mac); + } + + String softAPmacAddress(void) { + uint8_t mac[8]; + macAddress(mac); + char buff[32]; + sprintf(buff, "%02x:%02x:%02x:%02x:%02x:%02x", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); + return String(buff); + } + + String softAPSSID() { + return SSID(); + } + + // TODO - EAP is not supported by the driver. Maybe some way of user-level wap-supplicant in the future? //uint8_t beginEnterprise(const char* ssid, const char* username, const char* password); //uint8_t beginEnterprise(const char* ssid, const char* username, const char* password, const char* identity); @@ -147,13 +214,14 @@ class WiFiClass { */ void setHostname(const char* name); + const char *getHostname(); /* Disconnect from the network return: one value of wl_status_t enum */ - int disconnect(void); + int disconnect(bool wifi_off = false); void end(void); @@ -163,6 +231,13 @@ class WiFiClass { return: pointer to uint8_t array with length WL_MAC_ADDR_LENGTH */ uint8_t* macAddress(uint8_t* mac); + String macAddress(void) { + uint8_t mac[8]; + macAddress(mac); + char buff[32]; + sprintf(buff, "%02x:%02x:%02x:%02x:%02x:%02x", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); + return String(buff); + } /* Get the interface IP address. @@ -190,7 +265,7 @@ class WiFiClass { return: ssid string */ - const char* SSID(); + const String &SSID(); /* Return the current BSSID associated with the network. @@ -208,6 +283,10 @@ class WiFiClass { */ int32_t RSSI(); + + /* Return the current network channel */ + int channel(); + /* Return the Encryption Type associated with the network @@ -218,9 +297,23 @@ class WiFiClass { /* Start scan WiFi networks available + param async: whether to perform asynchronous scan + return: Number of discovered networks */ - int8_t scanNetworks(); + int8_t scanNetworks(bool async = false); + + /* + Return number of scanned WiFi networks + + return: Number of discovered networks + */ + int8_t scanComplete(); + + /* + Delete scan results + */ + void scanDelete(); /* Return the SSID discovered during the network scan. @@ -280,7 +373,8 @@ class WiFiClass { unsigned long getTime(); - void lowPowerMode(); + void aggressiveLowPowerMode(); + void defaultLowPowerMode(); void noLowPowerMode(); int ping(const char* hostname, uint8_t ttl = 128); @@ -292,10 +386,20 @@ class WiFiClass { void setFeedWatchdogFunc(FeedHostProcessorWatchdogFuncPointer func); void feedWatchdog(); + // ESP8266 compatibility + void persistent(bool unused) { + (void) unused; + } + + void hostname(const char *name) { + setHostname(name); + } + private: - int _timeout = 10000; - const char * _ssid = nullptr; - const char * _password = nullptr; + int _timeout = 15000; + String _ssid; + uint8_t _bssid[6]; + String _password; bool _wifiHWInitted = false; bool _apMode = false; @@ -308,7 +412,7 @@ class WiFiClass { // ESP compat bool _calledESP = false; // Should we behave like the ESP8266 for connect? - _wifiModeESP _modeESP = WIFI_STA; + WiFiMode_t _modeESP = WIFI_STA; }; extern WiFiClass WiFi; diff --git a/libraries/WiFi/src/WiFiClient.cpp b/libraries/WiFi/src/WiFiClient.cpp index cf6112e5e..32df6b01d 100644 --- a/libraries/WiFi/src/WiFiClient.cpp +++ b/libraries/WiFi/src/WiFiClient.cpp @@ -130,8 +130,6 @@ int WiFiClient::connect(IPAddress ip, uint16_t port) { _client = nullptr; } - LWIPMutex m; // Block the timer sys_check_timeouts call - tcp_pcb* pcb = tcp_new(); if (!pcb) { return 0; @@ -201,18 +199,13 @@ size_t WiFiClient::write(const uint8_t *buf, size_t size) { return _client->write((const char*)buf, size); } -//TODO - implement! -//size_t WiFiClient::write(Stream& stream) -//{ -// // (this method is deprecated) -// -// if (!_client || !stream.available()) -// { -// return 0; -// } -// // core up to 2.7.4 was equivalent to this -// return _client->write(stream); -//} +size_t WiFiClient::write(Stream& stream) { + if (!_client || !stream.available()) { + return 0; + } + _client->setTimeout(_timeout); + return _client->write(stream); +} int WiFiClient::available() { if (!_client) { diff --git a/libraries/WiFi/src/WiFiClient.h b/libraries/WiFi/src/WiFiClient.h index ff8459dcf..71b71e91f 100644 --- a/libraries/WiFi/src/WiFiClient.h +++ b/libraries/WiFi/src/WiFiClient.h @@ -23,7 +23,6 @@ #pragma once #include -#include "WiFi.h" #include "Print.h" #include "Client.h" #include "IPAddress.h" @@ -71,7 +70,7 @@ class WiFiClient : public Client, public SList { virtual int connect(const String& host, uint16_t port); virtual size_t write(uint8_t) override; virtual size_t write(const uint8_t *buf, size_t size) override; - //size_t write(Stream& stream); + size_t write(Stream& stream); virtual int available() override; virtual int read() override; diff --git a/libraries/WiFi/src/WiFiClientSecureBearSSL.cpp b/libraries/WiFi/src/WiFiClientSecureBearSSL.cpp index 913ab4d8e..8d951dca7 100644 --- a/libraries/WiFi/src/WiFiClientSecureBearSSL.cpp +++ b/libraries/WiFi/src/WiFiClientSecureBearSSL.cpp @@ -784,7 +784,7 @@ extern "C" { // Return the public key from the validator (set by x509_minimal) static const br_x509_pkey *insecure_get_pkey(const br_x509_class *const *ctx, unsigned *usages) { const br_x509_insecure_context *xc = (const br_x509_insecure_context *)ctx; - if (usages != NULL) { + if (usages != nullptr) { *usages = BR_KEYTYPE_KEYX | BR_KEYTYPE_SIGN; // I said we were insecure! } return &xc->ctx.pkey; @@ -1224,7 +1224,7 @@ bool WiFiClientSecureCtx::_connectSSL(const char* hostName) { _x509_insecure = nullptr; _x509_knownkey = nullptr; - // reduce timeout after successful handshake to fail fast if server stop accepting our data for whathever reason + // reduce timeout after successful handshake to fail fast if server stop accepting our data for whatever reason if (ret) { _timeout = 5000; } diff --git a/libraries/WiFi/src/WiFiClientSecureBearSSL.h b/libraries/WiFi/src/WiFiClientSecureBearSSL.h index d94789637..eff716e1f 100644 --- a/libraries/WiFi/src/WiFiClientSecureBearSSL.h +++ b/libraries/WiFi/src/WiFiClientSecureBearSSL.h @@ -125,7 +125,7 @@ class WiFiClientSecureCtx : public WiFiClient { } // Return an error code and possibly a text string in a passed-in buffer with last SSL failure - int getLastSSLError(char *dest = NULL, size_t len = 0); + int getLastSSLError(char *dest = nullptr, size_t len = 0); // Attach a preconfigured certificate store void setCertStore(CertStoreBase *certStore) { @@ -291,7 +291,7 @@ class WiFiClientSecureCtx : public WiFiClient { const PublicKey *_knownkey; unsigned _knownkey_usages; - // Custom cipher list pointer or NULL if default + // Custom cipher list pointer or nullptr if default std::shared_ptr _cipher_list; uint8_t _cipher_cnt; @@ -490,7 +490,7 @@ class WiFiClientSecure : public WiFiClient { } // Return an error code and possibly a text string in a passed-in buffer with last SSL failure - int getLastSSLError(char *dest = NULL, size_t len = 0) { + int getLastSSLError(char *dest = nullptr, size_t len = 0) { return _ctx->getLastSSLError(dest, len); } diff --git a/libraries/WiFi/src/WiFiMulti.cpp b/libraries/WiFi/src/WiFiMulti.cpp new file mode 100644 index 000000000..b33199ebb --- /dev/null +++ b/libraries/WiFi/src/WiFiMulti.cpp @@ -0,0 +1,123 @@ +/* + WiFiMulti.cpp - Choose best RSSI and connect + Copyright (c) 2022 Earle F. Philhower, III + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Modified by Ivan Grokhotkov, January 2015 - esp8266 support +*/ + +#include "WiFi.h" +#include +#include + +WiFiMulti::WiFiMulti() { +} + +WiFiMulti::~WiFiMulti() { + while (!_list.empty()) { + struct _AP ap = _list.front(); + _list.pop_front(); + free(ap.ssid); + free(ap.pass); + } +} + +bool WiFiMulti::addAP(const char *ssid, const char *pass) { + struct _AP ap; + if (!ssid) { + return false; + } + ap.ssid = strdup(ssid); + if (!ap.ssid) { + return false; + } + if (pass) { + ap.pass = strdup(pass); + if (!ap.pass) { + free(ap.ssid); + return false; + } + } else { + ap.pass = nullptr; + } + DEBUGV("[WIFIMULTI] Adding: '%s' %s' to list\n", ap.ssid, ap.pass); + _list.push_front(ap); + return true; +} + +uint8_t WiFiMulti::run(uint32_t to) { + struct _scanAP { + char *ssid; + char *psk; + uint8_t bssid[6]; + int rssi; + }; + std::list _scanList; + + // If we're already connected, don't re-scan/etc. + if (WiFi.status() == WL_CONNECTED) { + return WL_CONNECTED; + } + + DEBUGV("[WIFIMULTI] Rescanning to build new list of APs\n"); + int cnt = WiFi.scanNetworks(); + if (!cnt) { + return WL_DISCONNECTED; + } + + // Add all matching ones to the scanList + for (int i = 0; i < cnt; i++) { + for (auto j = _list.begin(); j != _list.end(); j++) { + if (!strcmp(j->ssid, WiFi.SSID(i))) { + _scanAP itm; + itm.ssid = j->ssid; + itm.psk = j->pass; + WiFi.BSSID(i, itm.bssid); + itm.rssi = WiFi.RSSI(i); + _scanList.push_front(itm); + } + } + } + // Sort by RSSI using C++ lambda magic + _scanList.sort([](const struct _scanAP & a, const struct _scanAP & b) { + return a.rssi > b.rssi; + }); + for (auto j = _scanList.begin(); j != _scanList.end(); j++) { + DEBUGV("[WIFIMULTI] scanList: SSID: '%s' -- BSSID: '%02X%02X%02X%02X%02X%02X' -- RSSI: %d\n", j->ssid, + j->bssid[0], j->bssid[1], j->bssid[2], j->bssid[3], j->bssid[4], j->bssid[5], j->rssi); + } + + // Attempt to connect to each (will be in order of decreasing RSSI) + for (auto j = _scanList.begin(); j != _scanList.end(); j++) { + DEBUGV("[WIFIMULTI] Connecting to: SSID: '%s' -- BSSID: '%02X%02X%02X%02X%02X%02X' -- RSSI: %d\n", j->ssid, + j->bssid[0], j->bssid[1], j->bssid[2], j->bssid[3], j->bssid[4], j->bssid[5], j->rssi); + uint32_t start = millis(); + if (j->psk) { + WiFi.begin(j->ssid, j->psk, j->bssid); + } else { + WiFi.beginBSSID(j->ssid, j->bssid); + } + while (!WiFi.connected() && (millis() - start < to)) { + delay(5); + } + if (WiFi.status() == WL_CONNECTED) { + return WL_CONNECTED; + } + } + + // Failed at this point... + return WiFi.status(); +} diff --git a/cores/rp2040/LWIPMutex.h b/libraries/WiFi/src/WiFiMulti.h similarity index 58% rename from cores/rp2040/LWIPMutex.h rename to libraries/WiFi/src/WiFiMulti.h index 02220a706..5fea2aee2 100644 --- a/cores/rp2040/LWIPMutex.h +++ b/libraries/WiFi/src/WiFiMulti.h @@ -1,10 +1,6 @@ /* - WiFiMutex.h - Ensure the timer-driven sys_check_timeouts doesn't - get executed while we're in the user-level TCP stack. - Copyright (c) 2022 Earle F. Philhower, III. All rights reserved. - - Implements the API defined by the Arduino WiFiNINA library, - copyright (c) 2018 Arduino SA. All rights reserved. + WiFiMulti.h - Choose best RSSI and connect + Copyright (c) 2022 Earle F. Philhower, III This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public @@ -19,23 +15,29 @@ You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Modified by Ivan Grokhotkov, January 2015 - esp8266 support */ #pragma once -extern "C" volatile bool __inLWIP; +#include +#include +#include "wl_definitions.h" -class LWIPMutex { +class WiFiMulti { public: - LWIPMutex() { - __inLWIP = true; - _ref++; - } - ~LWIPMutex() { - if (0 == --_ref) { - __inLWIP = false; - } - } + WiFiMulti(); + ~WiFiMulti(); + + bool addAP(const char *ssid, const char *pass = nullptr); + + uint8_t run(uint32_t to = 10000); + private: - static int _ref; + struct _AP { + char *ssid; + char *pass; + }; + std::list _list; }; diff --git a/libraries/WiFi/src/WiFiServer.cpp b/libraries/WiFi/src/WiFiServer.cpp index 364c11cda..305606658 100644 --- a/libraries/WiFi/src/WiFiServer.cpp +++ b/libraries/WiFi/src/WiFiServer.cpp @@ -56,8 +56,6 @@ void WiFiServer::begin(uint16_t port, uint8_t backlog) { } _port = port; - LWIPMutex m; // Block the timer sys_check_timeouts call - tcp_pcb* pcb = tcp_new(); if (!pcb) { return; @@ -134,7 +132,6 @@ WiFiClient WiFiServer::accept() { // pcb can be null when peer has already closed the connection if (_unclaimed->getPCB()) { - LWIPMutex m; // Block the timer sys_check_timeouts call // give permission to lwIP to accept one more peer tcp_backlog_accepted(_unclaimed->getPCB()); } @@ -162,7 +159,6 @@ void WiFiServer::close() { if (!_listen_pcb) { return; } - LWIPMutex m; // Block the timer sys_check_timeouts call tcp_close(_listen_pcb); _listen_pcb = nullptr; } @@ -197,7 +193,6 @@ err_t WiFiServer::_accept(tcp_pcb* apcb, err_t err) { // https://www.nongnu.org/lwip/2_1_x/group__tcp__raw.html#gaeff14f321d1eecd0431611f382fcd338 // increase lwIP's backlog - LWIPMutex m; // Block the timer sys_check_timeouts call tcp_backlog_delayed(apcb); _unclaimed = slist_append_tail(_unclaimed, client); diff --git a/libraries/WiFi/src/WiFiServer.h b/libraries/WiFi/src/WiFiServer.h index 669e3e933..78b3c6da2 100644 --- a/libraries/WiFi/src/WiFiServer.h +++ b/libraries/WiFi/src/WiFiServer.h @@ -24,7 +24,6 @@ #include struct tcp_pcb; -#include #include #include #include @@ -79,7 +78,8 @@ class WiFiServer { WiFiServer(uint16_t port); virtual ~WiFiServer() {} WiFiClient accept(); // https://www.arduino.cc/en/Reference/EthernetServerAccept - WiFiClient available(uint8_t* status = NULL); + WiFiClient available(uint8_t* status = nullptr); + bool hasClient(); // hasClientData(): // returns the amount of data available from the first client diff --git a/libraries/WiFi/src/WiFiServerSecureBearSSL.h b/libraries/WiFi/src/WiFiServerSecureBearSSL.h index c3c6e8783..511ebd13d 100644 --- a/libraries/WiFi/src/WiFiServerSecureBearSSL.h +++ b/libraries/WiFi/src/WiFiServerSecureBearSSL.h @@ -65,7 +65,7 @@ class WiFiServerSecure : public WiFiServer { // If awaiting connection available and authenticated (i.e. client cert), return it. WiFiClientSecure accept(); // https://www.arduino.cc/en/Reference/EthernetServerAccept - WiFiClientSecure available(uint8_t* status = NULL) __attribute__((deprecated("Renamed to accept()."))); + WiFiClientSecure available(uint8_t* status = nullptr); WiFiServerSecure& operator=(const WiFiServerSecure&) = default; diff --git a/libraries/WiFi/src/WiFiUdp.cpp b/libraries/WiFi/src/WiFiUdp.cpp index 74a4c7e1c..c6838d680 100644 --- a/libraries/WiFi/src/WiFiUdp.cpp +++ b/libraries/WiFi/src/WiFiUdp.cpp @@ -38,7 +38,7 @@ template<> WiFiUDP* SList::_s_first = 0; /* Constructor */ -WiFiUDP::WiFiUDP() : _ctx(0) { +WiFiUDP::WiFiUDP() : _ctx(0), _multicast(false) { WiFiUDP::_add(this); } @@ -48,6 +48,7 @@ WiFiUDP::WiFiUDP(const WiFiUDP& other) { _ctx->ref(); } WiFiUDP::_add(this); + _multicast = other._multicast; } WiFiUDP& WiFiUDP::operator=(const WiFiUDP& rhs) { @@ -97,6 +98,12 @@ uint8_t WiFiUDP::beginMulticast(IPAddress interfaceAddr, IPAddress multicast, ui return 1; } +uint8_t WiFiUDP::beginMulticast(IPAddress addr, uint16_t port) { + auto ret = beginMulticast(IP_ADDR_ANY, addr, port); + _multicast = true; + return ret; +} + /* return number of bytes available in the current packet, will return zero if parsePacket hasn't been called yet */ int WiFiUDP::available() { @@ -137,7 +144,13 @@ int WiFiUDP::beginPacket(IPAddress ip, uint16_t port) { _ctx = new UdpContext; _ctx->ref(); } - return (_ctx->connect(ip, port)) ? 1 : 0; + auto ret = (_ctx->connect(ip, port)) ? 1 : 0; + if (_multicast) { + _ctx->setMulticastInterface(IP_ADDR_ANY); + _ctx->setMulticastTTL(255); + } + return ret; + } int WiFiUDP::beginPacketMulticast(IPAddress multicastAddress, uint16_t port, diff --git a/libraries/WiFi/src/WiFiUdp.h b/libraries/WiFi/src/WiFiUdp.h index c455a66b6..15b2c75ea 100644 --- a/libraries/WiFi/src/WiFiUdp.h +++ b/libraries/WiFi/src/WiFiUdp.h @@ -44,9 +44,12 @@ class WiFiUDP : public UDP, public SList { // initialize, start listening on specified port. // Returns 1 if successful, 0 if there are no sockets available to use - uint8_t begin(uint16_t port) override; + virtual uint8_t begin(uint16_t port) override; + // initialize, start listening on specified multicast IP address and port. Returns 1 if successful, 0 if there are no sockets available to use + virtual uint8_t beginMulticast(IPAddress, uint16_t) override; + // Finish with the UDP connection - void stop() override; + virtual void stop() override; // join a multicast group and listen on the given port uint8_t beginMulticast(IPAddress interfaceAddr, IPAddress multicast, uint16_t port); @@ -110,4 +113,6 @@ class WiFiUDP : public UDP, public SList { static void stopAll(); static void stopAllExcept(WiFiUDP * exC); +private: + bool _multicast; }; diff --git a/libraries/WiFi/src/dhcpserver/dhcpserver.c b/libraries/WiFi/src/dhcpserver/dhcpserver.c index cc4f89c88..c02ead5e9 100644 --- a/libraries/WiFi/src/dhcpserver/dhcpserver.c +++ b/libraries/WiFi/src/dhcpserver/dhcpserver.c @@ -63,7 +63,7 @@ #define PORT_DHCP_SERVER (67) #define PORT_DHCP_CLIENT (68) -#define DEFAULT_DNS MAKE_IP4(8, 8, 8, 8) +//#define DEFAULT_DNS MAKE_IP4(8, 8, 8, 8) #define DEFAULT_LEASE_TIME_S (24 * 60 * 60) // in seconds #define MAC_LEN (6) @@ -184,8 +184,8 @@ static void dhcp_server_process(void *arg, struct udp_pcb *upcb, struct pbuf *p, (void)src_addr; (void)src_port; - // This is around 548 bytes - dhcp_msg_t dhcp_msg; + // This is around 548 bytes, so make static so it will live in the heap, not the stack (too large) + static dhcp_msg_t dhcp_msg; #define DHCP_MIN_SIZE (240 + 3) if (p->tot_len < DHCP_MIN_SIZE) { @@ -276,9 +276,10 @@ static void dhcp_server_process(void *arg, struct udp_pcb *upcb, struct pbuf *p, opt_write_n(&opt, DHCP_OPT_SERVER_ID, 4, ip_2_ip4(&d->ip)); opt_write_n(&opt, DHCP_OPT_SUBNET_MASK, 4, ip_2_ip4(&d->nm)); opt_write_n(&opt, DHCP_OPT_ROUTER, 4, ip_2_ip4(&d->ip)); // aka gateway; can have multiple addresses - opt_write_u32(&opt, DHCP_OPT_DNS, DEFAULT_DNS); // can have multiple addresses + opt_write_n(&opt, DHCP_OPT_DNS, 4, ip_2_ip4(&d->ip)); // can have multiple addresses opt_write_u32(&opt, DHCP_OPT_IP_LEASE_TIME, DEFAULT_LEASE_TIME_S); *opt++ = DHCP_OPT_END; + dhcp_socket_sendto(&d->udp, &dhcp_msg, opt - (uint8_t *)&dhcp_msg, 0xffffffff, PORT_DHCP_CLIENT); ignore_request: diff --git a/libraries/WiFi/src/include/ClientContext.h b/libraries/WiFi/src/include/ClientContext.h index d7e6ce0f1..8cb4be224 100644 --- a/libraries/WiFi/src/include/ClientContext.h +++ b/libraries/WiFi/src/include/ClientContext.h @@ -27,6 +27,8 @@ class WiFiClient; typedef void (*discard_cb_t)(void*, ClientContext*); #include +#include "lwip/timeouts.h" + //#include //#include @@ -36,6 +38,7 @@ template inline void esp_delay(const uint32_t timeout_ms, T&& blocked, const uint32_t intvl_ms) { const auto start_ms = millis(); while ((((uint32_t)millis() - start_ms) < timeout_ms) && blocked()) { + sys_check_timeouts(); delay(intvl_ms); } } @@ -63,12 +66,11 @@ class ClientContext { err_t abort() { if (_pcb) { DEBUGV(":abort\r\n"); - tcp_arg(_pcb, NULL); - tcp_sent(_pcb, NULL); - tcp_recv(_pcb, NULL); - tcp_err(_pcb, NULL); - tcp_poll(_pcb, NULL, 0); - LWIPMutex m; // Block the timer sys_check_timeouts call + tcp_arg(_pcb, nullptr); + tcp_sent(_pcb, nullptr); + tcp_recv(_pcb, nullptr); + tcp_err(_pcb, nullptr); + tcp_poll(_pcb, nullptr, 0); tcp_abort(_pcb); _pcb = nullptr; } @@ -79,12 +81,11 @@ class ClientContext { err_t err = ERR_OK; if (_pcb) { DEBUGV(":close\r\n"); - tcp_arg(_pcb, NULL); - tcp_sent(_pcb, NULL); - tcp_recv(_pcb, NULL); - tcp_err(_pcb, NULL); - tcp_poll(_pcb, NULL, 0); - LWIPMutex m; // Block the timer sys_check_timeouts call + tcp_arg(_pcb, nullptr); + tcp_sent(_pcb, nullptr); + tcp_recv(_pcb, nullptr); + tcp_err(_pcb, nullptr); + tcp_poll(_pcb, nullptr, 0); err = tcp_close(_pcb); if (err != ERR_OK) { DEBUGV(":tc err %d\r\n", (int) err); @@ -136,7 +137,6 @@ class ClientContext { ip6_addr_assign_zone(ip_2_ip6(addr), IP6_UNKNOWN, netif_default); } #endif - LWIPMutex m; // Block the timer sys_check_timeouts call err_t err = tcp_connect(_pcb, addr, port, &ClientContext::_s_connected); if (err != ERR_OK) { return 0; @@ -162,7 +162,6 @@ class ClientContext { } size_t availableForWrite() const { - LWIPMutex m; // Block the timer sys_check_timeouts call return _pcb ? tcp_sndbuf(_pcb) : 0; } @@ -170,7 +169,6 @@ class ClientContext { if (!_pcb) { return; } - LWIPMutex m; // Block the timer sys_check_timeouts call if (nodelay) { tcp_nagle_disable(_pcb); } else { @@ -182,7 +180,6 @@ class ClientContext { if (!_pcb) { return false; } - LWIPMutex m; // Block the timer sys_check_timeouts call return tcp_nagle_disabled(_pcb); } @@ -300,7 +297,6 @@ class ClientContext { if (!_rx_buf) { return; } - LWIPMutex m; // Block the timer sys_check_timeouts call if (_pcb) { tcp_recved(_pcb, (size_t) _rx_buf->tot_len); } @@ -332,8 +328,9 @@ class ClientContext { return false; } - LWIPMutex m; // Block the timer sys_check_timeouts call - + if (!_pcb) { + return false; + } // force lwIP to send what can be sent tcp_output(_pcb); @@ -374,6 +371,33 @@ class ClientContext { return _write_from_source(ds, dl); } + size_t write(Stream& stream) { + if (!_pcb) { + return 0; + } + size_t sent = 0; + uint8_t buff[256]; + while (stream.available()) { + // Stream only lets you read 1 byte at a time, so buffer in local copy + size_t i; + for (i = 0; (i < sizeof(buff)) && stream.available(); i++) { + buff[i] = stream.read(); + } + if (i) { + // Send as a single packet + int len = write((const char *)buff, i); + sent += len; + if (len != (int)i) { + break; // Write error... + } + } else { + // Out of data... + break; + } + } + return sent; + } + void keepAlive(uint16_t idle_sec = TCP_DEFAULT_KEEPALIVE_IDLE_SEC, uint16_t intv_sec = TCP_DEFAULT_KEEPALIVE_INTERVAL_SEC, uint8_t count = TCP_DEFAULT_KEEPALIVE_COUNT) { if (idle_sec && intv_sec && count) { _pcb->so_options |= SOF_KEEPALIVE; @@ -500,7 +524,9 @@ class ClientContext { const auto remaining = _datalen - _written; size_t next_chunk_size; { - LWIPMutex m; // Block the timer sys_check_timeouts call, just for this call + if (!_pcb) { + return false; + } next_chunk_size = std::min((size_t)tcp_sndbuf(_pcb), remaining); // Potentially reduce transmit size if we are tight on memory, but only if it doesn't return a 0 chunk size if (next_chunk_size > (size_t)(1 << scale)) { @@ -529,6 +555,9 @@ class ClientContext { flags |= TCP_WRITE_FLAG_COPY; } + if (!_pcb) { + return false; + } err_t err = tcp_write(_pcb, buf, next_chunk_size, flags); DEBUGV(":wrc %d %d %d\r\n", next_chunk_size, remaining, (int)err); @@ -550,11 +579,10 @@ class ClientContext { } } - if (has_written) { + if (has_written && _pcb) { // lwIP's tcp_output doc: "Find out what we can send and send it" // *with respect to Nagle* // more info: https://lists.gnu.org/archive/html/lwip-users/2017-11/msg00134.html - LWIPMutex m; // Block the timer sys_check_timeouts call tcp_output(_pcb); } @@ -579,7 +607,6 @@ class ClientContext { void _consume(size_t size) { ptrdiff_t left = _rx_buf->len - _rx_buf_offset - size; - LWIPMutex m; // Block the timer sys_check_timeouts call if (left > 0) { _rx_buf_offset += size; } else if (!_rx_buf->next) { @@ -621,7 +648,6 @@ class ClientContext { if (_rx_buf) { DEBUGV(":rch %d, %d\r\n", _rx_buf->tot_len, pb->tot_len); - LWIPMutex m; // Block the timer sys_check_timeouts call pbuf_cat(_rx_buf, pb); } else { DEBUGV(":rn %d\r\n", pb->tot_len); @@ -633,11 +659,11 @@ class ClientContext { void _error(err_t err) { (void) err; - DEBUGV(":er %d 0x%08x\r\n", (int) err, (uint32_t) _datasource); - tcp_arg(_pcb, NULL); - tcp_sent(_pcb, NULL); - tcp_recv(_pcb, NULL); - tcp_err(_pcb, NULL); + DEBUGV(":er %d 0x%08lx\r\n", (int) err, (uint32_t) _datasource); + tcp_arg(_pcb, nullptr); + tcp_sent(_pcb, nullptr); + tcp_recv(_pcb, nullptr); + tcp_err(_pcb, nullptr); _pcb = nullptr; _notify_error(); } @@ -659,24 +685,44 @@ class ClientContext { return ERR_OK; } + // We may receive a nullptr as arg in the case when an IRQ happens during a shutdown sequence + // In that case, just ignore the CB static err_t _s_recv(void *arg, struct tcp_pcb *tpcb, struct pbuf *pb, err_t err) { - return reinterpret_cast(arg)->_recv(tpcb, pb, err); + if (arg) { + return reinterpret_cast(arg)->_recv(tpcb, pb, err); + } else { + return ERR_OK; + } } static void _s_error(void *arg, err_t err) { - reinterpret_cast(arg)->_error(err); + if (arg) { + reinterpret_cast(arg)->_error(err); + } } static err_t _s_poll(void *arg, struct tcp_pcb *tpcb) { - return reinterpret_cast(arg)->_poll(tpcb); + if (arg) { + return reinterpret_cast(arg)->_poll(tpcb); + } else { + return ERR_OK; + } } static err_t _s_acked(void *arg, struct tcp_pcb *tpcb, uint16_t len) { - return reinterpret_cast(arg)->_acked(tpcb, len); + if (arg) { + return reinterpret_cast(arg)->_acked(tpcb, len); + } else { + return ERR_OK; + } } static err_t _s_connected(void* arg, struct tcp_pcb *pcb, err_t err) { - return reinterpret_cast(arg)->_connected(pcb, err); + if (arg) { + return reinterpret_cast(arg)->_connected(pcb, err); + } else { + return ERR_OK; + } } private: diff --git a/libraries/WiFi/src/include/UdpContext.h b/libraries/WiFi/src/include/UdpContext.h index bf4a6904f..5fa25c560 100644 --- a/libraries/WiFi/src/include/UdpContext.h +++ b/libraries/WiFi/src/include/UdpContext.h @@ -29,6 +29,8 @@ extern "C" { #include #include +#include "lwip/timeouts.h" + //#include #define PBUF_ALIGNER_ADJUST 4 @@ -383,6 +385,7 @@ class UdpContext { uint32_t start = millis(); while (((err = trySend(addr, port, /* keep buffer on error */true)) != ERR_OK) && (millis() - start < timeoutMs)) { delay(1); + sys_check_timeouts(); } if (err != ERR_OK) { cancelBuffer(); // get rid of buffer kept on error after timeout diff --git a/libraries/Wire/src/Wire.cpp b/libraries/Wire/src/Wire.cpp index 4e0d1d429..64674749a 100644 --- a/libraries/Wire/src/Wire.cpp +++ b/libraries/Wire/src/Wire.cpp @@ -140,8 +140,45 @@ void TwoWire::begin(uint8_t addr) { _running = true; } +// See: https://github.com/earlephilhower/arduino-pico/issues/979#issuecomment-1328237128 +#pragma GCC push_options +#pragma GCC optimize ("O0") void TwoWire::onIRQ() { - if (_i2c->hw->intr_stat & (1 << 12)) { + // Make a local copy of the IRQ status up front. If it changes while we're + // running the IRQ callback will fire again after returning. Avoids potential + // race conditions + uint32_t irqstat = _i2c->hw->intr_stat; + if (irqstat == 0) { + return; + } + + // First, pull off any data available + if (irqstat & (1 << 2)) { + // RX_FULL + if (_buffLen < (int)sizeof(_buff)) { + _buff[_buffLen++] = _i2c->hw->data_cmd & 0xff; + } else { + _i2c->hw->data_cmd; + } + } + // RD_REQ + if (irqstat & (1 << 5)) { + if (_onRequestCallback) { + _onRequestCallback(); + } + _i2c->hw->clr_rd_req; + } + // TX_ABRT + if (irqstat & (1 << 6)) { + _i2c->hw->clr_tx_abrt; + } + // START_DET + if (irqstat & (1 << 10)) { + _slaveStartDet = true; + _i2c->hw->clr_start_det; + } + // RESTART_DET + if (irqstat & (1 << 12)) { if (_onReceiveCallback && _buffLen) { _onReceiveCallback(_buffLen); } @@ -150,13 +187,8 @@ void TwoWire::onIRQ() { _slaveStartDet = false; _i2c->hw->clr_restart_det; } - if (_i2c->hw->intr_stat & (1 << 10)) { - _buffLen = 0; - _buffOff = 0; - _slaveStartDet = true; - _i2c->hw->clr_start_det; - } - if (_i2c->hw->intr_stat & (1 << 9)) { + // STOP_DET + if (irqstat & (1 << 9)) { if (_onReceiveCallback && _buffLen) { _onReceiveCallback(_buffLen); } @@ -165,26 +197,8 @@ void TwoWire::onIRQ() { _slaveStartDet = false; _i2c->hw->clr_stop_det; } - if (_i2c->hw->intr_stat & (1 << 6)) { - // TX_ABRT - _i2c->hw->clr_tx_abrt; - } - if (_i2c->hw->intr_stat & (1 << 5)) { - // RD_REQ - if (_onRequestCallback) { - _onRequestCallback(); - } - _i2c->hw->clr_rd_req; - } - if (_i2c->hw->intr_stat & (1 << 2)) { - // RX_FULL - if (_slaveStartDet && (_buffLen < (int)sizeof(_buff))) { - _buff[_buffLen++] = _i2c->hw->data_cmd & 0xff; - } else { - _i2c->hw->data_cmd; - } - } } +#pragma GCC pop_options void TwoWire::end() { if (!_running) { diff --git a/libraries/http-parser/LICENSE-MIT b/libraries/http-parser/LICENSE-MIT new file mode 100644 index 000000000..1ec0ab4e1 --- /dev/null +++ b/libraries/http-parser/LICENSE-MIT @@ -0,0 +1,19 @@ +Copyright Joyent, Inc. and other Node contributors. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to +deal in the Software without restriction, including without limitation the +rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +sell copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +IN THE SOFTWARE. diff --git a/libraries/http-parser/README.md b/libraries/http-parser/README.md new file mode 100644 index 000000000..e38d3a578 --- /dev/null +++ b/libraries/http-parser/README.md @@ -0,0 +1,249 @@ +HTTP Parser +=========== + +http-parser is [**not** actively maintained](https://github.com/nodejs/http-parser/issues/522). +New projects and projects looking to migrate should consider [llhttp](https://github.com/nodejs/llhttp). + +[![Build Status](https://api.travis-ci.org/nodejs/http-parser.svg?branch=master)](https://travis-ci.org/nodejs/http-parser) + +This is a parser for HTTP messages written in C. It parses both requests and +responses. The parser is designed to be used in performance HTTP +applications. It does not make any syscalls nor allocations, it does not +buffer data, it can be interrupted at anytime. Depending on your +architecture, it only requires about 40 bytes of data per message +stream (in a web server that is per connection). + +Features: + + * No dependencies + * Handles persistent streams (keep-alive). + * Decodes chunked encoding. + * Upgrade support + * Defends against buffer overflow attacks. + +The parser extracts the following information from HTTP messages: + + * Header fields and values + * Content-Length + * Request method + * Response status code + * Transfer-Encoding + * HTTP version + * Request URL + * Message body + + +Usage +----- + +One `http_parser` object is used per TCP connection. Initialize the struct +using `http_parser_init()` and set the callbacks. That might look something +like this for a request parser: +```c +http_parser_settings settings; +settings.on_url = my_url_callback; +settings.on_header_field = my_header_field_callback; +/* ... */ + +http_parser *parser = malloc(sizeof(http_parser)); +http_parser_init(parser, HTTP_REQUEST); +parser->data = my_socket; +``` + +When data is received on the socket execute the parser and check for errors. + +```c +size_t len = 80*1024, nparsed; +char buf[len]; +ssize_t recved; + +recved = recv(fd, buf, len, 0); + +if (recved < 0) { + /* Handle error. */ +} + +/* Start up / continue the parser. + * Note we pass recved==0 to signal that EOF has been received. + */ +nparsed = http_parser_execute(parser, &settings, buf, recved); + +if (parser->upgrade) { + /* handle new protocol */ +} else if (nparsed != recved) { + /* Handle error. Usually just close the connection. */ +} +``` + +`http_parser` needs to know where the end of the stream is. For example, sometimes +servers send responses without Content-Length and expect the client to +consume input (for the body) until EOF. To tell `http_parser` about EOF, give +`0` as the fourth parameter to `http_parser_execute()`. Callbacks and errors +can still be encountered during an EOF, so one must still be prepared +to receive them. + +Scalar valued message information such as `status_code`, `method`, and the +HTTP version are stored in the parser structure. This data is only +temporally stored in `http_parser` and gets reset on each new message. If +this information is needed later, copy it out of the structure during the +`headers_complete` callback. + +The parser decodes the transfer-encoding for both requests and responses +transparently. That is, a chunked encoding is decoded before being sent to +the on_body callback. + + +The Special Problem of Upgrade +------------------------------ + +`http_parser` supports upgrading the connection to a different protocol. An +increasingly common example of this is the WebSocket protocol which sends +a request like + + GET /demo HTTP/1.1 + Upgrade: WebSocket + Connection: Upgrade + Host: example.com + Origin: http://example.com + WebSocket-Protocol: sample + +followed by non-HTTP data. + +(See [RFC6455](https://tools.ietf.org/html/rfc6455) for more information the +WebSocket protocol.) + +To support this, the parser will treat this as a normal HTTP message without a +body, issuing both on_headers_complete and on_message_complete callbacks. However +http_parser_execute() will stop parsing at the end of the headers and return. + +The user is expected to check if `parser->upgrade` has been set to 1 after +`http_parser_execute()` returns. Non-HTTP data begins at the buffer supplied +offset by the return value of `http_parser_execute()`. + + +Callbacks +--------- + +During the `http_parser_execute()` call, the callbacks set in +`http_parser_settings` will be executed. The parser maintains state and +never looks behind, so buffering the data is not necessary. If you need to +save certain data for later usage, you can do that from the callbacks. + +There are two types of callbacks: + +* notification `typedef int (*http_cb) (http_parser*);` + Callbacks: on_message_begin, on_headers_complete, on_message_complete. +* data `typedef int (*http_data_cb) (http_parser*, const char *at, size_t length);` + Callbacks: (requests only) on_url, + (common) on_header_field, on_header_value, on_body; + +Callbacks must return 0 on success. Returning a non-zero value indicates +error to the parser, making it exit immediately. + +For cases where it is necessary to pass local information to/from a callback, +the `http_parser` object's `data` field can be used. +An example of such a case is when using threads to handle a socket connection, +parse a request, and then give a response over that socket. By instantiation +of a thread-local struct containing relevant data (e.g. accepted socket, +allocated memory for callbacks to write into, etc), a parser's callbacks are +able to communicate data between the scope of the thread and the scope of the +callback in a threadsafe manner. This allows `http_parser` to be used in +multi-threaded contexts. + +Example: +```c + typedef struct { + socket_t sock; + void* buffer; + int buf_len; + } custom_data_t; + + +int my_url_callback(http_parser* parser, const char *at, size_t length) { + /* access to thread local custom_data_t struct. + Use this access save parsed data for later use into thread local + buffer, or communicate over socket + */ + parser->data; + ... + return 0; +} + +... + +void http_parser_thread(socket_t sock) { + int nparsed = 0; + /* allocate memory for user data */ + custom_data_t *my_data = malloc(sizeof(custom_data_t)); + + /* some information for use by callbacks. + * achieves thread -> callback information flow */ + my_data->sock = sock; + + /* instantiate a thread-local parser */ + http_parser *parser = malloc(sizeof(http_parser)); + http_parser_init(parser, HTTP_REQUEST); /* initialise parser */ + /* this custom data reference is accessible through the reference to the + parser supplied to callback functions */ + parser->data = my_data; + + http_parser_settings settings; /* set up callbacks */ + settings.on_url = my_url_callback; + + /* execute parser */ + nparsed = http_parser_execute(parser, &settings, buf, recved); + + ... + /* parsed information copied from callback. + can now perform action on data copied into thread-local memory from callbacks. + achieves callback -> thread information flow */ + my_data->buffer; + ... +} + +``` + +In case you parse HTTP message in chunks (i.e. `read()` request line +from socket, parse, read half headers, parse, etc) your data callbacks +may be called more than once. `http_parser` guarantees that data pointer is only +valid for the lifetime of callback. You can also `read()` into a heap allocated +buffer to avoid copying memory around if this fits your application. + +Reading headers may be a tricky task if you read/parse headers partially. +Basically, you need to remember whether last header callback was field or value +and apply the following logic: + + (on_header_field and on_header_value shortened to on_h_*) + ------------------------ ------------ -------------------------------------------- + | State (prev. callback) | Callback | Description/action | + ------------------------ ------------ -------------------------------------------- + | nothing (first call) | on_h_field | Allocate new buffer and copy callback data | + | | | into it | + ------------------------ ------------ -------------------------------------------- + | value | on_h_field | New header started. | + | | | Copy current name,value buffers to headers | + | | | list and allocate new buffer for new name | + ------------------------ ------------ -------------------------------------------- + | field | on_h_field | Previous name continues. Reallocate name | + | | | buffer and append callback data to it | + ------------------------ ------------ -------------------------------------------- + | field | on_h_value | Value for current header started. Allocate | + | | | new buffer and copy callback data to it | + ------------------------ ------------ -------------------------------------------- + | value | on_h_value | Value continues. Reallocate value buffer | + | | | and append callback data to it | + ------------------------ ------------ -------------------------------------------- + + +Parsing URLs +------------ + +A simplistic zero-copy URL parser is provided as `http_parser_parse_url()`. +Users of this library may wish to use it to parse URLs constructed from +consecutive `on_url` callbacks. + +See examples of reading in headers: + +* [partial example](http://gist.github.com/155877) in C +* [from http-parser tests](http://github.com/joyent/http-parser/blob/37a0ff8/test.c#L403) in C +* [from Node library](http://github.com/joyent/node/blob/842eaf4/src/http.js#L284) in Javascript diff --git a/libraries/http-parser/lib/http-parser b/libraries/http-parser/lib/http-parser new file mode 160000 index 000000000..ec8b5ee63 --- /dev/null +++ b/libraries/http-parser/lib/http-parser @@ -0,0 +1 @@ +Subproject commit ec8b5ee63f0e51191ea43bb0c6eac7bfbff3141d diff --git a/libraries/http-parser/library.properties b/libraries/http-parser/library.properties new file mode 100644 index 000000000..91912ac64 --- /dev/null +++ b/libraries/http-parser/library.properties @@ -0,0 +1,11 @@ +name=http-parser +version=2.9.4 +author=Node.JS team +maintainer=Earle F. Philhower, III +sentence=HTTP parser from Node.js team, MIT license +paragraph=HTTP parser from Node.js team, MIT license +category=communications +url=https://github.com/earlephilhower/arduino-pico +architectures=rp2040 +dot_a_linkage=true +includes=http_parser.h diff --git a/libraries/http-parser/src/http_parser.c b/libraries/http-parser/src/http_parser.c new file mode 100644 index 000000000..beffe9211 --- /dev/null +++ b/libraries/http-parser/src/http_parser.c @@ -0,0 +1 @@ +#include "../lib/http-parser/http_parser.c" diff --git a/libraries/http-parser/src/http_parser.h b/libraries/http-parser/src/http_parser.h new file mode 100644 index 000000000..00b2d49c7 --- /dev/null +++ b/libraries/http-parser/src/http_parser.h @@ -0,0 +1 @@ +#include "../lib/http-parser/http_parser.h" diff --git a/libraries/lwIP_CYW43/library.properties b/libraries/lwIP_CYW43/library.properties index 50e757a78..8b7150a41 100644 --- a/libraries/lwIP_CYW43/library.properties +++ b/libraries/lwIP_CYW43/library.properties @@ -3,7 +3,7 @@ version=1 author=Earle F. Philhower, III maintainer=Earle F. Philhower, III sentence=RP2040 Cyw43XX wifi driver -paragraph=Driver for the raspberry Pi Pico W wireless chip, CYW43439, to integrate witrh arduino-pico +paragraph=Driver for the Raspberry Pi Pico W wireless chip, CYW43439, to integrate with arduino-pico category=Communication url=https://github.com/earlephilhower/arduino-pico architectures=rp2040 diff --git a/libraries/lwIP_CYW43/src/utility/CYW43shim.cpp b/libraries/lwIP_CYW43/src/utility/CYW43shim.cpp index 934fdf8b4..969a9761b 100644 --- a/libraries/lwIP_CYW43/src/utility/CYW43shim.cpp +++ b/libraries/lwIP_CYW43/src/utility/CYW43shim.cpp @@ -26,13 +26,29 @@ extern "C" { #include "pico/cyw43_arch.h" #include +// From cyw43_ctrl.c +#define WIFI_JOIN_STATE_KIND_MASK (0x000f) +#define WIFI_JOIN_STATE_ACTIVE (0x0001) +#define WIFI_JOIN_STATE_FAIL (0x0002) +#define WIFI_JOIN_STATE_NONET (0x0003) +#define WIFI_JOIN_STATE_BADAUTH (0x0004) +#define WIFI_JOIN_STATE_AUTH (0x0200) +#define WIFI_JOIN_STATE_LINK (0x0400) +#define WIFI_JOIN_STATE_KEYED (0x0800) +#define WIFI_JOIN_STATE_ALL (0x0e01) + netif *CYW43::_netif = nullptr; +struct netif *__getCYW43Netif() { + return CYW43::_netif; +} + CYW43::CYW43(int8_t cs, arduino::SPIClass& spi, int8_t intrpin) { (void) cs; (void) spi; (void) intrpin; _netif = nullptr; + bzero(_bssid, sizeof(_bssid)); } bool CYW43::begin(const uint8_t* address, netif* netif) { @@ -52,12 +68,29 @@ bool CYW43::begin(const uint8_t* address, netif* netif) { // Not currently possible to hook up igmp_mac_filter and mld_mac_filter // TODO: implement igmp_mac_filter and mld_mac_filter - cyw43_set_allmulti(_self, true); + // Implement cyw43_set_allmulti(_self, true) using exposed ioctl call (may not be functional in SDK 1.5?) + uint8_t allmulti_true[] = { 'a', 'l', 'l', 'm', 'u', 'l', 't', 'i', 0, 1, 0, 0, 0 }; + cyw43_ioctl(&cyw43_state, CYW43_IOCTL_SET_VAR, sizeof allmulti_true, allmulti_true, CYW43_ITF_STA); + // Add MDNS multicast MAC addresses manually, thanks Wikipedia! + uint8_t mdnsV4[] = {0x01, 0x00, 0x5E, 0x00, 0x00, 0xFB}; + cyw43_wifi_update_multicast_filter(&cyw43_state, mdnsV4, true); +#if LWIP_IPV6 + uint8_t mdnsV6[] = {0x33, 0x33, 0x00, 0x00, 0x00, 0xFB}; + cyw43_wifi_update_multicast_filter(&cyw43_state, mdnsV6, true); +#endif - if (cyw43_arch_wifi_connect_timeout_ms(_ssid, _password, authmode, _timeout)) { - return false; + if (_bssid[0] | _bssid[1] | _bssid[2] | _bssid[3] | _bssid[4] | _bssid[5]) { + if (cyw43_arch_wifi_connect_bssid_timeout_ms(_ssid, _bssid, _password, authmode, _timeout)) { + return false; + } else { + return true; + } } else { - return true; + if (cyw43_arch_wifi_connect_timeout_ms(_ssid, _password, authmode, _timeout)) { + return false; + } else { + return true; + } } } else { _itf = 1; @@ -72,7 +105,6 @@ void CYW43::end() { cyw43_deinit(&cyw43_state); } - uint16_t CYW43::sendFrame(const uint8_t* data, uint16_t datalen) { if (0 == cyw43_send_ethernet(_self, _itf, datalen, data, false)) { return datalen; @@ -86,63 +118,3 @@ uint16_t CYW43::readFrame(uint8_t* buffer, uint16_t bufsize) { (void) bufsize; return 0; } - -// CB from the cyg32_driver -extern "C" void cyw43_cb_process_ethernet(void *cb_data, int itf, size_t len, const uint8_t *buf) { - //cyw43_t *self = (cyw43_t *)cb_data - (void) cb_data; - (void) itf; - struct netif *netif = CYW43::_netif; // &self->netif[itf]; -#if CYW43_NETUTILS - if (self->trace_flags) { - cyw43_ethernet_trace(self, netif, len, buf, NETUTILS_TRACE_NEWLINE); - } -#endif - if (netif->flags & NETIF_FLAG_LINK_UP) { - struct pbuf *p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL); - if (p != NULL) { - pbuf_take(p, buf, len); - if (netif->input(p, netif) != ERR_OK) { - pbuf_free(p); - } - CYW43_STAT_INC(PACKET_IN_COUNT); - } - } -} - -extern "C" void cyw43_cb_tcpip_set_link_up(cyw43_t *self, int itf) { - (void) self; - (void) itf; - if (CYW43::_netif) { - netif_set_link_up(CYW43::_netif); - } -} - -extern "C" void cyw43_cb_tcpip_set_link_down(cyw43_t *self, int itf) { - (void) self; - (void) itf; - if (CYW43::_netif) { - netif_set_link_down(CYW43::_netif); - } -} - -extern "C" int cyw43_tcpip_link_status(cyw43_t *self, int itf) { - //if ((CYW43::_netif->flags & (NETIF_FLAG_UP | NETIF_FLAG_LINK_UP)) == (NETIF_FLAG_UP | NETIF_FLAG_LINK_UP)) - // Fake this since it's only used in the SDK - if ((CYW43::_netif->flags & (NETIF_FLAG_LINK_UP)) == (NETIF_FLAG_LINK_UP)) { - return CYW43_LINK_UP; - } else { - return cyw43_wifi_link_status(self, itf); - } -} - -// CBs from the SDK, not needed here as we do TCP later in the game -extern "C" void cyw43_cb_tcpip_init(cyw43_t *self, int itf) { - (void) self; - (void) itf; -} -extern "C" void cyw43_cb_tcpip_deinit(cyw43_t *self, int itf) { - (void) self; - (void) itf; -} - diff --git a/libraries/lwIP_CYW43/src/utility/CYW43shim.h b/libraries/lwIP_CYW43/src/utility/CYW43shim.h index 06efe50cf..cf35337ca 100644 --- a/libraries/lwIP_CYW43/src/utility/CYW43shim.h +++ b/libraries/lwIP_CYW43/src/utility/CYW43shim.h @@ -73,6 +73,11 @@ class CYW43 { void setSSID(const char *p) { _ssid = p; } + + void setBSSID(const uint8_t *bssid) { + memcpy(_bssid, bssid, sizeof(_bssid)); + } + void setPassword(const char *p) { _password = p; } @@ -99,4 +104,5 @@ class CYW43 { int _itf; const char *_ssid = nullptr; const char *_password = nullptr; + uint8_t _bssid[6]; }; diff --git a/libraries/lwIP_Ethernet/src/AddrList.h b/libraries/lwIP_Ethernet/src/AddrList.h index d7e5bc02a..5ff69c01d 100644 --- a/libraries/lwIP_Ethernet/src/AddrList.h +++ b/libraries/lwIP_Ethernet/src/AddrList.h @@ -72,8 +72,7 @@ } */ -#ifndef __ADDRLIST_H -#define __ADDRLIST_H +#pragma once #include #include @@ -254,6 +253,3 @@ inline AddressList::const_iterator end(const AddressList& a) { } // esp8266 extern esp8266::AddressListImplementation::AddressList addrList; - - -#endif diff --git a/libraries/lwIP_Ethernet/src/LwipEthernet.h b/libraries/lwIP_Ethernet/src/LwipEthernet.h index f4e434f9c..d9416cfa0 100644 --- a/libraries/lwIP_Ethernet/src/LwipEthernet.h +++ b/libraries/lwIP_Ethernet/src/LwipEthernet.h @@ -1,3 +1,25 @@ +/* + LwipEthernet.h + + Arduino interface for lwIP generic callbacks and functions + + Original Copyright (c) 2020 esp8266 Arduino All rights reserved. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + //#include // tcp API //#include diff --git a/libraries/lwIP_Ethernet/src/LwipIntfDev.h b/libraries/lwIP_Ethernet/src/LwipIntfDev.h index 31ebc9e8d..23c133b94 100644 --- a/libraries/lwIP_Ethernet/src/LwipIntfDev.h +++ b/libraries/lwIP_Ethernet/src/LwipIntfDev.h @@ -26,8 +26,6 @@ // TODO: // unchain pbufs -#include - #include #include #include @@ -176,7 +174,6 @@ int LwipIntfDev::hostByName(const char* aHostname, IPAddress& aResult, i return 1; } - LWIPMutex m; _dns_cb_t cb = { &aResult, this }; #if LWIP_IPV4 && LWIP_IPV6 err_t err = dns_gethostbyname_addrtype(aHostname, &addr, &_dns_found_callback, &cb, LWIP_DNS_ADDRTYPE_DEFAULT); @@ -230,8 +227,6 @@ int LwipIntfDev::ping(IPAddress host, uint8_t ttl, uint32_t _timeout) { auto ping_pcb = raw_new(IP_PROTO_ICMP); ping_pcb->ttl = ttl; - LWIPMutex m; - raw_recv(ping_pcb, _pingCB, this); raw_bind(ping_pcb, IP_ADDR_ANY); @@ -256,7 +251,7 @@ int LwipIntfDev::ping(IPAddress host, uint8_t ttl, uint32_t _timeout) { uint32_t now = millis(); while ((millis() - now < _timeout) && (_ping_ttl < 0)) { sys_check_timeouts(); - delay(10); + delay(1); } pbuf_free(p); raw_remove(ping_pcb); @@ -408,6 +403,7 @@ void LwipIntfDev::end() { RawDev::end(); netif_remove(&_netif); memset(&_netif, 0, sizeof(_netif)); + _started = false; } diff --git a/libraries/rp2040/examples/Bootsel/Bootsel.ino b/libraries/rp2040/examples/Bootsel/Bootsel.ino index 773978033..4ffd7cbb0 100644 --- a/libraries/rp2040/examples/Bootsel/Bootsel.ino +++ b/libraries/rp2040/examples/Bootsel/Bootsel.ino @@ -1,5 +1,5 @@ /* Simple sketch to do something on a BOOTSEL press */ -/* Releaed into the public domain */ +/* Released into the public domain */ void setup() { Serial.begin(115200); diff --git a/libraries/rp2040/examples/GetCycleCount/GetCycleCount.ino b/libraries/rp2040/examples/GetCycleCount/GetCycleCount.ino index 56c0fa8b7..56335e334 100644 --- a/libraries/rp2040/examples/GetCycleCount/GetCycleCount.ino +++ b/libraries/rp2040/examples/GetCycleCount/GetCycleCount.ino @@ -6,7 +6,7 @@ void setup() { uint32_t a = rp2040.getCycleCount(); delay(1000); uint32_t b = rp2040.getCycleCount(); - Serial.printf("There are %d cycles in one second.\n\n\n", b - a); + Serial.printf("There are %lu cycles in one second.\n\n\n", b - a); delay(3000); @@ -16,6 +16,6 @@ void setup() { } void loop() { - Serial.printf("%15u - %15llu\n", rp2040.getCycleCount(), rp2040.getCycleCount64()); + Serial.printf("%15lu - %15llu\n", rp2040.getCycleCount(), rp2040.getCycleCount64()); delay(1500); } diff --git a/ota/CMakeLists.txt b/ota/CMakeLists.txt index 9b2256073..30024b101 100644 --- a/ota/CMakeLists.txt +++ b/ota/CMakeLists.txt @@ -44,11 +44,14 @@ target_compile_definitions(ota PUBLIC LFS_NO_MALLOC=1 PICO_PANIC_FUNCTION= PICO_TIME_DEFAULT_ALARM_POOL_DISABLED=1 + PICO_NO_BINARY_INFO=1 ) target_compile_options(ota PUBLIC -fno-exceptions -Os + -Wall + -Werror $<$:-fno-rtti> ) diff --git a/ota/README.md b/ota/README.md index bffb4d831..0e346048e 100644 --- a/ota/README.md +++ b/ota/README.md @@ -12,6 +12,6 @@ Should a power failure happen, as long as it was not in the middle of writing a When the copy is completed, the command file's contents are erased so that on a reboot it won't attempt to write the same firmware over and over. It then reboots the chip (and re-runs the potentially new bootloader). -If there is no special file, or its contents don't have a proper checksum, the bootloaer simply adjusts the ARM internal vector pointers and jumps to the main application. +If there is no special file, or its contents don't have a proper checksum, the bootloader simply adjusts the ARM internal vector pointers and jumps to the main application. The files in the LittleFS filesystem can come over ``WiFi``, over an ``Ethernet`` object, or even over a serial port. diff --git a/ota/memmap_ota.ld b/ota/memmap_ota.ld index a4f92d343..d34ea92ac 100644 --- a/ota/memmap_ota.ld +++ b/ota/memmap_ota.ld @@ -23,21 +23,28 @@ MEMORY { - FLASH(rx) : ORIGIN = 0x10000100, LENGTH = 16384k - RAM(rwx) : ORIGIN = 0x20000000, LENGTH = 256k + FLASH(rx) : ORIGIN = 0x10000100, LENGTH = 16384k + RAM(rwx) : ORIGIN = 0x20000000, LENGTH = 212k + /* We split RAM into main (where the flash->ram code will be copied) and GLOBALS which has all large arrays */ + /* By placing those arrays at the end of RAM we can avoid overwriting uninitialize_ram from the main app as */ + /* long as those vars are stored after 12K by using an alignment value in the main app linker file. */ + GLOBALS(rwx) : ORIGIN = 0x20035000, LENGTH = 44k SCRATCH_X(rwx) : ORIGIN = 0x20040000, LENGTH = 4k SCRATCH_Y(rwx) : ORIGIN = 0x20041000, LENGTH = 4k } ENTRY(_entry_point) -SECTIONS -{ +SECTIONS { /* Second stage bootloader is prepended to the image. It must be 256 bytes big and checksummed. It is usually built by the boot_stage2 target in the Raspberry Pi Pico SDK */ + /* Make sure the globals are not copied/etc. They're empty RAM we will init ourselves */ + .globals (NOLOAD) : { + } > GLOBALS + .flash_begin : { __flash_binary_start = .; } > FLASH @@ -72,27 +79,16 @@ SECTIONS . = ALIGN(4); } > FLASH - .ARM.extab : - { + .ARM.extab : { *(.ARM.extab* .gnu.linkonce.armextab.*) } > FLASH __exidx_start = .; - .ARM.exidx : - { + .ARM.exidx : { *(.ARM.exidx* .gnu.linkonce.armexidx.*) } > FLASH __exidx_end = .; - /* Machine inspectable binary information */ - . = ALIGN(4); - __binary_info_start = .; - .binary_info : - { - KEEP(*(.binary_info.keep.*)) - *(.binary_info.*) - } > FLASH - __binary_info_end = .; . = ALIGN(4); /* Vector table goes first in RAM, to avoid large alignment hole */ @@ -197,7 +193,7 @@ SECTIONS } > SCRATCH_Y AT > FLASH __scratch_y_source__ = LOADADDR(.scratch_y); - .bss : { + .bss : { . = ALIGN(4); __bss_start__ = .; *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.bss*))) @@ -206,8 +202,7 @@ SECTIONS __bss_end__ = .; } > RAM - .heap (COPY): - { + .heap (COPY): { __end__ = .; end = __end__; *(.heap*) @@ -223,12 +218,10 @@ SECTIONS /* by default we put core 0 stack at the end of scratch Y, so that if core 1 * stack is not used then all of SCRATCH_X is free. */ - .stack1_dummy (COPY): - { + .stack1_dummy (COPY): { *(.stack1*) } > SCRATCH_X - .stack_dummy (COPY): - { + .stack_dummy (COPY): { *(.stack*) } > SCRATCH_Y diff --git a/ota/ota.c b/ota/ota.c index 22bd4f018..38b7b486e 100644 --- a/ota/ota.c +++ b/ota/ota.c @@ -53,8 +53,7 @@ void dumphex(uint32_t x) { #endif } -static OTACmdPage _ota_cmd; - +extern OTACmdPage _ota_cmd; void do_ota() { if (*__FS_START__ == *__FS_END__) { return; @@ -165,7 +164,7 @@ void do_ota() { #pragma GCC push_options #pragma GCC optimize("O0") -int main(int a, unsigned char **b) { +int main(int a, char **b) { (void) a; (void) b; @@ -190,7 +189,7 @@ int main(int a, unsigned char **b) { fcn(); // Should never get here! - return 0; + return *sp; } #pragma GCC pop_options diff --git a/ota/ota_lfs.c b/ota/ota_lfs.c index db0cf5f6b..cf04cc3de 100644 --- a/ota/ota_lfs.c +++ b/ota/ota_lfs.c @@ -26,6 +26,8 @@ #include "../libraries/LittleFS/lib/littlefs/lfs_util.h" #include "./uzlib/src/uzlib.h" +OTACmdPage __attribute__((section (".globals"))) _ota_cmd; + static lfs_t _lfs; static struct lfs_config _lfs_cfg; @@ -70,9 +72,9 @@ static int lfs_flash_sync(const struct lfs_config *c) { return 0; } -uint8_t _read_buffer[256]; -uint8_t _prog_buffer[256]; -uint8_t _lookahead_buffer[256]; +uint8_t __attribute__((section (".globals"))) _read_buffer[256]; +uint8_t __attribute__((section (".globals"))) _prog_buffer[256]; +uint8_t __attribute__((section (".globals"))) _lookahead_buffer[256]; bool lfsMount(uint8_t *start, uint32_t blockSize, uint32_t size) { _start = start; _blockSize = blockSize; @@ -104,16 +106,16 @@ bool lfsMount(uint8_t *start, uint32_t blockSize, uint32_t size) { static bool _gzip = false; static lfs_file_t _file; -static unsigned char __attribute__((aligned(4))) uzlib_read_buff[4096]; -static unsigned char gzip_dict[32768]; -static uint8_t _flash_buff[4096]; // no room for this on the stack -static struct uzlib_uncomp m_uncomp; +unsigned char __attribute__((section (".globals"))) uzlib_read_buff[4096]; +unsigned char __attribute__((section (".globals"))) gzip_dict[32768]; +uint8_t __attribute__((section (".globals")))_flash_buff[4096]; // no room for this on the stack +struct uzlib_uncomp __attribute__((section (".globals"))) m_uncomp; -static uint8_t _ota_buff[256]; -static struct lfs_file_config _ota_cfg = { (void *)_ota_buff, NULL, 0 }; +uint8_t __attribute__((section (".globals")))_ota_buff[256]; +struct lfs_file_config _ota_cfg = { (void *)_ota_buff, NULL, 0 }; -static uint8_t _file_buff[256]; -static struct lfs_file_config _file_cfg = { (void *)_file_buff, NULL, 0 }; +uint8_t __attribute__((section (".globals")))_file_buff[256]; +struct lfs_file_config _file_cfg = { (void *)_file_buff, NULL, 0 }; bool lfsReadOTA(OTACmdPage *ota, uint32_t *blockToErase) { lfs_file_t f; diff --git a/package.json b/package.json index 63e183419..5219aa872 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "framework-arduinopico", - "version": "1.20400.0", + "version": "1.30200.0", "description": "Arduino Wiring-based Framework (RPi Pico RP2040)", "keywords": [ "framework", diff --git a/package/build_boards_manager_package.sh b/package/build_boards_manager_package.sh index 7c4f63345..272789db6 100755 --- a/package/build_boards_manager_package.sh +++ b/package/build_boards_manager_package.sh @@ -72,7 +72,6 @@ cat << EOF > exclude.txt .travis.yml package doc -ArduinoCore-API EOF # Also include all files which are ignored by git git ls-files --other --directory >> exclude.txt @@ -112,8 +111,18 @@ sed 's/^tools.uf2conv.network_cmd=.*//g' | \ sed 's/^#tools.uf2conv.network_cmd=/tools.uf2conv.network_cmd=/g' | \ sed 's/^tools.picoprobe.cmd=.*//g' | \ sed 's/^#tools.picoprobe.cmd=/tools.picoprobe.cmd=/g' | \ +sed 's/^tools.picoprobe_cmsis_dap.cmd=.*//g' | \ +sed 's/^#tools.picoprobe_cmsis_dap.cmd=/tools.picoprobe_cmsis_dap.cmd=/g' | \ +sed 's/^tools.picotool.cmd=.*//g' | \ +sed 's/^#tools.picotool.cmd=/tools.picotool.cmd=/g' | \ sed 's/^tools.picodebug.cmd=.*//g' | \ sed 's/^#tools.picodebug.cmd=/tools.picodebug.cmd=/g' | \ +sed 's/^discovery.rp2040.pattern=.*//g' | \ +sed 's/^#discovery.rp2040.pattern=/discovery.rp2040.pattern=/g' | \ +sed 's/^pluggable_discovery.rp2040.pattern=.*//g' | \ +sed 's/^#pluggable_discovery.rp2040.pattern=/pluggable_discovery.rp2040.pattern=/g' | \ +sed 's/^tools.uf2conv-network.cmd=.*//g' | \ +sed 's/^#tools.uf2conv-network.cmd=/tools.uf2conv-network.cmd=/g' | \ sed "s/version=.*/version=$ver/g" |\ sed -E "s/name=([a-zA-Z0-9\ -]+).*/name=\1($ver)/g"\ > $outdir/platform.txt diff --git a/package/package_pico_index.template.json b/package/package_pico_index.template.json index 87d2d293c..bde57f981 100644 --- a/package/package_pico_index.template.json +++ b/package/package_pico_index.template.json @@ -23,9 +23,33 @@ { "name": "Raspberry Pi Pico W" }, + { + "name": "0xCB Helios" + }, { "name": "Adafruit Feather RP2040" }, + { + "name": "Adafruit Feather RP2040 SCORPIO" + }, + { + "name": "Adafruit Feather RP2040 DVI" + }, + { + "name": "Adafruit Feather RP2040 RFM" + }, + { + "name": "Adafruit Feather RP2040 ThinkINK" + }, + { + "name": "Adafruit Feather RP2040 USB Host" + }, + { + "name": "Adafruit Feather RP2040 CAN" + }, + { + "name": "Adafruit Feather RP2040 Prop-Maker" + }, { "name": "Adafruit ItsyBitsy RP2040" }, @@ -47,12 +71,18 @@ { "name": "Arduino Nano RP2040 Connect" }, + { + "name": "BridgeTek IDM2040-7A" + }, { "name": "Cytron Maker Nano RP2040" }, { "name": "Cytron Maker Pi RP2040" }, + { + "name": "DatanoiseTV PicoADK" + }, { "name": "DeRuiLab FlyBoard2040Core" }, @@ -62,6 +92,9 @@ { "name": "ElectronicCats HunterCat NFC RP2040" }, + { + "name": "ExtremeElectronics RC2040" + }, { "name": "iLabs Challenger 2040 LTE" }, @@ -83,12 +116,30 @@ { "name": "iLabs Challenger 2040 SD/RTC" }, + { + "name": "iLabs Challenger 2040 NFC" + }, + { + "name": "iLabs Challenger 2040 UWB" + }, { "name": "iLabs RPICO32" }, + { + "name": "Melopero Cookie RP2040" + }, { "name": "Melopero Shake RP2040" }, + { + "name": "Neko Systems BL2040 Mini" + }, + { + "name": "nullbits Bit-C PRO" + }, + { + "name": "Pimoroni PGA2040" + }, { "name": "Solder Party RP2040 Stamp" }, @@ -101,9 +152,36 @@ { "name": "uPesy RP2040 DevKit" }, + { + "name": "Seeed INDICATOR RP2040" + }, { "name": "Seeed XIAO RP2040" }, + { + "name": "VCC-GND YD RP2040" + }, + { + "name": "Viyalab Mizu RP2040" + }, + { + "name": "Waveshare RP2040 Zero" + }, + { + "name": "Waveshare RP2040 One" + }, + { + "name": "Waveshare RP2040 Plus 4MB" + }, + { + "name": "Waveshare RP2040 Plus 16MB" + }, + { + "name": "Waveshare RP2040 LCD 0.96" + }, + { + "name": "Waveshare RP2040 LCD 1.28" + }, { "name": "WIZnet W5100S-EVB-Pico" }, @@ -123,22 +201,22 @@ "toolsDependencies": [ { "packager": "rp2040-ethernet", - "version": "1.4.0-c-0196c06", + "version": "1.5.0-b-c7bab52", "name": "pqt-gcc" }, { "packager": "rp2040-ethernet", - "version": "1.4.0-c-0196c06", + "version": "1.5.0-b-c7bab52", "name": "pqt-mklittlefs" }, { "packager": "rp2040-ethernet", - "version": "1.4.0-c-0196c06", + "version": "1.5.0-b-c7bab52", "name": "pqt-elf2uf2" }, { "packager": "rp2040-ethernet", - "version": "1.4.0-c-0196c06", + "version": "1.5.0-b-c7bab52", "name": "pqt-pioasm" }, { @@ -148,8 +226,13 @@ }, { "packager": "rp2040-ethernet", - "version": "1.4.0-c-0196c06", + "version": "1.5.0-b-c7bab52", "name": "pqt-openocd" + }, + { + "packager": "rp2040", + "version": "1.5.0-b-03f2812", + "name": "pqt-picotool" } ], "help": { @@ -159,57 +242,112 @@ ], "tools": [ { - "version": "1.4.0-c-0196c06", + "version": "1.5.0-b-03f2812", + "name": "pqt-picotool", + "systems": [ + { + "host": "aarch64-linux-gnu", + "url": "https://github.com/earlephilhower/pico-quick-toolchain/releases/download/1.5.0-b/aarch64-linux-gnu.picotool-03f2812.230216.tar.gz", + "archiveFileName": "aarch64-linux-gnu.picotool-03f2812.230216.tar.gz", + "checksum": "SHA-256:5efe9c4ccc08d9d28cc87a0cfaf563b6fc1caa5d3967c963814225fd252756c7", + "size": "171877" + }, + { + "host": "arm-linux-gnueabihf", + "url": "https://github.com/earlephilhower/pico-quick-toolchain/releases/download/1.5.0-b/arm-linux-gnueabihf.picotool-03f2812.230216.tar.gz", + "archiveFileName": "arm-linux-gnueabihf.picotool-03f2812.230216.tar.gz", + "checksum": "SHA-256:38f3f0925be5e053866ad33e8a535ac9d08f58af837a53b65dfe45f2ccbe9c5b", + "size": "152925" + }, + { + "host": "i686-pc-linux-gnu", + "url": "https://github.com/earlephilhower/pico-quick-toolchain/releases/download/1.5.0-b/i686-linux-gnu.picotool-03f2812.230216.tar.gz", + "archiveFileName": "i686-linux-gnu.picotool-03f2812.230216.tar.gz", + "checksum": "SHA-256:485c09be49850d2e05c32e20fcc899b58e649e2863b300c7e89110d36094dce1", + "size": "183644" + }, + { + "host": "i686-mingw32", + "url": "https://github.com/earlephilhower/pico-quick-toolchain/releases/download/1.5.0-b/i686-w64-mingw32.picotool-03f2812.230216.zip", + "archiveFileName": "i686-w64-mingw32.picotool-03f2812.230216.zip", + "checksum": "SHA-256:9d7516313c1e9b341fe8ce05b786348def60692dc88f17bdee5bc25b6baf6871", + "size": "352766" + }, + { + "host": "x86_64-apple-darwin", + "url": "https://github.com/earlephilhower/pico-quick-toolchain/releases/download/1.5.0-b/x86_64-apple-darwin14.picotool-03f2812.230216.tar.gz", + "archiveFileName": "x86_64-apple-darwin14.picotool-03f2812.230216.tar.gz", + "checksum": "SHA-256:8b48c395f871dac7cbe396e4518649d40582d5a78948f0e792d0569db5069226", + "size": "852423" + }, + { + "host": "x86_64-pc-linux-gnu", + "url": "https://github.com/earlephilhower/pico-quick-toolchain/releases/download/1.5.0-b/x86_64-linux-gnu.picotool-03f2812.230216.tar.gz", + "archiveFileName": "x86_64-linux-gnu.picotool-03f2812.230216.tar.gz", + "checksum": "SHA-256:507d7d01d63caebb2c3f33e99a8545a3719699c5645c423175bf0b7bfd685a48", + "size": "131605" + }, + { + "host": "x86_64-mingw32", + "url": "https://github.com/earlephilhower/pico-quick-toolchain/releases/download/1.5.0-b/x86_64-w64-mingw32.picotool-03f2812.230216.zip", + "archiveFileName": "x86_64-w64-mingw32.picotool-03f2812.230216.zip", + "checksum": "SHA-256:ca62fe7dd783fc38080d834e413e1632086c6bc24660e6f5eaad931465ca87e3", + "size": "337119" + } + ] + }, + { + "version": "1.5.0-b-c7bab52", "name": "pqt-openocd", "systems": [ { "host": "aarch64-linux-gnu", - "url": "https://github.com/earlephilhower/pico-quick-toolchain/releases/download/1.4.0-c/aarch64-linux-gnu.openocd-e3428fadb.220714.tar.gz", - "archiveFileName": "aarch64-linux-gnu.openocd-e3428fadb.220714.tar.gz", - "checksum": "SHA-256:8da4fd922fd7392e87c0057b193e67962606cd13450af935c9846992f2bce916", - "size": "5607131" + "url": "https://github.com/earlephilhower/pico-quick-toolchain/releases/download/1.5.0-b/aarch64-linux-gnu.openocd-8e3c38f78.230216.tar.gz", + "archiveFileName": "aarch64-linux-gnu.openocd-8e3c38f78.230216.tar.gz", + "checksum": "SHA-256:6875c0c2e7faa320882d00f33f415499e1028d3bd0bac7d672d4342968c28eaf", + "size": "5812640" }, { "host": "arm-linux-gnueabihf", - "url": "https://github.com/earlephilhower/pico-quick-toolchain/releases/download/1.4.0-c/arm-linux-gnueabihf.openocd-e3428fadb.220714.tar.gz", - "archiveFileName": "arm-linux-gnueabihf.openocd-e3428fadb.220714.tar.gz", - "checksum": "SHA-256:ce7650961c8200fe2cc2d4a88efc952fe1bb7b4175f2cf650a9a7d992ae08298", - "size": "5344149" + "url": "https://github.com/earlephilhower/pico-quick-toolchain/releases/download/1.5.0-b/arm-linux-gnueabihf.openocd-8e3c38f78.230216.tar.gz", + "archiveFileName": "arm-linux-gnueabihf.openocd-8e3c38f78.230216.tar.gz", + "checksum": "SHA-256:fa35b2c6ca10b332718db8217c7bb57cc1e15bafc526dd05c0d6a890b05dec50", + "size": "5543967" }, { "host": "i686-pc-linux-gnu", - "url": "https://github.com/earlephilhower/pico-quick-toolchain/releases/download/1.4.0-c/i686-linux-gnu.openocd-e3428fadb.220714.tar.gz", - "archiveFileName": "i686-linux-gnu.openocd-e3428fadb.220714.tar.gz", - "checksum": "SHA-256:9391ae74c6474f685f45ccefb82e18f382f1a59f3e13e2b22fe00967264d2482", - "size": "5168334" + "url": "https://github.com/earlephilhower/pico-quick-toolchain/releases/download/1.5.0-b/i686-linux-gnu.openocd-8e3c38f78.230216.tar.gz", + "archiveFileName": "i686-linux-gnu.openocd-8e3c38f78.230216.tar.gz", + "checksum": "SHA-256:0f27f4a7be0411db032b8fc0aa8f55b559d03909830b38dc6610301a9a79050c", + "size": "5347247" }, { "host": "i686-mingw32", - "url": "https://github.com/earlephilhower/pico-quick-toolchain/releases/download/1.4.0-c/i686-w64-mingw32.openocd-e3428fadb.220714.zip", - "archiveFileName": "i686-w64-mingw32.openocd-e3428fadb.220714.zip", - "checksum": "SHA-256:f4b7803527a0a587fe95e52bcf056fcbe58d64b78705edd38810655d3abee1fe", - "size": "2156831" + "url": "https://github.com/earlephilhower/pico-quick-toolchain/releases/download/1.5.0-b/i686-w64-mingw32.openocd-8e3c38f78.230216.zip", + "archiveFileName": "i686-w64-mingw32.openocd-8e3c38f78.230216.zip", + "checksum": "SHA-256:a53ee67b63893d2dc432df293f494443921301021ec0828a044813528880d16a", + "size": "2207880" }, { "host": "x86_64-apple-darwin", - "url": "https://github.com/earlephilhower/pico-quick-toolchain/releases/download/1.4.0-c/x86_64-apple-darwin14.openocd-e3428fadb.220714.tar.gz", - "archiveFileName": "x86_64-apple-darwin14.openocd-e3428fadb.220714.tar.gz", - "checksum": "SHA-256:4e6a8da43758941478e6740e023ea5be051f09bf92e49d65c2b54a1ca4a2660c", - "size": "2002508" + "url": "https://github.com/earlephilhower/pico-quick-toolchain/releases/download/1.5.0-b/x86_64-apple-darwin14.openocd-8e3c38f78.230216.tar.gz", + "archiveFileName": "x86_64-apple-darwin14.openocd-8e3c38f78.230216.tar.gz", + "checksum": "SHA-256:8f68f93ee51973926cb94c24164013d35d4dd42a636e4c15af5d3bb3884e6daf", + "size": "2599703" }, { "host": "x86_64-pc-linux-gnu", - "url": "https://github.com/earlephilhower/pico-quick-toolchain/releases/download/1.4.0-c/x86_64-linux-gnu.openocd-e3428fadb.220714.tar.gz", - "archiveFileName": "x86_64-linux-gnu.openocd-e3428fadb.220714.tar.gz", - "checksum": "SHA-256:2518c6451c0e4c148c8c6cb9330e216075177003b064c509b168f42a44a6eb5a", - "size": "5540574" + "url": "https://github.com/earlephilhower/pico-quick-toolchain/releases/download/1.5.0-b/x86_64-linux-gnu.openocd-8e3c38f78.230216.tar.gz", + "archiveFileName": "x86_64-linux-gnu.openocd-8e3c38f78.230216.tar.gz", + "checksum": "SHA-256:50fe784a938922ffb0c12076245cedbc467f5f51b6030da776b6f95305308492", + "size": "5732546" }, { "host": "x86_64-mingw32", - "url": "https://github.com/earlephilhower/pico-quick-toolchain/releases/download/1.4.0-c/x86_64-w64-mingw32.openocd-e3428fadb.220714.zip", - "archiveFileName": "x86_64-w64-mingw32.openocd-e3428fadb.220714.zip", - "checksum": "SHA-256:c2da993d74152ec8ca80b350ede77ee94942518081a48dafd7a3b49631778e75", - "size": "2156831" + "url": "https://github.com/earlephilhower/pico-quick-toolchain/releases/download/1.5.0-b/x86_64-w64-mingw32.openocd-8e3c38f78.230216.zip", + "archiveFileName": "x86_64-w64-mingw32.openocd-8e3c38f78.230216.zip", + "checksum": "SHA-256:d36a25b7e40771bcc286a51bfa4803668037662651bce5a40a36608babbc3f5f", + "size": "2168940" } ] }, @@ -276,222 +414,222 @@ ] }, { - "version": "1.4.0-c-0196c06", + "version": "1.5.0-b-c7bab52", "name": "pqt-gcc", "systems": [ { "host": "aarch64-linux-gnu", - "url": "https://github.com/earlephilhower/pico-quick-toolchain/releases/download/1.4.0-c/aarch64-linux-gnu.arm-none-eabi-0196c06.220714.tar.gz", - "archiveFileName": "aarch64-linux-gnu.arm-none-eabi-0196c06.220714.tar.gz", - "checksum": "SHA-256:0bc906c2eb4b3999285ea8a71ec0c95a20a21f2ff46b1bdd264f2fd3c30fe580", - "size": "77889379" + "url": "https://github.com/earlephilhower/pico-quick-toolchain/releases/download/1.5.0-b/aarch64-linux-gnu.arm-none-eabi-c7bab52.230216.tar.gz", + "archiveFileName": "aarch64-linux-gnu.arm-none-eabi-c7bab52.230216.tar.gz", + "checksum": "SHA-256:2b3ec7c790bab21e08347205b8dec03a39747d0ef99266ce26a04e8e55bd7db8", + "size": "81474732" }, { "host": "arm-linux-gnueabihf", - "url": "https://github.com/earlephilhower/pico-quick-toolchain/releases/download/1.4.0-c/arm-linux-gnueabihf.arm-none-eabi-0196c06.220714.tar.gz", - "archiveFileName": "arm-linux-gnueabihf.arm-none-eabi-0196c06.220714.tar.gz", - "checksum": "SHA-256:2bf9f691d1fa97cea3b835a364fc24d06102181725001a00fe3e77526f90e2bd", - "size": "73342377" + "url": "https://github.com/earlephilhower/pico-quick-toolchain/releases/download/1.5.0-b/arm-linux-gnueabihf.arm-none-eabi-c7bab52.230216.tar.gz", + "archiveFileName": "arm-linux-gnueabihf.arm-none-eabi-c7bab52.230216.tar.gz", + "checksum": "SHA-256:9ec76a79f045d6f634a21e2b1e814b39bf85bb294c53a076b9c8ac2640ad3acc", + "size": "76133046" }, { "host": "i686-pc-linux-gnu", - "url": "https://github.com/earlephilhower/pico-quick-toolchain/releases/download/1.4.0-c/i686-linux-gnu.arm-none-eabi-0196c06.220714.tar.gz", - "archiveFileName": "i686-linux-gnu.arm-none-eabi-0196c06.220714.tar.gz", - "checksum": "SHA-256:e0fe347f2602247ffbc16bb7b74653fdb78c4f75b90037f2e82fc5498b5d1cb9", - "size": "79511866" + "url": "https://github.com/earlephilhower/pico-quick-toolchain/releases/download/1.5.0-b/i686-linux-gnu.arm-none-eabi-c7bab52.230216.tar.gz", + "archiveFileName": "i686-linux-gnu.arm-none-eabi-c7bab52.230216.tar.gz", + "checksum": "SHA-256:dea62b8d66c323a07e366625049a17b2d1d8a8a7882b4d2b3aa6247456614867", + "size": "83713275" }, { "host": "i686-mingw32", - "url": "https://github.com/earlephilhower/pico-quick-toolchain/releases/download/1.4.0-c/i686-w64-mingw32.arm-none-eabi-0196c06.220714.zip", - "archiveFileName": "i686-w64-mingw32.arm-none-eabi-0196c06.220714.zip", - "checksum": "SHA-256:d1ee0f00c97dc50dc06487d6fb6b5dd94bbb3cf1579c975bcd23d7a7922e53b7", - "size": "82626868" + "url": "https://github.com/earlephilhower/pico-quick-toolchain/releases/download/1.5.0-b/i686-w64-mingw32.arm-none-eabi-c7bab52.230216.zip", + "archiveFileName": "i686-w64-mingw32.arm-none-eabi-c7bab52.230216.zip", + "checksum": "SHA-256:0b76a320398ce6f0457edf98033742afd85ea3f143dec034a3fec7d3a21c52bf", + "size": "85634400" }, { "host": "x86_64-apple-darwin", - "url": "https://github.com/earlephilhower/pico-quick-toolchain/releases/download/1.4.0-c/x86_64-apple-darwin14.arm-none-eabi-0196c06.220714.tar.gz", - "archiveFileName": "x86_64-apple-darwin14.arm-none-eabi-0196c06.220714.tar.gz", - "checksum": "SHA-256:1b030451a5a6ddf42ac796c46b2f077f90f6d56586f4537a3486ce47670996cd", - "size": "82119254" + "url": "https://github.com/earlephilhower/pico-quick-toolchain/releases/download/1.5.0-b/x86_64-apple-darwin14.arm-none-eabi-c7bab52.230216.tar.gz", + "archiveFileName": "x86_64-apple-darwin14.arm-none-eabi-c7bab52.230216.tar.gz", + "checksum": "SHA-256:f83f143d424077322f7ea3971b88ac558c7b211f4a27776f6ba7c012a7c19938", + "size": "84979864" }, { "host": "x86_64-pc-linux-gnu", - "url": "https://github.com/earlephilhower/pico-quick-toolchain/releases/download/1.4.0-c/x86_64-linux-gnu.arm-none-eabi-0196c06.220714.tar.gz", - "archiveFileName": "x86_64-linux-gnu.arm-none-eabi-0196c06.220714.tar.gz", - "checksum": "SHA-256:73d032ba42d33f6e9c1d5de79b73bf5e9740b8e6b7fee37de3db03814c553694", - "size": "80363125" + "url": "https://github.com/earlephilhower/pico-quick-toolchain/releases/download/1.5.0-b/x86_64-linux-gnu.arm-none-eabi-c7bab52.230216.tar.gz", + "archiveFileName": "x86_64-linux-gnu.arm-none-eabi-c7bab52.230216.tar.gz", + "checksum": "SHA-256:bf197bde7ee76d26a8c142b2308e46269252b19403df5617aa1bd90ea4618427", + "size": "83669292" }, { "host": "x86_64-mingw32", - "url": "https://github.com/earlephilhower/pico-quick-toolchain/releases/download/1.4.0-c/x86_64-w64-mingw32.arm-none-eabi-0196c06.220714.zip", - "archiveFileName": "x86_64-w64-mingw32.arm-none-eabi-0196c06.220714.zip", - "checksum": "SHA-256:3f67e15adbe49ebaee72734e9d469bd6b34fd1be30ccdb6e55a1e05a0be4e1db", - "size": "86064664" + "url": "https://github.com/earlephilhower/pico-quick-toolchain/releases/download/1.5.0-b/x86_64-w64-mingw32.arm-none-eabi-c7bab52.230216.zip", + "archiveFileName": "x86_64-w64-mingw32.arm-none-eabi-c7bab52.230216.zip", + "checksum": "SHA-256:ed1a7103c9d55ad3d44eeb399a308789d1d1094a73c78b554e2693eb8140b9c5", + "size": "88352385" } ] }, { - "version": "1.4.0-c-0196c06", + "version": "1.5.0-b-c7bab52", "name": "pqt-elf2uf2", "systems": [ { "host": "aarch64-linux-gnu", - "url": "https://github.com/earlephilhower/pico-quick-toolchain/releases/download/1.4.0-c/aarch64-linux-gnu.elf2uf2-2e6142b.220714.tar.gz", - "archiveFileName": "aarch64-linux-gnu.elf2uf2-2e6142b.220714.tar.gz", - "checksum": "SHA-256:14d7c1be08151bcddcc19fdb5741bf52b435f08f52daff2d498a07c5ebfb5bfb", - "size": "82682" + "url": "https://github.com/earlephilhower/pico-quick-toolchain/releases/download/1.5.0-b/aarch64-linux-gnu.elf2uf2-2e6142b.230216.tar.gz", + "archiveFileName": "aarch64-linux-gnu.elf2uf2-2e6142b.230216.tar.gz", + "checksum": "SHA-256:00adc6949c467c75181364e9e5bf6378e50483caf4f04b0fc5e4c1d105f780ee", + "size": "82856" }, { "host": "arm-linux-gnueabihf", - "url": "https://github.com/earlephilhower/pico-quick-toolchain/releases/download/1.4.0-c/arm-linux-gnueabihf.elf2uf2-2e6142b.220714.tar.gz", - "archiveFileName": "arm-linux-gnueabihf.elf2uf2-2e6142b.220714.tar.gz", - "checksum": "SHA-256:31b790b5a19bbb5950212098aa42be43702fb4db50aa541c9f40b2320e2280be", - "size": "55991" + "url": "https://github.com/earlephilhower/pico-quick-toolchain/releases/download/1.5.0-b/arm-linux-gnueabihf.elf2uf2-2e6142b.230216.tar.gz", + "archiveFileName": "arm-linux-gnueabihf.elf2uf2-2e6142b.230216.tar.gz", + "checksum": "SHA-256:de9991519727ecbb3a157e672de2572c843558018515d7c680a3aa5a0d700056", + "size": "56175" }, { "host": "i686-pc-linux-gnu", - "url": "https://github.com/earlephilhower/pico-quick-toolchain/releases/download/1.4.0-c/i686-linux-gnu.elf2uf2-2e6142b.220714.tar.gz", - "archiveFileName": "i686-linux-gnu.elf2uf2-2e6142b.220714.tar.gz", - "checksum": "SHA-256:a3dd93861857fd81f8c9ed01509a0af012f446f23f405bc696f6a4d2f344262c", - "size": "91386" + "url": "https://github.com/earlephilhower/pico-quick-toolchain/releases/download/1.5.0-b/i686-linux-gnu.elf2uf2-2e6142b.230216.tar.gz", + "archiveFileName": "i686-linux-gnu.elf2uf2-2e6142b.230216.tar.gz", + "checksum": "SHA-256:12c4d4566a61c15104e26b10a1330a2dc12ecf63e054966e2d6cea13cef8f92b", + "size": "91559" }, { "host": "i686-mingw32", - "url": "https://github.com/earlephilhower/pico-quick-toolchain/releases/download/1.4.0-c/i686-w64-mingw32.elf2uf2-2e6142b.220714.zip", - "archiveFileName": "i686-w64-mingw32.elf2uf2-2e6142b.220714.zip", - "checksum": "SHA-256:25d6a934643074590c3006468ec051f62d02298abbff27d7e3643ee147e818e0", - "size": "71949" + "url": "https://github.com/earlephilhower/pico-quick-toolchain/releases/download/1.5.0-b/i686-w64-mingw32.elf2uf2-2e6142b.230216.zip", + "archiveFileName": "i686-w64-mingw32.elf2uf2-2e6142b.230216.zip", + "checksum": "SHA-256:6537879c71359b916dd604dc4833aeaab6ff7571ad9e498f1f2aa8085670548c", + "size": "72230" }, { "host": "x86_64-apple-darwin", - "url": "https://github.com/earlephilhower/pico-quick-toolchain/releases/download/1.4.0-c/x86_64-apple-darwin14.elf2uf2-2e6142b.220714.tar.gz", - "archiveFileName": "x86_64-apple-darwin14.elf2uf2-2e6142b.220714.tar.gz", - "checksum": "SHA-256:f2743d086d1992599d656aaa9a38a736d443bdc96619fd5bcabdc7fcb05225c8", - "size": "86600" + "url": "https://github.com/earlephilhower/pico-quick-toolchain/releases/download/1.5.0-b/x86_64-apple-darwin14.elf2uf2-2e6142b.230216.tar.gz", + "archiveFileName": "x86_64-apple-darwin14.elf2uf2-2e6142b.230216.tar.gz", + "checksum": "SHA-256:5b8fb8fc2dec9819ca018fa53d84b824dd2136fdcde713d98ef2cea9e5a1ce3f", + "size": "86779" }, { "host": "x86_64-pc-linux-gnu", - "url": "https://github.com/earlephilhower/pico-quick-toolchain/releases/download/1.4.0-c/x86_64-linux-gnu.elf2uf2-2e6142b.220714.tar.gz", - "archiveFileName": "x86_64-linux-gnu.elf2uf2-2e6142b.220714.tar.gz", - "checksum": "SHA-256:5b0e79bfd9d7e5f4d5e5cb0e6e2b685e10fdf3071139c00bf6274a5ca9b9717e", - "size": "82339" + "url": "https://github.com/earlephilhower/pico-quick-toolchain/releases/download/1.5.0-b/x86_64-linux-gnu.elf2uf2-2e6142b.230216.tar.gz", + "archiveFileName": "x86_64-linux-gnu.elf2uf2-2e6142b.230216.tar.gz", + "checksum": "SHA-256:784b76139053cd5fd3cac25ec00ac75d1612dc512c0cd5f7a69b5867df8ec7ba", + "size": "82555" }, { "host": "x86_64-mingw32", - "url": "https://github.com/earlephilhower/pico-quick-toolchain/releases/download/1.4.0-c/x86_64-w64-mingw32.elf2uf2-2e6142b.220714.zip", - "archiveFileName": "x86_64-w64-mingw32.elf2uf2-2e6142b.220714.zip", - "checksum": "SHA-256:f09e022cbb1fe73315ccf16a2af6bc687b64d0c44066f801fb9dee8326e941b1", - "size": "80399" + "url": "https://github.com/earlephilhower/pico-quick-toolchain/releases/download/1.5.0-b/x86_64-w64-mingw32.elf2uf2-2e6142b.230216.zip", + "archiveFileName": "x86_64-w64-mingw32.elf2uf2-2e6142b.230216.zip", + "checksum": "SHA-256:7ab9d08f6f3cd472c7fc005def31c87d9ce9ea57923ef7a6a81fe4f86a75b12a", + "size": "80680" } ] }, { - "version": "1.4.0-c-0196c06", + "version": "1.5.0-b-c7bab52", "name": "pqt-pioasm", "systems": [ { "host": "aarch64-linux-gnu", - "url": "https://github.com/earlephilhower/pico-quick-toolchain/releases/download/1.4.0-c/aarch64-linux-gnu.pioasm-2e6142b.220714.tar.gz", - "archiveFileName": "aarch64-linux-gnu.pioasm-2e6142b.220714.tar.gz", - "checksum": "SHA-256:d4ac4b39841984178babd75f5c09cad87e06bd2fb18cf04e40f561d72e604a5d", - "size": "453440" + "url": "https://github.com/earlephilhower/pico-quick-toolchain/releases/download/1.5.0-b/aarch64-linux-gnu.pioasm-2e6142b.230216.tar.gz", + "archiveFileName": "aarch64-linux-gnu.pioasm-2e6142b.230216.tar.gz", + "checksum": "SHA-256:6b60c57530bb3bd07f85a95808209f158b7b45b2808544794307701d8d468dd8", + "size": "453460" }, { "host": "arm-linux-gnueabihf", - "url": "https://github.com/earlephilhower/pico-quick-toolchain/releases/download/1.4.0-c/arm-linux-gnueabihf.pioasm-2e6142b.220714.tar.gz", - "archiveFileName": "arm-linux-gnueabihf.pioasm-2e6142b.220714.tar.gz", - "checksum": "SHA-256:568ebdd7b1a47c6dbf45793f9bf019855a1b14182fbeb7ed7e342979c6632eef", - "size": "360675" + "url": "https://github.com/earlephilhower/pico-quick-toolchain/releases/download/1.5.0-b/arm-linux-gnueabihf.pioasm-2e6142b.230216.tar.gz", + "archiveFileName": "arm-linux-gnueabihf.pioasm-2e6142b.230216.tar.gz", + "checksum": "SHA-256:079dc194321751d70e76496f0bcffdec58b73eb9976670a170f65ec06f110450", + "size": "360828" }, { "host": "i686-pc-linux-gnu", - "url": "https://github.com/earlephilhower/pico-quick-toolchain/releases/download/1.4.0-c/i686-linux-gnu.pioasm-2e6142b.220714.tar.gz", - "archiveFileName": "i686-linux-gnu.pioasm-2e6142b.220714.tar.gz", - "checksum": "SHA-256:2abac2bef690f7ffadfcf74af4832bfcc0e212606efbed21b385bda0517554ef", - "size": "511442" + "url": "https://github.com/earlephilhower/pico-quick-toolchain/releases/download/1.5.0-b/i686-linux-gnu.pioasm-2e6142b.230216.tar.gz", + "archiveFileName": "i686-linux-gnu.pioasm-2e6142b.230216.tar.gz", + "checksum": "SHA-256:8926f848f80c29d6e52595e54e9021c4955f053f8cf157b88275408a0047d08f", + "size": "511533" }, { "host": "i686-mingw32", - "url": "https://github.com/earlephilhower/pico-quick-toolchain/releases/download/1.4.0-c/i686-w64-mingw32.pioasm-2e6142b.220714.zip", - "archiveFileName": "i686-w64-mingw32.pioasm-2e6142b.220714.zip", - "checksum": "SHA-256:0b1336b999a31d164248248d37fa550aa14a06dae8ef5b215818c5f0597ca80b", - "size": "385882" + "url": "https://github.com/earlephilhower/pico-quick-toolchain/releases/download/1.5.0-b/i686-w64-mingw32.pioasm-2e6142b.230216.zip", + "archiveFileName": "i686-w64-mingw32.pioasm-2e6142b.230216.zip", + "checksum": "SHA-256:55a887da459e46b62b4e2eb6d62556e27a879e8bbf241c719f4d85b495d1caab", + "size": "386161" }, { "host": "x86_64-apple-darwin", - "url": "https://github.com/earlephilhower/pico-quick-toolchain/releases/download/1.4.0-c/x86_64-apple-darwin14.pioasm-2e6142b.220714.tar.gz", - "archiveFileName": "x86_64-apple-darwin14.pioasm-2e6142b.220714.tar.gz", - "checksum": "SHA-256:7057ba222a54ff9bd43a6a4232a6355100f29e0cc20d3facb5d600180f418e68", - "size": "480538" + "url": "https://github.com/earlephilhower/pico-quick-toolchain/releases/download/1.5.0-b/x86_64-apple-darwin14.pioasm-2e6142b.230216.tar.gz", + "archiveFileName": "x86_64-apple-darwin14.pioasm-2e6142b.230216.tar.gz", + "checksum": "SHA-256:2818ab1de24bad4e421315ac497b20373beaa16dd09b876bc6d00e2bba1f3d15", + "size": "480566" }, { "host": "x86_64-pc-linux-gnu", - "url": "https://github.com/earlephilhower/pico-quick-toolchain/releases/download/1.4.0-c/x86_64-linux-gnu.pioasm-2e6142b.220714.tar.gz", - "archiveFileName": "x86_64-linux-gnu.pioasm-2e6142b.220714.tar.gz", - "checksum": "SHA-256:30b367e8d2cd4ccdf151e728b4137bad1d993c42f0d640307e27d5fc55fce2c0", - "size": "458691" + "url": "https://github.com/earlephilhower/pico-quick-toolchain/releases/download/1.5.0-b/x86_64-linux-gnu.pioasm-2e6142b.230216.tar.gz", + "archiveFileName": "x86_64-linux-gnu.pioasm-2e6142b.230216.tar.gz", + "checksum": "SHA-256:c79400b056594268aab8ae1baf18abc8cf3170c6edb1f8104579738d78cd22ad", + "size": "458858" }, { "host": "x86_64-mingw32", - "url": "https://github.com/earlephilhower/pico-quick-toolchain/releases/download/1.4.0-c/x86_64-w64-mingw32.pioasm-2e6142b.220714.zip", - "archiveFileName": "x86_64-w64-mingw32.pioasm-2e6142b.220714.zip", - "checksum": "SHA-256:b7b340862e673f9e57287f02219b2d56094a497fe9d8c451acf28aaef721e038", - "size": "409101" + "url": "https://github.com/earlephilhower/pico-quick-toolchain/releases/download/1.5.0-b/x86_64-w64-mingw32.pioasm-2e6142b.230216.zip", + "archiveFileName": "x86_64-w64-mingw32.pioasm-2e6142b.230216.zip", + "checksum": "SHA-256:8c06fa68fe5d51fd54e9e9db11608e0e893d3b90e0437a6507eaef972e95b891", + "size": "409379" } ] }, { - "version": "1.4.0-c-0196c06", + "version": "1.5.0-b-c7bab52", "name": "pqt-mklittlefs", "systems": [ { "host": "aarch64-linux-gnu", - "url": "https://github.com/earlephilhower/pico-quick-toolchain/releases/download/1.4.0-c/aarch64-linux-gnu.mklittlefs-affa497.220714.tar.gz", - "archiveFileName": "aarch64-linux-gnu.mklittlefs-affa497.220714.tar.gz", - "checksum": "SHA-256:ad0af70d568e10a9a2a74c6e0a3cf8659a47b80fbf594b01731579bc21a5c212", - "size": "47287" + "url": "https://github.com/earlephilhower/pico-quick-toolchain/releases/download/1.5.0-b/aarch64-linux-gnu.mklittlefs-4aca452.230216.tar.gz", + "archiveFileName": "aarch64-linux-gnu.mklittlefs-4aca452.230216.tar.gz", + "checksum": "SHA-256:07d1baa8f0e8c3eb38db8751eb647e0f3ff465c5d7973642c8f9011a2c05dba2", + "size": "63222" }, { "host": "arm-linux-gnueabihf", - "url": "https://github.com/earlephilhower/pico-quick-toolchain/releases/download/1.4.0-c/arm-linux-gnueabihf.mklittlefs-affa497.220714.tar.gz", - "archiveFileName": "arm-linux-gnueabihf.mklittlefs-affa497.220714.tar.gz", - "checksum": "SHA-256:f8f1a1dd7b02220f11cf0f6a6c88692f7e056eb245fbc41017c33d333751980e", - "size": "40826" + "url": "https://github.com/earlephilhower/pico-quick-toolchain/releases/download/1.5.0-b/arm-linux-gnueabihf.mklittlefs-4aca452.230216.tar.gz", + "archiveFileName": "arm-linux-gnueabihf.mklittlefs-4aca452.230216.tar.gz", + "checksum": "SHA-256:e7ce6a71ea02cae9d149ee1e078702a4af50d7a930452237666a2b402c3f1181", + "size": "53461" }, { "host": "i686-pc-linux-gnu", - "url": "https://github.com/earlephilhower/pico-quick-toolchain/releases/download/1.4.0-c/i686-linux-gnu.mklittlefs-affa497.220714.tar.gz", - "archiveFileName": "i686-linux-gnu.mklittlefs-affa497.220714.tar.gz", - "checksum": "SHA-256:4d10a2bc6a8fa41a7e5642aa30128f797f84b099e1bb2282c6c2d62a06e81e21", - "size": "50925" + "url": "https://github.com/earlephilhower/pico-quick-toolchain/releases/download/1.5.0-b/i686-linux-gnu.mklittlefs-4aca452.230216.tar.gz", + "archiveFileName": "i686-linux-gnu.mklittlefs-4aca452.230216.tar.gz", + "checksum": "SHA-256:8c41373fb26bcdc15590b2924f23672a46464877702c583d9a7c30ac3a1ea942", + "size": "69995" }, { "host": "i686-mingw32", - "url": "https://github.com/earlephilhower/pico-quick-toolchain/releases/download/1.4.0-c/i686-w64-mingw32.mklittlefs-affa497.220714.zip", - "archiveFileName": "i686-w64-mingw32.mklittlefs-affa497.220714.zip", - "checksum": "SHA-256:71117412351ea2486848848d76f4d1e3c7a507a4d7546f6b0646bbc10c96d557", - "size": "334062" + "url": "https://github.com/earlephilhower/pico-quick-toolchain/releases/download/1.5.0-b/i686-w64-mingw32.mklittlefs-4aca452.230216.zip", + "archiveFileName": "i686-w64-mingw32.mklittlefs-4aca452.230216.zip", + "checksum": "SHA-256:9a4460c0e2e46847c2bd1ab934544f88fbd611237a12445ae69dbc6086f05c4f", + "size": "347619" }, { "host": "x86_64-apple-darwin", - "url": "https://github.com/earlephilhower/pico-quick-toolchain/releases/download/1.4.0-c/x86_64-apple-darwin14.mklittlefs-affa497.220714.tar.gz", - "archiveFileName": "x86_64-apple-darwin14.mklittlefs-affa497.220714.tar.gz", - "checksum": "SHA-256:b3d0c30f942982337cd4c0e4f70855f8eabcf1d378eac78465c7fee39ab5915f", - "size": "365780" + "url": "https://github.com/earlephilhower/pico-quick-toolchain/releases/download/1.5.0-b/x86_64-apple-darwin14.mklittlefs-4aca452.230216.tar.gz", + "archiveFileName": "x86_64-apple-darwin14.mklittlefs-4aca452.230216.tar.gz", + "checksum": "SHA-256:3575877065d206083c3dc4715bee983a1e7145969457d1fca752943aa67eb655", + "size": "378957" }, { "host": "x86_64-pc-linux-gnu", - "url": "https://github.com/earlephilhower/pico-quick-toolchain/releases/download/1.4.0-c/x86_64-linux-gnu.mklittlefs-affa497.220714.tar.gz", - "archiveFileName": "x86_64-linux-gnu.mklittlefs-affa497.220714.tar.gz", - "checksum": "SHA-256:9241e8e642748048bd32c7ccf4a8200e8bc104d6e328fe7437e8727866f29d94", - "size": "49787" + "url": "https://github.com/earlephilhower/pico-quick-toolchain/releases/download/1.5.0-b/x86_64-linux-gnu.mklittlefs-4aca452.230216.tar.gz", + "archiveFileName": "x86_64-linux-gnu.mklittlefs-4aca452.230216.tar.gz", + "checksum": "SHA-256:af472f914ba46b6a7466049cb989804ce56d5808334b1af09403dedfdf6e1ff2", + "size": "64931" }, { "host": "x86_64-mingw32", - "url": "https://github.com/earlephilhower/pico-quick-toolchain/releases/download/1.4.0-c/x86_64-w64-mingw32.mklittlefs-affa497.220714.zip", - "archiveFileName": "x86_64-w64-mingw32.mklittlefs-affa497.220714.zip", - "checksum": "SHA-256:2f39dd727e9cb61dbc631d00f543a99b6224fb24ffde0dff0cb2b70c9561ae69", - "size": "347612" + "url": "https://github.com/earlephilhower/pico-quick-toolchain/releases/download/1.5.0-b/x86_64-w64-mingw32.mklittlefs-4aca452.230216.zip", + "archiveFileName": "x86_64-w64-mingw32.mklittlefs-4aca452.230216.zip", + "checksum": "SHA-256:fd3dbfd224708f05f14d1c3f715d90473d462ba2fa06683fc523e13d2bb716f2", + "size": "359304" } ] } diff --git a/platform.txt b/platform.txt index dff74fecb..12fbc0063 100644 --- a/platform.txt +++ b/platform.txt @@ -20,14 +20,15 @@ # https://github.com/arduino/Arduino/wiki/Arduino-IDE-1.5---3rd-party-Hardware-specification name=Raspberry Pi RP2040 Boards -version=2.4.0 +version=3.2.0 runtime.tools.pqt-gcc.path={runtime.platform.path}/system/arm-none-eabi runtime.tools.pqt-python3.path={runtime.platform.path}/system/python3 runtime.tools.pqt-mklittlefs.path={runtime.platform.path}/system/mklittlefs runtime.tools.pqt-pioasm.path={runtime.platform.path}/system/pioasm runtime.tools.pqt-elf2uf2.path={runtime.platform.path}/system/elf2uf2 - +runtime.tools.pqt-openocd.path={runtime.platform.path}/system/openocd +runtime.tools.pqt-picotool.path={runtime.platform.path}/system/picotool compiler.path={runtime.tools.pqt-gcc.path}/bin/ compiler.libraries.ldflags= @@ -41,21 +42,21 @@ compiler.warning_flags.default=-Werror=return-type compiler.warning_flags.more=-Wall -Werror=return-type -Wno-ignored-qualifiers compiler.warning_flags.all=-Wall -Wextra -Werror=return-type -Wno-ignored-qualifiers -compiler.netdefines=-DPICO_CYW43_ARCH_THREADSAFE_BACKGROUND=1 -DCYW43_LWIP=0 {build.lwipdefs} -DLWIP_IGMP=1 -DLWIP_CHECKSUM_CTRL_PER_NETIF=1 -compiler.defines={build.led} {build.usbstack_flags} -DCFG_TUSB_MCU=OPT_MCU_RP2040 -DUSB_VID={build.vid} -DUSB_PID={build.pid} '-DUSB_MANUFACTURER={build.usb_manufacturer}' '-DUSB_PRODUCT={build.usb_product}' {compiler.netdefines} -DARDUINO_VARIANT="{build.variant}" +compiler.netdefines=-DPICO_CYW43_ARCH_THREADSAFE_BACKGROUND=1 -DCYW43_LWIP=1 {build.libpicowdefs} -DLWIP_IGMP=1 -DLWIP_CHECKSUM_CTRL_PER_NETIF=1 +compiler.defines={build.led} {build.usbstack_flags} -DCFG_TUSB_MCU=OPT_MCU_RP2040 {build.usbpid} {build.usbvid} {build.usbpwr} '-DUSB_MANUFACTURER={build.usb_manufacturer}' '-DUSB_PRODUCT={build.usb_product}' {compiler.netdefines} -DARDUINO_VARIANT="{build.variant}" -DTARGET_RP2040 -DPICO_FLASH_SIZE_BYTES={build.flash_total} compiler.includes="-iprefix{runtime.platform.path}/" "@{runtime.platform.path}/lib/platform_inc.txt" "-I{runtime.platform.path}/include" -compiler.flags=-march=armv6-m -mcpu=cortex-m0plus -mthumb -ffunction-sections -fdata-sections {build.flags.exceptions} {build.flags.stackprotect} {build.flags.cmsis} +compiler.flags=-march=armv6-m -mcpu=cortex-m0plus -mthumb -ffunction-sections -fdata-sections {build.flags.exceptions} {build.flags.stackprotect} {build.flags.cmsis} {build.picodebugflags} compiler.wrap="@{runtime.platform.path}/lib/platform_wrap.txt" compiler.libbearssl="{runtime.platform.path}/lib/libbearssl.a" compiler.c.cmd=arm-none-eabi-gcc -compiler.c.flags=-c {compiler.warning_flags} {compiler.defines} {compiler.flags} -MMD {compiler.includes} -std=gnu17 -g +compiler.c.flags=-c {compiler.warning_flags} {compiler.defines} {compiler.flags} -MMD {compiler.includes} -std=gnu17 -g -pipe compiler.c.elf.cmd=arm-none-eabi-g++ compiler.c.elf.flags={compiler.warning_flags} {compiler.defines} {compiler.flags} {build.flags.optimize} -u _printf_float -u _scanf_float compiler.S.cmd=arm-none-eabi-gcc compiler.S.flags=-c {compiler.warning_flags} -g -x assembler-with-cpp -MMD {compiler.includes} -g {build.flags.cmsis} compiler.cpp.cmd=arm-none-eabi-g++ -compiler.cpp.flags=-c {compiler.warning_flags} {compiler.defines} {compiler.flags} -MMD {compiler.includes} {build.flags.rtti} -std=gnu++17 -g +compiler.cpp.flags=-c {compiler.warning_flags} {compiler.defines} {compiler.flags} -MMD {compiler.includes} {build.flags.rtti} -std=gnu++17 -g -pipe compiler.ar.cmd=arm-none-eabi-ar compiler.ar.flags=rcs @@ -81,6 +82,7 @@ compiler.ar.extra_flags= compiler.elf2hex.extra_flags= # Board configuration, set in boards.txt. Present here to ensure substitution works +build.flash_total= build.flash_length= build.eeprom_start= build.flags.optimize=-Os @@ -93,11 +95,18 @@ build.flags.libstdcpp=-lstdc++ build.flags.exceptions=-fno-exceptions build.flags.stackprotect= build.libpico=libpico.a +build.libpicow=libpicow-noipv6-nobtc-noble.a build.boot2=boot2_generic_03h_4_padded_checksum -build.lwipdefs=-DLWIP_IPV6=0 -DLWIP_IPV4=1 +build.libpicowdefs=-DLWIP_IPV6=0 -DLWIP_IPV4=1 +build.wificc=-DWIFICC=CYW43_COUNTRY_WORLDWIDE +build.debugscript=picoprobe.tcl +build.picodebugflags= # Allow Pico boards do be auto-discovered by the IDE -discovery.rp2040.pattern="{runtime.tools.pqt-python3.path}/python3" -I "{runtime.platform.path}/tools/discovery.py" +#discovery.rp2040.pattern={runtime.tools.pqt-python3.path}/python3 -I "{runtime.platform.path}/tools/pluggable_discovery.py" +discovery.rp2040.pattern={runtime.platform.path}/system/python3/python3 -I "{runtime.platform.path}/tools/pluggable_discovery.py" +#pluggable_discovery.rp2040.pattern="{runtime.tools.pqt-python3.path}/python3" -I "{runtime.platform.path}/tools/pluggable_discovery.py" +pluggable_discovery.rp2040.pattern="{runtime.platform.path}/system/python3/python3" -I "{runtime.platform.path}/tools/pluggable_discovery.py" # Compile patterns @@ -107,13 +116,13 @@ discovery.rp2040.pattern="{runtime.tools.pqt-python3.path}/python3" -I "{runtime recipe.hooks.sketch.prebuild.pattern="{runtime.tools.pqt-python3.path}/python3" -I "{runtime.platform.path}/tools/signing.py" --mode header --publickey "{build.source.path}/public.key" --out "{build.path}/core/Updater_Signing.h" ## Compile c files -recipe.c.o.pattern="{compiler.path}{compiler.c.cmd}" {compiler.c.flags} {build.usbpid} {build.usbpwr} -DF_CPU={build.f_cpu} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DBOARD_NAME="{build.board}" -DARDUINO_ARCH_{build.arch} {compiler.c.extra_flags} {build.extra_flags} {build.debug_port} {build.debug_level} {build.flags.optimize} {includes} "{source_file}" -o "{object_file}" +recipe.c.o.pattern="{compiler.path}{compiler.c.cmd}" {compiler.c.flags} -DF_CPU={build.f_cpu} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DBOARD_NAME="{build.board}" -DARDUINO_ARCH_{build.arch} {compiler.c.extra_flags} {build.extra_flags} {build.debug_port} {build.debug_level} {build.flags.optimize} {includes} "{source_file}" -o "{object_file}" ## Compile c++ files -recipe.cpp.o.pattern="{compiler.path}{compiler.cpp.cmd}" {compiler.cpp.flags} {build.usbpid} {build.usbpwr} -DF_CPU={build.f_cpu} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DBOARD_NAME="{build.board}" -DARDUINO_ARCH_{build.arch} {compiler.cpp.extra_flags} {build.extra_flags} {build.debug_port} {build.debug_level} {build.flags.optimize} {includes} "{source_file}" -o "{object_file}" +recipe.cpp.o.pattern="{compiler.path}{compiler.cpp.cmd}" -I "{build.path}/core" {compiler.cpp.flags} -DF_CPU={build.f_cpu} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DBOARD_NAME="{build.board}" -DARDUINO_ARCH_{build.arch} {compiler.cpp.extra_flags} {build.extra_flags} {build.debug_port} {build.debug_level} {build.flags.optimize} {build.wificc} {includes} "{source_file}" -o "{object_file}" ## Compile S files -recipe.S.o.pattern="{compiler.path}{compiler.S.cmd}" {compiler.S.flags} {build.usbpid} {build.usbpwr} -DF_CPU={build.f_cpu} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DBOARD_NAME="{build.board}" -DARDUINO_ARCH_{build.arch} {compiler.S.extra_flags} {build.extra_flags} {build.debug_port} {build.debug_level} {includes} "{source_file}" -o "{object_file}" +recipe.S.o.pattern="{compiler.path}{compiler.S.cmd}" {compiler.S.flags} -DF_CPU={build.f_cpu} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DBOARD_NAME="{build.board}" -DARDUINO_ARCH_{build.arch} {compiler.S.extra_flags} {build.extra_flags} {build.debug_port} {build.debug_level} {includes} "{source_file}" -o "{object_file}" ## Create archives # archive_file_path is needed for backwards compatibility with IDE 1.6.5 or older, IDE 1.6.6 or newer overrides this value @@ -127,7 +136,7 @@ recipe.hooks.linking.prelink.1.pattern="{runtime.tools.pqt-python3.path}/python3 recipe.hooks.linking.prelink.2.pattern="{compiler.path}{compiler.S.cmd}" {compiler.c.elf.flags} {compiler.c.elf.extra_flags} -c "{runtime.platform.path}/boot2/{build.boot2}.S" "-I{runtime.platform.path}/pico-sdk/src/rp2040/hardware_regs/include/" "-I{runtime.platform.path}/pico-sdk/src/common/pico_binary_info/include" -o "{build.path}/boot2.o" ## Combine gc-sections, archives, and objects -recipe.c.combine.pattern="{compiler.path}{compiler.c.elf.cmd}" "-L{build.path}" {compiler.c.elf.flags} {compiler.c.elf.extra_flags} {compiler.ldflags} "-Wl,--script={build.path}/memmap_default.ld" "-Wl,-Map,{build.path}/{build.project_name}.map" -o "{build.path}/{build.project_name}.elf" -Wl,--start-group {object_files} "{build.path}/{archive_file}" "{build.path}/boot2.o" "{runtime.platform.path}/lib/ota.o" {compiler.libraries.ldflags} "{runtime.platform.path}/lib/{build.libpico}" {compiler.libbearssl} -lm -lc {build.flags.libstdcpp} -lc -Wl,--end-group +recipe.c.combine.pattern="{compiler.path}{compiler.c.elf.cmd}" "-L{build.path}" {compiler.c.elf.flags} {compiler.c.elf.extra_flags} {compiler.ldflags} "-Wl,--script={build.path}/memmap_default.ld" "-Wl,-Map,{build.path}/{build.project_name}.map" -o "{build.path}/{build.project_name}.elf" -Wl,--start-group {object_files} "{build.path}/{archive_file}" "{build.path}/boot2.o" "{runtime.platform.path}/lib/ota.o" {compiler.libraries.ldflags} "{runtime.platform.path}/lib/{build.libpico}" "{runtime.platform.path}/lib/{build.libpicow}" {compiler.libbearssl} -lm -lc {build.flags.libstdcpp} -lc -Wl,--end-group ## Create output (UF2 file) recipe.objcopy.uf2.pattern="{runtime.tools.pqt-elf2uf2.path}/elf2uf2" "{build.path}/{build.project_name}.elf" "{build.path}/{build.project_name}.uf2" @@ -146,7 +155,20 @@ recipe.output.save_file={build.project_name}.{build.variant}.{build.preferred_ou ## Compute size recipe.size.pattern="{compiler.path}{compiler.size.cmd}" -A "{build.path}/{build.project_name}.elf" recipe.size.regex=^(?:\.boot2|\.text|\.rodata|\.ARM\.extab|\.ARM\.exidx)\s+([0-9]+).* -recipe.size.regex.data=^(?:\.data|\.bss|\.ram_vector_table|\.uninitialized_data)\s+([0-9]+).* +recipe.size.regex.data=^(?:\.data|\.bss|\.ram_vector_table|\.uninitialized_ram|\.uninitialized_data)\s+([0-9]+).* + + +# Debugging +debug.executable={build.path}/{build.project_name}.elf +debug.toolchain=gcc +debug.toolchain.path={runtime.tools.pqt-gcc.path}/bin/ +debug.toolchain.prefix=arm-none-eabi- +debug.server=openocd +debug.server.openocd.path={runtime.tools.pqt-openocd.path}/bin/openocd +debug.server.openocd.scripts_dir={runtime.tools.pqt-openocd.path}/share/openocd/scripts/ +debug.server.openocd.script={runtime.platform.path}/lib/{build.debugscript} + + tools.uf2conv.path= # Because the variable expansion doesn't allow one tool to find another, the following lines @@ -162,6 +184,20 @@ tools.uf2conv.upload.params.quiet= tools.uf2conv.upload.pattern="{cmd}" -I "{runtime.platform.path}/tools/uf2conv.py" --serial "{serial.port}" --family RP2040 --deploy "{build.path}/{build.project_name}.uf2" tools.uf2conv.upload.network_pattern="{network_cmd}" -I "{runtime.platform.path}/tools/espota.py" -i "{serial.port}" -p "{network.port}" "--auth={network.password}" -f "{build.path}/{build.project_name}.bin" +#tools.uf2conv-network.cmd={runtime.tools.pqt-python3.path}/python3 +tools.uf2conv-network.cmd={runtime.platform.path}/system/python3/python3 +tools.uf2conv-network.upload.protocol=uf2 +tools.uf2conv-network.upload.params.verbose= +tools.uf2conv-network.upload.params.quiet= +tools.uf2conv-network.upload.pattern="{cmd}" -I "{runtime.platform.path}/tools/espota.py" -i "{upload.port.address}" -p "{upload.port.properties.port}" "--auth={upload.field.password}" -f "{build.path}/{build.project_name}.bin" + +#tools.picotool.cmd={runtime.tools.pqt-picotool.path} +tools.picotool.cmd={runtime.platform.path}/system/picotool +tools.picotool.upload.protocol=picotool +tools.picotool.upload.params.verbose= +tools.picotool.upload.params.quiet= +tools.picotool.upload.pattern="{cmd}/picotool" load "{build.path}/{build.project_name}.uf2" -f + #tools.picoprobe.cmd={runtime.tools.pqt-openocd.path} tools.picoprobe.cmd={runtime.platform.path}/system/openocd tools.picoprobe.upload.protocol=picoprobe @@ -169,6 +205,13 @@ tools.picoprobe.upload.params.verbose= tools.picoprobe.upload.params.quiet= tools.picoprobe.upload.pattern="{cmd}/bin/openocd" -f "interface/picoprobe.cfg" -f "target/rp2040.cfg" -s "{cmd}/share/openocd/scripts" -c "program {{build.path}/{build.project_name}.elf} verify reset exit" +#tools.picoprobe_cmsis_dap.cmd={runtime.tools.pqt-openocd.path} +tools.picoprobe_cmsis_dap.cmd={runtime.platform.path}/system/openocd +tools.picoprobe_cmsis_dap.upload.protocol=picoprobe_cmsis_dap +tools.picoprobe_cmsis_dap.upload.params.verbose= +tools.picoprobe_cmsis_dap.upload.params.quiet= +tools.picoprobe_cmsis_dap.upload.pattern="{cmd}/bin/openocd" -f "interface/cmsis-dap.cfg" -f "target/rp2040.cfg" -s "{cmd}/share/openocd/scripts" -c "adapter speed 5000" -c "program {{build.path}/{build.project_name}.elf} verify reset exit" + #tools.picodebug.cmd={runtime.tools.pqt-openocd.path} tools.picodebug.cmd={runtime.platform.path}/system/openocd tools.picodebug.upload.protocol=pico-debug diff --git a/tests/common.sh b/tests/common.sh index 742c80d6d..8b1ac89ce 100755 --- a/tests/common.sh +++ b/tests/common.sh @@ -80,7 +80,8 @@ function build_sketches() continue # Not ours to do fi - if [ -e $cache_dir/core/*.a ]; then + cacheas=( $cache_dir/core/*.a ) + if [ -e ${cacheas[0]} ]; then # We need to preserve the build.options.json file and replace the last .ino # with this sketch's ino file, or builder will throw everything away. jq '."sketchLocation" = "'$sketch'"' $build_dir/build.options.json > $build_dir/build.options.json.tmp diff --git a/tests/restyle.sh b/tests/restyle.sh index aae714d5e..37bbcbf8f 100755 --- a/tests/restyle.sh +++ b/tests/restyle.sh @@ -1,13 +1,18 @@ #!/bin/bash -for dir in ./cores/rp2040 ./libraries/EEPROM ./libraries/I2S \ - ./libraries/LittleFS/src ./libraries/LittleFS/examples \ - ./libraries/rp2040 ./libraries/SD ./libraries/ESP8266SdFat \ - ./libraries/Servo ./libraries/SPI ./libraries/Wire \ +for dir in ./cores/rp2040 ./libraries/EEPROM ./libraries/I2S ./libraries/SingleFileDrive \ + ./libraries/LittleFS/src ./libraries/LittleFS/examples ./libraries/PWMAudio \ + ./libraries/rp2040 ./libraries/SD ./libraries/ESP8266SdFat ./libraries/ADCInput \ + ./libraries/Servo ./libraries/SPI ./libraries/Wire ./libraries/PDM \ ./libraries/WiFi ./libraries/lwIP_Ethernet ./libraries/lwIP_CYW43 \ ./libraries/FreeRTOS/src ./libraries/LEAmDNS ./libraries/MD5Builder \ ./libraries/PicoOTA ./libraries/SDFS ./libraries/ArduinoOTA \ - ./libraries/Updater; do + ./libraries/Updater ./libraries/HTTPClient ./libraries/HTTPUpdate \ + ./libraries/WebServer ./libraries/HTTPUpdateServer ./libraries/DNSServer \ + ./libraries/Joystick ./libraries/Keyboard ./libraries/Mouse \ + ./libraries/JoystickBT ./libraries/KeyboardBT ./variants ./libraries/BTstackLib \ + ./libraries/MouseBT ./libraries/SerialBT ./libraries/HID_Bluetooth \ + ./libraries/JoystickBLE ./libraries/KeyboardBLE ./libraries/MouseBLE ; do find $dir -type f \( -name "*.c" -o -name "*.h" -o -name "*.cpp" \) -a \! -path '*api*' -exec astyle --suffix=none --options=./tests/astyle_core.conf \{\} \; find $dir -type f -name "*.ino" -exec astyle --suffix=none --options=./tests/astyle_examples.conf \{\} \; done diff --git a/tools/build.py b/tools/build.py index 86cc160b4..876a33186 100755 --- a/tools/build.py +++ b/tools/build.py @@ -65,10 +65,10 @@ def compile(tmp_dir, sketch, cache, tools_dir, hardware_dir, ide_path, f, args): 'dbgport={dbgport},' \ 'dbglvl={dbglvl},' \ 'usbstack={usbstack}'.format(**vars(args)) - if "/WiFi" in sketch: - fqbn = fqbn.replace("rpipico", "rpipicow") - if "/ArduinoOTA" in sketch: + if ("/WiFi" in sketch) or ("/ArduinoOTA" in sketch) or ("/HTTPClient" in sketch) or ('/HTTPUpdate' in sketch) or ('/WebServer' in sketch) or ('/DNSServer' in sketch) or ('/BT' in sketch) or ('/BLE' in sketch): fqbn = fqbn.replace("rpipico", "rpipicow") + if ('/BT' in sketch) or ('/BLE' in sketch): + fqbn = fqbn + ",ipbtstack=ipv4btcble" cmd += [fqbn] cmd += ['-built-in-libraries', ide_path + '/libraries'] cmd += ['-ide-version=10607'] diff --git a/tools/discovery.py b/tools/discovery.py deleted file mode 100755 index 8c70a08d1..000000000 --- a/tools/discovery.py +++ /dev/null @@ -1,39 +0,0 @@ -#!/usr/bin/env python3 -import time -import subprocess -import uf2conv - -boards = False -while True: - l = uf2conv.get_drives() - if (len(l) > 0) and (not boards): - print (""" -{ - "eventType": "add", - "port": { - "address": "1", - "label": "Board", - "boardName": "RPI 2040", - "protocol": "uf2", - "protocolLabel": "UF2 Devices", - "prefs": {}, - "identificationPrefs": {} - } -}""", flush=True) - boards = True - elif (len(l) == 0) and boards: - print (""" -{ - "eventType": "remove", - "port": { - "address": "1", - "label": "Board", - "boardName": "RPI 2040", - "protocol": "uf2", - "protocolLabel": "UF2 Devices", - "prefs": {}, - "identificationPrefs": {} - } -}""", flush=True) - boards = False - time.sleep(1) diff --git a/tools/json/0xcb_helios.json b/tools/json/0xcb_helios.json new file mode 100644 index 000000000..c3b6a0101 --- /dev/null +++ b/tools/json/0xcb_helios.json @@ -0,0 +1,56 @@ +{ + "build": { + "arduino": { + "earlephilhower": { + "boot2_source": "boot2_w25q128jvxq_4_padded_checksum.S", + "usb_vid": "0x1209", + "usb_pid": "0xCB74" + } + }, + "core": "earlephilhower", + "cpu": "cortex-m0plus", + "extra_flags": "-D ARDUINO_0XCB_HELIOS -DARDUINO_ARCH_RP2040 -DUSBD_MAX_POWER_MA=500", + "f_cpu": "133000000L", + "hwids": [ + [ + "0x2E8A", + "0x00C0" + ], + [ + "0x1209", + "0xCB74" + ] + ], + "mcu": "rp2040", + "variant": "0xcb_helios" + }, + "debug": { + "jlink_device": "RP2040_M0_0", + "openocd_target": "rp2040.cfg", + "svd_path": "rp2040.svd" + }, + "frameworks": [ + "arduino" + ], + "name": "Helios", + "upload": { + "maximum_ram_size": 270336, + "maximum_size": 16777216, + "require_upload_port": true, + "native_usb": true, + "use_1200bps_touch": true, + "wait_for_upload_port": false, + "protocol": "picotool", + "protocols": [ + "blackmagic", + "cmsis-dap", + "jlink", + "raspberrypi-swd", + "picotool", + "picoprobe", + "pico-debug" + ] + }, + "url": "https://www.raspberrypi.org/products/raspberry-pi-pico/", + "vendor": "0xCB" +} diff --git a/tools/json/adafruit_feather.json b/tools/json/adafruit_feather.json index 9fa4cce72..c699d5bce 100644 --- a/tools/json/adafruit_feather.json +++ b/tools/json/adafruit_feather.json @@ -42,11 +42,13 @@ "wait_for_upload_port": false, "protocol": "picotool", "protocols": [ + "blackmagic", "cmsis-dap", "jlink", "raspberrypi-swd", "picotool", - "picoprobe" + "picoprobe", + "pico-debug" ] }, "url": "https://www.raspberrypi.org/products/raspberry-pi-pico/", diff --git a/tools/json/adafruit_feather_can.json b/tools/json/adafruit_feather_can.json new file mode 100644 index 000000000..c6777cb69 --- /dev/null +++ b/tools/json/adafruit_feather_can.json @@ -0,0 +1,56 @@ +{ + "build": { + "arduino": { + "earlephilhower": { + "boot2_source": "boot2_w25q080_2_padded_checksum.S", + "usb_vid": "0x239A", + "usb_pid": "0x812F" + } + }, + "core": "earlephilhower", + "cpu": "cortex-m0plus", + "extra_flags": "-D ARDUINO_ADAFRUIT_FEATHER_RP2040_CAN -DARDUINO_ARCH_RP2040 -DUSBD_MAX_POWER_MA=250", + "f_cpu": "133000000L", + "hwids": [ + [ + "0x2E8A", + "0x00C0" + ], + [ + "0x239A", + "0x812F" + ] + ], + "mcu": "rp2040", + "variant": "adafruit_feather_can" + }, + "debug": { + "jlink_device": "RP2040_M0_0", + "openocd_target": "rp2040.cfg", + "svd_path": "rp2040.svd" + }, + "frameworks": [ + "arduino" + ], + "name": "Feather RP2040 CAN", + "upload": { + "maximum_ram_size": 270336, + "maximum_size": 8388608, + "require_upload_port": true, + "native_usb": true, + "use_1200bps_touch": true, + "wait_for_upload_port": false, + "protocol": "picotool", + "protocols": [ + "blackmagic", + "cmsis-dap", + "jlink", + "raspberrypi-swd", + "picotool", + "picoprobe", + "pico-debug" + ] + }, + "url": "https://www.raspberrypi.org/products/raspberry-pi-pico/", + "vendor": "Adafruit" +} diff --git a/tools/json/adafruit_feather_dvi.json b/tools/json/adafruit_feather_dvi.json new file mode 100644 index 000000000..36bae0a6d --- /dev/null +++ b/tools/json/adafruit_feather_dvi.json @@ -0,0 +1,56 @@ +{ + "build": { + "arduino": { + "earlephilhower": { + "boot2_source": "boot2_w25q080_2_padded_checksum.S", + "usb_vid": "0x239A", + "usb_pid": "0x8127" + } + }, + "core": "earlephilhower", + "cpu": "cortex-m0plus", + "extra_flags": "-D ARDUINO_ADAFRUIT_FEATHER_RP2040_DVI -DARDUINO_ARCH_RP2040 -DUSBD_MAX_POWER_MA=250", + "f_cpu": "133000000L", + "hwids": [ + [ + "0x2E8A", + "0x00C0" + ], + [ + "0x239A", + "0x8127" + ] + ], + "mcu": "rp2040", + "variant": "adafruit_feather_dvi" + }, + "debug": { + "jlink_device": "RP2040_M0_0", + "openocd_target": "rp2040.cfg", + "svd_path": "rp2040.svd" + }, + "frameworks": [ + "arduino" + ], + "name": "Feather RP2040 DVI", + "upload": { + "maximum_ram_size": 270336, + "maximum_size": 8388608, + "require_upload_port": true, + "native_usb": true, + "use_1200bps_touch": true, + "wait_for_upload_port": false, + "protocol": "picotool", + "protocols": [ + "blackmagic", + "cmsis-dap", + "jlink", + "raspberrypi-swd", + "picotool", + "picoprobe", + "pico-debug" + ] + }, + "url": "https://www.raspberrypi.org/products/raspberry-pi-pico/", + "vendor": "Adafruit" +} diff --git a/tools/json/adafruit_feather_prop_maker.json b/tools/json/adafruit_feather_prop_maker.json new file mode 100644 index 000000000..e0f586eaa --- /dev/null +++ b/tools/json/adafruit_feather_prop_maker.json @@ -0,0 +1,56 @@ +{ + "build": { + "arduino": { + "earlephilhower": { + "boot2_source": "boot2_w25q080_2_padded_checksum.S", + "usb_vid": "0x239A", + "usb_pid": "0x8131" + } + }, + "core": "earlephilhower", + "cpu": "cortex-m0plus", + "extra_flags": "-D ARDUINO_ADAFRUIT_FEATHER_RP2040_PROP_MAKER -DARDUINO_ARCH_RP2040 -DUSBD_MAX_POWER_MA=250", + "f_cpu": "133000000L", + "hwids": [ + [ + "0x2E8A", + "0x00C0" + ], + [ + "0x239A", + "0x8131" + ] + ], + "mcu": "rp2040", + "variant": "adafruit_feather_prop_maker" + }, + "debug": { + "jlink_device": "RP2040_M0_0", + "openocd_target": "rp2040.cfg", + "svd_path": "rp2040.svd" + }, + "frameworks": [ + "arduino" + ], + "name": "Feather RP2040 Prop-Maker", + "upload": { + "maximum_ram_size": 270336, + "maximum_size": 8388608, + "require_upload_port": true, + "native_usb": true, + "use_1200bps_touch": true, + "wait_for_upload_port": false, + "protocol": "picotool", + "protocols": [ + "blackmagic", + "cmsis-dap", + "jlink", + "raspberrypi-swd", + "picotool", + "picoprobe", + "pico-debug" + ] + }, + "url": "https://www.raspberrypi.org/products/raspberry-pi-pico/", + "vendor": "Adafruit" +} diff --git a/tools/json/adafruit_feather_rfm.json b/tools/json/adafruit_feather_rfm.json new file mode 100644 index 000000000..163d896a7 --- /dev/null +++ b/tools/json/adafruit_feather_rfm.json @@ -0,0 +1,56 @@ +{ + "build": { + "arduino": { + "earlephilhower": { + "boot2_source": "boot2_w25q080_2_padded_checksum.S", + "usb_vid": "0x239A", + "usb_pid": "0x812D" + } + }, + "core": "earlephilhower", + "cpu": "cortex-m0plus", + "extra_flags": "-D ARDUINO_ADAFRUIT_FEATHER_RP2040_RFM -DARDUINO_ARCH_RP2040 -DUSBD_MAX_POWER_MA=250", + "f_cpu": "133000000L", + "hwids": [ + [ + "0x2E8A", + "0x00C0" + ], + [ + "0x239A", + "0x812D" + ] + ], + "mcu": "rp2040", + "variant": "adafruit_feather_rfm" + }, + "debug": { + "jlink_device": "RP2040_M0_0", + "openocd_target": "rp2040.cfg", + "svd_path": "rp2040.svd" + }, + "frameworks": [ + "arduino" + ], + "name": "Feather RP2040 RFM", + "upload": { + "maximum_ram_size": 270336, + "maximum_size": 8388608, + "require_upload_port": true, + "native_usb": true, + "use_1200bps_touch": true, + "wait_for_upload_port": false, + "protocol": "picotool", + "protocols": [ + "blackmagic", + "cmsis-dap", + "jlink", + "raspberrypi-swd", + "picotool", + "picoprobe", + "pico-debug" + ] + }, + "url": "https://www.raspberrypi.org/products/raspberry-pi-pico/", + "vendor": "Adafruit" +} diff --git a/tools/json/adafruit_feather_scorpio.json b/tools/json/adafruit_feather_scorpio.json new file mode 100644 index 000000000..c38f39a13 --- /dev/null +++ b/tools/json/adafruit_feather_scorpio.json @@ -0,0 +1,56 @@ +{ + "build": { + "arduino": { + "earlephilhower": { + "boot2_source": "boot2_w25q080_2_padded_checksum.S", + "usb_vid": "0x239A", + "usb_pid": "0x8121" + } + }, + "core": "earlephilhower", + "cpu": "cortex-m0plus", + "extra_flags": "-D ARDUINO_ADAFRUIT_FEATHER_RP2040_SCORPIO -DARDUINO_ARCH_RP2040 -DUSBD_MAX_POWER_MA=250", + "f_cpu": "133000000L", + "hwids": [ + [ + "0x2E8A", + "0x00C0" + ], + [ + "0x239A", + "0x8121" + ] + ], + "mcu": "rp2040", + "variant": "adafruit_feather_scorpio" + }, + "debug": { + "jlink_device": "RP2040_M0_0", + "openocd_target": "rp2040.cfg", + "svd_path": "rp2040.svd" + }, + "frameworks": [ + "arduino" + ], + "name": "Feather RP2040 SCORPIO", + "upload": { + "maximum_ram_size": 270336, + "maximum_size": 8388608, + "require_upload_port": true, + "native_usb": true, + "use_1200bps_touch": true, + "wait_for_upload_port": false, + "protocol": "picotool", + "protocols": [ + "blackmagic", + "cmsis-dap", + "jlink", + "raspberrypi-swd", + "picotool", + "picoprobe", + "pico-debug" + ] + }, + "url": "https://www.raspberrypi.org/products/raspberry-pi-pico/", + "vendor": "Adafruit" +} diff --git a/tools/json/adafruit_feather_thinkink.json b/tools/json/adafruit_feather_thinkink.json new file mode 100644 index 000000000..a76ee7e83 --- /dev/null +++ b/tools/json/adafruit_feather_thinkink.json @@ -0,0 +1,56 @@ +{ + "build": { + "arduino": { + "earlephilhower": { + "boot2_source": "boot2_w25q080_2_padded_checksum.S", + "usb_vid": "0x239A", + "usb_pid": "0x812B" + } + }, + "core": "earlephilhower", + "cpu": "cortex-m0plus", + "extra_flags": "-D ARDUINO_ADAFRUIT_FEATHER_RP2040_THINKINK -DARDUINO_ARCH_RP2040 -DUSBD_MAX_POWER_MA=250", + "f_cpu": "133000000L", + "hwids": [ + [ + "0x2E8A", + "0x00C0" + ], + [ + "0x239A", + "0x812B" + ] + ], + "mcu": "rp2040", + "variant": "adafruit_feather_thinkink" + }, + "debug": { + "jlink_device": "RP2040_M0_0", + "openocd_target": "rp2040.cfg", + "svd_path": "rp2040.svd" + }, + "frameworks": [ + "arduino" + ], + "name": "Feather RP2040 ThinkINK", + "upload": { + "maximum_ram_size": 270336, + "maximum_size": 8388608, + "require_upload_port": true, + "native_usb": true, + "use_1200bps_touch": true, + "wait_for_upload_port": false, + "protocol": "picotool", + "protocols": [ + "blackmagic", + "cmsis-dap", + "jlink", + "raspberrypi-swd", + "picotool", + "picoprobe", + "pico-debug" + ] + }, + "url": "https://www.raspberrypi.org/products/raspberry-pi-pico/", + "vendor": "Adafruit" +} diff --git a/tools/json/adafruit_feather_usb_host.json b/tools/json/adafruit_feather_usb_host.json new file mode 100644 index 000000000..4c017c016 --- /dev/null +++ b/tools/json/adafruit_feather_usb_host.json @@ -0,0 +1,56 @@ +{ + "build": { + "arduino": { + "earlephilhower": { + "boot2_source": "boot2_w25q080_2_padded_checksum.S", + "usb_vid": "0x239A", + "usb_pid": "0x8129" + } + }, + "core": "earlephilhower", + "cpu": "cortex-m0plus", + "extra_flags": "-D ARDUINO_ADAFRUIT_FEATHER_RP2040_USB_HOST -DARDUINO_ARCH_RP2040 -DUSBD_MAX_POWER_MA=250", + "f_cpu": "133000000L", + "hwids": [ + [ + "0x2E8A", + "0x00C0" + ], + [ + "0x239A", + "0x8129" + ] + ], + "mcu": "rp2040", + "variant": "adafruit_feather_usb_host" + }, + "debug": { + "jlink_device": "RP2040_M0_0", + "openocd_target": "rp2040.cfg", + "svd_path": "rp2040.svd" + }, + "frameworks": [ + "arduino" + ], + "name": "Feather RP2040 USB Host", + "upload": { + "maximum_ram_size": 270336, + "maximum_size": 8388608, + "require_upload_port": true, + "native_usb": true, + "use_1200bps_touch": true, + "wait_for_upload_port": false, + "protocol": "picotool", + "protocols": [ + "blackmagic", + "cmsis-dap", + "jlink", + "raspberrypi-swd", + "picotool", + "picoprobe", + "pico-debug" + ] + }, + "url": "https://www.raspberrypi.org/products/raspberry-pi-pico/", + "vendor": "Adafruit" +} diff --git a/tools/json/adafruit_itsybitsy.json b/tools/json/adafruit_itsybitsy.json index bb3e1c00e..acfc7f4e9 100644 --- a/tools/json/adafruit_itsybitsy.json +++ b/tools/json/adafruit_itsybitsy.json @@ -42,11 +42,13 @@ "wait_for_upload_port": false, "protocol": "picotool", "protocols": [ + "blackmagic", "cmsis-dap", "jlink", "raspberrypi-swd", "picotool", - "picoprobe" + "picoprobe", + "pico-debug" ] }, "url": "https://www.raspberrypi.org/products/raspberry-pi-pico/", diff --git a/tools/json/adafruit_kb2040.json b/tools/json/adafruit_kb2040.json index 9b9e27c67..e540e7b0d 100644 --- a/tools/json/adafruit_kb2040.json +++ b/tools/json/adafruit_kb2040.json @@ -42,11 +42,13 @@ "wait_for_upload_port": false, "protocol": "picotool", "protocols": [ + "blackmagic", "cmsis-dap", "jlink", "raspberrypi-swd", "picotool", - "picoprobe" + "picoprobe", + "pico-debug" ] }, "url": "https://www.raspberrypi.org/products/raspberry-pi-pico/", diff --git a/tools/json/adafruit_macropad2040.json b/tools/json/adafruit_macropad2040.json index fd21d5af5..b76e3c3e1 100644 --- a/tools/json/adafruit_macropad2040.json +++ b/tools/json/adafruit_macropad2040.json @@ -42,11 +42,13 @@ "wait_for_upload_port": false, "protocol": "picotool", "protocols": [ + "blackmagic", "cmsis-dap", "jlink", "raspberrypi-swd", "picotool", - "picoprobe" + "picoprobe", + "pico-debug" ] }, "url": "https://www.raspberrypi.org/products/raspberry-pi-pico/", diff --git a/tools/json/adafruit_qtpy.json b/tools/json/adafruit_qtpy.json index 74bf84f14..d8997c8dc 100644 --- a/tools/json/adafruit_qtpy.json +++ b/tools/json/adafruit_qtpy.json @@ -42,11 +42,13 @@ "wait_for_upload_port": false, "protocol": "picotool", "protocols": [ + "blackmagic", "cmsis-dap", "jlink", "raspberrypi-swd", "picotool", - "picoprobe" + "picoprobe", + "pico-debug" ] }, "url": "https://www.raspberrypi.org/products/raspberry-pi-pico/", diff --git a/tools/json/adafruit_stemmafriend.json b/tools/json/adafruit_stemmafriend.json index 5d3b43229..26fc96c0f 100644 --- a/tools/json/adafruit_stemmafriend.json +++ b/tools/json/adafruit_stemmafriend.json @@ -42,11 +42,13 @@ "wait_for_upload_port": false, "protocol": "picotool", "protocols": [ + "blackmagic", "cmsis-dap", "jlink", "raspberrypi-swd", "picotool", - "picoprobe" + "picoprobe", + "pico-debug" ] }, "url": "https://www.raspberrypi.org/products/raspberry-pi-pico/", diff --git a/tools/json/adafruit_trinkeyrp2040qt.json b/tools/json/adafruit_trinkeyrp2040qt.json index 3765368d5..f2e14746b 100644 --- a/tools/json/adafruit_trinkeyrp2040qt.json +++ b/tools/json/adafruit_trinkeyrp2040qt.json @@ -42,11 +42,13 @@ "wait_for_upload_port": false, "protocol": "picotool", "protocols": [ + "blackmagic", "cmsis-dap", "jlink", "raspberrypi-swd", "picotool", - "picoprobe" + "picoprobe", + "pico-debug" ] }, "url": "https://www.raspberrypi.org/products/raspberry-pi-pico/", diff --git a/tools/json/arduino_nano_connect.json b/tools/json/arduino_nano_connect.json index 340bf0f17..ba183fd86 100644 --- a/tools/json/arduino_nano_connect.json +++ b/tools/json/arduino_nano_connect.json @@ -4,7 +4,7 @@ "earlephilhower": { "boot2_source": "boot2_w25q080_2_padded_checksum.S", "usb_vid": "0x2341", - "usb_pid": "0x0058" + "usb_pid": "0x005E" } }, "core": "earlephilhower", @@ -18,7 +18,7 @@ ], [ "0x2341", - "0x0058" + "0x005E" ] ], "mcu": "rp2040", @@ -42,11 +42,13 @@ "wait_for_upload_port": false, "protocol": "picotool", "protocols": [ + "blackmagic", "cmsis-dap", "jlink", "raspberrypi-swd", "picotool", - "picoprobe" + "picoprobe", + "pico-debug" ] }, "url": "https://www.raspberrypi.org/products/raspberry-pi-pico/", diff --git a/tools/json/bridgetek_idm2040-7a.json b/tools/json/bridgetek_idm2040-7a.json new file mode 100644 index 000000000..9b73b67e6 --- /dev/null +++ b/tools/json/bridgetek_idm2040-7a.json @@ -0,0 +1,56 @@ +{ + "build": { + "arduino": { + "earlephilhower": { + "boot2_source": "boot2_w25q080_2_padded_checksum.S", + "usb_vid": "0x2E8A", + "usb_pid": "0x1041" + } + }, + "core": "earlephilhower", + "cpu": "cortex-m0plus", + "extra_flags": "-D ARDUINO_BRIDGETEK_IDM2040-7A -DARDUINO_ARCH_RP2040 -DUSBD_MAX_POWER_MA=250 -DFT8XX_TYPE=BT817 -DDISPLAY_RES=WVGA -DPLATFORM_RP2040", + "f_cpu": "133000000L", + "hwids": [ + [ + "0x2E8A", + "0x00C0" + ], + [ + "0x2E8A", + "0x1041" + ] + ], + "mcu": "rp2040", + "variant": "bridgetek_idm2040-7a" + }, + "debug": { + "jlink_device": "RP2040_M0_0", + "openocd_target": "rp2040.cfg", + "svd_path": "rp2040.svd" + }, + "frameworks": [ + "arduino" + ], + "name": "IDM2040-7A", + "upload": { + "maximum_ram_size": 270336, + "maximum_size": 8388608, + "require_upload_port": true, + "native_usb": true, + "use_1200bps_touch": true, + "wait_for_upload_port": false, + "protocol": "picotool", + "protocols": [ + "blackmagic", + "cmsis-dap", + "jlink", + "raspberrypi-swd", + "picotool", + "picoprobe", + "pico-debug" + ] + }, + "url": "https://www.raspberrypi.org/products/raspberry-pi-pico/", + "vendor": "BridgeTek" +} diff --git a/tools/json/challenger_2040_lora.json b/tools/json/challenger_2040_lora.json index 4636c1d5f..7a03d907b 100644 --- a/tools/json/challenger_2040_lora.json +++ b/tools/json/challenger_2040_lora.json @@ -42,11 +42,13 @@ "wait_for_upload_port": false, "protocol": "picotool", "protocols": [ + "blackmagic", "cmsis-dap", "jlink", "raspberrypi-swd", "picotool", - "picoprobe" + "picoprobe", + "pico-debug" ] }, "url": "https://www.raspberrypi.org/products/raspberry-pi-pico/", diff --git a/tools/json/challenger_2040_lte.json b/tools/json/challenger_2040_lte.json index e2ce6a403..e9d1cce4f 100644 --- a/tools/json/challenger_2040_lte.json +++ b/tools/json/challenger_2040_lte.json @@ -42,11 +42,13 @@ "wait_for_upload_port": false, "protocol": "picotool", "protocols": [ + "blackmagic", "cmsis-dap", "jlink", "raspberrypi-swd", "picotool", - "picoprobe" + "picoprobe", + "pico-debug" ] }, "url": "https://www.raspberrypi.org/products/raspberry-pi-pico/", diff --git a/tools/json/challenger_2040_nfc.json b/tools/json/challenger_2040_nfc.json new file mode 100644 index 000000000..30887c124 --- /dev/null +++ b/tools/json/challenger_2040_nfc.json @@ -0,0 +1,56 @@ +{ + "build": { + "arduino": { + "earlephilhower": { + "boot2_source": "boot2_w25q080_2_padded_checksum.S", + "usb_vid": "0x2E8A", + "usb_pid": "0x1036" + } + }, + "core": "earlephilhower", + "cpu": "cortex-m0plus", + "extra_flags": "-D ARDUINO_CHALLENGER_2040_NFC_RP2040 -DARDUINO_ARCH_RP2040 -DUSBD_MAX_POWER_MA=250", + "f_cpu": "133000000L", + "hwids": [ + [ + "0x2E8A", + "0x00C0" + ], + [ + "0x2E8A", + "0x1036" + ] + ], + "mcu": "rp2040", + "variant": "challenger_2040_nfc" + }, + "debug": { + "jlink_device": "RP2040_M0_0", + "openocd_target": "rp2040.cfg", + "svd_path": "rp2040.svd" + }, + "frameworks": [ + "arduino" + ], + "name": "Challenger 2040 NFC", + "upload": { + "maximum_ram_size": 270336, + "maximum_size": 8388608, + "require_upload_port": true, + "native_usb": true, + "use_1200bps_touch": true, + "wait_for_upload_port": false, + "protocol": "picotool", + "protocols": [ + "blackmagic", + "cmsis-dap", + "jlink", + "raspberrypi-swd", + "picotool", + "picoprobe", + "pico-debug" + ] + }, + "url": "https://www.raspberrypi.org/products/raspberry-pi-pico/", + "vendor": "iLabs" +} diff --git a/tools/json/challenger_2040_sdrtc.json b/tools/json/challenger_2040_sdrtc.json index 6c9cb975c..56a2bcdbb 100644 --- a/tools/json/challenger_2040_sdrtc.json +++ b/tools/json/challenger_2040_sdrtc.json @@ -9,7 +9,7 @@ }, "core": "earlephilhower", "cpu": "cortex-m0plus", - "extra_flags": "-D ARDUINO_CHALLENGER_NB_2040_SDRTC_RP2040 -DARDUINO_ARCH_RP2040 -DUSBD_MAX_POWER_MA=250", + "extra_flags": "-D ARDUINO_CHALLENGER_2040_SDRTC_RP2040 -DARDUINO_ARCH_RP2040 -DUSBD_MAX_POWER_MA=250", "f_cpu": "133000000L", "hwids": [ [ @@ -42,11 +42,13 @@ "wait_for_upload_port": false, "protocol": "picotool", "protocols": [ + "blackmagic", "cmsis-dap", "jlink", "raspberrypi-swd", "picotool", - "picoprobe" + "picoprobe", + "pico-debug" ] }, "url": "https://www.raspberrypi.org/products/raspberry-pi-pico/", diff --git a/tools/json/challenger_2040_subghz.json b/tools/json/challenger_2040_subghz.json index 43d8e8b90..2af31881a 100644 --- a/tools/json/challenger_2040_subghz.json +++ b/tools/json/challenger_2040_subghz.json @@ -42,11 +42,13 @@ "wait_for_upload_port": false, "protocol": "picotool", "protocols": [ + "blackmagic", "cmsis-dap", "jlink", "raspberrypi-swd", "picotool", - "picoprobe" + "picoprobe", + "pico-debug" ] }, "url": "https://www.raspberrypi.org/products/raspberry-pi-pico/", diff --git a/tools/json/challenger_2040_uwb.json b/tools/json/challenger_2040_uwb.json new file mode 100644 index 000000000..ff3713d50 --- /dev/null +++ b/tools/json/challenger_2040_uwb.json @@ -0,0 +1,56 @@ +{ + "build": { + "arduino": { + "earlephilhower": { + "boot2_source": "boot2_w25q080_2_padded_checksum.S", + "usb_vid": "0x2E8A", + "usb_pid": "0x1052" + } + }, + "core": "earlephilhower", + "cpu": "cortex-m0plus", + "extra_flags": "-D ARDUINO_CHALLENGER_2040_UWB_RP2040 -DARDUINO_ARCH_RP2040 -DUSBD_MAX_POWER_MA=500", + "f_cpu": "133000000L", + "hwids": [ + [ + "0x2E8A", + "0x00C0" + ], + [ + "0x2E8A", + "0x1052" + ] + ], + "mcu": "rp2040", + "variant": "challenger_2040_uwb" + }, + "debug": { + "jlink_device": "RP2040_M0_0", + "openocd_target": "rp2040.cfg", + "svd_path": "rp2040.svd" + }, + "frameworks": [ + "arduino" + ], + "name": "Challenger 2040 UWB", + "upload": { + "maximum_ram_size": 270336, + "maximum_size": 8388608, + "require_upload_port": true, + "native_usb": true, + "use_1200bps_touch": true, + "wait_for_upload_port": false, + "protocol": "picotool", + "protocols": [ + "blackmagic", + "cmsis-dap", + "jlink", + "raspberrypi-swd", + "picotool", + "picoprobe", + "pico-debug" + ] + }, + "url": "https://www.raspberrypi.org/products/raspberry-pi-pico/", + "vendor": "iLabs" +} diff --git a/tools/json/challenger_2040_wifi.json b/tools/json/challenger_2040_wifi.json index 6b2bcff99..410fa474b 100644 --- a/tools/json/challenger_2040_wifi.json +++ b/tools/json/challenger_2040_wifi.json @@ -42,11 +42,13 @@ "wait_for_upload_port": false, "protocol": "picotool", "protocols": [ + "blackmagic", "cmsis-dap", "jlink", "raspberrypi-swd", "picotool", - "picoprobe" + "picoprobe", + "pico-debug" ] }, "url": "https://www.raspberrypi.org/products/raspberry-pi-pico/", diff --git a/tools/json/challenger_2040_wifi_ble.json b/tools/json/challenger_2040_wifi_ble.json index 5d4b8296f..79e86efca 100644 --- a/tools/json/challenger_2040_wifi_ble.json +++ b/tools/json/challenger_2040_wifi_ble.json @@ -42,11 +42,13 @@ "wait_for_upload_port": false, "protocol": "picotool", "protocols": [ + "blackmagic", "cmsis-dap", "jlink", "raspberrypi-swd", "picotool", - "picoprobe" + "picoprobe", + "pico-debug" ] }, "url": "https://www.raspberrypi.org/products/raspberry-pi-pico/", diff --git a/tools/json/challenger_nb_2040_wifi.json b/tools/json/challenger_nb_2040_wifi.json index 3d34647a5..d1cf53c0a 100644 --- a/tools/json/challenger_nb_2040_wifi.json +++ b/tools/json/challenger_nb_2040_wifi.json @@ -42,11 +42,13 @@ "wait_for_upload_port": false, "protocol": "picotool", "protocols": [ + "blackmagic", "cmsis-dap", "jlink", "raspberrypi-swd", "picotool", - "picoprobe" + "picoprobe", + "pico-debug" ] }, "url": "https://www.raspberrypi.org/products/raspberry-pi-pico/", diff --git a/tools/json/cytron_maker_nano_rp2040.json b/tools/json/cytron_maker_nano_rp2040.json index 2ec7fdfba..16fc2a603 100644 --- a/tools/json/cytron_maker_nano_rp2040.json +++ b/tools/json/cytron_maker_nano_rp2040.json @@ -42,11 +42,13 @@ "wait_for_upload_port": false, "protocol": "picotool", "protocols": [ + "blackmagic", "cmsis-dap", "jlink", "raspberrypi-swd", "picotool", - "picoprobe" + "picoprobe", + "pico-debug" ] }, "url": "https://www.raspberrypi.org/products/raspberry-pi-pico/", diff --git a/tools/json/cytron_maker_pi_rp2040.json b/tools/json/cytron_maker_pi_rp2040.json index ccc793d3c..7ed3a04d8 100644 --- a/tools/json/cytron_maker_pi_rp2040.json +++ b/tools/json/cytron_maker_pi_rp2040.json @@ -42,11 +42,13 @@ "wait_for_upload_port": false, "protocol": "picotool", "protocols": [ + "blackmagic", "cmsis-dap", "jlink", "raspberrypi-swd", "picotool", - "picoprobe" + "picoprobe", + "pico-debug" ] }, "url": "https://www.raspberrypi.org/products/raspberry-pi-pico/", diff --git a/tools/json/datanoisetv_picoadk.json b/tools/json/datanoisetv_picoadk.json new file mode 100644 index 000000000..b9cb8e4f4 --- /dev/null +++ b/tools/json/datanoisetv_picoadk.json @@ -0,0 +1,56 @@ +{ + "build": { + "arduino": { + "earlephilhower": { + "boot2_source": "boot2_w25q080_2_padded_checksum.S", + "usb_vid": "0x2E8A", + "usb_pid": "0x000A" + } + }, + "core": "earlephilhower", + "cpu": "cortex-m0plus", + "extra_flags": "-D ARDUINO_DATANOISETV_PICOADK -DARDUINO_ARCH_RP2040 -DUSBD_MAX_POWER_MA=250", + "f_cpu": "133000000L", + "hwids": [ + [ + "0x2E8A", + "0x00C0" + ], + [ + "0x2E8A", + "0x000A" + ] + ], + "mcu": "rp2040", + "variant": "datanoisetv_picoadk" + }, + "debug": { + "jlink_device": "RP2040_M0_0", + "openocd_target": "rp2040.cfg", + "svd_path": "rp2040.svd" + }, + "frameworks": [ + "arduino" + ], + "name": "PicoADK", + "upload": { + "maximum_ram_size": 270336, + "maximum_size": 2097152, + "require_upload_port": true, + "native_usb": true, + "use_1200bps_touch": true, + "wait_for_upload_port": false, + "protocol": "picotool", + "protocols": [ + "blackmagic", + "cmsis-dap", + "jlink", + "raspberrypi-swd", + "picotool", + "picoprobe", + "pico-debug" + ] + }, + "url": "https://www.raspberrypi.org/products/raspberry-pi-pico/", + "vendor": "DatanoiseTV" +} diff --git a/tools/json/dfrobot_beetle_rp2040.json b/tools/json/dfrobot_beetle_rp2040.json index 44bcd65fc..dade44e6d 100644 --- a/tools/json/dfrobot_beetle_rp2040.json +++ b/tools/json/dfrobot_beetle_rp2040.json @@ -42,11 +42,13 @@ "wait_for_upload_port": false, "protocol": "picotool", "protocols": [ + "blackmagic", "cmsis-dap", "jlink", "raspberrypi-swd", "picotool", - "picoprobe" + "picoprobe", + "pico-debug" ] }, "url": "https://www.raspberrypi.org/products/raspberry-pi-pico/", diff --git a/tools/json/electroniccats_bombercat.json b/tools/json/electroniccats_huntercat_nfc.json similarity index 75% rename from tools/json/electroniccats_bombercat.json rename to tools/json/electroniccats_huntercat_nfc.json index a8cbd1206..a72035b6f 100644 --- a/tools/json/electroniccats_bombercat.json +++ b/tools/json/electroniccats_huntercat_nfc.json @@ -3,13 +3,13 @@ "arduino": { "earlephilhower": { "boot2_source": "boot2_w25q080_2_padded_checksum.S", - "usb_vid": "0x1209", - "usb_pid": "0x1209" + "usb_vid": "0x2E8A", + "usb_pid": "0x1037" } }, "core": "earlephilhower", "cpu": "cortex-m0plus", - "extra_flags": "-D ARDUINO_ELECTRONICCATS_BOMBERCAT -DARDUINO_ARCH_RP2040 -DUSBD_MAX_POWER_MA=500", + "extra_flags": "-D ARDUINO_ELECTRONICCATS_HUNTERCAT_NFC -DARDUINO_ARCH_RP2040 -DUSBD_MAX_POWER_MA=500", "f_cpu": "133000000L", "hwids": [ [ @@ -17,12 +17,12 @@ "0x00C0" ], [ - "0x1209", - "0x1209" + "0x2E8A", + "0x1037" ] ], "mcu": "rp2040", - "variant": "electroniccats_bombercat" + "variant": "electroniccats_huntercat_nfc" }, "debug": { "jlink_device": "RP2040_M0_0", @@ -42,11 +42,13 @@ "wait_for_upload_port": false, "protocol": "picotool", "protocols": [ + "blackmagic", "cmsis-dap", "jlink", "raspberrypi-swd", "picotool", - "picoprobe" + "picoprobe", + "pico-debug" ] }, "url": "https://www.raspberrypi.org/products/raspberry-pi-pico/", diff --git a/tools/json/extelec_rc2040.json b/tools/json/extelec_rc2040.json new file mode 100644 index 000000000..07f2a6a24 --- /dev/null +++ b/tools/json/extelec_rc2040.json @@ -0,0 +1,56 @@ +{ + "build": { + "arduino": { + "earlephilhower": { + "boot2_source": "boot2_w25q080_2_padded_checksum.S", + "usb_vid": "0x2E8A", + "usb_pid": "0xEE20" + } + }, + "core": "earlephilhower", + "cpu": "cortex-m0plus", + "extra_flags": "-D ARDUINO_EXTREMEELEXTRONICS_RC2040 -DARDUINO_ARCH_RP2040 -DUSBD_MAX_POWER_MA=250", + "f_cpu": "133000000L", + "hwids": [ + [ + "0x2E8A", + "0x00C0" + ], + [ + "0x2E8A", + "0xEE20" + ] + ], + "mcu": "rp2040", + "variant": "extelec_rc2040" + }, + "debug": { + "jlink_device": "RP2040_M0_0", + "openocd_target": "rp2040.cfg", + "svd_path": "rp2040.svd" + }, + "frameworks": [ + "arduino" + ], + "name": "RC2040", + "upload": { + "maximum_ram_size": 270336, + "maximum_size": 2097152, + "require_upload_port": true, + "native_usb": true, + "use_1200bps_touch": true, + "wait_for_upload_port": false, + "protocol": "picotool", + "protocols": [ + "blackmagic", + "cmsis-dap", + "jlink", + "raspberrypi-swd", + "picotool", + "picoprobe", + "pico-debug" + ] + }, + "url": "https://www.raspberrypi.org/products/raspberry-pi-pico/", + "vendor": "ExtremeElectronics" +} diff --git a/tools/json/flyboard2040_core.json b/tools/json/flyboard2040_core.json index fab7a0b86..af8efd87d 100644 --- a/tools/json/flyboard2040_core.json +++ b/tools/json/flyboard2040_core.json @@ -2,7 +2,7 @@ "build": { "arduino": { "earlephilhower": { - "boot2_source": "boot2_generic_03h_4_padded_checksum.S", + "boot2_source": "boot2_w25q080_2_padded_checksum.S", "usb_vid": "0x2E8A", "usb_pid": "0x008A" } @@ -42,11 +42,13 @@ "wait_for_upload_port": false, "protocol": "picotool", "protocols": [ + "blackmagic", "cmsis-dap", "jlink", "raspberrypi-swd", "picotool", - "picoprobe" + "picoprobe", + "pico-debug" ] }, "url": "https://www.raspberrypi.org/products/raspberry-pi-pico/", diff --git a/tools/json/generic.json b/tools/json/generic.json index 3c956418d..95633e3c6 100644 --- a/tools/json/generic.json +++ b/tools/json/generic.json @@ -42,11 +42,13 @@ "wait_for_upload_port": false, "protocol": "picotool", "protocols": [ + "blackmagic", "cmsis-dap", "jlink", "raspberrypi-swd", "picotool", - "picoprobe" + "picoprobe", + "pico-debug" ] }, "url": "https://www.raspberrypi.org/products/raspberry-pi-pico/", diff --git a/tools/json/ilabs_rpico32.json b/tools/json/ilabs_rpico32.json index 97bffc0f5..fd57fad3e 100644 --- a/tools/json/ilabs_rpico32.json +++ b/tools/json/ilabs_rpico32.json @@ -42,11 +42,13 @@ "wait_for_upload_port": false, "protocol": "picotool", "protocols": [ + "blackmagic", "cmsis-dap", "jlink", "raspberrypi-swd", "picotool", - "picoprobe" + "picoprobe", + "pico-debug" ] }, "url": "https://www.raspberrypi.org/products/raspberry-pi-pico/", diff --git a/tools/json/melopero_cookie_rp2040.json b/tools/json/melopero_cookie_rp2040.json new file mode 100644 index 000000000..300b27aa1 --- /dev/null +++ b/tools/json/melopero_cookie_rp2040.json @@ -0,0 +1,56 @@ +{ + "build": { + "arduino": { + "earlephilhower": { + "boot2_source": "boot2_w25q080_2_padded_checksum.S", + "usb_vid": "0x2E8A", + "usb_pid": "0x1011" + } + }, + "core": "earlephilhower", + "cpu": "cortex-m0plus", + "extra_flags": "-D ARDUINO_MELOPERO_COOKIE_RP2040 -DARDUINO_ARCH_RP2040 -DUSBD_MAX_POWER_MA=250", + "f_cpu": "133000000L", + "hwids": [ + [ + "0x2E8A", + "0x00C0" + ], + [ + "0x2E8A", + "0x1011" + ] + ], + "mcu": "rp2040", + "variant": "melopero_cookie_rp2040" + }, + "debug": { + "jlink_device": "RP2040_M0_0", + "openocd_target": "rp2040.cfg", + "svd_path": "rp2040.svd" + }, + "frameworks": [ + "arduino" + ], + "name": "Cookie RP2040", + "upload": { + "maximum_ram_size": 270336, + "maximum_size": 8388608, + "require_upload_port": true, + "native_usb": true, + "use_1200bps_touch": true, + "wait_for_upload_port": false, + "protocol": "picotool", + "protocols": [ + "blackmagic", + "cmsis-dap", + "jlink", + "raspberrypi-swd", + "picotool", + "picoprobe", + "pico-debug" + ] + }, + "url": "https://www.raspberrypi.org/products/raspberry-pi-pico/", + "vendor": "Melopero" +} diff --git a/tools/json/melopero_shake_rp2040.json b/tools/json/melopero_shake_rp2040.json index c36111b29..afea254ff 100644 --- a/tools/json/melopero_shake_rp2040.json +++ b/tools/json/melopero_shake_rp2040.json @@ -42,11 +42,13 @@ "wait_for_upload_port": false, "protocol": "picotool", "protocols": [ + "blackmagic", "cmsis-dap", "jlink", "raspberrypi-swd", "picotool", - "picoprobe" + "picoprobe", + "pico-debug" ] }, "url": "https://www.raspberrypi.org/products/raspberry-pi-pico/", diff --git a/tools/json/nekosystems_bl2040_mini.json b/tools/json/nekosystems_bl2040_mini.json new file mode 100644 index 000000000..5fdd1c914 --- /dev/null +++ b/tools/json/nekosystems_bl2040_mini.json @@ -0,0 +1,56 @@ +{ + "build": { + "arduino": { + "earlephilhower": { + "boot2_source": "boot2_generic_03h_2_padded_checksum.S", + "usb_vid": "0x2E8A", + "usb_pid": "0x000A" + } + }, + "core": "earlephilhower", + "cpu": "cortex-m0plus", + "extra_flags": "-D ARDUINO_NEKOSYSTEMS_BL2040_MINI -DARDUINO_ARCH_RP2040 -DUSBD_MAX_POWER_MA=500", + "f_cpu": "133000000L", + "hwids": [ + [ + "0x2E8A", + "0x00C0" + ], + [ + "0x2E8A", + "0x000A" + ] + ], + "mcu": "rp2040", + "variant": "nekosystems_bl2040_mini" + }, + "debug": { + "jlink_device": "RP2040_M0_0", + "openocd_target": "rp2040.cfg", + "svd_path": "rp2040.svd" + }, + "frameworks": [ + "arduino" + ], + "name": "BL2040 Mini", + "upload": { + "maximum_ram_size": 270336, + "maximum_size": 4194304, + "require_upload_port": true, + "native_usb": true, + "use_1200bps_touch": true, + "wait_for_upload_port": false, + "protocol": "picotool", + "protocols": [ + "blackmagic", + "cmsis-dap", + "jlink", + "raspberrypi-swd", + "picotool", + "picoprobe", + "pico-debug" + ] + }, + "url": "https://www.raspberrypi.org/products/raspberry-pi-pico/", + "vendor": "Neko Systems" +} diff --git a/tools/json/nullbits_bit_c_pro.json b/tools/json/nullbits_bit_c_pro.json new file mode 100644 index 000000000..f63470a33 --- /dev/null +++ b/tools/json/nullbits_bit_c_pro.json @@ -0,0 +1,56 @@ +{ + "build": { + "arduino": { + "earlephilhower": { + "boot2_source": "boot2_w25x10cl_4_padded_checksum.S", + "usb_vid": "0x2E8A", + "usb_pid": "0x6E61" + } + }, + "core": "earlephilhower", + "cpu": "cortex-m0plus", + "extra_flags": "-D ARDUINO_NULLBITS_BIT_C_PRO -DARDUINO_ARCH_RP2040 -DUSBD_MAX_POWER_MA=500", + "f_cpu": "133000000L", + "hwids": [ + [ + "0x2E8A", + "0x00C0" + ], + [ + "0x2E8A", + "0x6E61" + ] + ], + "mcu": "rp2040", + "variant": "nullbits_bit_c_pro" + }, + "debug": { + "jlink_device": "RP2040_M0_0", + "openocd_target": "rp2040.cfg", + "svd_path": "rp2040.svd" + }, + "frameworks": [ + "arduino" + ], + "name": "Bit-C PRO", + "upload": { + "maximum_ram_size": 270336, + "maximum_size": 4194304, + "require_upload_port": true, + "native_usb": true, + "use_1200bps_touch": true, + "wait_for_upload_port": false, + "protocol": "picotool", + "protocols": [ + "blackmagic", + "cmsis-dap", + "jlink", + "raspberrypi-swd", + "picotool", + "picoprobe", + "pico-debug" + ] + }, + "url": "https://www.raspberrypi.org/products/raspberry-pi-pico/", + "vendor": "nullbits" +} diff --git a/tools/json/pimoroni_pga2040.json b/tools/json/pimoroni_pga2040.json new file mode 100644 index 000000000..76a007eb6 --- /dev/null +++ b/tools/json/pimoroni_pga2040.json @@ -0,0 +1,56 @@ +{ + "build": { + "arduino": { + "earlephilhower": { + "boot2_source": "boot2_w25q64jv_4_padded_checksum.S", + "usb_vid": "0x2E8A", + "usb_pid": "0x1008" + } + }, + "core": "earlephilhower", + "cpu": "cortex-m0plus", + "extra_flags": "-D ARDUINO_PIMORONI_PGA2040 -DARDUINO_ARCH_RP2040 -DUSBD_MAX_POWER_MA=250", + "f_cpu": "133000000L", + "hwids": [ + [ + "0x2E8A", + "0x00C0" + ], + [ + "0x2E8A", + "0x1008" + ] + ], + "mcu": "rp2040", + "variant": "pimoroni_pga2040" + }, + "debug": { + "jlink_device": "RP2040_M0_0", + "openocd_target": "rp2040.cfg", + "svd_path": "rp2040.svd" + }, + "frameworks": [ + "arduino" + ], + "name": "PGA2040", + "upload": { + "maximum_ram_size": 270336, + "maximum_size": 8388608, + "require_upload_port": true, + "native_usb": true, + "use_1200bps_touch": true, + "wait_for_upload_port": false, + "protocol": "picotool", + "protocols": [ + "blackmagic", + "cmsis-dap", + "jlink", + "raspberrypi-swd", + "picotool", + "picoprobe", + "pico-debug" + ] + }, + "url": "https://www.raspberrypi.org/products/raspberry-pi-pico/", + "vendor": "Pimoroni" +} diff --git a/tools/json/rpipico.json b/tools/json/rpipico.json index 72d6beb10..77a9f7f67 100644 --- a/tools/json/rpipico.json +++ b/tools/json/rpipico.json @@ -42,11 +42,13 @@ "wait_for_upload_port": false, "protocol": "picotool", "protocols": [ + "blackmagic", "cmsis-dap", "jlink", "raspberrypi-swd", "picotool", - "picoprobe" + "picoprobe", + "pico-debug" ] }, "url": "https://www.raspberrypi.org/products/raspberry-pi-pico/", diff --git a/tools/json/rpipicow.json b/tools/json/rpipicow.json index 33b4cc887..b7fc47f1f 100644 --- a/tools/json/rpipicow.json +++ b/tools/json/rpipicow.json @@ -42,11 +42,13 @@ "wait_for_upload_port": false, "protocol": "picotool", "protocols": [ + "blackmagic", "cmsis-dap", "jlink", "raspberrypi-swd", "picotool", - "picoprobe" + "picoprobe", + "pico-debug" ] }, "url": "https://www.raspberrypi.org/products/raspberry-pi-pico/", diff --git a/tools/json/seeed_indicator_rp2040.json b/tools/json/seeed_indicator_rp2040.json new file mode 100644 index 000000000..a18a32817 --- /dev/null +++ b/tools/json/seeed_indicator_rp2040.json @@ -0,0 +1,56 @@ +{ + "build": { + "arduino": { + "earlephilhower": { + "boot2_source": "boot2_w25q080_2_padded_checksum.S", + "usb_vid": "0x2886", + "usb_pid": "0x0050" + } + }, + "core": "earlephilhower", + "cpu": "cortex-m0plus", + "extra_flags": "-D ARDUINO_SEEED_INDICATOR_RP2040 -DARDUINO_ARCH_RP2040 -DUSBD_MAX_POWER_MA=250", + "f_cpu": "133000000L", + "hwids": [ + [ + "0x2E8A", + "0x00C0" + ], + [ + "0x2886", + "0x0050" + ] + ], + "mcu": "rp2040", + "variant": "seeed_indicator_rp2040" + }, + "debug": { + "jlink_device": "RP2040_M0_0", + "openocd_target": "rp2040.cfg", + "svd_path": "rp2040.svd" + }, + "frameworks": [ + "arduino" + ], + "name": "INDICATOR RP2040", + "upload": { + "maximum_ram_size": 270336, + "maximum_size": 2097152, + "require_upload_port": true, + "native_usb": true, + "use_1200bps_touch": true, + "wait_for_upload_port": false, + "protocol": "picotool", + "protocols": [ + "blackmagic", + "cmsis-dap", + "jlink", + "raspberrypi-swd", + "picotool", + "picoprobe", + "pico-debug" + ] + }, + "url": "https://www.raspberrypi.org/products/raspberry-pi-pico/", + "vendor": "Seeed" +} diff --git a/tools/json/seeed_xiao_rp2040.json b/tools/json/seeed_xiao_rp2040.json index 53935d484..1d3fb10ec 100644 --- a/tools/json/seeed_xiao_rp2040.json +++ b/tools/json/seeed_xiao_rp2040.json @@ -42,11 +42,13 @@ "wait_for_upload_port": false, "protocol": "picotool", "protocols": [ + "blackmagic", "cmsis-dap", "jlink", "raspberrypi-swd", "picotool", - "picoprobe" + "picoprobe", + "pico-debug" ] }, "url": "https://www.raspberrypi.org/products/raspberry-pi-pico/", diff --git a/tools/json/solderparty_rp2040_stamp.json b/tools/json/solderparty_rp2040_stamp.json index a45944982..6d96253ff 100644 --- a/tools/json/solderparty_rp2040_stamp.json +++ b/tools/json/solderparty_rp2040_stamp.json @@ -42,11 +42,13 @@ "wait_for_upload_port": false, "protocol": "picotool", "protocols": [ + "blackmagic", "cmsis-dap", "jlink", "raspberrypi-swd", "picotool", - "picoprobe" + "picoprobe", + "pico-debug" ] }, "url": "https://www.raspberrypi.org/products/raspberry-pi-pico/", diff --git a/tools/json/sparkfun_promicrorp2040.json b/tools/json/sparkfun_promicrorp2040.json index 2052a8b47..ddaca3f55 100644 --- a/tools/json/sparkfun_promicrorp2040.json +++ b/tools/json/sparkfun_promicrorp2040.json @@ -42,11 +42,13 @@ "wait_for_upload_port": false, "protocol": "picotool", "protocols": [ + "blackmagic", "cmsis-dap", "jlink", "raspberrypi-swd", "picotool", - "picoprobe" + "picoprobe", + "pico-debug" ] }, "url": "https://www.raspberrypi.org/products/raspberry-pi-pico/", diff --git a/tools/json/sparkfun_thingplusrp2040.json b/tools/json/sparkfun_thingplusrp2040.json index a14c9d655..c6863c2c6 100644 --- a/tools/json/sparkfun_thingplusrp2040.json +++ b/tools/json/sparkfun_thingplusrp2040.json @@ -42,11 +42,13 @@ "wait_for_upload_port": false, "protocol": "picotool", "protocols": [ + "blackmagic", "cmsis-dap", "jlink", "raspberrypi-swd", "picotool", - "picoprobe" + "picoprobe", + "pico-debug" ] }, "url": "https://www.raspberrypi.org/products/raspberry-pi-pico/", diff --git a/tools/json/upesy_rp2040_devkit.json b/tools/json/upesy_rp2040_devkit.json index de0d5cef7..713216a55 100644 --- a/tools/json/upesy_rp2040_devkit.json +++ b/tools/json/upesy_rp2040_devkit.json @@ -42,11 +42,13 @@ "wait_for_upload_port": false, "protocol": "picotool", "protocols": [ + "blackmagic", "cmsis-dap", "jlink", "raspberrypi-swd", "picotool", - "picoprobe" + "picoprobe", + "pico-debug" ] }, "url": "https://www.raspberrypi.org/products/raspberry-pi-pico/", diff --git a/tools/json/vccgnd_yd_rp2040.json b/tools/json/vccgnd_yd_rp2040.json new file mode 100644 index 000000000..5bb7f15e4 --- /dev/null +++ b/tools/json/vccgnd_yd_rp2040.json @@ -0,0 +1,56 @@ +{ + "build": { + "arduino": { + "earlephilhower": { + "boot2_source": "boot2_generic_03h_4_padded_checksum.S", + "usb_vid": "0x2E8A", + "usb_pid": "0x800A" + } + }, + "core": "earlephilhower", + "cpu": "cortex-m0plus", + "extra_flags": "-D ARDUINO_YD_RP2040 -DARDUINO_ARCH_RP2040 -DUSBD_MAX_POWER_MA=500", + "f_cpu": "133000000L", + "hwids": [ + [ + "0x2E8A", + "0x00C0" + ], + [ + "0x2E8A", + "0x800A" + ] + ], + "mcu": "rp2040", + "variant": "vccgnd_yd_rp2040" + }, + "debug": { + "jlink_device": "RP2040_M0_0", + "openocd_target": "rp2040.cfg", + "svd_path": "rp2040.svd" + }, + "frameworks": [ + "arduino" + ], + "name": "YD RP2040", + "upload": { + "maximum_ram_size": 270336, + "maximum_size": 16777216, + "require_upload_port": true, + "native_usb": true, + "use_1200bps_touch": true, + "wait_for_upload_port": false, + "protocol": "picotool", + "protocols": [ + "blackmagic", + "cmsis-dap", + "jlink", + "raspberrypi-swd", + "picotool", + "picoprobe", + "pico-debug" + ] + }, + "url": "https://www.raspberrypi.org/products/raspberry-pi-pico/", + "vendor": "VCC-GND" +} diff --git a/tools/json/viyalab_mizu.json b/tools/json/viyalab_mizu.json new file mode 100644 index 000000000..aac79f30d --- /dev/null +++ b/tools/json/viyalab_mizu.json @@ -0,0 +1,56 @@ +{ + "build": { + "arduino": { + "earlephilhower": { + "boot2_source": "boot2_generic_03h_4_padded_checksum.S", + "usb_vid": "0x2E8A", + "usb_pid": "0x000A" + } + }, + "core": "earlephilhower", + "cpu": "cortex-m0plus", + "extra_flags": "-D ARDUINO_VIYALAB_MIZU_RP2040 -DARDUINO_ARCH_RP2040 -DUSBD_MAX_POWER_MA=250", + "f_cpu": "133000000L", + "hwids": [ + [ + "0x2E8A", + "0x00C0" + ], + [ + "0x2E8A", + "0x000A" + ] + ], + "mcu": "rp2040", + "variant": "viyalab_mizu" + }, + "debug": { + "jlink_device": "RP2040_M0_0", + "openocd_target": "rp2040.cfg", + "svd_path": "rp2040.svd" + }, + "frameworks": [ + "arduino" + ], + "name": "Mizu RP2040", + "upload": { + "maximum_ram_size": 270336, + "maximum_size": 8388608, + "require_upload_port": true, + "native_usb": true, + "use_1200bps_touch": true, + "wait_for_upload_port": false, + "protocol": "picotool", + "protocols": [ + "blackmagic", + "cmsis-dap", + "jlink", + "raspberrypi-swd", + "picotool", + "picoprobe", + "pico-debug" + ] + }, + "url": "https://www.raspberrypi.org/products/raspberry-pi-pico/", + "vendor": "Viyalab" +} diff --git a/tools/json/waveshare_rp2040_lcd_0_96.json b/tools/json/waveshare_rp2040_lcd_0_96.json new file mode 100644 index 000000000..1b1a1d8a3 --- /dev/null +++ b/tools/json/waveshare_rp2040_lcd_0_96.json @@ -0,0 +1,56 @@ +{ + "build": { + "arduino": { + "earlephilhower": { + "boot2_source": "boot2_w25q16jvxq_4_padded_checksum.S", + "usb_vid": "0x2E8A", + "usb_pid": "0x1021" + } + }, + "core": "earlephilhower", + "cpu": "cortex-m0plus", + "extra_flags": "-D ARDUINO_WAVESHARE_RP2040_LCD_0_96 -DARDUINO_ARCH_RP2040 -DUSBD_MAX_POWER_MA=500", + "f_cpu": "133000000L", + "hwids": [ + [ + "0x2E8A", + "0x00C0" + ], + [ + "0x2E8A", + "0x1021" + ] + ], + "mcu": "rp2040", + "variant": "waveshare_rp2040_lcd_0_96" + }, + "debug": { + "jlink_device": "RP2040_M0_0", + "openocd_target": "rp2040.cfg", + "svd_path": "rp2040.svd" + }, + "frameworks": [ + "arduino" + ], + "name": "RP2040 LCD 0.96", + "upload": { + "maximum_ram_size": 270336, + "maximum_size": 2097152, + "require_upload_port": true, + "native_usb": true, + "use_1200bps_touch": true, + "wait_for_upload_port": false, + "protocol": "picotool", + "protocols": [ + "blackmagic", + "cmsis-dap", + "jlink", + "raspberrypi-swd", + "picotool", + "picoprobe", + "pico-debug" + ] + }, + "url": "https://www.raspberrypi.org/products/raspberry-pi-pico/", + "vendor": "Waveshare" +} diff --git a/tools/json/waveshare_rp2040_lcd_1_28.json b/tools/json/waveshare_rp2040_lcd_1_28.json new file mode 100644 index 000000000..f49c67cdf --- /dev/null +++ b/tools/json/waveshare_rp2040_lcd_1_28.json @@ -0,0 +1,56 @@ +{ + "build": { + "arduino": { + "earlephilhower": { + "boot2_source": "boot2_w25q16jvxq_4_padded_checksum.S", + "usb_vid": "0x2E8A", + "usb_pid": "0x1039" + } + }, + "core": "earlephilhower", + "cpu": "cortex-m0plus", + "extra_flags": "-D ARDUINO_WAVESHARE_RP2040_LCD_1_28 -DARDUINO_ARCH_RP2040 -DUSBD_MAX_POWER_MA=500", + "f_cpu": "133000000L", + "hwids": [ + [ + "0x2E8A", + "0x00C0" + ], + [ + "0x2E8A", + "0x1039" + ] + ], + "mcu": "rp2040", + "variant": "waveshare_rp2040_lcd_1_28" + }, + "debug": { + "jlink_device": "RP2040_M0_0", + "openocd_target": "rp2040.cfg", + "svd_path": "rp2040.svd" + }, + "frameworks": [ + "arduino" + ], + "name": "RP2040 LCD 1.28", + "upload": { + "maximum_ram_size": 270336, + "maximum_size": 2097152, + "require_upload_port": true, + "native_usb": true, + "use_1200bps_touch": true, + "wait_for_upload_port": false, + "protocol": "picotool", + "protocols": [ + "blackmagic", + "cmsis-dap", + "jlink", + "raspberrypi-swd", + "picotool", + "picoprobe", + "pico-debug" + ] + }, + "url": "https://www.raspberrypi.org/products/raspberry-pi-pico/", + "vendor": "Waveshare" +} diff --git a/tools/json/waveshare_rp2040_one.json b/tools/json/waveshare_rp2040_one.json new file mode 100644 index 000000000..77e8b87f0 --- /dev/null +++ b/tools/json/waveshare_rp2040_one.json @@ -0,0 +1,56 @@ +{ + "build": { + "arduino": { + "earlephilhower": { + "boot2_source": "boot2_w25q16jvxq_4_padded_checksum.S", + "usb_vid": "0x2E8A", + "usb_pid": "0x103A" + } + }, + "core": "earlephilhower", + "cpu": "cortex-m0plus", + "extra_flags": "-D ARDUINO_WAVESHARE_RP2040_ONE -DARDUINO_ARCH_RP2040 -DUSBD_MAX_POWER_MA=500", + "f_cpu": "133000000L", + "hwids": [ + [ + "0x2E8A", + "0x00C0" + ], + [ + "0x2E8A", + "0x103A" + ] + ], + "mcu": "rp2040", + "variant": "waveshare_rp2040_one" + }, + "debug": { + "jlink_device": "RP2040_M0_0", + "openocd_target": "rp2040.cfg", + "svd_path": "rp2040.svd" + }, + "frameworks": [ + "arduino" + ], + "name": "RP2040 One", + "upload": { + "maximum_ram_size": 270336, + "maximum_size": 4194304, + "require_upload_port": true, + "native_usb": true, + "use_1200bps_touch": true, + "wait_for_upload_port": false, + "protocol": "picotool", + "protocols": [ + "blackmagic", + "cmsis-dap", + "jlink", + "raspberrypi-swd", + "picotool", + "picoprobe", + "pico-debug" + ] + }, + "url": "https://www.raspberrypi.org/products/raspberry-pi-pico/", + "vendor": "Waveshare" +} diff --git a/tools/json/waveshare_rp2040_plus_16mb.json b/tools/json/waveshare_rp2040_plus_16mb.json new file mode 100644 index 000000000..c041e0933 --- /dev/null +++ b/tools/json/waveshare_rp2040_plus_16mb.json @@ -0,0 +1,56 @@ +{ + "build": { + "arduino": { + "earlephilhower": { + "boot2_source": "boot2_w25q080_2_padded_checksum.S", + "usb_vid": "0x2E8A", + "usb_pid": "0x1020" + } + }, + "core": "earlephilhower", + "cpu": "cortex-m0plus", + "extra_flags": "-D ARDUINO_WAVESHARE_RP2040_PLUS -DARDUINO_ARCH_RP2040 -DUSBD_MAX_POWER_MA=500", + "f_cpu": "133000000L", + "hwids": [ + [ + "0x2E8A", + "0x00C0" + ], + [ + "0x2E8A", + "0x1020" + ] + ], + "mcu": "rp2040", + "variant": "waveshare_rp2040_plus_16mb" + }, + "debug": { + "jlink_device": "RP2040_M0_0", + "openocd_target": "rp2040.cfg", + "svd_path": "rp2040.svd" + }, + "frameworks": [ + "arduino" + ], + "name": "RP2040 Plus 16MB", + "upload": { + "maximum_ram_size": 270336, + "maximum_size": 16777216, + "require_upload_port": true, + "native_usb": true, + "use_1200bps_touch": true, + "wait_for_upload_port": false, + "protocol": "picotool", + "protocols": [ + "blackmagic", + "cmsis-dap", + "jlink", + "raspberrypi-swd", + "picotool", + "picoprobe", + "pico-debug" + ] + }, + "url": "https://www.raspberrypi.org/products/raspberry-pi-pico/", + "vendor": "Waveshare" +} diff --git a/tools/json/waveshare_rp2040_plus_4mb.json b/tools/json/waveshare_rp2040_plus_4mb.json new file mode 100644 index 000000000..891c9a6e0 --- /dev/null +++ b/tools/json/waveshare_rp2040_plus_4mb.json @@ -0,0 +1,56 @@ +{ + "build": { + "arduino": { + "earlephilhower": { + "boot2_source": "boot2_w25q080_2_padded_checksum.S", + "usb_vid": "0x2E8A", + "usb_pid": "0x1020" + } + }, + "core": "earlephilhower", + "cpu": "cortex-m0plus", + "extra_flags": "-D ARDUINO_WAVESHARE_RP2040_PLUS -DARDUINO_ARCH_RP2040 -DUSBD_MAX_POWER_MA=500", + "f_cpu": "133000000L", + "hwids": [ + [ + "0x2E8A", + "0x00C0" + ], + [ + "0x2E8A", + "0x1020" + ] + ], + "mcu": "rp2040", + "variant": "waveshare_rp2040_plus_4mb" + }, + "debug": { + "jlink_device": "RP2040_M0_0", + "openocd_target": "rp2040.cfg", + "svd_path": "rp2040.svd" + }, + "frameworks": [ + "arduino" + ], + "name": "RP2040 Plus 4MB", + "upload": { + "maximum_ram_size": 270336, + "maximum_size": 4194304, + "require_upload_port": true, + "native_usb": true, + "use_1200bps_touch": true, + "wait_for_upload_port": false, + "protocol": "picotool", + "protocols": [ + "blackmagic", + "cmsis-dap", + "jlink", + "raspberrypi-swd", + "picotool", + "picoprobe", + "pico-debug" + ] + }, + "url": "https://www.raspberrypi.org/products/raspberry-pi-pico/", + "vendor": "Waveshare" +} diff --git a/tools/json/waveshare_rp2040_zero.json b/tools/json/waveshare_rp2040_zero.json new file mode 100644 index 000000000..fa159e225 --- /dev/null +++ b/tools/json/waveshare_rp2040_zero.json @@ -0,0 +1,56 @@ +{ + "build": { + "arduino": { + "earlephilhower": { + "boot2_source": "boot2_w25q16jvxq_4_padded_checksum.S", + "usb_vid": "0x2E8A", + "usb_pid": "0x0003" + } + }, + "core": "earlephilhower", + "cpu": "cortex-m0plus", + "extra_flags": "-D ARDUINO_WAVESHARE_RP2040_ZERO -DARDUINO_ARCH_RP2040 -DUSBD_MAX_POWER_MA=500", + "f_cpu": "133000000L", + "hwids": [ + [ + "0x2E8A", + "0x00C0" + ], + [ + "0x2E8A", + "0x0003" + ] + ], + "mcu": "rp2040", + "variant": "waveshare_rp2040_zero" + }, + "debug": { + "jlink_device": "RP2040_M0_0", + "openocd_target": "rp2040.cfg", + "svd_path": "rp2040.svd" + }, + "frameworks": [ + "arduino" + ], + "name": "RP2040 Zero", + "upload": { + "maximum_ram_size": 270336, + "maximum_size": 2097152, + "require_upload_port": true, + "native_usb": true, + "use_1200bps_touch": true, + "wait_for_upload_port": false, + "protocol": "picotool", + "protocols": [ + "blackmagic", + "cmsis-dap", + "jlink", + "raspberrypi-swd", + "picotool", + "picoprobe", + "pico-debug" + ] + }, + "url": "https://www.raspberrypi.org/products/raspberry-pi-pico/", + "vendor": "Waveshare" +} diff --git a/tools/json/wiznet_5100s_evb_pico.json b/tools/json/wiznet_5100s_evb_pico.json index f86924a14..30b0b8c8d 100644 --- a/tools/json/wiznet_5100s_evb_pico.json +++ b/tools/json/wiznet_5100s_evb_pico.json @@ -42,11 +42,13 @@ "wait_for_upload_port": false, "protocol": "picotool", "protocols": [ + "blackmagic", "cmsis-dap", "jlink", "raspberrypi-swd", "picotool", - "picoprobe" + "picoprobe", + "pico-debug" ] }, "url": "https://www.raspberrypi.org/products/raspberry-pi-pico/", diff --git a/tools/json/wiznet_5500_evb_pico.json b/tools/json/wiznet_5500_evb_pico.json index b633f6d60..b7ee86a7d 100644 --- a/tools/json/wiznet_5500_evb_pico.json +++ b/tools/json/wiznet_5500_evb_pico.json @@ -42,11 +42,13 @@ "wait_for_upload_port": false, "protocol": "picotool", "protocols": [ + "blackmagic", "cmsis-dap", "jlink", "raspberrypi-swd", "picotool", - "picoprobe" + "picoprobe", + "pico-debug" ] }, "url": "https://www.raspberrypi.org/products/raspberry-pi-pico/", diff --git a/tools/json/wiznet_wizfi360_evb_pico.json b/tools/json/wiznet_wizfi360_evb_pico.json index a911556c5..d9da91ef0 100644 --- a/tools/json/wiznet_wizfi360_evb_pico.json +++ b/tools/json/wiznet_wizfi360_evb_pico.json @@ -42,11 +42,13 @@ "wait_for_upload_port": false, "protocol": "picotool", "protocols": [ + "blackmagic", "cmsis-dap", "jlink", "raspberrypi-swd", "picotool", - "picoprobe" + "picoprobe", + "pico-debug" ] }, "url": "https://www.raspberrypi.org/products/raspberry-pi-pico/", diff --git a/tools/libpico/CMakeLists.txt b/tools/libpico/CMakeLists.txt index fd578b9ca..696215994 100644 --- a/tools/libpico/CMakeLists.txt +++ b/tools/libpico/CMakeLists.txt @@ -13,89 +13,153 @@ set(PICO_BOARD pico_w) # Initialize the SDK pico_sdk_init() -add_library(pico STATIC) +add_library(common INTERFACE) # Use a longer XOSC startup time, to accommodate Adafruit and other boards that may need it. -target_compile_definitions(pico PUBLIC - PICO_PRINTF_ALWAYS_INCLUDED=1 - PICO_FLASH_SIZE_BYTES=16777216 - PICO_XOSC_STARTUP_DELAY_MULTIPLIER=64 - LWIP_IPV4=1 - LWIP_IPV6=${IPV6} - LWIP_UDP=1 - LWIP_IGMP=1 - LWIP_CHECKSUM_CTRL_PER_NETIF=1 - CYW43_WARN=// - PICO_FLOAT_SUPPORT_ROM_V1=1 - PICO_DOUBLE_SUPPORT_ROM_V1=1 - PICO_RP2040_B0_SUPPORTED=1 - PICO_RP2040_B1_SUPPORTED=1 - PICO_RP2040_B2_SUPPORTED=1 +target_compile_definitions(common INTERFACE + PICO_PRINTF_ALWAYS_INCLUDED=1 + PICO_FLASH_SIZE_BYTES=16777216 + PICO_XOSC_STARTUP_DELAY_MULTIPLIER=64 + CYW43_WARN=// + PICO_FLOAT_SUPPORT_ROM_V1=1 + PICO_DOUBLE_SUPPORT_ROM_V1=1 + PICO_RP2040_B0_SUPPORTED=1 + PICO_RP2040_B1_SUPPORTED=1 + PICO_RP2040_B2_SUPPORTED=1 + PICO_NO_BINARY_INFO=1 + PICO_CYW43_ARCH_THREADSAFE_BACKGROUND=1 + LWIP_IPV4=1 + LWIP_UDP=1 + LWIP_IGMP=1 + LWIP_CHECKSUM_CTRL_PER_NETIF=1 ) -target_compile_options(pico PUBLIC - -fno-exceptions - -Os - $<$:-fno-rtti> +target_compile_options(common INTERFACE + -fno-exceptions + -Os + $<$:-fno-rtti> ) include_directories(BEFORE ${PICO_SDK_PATH}/../tools/libpico) +add_library(pico STATIC) +target_compile_definitions(pico PUBLIC + LWIP_IPV6=0 +) + target_link_libraries(pico - boot_stage2 - cyw43_driver - hardware_adc - hardware_base - hardware_claim - hardware_clocks - hardware_divider - hardware_dma - hardware_exception - hardware_flash - hardware_gpio - hardware_i2c - hardware_interp - hardware_irq - hardware_pio - hardware_pll - hardware_pwm - hardware_resets - hardware_rtc - hardware_spi - hardware_sync - hardware_timer - hardware_uart - hardware_vreg - hardware_watchdog - hardware_xosc - cmsis - pico_bit_ops - pico_bootrom - pico_bootsel_via_double_reset - pico_cxx_options - pico_cyw43_arch_none - pico_divider - pico_double - pico_fix - pico_float - pico_int64_ops - pico_lwip - pico_lwip_nosys - pico_lwip_sntp - pico_malloc - pico_mem_ops - pico_multicore - pico_platform - pico_runtime - pico_standard_link - pico_stdlib - pico_unique_id - pico_util - tinyusb - tinyusb_device_unmarked + common + boot_stage2 + hardware_adc + hardware_base + hardware_claim + hardware_clocks + hardware_divider + hardware_dma + hardware_exception + hardware_flash + hardware_gpio + hardware_i2c + hardware_interp + hardware_irq + hardware_pio + hardware_pll + hardware_pwm + hardware_resets + hardware_rtc + hardware_spi + hardware_sync + hardware_timer + hardware_uart + hardware_vreg + hardware_watchdog + hardware_xosc + cmsis + pico_bit_ops + pico_bootrom + pico_bootsel_via_double_reset + pico_cxx_options + pico_divider + pico_double + pico_fix + pico_float + pico_int64_ops + pico_malloc + pico_mem_ops + pico_multicore + pico_platform + pico_rand + pico_runtime + pico_standard_link + pico_stdlib + pico_unique_id + pico_util + tinyusb + tinyusb_device_unmarked ) -add_custom_command(TARGET pico POST_BUILD - COMMAND ar d libpico.a stdio.c.obj stdio_usb.c.obj stdio_usb_descriptors.c.obj cyw43_arch_threadsafe_background.c.obj - COMMAND ar q libpico.a pico-sdk/src/rp2_common/cyw43_driver/cyw43_resource.o +add_library(picow-noipv6-nobtc-noble STATIC) +target_compile_definitions(picow-noipv6-nobtc-noble PUBLIC + LWIP_IPV6=0 ) + +set(picow_link_libraries + common + cyw43_driver + cyw43_driver_picow + pico_async_context + pico_cyw43_driver + pico_cyw43_arch + pico_cyw43_arch_threadsafe_background + pico_lwip + pico_lwip_nosys + pico_lwip_sntp + pico_stdlib +) + +target_link_libraries(picow-noipv6-nobtc-noble + ${picow_link_libraries} +) + +add_library(picow-ipv6-nobtc-noble STATIC) +target_compile_definitions(picow-ipv6-nobtc-noble PUBLIC + LWIP_IPV6=1 +) + +target_link_libraries(picow-ipv6-nobtc-noble + ${picow_link_libraries} +) + +add_library(picow-noipv6-btc-ble STATIC) +target_compile_definitions(picow-noipv6-btc-ble PUBLIC + LWIP_IPV6=0 +) + +set(picow_bt_link_libraries + pico_btstack_cyw43 + pico_btstack_ble + pico_btstack_classic +) + +target_link_libraries(picow-noipv6-btc-ble + ${picow_link_libraries} + ${picow_bt_link_libraries} +) + +add_library(picow-ipv6-btc-ble STATIC) +target_compile_definitions(picow-ipv6-btc-ble PUBLIC + LWIP_IPV6=1 +) + +target_link_libraries(picow-ipv6-btc-ble + ${picow_link_libraries} + ${picow_bt_link_libraries} +) + +foreach(tgt pico picow-noipv6-nobtc-noble picow-ipv6-nobtc-noble picow-noipv6-btc-ble picow-ipv6-btc-ble) + add_custom_command(TARGET ${tgt} POST_BUILD + COMMAND ar d lib${tgt}.a stdio.c.obj stdio_uart.c.obj stdio_usb.c.obj stdio_usb_descriptors.c.obj pico_malloc.c.obj + COMMAND ar d lib${tgt}.a btstack_flash_bank.c.obj # Need to override with our own implementation + COMMAND cp lib${tgt}.a ../../../lib/. + ) +endforeach() diff --git a/tools/libpico/btstack_config.h b/tools/libpico/btstack_config.h new file mode 100644 index 000000000..3d1ee3576 --- /dev/null +++ b/tools/libpico/btstack_config.h @@ -0,0 +1,74 @@ +#pragma once + +// BTstack features that can be enabled +#define ENABLE_LOG_INFO +#define ENABLE_LOG_ERROR +#define ENABLE_PRINTF_HEXDUMP +#define ENABLE_SCO_OVER_HCI + +#ifdef ENABLE_CLASSIC +#define ENABLE_L2CAP_ENHANCED_RETRANSMISSION_MODE +#endif + +#ifdef ENABLE_BLE +#define ENABLE_L2CAP_LE_CREDIT_BASED_FLOW_CONTROL_MODE +#define ENABLE_LE_PERIPHERAL +#define ENABLE_LE_CENTRAL +#endif + +// BTstack configuration. buffers, sizes, ... +#define HCI_OUTGOING_PRE_BUFFER_SIZE 4 +#define HCI_ACL_PAYLOAD_SIZE (1691 + 4) +#define HCI_ACL_CHUNK_SIZE_ALIGNMENT 4 +#define MAX_NR_AVDTP_CONNECTIONS 1 +#define MAX_NR_AVDTP_STREAM_ENDPOINTS 1 +#define MAX_NR_AVRCP_CONNECTIONS 2 +#define MAX_NR_BNEP_CHANNELS 1 +#define MAX_NR_BNEP_SERVICES 1 +#define MAX_NR_BTSTACK_LINK_KEY_DB_MEMORY_ENTRIES 2 +#define MAX_NR_GATT_CLIENTS 1 +#define MAX_NR_HCI_CONNECTIONS 2 +#define MAX_NR_HID_HOST_CONNECTIONS 1 +#define MAX_NR_HIDS_CLIENTS 1 +#define MAX_NR_HFP_CONNECTIONS 1 +#define MAX_NR_L2CAP_CHANNELS 4 +#define MAX_NR_L2CAP_SERVICES 3 +#define MAX_NR_RFCOMM_CHANNELS 1 +#define MAX_NR_RFCOMM_MULTIPLEXERS 1 +#define MAX_NR_RFCOMM_SERVICES 1 +#define MAX_NR_SERVICE_RECORD_ITEMS 4 +#define MAX_NR_SM_LOOKUP_ENTRIES 3 +#define MAX_NR_WHITELIST_ENTRIES 16 +#define MAX_NR_LE_DEVICE_DB_ENTRIES 16 + +// Limit number of ACL/SCO Buffer to use by stack to avoid cyw43 shared bus overrun +#define MAX_NR_CONTROLLER_ACL_BUFFERS 3 +#define MAX_NR_CONTROLLER_SCO_PACKETS 3 + +// Enable and configure HCI Controller to Host Flow Control to avoid cyw43 shared bus overrun +#define ENABLE_HCI_CONTROLLER_TO_HOST_FLOW_CONTROL +#define HCI_HOST_ACL_PACKET_LEN 1024 +#define HCI_HOST_ACL_PACKET_NUM 3 +#define HCI_HOST_SCO_PACKET_LEN 120 +#define HCI_HOST_SCO_PACKET_NUM 3 + +// Link Key DB and LE Device DB using TLV on top of Flash Sector interface +#define NVM_NUM_DEVICE_DB_ENTRIES 16 +#define NVM_NUM_LINK_KEYS 16 + +// We don't give btstack a malloc, so use a fixed-size ATT DB. +#define MAX_ATT_DB_SIZE 512 + +// BTstack HAL configuration +#define HAVE_EMBEDDED_TIME_MS + +// map btstack_assert onto Pico SDK assert() +#define HAVE_ASSERT + +// Some USB dongles take longer to respond to HCI reset (e.g. BCM20702A). +#define HCI_RESET_RESEND_TIMEOUT_MS 1000 + +#define ENABLE_SOFTWARE_AES128 +#define ENABLE_MICRO_ECC_FOR_LE_SECURE_CONNECTIONS + +#undef HAVE_BTSTACK_STDIN diff --git a/tools/libpico/lwipopts.h b/tools/libpico/lwipopts.h index 697b9548c..0dc0ed683 100644 --- a/tools/libpico/lwipopts.h +++ b/tools/libpico/lwipopts.h @@ -13,6 +13,9 @@ extern void interrupts(); #define SYS_ARCH_PROTECT(lev) noInterrupts #define SYS_ARCH_UNPROTECT(lev) interrupts +extern unsigned long get_rand_32(void); +#define LWIP_RAND() get_rand_32() + // Common settings used in most of the pico_w examples // (see https://www.nongnu.org/lwip/2_1_x/group__lwip__opts.html for details) @@ -25,7 +28,7 @@ extern void interrupts(); #define MEMP_NUM_TCP_SEG 32 #define MEMP_NUM_ARP_QUEUE 10 #define PBUF_POOL_SIZE 24 -#define LWIP_ARP 1 +#define LWIP_ARP 2 #define LWIP_ETHERNET 1 #define LWIP_ICMP 1 #define LWIP_RAW 1 @@ -53,6 +56,9 @@ extern void interrupts(); #define DHCP_DOES_ARP_CHECK 0 #define LWIP_DHCP_DOES_ACD_CHECK 0 +// See #1285 +#define MEMP_NUM_UDP_PCB 6 + #if LWIP_IPV6 #define LWIP_IPV6_DHCP6 1 #endif diff --git a/tools/libpico/make-libpico.sh b/tools/libpico/make-libpico.sh index 9a1448d60..aa008bc87 100755 --- a/tools/libpico/make-libpico.sh +++ b/tools/libpico/make-libpico.sh @@ -8,22 +8,14 @@ export PATH="$(cd ../../system/arm-none-eabi/bin; pwd):$PATH" rm -rf build mkdir build cd build -cmake .. -DIPV6=0 -make -j +cmake .. +make -j V=1 # Put everything in its place -mv libpico.a ../../../lib/. mv generated/pico_base/pico/version.h ../../../include/pico_base/pico/. cp ../lwipopts.h ../../../include/. cp ../tusb_config.h ../../../include/. - -cd .. -rm -rf build -mkdir build -cd build -cmake .. -DIPV6=1 -make -j -mv libpico.a ../../../lib/libpico-ipv6.a +cp ../btstack_config.h ../../../include/. rm -rf boot mkdir boot diff --git a/tools/libpico/tusb_config.h b/tools/libpico/tusb_config.h index 5e3b624e9..91c9c1a7a 100644 --- a/tools/libpico/tusb_config.h +++ b/tools/libpico/tusb_config.h @@ -72,15 +72,14 @@ //------------- CLASS -------------// #define CFG_TUD_HID (2) #define CFG_TUD_CDC (1) -#define CFG_TUD_MSC (0) +#define CFG_TUD_MSC (1) #define CFG_TUD_MIDI (0) #define CFG_TUD_VENDOR (0) #define CFG_TUD_CDC_RX_BUFSIZE (256) #define CFG_TUD_CDC_TX_BUFSIZE (256) -#define CFG_TUD_MIDI_RX_BUFSIZE (64) -#define CFG_TUD_MIDI_TX_BUFSIZE (64) +#define CFG_TUD_MSC_EP_BUFSIZE (64) // HID buffer size Should be sufficient to hold ID (if any) + Data #define CFG_TUD_HID_EP_BUFSIZE (64) diff --git a/tools/makeboards.py b/tools/makeboards.py index 6f4f2349e..be3aef676 100755 --- a/tools/makeboards.py +++ b/tools/makeboards.py @@ -14,6 +14,7 @@ def BuildFlashMenu(name, flashsize, fssizelist): mn="%d_%d" % (flashsize, fssize) print("%s.menu.flash.%s=%dMB (%s)" % (name, mn, flashsize / (1024 * 1024), fssizename)) print("%s.menu.flash.%s.upload.maximum_size=%d" % (name, mn, flashsize - 4096 - fssize)) + print("%s.menu.flash.%s.build.flash_total=%d" % (name, mn, flashsize)) print("%s.menu.flash.%s.build.flash_length=%d" % (name, mn, flashsize - 4096 - fssize)) print("%s.menu.flash.%s.build.eeprom_start=%d" % (name, mn, int("0x10000000",0) + flashsize - 4096)) print("%s.menu.flash.%s.build.fs_start=%d" % (name, mn, int("0x10000000",0) + flashsize - 4096 - fssize)) @@ -69,7 +70,16 @@ def BuildBoot(name): for l in [ ("Generic SPI /2", "boot2_generic_03h_2_padded_checksum"), ("Generic SPI /4", "boot2_generic_03h_4_padded_checksum"), ("IS25LP080 QSPI /2", "boot2_is25lp080_2_padded_checksum"), ("IS25LP080 QSPI /4", "boot2_is25lp080_4_padded_checksum"), ("W25Q080 QSPI /2", "boot2_w25q080_2_padded_checksum"), ("W25Q080 QSPI /4", "boot2_w25q080_4_padded_checksum"), - ("W25X10CL QSPI /2", "boot2_w25x10cl_2_padded_checksum"), ("W25X10CL QSPI /4", "boot2_w25x10cl_4_padded_checksum") ]: + ("W25X10CL QSPI /2", "boot2_w25x10cl_2_padded_checksum"), ("W25X10CL QSPI /4", "boot2_w25x10cl_4_padded_checksum"), + ("W25Q64JV QSPI /4", "boot2_w25q64jv_4_padded_checksum"), ("W25Q16JVxQ QSPI /4", "boot2_w25q16jvxq_4_padded_checksum"), + ("W25Q128JV QSPI /4", "boot2_w25q128jvxq_4_padded_checksum")]: + print("%s.menu.boot2.%s=%s" % (name, l[1], l[0])) + print("%s.menu.boot2.%s.build.boot2=%s" % (name, l[1], l[1])) + +# Abbreviated Boot Stage 2 menu for some W25Q-equipped Adafruit boards. +# In extreme overclock situations, these may require QSPI /4 to work. +def BuildBootW25Q(name): + for l in [ ("W25Q080 QSPI /2", "boot2_w25q080_2_padded_checksum"), ("W25Q080 QSPI /4", "boot2_w25q080_4_padded_checksum")]: print("%s.menu.boot2.%s=%s" % (name, l[1], l[0])) print("%s.menu.boot2.%s.build.boot2=%s" % (name, l[1], l[1])) @@ -78,36 +88,85 @@ def BuildUSBStack(name): print('%s.menu.usbstack.picosdk.build.usbstack_flags=' % (name)) print("%s.menu.usbstack.tinyusb=Adafruit TinyUSB" % (name)) print('%s.menu.usbstack.tinyusb.build.usbstack_flags=-DUSE_TINYUSB "-I{runtime.platform.path}/libraries/Adafruit_TinyUSB_Arduino/src/arduino"' % (name)) - -def BuildWithoutUSBStack(name): print("%s.menu.usbstack.nousb=No USB" % (name)) print('%s.menu.usbstack.nousb.build.usbstack_flags="-DNO_USB -DDISABLE_USB_SERIAL -I{runtime.platform.path}/tools/libpico"' % (name)) -def BuildIPStack(name): - print("%s.menu.ipstack.ipv4only=IPv4 Only" % (name)) - print('%s.menu.ipstack.ipv4only.build.libpico=libpico.a' % (name)) - print('%s.menu.ipstack.ipv4only.build.lwipdefs=-DLWIP_IPV6=0 -DLWIP_IPV4=1' % (name)) - print("%s.menu.ipstack.ipv4ipv6=IPv4 and IPv6" % (name)) - print('%s.menu.ipstack.ipv4ipv6.build.libpico=libpico-ipv6.a' % (name)) - print('%s.menu.ipstack.ipv4ipv6.build.lwipdefs=-DLWIP_IPV6=1 -DLWIP_IPV4=1' % (name)) - -def BuildHeader(name, vendor_name, product_name, vidtouse, pidtouse, vid, pid, pwr, boarddefine, variant, uploadtool, flashsize, ramsize, boot2, extra): +def BuildCountry(name): + countries = [ "Worldwide", "Australia", "Austria", "Belgium", "Brazil", "Canada", "Chile", "China", "Colombia", "Czech Republic", + "Denmark", "Estonia", "Finland", "France", "Germany", "Greece", "Hong Kong", "Hungary", "Iceland", "India", "Israel", + "Italy", "Japan", "Kenya", "Latvia", "Liechtenstein", "Lithuania", "Luxembourg", "Malaysia", "Malta", "Mexico", + "Netherlands", "New Zealand", "Nigeria", "Norway", "Peru", "Philippines", "Poland", "Portugal", "Singapore", "Slovakia", + "Slovenia", "South Africa", "South Korea", "Spain", "Sweden", "Switzerland", "Taiwan", "Thailand", "Turkey", "UK", "USA"] + for c in countries: + sane = c.replace(" ", "_").upper() + print("%s.menu.wificountry.%s=%s" % (name, sane.lower(), c)) + print("%s.menu.wificountry.%s.build.wificc=-DWIFICC=CYW43_COUNTRY_%s" % (name, sane.lower(), sane)) + +def BuildIPBTStack(name): + print("%s.menu.ipbtstack.ipv4only=IPv4 Only" % (name)) + print('%s.menu.ipbtstack.ipv4only.build.libpicow=libpicow-noipv6-nobtc-noble.a' % (name)) + print('%s.menu.ipbtstack.ipv4only.build.libpicowdefs=-DLWIP_IPV6=0 -DLWIP_IPV4=1' % (name)) + print("%s.menu.ipbtstack.ipv4ipv6=IPv4 + IPv6" % (name)) + print('%s.menu.ipbtstack.ipv4ipv6.build.libpicow=libpicow-ipv6-nobtc-noble.a' % (name)) + print('%s.menu.ipbtstack.ipv4ipv6.build.libpicowdefs=-DLWIP_IPV6=1 -DLWIP_IPV4=1' % (name)) + print("%s.menu.ipbtstack.ipv4btcble=IPv4 + Bluetooth" % (name)) + print('%s.menu.ipbtstack.ipv4btcble.build.libpicow=libpicow-noipv6-btc-ble.a' % (name)) + print('%s.menu.ipbtstack.ipv4btcble.build.libpicowdefs=-DLWIP_IPV6=0 -DLWIP_IPV4=1 -DENABLE_CLASSIC=1 -DENABLE_BLE=1' % (name)) + print("%s.menu.ipbtstack.ipv4ipv6btcble=IPv4 + IPv6 + Bluetooth" % (name)) + print('%s.menu.ipbtstack.ipv4ipv6btcble.build.libpicow=libpicow-ipv6-btc-ble.a' % (name)) + print('%s.menu.ipbtstack.ipv4ipv6btcble.build.libpicowdefs=-DLWIP_IPV6=1 -DLWIP_IPV4=1 -DENABLE_CLASSIC=1 -DENABLE_BLE=1' % (name)) + +def BuildUploadMethodMenu(name): + for a, b, c, d, e, f in [ ["default", "Default (UF2)", 256, "picoprobe.tcl", "uf2conv", "uf2conv-network"], + ["picotool", "Picotool", 256, "picoprobe.tcl", "picotool", None], + ["picoprobe", "Picoprobe", 256, "picoprobe.tcl", "picoprobe", None], + ["picoprobe_cmsis_dap", "Picoprobe (CMSIS-DAP)", 256, "picoprobe_cmsis_dap.tcl", "picoprobe_cmsis_dap", None], + ["picodebug", "Pico-Debug", 240, "picodebug.tcl", "picodebug", None] ]: + print("%s.menu.uploadmethod.%s=%s" % (name, a, b)) + print("%s.menu.uploadmethod.%s.build.ram_length=%dk" % (name, a, c)) + print("%s.menu.uploadmethod.%s.build.debugscript=%s" % (name, a, d)) + # For pico-debug, need to disable USB unconditionally + if a == "picodebug": + print("%s.menu.uploadmethod.%s.build.picodebugflags=-UUSE_TINYUSB -DNO_USB -DDISABLE_USB_SERIAL -I{runtime.platform.path}/tools/libpico" % (name, a)) + elif a == "picotool": + print("%s.menu.uploadmethod.%s.build.picodebugflags=-DENABLE_PICOTOOL_USB" % (name, a)) + print("%s.menu.uploadmethod.%s.upload.maximum_data_size=%d" % (name, a, c * 1024)) + print("%s.menu.uploadmethod.%s.upload.tool=%s" % (name, a, e)) + print("%s.menu.uploadmethod.%s.upload.tool.default=%s" % (name, a, e)) + if f != None: + print("%s.menu.uploadmethod.%s.upload.tool.network=%s" % (name, a, f)) + +def BuildHeader(name, vendor_name, product_name, vid, pid, pwr, boarddefine, variant, flashsize, boot2, extra): prettyname = vendor_name + " " + product_name print() print("# -----------------------------------") print("# %s" % (prettyname)) print("# -----------------------------------") print("%s.name=%s" % (name, prettyname)) - print("%s.vid.0=%s" % (name, vidtouse)) - print("%s.pid.0=%s" % (name, pidtouse)) - print("%s.build.usbpid=-DSERIALUSB_PID=%s" % (name, pid)) + usb = 0 + if type(pid) == list: + for tp in pid: + print("%s.vid.%d=%s" % (name, usb, vid)) + print("%s.pid.%d=0x%04x" % (name, usb, int(tp, 16))) + usb = usb + 1 + else: + for kb in [ "0", "0x8000" ]: + for ms in [ "0", "0x4000" ]: + for jy in [ "0", "0x0100" ]: + thispid = int(pid, 16) | int(kb, 16) | int(ms, 16) | int(jy, 16) + print("%s.vid.%d=%s" % (name, usb, vid)) + print("%s.pid.%d=0x%04x" % (name, usb, thispid)) + usb = usb + 1 + print("%s.build.usbvid=-DUSBD_VID=%s" % (name, vid)) + if type(pid) == list: + print("%s.build.usbpid=-DUSBD_PID=%s" % (name, pid[0])) + else: + print("%s.build.usbpid=-DUSBD_PID=%s" % (name, pid)) print("%s.build.usbpwr=-DUSBD_MAX_POWER_MA=%s" % (name, pwr)) print("%s.build.board=%s" % (name, boarddefine)) print("%s.build.mcu=cortex-m0plus" % (name)) print("%s.build.variant=%s" % (name, variant)) - print("%s.upload.tool=%s" % (name, uploadtool)) print("%s.upload.maximum_size=%d" % (name, flashsize)) - print("%s.upload.maximum_data_size=%d" % (name, ramsize)) print("%s.upload.wait_for_upload_port=true" % (name)) print("%s.upload.erase_cmd=" % (name)) print("%s.serial.disableDTR=false" % (name)) @@ -116,10 +175,7 @@ def BuildHeader(name, vendor_name, product_name, vidtouse, pidtouse, vid, pid, p print("%s.build.led=" % (name)) print("%s.build.core=rp2040" % (name)) print("%s.build.ldscript=memmap_default.ld" % (name)) - print("%s.build.ram_length=%dk" % (name, ramsize / 1024)) print("%s.build.boot2=%s" % (name, boot2)) - print("%s.build.vid=%s" % (name, vid)) - print("%s.build.pid=%s" % (name, pid)) print('%s.build.usb_manufacturer="%s"' % (name, vendor_name)) print('%s.build.usb_product="%s"' % (name, product_name)) if extra != None: @@ -145,48 +201,39 @@ def BuildGlobalMenuList(): print("menu.dbgport=Debug Port") print("menu.dbglvl=Debug Level") print("menu.boot2=Boot Stage 2") + print("menu.wificountry=WiFi Region") print("menu.usbstack=USB Stack") - print("menu.ipstack=IP Stack") + print("menu.ipbtstack=IP/Bluetooth Stack") + print("menu.uploadmethod=Upload Method") def MakeBoard(name, vendor_name, product_name, vid, pid, pwr, boarddefine, flashsizemb, boot2, extra = None): - for a, b, c in [ ["", "", "uf2conv"], ["picoprobe", " (Picoprobe)", "picoprobe"], ["picodebug", " (pico-debug)", "picodebug"]]: - n = name + a - p = product_name + b - fssizelist = [ 0, 64 * 1024, 128 * 1024, 256 * 1024, 512 * 1024 ] - for i in range(1, flashsizemb): - fssizelist.append(i * 1024 * 1024) - vidtouse = vid; - ramsizekb = 256; - if a == "picoprobe": - pidtouse = '0x0004' - elif a == "picodebug": - vidtouse = '0x1209' - pidtouse = '0x2488' - ramsizekb = 240; - else: - pidtouse = pid - BuildHeader(n, vendor_name, p, vidtouse, pidtouse, vid, pid, pwr, boarddefine, name, c, flashsizemb * 1024 * 1024, ramsizekb * 1024, boot2, extra) - if name == "generic": - BuildFlashMenu(n, 2*1024*1024, [0, 1*1024*1024]) - BuildFlashMenu(n, 4*1024*1024, [0, 2*1024*1024]) - BuildFlashMenu(n, 8*1024*1024, [0, 4*1024*1024]) - BuildFlashMenu(n, 16*1024*1024, [0, 8*1024*1024]) - else: - BuildFlashMenu(n, flashsizemb * 1024 * 1024, fssizelist) - BuildFreq(n) - BuildOptimize(n) - BuildRTTI(n) - BuildStackProtect(n) - BuildExceptions(n) - BuildDebugPort(n) - BuildDebugLevel(n) - if a == "picodebug": - BuildWithoutUSBStack(n) - else: - BuildUSBStack(n) - BuildIPStack(n) - if name == "generic": - BuildBoot(n) + fssizelist = [ 0, 64 * 1024, 128 * 1024, 256 * 1024, 512 * 1024 ] + for i in range(1, flashsizemb): + fssizelist.append(i * 1024 * 1024) + BuildHeader(name, vendor_name, product_name, vid, pid, pwr, boarddefine, name, flashsizemb * 1024 * 1024, boot2, extra) + if (name == "generic") or (name == "vccgnd_yd_rp2040"): + BuildFlashMenu(name, 2*1024*1024, [0, 1*1024*1024]) + BuildFlashMenu(name, 4*1024*1024, [0, 3*1024*1024, 2*1024*1024]) + BuildFlashMenu(name, 8*1024*1024, [0, 7*1024*1024, 4*1024*1024, 2*1024*1024]) + BuildFlashMenu(name, 16*1024*1024, [0, 15*1024*1024, 14*1024*1024, 12*1024*1024, 8*1024*1024, 4*1024*1024, 2*1024*1024]) + else: + BuildFlashMenu(name, flashsizemb * 1024 * 1024, fssizelist) + BuildFreq(name) + BuildOptimize(name) + BuildRTTI(name) + BuildStackProtect(name) + BuildExceptions(name) + BuildDebugPort(name) + BuildDebugLevel(name) + BuildUSBStack(name) + if name == "rpipicow": + BuildCountry(name) + BuildIPBTStack(name) + if name == "generic": + BuildBoot(name) + elif name.startswith("adafruit") and "w25q080" in boot2: + BuildBootW25Q(name) + BuildUploadMethodMenu(name) MakeBoardJSON(name, vendor_name, product_name, vid, pid, pwr, boarddefine, flashsizemb, boot2, extra) global pkgjson thisbrd = {} @@ -194,6 +241,8 @@ def MakeBoard(name, vendor_name, product_name, vid, pid, pwr, boarddefine, flash pkgjson['packages'][0]['platforms'][0]['boards'].append(thisbrd) def MakeBoardJSON(name, vendor_name, product_name, vid, pid, pwr, boarddefine, flashsizemb, boot2, extra): + if type(pid) == list: + pid = pid[0] if extra != None: m_extra = ' ' for m_item in extra: @@ -244,11 +293,13 @@ def MakeBoardJSON(name, vendor_name, product_name, vid, pid, pwr, boarddefine, f "wait_for_upload_port": false, "protocol": "picotool", "protocols": [ + "blackmagic", "cmsis-dap", "jlink", "raspberrypi-swd", "picotool", - "picoprobe" + "picoprobe", + "pico-debug" ] }, "url": "https://www.raspberrypi.org/products/raspberry-pi-pico/", @@ -284,8 +335,18 @@ def MakeBoardJSON(name, vendor_name, product_name, vid, pid, pwr, boarddefine, f MakeBoard("rpipico", "Raspberry Pi", "Pico", "0x2e8a", "0x000a", 250, "RASPBERRY_PI_PICO", 2, "boot2_w25q080_2_padded_checksum") MakeBoard("rpipicow", "Raspberry Pi", "Pico W", "0x2e8a", "0xf00a", 250, "RASPBERRY_PI_PICO_W", 2, "boot2_w25q080_2_padded_checksum") +# 0xCB +MakeBoard("0xcb_helios", "0xCB", "Helios", "0x1209", "0xCB74", 500, "0XCB_HELIOS", 16, "boot2_w25q128jvxq_4_padded_checksum") + # Adafruit MakeBoard("adafruit_feather", "Adafruit", "Feather RP2040", "0x239a", "0x80f1", 250, "ADAFRUIT_FEATHER_RP2040", 8, "boot2_w25x10cl_4_padded_checksum") +MakeBoard("adafruit_feather_scorpio", "Adafruit", "Feather RP2040 SCORPIO", "0x239a", "0x8121", 250, "ADAFRUIT_FEATHER_RP2040_SCORPIO", 8, "boot2_w25q080_2_padded_checksum") +MakeBoard("adafruit_feather_dvi", "Adafruit", "Feather RP2040 DVI", "0x239a", "0x8127", 250, "ADAFRUIT_FEATHER_RP2040_DVI", 8, "boot2_w25q080_2_padded_checksum") +MakeBoard("adafruit_feather_rfm", "Adafruit", "Feather RP2040 RFM", "0x239a", "0x812D", 250, "ADAFRUIT_FEATHER_RP2040_RFM", 8, "boot2_w25q080_2_padded_checksum") +MakeBoard("adafruit_feather_thinkink", "Adafruit", "Feather RP2040 ThinkINK", "0x239a", "0x812B", 250, "ADAFRUIT_FEATHER_RP2040_THINKINK", 8, "boot2_w25q080_2_padded_checksum") +MakeBoard("adafruit_feather_usb_host", "Adafruit", "Feather RP2040 USB Host", "0x239a", "0x8129", 250, "ADAFRUIT_FEATHER_RP2040_USB_HOST", 8, "boot2_w25q080_2_padded_checksum") +MakeBoard("adafruit_feather_can", "Adafruit", "Feather RP2040 CAN", "0x239a", "0x812f", 250, "ADAFRUIT_FEATHER_RP2040_CAN", 8, "boot2_w25q080_2_padded_checksum") +MakeBoard("adafruit_feather_prop_maker", "Adafruit", "Feather RP2040 Prop-Maker", "0x239a", "0x8131", 250, "ADAFRUIT_FEATHER_RP2040_PROP_MAKER", 8, "boot2_w25q080_2_padded_checksum") MakeBoard("adafruit_itsybitsy", "Adafruit", "ItsyBitsy RP2040", "0x239a", "0x80fd", 250, "ADAFRUIT_ITSYBITSY_RP2040", 8, "boot2_w25q080_2_padded_checksum") MakeBoard("adafruit_qtpy", "Adafruit", "QT Py RP2040", "0x239a", "0x80f7", 250, "ADAFRUIT_QTPY_RP2040", 8, "boot2_w25q080_2_padded_checksum") MakeBoard("adafruit_stemmafriend", "Adafruit", "STEMMA Friend RP2040", "0x239a", "0x80e3", 250, "ADAFRUIT_STEMMAFRIEND_RP2040", 8, "boot2_w25q080_2_padded_checksum") @@ -294,20 +355,29 @@ def MakeBoardJSON(name, vendor_name, product_name, vid, pid, pwr, boarddefine, f MakeBoard("adafruit_kb2040", "Adafruit", "KB2040", "0x239a", "0x8105", 250, "ADAFRUIT_KB2040_RP2040", 8, "boot2_w25q080_2_padded_checksum") # Arduino -MakeBoard("arduino_nano_connect", "Arduino", "Nano RP2040 Connect", "0x2341", "0x0058", 250, "NANO_RP2040_CONNECT", 16, "boot2_w25q080_2_padded_checksum") +MakeBoard("arduino_nano_connect", "Arduino", "Nano RP2040 Connect", "0x2341", ["0x005e", "0x805e", "0x015e", "0x025e"] , 250, "NANO_RP2040_CONNECT", 16, "boot2_w25q080_2_padded_checksum") + +# BridgeTek +MakeBoard("bridgetek_idm2040-7a", "BridgeTek", "IDM2040-7A", "0x2e8a", "0x1041", 250, "BRIDGETEK_IDM2040-7A", 8, "boot2_w25q080_2_padded_checksum", ["FT8XX_TYPE=BT817", "DISPLAY_RES=WVGA", "PLATFORM_RP2040"]) # Cytron MakeBoard("cytron_maker_nano_rp2040", "Cytron", "Maker Nano RP2040", "0x2e8a", "0x100f", 250, "CYTRON_MAKER_NANO_RP2040", 2, "boot2_w25q080_2_padded_checksum") MakeBoard("cytron_maker_pi_rp2040", "Cytron", "Maker Pi RP2040", "0x2e8a", "0x1000", 250, "CYTRON_MAKER_PI_RP2040", 2, "boot2_w25q080_2_padded_checksum") +# DatanoiseTV +MakeBoard("datanoisetv_picoadk", "DatanoiseTV", "PicoADK", "0x2e8a", "0x000a", 250, "DATANOISETV_PICOADK", 2, "boot2_w25q080_2_padded_checksum") + # DeRuiLab -MakeBoard("flyboard2040_core", "DeRuiLab", "FlyBoard2040Core", "0x2e8a", "0x008a", 500, "FLYBOARD2040_CORE", 4, "boot2_generic_03h_4_padded_checksum") +MakeBoard("flyboard2040_core", "DeRuiLab", "FlyBoard2040Core", "0x2e8a", "0x008a", 500, "FLYBOARD2040_CORE", 4, "boot2_w25q080_2_padded_checksum") # DFRobot MakeBoard("dfrobot_beetle_rp2040", "DFRobot", "Beetle RP2040", "0x3343", "0x4253", 250, "DFROBOT_BEETLE_RP2040", 2, "boot2_w25q080_2_padded_checksum") # ElectronicCat -MakeBoard("electroniccats_bombercat", "ElectronicCats", "HunterCat NFC RP2040", "0x1209", "0x1209", 500, "ELECTRONICCATS_BOMBERCAT", 2, "boot2_w25q080_2_padded_checksum") +MakeBoard("electroniccats_huntercat_nfc", "ElectronicCats", "HunterCat NFC RP2040", "0x2E8A", "0x1037", 500, "ELECTRONICCATS_HUNTERCAT_NFC", 2, "boot2_w25q080_2_padded_checksum") + +# ExtremeElectronics +MakeBoard("extelec_rc2040", "ExtremeElectronics", "RC2040", "0x2e8a", "0xee20", 250, "EXTREMEELEXTRONICS_RC2040", 2, "boot2_w25q080_2_padded_checksum") # iLabs MakeBoard("challenger_2040_lte", "iLabs", "Challenger 2040 LTE", "0x2e8a", "0x100b", 500, "CHALLENGER_2040_LTE_RP2040", 8, "boot2_w25q080_2_padded_checksum") @@ -316,12 +386,24 @@ def MakeBoardJSON(name, vendor_name, product_name, vid, pid, pwr, boarddefine, f MakeBoard("challenger_2040_wifi", "iLabs", "Challenger 2040 WiFi", "0x2e8a", "0x1006", 250, "CHALLENGER_2040_WIFI_RP2040", 8, "boot2_w25q080_2_padded_checksum", ["WIFIESPAT2"]) MakeBoard("challenger_2040_wifi_ble", "iLabs", "Challenger 2040 WiFi/BLE", "0x2e8a", "0x102C", 500, "CHALLENGER_2040_WIFI_BLE_RP2040", 8, "boot2_w25q080_2_padded_checksum", ["WIFIESPAT2"]) MakeBoard("challenger_nb_2040_wifi", "iLabs", "Challenger NB 2040 WiFi", "0x2e8a", "0x100d", 500, "CHALLENGER_NB_2040_WIFI_RP2040", 8, "boot2_w25q080_2_padded_checksum", ["WIFIESPAT2"]) -MakeBoard("challenger_2040_sdrtc", "iLabs", "Challenger 2040 SD/RTC", "0x2e8a", "0x102d", 250, "CHALLENGER_NB_2040_SDRTC_RP2040", 8, "boot2_w25q080_2_padded_checksum") +MakeBoard("challenger_2040_sdrtc", "iLabs", "Challenger 2040 SD/RTC", "0x2e8a", "0x102d", 250, "CHALLENGER_2040_SDRTC_RP2040", 8, "boot2_w25q080_2_padded_checksum") +MakeBoard("challenger_2040_nfc", "iLabs", "Challenger 2040 NFC", "0x2e8a", "0x1036", 250, "CHALLENGER_2040_NFC_RP2040", 8, "boot2_w25q080_2_padded_checksum") +MakeBoard("challenger_2040_uwb", "iLabs", "Challenger 2040 UWB", "0x2e8a", "0x1052", 500, "CHALLENGER_2040_UWB_RP2040", 8, "boot2_w25q080_2_padded_checksum") MakeBoard("ilabs_rpico32", "iLabs", "RPICO32", "0x2e8a", "0x1010", 250, "ILABS_2040_RPICO32_RP2040", 8, "boot2_w25q080_2_padded_checksum") -# Melopera +# Melopero +MakeBoard("melopero_cookie_rp2040", "Melopero", "Cookie RP2040", "0x2e8a", "0x1011", 250, "MELOPERO_COOKIE_RP2040", 8, "boot2_w25q080_2_padded_checksum") MakeBoard("melopero_shake_rp2040", "Melopero", "Shake RP2040", "0x2e8a", "0x1005", 250, "MELOPERO_SHAKE_RP2040", 16, "boot2_w25q080_2_padded_checksum") +# Neko Systems +MakeBoard("nekosystems_bl2040_mini", "Neko Systems", "BL2040 Mini", "0x2e8a", "0x000a", 500, "NEKOSYSTEMS_BL2040_MINI", 4, "boot2_generic_03h_2_padded_checksum") + +# nullbits +MakeBoard("nullbits_bit_c_pro", "nullbits", "Bit-C PRO", "0x2e8a", "0x6e61", 500, "NULLBITS_BIT_C_PRO", 4, "boot2_w25x10cl_4_padded_checksum") + +# Pimoroni +MakeBoard("pimoroni_pga2040", "Pimoroni", "PGA2040", "0x2e8a", "0x1008", 250, "PIMORONI_PGA2040", 8, "boot2_w25q64jv_4_padded_checksum") + # Solder Party MakeBoard("solderparty_rp2040_stamp", "Solder Party", "RP2040 Stamp", "0x1209", "0xa182", 500, "SOLDERPARTY_RP2040_STAMP", 8, "boot2_generic_03h_4_padded_checksum") @@ -333,8 +415,23 @@ def MakeBoardJSON(name, vendor_name, product_name, vid, pid, pwr, boarddefine, f MakeBoard("upesy_rp2040_devkit", "uPesy", "RP2040 DevKit", "0x2e8a", "0x1007", 250, "UPESY_RP2040_DEVKIT", 2, "boot2_w25q080_2_padded_checksum") # Seeed +MakeBoard("seeed_indicator_rp2040", "Seeed", "INDICATOR RP2040", "0x2886", "0x0050", 250, "SEEED_INDICATOR_RP2040", 2, "boot2_w25q080_2_padded_checksum") MakeBoard("seeed_xiao_rp2040", "Seeed", "XIAO RP2040", "0x2e8a", "0x000a", 250, "SEEED_XIAO_RP2040", 2, "boot2_w25q080_2_padded_checksum") +# VCC-GND YD-2040 - Use generic SPI/4 because boards seem to come with varied flash modules but same name +MakeBoard('vccgnd_yd_rp2040', "VCC-GND", "YD RP2040", "0x2e8a", "0x800a", 500, "YD_RP2040", 16, "boot2_generic_03h_4_padded_checksum") + +# Viyalab +MakeBoard("viyalab_mizu", "Viyalab", "Mizu RP2040", "0x2e8a", "0x000a", 250, "VIYALAB_MIZU_RP2040", 8, "boot2_generic_03h_4_padded_checksum") + +# Waveshare +MakeBoard("waveshare_rp2040_zero", "Waveshare", "RP2040 Zero", "0x2e8a", "0x0003", 500, "WAVESHARE_RP2040_ZERO", 2, "boot2_w25q16jvxq_4_padded_checksum") +MakeBoard("waveshare_rp2040_one", "Waveshare", "RP2040 One", "0x2e8a", "0x103a", 500, "WAVESHARE_RP2040_ONE", 4, "boot2_w25q16jvxq_4_padded_checksum") +MakeBoard("waveshare_rp2040_plus_4mb", "Waveshare", "RP2040 Plus 4MB", "0x2e8a", "0x1020", 500, "WAVESHARE_RP2040_PLUS", 4, "boot2_w25q080_2_padded_checksum") +MakeBoard("waveshare_rp2040_plus_16mb", "Waveshare", "RP2040 Plus 16MB", "0x2e8a", "0x1020", 500, "WAVESHARE_RP2040_PLUS", 16, "boot2_w25q080_2_padded_checksum") +MakeBoard("waveshare_rp2040_lcd_0_96", "Waveshare", "RP2040 LCD 0.96", "0x2e8a", "0x1021", 500, "WAVESHARE_RP2040_LCD_0_96", 2, "boot2_w25q16jvxq_4_padded_checksum") +MakeBoard("waveshare_rp2040_lcd_1_28", "Waveshare", "RP2040 LCD 1.28", "0x2e8a", "0x1039", 500, "WAVESHARE_RP2040_LCD_1_28", 2, "boot2_w25q16jvxq_4_padded_checksum") + # WIZnet MakeBoard("wiznet_5100s_evb_pico", "WIZnet", "W5100S-EVB-Pico", "0x2e8a", "0x1027", 250, "WIZNET_5100S_EVB_PICO", 2, "boot2_w25q080_2_padded_checksum") MakeBoard("wiznet_wizfi360_evb_pico", "WIZnet", "WizFi360-EVB-Pico", "0x2e8a", "0x1028", 250, "WIZNET_WIZFI360_EVB_PICO", 2, "boot2_w25q080_2_padded_checksum") diff --git a/tools/platformio-build.py b/tools/platformio-build.py index 7cf811701..08e38f622 100755 --- a/tools/platformio-build.py +++ b/tools/platformio-build.py @@ -21,8 +21,17 @@ board = env.BoardConfig() upload_protocol = env.subst("$UPLOAD_PROTOCOL") or "picotool" #ram_size = board.get("upload.maximum_ram_size") # PlatformIO gives 264K here -# override to correct 256K for RAM section in linkerscript -ram_size = 256 * 1024 # not the 264K, which is 256K SRAM + 2*4K SCRATCH(X/Y). +# but the RAM size we need is without the SCRATCH memory. +if upload_protocol == "pico-debug": + ram_size = 240 * 1024 # pico-debug needs 16K of the upper memory for itself with pico-debug-gimmecache.uf2 + # this only works when the user disables the USB stack. + if "PIO_FRAMEWORK_ARDUINO_NO_USB" not in env.Flatten(env.get("CPPDEFINES", [])): + sys.stderr.write("Must define PIO_FRAMEWORK_ARDUINO_NO_USB when using pico-debug!\n") + env.Exit(-1) +else: + ram_size = 256 * 1024 # not the 264K, which is 256K SRAM + 2*4K SCRATCH(X/Y). +# Update available RAM size +board.update("upload.maximum_ram_size", ram_size) FRAMEWORK_DIR = platform.get_package_dir("framework-arduinopico") assert os.path.isdir(FRAMEWORK_DIR) @@ -80,10 +89,22 @@ def is_pio_build(): ) # pico support library depends on ipv6 enable/disable -if "PIO_FRAMEWORK_ARDUINO_ENABLE_IPV6" in flatten_cppdefines: - libpico = File(os.path.join(FRAMEWORK_DIR, "lib", "libpico-ipv6.a")) +libpico = File(os.path.join(FRAMEWORK_DIR, "lib", "libpico.a")) +if "PIO_FRAMEWORK_ARDUINO_ENABLE_BLUETOOTH" in flatten_cppdefines: + if "PIO_FRAMEWORK_ARDUINO_ENABLE_IPV6" in flatten_cppdefines: + libpicow = File(os.path.join(FRAMEWORK_DIR, "lib", "libpicow-ipv6-btc-ble.a")) + else: + libpicow = File(os.path.join(FRAMEWORK_DIR, "lib", "libpicow-noipv6-btc-ble.a")) + env.Append( + CPPDEFINES=[ + ("ENABLE_CLASSIC", 1), + ("ENABLE_BLE", 1) + ] + ) +elif "PIO_FRAMEWORK_ARDUINO_ENABLE_IPV6" in flatten_cppdefines: + libpicow = File(os.path.join(FRAMEWORK_DIR, "lib", "libpicow-ipv6-nobtc-noble.a")) else: - libpico = File(os.path.join(FRAMEWORK_DIR, "lib", "libpico.a")) + libpicow = File(os.path.join(FRAMEWORK_DIR, "lib", "libpicow-noipv6-nobtc-noble.a")) env.Append( ASFLAGS=env.get("CCFLAGS", [])[:], @@ -96,7 +117,7 @@ def is_pio_build(): "-mthumb", "-ffunction-sections", "-fdata-sections" - # -iprefix etc. added lader if in build mode + # -iprefix etc. added later if in build mode ], CFLAGS=[ @@ -114,6 +135,10 @@ def is_pio_build(): ("BOARD_NAME", '\\"%s\\"' % env.subst("$BOARD")), "ARM_MATH_CM0_FAMILY", "ARM_MATH_CM0_PLUS", + "TARGET_RP2040", + # at this point, the main.py builder script hasn't updated upload.maximum_size yet, + # so it's the original value for the full flash. + ("PICO_FLASH_SIZE_BYTES", board.get("upload.maximum_size")) ], CPPPATH=[ @@ -150,6 +175,7 @@ def is_pio_build(): LIBS=[ File(os.path.join(FRAMEWORK_DIR, "lib", "ota.o")), libpico, + libpicow, File(os.path.join(FRAMEWORK_DIR, "lib", "libbearssl.a")), "m", "c", stdcpp_lib, "c"] ) @@ -165,7 +191,6 @@ def is_pio_build(): def configure_usb_flags(cpp_defines): - global ram_size if "USE_TINYUSB" in cpp_defines: env.Append(CPPPATH=[os.path.join( FRAMEWORK_DIR, "libraries", "Adafruit_TinyUSB_Arduino", "src", "arduino")]) @@ -204,10 +229,9 @@ def configure_usb_flags(cpp_defines): pidtouse = usb_pid if upload_protocol == "picoprobe": pidtouse = '0x0004' - elif upload_protocol == "picodebug": + elif upload_protocol == "pico-debug": vidtouse = '0x1209' pidtouse = '0x2488' - ram_size = 240 * 1024 env.Append(CPPDEFINES=[ ("CFG_TUSB_MCU", "OPT_MCU_RP2040"), @@ -228,12 +252,11 @@ def configure_usb_flags(cpp_defines): hw_ids[0][0] = vidtouse hw_ids[0][1] = pidtouse board.update("build.hwids", hw_ids) - board.update("upload.maximum_ram_size", ram_size) def configure_network_flags(cpp_defines): env.Append(CPPDEFINES=[ ("PICO_CYW43_ARCH_THREADSAFE_BACKGROUND", 1), - ("CYW43_LWIP", 0), + ("CYW43_LWIP", 1), ("LWIP_IPV4", 1), ("LWIP_IGMP", 1), ("LWIP_CHECKSUM_CTRL_PER_NETIF", 1) diff --git a/tools/pluggable_discovery.py b/tools/pluggable_discovery.py new file mode 100755 index 000000000..51dec16be --- /dev/null +++ b/tools/pluggable_discovery.py @@ -0,0 +1,120 @@ +#!/usr/bin/env python3 +import os +import subprocess +import sys +import time +import threading + + +toolspath = os.path.dirname(os.path.realpath(__file__)) +try: + sys.path.insert(0, os.path.join(toolspath, ".")) # Add pyserial dir to search path + import uf2conv # If this fails, we can't continue and will bomb below +except ImportError: + sys.stderr.write("uf2conv not found next to this tool.\n") + sys.exit(1) + + +scannerGo = False + +def scanner(): + global scannerGo + scannerGo = True + boards = False + while scannerGo: + l = uf2conv.get_drives() + if (len(l) > 0) and scannerGo and not boards: + boards = True + print ("""{ + "eventType": "add", + "port": { + "address": "UF2_Board", + "label": "UF2 Board", + "protocol": "uf2conv", + "protocolLabel": "UF2 Devices", + "properties": { + "mac": "ffffffffffff", + "pid" : "0x2e8a", + "vid" : "0x000a" + } + } +}""", flush=True) + elif (len(l) == 0) and scannerGo and boards: + boards = False + print("""{ + "eventType": "remove", + "port": { + "address": "UF2_Board", + "protocol": "uf2conv" + } +}""", flush = True) + n = time.time() + 2 + while scannerGo and (time.time() < n): + time.sleep(.1) + scannerGo = True + +def main(): + global scannerGo + while True: + cmdline = input() + cmd = cmdline.split()[0] + if cmd == "HELLO": + print(""" { + "eventType": "hello", + "message": "OK", + "protocolVersion": 1 +}""", flush = True) + elif cmd == "START": + print("""{ + "eventType": "start", + "message": "OK" +}""", flush = True); + elif cmd == "STOP": + scannerGo = False + while not scannerGo: + time.sleep(.1) + print("""{ + "eventType": "stop", + "message": "OK" +}""", flush = True) + elif cmd == "QUIT": + scannerGo = False + print("""{ + "eventType": "quit", + "message": "OK" +}""", flush = True) + return + elif cmd == "LIST": + l = uf2conv.get_drives() + if len(l) > 0: + print ("""{ + "eventType": "list", + "ports": [ + { + "address": "UF2_Board", + "label": "UF2 Board", + "protocol": "uf2conv", + "protocolLabel": "UF2 Devices", + "properties": { + "mac": "ffffffffffff", + "pid" : "0x2e8a", + "vid" : "0x000a" + } + } + ] +}""", flush=True) + else: + print ("""{ + "eventType": "list", + "ports": [ ] +}""", flush=True) + elif cmd == "START_SYNC": + print("""{ + "eventType": "start_sync", + "message": "OK" +}""", flush = True) + scannerGo = True + threading.Thread(target = scanner).start() + time.sleep(.5) + +main() diff --git a/tools/uf2conv.py b/tools/uf2conv.py index 2905929d4..d4ed34fb5 100755 --- a/tools/uf2conv.py +++ b/tools/uf2conv.py @@ -225,6 +225,23 @@ def convert_from_hex_to_uf2(buf): def to_str(b): return b.decode("utf-8", "replace") +def possibly_add(p, q): + if p not in q: + if os.path.isdir(p): + if os.access(p, os.W_OK): + q.append(p) + +def possibly_anydir(p, q): + if os.path.isdir(p): + if os.access(p, os.R_OK): + r = glob.glob(p + "/*") + for t in r: + possibly_add(t, q) + +def possibly_any(p, q, r): + possibly_anydir(p, q) + possibly_anydir(p + r, q) + def get_drives(): drives = [] if sys.platform == "win32": @@ -248,21 +265,9 @@ def get_drives(): if len(words) >= 3 and words[1] == "2" and words[2] == "FAT": drives.append(words[0]) else: - rootpath = "/run/media" - if not os.path.isdir(rootpath): - rootpath = "/media" - if not os.path.isdir(rootpath): - rootpath = "/opt/media" if sys.platform == "darwin": - rootpath = "/Volumes" + possibly_anydir("/Volumes", drives) elif sys.platform == "linux": - tmp = rootpath + "/" + os.environ["USER"] - if os.path.isdir(tmp): - rootpath = tmp - for d in os.listdir(rootpath): - drives.append(os.path.join(rootpath, d)) - - if (len(drives) == 0) and (sys.platform == "linux"): globexpr = "/dev/disk/by-id/usb-RPI_RP2*-part1" rpidisk = glob.glob(globexpr) if len(rpidisk) > 0: @@ -277,6 +282,19 @@ def get_drives(): except Exception as ex: print("Exception executing udisksctl. Exception: {}".format(ex)) # If it fails, no problem since it was a heroic attempt + ''' + Generate a list and scan those too. + First add the usual suspects. + Then Scan a returned list. + ''' + u="/" + os.environ["USER"] + possibly_anydir("/mnt", drives) + possibly_any("/media", drives, u) + possibly_any("/opt/media", drives, u) + possibly_any("/run/media", drives, u) + possibly_any("/var/run/media", drives, u) + # Add from udisksctl info? + # Add from /proc/mounts? def has_info(d): try: @@ -346,9 +364,17 @@ def error(msg): if str(args.serial).startswith("/dev/tty") or str(args.serial).startswith("COM") or str(args.serial).startswith("/dev/cu"): try: print("Resetting " + str(args.serial)) + sys.stdout.flush() try: - ser = serial.Serial(args.serial, 1200) + ser = serial.Serial() + ser.port = args.serial + ser.open() + ser.baudrate = 9600 + ser.dtr = True + time.sleep(0.1) ser.dtr = False + ser.baudrate = 1200 + ser.close() except: pass # Ignore error in the case it is already in upload mode except: @@ -376,15 +402,18 @@ def error(msg): outbuf = convert_to_uf2(inpbuf) print("Converting to %s, output size: %d, start address: 0x%x" % (ext, len(outbuf), appstartaddr)) + sys.stdout.flush() if args.convert or ext != "uf2": drives = [] if args.output == None: args.output = "flash." + ext else: + print("Scanning for RP2040 devices") + sys.stdout.flush() now = time.time() drives = [] while (time.time() - now < 10.0) and (len(drives) == 0): - time.sleep(0.5) # Avoid 100% CPU use while waiting for drive to appear + time.sleep(1.0) # Avoid 100% CPU use while waiting for drive to appear drives = get_drives() if args.output: @@ -394,8 +423,20 @@ def error(msg): error("No drive to deploy.") for d in drives: print("Flashing %s (%s)" % (d, board_id(d))) + sys.stdout.flush() write_file(d + "/NEW.UF2", outbuf) + # Wait until serial port (if defined) re-appears, or 2s timeout unless UF2 drive direct upload + try: + if args.serial != "UF2 Board": + timeout = time.time() + 2.0 + while time.time() < timeout: + if os.access(args.serial, os.W_OK): + break + time.sleep(0.2) + except: + pass + if __name__ == "__main__": main() diff --git a/variants/0xcb_helios/pins_arduino.h b/variants/0xcb_helios/pins_arduino.h new file mode 100644 index 000000000..7dd1218b9 --- /dev/null +++ b/variants/0xcb_helios/pins_arduino.h @@ -0,0 +1,41 @@ +#pragma once + +// Pin definitions taken from: https://raw.githubusercontent.com/0xCB-dev/0xCB-Helios/main/rev1.0/helios.webp + +// LEDs +#define PIN_LED (17u) + +// Serial +#define PIN_SERIAL1_TX (0u) +#define PIN_SERIAL1_RX (1u) + +// Not pinned out +#define PIN_SERIAL2_TX (31u) +#define PIN_SERIAL2_RX (31u) + +// SPI +#define PIN_SPI0_MISO (20u) +#define PIN_SPI0_MOSI (23u) +#define PIN_SPI0_SCK (22u) +#define PIN_SPI0_SS (21u) + +// Not pinned out +#define PIN_SPI1_MISO (31u) +#define PIN_SPI1_MOSI (31u) +#define PIN_SPI1_SCK (31u) +#define PIN_SPI1_SS (31u) + +// Not pinned out +#define PIN_WIRE0_SDA (31u) +#define PIN_WIRE0_SCL (31u) + +// Wire +#define PIN_WIRE1_SDA (2u) +#define PIN_WIRE1_SCL (3u) + +#define SERIAL_HOWMANY (1u) +#define SPI_HOWMANY (1u) +#define WIRE_HOWMANY (1u) + +#define PIN_NEOPIXEL (25u) +#include "../generic/common.h" diff --git a/variants/adafruit_feather_can/pins_arduino.h b/variants/adafruit_feather_can/pins_arduino.h new file mode 100644 index 000000000..76d537a65 --- /dev/null +++ b/variants/adafruit_feather_can/pins_arduino.h @@ -0,0 +1,59 @@ +#pragma once + +// Pin definitions taken from: +// https://learn.adafruit.com/assets/100337 + +// LEDs +#define PIN_LED (13u) + +// NeoPixel +#define PIN_NEOPIXEL (21u) +#define NEOPIXEL_POWER (20u) + +// 'Boot0' button also on GPIO #7 +#define PIN_BUTTON (7u) + +// CAN bus +#define PIN_CAN_STANDBY (16u) +#define PIN_CAN_TX0_RTS (17u) +#define PIN_CAN_RESET (18u) +#define PIN_CAN_CS (19u) +#define PIN_CAN_INTERRUPT (22u) +#define PIN_CAN_RX0_BF (23u) + +// Serial +#define PIN_SERIAL1_TX (0u) +#define PIN_SERIAL1_RX (1u) + +// Not pinned out +#define PIN_SERIAL2_TX (31u) +#define PIN_SERIAL2_RX (31u) + +// SPI +#define PIN_SPI0_MISO (8u) +#define PIN_SPI0_MOSI (15u) +#define PIN_SPI0_SCK (14u) +#define PIN_SPI0_SS (13u) +#define __SPI0_DEVICE spi1 + +// Not pinned out +#define PIN_SPI1_MISO (31u) +#define PIN_SPI1_MOSI (31u) +#define PIN_SPI1_SCK (31u) +#define PIN_SPI1_SS (31u) +#define __SPI1_DEVICE spi0 + +// Wire +#define PIN_WIRE0_SDA (2u) +#define PIN_WIRE0_SCL (3u) +#define __WIRE0_DEVICE i2c1 + +#define PIN_WIRE1_SDA (31u) +#define PIN_WIRE1_SCL (31u) +#define __WIRE1_DEVICE i2c0 + +#define SERIAL_HOWMANY (2u) +#define SPI_HOWMANY (1u) +#define WIRE_HOWMANY (1u) + +#include "../generic/common.h" diff --git a/variants/adafruit_feather_dvi/pins_arduino.h b/variants/adafruit_feather_dvi/pins_arduino.h new file mode 100644 index 000000000..a003be97c --- /dev/null +++ b/variants/adafruit_feather_dvi/pins_arduino.h @@ -0,0 +1,60 @@ +#pragma once + +// Pin definitions taken from: +// https://learn.adafruit.com/assets/100337 + +// LEDs +#define PIN_LED (13u) + +// NeoPixel +#define PIN_NEOPIXEL (4u) + +// 'Boot0' button also on GPIO #7 +#define PIN_BUTTON (7u) + +// DVI connector +#define PIN_CKN (16u) +#define PIN_CKP (17u) +#define PIN_D0N (18u) +#define PIN_D0P (19u) +#define PIN_D1N (20u) +#define PIN_D1P (21u) +#define PIN_D2N (22u) +#define PIN_D2P (23u) + +// Serial +#define PIN_SERIAL1_TX (0u) +#define PIN_SERIAL1_RX (1u) + +// Not pinned out +#define PIN_SERIAL2_TX (31u) +#define PIN_SERIAL2_RX (31u) + +// SPI +#define PIN_SPI0_MISO (8u) +#define PIN_SPI0_MOSI (15u) +#define PIN_SPI0_SCK (14u) +#define PIN_SPI0_SS (13u) +#define __SPI0_DEVICE spi1 + +// Not pinned out +#define PIN_SPI1_MISO (31u) +#define PIN_SPI1_MOSI (31u) +#define PIN_SPI1_SCK (31u) +#define PIN_SPI1_SS (31u) +#define __SPI1_DEVICE spi0 + +// Wire +#define PIN_WIRE0_SDA (2u) +#define PIN_WIRE0_SCL (3u) +#define __WIRE0_DEVICE i2c1 + +#define PIN_WIRE1_SDA (31u) +#define PIN_WIRE1_SCL (31u) +#define __WIRE1_DEVICE i2c0 + +#define SERIAL_HOWMANY (2u) +#define SPI_HOWMANY (1u) +#define WIRE_HOWMANY (1u) + +#include "../generic/common.h" diff --git a/variants/adafruit_feather_prop_maker/pins_arduino.h b/variants/adafruit_feather_prop_maker/pins_arduino.h new file mode 100644 index 000000000..1ab10686b --- /dev/null +++ b/variants/adafruit_feather_prop_maker/pins_arduino.h @@ -0,0 +1,60 @@ +#pragma once + +// Pin definitions taken from: +// https://learn.adafruit.com/assets/100337 + +// LEDs +#define PIN_LED (13u) + +// NeoPixel +#define PIN_NEOPIXEL (4u) + +// 'Boot0' button also on GPIO #7 +#define PIN_BUTTON (7u) + +// Prop-Maker features +#define PIN_I2S_DATA (16u) +#define PIN_I2S_BIT_CLOCK (17u) +#define PIN_I2S_WORD_SELECT (18u) +#define PIN_EXTERNAL_BUTTON (19u) +#define PIN_EXTERNAL_SERVO (20u) +#define PIN_EXTERNAL_NEOPIXELS (21u) +#define PIN_ACCELEROMETER_INTERRUPT (22u) +#define PIN_EXTERNAL_POWER (23u) + +// Serial +#define PIN_SERIAL1_TX (0u) +#define PIN_SERIAL1_RX (1u) + +// Not pinned out +#define PIN_SERIAL2_TX (31u) +#define PIN_SERIAL2_RX (31u) + +// SPI +#define PIN_SPI0_MISO (8u) +#define PIN_SPI0_MOSI (15u) +#define PIN_SPI0_SCK (14u) +#define PIN_SPI0_SS (13u) +#define __SPI0_DEVICE spi1 + +// Not pinned out +#define PIN_SPI1_MISO (31u) +#define PIN_SPI1_MOSI (31u) +#define PIN_SPI1_SCK (31u) +#define PIN_SPI1_SS (31u) +#define __SPI1_DEVICE spi0 + +// Wire +#define PIN_WIRE0_SDA (2u) +#define PIN_WIRE0_SCL (3u) +#define __WIRE0_DEVICE i2c1 + +#define PIN_WIRE1_SDA (31u) +#define PIN_WIRE1_SCL (31u) +#define __WIRE1_DEVICE i2c0 + +#define SERIAL_HOWMANY (2u) +#define SPI_HOWMANY (1u) +#define WIRE_HOWMANY (1u) + +#include "../generic/common.h" diff --git a/variants/adafruit_feather_rfm/pins_arduino.h b/variants/adafruit_feather_rfm/pins_arduino.h new file mode 100644 index 000000000..91731d913 --- /dev/null +++ b/variants/adafruit_feather_rfm/pins_arduino.h @@ -0,0 +1,60 @@ +#pragma once + +// Pin definitions taken from: +// https://learn.adafruit.com/assets/100337 + +// LEDs +#define PIN_LED (13u) + +// NeoPixel +#define PIN_NEOPIXEL (4u) + +// 'Boot0' button also on GPIO #7 +#define PIN_BUTTON (7u) + +// RFM transceiver module +#define PIN_RFM_CS (16u) +#define PIN_RFM_RST (17u) +#define PIN_RFM_DIO5 (18u) +#define PIN_RFM_DIO3 (19u) +#define PIN_RFM_DIO4 (20u) +#define PIN_RFM_DIO0 (21u) +#define PIN_RFM_DIO1 (22u) +#define PIN_RFM_DIO2 (23u) + +// Serial +#define PIN_SERIAL1_TX (0u) +#define PIN_SERIAL1_RX (1u) + +// Not pinned out +#define PIN_SERIAL2_TX (31u) +#define PIN_SERIAL2_RX (31u) + +// SPI +#define PIN_SPI0_MISO (8u) +#define PIN_SPI0_MOSI (15u) +#define PIN_SPI0_SCK (14u) +#define PIN_SPI0_SS (13u) +#define __SPI0_DEVICE spi1 + +// Not pinned out +#define PIN_SPI1_MISO (31u) +#define PIN_SPI1_MOSI (31u) +#define PIN_SPI1_SCK (31u) +#define PIN_SPI1_SS (31u) +#define __SPI1_DEVICE spi0 + +// Wire +#define PIN_WIRE0_SDA (2u) +#define PIN_WIRE0_SCL (3u) +#define __WIRE0_DEVICE i2c1 + +#define PIN_WIRE1_SDA (31u) +#define PIN_WIRE1_SCL (31u) +#define __WIRE1_DEVICE i2c0 + +#define SERIAL_HOWMANY (2u) +#define SPI_HOWMANY (1u) +#define WIRE_HOWMANY (1u) + +#include "../generic/common.h" diff --git a/variants/adafruit_feather_scorpio/pins_arduino.h b/variants/adafruit_feather_scorpio/pins_arduino.h new file mode 100644 index 000000000..72048ad8c --- /dev/null +++ b/variants/adafruit_feather_scorpio/pins_arduino.h @@ -0,0 +1,60 @@ +#pragma once + +// Pin definitions taken from: +// https://learn.adafruit.com/assets/100337 + +// LEDs +#define PIN_LED (13u) + +// NeoPixel +#define PIN_NEOPIXEL (4u) + +// 'Boot0' button also on GPIO #7 +#define PIN_BUTTON (7u) + +// SCORPIO end connector (level-shifted I/O) +#define PIN_NEOPIXEL0 (16u) +#define PIN_NEOPIXEL1 (17u) +#define PIN_NEOPIXEL2 (18u) +#define PIN_NEOPIXEL3 (19u) +#define PIN_NEOPIXEL4 (20u) +#define PIN_NEOPIXEL5 (21u) +#define PIN_NEOPIXEL6 (22u) +#define PIN_NEOPIXEL7 (23u) + +// Serial +#define PIN_SERIAL1_TX (0u) +#define PIN_SERIAL1_RX (1u) + +// Not pinned out +#define PIN_SERIAL2_TX (31u) +#define PIN_SERIAL2_RX (31u) + +// SPI +#define PIN_SPI0_MISO (8u) +#define PIN_SPI0_MOSI (15u) +#define PIN_SPI0_SCK (14u) +#define PIN_SPI0_SS (13u) +#define __SPI0_DEVICE spi1 + +// Not pinned out +#define PIN_SPI1_MISO (31u) +#define PIN_SPI1_MOSI (31u) +#define PIN_SPI1_SCK (31u) +#define PIN_SPI1_SS (31u) +#define __SPI1_DEVICE spi0 + +// Wire +#define PIN_WIRE0_SDA (2u) +#define PIN_WIRE0_SCL (3u) +#define __WIRE0_DEVICE i2c1 + +#define PIN_WIRE1_SDA (31u) +#define PIN_WIRE1_SCL (31u) +#define __WIRE1_DEVICE i2c0 + +#define SERIAL_HOWMANY (2u) +#define SPI_HOWMANY (1u) +#define WIRE_HOWMANY (1u) + +#include "../generic/common.h" diff --git a/variants/adafruit_feather_thinkink/pins_arduino.h b/variants/adafruit_feather_thinkink/pins_arduino.h new file mode 100644 index 000000000..9e9cc293d --- /dev/null +++ b/variants/adafruit_feather_thinkink/pins_arduino.h @@ -0,0 +1,59 @@ +#pragma once + +// Pin definitions taken from: +// https://learn.adafruit.com/assets/100337 + +// LEDs +#define PIN_LED (13u) + +// NeoPixel +#define PIN_NEOPIXEL (21u) +#define NEOPIXEL_POWER (20u) + +// 'Boot0' button also on GPIO #7 +#define PIN_BUTTON (7u) + +// EPD connector +#define PIN_EPD_BUSY (16u) +#define PIN_EPD_RESET (17u) +#define PIN_EPD_DC (18u) +#define PIN_EPD_CS (19u) +#define PIN_EPD_SCK (22u) +#define PIN_EPD_MOSI (23u) + +// Serial +#define PIN_SERIAL1_TX (0u) +#define PIN_SERIAL1_RX (1u) + +// Not pinned out +#define PIN_SERIAL2_TX (31u) +#define PIN_SERIAL2_RX (31u) + +// SPI +#define PIN_SPI0_MISO (8u) +#define PIN_SPI0_MOSI (15u) +#define PIN_SPI0_SCK (14u) +#define PIN_SPI0_SS (13u) +#define __SPI0_DEVICE spi1 + +// EPD SPI +#define PIN_SPI1_MISO (31u) +#define PIN_SPI1_MOSI (23u) +#define PIN_SPI1_SCK (22u) +#define PIN_SPI1_SS (19u) +#define __SPI1_DEVICE spi0 + +// Wire +#define PIN_WIRE0_SDA (2u) +#define PIN_WIRE0_SCL (3u) +#define __WIRE0_DEVICE i2c1 + +#define PIN_WIRE1_SDA (31u) +#define PIN_WIRE1_SCL (31u) +#define __WIRE1_DEVICE i2c0 + +#define SERIAL_HOWMANY (2u) +#define SPI_HOWMANY (2u) +#define WIRE_HOWMANY (1u) + +#include "../generic/common.h" diff --git a/variants/adafruit_feather_usb_host/pins_arduino.h b/variants/adafruit_feather_usb_host/pins_arduino.h new file mode 100644 index 000000000..a8a77cb53 --- /dev/null +++ b/variants/adafruit_feather_usb_host/pins_arduino.h @@ -0,0 +1,56 @@ +#pragma once + +// Pin definitions taken from: +// https://learn.adafruit.com/assets/100337 + +// LEDs +#define PIN_LED (13u) + +// NeoPixel +#define PIN_NEOPIXEL (21u) +#define NEOPIXEL_POWER (20u) + +// 'Boot0' button also on GPIO #7 +#define PIN_BUTTON (7u) + +// USB host connector +#define PIN_USB_HOST_DP (16u) +#define PIN_USB_HOST_DM (17u) +#define PIN_5V_EN (18u) + +// Serial +#define PIN_SERIAL1_TX (0u) +#define PIN_SERIAL1_RX (1u) + +// Not pinned out +#define PIN_SERIAL2_TX (31u) +#define PIN_SERIAL2_RX (31u) + +// SPI +#define PIN_SPI0_MISO (8u) +#define PIN_SPI0_MOSI (15u) +#define PIN_SPI0_SCK (14u) +#define PIN_SPI0_SS (13u) +#define __SPI0_DEVICE spi1 + +// Not pinned out +#define PIN_SPI1_MISO (31u) +#define PIN_SPI1_MOSI (31u) +#define PIN_SPI1_SCK (31u) +#define PIN_SPI1_SS (31u) +#define __SPI1_DEVICE spi0 + +// Wire +#define PIN_WIRE0_SDA (2u) +#define PIN_WIRE0_SCL (3u) +#define __WIRE0_DEVICE i2c1 + +#define PIN_WIRE1_SDA (31u) +#define PIN_WIRE1_SCL (31u) +#define __WIRE1_DEVICE i2c0 + +#define SERIAL_HOWMANY (2u) +#define SPI_HOWMANY (1u) +#define WIRE_HOWMANY (1u) + +#include "../generic/common.h" diff --git a/variants/arduino_nano_connect/nina_pins.h b/variants/arduino_nano_connect/nina_pins.h index 78dd7ebf6..66a136185 100644 --- a/variants/arduino_nano_connect/nina_pins.h +++ b/variants/arduino_nano_connect/nina_pins.h @@ -4,33 +4,33 @@ #define _NINA_PINS_ /****************************************************************************** - * INCLUDE + INCLUDE ******************************************************************************/ #include "Arduino.h" /****************************************************************************** - * TYPEDEF + TYPEDEF ******************************************************************************/ int getAnalogReadResolution(); class NinaPin { public: - NinaPin(int _pin) : pin(_pin) {}; - int get() { - return pin; - }; - int analogReadResolution() { - return getAnalogReadResolution(); - }; - bool operator== (NinaPin const & other) const { - return pin == other.pin; - } - //operator int() = delete; - __attribute__ ((error("Change me to a #define"))) operator int(); + NinaPin(int _pin) : pin(_pin) {}; + int get() { + return pin; + }; + int analogReadResolution() { + return getAnalogReadResolution(); + }; + bool operator== (NinaPin const & other) const { + return pin == other.pin; + } + //operator int() = delete; + __attribute__((error("Change me to a #define"))) operator int(); private: - int pin; + int pin; }; extern NinaPin LEDR; @@ -44,13 +44,13 @@ extern NinaPin A7; #define NINA_PINS_AS_CLASS /****************************************************************************** - * FUNCTION DECLARATION + FUNCTION DECLARATION ******************************************************************************/ -void pinMode (NinaPin pin, PinMode mode); -PinStatus digitalRead (NinaPin pin); +void pinMode(NinaPin pin, PinMode mode); +PinStatus digitalRead(NinaPin pin); void digitalWrite(NinaPin pin, PinStatus value); -int analogRead (NinaPin pin); -void analogWrite (NinaPin pin, int value); +int analogRead(NinaPin pin); +void analogWrite(NinaPin pin, int value); #endif /* _NINA_PINS_ */ diff --git a/variants/arduino_nano_connect/pins_arduino.h b/variants/arduino_nano_connect/pins_arduino.h index a4433217f..ff0a5a627 100644 --- a/variants/arduino_nano_connect/pins_arduino.h +++ b/variants/arduino_nano_connect/pins_arduino.h @@ -21,9 +21,9 @@ static const uint8_t D13 = (6u); static const uint8_t D14 = (26u); static const uint8_t D15 = (27u); static const uint8_t D16 = (28u); -static const uint8_t D17 = (29u); -static const uint8_t D18 = (12u); -static const uint8_t D19 = (13u); +static const uint8_t D17 = (29u); +static const uint8_t D18 = (12u); +static const uint8_t D19 = (13u); static const uint8_t D20 = (2u); static const uint8_t D21 = (24u); static const uint8_t D22 = (22u); @@ -94,6 +94,9 @@ static const uint8_t SCK = PIN_SPI0_SCK; #define SerialNina Serial3 #define SerialHCI Serial2 +#define SERIAL3_TX (D25) +#define SERIAL3_RX (D26) + //#define NINA_GPIOIRQ (21u) // LEDG pin (GPIO26 on NINA) #define NINA_GPIO0 (D20) // (2u), real GPIO0 on NINA diff --git a/variants/bridgetek_idm2040-7a/pins_arduino.h b/variants/bridgetek_idm2040-7a/pins_arduino.h new file mode 100644 index 000000000..589be765c --- /dev/null +++ b/variants/bridgetek_idm2040-7a/pins_arduino.h @@ -0,0 +1,46 @@ +#pragma once + +// Pin definitions taken from: +// https://brtchip.com/ic-module/wp-content/uploads/sites/3/2022/07/DS_IDM2040-7A-Revised.pdf + + +// LEDs +#define PIN_LED (25u) + +// Serial +#define PIN_SERIAL1_TX (0u) +#define PIN_SERIAL1_RX (1u) + +#define PIN_SERIAL2_TX (8u) +#define PIN_SERIAL2_RX (9u) + +// SPI +#define PIN_SPI0_MISO (4u) +#define PIN_SPI0_MOSI (3u) +#define PIN_SPI0_SCK (2u) +#define PIN_SPI0_SS (5u) + +#define PIN_SPI1_MISO (12u) +#define PIN_SPI1_MOSI (11u) +#define PIN_SPI1_SCK (10u) +#define PIN_SPI1_SS (13u) + +// default spi +#define PIN_SD_MOSI PIN_SPI1_MOSI +#define PIN_SD_MISO PIN_SPI1_MISO +#define PIN_SD_SCK PIN_SPI1_SCK +#define PIN_SD_SS PIN_SPI1_SS +#define SDCARD_DETECT 33 + +// Wire +#define PIN_WIRE0_SDA (4u) +#define PIN_WIRE0_SCL (5u) + +#define PIN_WIRE1_SDA (26u) +#define PIN_WIRE1_SCL (27u) + +#define SERIAL_HOWMANY (3u) +#define SPI_HOWMANY (2u) +#define WIRE_HOWMANY (2u) + +#include "../generic/common.h" diff --git a/variants/challenger_2040_lora/pins_arduino.h b/variants/challenger_2040_lora/pins_arduino.h index b800b7f3c..72e455919 100644 --- a/variants/challenger_2040_lora/pins_arduino.h +++ b/variants/challenger_2040_lora/pins_arduino.h @@ -47,20 +47,20 @@ #define LED_BUILTIN PIN_LED -static const uint8_t D0 = (16u); -static const uint8_t D1 = (17u); -static const uint8_t D2 = (20u); -static const uint8_t D3 = (23u); -static const uint8_t D4 = (22u); -static const uint8_t D5 = (2u); -static const uint8_t D6 = (3u); -static const uint8_t D7 = (0u); -static const uint8_t D8 = (1u); -static const uint8_t D9 = (4u); -static const uint8_t D10 = (5u); -static const uint8_t D11 = (6u); -static const uint8_t D12 = (7u); -static const uint8_t D13 = (8u); +static const uint8_t D0 = (16u); +static const uint8_t D1 = (17u); +static const uint8_t D2 = (20u); +static const uint8_t D3 = (23u); +static const uint8_t D4 = (22u); +static const uint8_t D5 = (2u); +static const uint8_t D6 = (3u); +static const uint8_t D7 = (0u); +static const uint8_t D8 = (1u); +static const uint8_t D9 = (4u); +static const uint8_t D10 = (5u); +static const uint8_t D11 = (6u); +static const uint8_t D12 = (7u); +static const uint8_t D13 = (8u); static const uint8_t D14 = (13u); static const uint8_t D15 = (14u); static const uint8_t D16 = (15u); diff --git a/variants/challenger_2040_lte/ChallengerLTE.cpp b/variants/challenger_2040_lte/ChallengerLTE.cpp index 623904127..9494d16af 100644 --- a/variants/challenger_2040_lte/ChallengerLTE.cpp +++ b/variants/challenger_2040_lte/ChallengerLTE.cpp @@ -22,92 +22,99 @@ #include Challenger2040LTEClass::Challenger2040LTEClass() { - pinMode(PIN_SARA_ON, OUTPUT); - digitalWrite(PIN_SARA_ON, LOW); // Output register must always be low - pinMode(PIN_SARA_ON, INPUT_PULLUP); + pinMode(PIN_SARA_ON, OUTPUT); + digitalWrite(PIN_SARA_ON, LOW); // Output register must always be low + pinMode(PIN_SARA_ON, INPUT_PULLUP); - pinMode(PIN_SARA_RST, INPUT_PULLUP); // Keep as input for now + pinMode(PIN_SARA_RST, INPUT_PULLUP); // Keep as input for now - pinMode(PIN_SARA_PWR, OUTPUT); - digitalWrite(PIN_SARA_PWR, LOW); // No power to SARA yet - serialPortConfigured = false; + pinMode(PIN_SARA_PWR, OUTPUT); + digitalWrite(PIN_SARA_PWR, LOW); // No power to SARA yet + serialPortConfigured = false; } // Do a HW reset by applying a low pulse to the reset line for 1mSec bool Challenger2040LTEClass::doPowerOn() { - bool ret; - digitalWrite(PIN_SARA_PWR, HIGH); // Make sure LDO is on - delay(100); // let the power stabilize - pinMode(PIN_SARA_ON, OUTPUT); // Pull power on control low - delay(150); // For 150mS - pinMode(PIN_SARA_ON, INPUT_PULLUP); // before releasing it again. - delay(1000); // Now wait for 1 second - SARA_SERIAL_PORT.begin(DEFAULT_SARA_BAUDRATE); - serialPortConfigured = true; - ret = isAlive(); // Makie sure the modem is - // up and running - - delay(250); // Allow for any extra characters - // before flushing the input buffer - while(SARA_SERIAL_PORT.available()) SARA_SERIAL_PORT.read(); - - return ret; + bool ret; + digitalWrite(PIN_SARA_PWR, HIGH); // Make sure LDO is on + delay(100); // let the power stabilize + pinMode(PIN_SARA_ON, OUTPUT); // Pull power on control low + delay(150); // For 150mS + pinMode(PIN_SARA_ON, INPUT_PULLUP); // before releasing it again. + delay(1000); // Now wait for 1 second + SARA_SERIAL_PORT.begin(DEFAULT_SARA_BAUDRATE); + serialPortConfigured = true; + ret = isAlive(); // Makie sure the modem is + // up and running + + delay(250); // Allow for any extra characters + // before flushing the input buffer + while (SARA_SERIAL_PORT.available()) { + SARA_SERIAL_PORT.read(); + } + + return ret; } // Checks to see if the modem responds to the "AT" poll command. bool Challenger2040LTEClass::isAlive(uint32_t timeout) { - SARA_SERIAL_PORT.setTimeout(100); - SARA_SERIAL_PORT.println(F("AT")); - String rdy = SARA_SERIAL_PORT.readStringUntil('\n'); - while(!rdy.startsWith(F("OK")) && --timeout) { + SARA_SERIAL_PORT.setTimeout(100); SARA_SERIAL_PORT.println(F("AT")); - rdy = SARA_SERIAL_PORT.readStringUntil('\n'); - //Serial.println(rdy); - } - SARA_SERIAL_PORT.setTimeout(1000); // Restore serial timeout - if (timeout) - return true; - return false; + String rdy = SARA_SERIAL_PORT.readStringUntil('\n'); + while (!rdy.startsWith(F("OK")) && --timeout) { + SARA_SERIAL_PORT.println(F("AT")); + rdy = SARA_SERIAL_PORT.readStringUntil('\n'); + //Serial.println(rdy); + } + SARA_SERIAL_PORT.setTimeout(1000); // Restore serial timeout + if (timeout) { + return true; + } + return false; } // Return the current MNO profile // Returns -1 if the serial port is not yet setup or the number of the current // MNO profile setting from the modem. int Challenger2040LTEClass::getMNOProfile() { - if (!serialPortConfigured) - return -1; - SARA_SERIAL_PORT.println(F("AT+UMNOPROF?")); - String resp = getResponse(); - return resp.substring(resp.indexOf("+UMNOPROF: ") + 11).toInt(); + if (!serialPortConfigured) { + return -1; + } + SARA_SERIAL_PORT.println(F("AT+UMNOPROF?")); + String resp = getResponse(); + return resp.substring(resp.indexOf("+UMNOPROF: ") + 11).toInt(); } // Set a new MNO profile // Returns false if the serial port is not yet setup bool Challenger2040LTEClass::setMNOProfile(int profile) { - if (!serialPortConfigured) - return false; - String cmd = "AT+UMNOPROF=" + String(profile) + ",1"; - SARA_SERIAL_PORT.println(cmd); - - if (!getResponse().endsWith("OK")) { - return false; - } - return true; + if (!serialPortConfigured) { + return false; + } + String cmd = "AT+UMNOPROF=" + String(profile) + ",1"; + SARA_SERIAL_PORT.println(cmd); + + if (!getResponse().endsWith("OK")) { + return false; + } + return true; } // Disable power save features bool Challenger2040LTEClass::enablePS(bool enable) { - if (!serialPortConfigured) - return false; - if (enable) - SARA_SERIAL_PORT.println(F("AT+CPSMS=1")); - else - SARA_SERIAL_PORT.println(F("AT+CPSMS=0")); - - if (!getResponse().endsWith("OK")) { - return false; - } - return true; + if (!serialPortConfigured) { + return false; + } + if (enable) { + SARA_SERIAL_PORT.println(F("AT+CPSMS=1")); + } else { + SARA_SERIAL_PORT.println(F("AT+CPSMS=0")); + } + + if (!getResponse().endsWith("OK")) { + return false; + } + return true; } // Get a response from SARA @@ -116,18 +123,19 @@ bool Challenger2040LTEClass::enablePS(bool enable) { // from control characters and appended with a tab character as a separator. // String Challenger2040LTEClass::getResponse(int timeout) { - SARA_SERIAL_PORT.setTimeout(2000); // allow for really slow responses + SARA_SERIAL_PORT.setTimeout(2000); // allow for really slow responses - String resp = SARA_SERIAL_PORT.readStringUntil('\n'); - resp.trim(); - String acc = resp; - while(resp.indexOf("OK") == -1 && resp.indexOf("ERROR") == -1 && --timeout) { - resp = SARA_SERIAL_PORT.readStringUntil('\n'); + String resp = SARA_SERIAL_PORT.readStringUntil('\n'); resp.trim(); - if (resp.length()) - acc += "\t" + resp; - } - return acc; + String acc = resp; + while (resp.indexOf("OK") == -1 && resp.indexOf("ERROR") == -1 && --timeout) { + resp = SARA_SERIAL_PORT.readStringUntil('\n'); + resp.trim(); + if (resp.length()) { + acc += "\t" + resp; + } + } + return acc; } Challenger2040LTEClass Challenger2040LTE; diff --git a/variants/challenger_2040_lte/ChallengerLTE.h b/variants/challenger_2040_lte/ChallengerLTE.h index 34069cfff..2b5fd2104 100644 --- a/variants/challenger_2040_lte/ChallengerLTE.h +++ b/variants/challenger_2040_lte/ChallengerLTE.h @@ -22,7 +22,7 @@ #define DEFAULT_SARA_BAUDRATE 115200 class Challenger2040LTEClass { - public: +public: Challenger2040LTEClass(); bool doPowerOn(); bool isAlive(uint32_t timeout = 50); @@ -31,7 +31,7 @@ class Challenger2040LTEClass { bool enablePS(bool enable = true); String getResponse(int timeout = 5); - private: +private: bool serialPortConfigured; }; diff --git a/variants/challenger_2040_lte/pins_arduino.h b/variants/challenger_2040_lte/pins_arduino.h index 12378307b..9920787db 100644 --- a/variants/challenger_2040_lte/pins_arduino.h +++ b/variants/challenger_2040_lte/pins_arduino.h @@ -49,28 +49,28 @@ #define LED_BUILTIN PIN_LED -static const uint8_t D0 = (16u); -static const uint8_t D1 = (17u); -static const uint8_t D2 = (24u); -static const uint8_t D3 = (23u); -static const uint8_t D4 = (22u); -static const uint8_t D5 = (2u); -static const uint8_t D6 = (3u); -static const uint8_t D7 = (0u); -static const uint8_t D8 = (1u); -static const uint8_t D9 = (12u); -static const uint8_t D10 = (11u); -static const uint8_t D11 = (10u); -static const uint8_t D12 = (9u); -static const uint8_t D13 = (8u); -static const uint8_t D14 = (13u); -static const uint8_t D15 = (14u); -static const uint8_t D16 = (15u); -static const uint8_t D17 = (19u); +static const uint8_t D0 = (16u); +static const uint8_t D1 = (17u); +static const uint8_t D2 = (24u); +static const uint8_t D3 = (23u); +static const uint8_t D4 = (22u); +static const uint8_t D5 = (2u); +static const uint8_t D6 = (3u); +static const uint8_t D7 = (0u); +static const uint8_t D8 = (1u); +static const uint8_t D9 = (12u); +static const uint8_t D10 = (11u); +static const uint8_t D11 = (10u); +static const uint8_t D12 = (9u); +static const uint8_t D13 = (8u); +static const uint8_t D14 = (13u); +static const uint8_t D15 = (14u); +static const uint8_t D16 = (15u); +static const uint8_t D17 = (19u); -static const uint8_t A0 = (29u); -static const uint8_t A1 = (28u); -static const uint8_t A2 = (27u); -static const uint8_t A3 = (26u); -static const uint8_t A4 = (25u); -static const uint8_t A5 = (21u); +static const uint8_t A0 = (29u); +static const uint8_t A1 = (28u); +static const uint8_t A2 = (27u); +static const uint8_t A3 = (26u); +static const uint8_t A4 = (25u); +static const uint8_t A5 = (21u); diff --git a/variants/challenger_2040_nfc/board_init.cpp b/variants/challenger_2040_nfc/board_init.cpp new file mode 100644 index 000000000..2411b5c94 --- /dev/null +++ b/variants/challenger_2040_nfc/board_init.cpp @@ -0,0 +1,34 @@ +/* + Board init for the Challenger RP2040 NFC + + Copyright (c) 2022 P. Oldberg + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ +#include + +/** + Setup control pins for the NFC chip. +*/ +void initVariant() { + // Initialize the interrupt pin to be an input. + // Setting it to an interrupt and connecting a call back is up to the app. + pinMode(PIN_PN7150_IRQ_B, INPUT); + + // Initialize the reset pin to an output and hold the device in reset. + // It is up to the application to release it. + pinMode(PIN_PN7150_RST_B, OUTPUT); + digitalWrite(PIN_PN7150_RST_B, LOW); +} diff --git a/variants/challenger_2040_nfc/pins_arduino.h b/variants/challenger_2040_nfc/pins_arduino.h new file mode 100644 index 000000000..20e9dc525 --- /dev/null +++ b/variants/challenger_2040_nfc/pins_arduino.h @@ -0,0 +1,67 @@ +#pragma once + +#define PINS_COUNT (26u) +#define NUM_DIGITAL_PINS (26u) +#define NUM_ANALOG_INPUTS (4u) +#define NUM_ANALOG_OUTPUTS (0u) +#define ADC_RESOLUTION (12u) + +// LEDs +#define PIN_LED (24u) +#define NEOPIXEL (14u) +#define PIN_NEOPIXEL NEOPIXEL + +// Serial +#define PIN_SERIAL1_TX (16u) +#define PIN_SERIAL1_RX (17u) + +// SPI +#define PIN_SPI0_MISO (20u) +#define PIN_SPI0_MOSI (23u) +#define PIN_SPI0_SCK (22u) +#define PIN_SPI0_SS (21u) + +// Wire +#define PIN_WIRE0_SDA (0u) +#define PIN_WIRE0_SCL (1u) + +// Connected to PN7150 NFC controller on I2C channel 2 +#define PIN_WIRE1_SDA (10u) +#define PIN_WIRE1_SCL (11u) +#define PIN_PN7150_IRQ_B (9u) +#define PIN_PN7150_RST_B (12u) +#define PN7150_I2C_ADDR (0x28) + +// Not pinned out +#define PIN_SERIAL2_RX (31u) +#define PIN_SERIAL2_TX (31u) + +#define SERIAL_HOWMANY (1u) +#define SPI_HOWMANY (1u) +#define WIRE_HOWMANY (2u) + +#define LED_BUILTIN PIN_LED + +static const uint8_t D0 = (16u); +static const uint8_t D1 = (17u); +static const uint8_t D2 = (20u); +static const uint8_t D3 = (23u); +static const uint8_t D4 = (22u); +static const uint8_t D5 = (2u); +static const uint8_t D6 = (3u); +static const uint8_t D7 = (0u); +static const uint8_t D8 = (1u); +static const uint8_t D9 = (4u); +static const uint8_t D10 = (5u); +static const uint8_t D11 = (6u); +static const uint8_t D12 = (7u); +static const uint8_t D13 = (8u); +static const uint8_t D14 = (13u); +static const uint8_t D18 = (24u); + +static const uint8_t A0 = (26u); +static const uint8_t A1 = (27u); +static const uint8_t A2 = (28u); +static const uint8_t A3 = (29u); +static const uint8_t A4 = (19u); +static const uint8_t A5 = (21u); diff --git a/variants/challenger_2040_sdrtc/pins_arduino.h b/variants/challenger_2040_sdrtc/pins_arduino.h index e289ee888..e5bcb2cec 100644 --- a/variants/challenger_2040_sdrtc/pins_arduino.h +++ b/variants/challenger_2040_sdrtc/pins_arduino.h @@ -48,26 +48,26 @@ #define LED_BUILTIN PIN_LED -static const uint8_t D0 = (16u); -static const uint8_t D1 = (17u); -static const uint8_t D2 = (20u); -static const uint8_t D3 = (23u); -static const uint8_t D4 = (22u); -static const uint8_t D5 = (2u); -static const uint8_t D6 = (3u); -static const uint8_t D7 = (0u); -static const uint8_t D8 = (1u); -static const uint8_t D9 = (4u); -static const uint8_t D10 = (5u); -static const uint8_t D11 = (6u); -static const uint8_t D12 = (7u); -static const uint8_t D13 = (8u); -static const uint8_t D14 = (13u); -static const uint8_t D18 = (24u); +static const uint8_t D0 = (16u); +static const uint8_t D1 = (17u); +static const uint8_t D2 = (20u); +static const uint8_t D3 = (23u); +static const uint8_t D4 = (22u); +static const uint8_t D5 = (2u); +static const uint8_t D6 = (3u); +static const uint8_t D7 = (0u); +static const uint8_t D8 = (1u); +static const uint8_t D9 = (4u); +static const uint8_t D10 = (5u); +static const uint8_t D11 = (6u); +static const uint8_t D12 = (7u); +static const uint8_t D13 = (8u); +static const uint8_t D14 = (13u); +static const uint8_t D18 = (24u); -static const uint8_t A0 = (26u); -static const uint8_t A1 = (27u); -static const uint8_t A2 = (28u); -static const uint8_t A3 = (29u); -static const uint8_t A4 = (19u); -static const uint8_t A5 = (21u); +static const uint8_t A0 = (26u); +static const uint8_t A1 = (27u); +static const uint8_t A2 = (28u); +static const uint8_t A3 = (29u); +static const uint8_t A4 = (19u); +static const uint8_t A5 = (21u); diff --git a/variants/challenger_2040_subghz/pins_arduino.h b/variants/challenger_2040_subghz/pins_arduino.h index 8e50938bc..e2632e462 100644 --- a/variants/challenger_2040_subghz/pins_arduino.h +++ b/variants/challenger_2040_subghz/pins_arduino.h @@ -47,20 +47,20 @@ #define LED_BUILTIN PIN_LED -static const uint8_t D0 = (16u); -static const uint8_t D1 = (17u); -static const uint8_t D2 = (20u); -static const uint8_t D3 = (23u); -static const uint8_t D4 = (22u); -static const uint8_t D5 = (2u); -static const uint8_t D6 = (3u); -static const uint8_t D7 = (0u); -static const uint8_t D8 = (1u); -static const uint8_t D9 = (4u); -static const uint8_t D10 = (5u); -static const uint8_t D11 = (6u); -static const uint8_t D12 = (7u); -static const uint8_t D13 = (8u); +static const uint8_t D0 = (16u); +static const uint8_t D1 = (17u); +static const uint8_t D2 = (20u); +static const uint8_t D3 = (23u); +static const uint8_t D4 = (22u); +static const uint8_t D5 = (2u); +static const uint8_t D6 = (3u); +static const uint8_t D7 = (0u); +static const uint8_t D8 = (1u); +static const uint8_t D9 = (4u); +static const uint8_t D10 = (5u); +static const uint8_t D11 = (6u); +static const uint8_t D12 = (7u); +static const uint8_t D13 = (8u); static const uint8_t D14 = (13u); static const uint8_t D15 = (14u); static const uint8_t D16 = (15u); diff --git a/variants/challenger_2040_uwb/pins_arduino.h b/variants/challenger_2040_uwb/pins_arduino.h new file mode 100644 index 000000000..e9e8c749b --- /dev/null +++ b/variants/challenger_2040_uwb/pins_arduino.h @@ -0,0 +1,74 @@ +#pragma once + +#define PINS_COUNT (25u) +#define NUM_DIGITAL_PINS (25u) +#define NUM_ANALOG_INPUTS (4u) +#define NUM_ANALOG_OUTPUTS (0u) +#define ADC_RESOLUTION (12u) + +// LEDs +#define PIN_LED (24u) + +// Serial +#define PIN_SERIAL1_TX (16u) +#define PIN_SERIAL1_RX (17u) + +// SPI +#define PIN_SPI0_MISO (20u) +#define PIN_SPI0_MOSI (23u) +#define PIN_SPI0_SCK (22u) +#define PIN_SPI0_SS (21u) + +// Connected to DWM3000 module +#define PIN_SPI1_MISO (12u) +#define PIN_SPI1_MOSI (11u) +#define PIN_SPI1_SCK (10u) +#define PIN_SPI1_SS (9u) +#define DWM3000_SS PIN_SPI1_SS +#define DWM3000_RST (13u) +#define DWM3000_IRQ (14u) +#define DWM3000_WAKEUP (15u) +#define DWM3000_SPI SPI1 + +// Wire +#define PIN_WIRE0_SDA (0u) +#define PIN_WIRE0_SCL (1u) + +// Not pinned out +#define PIN_WIRE1_SDA (31u) +#define PIN_WIRE1_SCL (31u) +#define PIN_SERIAL2_RX (31u) +#define PIN_SERIAL2_TX (31u) + +#define SERIAL_HOWMANY (1u) +#define SPI_HOWMANY (2u) +#define WIRE_HOWMANY (1u) + +#define LED_BUILTIN PIN_LED + +static const uint8_t D0 = (16u); +static const uint8_t D1 = (17u); +static const uint8_t D2 = (20u); +static const uint8_t D3 = (23u); +static const uint8_t D4 = (22u); +static const uint8_t D5 = (2u); +static const uint8_t D6 = (3u); +static const uint8_t D7 = (0u); +static const uint8_t D8 = (1u); +static const uint8_t D9 = (4u); +static const uint8_t D10 = (5u); +static const uint8_t D11 = (6u); +static const uint8_t D12 = (7u); +static const uint8_t D13 = (8u); +static const uint8_t D14 = (13u); +static const uint8_t D15 = (14u); +static const uint8_t D16 = (15u); +static const uint8_t D17 = (18u); +static const uint8_t D18 = (24u); + +static const uint8_t A0 = (26u); +static const uint8_t A1 = (27u); +static const uint8_t A2 = (28u); +static const uint8_t A3 = (29u); +static const uint8_t A4 = (19u); +static const uint8_t A5 = (21u); diff --git a/variants/challenger_2040_wifi/ChallengerWiFi.cpp b/variants/challenger_2040_wifi/ChallengerWiFi.cpp index 0ac6737d0..6bd537474 100644 --- a/variants/challenger_2040_wifi/ChallengerWiFi.cpp +++ b/variants/challenger_2040_wifi/ChallengerWiFi.cpp @@ -22,75 +22,77 @@ #include Challenger2040WiFiClass::Challenger2040WiFiClass(HardwareSerial* serial) { - _serial = serial; + _serial = serial; - pinMode(PIN_ESP_RST, OUTPUT); - digitalWrite(PIN_ESP_RST, LOW); // Hold ESP in reset - pinMode(PIN_ESP_MODE, OUTPUT); - digitalWrite(PIN_ESP_MODE, HIGH); // Prepare for normal start + pinMode(PIN_ESP_RST, OUTPUT); + digitalWrite(PIN_ESP_RST, LOW); // Hold ESP in reset + pinMode(PIN_ESP_MODE, OUTPUT); + digitalWrite(PIN_ESP_MODE, HIGH); // Prepare for normal start } // Do a HW reset by applying a low pulse to the reset line for 1mSec void Challenger2040WiFiClass::doHWReset() { - digitalWrite(PIN_ESP_RST, LOW); // Hold ESP in reset - delay(1); - digitalWrite(PIN_ESP_RST, HIGH); // Release ESP reset + digitalWrite(PIN_ESP_RST, LOW); // Hold ESP in reset + delay(1); + digitalWrite(PIN_ESP_RST, HIGH); // Release ESP reset } // Set the mode flag high to indicate normal run operation and do a HW // reset. void Challenger2040WiFiClass::runReset() { // Prepare ESP for normal op - digitalWrite(PIN_ESP_MODE, HIGH); // Prepare for normal start - doHWReset(); + digitalWrite(PIN_ESP_MODE, HIGH); // Prepare for normal start + doHWReset(); } // Set the mode flag low to indicate flash operation and do a HW // reset. void Challenger2040WiFiClass::flashReset() { // Prepare ESP for flashing - digitalWrite(PIN_ESP_MODE, LOW); // Prepare for normal start - doHWReset(); + digitalWrite(PIN_ESP_MODE, LOW); // Prepare for normal start + doHWReset(); } // Wait for the modem to reply with a "ready" prompt. This can be done // after a sw or hw reset have been performed to ensure that the AT // interpreter is up and running. bool Challenger2040WiFiClass::waitForReady() { - int timeout = 20; // Aprox max 2 sec - - _serial->setTimeout(100); - String rdy = _serial->readStringUntil('\n'); - while(!rdy.startsWith("ready") && timeout--) { - rdy = _serial->readStringUntil('\n'); - } - _serial->setTimeout(1000); // Reset default timeout to 1000 - if (timeout) - return true; - return false; + int timeout = 20; // Aprox max 2 sec + + _serial->setTimeout(100); + String rdy = _serial->readStringUntil('\n'); + while (!rdy.startsWith("ready") && timeout--) { + rdy = _serial->readStringUntil('\n'); + } + _serial->setTimeout(1000); // Reset default timeout to 1000 + if (timeout) { + return true; + } + return false; } // Reset the ESP and wait for the "ready" prompt to be returned. bool Challenger2040WiFiClass::reset() { - runReset(); - _serial->begin(DEFAULT_ESP_BAUDRATE); - return waitForReady(); + runReset(); + _serial->begin(DEFAULT_ESP_BAUDRATE); + return waitForReady(); } // Checks to see if the modem responds to the "AT" poll command. bool Challenger2040WiFiClass::isAlive() { - int timeout = 100; + int timeout = 100; - _serial->setTimeout(250); - _serial->println(F("AT")); - String rdy = _serial->readStringUntil('\n'); - while(!rdy.startsWith(F("OK")) && timeout--) { + _serial->setTimeout(250); _serial->println(F("AT")); - rdy = _serial->readStringUntil('\n'); - } - _serial->setTimeout(1000); - - if (timeout) - return true; - return false; + String rdy = _serial->readStringUntil('\n'); + while (!rdy.startsWith(F("OK")) && timeout--) { + _serial->println(F("AT")); + rdy = _serial->readStringUntil('\n'); + } + _serial->setTimeout(1000); + + if (timeout) { + return true; + } + return false; } // Change the baud rate of the ESP device as well as the local UART. @@ -98,19 +100,19 @@ bool Challenger2040WiFiClass::isAlive() { // baud rates are valid. The function ends by checking if the ESP is // reachable by doing an "AT" poll. bool Challenger2040WiFiClass::changeBaudRate(int baud) { - _serial->print(F("AT+UART_CUR=")); - _serial->print(baud); - _serial->println(F(",8,1,0,0")); - delay(100); - _serial->end(); - _serial->begin(baud); - return isAlive(); + _serial->print(F("AT+UART_CUR=")); + _serial->print(baud); + _serial->println(F(",8,1,0,0")); + delay(100); + _serial->end(); + _serial->begin(baud); + return isAlive(); } // This method should be called id the builtin object isn't needed any more // It basically just releases the UART pins for other use. void Challenger2040WiFiClass::release() { - _serial->end(); + _serial->end(); } // We can assign a new hardware serial port to accommodate the ESP device here. @@ -121,18 +123,18 @@ void Challenger2040WiFiClass::release() { // with the ESP instead of the built in hardware serial port. void Challenger2040WiFiClass::setSerial(HardwareSerial* serial) { - release(); - _serial = serial; + release(); + _serial = serial; - pinMode(PIN_ESP_RST, OUTPUT); - digitalWrite(PIN_ESP_RST, LOW); // Hold ESP in reset - pinMode(PIN_ESP_MODE, OUTPUT); - digitalWrite(PIN_ESP_MODE, HIGH); // Prepare for normal start + pinMode(PIN_ESP_RST, OUTPUT); + digitalWrite(PIN_ESP_RST, LOW); // Hold ESP in reset + pinMode(PIN_ESP_MODE, OUTPUT); + digitalWrite(PIN_ESP_MODE, HIGH); // Prepare for normal start } // Return the current serial object HardwareSerial* Challenger2040WiFiClass::getSerial() { - return _serial; + return _serial; } Challenger2040WiFiClass Challenger2040WiFi; diff --git a/variants/challenger_2040_wifi/ChallengerWiFi.h b/variants/challenger_2040_wifi/ChallengerWiFi.h index 0a38c49de..1a16ba030 100644 --- a/variants/challenger_2040_wifi/ChallengerWiFi.h +++ b/variants/challenger_2040_wifi/ChallengerWiFi.h @@ -24,7 +24,7 @@ #define DEFAULT_ESP_BAUDRATE DEFAULT_ESP8285_BAUDRATE class Challenger2040WiFiClass { - public: +public: Challenger2040WiFiClass(HardwareSerial* = &ESP_SERIAL_PORT); void doHWReset(); void runReset(); @@ -36,7 +36,7 @@ class Challenger2040WiFiClass { void release(); void setSerial(HardwareSerial*); HardwareSerial* getSerial(); - private: +private: HardwareSerial* _serial; }; diff --git a/variants/challenger_2040_wifi/board_init.cpp b/variants/challenger_2040_wifi/board_init.cpp index 4edff342c..e536b89d3 100644 --- a/variants/challenger_2040_wifi/board_init.cpp +++ b/variants/challenger_2040_wifi/board_init.cpp @@ -21,9 +21,9 @@ #include /** - * Just make sure we try to reset the ESP device before the user starts - * using the device. - */ + Just make sure we try to reset the ESP device before the user starts + using the device. +*/ void initVariant() { - Challenger2040WiFi.reset(); + Challenger2040WiFi.reset(); } diff --git a/variants/challenger_2040_wifi/pins_arduino.h b/variants/challenger_2040_wifi/pins_arduino.h index d04f2d606..d77fdba9b 100644 --- a/variants/challenger_2040_wifi/pins_arduino.h +++ b/variants/challenger_2040_wifi/pins_arduino.h @@ -53,19 +53,19 @@ #define LED_BUILTIN PIN_LED #define NEOPIXEL (11u) -static const uint8_t D0 = (16u); -static const uint8_t D1 = (17u); -static const uint8_t D2 = (24u); -static const uint8_t D3 = (23u); -static const uint8_t D4 = (22u); -static const uint8_t D5 = (2u); -static const uint8_t D6 = (3u); -static const uint8_t D7 = (0u); -static const uint8_t D8 = (1u); -static const uint8_t D9 = (6u); -static const uint8_t D10 = (7u); -static const uint8_t D11 = (8u); -static const uint8_t D12 = (9u); +static const uint8_t D0 = (16u); +static const uint8_t D1 = (17u); +static const uint8_t D2 = (24u); +static const uint8_t D3 = (23u); +static const uint8_t D4 = (22u); +static const uint8_t D5 = (2u); +static const uint8_t D6 = (3u); +static const uint8_t D7 = (0u); +static const uint8_t D8 = (1u); +static const uint8_t D9 = (6u); +static const uint8_t D10 = (7u); +static const uint8_t D11 = (8u); +static const uint8_t D12 = (9u); static const uint8_t D13 = (10u); static const uint8_t D14 = (11u); static const uint8_t D15 = (12u); diff --git a/variants/challenger_2040_wifi_ble/ChallengerWiFi.cpp b/variants/challenger_2040_wifi_ble/ChallengerWiFi.cpp index 0ac6737d0..6bd537474 100644 --- a/variants/challenger_2040_wifi_ble/ChallengerWiFi.cpp +++ b/variants/challenger_2040_wifi_ble/ChallengerWiFi.cpp @@ -22,75 +22,77 @@ #include Challenger2040WiFiClass::Challenger2040WiFiClass(HardwareSerial* serial) { - _serial = serial; + _serial = serial; - pinMode(PIN_ESP_RST, OUTPUT); - digitalWrite(PIN_ESP_RST, LOW); // Hold ESP in reset - pinMode(PIN_ESP_MODE, OUTPUT); - digitalWrite(PIN_ESP_MODE, HIGH); // Prepare for normal start + pinMode(PIN_ESP_RST, OUTPUT); + digitalWrite(PIN_ESP_RST, LOW); // Hold ESP in reset + pinMode(PIN_ESP_MODE, OUTPUT); + digitalWrite(PIN_ESP_MODE, HIGH); // Prepare for normal start } // Do a HW reset by applying a low pulse to the reset line for 1mSec void Challenger2040WiFiClass::doHWReset() { - digitalWrite(PIN_ESP_RST, LOW); // Hold ESP in reset - delay(1); - digitalWrite(PIN_ESP_RST, HIGH); // Release ESP reset + digitalWrite(PIN_ESP_RST, LOW); // Hold ESP in reset + delay(1); + digitalWrite(PIN_ESP_RST, HIGH); // Release ESP reset } // Set the mode flag high to indicate normal run operation and do a HW // reset. void Challenger2040WiFiClass::runReset() { // Prepare ESP for normal op - digitalWrite(PIN_ESP_MODE, HIGH); // Prepare for normal start - doHWReset(); + digitalWrite(PIN_ESP_MODE, HIGH); // Prepare for normal start + doHWReset(); } // Set the mode flag low to indicate flash operation and do a HW // reset. void Challenger2040WiFiClass::flashReset() { // Prepare ESP for flashing - digitalWrite(PIN_ESP_MODE, LOW); // Prepare for normal start - doHWReset(); + digitalWrite(PIN_ESP_MODE, LOW); // Prepare for normal start + doHWReset(); } // Wait for the modem to reply with a "ready" prompt. This can be done // after a sw or hw reset have been performed to ensure that the AT // interpreter is up and running. bool Challenger2040WiFiClass::waitForReady() { - int timeout = 20; // Aprox max 2 sec - - _serial->setTimeout(100); - String rdy = _serial->readStringUntil('\n'); - while(!rdy.startsWith("ready") && timeout--) { - rdy = _serial->readStringUntil('\n'); - } - _serial->setTimeout(1000); // Reset default timeout to 1000 - if (timeout) - return true; - return false; + int timeout = 20; // Aprox max 2 sec + + _serial->setTimeout(100); + String rdy = _serial->readStringUntil('\n'); + while (!rdy.startsWith("ready") && timeout--) { + rdy = _serial->readStringUntil('\n'); + } + _serial->setTimeout(1000); // Reset default timeout to 1000 + if (timeout) { + return true; + } + return false; } // Reset the ESP and wait for the "ready" prompt to be returned. bool Challenger2040WiFiClass::reset() { - runReset(); - _serial->begin(DEFAULT_ESP_BAUDRATE); - return waitForReady(); + runReset(); + _serial->begin(DEFAULT_ESP_BAUDRATE); + return waitForReady(); } // Checks to see if the modem responds to the "AT" poll command. bool Challenger2040WiFiClass::isAlive() { - int timeout = 100; + int timeout = 100; - _serial->setTimeout(250); - _serial->println(F("AT")); - String rdy = _serial->readStringUntil('\n'); - while(!rdy.startsWith(F("OK")) && timeout--) { + _serial->setTimeout(250); _serial->println(F("AT")); - rdy = _serial->readStringUntil('\n'); - } - _serial->setTimeout(1000); - - if (timeout) - return true; - return false; + String rdy = _serial->readStringUntil('\n'); + while (!rdy.startsWith(F("OK")) && timeout--) { + _serial->println(F("AT")); + rdy = _serial->readStringUntil('\n'); + } + _serial->setTimeout(1000); + + if (timeout) { + return true; + } + return false; } // Change the baud rate of the ESP device as well as the local UART. @@ -98,19 +100,19 @@ bool Challenger2040WiFiClass::isAlive() { // baud rates are valid. The function ends by checking if the ESP is // reachable by doing an "AT" poll. bool Challenger2040WiFiClass::changeBaudRate(int baud) { - _serial->print(F("AT+UART_CUR=")); - _serial->print(baud); - _serial->println(F(",8,1,0,0")); - delay(100); - _serial->end(); - _serial->begin(baud); - return isAlive(); + _serial->print(F("AT+UART_CUR=")); + _serial->print(baud); + _serial->println(F(",8,1,0,0")); + delay(100); + _serial->end(); + _serial->begin(baud); + return isAlive(); } // This method should be called id the builtin object isn't needed any more // It basically just releases the UART pins for other use. void Challenger2040WiFiClass::release() { - _serial->end(); + _serial->end(); } // We can assign a new hardware serial port to accommodate the ESP device here. @@ -121,18 +123,18 @@ void Challenger2040WiFiClass::release() { // with the ESP instead of the built in hardware serial port. void Challenger2040WiFiClass::setSerial(HardwareSerial* serial) { - release(); - _serial = serial; + release(); + _serial = serial; - pinMode(PIN_ESP_RST, OUTPUT); - digitalWrite(PIN_ESP_RST, LOW); // Hold ESP in reset - pinMode(PIN_ESP_MODE, OUTPUT); - digitalWrite(PIN_ESP_MODE, HIGH); // Prepare for normal start + pinMode(PIN_ESP_RST, OUTPUT); + digitalWrite(PIN_ESP_RST, LOW); // Hold ESP in reset + pinMode(PIN_ESP_MODE, OUTPUT); + digitalWrite(PIN_ESP_MODE, HIGH); // Prepare for normal start } // Return the current serial object HardwareSerial* Challenger2040WiFiClass::getSerial() { - return _serial; + return _serial; } Challenger2040WiFiClass Challenger2040WiFi; diff --git a/variants/challenger_2040_wifi_ble/ChallengerWiFi.h b/variants/challenger_2040_wifi_ble/ChallengerWiFi.h index f008b7f7e..692907059 100644 --- a/variants/challenger_2040_wifi_ble/ChallengerWiFi.h +++ b/variants/challenger_2040_wifi_ble/ChallengerWiFi.h @@ -24,7 +24,7 @@ #define DEFAULT_ESP_BAUDRATE DEFAULT_ESP32_BAUDRATE class Challenger2040WiFiClass { - public: +public: Challenger2040WiFiClass(HardwareSerial* = &ESP_SERIAL_PORT); void doHWReset(); void runReset(); @@ -36,7 +36,7 @@ class Challenger2040WiFiClass { void release(); void setSerial(HardwareSerial*); HardwareSerial* getSerial(); - private: +private: HardwareSerial* _serial; }; diff --git a/variants/challenger_2040_wifi_ble/board_init.cpp b/variants/challenger_2040_wifi_ble/board_init.cpp index 4edff342c..e536b89d3 100644 --- a/variants/challenger_2040_wifi_ble/board_init.cpp +++ b/variants/challenger_2040_wifi_ble/board_init.cpp @@ -21,9 +21,9 @@ #include /** - * Just make sure we try to reset the ESP device before the user starts - * using the device. - */ + Just make sure we try to reset the ESP device before the user starts + using the device. +*/ void initVariant() { - Challenger2040WiFi.reset(); + Challenger2040WiFi.reset(); } diff --git a/variants/challenger_2040_wifi_ble/pins_arduino.h b/variants/challenger_2040_wifi_ble/pins_arduino.h index a8977d05e..c5c2d5b69 100644 --- a/variants/challenger_2040_wifi_ble/pins_arduino.h +++ b/variants/challenger_2040_wifi_ble/pins_arduino.h @@ -56,19 +56,19 @@ #define LED_BUILTIN PIN_LED #define NEOPIXEL (11u) -static const uint8_t D0 = (16u); -static const uint8_t D1 = (17u); -static const uint8_t D2 = (20u); -static const uint8_t D3 = (23u); -static const uint8_t D4 = (22u); -static const uint8_t D5 = (2u); -static const uint8_t D6 = (3u); -static const uint8_t D7 = (0u); -static const uint8_t D8 = (1u); -static const uint8_t D9 = (6u); -static const uint8_t D10 = (7u); -static const uint8_t D11 = (8u); -static const uint8_t D12 = (9u); +static const uint8_t D0 = (16u); +static const uint8_t D1 = (17u); +static const uint8_t D2 = (20u); +static const uint8_t D3 = (23u); +static const uint8_t D4 = (22u); +static const uint8_t D5 = (2u); +static const uint8_t D6 = (3u); +static const uint8_t D7 = (0u); +static const uint8_t D8 = (1u); +static const uint8_t D9 = (6u); +static const uint8_t D10 = (7u); +static const uint8_t D11 = (8u); +static const uint8_t D12 = (9u); static const uint8_t D13 = (10u); static const uint8_t D14 = (11u); static const uint8_t D15 = (12u); diff --git a/variants/challenger_nb_2040_wifi/ChallengerWiFi.cpp b/variants/challenger_nb_2040_wifi/ChallengerWiFi.cpp index 0ac6737d0..6bd537474 100644 --- a/variants/challenger_nb_2040_wifi/ChallengerWiFi.cpp +++ b/variants/challenger_nb_2040_wifi/ChallengerWiFi.cpp @@ -22,75 +22,77 @@ #include Challenger2040WiFiClass::Challenger2040WiFiClass(HardwareSerial* serial) { - _serial = serial; + _serial = serial; - pinMode(PIN_ESP_RST, OUTPUT); - digitalWrite(PIN_ESP_RST, LOW); // Hold ESP in reset - pinMode(PIN_ESP_MODE, OUTPUT); - digitalWrite(PIN_ESP_MODE, HIGH); // Prepare for normal start + pinMode(PIN_ESP_RST, OUTPUT); + digitalWrite(PIN_ESP_RST, LOW); // Hold ESP in reset + pinMode(PIN_ESP_MODE, OUTPUT); + digitalWrite(PIN_ESP_MODE, HIGH); // Prepare for normal start } // Do a HW reset by applying a low pulse to the reset line for 1mSec void Challenger2040WiFiClass::doHWReset() { - digitalWrite(PIN_ESP_RST, LOW); // Hold ESP in reset - delay(1); - digitalWrite(PIN_ESP_RST, HIGH); // Release ESP reset + digitalWrite(PIN_ESP_RST, LOW); // Hold ESP in reset + delay(1); + digitalWrite(PIN_ESP_RST, HIGH); // Release ESP reset } // Set the mode flag high to indicate normal run operation and do a HW // reset. void Challenger2040WiFiClass::runReset() { // Prepare ESP for normal op - digitalWrite(PIN_ESP_MODE, HIGH); // Prepare for normal start - doHWReset(); + digitalWrite(PIN_ESP_MODE, HIGH); // Prepare for normal start + doHWReset(); } // Set the mode flag low to indicate flash operation and do a HW // reset. void Challenger2040WiFiClass::flashReset() { // Prepare ESP for flashing - digitalWrite(PIN_ESP_MODE, LOW); // Prepare for normal start - doHWReset(); + digitalWrite(PIN_ESP_MODE, LOW); // Prepare for normal start + doHWReset(); } // Wait for the modem to reply with a "ready" prompt. This can be done // after a sw or hw reset have been performed to ensure that the AT // interpreter is up and running. bool Challenger2040WiFiClass::waitForReady() { - int timeout = 20; // Aprox max 2 sec - - _serial->setTimeout(100); - String rdy = _serial->readStringUntil('\n'); - while(!rdy.startsWith("ready") && timeout--) { - rdy = _serial->readStringUntil('\n'); - } - _serial->setTimeout(1000); // Reset default timeout to 1000 - if (timeout) - return true; - return false; + int timeout = 20; // Aprox max 2 sec + + _serial->setTimeout(100); + String rdy = _serial->readStringUntil('\n'); + while (!rdy.startsWith("ready") && timeout--) { + rdy = _serial->readStringUntil('\n'); + } + _serial->setTimeout(1000); // Reset default timeout to 1000 + if (timeout) { + return true; + } + return false; } // Reset the ESP and wait for the "ready" prompt to be returned. bool Challenger2040WiFiClass::reset() { - runReset(); - _serial->begin(DEFAULT_ESP_BAUDRATE); - return waitForReady(); + runReset(); + _serial->begin(DEFAULT_ESP_BAUDRATE); + return waitForReady(); } // Checks to see if the modem responds to the "AT" poll command. bool Challenger2040WiFiClass::isAlive() { - int timeout = 100; + int timeout = 100; - _serial->setTimeout(250); - _serial->println(F("AT")); - String rdy = _serial->readStringUntil('\n'); - while(!rdy.startsWith(F("OK")) && timeout--) { + _serial->setTimeout(250); _serial->println(F("AT")); - rdy = _serial->readStringUntil('\n'); - } - _serial->setTimeout(1000); - - if (timeout) - return true; - return false; + String rdy = _serial->readStringUntil('\n'); + while (!rdy.startsWith(F("OK")) && timeout--) { + _serial->println(F("AT")); + rdy = _serial->readStringUntil('\n'); + } + _serial->setTimeout(1000); + + if (timeout) { + return true; + } + return false; } // Change the baud rate of the ESP device as well as the local UART. @@ -98,19 +100,19 @@ bool Challenger2040WiFiClass::isAlive() { // baud rates are valid. The function ends by checking if the ESP is // reachable by doing an "AT" poll. bool Challenger2040WiFiClass::changeBaudRate(int baud) { - _serial->print(F("AT+UART_CUR=")); - _serial->print(baud); - _serial->println(F(",8,1,0,0")); - delay(100); - _serial->end(); - _serial->begin(baud); - return isAlive(); + _serial->print(F("AT+UART_CUR=")); + _serial->print(baud); + _serial->println(F(",8,1,0,0")); + delay(100); + _serial->end(); + _serial->begin(baud); + return isAlive(); } // This method should be called id the builtin object isn't needed any more // It basically just releases the UART pins for other use. void Challenger2040WiFiClass::release() { - _serial->end(); + _serial->end(); } // We can assign a new hardware serial port to accommodate the ESP device here. @@ -121,18 +123,18 @@ void Challenger2040WiFiClass::release() { // with the ESP instead of the built in hardware serial port. void Challenger2040WiFiClass::setSerial(HardwareSerial* serial) { - release(); - _serial = serial; + release(); + _serial = serial; - pinMode(PIN_ESP_RST, OUTPUT); - digitalWrite(PIN_ESP_RST, LOW); // Hold ESP in reset - pinMode(PIN_ESP_MODE, OUTPUT); - digitalWrite(PIN_ESP_MODE, HIGH); // Prepare for normal start + pinMode(PIN_ESP_RST, OUTPUT); + digitalWrite(PIN_ESP_RST, LOW); // Hold ESP in reset + pinMode(PIN_ESP_MODE, OUTPUT); + digitalWrite(PIN_ESP_MODE, HIGH); // Prepare for normal start } // Return the current serial object HardwareSerial* Challenger2040WiFiClass::getSerial() { - return _serial; + return _serial; } Challenger2040WiFiClass Challenger2040WiFi; diff --git a/variants/challenger_nb_2040_wifi/ChallengerWiFi.h b/variants/challenger_nb_2040_wifi/ChallengerWiFi.h index 0a38c49de..1a16ba030 100644 --- a/variants/challenger_nb_2040_wifi/ChallengerWiFi.h +++ b/variants/challenger_nb_2040_wifi/ChallengerWiFi.h @@ -24,7 +24,7 @@ #define DEFAULT_ESP_BAUDRATE DEFAULT_ESP8285_BAUDRATE class Challenger2040WiFiClass { - public: +public: Challenger2040WiFiClass(HardwareSerial* = &ESP_SERIAL_PORT); void doHWReset(); void runReset(); @@ -36,7 +36,7 @@ class Challenger2040WiFiClass { void release(); void setSerial(HardwareSerial*); HardwareSerial* getSerial(); - private: +private: HardwareSerial* _serial; }; diff --git a/variants/challenger_nb_2040_wifi/board_init.cpp b/variants/challenger_nb_2040_wifi/board_init.cpp index 4edff342c..e536b89d3 100644 --- a/variants/challenger_nb_2040_wifi/board_init.cpp +++ b/variants/challenger_nb_2040_wifi/board_init.cpp @@ -21,9 +21,9 @@ #include /** - * Just make sure we try to reset the ESP device before the user starts - * using the device. - */ + Just make sure we try to reset the ESP device before the user starts + using the device. +*/ void initVariant() { - Challenger2040WiFi.reset(); + Challenger2040WiFi.reset(); } diff --git a/variants/challenger_nb_2040_wifi/pins_arduino.h b/variants/challenger_nb_2040_wifi/pins_arduino.h index 2eed41fc1..5af17ae54 100644 --- a/variants/challenger_nb_2040_wifi/pins_arduino.h +++ b/variants/challenger_nb_2040_wifi/pins_arduino.h @@ -53,19 +53,19 @@ #define LED_BUILTIN PIN_LED #define NEOPIXEL (11u) -static const uint8_t D0 = (16u); -static const uint8_t D1 = (17u); -static const uint8_t D2 = (24u); -static const uint8_t D3 = (23u); -static const uint8_t D4 = (22u); -static const uint8_t D5 = (2u); -static const uint8_t D6 = (3u); -static const uint8_t D7 = (0u); -static const uint8_t D8 = (1u); -static const uint8_t D9 = (6u); -static const uint8_t D10 = (7u); -static const uint8_t D11 = (8u); -static const uint8_t D12 = (9u); +static const uint8_t D0 = (16u); +static const uint8_t D1 = (17u); +static const uint8_t D2 = (24u); +static const uint8_t D3 = (23u); +static const uint8_t D4 = (22u); +static const uint8_t D5 = (2u); +static const uint8_t D6 = (3u); +static const uint8_t D7 = (0u); +static const uint8_t D8 = (1u); +static const uint8_t D9 = (6u); +static const uint8_t D10 = (7u); +static const uint8_t D11 = (8u); +static const uint8_t D12 = (9u); static const uint8_t D13 = (10u); static const uint8_t D14 = (14u); static const uint8_t D15 = (15u); diff --git a/variants/cytron_maker_pi_rp2040/pins_arduino.h b/variants/cytron_maker_pi_rp2040/pins_arduino.h index b6b509343..92e3e16da 100644 --- a/variants/cytron_maker_pi_rp2040/pins_arduino.h +++ b/variants/cytron_maker_pi_rp2040/pins_arduino.h @@ -36,10 +36,10 @@ #define PIN_SPI0_SCK (31u) #define PIN_SPI0_SS (31u) -#define PIN_SPI1_MISO (31u) -#define PIN_SPI1_MOSI (31u) -#define PIN_SPI1_SCK (31u) -#define PIN_SPI1_SS (31u) +#define PIN_SPI1_MISO (11u) +#define PIN_SPI1_MOSI (12u) +#define PIN_SPI1_SCK (10u) +#define PIN_SPI1_SS (15u) // Wire #define PIN_WIRE0_SDA (16u) @@ -48,10 +48,8 @@ #define PIN_WIRE1_SDA (2u) #define PIN_WIRE1_SCL (3u) - - #define SERIAL_HOWMANY (2u) -#define SPI_HOWMANY (0u) +#define SPI_HOWMANY (2u) #define WIRE_HOWMANY (2u) #include "../generic/common.h" diff --git a/variants/datanoisetv_picoadk/pins_arduino.h b/variants/datanoisetv_picoadk/pins_arduino.h new file mode 100644 index 000000000..5de92afc0 --- /dev/null +++ b/variants/datanoisetv_picoadk/pins_arduino.h @@ -0,0 +1,51 @@ +#pragma once + +// DatanoiseTV PicoADK+ - Audio Development Kit +// Pin definitions taken from: +// https://github.com/DatanoiseTV/PicoDSP-Hardware + +// LEDs +#define PIN_LED (15u) + +// Debug LEDs near the USB connector +#define PIN_LED0 (2u) +#define PIN_LED1 (3u) +#define PIN_LED2 (4u) +#define PIN_LED3 (5u) + +// Serial +#define PIN_SERIAL1_TX (0u) +#define PIN_SERIAL1_RX (1u) + +#define PIN_SERIAL2_TX (8u) +#define PIN_SERIAL2_RX (9u) + +// SPI0 +#define PIN_SPI0_MISO (16u) +#define PIN_SPI0_MOSI (19u) +#define PIN_SPI0_SCK (18u) +#define PIN_SPI0_SS (17u) + +// SPI1 +#define PIN_SPI1_MISO (12u) +#define PIN_SPI1_MOSI (11u) +#define PIN_SPI1_SCK (10u) +#define PIN_SPI1_SS (13u) + +// Wire +#define PIN_WIRE0_SDA (8u) +#define PIN_WIRE0_SCL (9u) + +#define PIN_WIRE1_SDA (6u) +#define PIN_WIRE1_SCL (7u) + +// I2S +#define PIN_I2S_BCLK (17u) +#define PIN_I2S_LRCLK (18u) +#define PIN_I2S_DOUT (16u) + +#define SERIAL_HOWMANY (3u) +#define SPI_HOWMANY (2u) +#define WIRE_HOWMANY (2u) + +#include "../generic/common.h" diff --git a/variants/dfrobot_beetle_rp2040/pins_arduino.h b/variants/dfrobot_beetle_rp2040/pins_arduino.h index 6aa7305a7..d8f7f1f05 100644 --- a/variants/dfrobot_beetle_rp2040/pins_arduino.h +++ b/variants/dfrobot_beetle_rp2040/pins_arduino.h @@ -16,7 +16,7 @@ #define PIN_SERIAL2_RX (5u) // SPI -#define PIN_SPI0_MISO (0u) +#define PIN_SPI0_MISO (0u) #define PIN_SPI0_MOSI (3u) #define PIN_SPI0_SCK (2u) #define PIN_SPI0_SS (1u) @@ -28,8 +28,8 @@ #define PIN_SPI1_SS (31u) // Wire -#define PIN_WIRE0_SDA (4u) -#define PIN_WIRE0_SCL (5u) +#define PIN_WIRE0_SDA (4u) +#define PIN_WIRE0_SCL (5u) #define PIN_WIRE1_SDA (2u) #define PIN_WIRE1_SCL (3u) diff --git a/variants/extelec_rc2040/pins_arduino.h b/variants/extelec_rc2040/pins_arduino.h new file mode 100644 index 000000000..65107f0e4 --- /dev/null +++ b/variants/extelec_rc2040/pins_arduino.h @@ -0,0 +1,57 @@ +#pragma once + +// LEDs +#define PIN_LED (25u) + +// Serial +#define PIN_SERIAL1_TX (0u) +#define PIN_SERIAL1_RX (1u) + +// ATTENTION -> USED by SPI0 +#define PIN_SERIAL2_TX (4u) +#define PIN_SERIAL2_RX (5u) + +// SPI +#define PIN_SPI0_MISO (4u) +#define PIN_SPI0_MOSI (3u) +#define PIN_SPI0_SCK (2u) +#define PIN_SPI0_SS (5u) + +// ATTENTION -> USED by ROM_SELECT Jumpers +#define PIN_SPI1_MISO (12u) +#define PIN_SPI1_MOSI (11u) +#define PIN_SPI1_SCK (10u) +#define PIN_SPI1_SS (13u) + +// ATTENTION -> USED by SPI0 +// Wire +#define PIN_WIRE0_SDA (4u) +#define PIN_WIRE0_SCL (5u) + +#define SERIAL_HOWMANY (3u) +#define SPI_HOWMANY (2u) +#define WIRE_HOWMANY (1u) + +#include "../generic/common.h" + +// GPIO 0 UART_TX_PIN 0 +// GPIO 1 UART_RX_PIN 1 +// GPIO 2 SPI SCK +// GOIO 3 SPI MOSI +// GPIO 4 SPI MISO +// GPIO 5 SPI CS/SS + +// GPIO 6 Free(?) + +// GPIO 7 RESET_BUTTON + +// GPIO 8 Free(?) + +// GPIO 9 DUMP_BUTTON +// GPIO 10 ROM_A13 +// GPIO 11 ROM_A14 +// GPIO 12 ROM_A15 +// GPIO 13 SELSEL +// GPIO 14 SOUNDIO_1 +// GPIO 15 SOUNDIO_2 +// GPIO 22 HAS_SWITCHES_IO (former SD Card Detect) diff --git a/variants/flyboard2040_core/pins_arduino.h b/variants/flyboard2040_core/pins_arduino.h index e451e85ad..800e00eb1 100644 --- a/variants/flyboard2040_core/pins_arduino.h +++ b/variants/flyboard2040_core/pins_arduino.h @@ -27,8 +27,8 @@ #define PIN_SPI1_SS (13u) // Wire -#define PIN_WIRE0_SDA (6u) -#define PIN_WIRE0_SCL (7u) +#define PIN_WIRE0_SDA (16u) +#define PIN_WIRE0_SCL (17u) #define PIN_WIRE1_SDA (14u) #define PIN_WIRE1_SCL (15u) diff --git a/variants/generic/common.h b/variants/generic/common.h index 19741cb85..f757bca93 100644 --- a/variants/generic/common.h +++ b/variants/generic/common.h @@ -6,7 +6,9 @@ #define NUM_ANALOG_OUTPUTS (0u) #define ADC_RESOLUTION (12u) +#ifdef PIN_LED #define LED_BUILTIN PIN_LED +#endif static const uint8_t D0 = (0u); static const uint8_t D1 = (1u); @@ -40,27 +42,27 @@ static const uint8_t D28 = (28u); static const uint8_t D29 = (29u); #ifdef __PIN_A0 - static const uint8_t A0 = __PIN_A0; +static const uint8_t A0 = __PIN_A0; #else - static const uint8_t A0 = (26u); +static const uint8_t A0 = (26u); #endif #ifdef __PIN_A1 - static const uint8_t A1 = __PIN_A1; +static const uint8_t A1 = __PIN_A1; #else - static const uint8_t A1 = (27u); +static const uint8_t A1 = (27u); #endif #ifdef __PIN_A2 - static const uint8_t A2 = __PIN_A2; +static const uint8_t A2 = __PIN_A2; #else - static const uint8_t A2 = (28u); +static const uint8_t A2 = (28u); #endif #ifdef __PIN_A3 - static const uint8_t A3 = __PIN_A3; +static const uint8_t A3 = __PIN_A3; #else - static const uint8_t A3 = (29u); +static const uint8_t A3 = (29u); #endif static const uint8_t SS = PIN_SPI0_SS; diff --git a/variants/ilabs_rpico32/Ilabs2040WiFiClass.cpp b/variants/ilabs_rpico32/Ilabs2040WiFiClass.cpp index 1adbec72f..0433cd756 100644 --- a/variants/ilabs_rpico32/Ilabs2040WiFiClass.cpp +++ b/variants/ilabs_rpico32/Ilabs2040WiFiClass.cpp @@ -22,72 +22,74 @@ #include Ilabs2040WiFiClass::Ilabs2040WiFiClass() { - pinMode(PIN_ESP_RESET, OUTPUT); - digitalWrite(PIN_ESP_RESET, LOW); // Hold ESP8285 in reset - pinMode(PIN_ESP_MODE, OUTPUT); - digitalWrite(PIN_ESP_MODE, HIGH); // Prepare for normal start + pinMode(PIN_ESP_RESET, OUTPUT); + digitalWrite(PIN_ESP_RESET, LOW); // Hold ESP8285 in reset + pinMode(PIN_ESP_MODE, OUTPUT); + digitalWrite(PIN_ESP_MODE, HIGH); // Prepare for normal start } // Do a HW reset by applying a low pulse to the reset line for 1mSec void Ilabs2040WiFiClass::doHWReset() { - digitalWrite(PIN_ESP_RESET, LOW); // Hold ESP8285 in reset - delay(1); - digitalWrite(PIN_ESP_RESET, HIGH); // Release ESP8285 reset + digitalWrite(PIN_ESP_RESET, LOW); // Hold ESP8285 in reset + delay(1); + digitalWrite(PIN_ESP_RESET, HIGH); // Release ESP8285 reset } // Set the mode flag high to indicate normal run operation and do a HW // reset. void Ilabs2040WiFiClass::runReset() { // Prepare ESP8285 for normal op - digitalWrite(PIN_ESP_MODE, HIGH); // Prepare for normal start - doHWReset(); + digitalWrite(PIN_ESP_MODE, HIGH); // Prepare for normal start + doHWReset(); } // Set the mode flag low to indicate flash operation and do a HW // reset. void Ilabs2040WiFiClass::flashReset() { // Prepare ESP8285 for flashing - digitalWrite(PIN_ESP_MODE, LOW); // Prepare for normal start - doHWReset(); + digitalWrite(PIN_ESP_MODE, LOW); // Prepare for normal start + doHWReset(); } // Wait for the modem to reply with a "ready" prompt. This can be done // after a sw or hw reset have been performed to ensure that the AT // interpreter is up and running. bool Ilabs2040WiFiClass::waitForReady() { - int timeout = 20; // Aprox max 2 sec - - ESP_SERIAL_PORT.begin(DEFAULT_ESP8285_BAUDRATE); - ESP_SERIAL_PORT.setTimeout(100); - String rdy = ESP_SERIAL_PORT.readStringUntil('\n'); - while(!rdy.startsWith("ready") && timeout--) { - rdy = ESP_SERIAL_PORT.readStringUntil('\n'); - } - ESP_SERIAL_PORT.setTimeout(1000); // Reset default timeout to 1000 - if (timeout) - return true; - return false; + int timeout = 20; // Aprox max 2 sec + + ESP_SERIAL_PORT.begin(DEFAULT_ESP8285_BAUDRATE); + ESP_SERIAL_PORT.setTimeout(100); + String rdy = ESP_SERIAL_PORT.readStringUntil('\n'); + while (!rdy.startsWith("ready") && timeout--) { + rdy = ESP_SERIAL_PORT.readStringUntil('\n'); + } + ESP_SERIAL_PORT.setTimeout(1000); // Reset default timeout to 1000 + if (timeout) { + return true; + } + return false; } // Reset the ESP8285 and wait for the "ready" prompt to be returned. bool Ilabs2040WiFiClass::reset() { - runReset(); - return waitForReady(); + runReset(); + return waitForReady(); } // Checks to see if the modem responds to the "AT" poll command. bool Ilabs2040WiFiClass::isAlive() { - int timeout = 5; - - ESP_SERIAL_PORT.setTimeout(250); - ESP_SERIAL_PORT.println(F("AT")); - String rdy = ESP_SERIAL_PORT.readStringUntil('\n'); - while(!rdy.startsWith(F("OK")) && timeout--) { - rdy = ESP_SERIAL_PORT.readStringUntil('\n'); - } - ESP_SERIAL_PORT.setTimeout(1000); - - if (timeout) - return true; - return false; + int timeout = 5; + + ESP_SERIAL_PORT.setTimeout(250); + ESP_SERIAL_PORT.println(F("AT")); + String rdy = ESP_SERIAL_PORT.readStringUntil('\n'); + while (!rdy.startsWith(F("OK")) && timeout--) { + rdy = ESP_SERIAL_PORT.readStringUntil('\n'); + } + ESP_SERIAL_PORT.setTimeout(1000); + + if (timeout) { + return true; + } + return false; } // Change the baud rate of the ESP8285 as well as the local UART. @@ -95,13 +97,13 @@ bool Ilabs2040WiFiClass::isAlive() { // baud rates are valid. The function ends by checking if the ESP8285 is // reachable by doing an "AT" poll. bool Ilabs2040WiFiClass::changeBaudRate(int baud) { - ESP_SERIAL_PORT.print(F("AT+UART_CUR=")); - ESP_SERIAL_PORT.print(baud); - ESP_SERIAL_PORT.println(F(",8,1,0,0")); - delay(100); - ESP_SERIAL_PORT.end(); - ESP_SERIAL_PORT.begin(baud); - return isAlive(); + ESP_SERIAL_PORT.print(F("AT+UART_CUR=")); + ESP_SERIAL_PORT.print(baud); + ESP_SERIAL_PORT.println(F(",8,1,0,0")); + delay(100); + ESP_SERIAL_PORT.end(); + ESP_SERIAL_PORT.begin(baud); + return isAlive(); } Ilabs2040WiFiClass Ilabs2040WiFi; diff --git a/variants/ilabs_rpico32/Ilabs2040WiFiClass.h b/variants/ilabs_rpico32/Ilabs2040WiFiClass.h index 1a0fe0912..7ca702c5e 100644 --- a/variants/ilabs_rpico32/Ilabs2040WiFiClass.h +++ b/variants/ilabs_rpico32/Ilabs2040WiFiClass.h @@ -22,7 +22,7 @@ #define DEFAULT_ESP8285_BAUDRATE 115200 class Ilabs2040WiFiClass { - public: +public: Ilabs2040WiFiClass(); void doHWReset(); void runReset(); diff --git a/variants/melopero_cookie_rp2040/pins_arduino.h b/variants/melopero_cookie_rp2040/pins_arduino.h new file mode 100644 index 000000000..3e2098208 --- /dev/null +++ b/variants/melopero_cookie_rp2040/pins_arduino.h @@ -0,0 +1,40 @@ +#pragma once + +// Pin definitions taken from: +// https://datasheets.raspberrypi.org/pico/pico-datasheet.pdf + + +// LEDs +#define PIN_LED (21u) + +// Serial +#define PIN_SERIAL1_TX (0u) +#define PIN_SERIAL1_RX (1u) + +//Serial 2 not pinned out +#define PIN_SERIAL2_TX (31u) +#define PIN_SERIAL2_RX (31u) + +// SPI +#define PIN_SPI0_MISO (20u) +#define PIN_SPI0_MOSI (19u) +#define PIN_SPI0_SCK (18u) +#define PIN_SPI0_SS (1u) + +#define PIN_SPI1_MISO (28u) +#define PIN_SPI1_MOSI (27u) +#define PIN_SPI1_SCK (26u) +#define PIN_SPI1_SS (29u) + +// Wire +#define PIN_WIRE0_SDA (12u) +#define PIN_WIRE0_SCL (13u) + +#define PIN_WIRE1_SDA (2u) +#define PIN_WIRE1_SCL (3u) + +#define SERIAL_HOWMANY (3u) +#define SPI_HOWMANY (2u) +#define WIRE_HOWMANY (2u) + +#include "../generic/common.h" diff --git a/variants/melopero_shake_rp2040/pins_arduino.h b/variants/melopero_shake_rp2040/pins_arduino.h index ba104e30d..be2c47503 100644 --- a/variants/melopero_shake_rp2040/pins_arduino.h +++ b/variants/melopero_shake_rp2040/pins_arduino.h @@ -26,10 +26,10 @@ #define PIN_SPI1_SS (13u) // Wire -#define PIN_WIRE0_SDA (8u) +#define PIN_WIRE0_SDA (8u) #define PIN_WIRE0_SCL (9u) -#define PIN_WIRE1_SDA (2u) +#define PIN_WIRE1_SDA (2u) #define PIN_WIRE1_SCL (3u) #define SERIAL_HOWMANY (3u) diff --git a/variants/nekosystems_bl2040_mini/pins_arduino.h b/variants/nekosystems_bl2040_mini/pins_arduino.h new file mode 100644 index 000000000..6ba2c865e --- /dev/null +++ b/variants/nekosystems_bl2040_mini/pins_arduino.h @@ -0,0 +1,69 @@ +#pragma once + +// MOTOR CONTROL SECTION: +// SimpleFOC Flags +#define SIMPLEFOC_PWM_HIGHSIDE_ACTIVE_HIGH true +#define SIMPLEFOC_PWM_LOWSIDE_ACTIVE_HIGH false + +// Important Constants +#define CURR_SENSE_RES (0.001f) +#define CURR_SENSE_GAIN (66.0f) + +// Power Stage Control Pins +#define PIN_PWMH_A (0u) +#define PIN_PWML_A (1u) +#define PIN_PWMH_B (2u) +#define PIN_PWML_B (3u) +#define PIN_PWMH_C (4u) +#define PIN_PWML_C (5u) + +// Hall-Effect Angle Sensor Pins +#define PIN_HALL_RX (16u) +#define PIN_HALL_CS (17u) +#define PIN_HALL_SCK (18u) + +// Current Sensing Pins +#define PIN_IOUT_A (26u) // Analog Input +#define PIN_IOUT_B (27u) // Analog Input + +// Power Supply Feedback Pins +#define PIN_VBUS_DET (7u) // Digital Input +#define PIN_VCC_SENSE (28u) // Analog Input + + +// STANDARD SECTION: +// LED +#define PIN_LED (6u) + +// Serial +#define PIN_SERIAL1_TX (12u) +#define PIN_SERIAL1_RX (13u) + +#define PIN_SERIAL2_TX (20u) +#define PIN_SERIAL2_RX (21u) + +// NOTE: SPI0 is used by the on-board magnetic angle sensor, +// do not change the pins assigned to this SPI object! +// SPI +#define PIN_SPI0_MISO (16u) +#define PIN_SPI0_MOSI (19u) +#define PIN_SPI0_SCK (18u) +#define PIN_SPI0_SS (17u) + +#define PIN_SPI1_MISO (8u) +#define PIN_SPI1_MOSI (11u) +#define PIN_SPI1_SCK (10u) +#define PIN_SPI1_SS (9u) + +// Wire +#define PIN_WIRE0_SDA (24u) +#define PIN_WIRE0_SCL (25u) + +#define PIN_WIRE1_SDA (22u) +#define PIN_WIRE1_SCL (23u) + +#define SERIAL_HOWMANY (3u) +#define SPI_HOWMANY (2u) +#define WIRE_HOWMANY (2u) + +#include "../generic/common.h" diff --git a/variants/nullbits_bit_c_pro/pins_arduino.h b/variants/nullbits_bit_c_pro/pins_arduino.h new file mode 100644 index 000000000..bcfa3e145 --- /dev/null +++ b/variants/nullbits_bit_c_pro/pins_arduino.h @@ -0,0 +1,37 @@ +#pragma once + +// Taken from pinout at https://nullbits.co/static/img/BIt-C_PRO_pinout.png + +// LEDs +#define PIN_LED (18u) + +// UARTs +#define PIN_SERIAL1_TX (0u) +#define PIN_SERIAL1_RX (1u) + +#define PIN_SERIAL2_TX (8u) +#define PIN_SERIAL2_RX (9u) + +// SPI +#define PIN_SPI0_MISO (20u) +#define PIN_SPI0_MOSI (23u) +#define PIN_SPI0_SCK (22u) +#define PIN_SPI0_SS (21u) + +#define PIN_SPI1_MISO (12u) +#define PIN_SPI1_MOSI (11u) +#define PIN_SPI1_SCK (14u) +#define PIN_SPI1_SS (13u) + +// Wire +#define PIN_WIRE0_SDA (2u) +#define PIN_WIRE0_SCL (3u) + +#define PIN_WIRE1_SDA (4u) +#define PIN_WIRE1_SCL (5u) + +#define SERIAL_HOWMANY (3u) +#define SPI_HOWMANY (2u) +#define WIRE_HOWMANY (2u) + +#include "../generic/common.h" diff --git a/variants/pimoroni_pga2040/pins_arduino.h b/variants/pimoroni_pga2040/pins_arduino.h new file mode 100644 index 000000000..f6c61e39c --- /dev/null +++ b/variants/pimoroni_pga2040/pins_arduino.h @@ -0,0 +1,5 @@ +#pragma once + +// This is a bare board with no real predefined pins, so use generic + +#include "../generic/pins_arduino.h" diff --git a/variants/rpipicow/picow_digital.cpp b/variants/rpipicow/picow_digital.cpp index 29b989208..468791162 100644 --- a/variants/rpipicow/picow_digital.cpp +++ b/variants/rpipicow/picow_digital.cpp @@ -24,7 +24,12 @@ extern "C" void __pinMode(pin_size_t pin, PinMode mode); extern "C" void __digitalWrite(pin_size_t pin, PinStatus val); extern "C" PinStatus __digitalRead(pin_size_t pin); +extern bool __isPicoW; + extern "C" void pinMode(pin_size_t pin, PinMode mode) { + if (!__isPicoW && (pin == PIN_LED)) { + pin = 25; // Silently swap in the Pico's LED + } if (pin < 32) { __pinMode(pin, mode); } else { @@ -33,6 +38,9 @@ extern "C" void pinMode(pin_size_t pin, PinMode mode) { } extern "C" void digitalWrite(pin_size_t pin, PinStatus val) { + if (!__isPicoW && (pin == PIN_LED)) { + pin = 25; // Silently swap in the Pico's LED + } if (pin < 32) { __digitalWrite(pin, val); } else { @@ -41,6 +49,9 @@ extern "C" void digitalWrite(pin_size_t pin, PinStatus val) { } extern "C" PinStatus digitalRead(pin_size_t pin) { + if (!__isPicoW && (pin == PIN_LED)) { + pin = 25; // Silently swap in the Pico's LED + } if (pin < 32) { return __digitalRead(pin); } else { diff --git a/variants/rpipicow/picow_init.cpp b/variants/rpipicow/picow_init.cpp index aa6199c44..b3d7ce3bb 100644 --- a/variants/rpipicow/picow_init.cpp +++ b/variants/rpipicow/picow_init.cpp @@ -19,7 +19,49 @@ */ #include +#include +#include "hardware/resets.h" +#include "hardware/gpio.h" +#include "hardware/adc.h" + +#ifndef WIFICC +#define WIFICC CYW43_COUNTRY_WORLDWIDE +#endif + +// Taken from https://datasheets.raspberrypi.com/picow/connecting-to-the-internet-with-pico-w.pdf +// also discussion in https://github.com/earlephilhower/arduino-pico/issues/849 +static bool CheckPicoW() { + adc_init(); + auto dir = gpio_get_dir(29); + auto fnc = gpio_get_function(29); + adc_gpio_init(29); + adc_select_input(3); + auto adc29 = adc_read(); + gpio_set_function(29, fnc); + gpio_set_dir(29, dir); + + dir = gpio_get_dir(25); + fnc = gpio_get_function(25); + gpio_init(25); + gpio_set_dir(25, GPIO_IN); + auto gp25 = gpio_get(25); + gpio_set_function(25, fnc); + gpio_set_dir(25, dir); + + if (gp25) { + return true; // Can't tell, so assume yes + } else if (adc29 < 200) { + return true; // PicoW + } else { + return false; + } +} + +bool __isPicoW = true; extern "C" void initVariant() { - cyw43_arch_init(); + __isPicoW = CheckPicoW(); + if (__isPicoW) { + cyw43_arch_init_with_country(WIFICC); + } } diff --git a/variants/rpipicow/pins_arduino.h b/variants/rpipicow/pins_arduino.h index 430ea6dda..efcf4cc6b 100644 --- a/variants/rpipicow/pins_arduino.h +++ b/variants/rpipicow/pins_arduino.h @@ -3,6 +3,7 @@ // Pin definitions taken from: // https://datasheets.raspberrypi.org/pico/pico-datasheet.pdf +extern bool __isPicoW; // LEDs #define PIN_LED (32u) diff --git a/variants/seeed_indicator_rp2040/pins_arduino.h b/variants/seeed_indicator_rp2040/pins_arduino.h new file mode 100644 index 000000000..b204d9640 --- /dev/null +++ b/variants/seeed_indicator_rp2040/pins_arduino.h @@ -0,0 +1,33 @@ +#pragma once + + +// Serial +#define PIN_SERIAL1_TX (16u) +#define PIN_SERIAL1_RX (17u) + +#define PIN_SERIAL2_TX (8u) +#define PIN_SERIAL2_RX (9u) + +// SPI +#define PIN_SPI0_MISO (0u) +#define PIN_SPI0_MOSI (3u) +#define PIN_SPI0_SCK (2u) +#define PIN_SPI0_SS (1u) + +#define PIN_SPI1_MISO (12u) +#define PIN_SPI1_MOSI (11u) +#define PIN_SPI1_SCK (10u) +#define PIN_SPI1_SS (13u) + +// Wire +#define PIN_WIRE0_SDA (20u) +#define PIN_WIRE0_SCL (21u) + +#define PIN_WIRE1_SDA (14u) +#define PIN_WIRE1_SCL (15u) + +#define SERIAL_HOWMANY (3u) +#define SPI_HOWMANY (2u) +#define WIRE_HOWMANY (2u) + +#include "../generic/common.h" diff --git a/variants/vccgnd_yd_rp2040/pins_arduino.h b/variants/vccgnd_yd_rp2040/pins_arduino.h new file mode 100644 index 000000000..3911e61f1 --- /dev/null +++ b/variants/vccgnd_yd_rp2040/pins_arduino.h @@ -0,0 +1,41 @@ +#pragma once + +// Pin definitions taken from: +// https://user-images.githubusercontent.com/57373245/211920388-d339f085-840d-433d-a575-590ace58219c.png + + +// LEDs +#define PIN_NEOPIXEL (23u) +#define PIN_USRKEY (24u) +#define PIN_LED (25u) + +// Serial +#define PIN_SERIAL1_TX (0u) +#define PIN_SERIAL1_RX (1u) + +#define PIN_SERIAL2_TX (8u) +#define PIN_SERIAL2_RX (9u) + +// SPI +#define PIN_SPI0_MISO (16u) +#define PIN_SPI0_MOSI (19u) +#define PIN_SPI0_SCK (18u) +#define PIN_SPI0_SS (17u) + +#define PIN_SPI1_MISO (12u) +#define PIN_SPI1_MOSI (15u) +#define PIN_SPI1_SCK (14u) +#define PIN_SPI1_SS (13u) + +// Wire +#define PIN_WIRE0_SDA (4u) +#define PIN_WIRE0_SCL (5u) + +#define PIN_WIRE1_SDA (26u) +#define PIN_WIRE1_SCL (27u) + +#define SERIAL_HOWMANY (3u) +#define SPI_HOWMANY (2u) +#define WIRE_HOWMANY (2u) + +#include "../generic/common.h" diff --git a/variants/viyalab_mizu/pins_arduino.h b/variants/viyalab_mizu/pins_arduino.h new file mode 100644 index 000000000..abc732ea8 --- /dev/null +++ b/variants/viyalab_mizu/pins_arduino.h @@ -0,0 +1,39 @@ +#pragma once + +// Pin definitions taken from: +// https://datasheets.raspberrypi.org/pico/pico-datasheet.pdf + + +// LEDs +#define PIN_LED (25u) + +// Serial +#define PIN_SERIAL1_TX (0u) +#define PIN_SERIAL1_RX (1u) + +#define PIN_SERIAL2_TX (8u) +#define PIN_SERIAL2_RX (9u) + +// SPI +#define PIN_SPI0_MISO (16u) +#define PIN_SPI0_MOSI (7u) +#define PIN_SPI0_SCK (6u) +#define PIN_SPI0_SS (17u) + +#define PIN_SPI1_MISO (12u) +#define PIN_SPI1_MOSI (11u) +#define PIN_SPI1_SCK (10u) +#define PIN_SPI1_SS (13u) + +// Wire +#define PIN_WIRE0_SDA (4u) +#define PIN_WIRE0_SCL (5u) + +#define PIN_WIRE1_SDA (2u) +#define PIN_WIRE1_SCL (3u) + +#define SERIAL_HOWMANY (3u) +#define SPI_HOWMANY (2u) +#define WIRE_HOWMANY (2u) + +#include "../generic/common.h" diff --git a/variants/waveshare_rp2040_lcd_0_96/pins_arduino.h b/variants/waveshare_rp2040_lcd_0_96/pins_arduino.h new file mode 100644 index 000000000..0b88e454f --- /dev/null +++ b/variants/waveshare_rp2040_lcd_0_96/pins_arduino.h @@ -0,0 +1,78 @@ +#pragma once + +// Waveshare RP2040 lcd 0.96 +// https://www.waveshare.com/wiki/RP2040-LCD-0.96 +// https://www.waveshare.com/w/upload/0/01/RP2040-LCD-0.96.pdf +// https://www.waveshare.com/img/devkit/RP2040-LCD-0.96/RP2040-LCD-0.96-details-7.jpg +// + +/* + Pin# Pin# + ___(_____)___ + GPIO0 1 | *USB C* | 40 VBUS + GPIO1 2 | | 39 VSYS + GND 3 | | 38 GND + GPIO2 4 | | 37 3V3_EN + GPIO3 5 | | 36 3V3(OUT) + GPIO4 6 | | 35 ADC_VREF + GPIO5 7 | | 34 GPIO28 + GND 8 | | 33 GND + GPIO6 9 | | 32 GPIO27 + GPIO7 10 | | 31 GPIO26 + GPIO8 11 | | 30 RUN + GPIO9 12 | | 29 GPIO22 + GND 13 | | 28 GND + GPIO10 14 | | 27 GPIO21 + GPIO11 15 | | 25 GPIO20 + GPIO12 16 | | 25 GPIO19 + GPIO13 17 | | 24 GPIO18 + GND 18 | | 23 GND + GPIO14 19 | | 22 GPIO17 + GPIO15 20 |____|_|_|____| 21 GPIO16 + S G S + W N W + C D D + L I + K N +*/ + +// LCD +#define LDC_SPI (1u) +#define PIN_LCD_DC (8u) +#define PIN_LCD_CS (9u) +#define PIN_LCD_SCLK (10u) +#define PIN_LCD_MOSI (11u) +#define PIN_LCD_RST (12u) +#define PIN_LCD_BL (25u) + +// Serial +#define PIN_SERIAL1_TX (0u) +#define PIN_SERIAL1_RX (1u) + +#define PIN_SERIAL2_TX (8u) +#define PIN_SERIAL2_RX (9u) + +// SPI +#define PIN_SPI0_MISO (16u) +#define PIN_SPI0_MOSI (19u) +#define PIN_SPI0_SCK (18u) +#define PIN_SPI0_SS (17u) + +#define PIN_SPI1_MISO (12u) +#define PIN_SPI1_MOSI (15u) +#define PIN_SPI1_SCK (14u) +#define PIN_SPI1_SS (13u) + +// Wire +#define PIN_WIRE0_SDA (8u) +#define PIN_WIRE0_SCL (9u) + +#define PIN_WIRE1_SDA (6u) +#define PIN_WIRE1_SCL (7u) + +#define SERIAL_HOWMANY (3u) +#define SPI_HOWMANY (2u) +#define WIRE_HOWMANY (2u) + +#include "../generic/common.h" + diff --git a/variants/waveshare_rp2040_lcd_1_28/pins_arduino.h b/variants/waveshare_rp2040_lcd_1_28/pins_arduino.h new file mode 100644 index 000000000..282ed1d69 --- /dev/null +++ b/variants/waveshare_rp2040_lcd_1_28/pins_arduino.h @@ -0,0 +1,70 @@ +#pragma once + +// Waveshare RP2040 LCD 1.28 +// https://www.waveshare.com/wiki/RP2040-LCD-1.28 +// https://www.waveshare.com/w/upload/6/60/RP2040-LCD-1.28-sch.pdf +// https://www.waveshare.com/img/devkit/RP2040-LCD-1.28/RP2040-LCD-1.28-details-3.jpg +// + +/* + H1 H2 + Pin# Pin# Pin# Pin# + GPIO8 1 2 GPIO0 GND 1 2 GND + GPIO9 3 4 GPIO1 VSYS 3 4 ADC_AVDD + GPIO10 5 6 GPIO2 GPIO23 5 6 BOOT + GPIO11 7 8 GPIO3 GPIO22 7 8 RUM + GPIO12 9 10 GPIO4 GPIO21 9 10 GPIO29 + GPIO13 11 12 GPIO5 GPIO20 11 12 GPIO28 + GPIO14 13 14 GPIO6 GPIO19 13 14 GPIO27 + GPIO15 15 16 GPIO7 GPIO18 15 16 GPIO26 + SWCLK 17 18 VSYS GPIO17 17 18 GPIO25 + SWDIP 19 20 GND GPIO16 19 20 GPIO24 +*/ + +// LCD +#define LDC_SPI (1u) +#define PIN_LCD_DC (8u) +#define PIN_LCD_CS (9u) +#define PIN_LCD_SCLK (10u) +#define PIN_LCD_MOSI (11u) +#define PIN_LCD_RST (12u) +#define PIN_LCD_BL (25u) +// BAT_ADC +#define PIN_BAT_ADC (29u) +// IMU +#define PIN_IMU_SDA (6u) +#define PIN_IMU_SCL (7u) +#define PIN_IMU_INT1 (23u) +#define PIN_IMU_INT2 (24u) + +// Serial +#define PIN_SERIAL1_TX (0u) +#define PIN_SERIAL1_RX (1u) + +#define PIN_SERIAL2_TX (8u) +#define PIN_SERIAL2_RX (9u) + +// SPI +#define PIN_SPI0_MISO (16u) +#define PIN_SPI0_MOSI (19u) +#define PIN_SPI0_SCK (18u) +#define PIN_SPI0_SS (17u) + +#define PIN_SPI1_MISO (12u) +#define PIN_SPI1_MOSI (15u) +#define PIN_SPI1_SCK (14u) +#define PIN_SPI1_SS (13u) + +// Wire +#define PIN_WIRE0_SDA (8u) +#define PIN_WIRE0_SCL (9u) + +#define PIN_WIRE1_SDA (6u) +#define PIN_WIRE1_SCL (7u) + +#define SERIAL_HOWMANY (3u) +#define SPI_HOWMANY (2u) +#define WIRE_HOWMANY (2u) + +#include "../generic/common.h" + diff --git a/variants/waveshare_rp2040_one/pins_arduino.h b/variants/waveshare_rp2040_one/pins_arduino.h new file mode 100644 index 000000000..bf2bbc7a4 --- /dev/null +++ b/variants/waveshare_rp2040_one/pins_arduino.h @@ -0,0 +1,65 @@ +#pragma once + +// Waveshare RP2040 One +// https://www.waveshare.com/wiki/RP2040-One +// https://www.waveshare.com/w/upload/9/90/RP2040-One.pdf +// https://www.waveshare.com/img/devkit/RP2040-One/RP2040-One-details-9.jpg + +/* + Pin# Pin# + _____ + |USB A| + ___| |___ + 5v 1 | | 23 GPIO0 + GND 2 | | 22 GPIO1 + 3.3v 3 | | 21 GPIO2 + GPIO29 4 | | 20 GPIO3 + GPIO28 5 | | 19 GPIO4 + GPIO27 6 | | 18 GPIO5 + GPIO26 7 | | 17 GPIO6 + GPIO15 8 | | 16 GPIO7 + GPIO14 9 |__|_|_|_|_|__| 15 GPIO8 + 1 1 1 1 1 + 0 1 2 3 4 + + Pin10 = GPIO13 + Pin11 = GPIO12 + Pin12 = GPIO11 + Pin13 = GPIO10 + Pin14 = GPIO9 +*/ + +// NeoPixel +#define PIN_NEOPIXEL (16u) +//#define LED_BUILTIN PIN_NEOPIXEL + +// Serial1 +#define PIN_SERIAL1_TX (0u) +#define PIN_SERIAL1_RX (1u) + +#define PIN_SERIAL2_TX (8u) +#define PIN_SERIAL2_RX (9u) + +// SPI +#define PIN_SPI0_MISO (4u) +#define PIN_SPI0_MOSI (3u) +#define PIN_SPI0_SCK (2u) +#define PIN_SPI0_SS (5u) + +#define PIN_SPI1_MISO (12u) +#define PIN_SPI1_MOSI (15u) +#define PIN_SPI1_SCK (14u) +#define PIN_SPI1_SS (13u) + +// Wire +#define PIN_WIRE0_SDA (4u) +#define PIN_WIRE0_SCL (5u) + +#define PIN_WIRE1_SDA (26u) +#define PIN_WIRE1_SCL (27u) + +#define SERIAL_HOWMANY (2u) +#define SPI_HOWMANY (2u) +#define WIRE_HOWMANY (2u) + +#include "../generic/common.h" diff --git a/variants/waveshare_rp2040_plus_16mb/pins_arduino.h b/variants/waveshare_rp2040_plus_16mb/pins_arduino.h new file mode 100644 index 000000000..3017dc107 --- /dev/null +++ b/variants/waveshare_rp2040_plus_16mb/pins_arduino.h @@ -0,0 +1,72 @@ +#pragma once + +// Waveshare RP2040 Plus +// https://www.waveshare.com/wiki/RP2040-Plus +// https://www.waveshare.com/w/upload/d/d1/RP2040_Plus.pdf +// https://www.waveshare.com/img/devkit/RP2040-Plus/RP2040-Plus-details-7.jpg +// + +/* + Pin# Pin# + ___(_____)___ + GPIO0 1 | *USB C* | 40 VBUS + GPIO1 2 | | 39 VSYS + GND 3 | | 38 GND + GPIO2 4 | | 37 3V3_EN + GPIO3 5 | | 36 3V3(OUT) + GPIO4 6 | | 35 ADC_VREF + GPIO5 7 | | 34 GPIO28 + GND 8 | | 33 GND + GPIO6 9 | | 32 GPIO27 + GPIO7 10 | | 31 GPIO26 + GPIO8 11 | | 30 RUN + GPIO9 12 | | 29 GPIO22 + GND 13 | | 28 GND + GPIO10 14 | | 27 GPIO21 + GPIO11 15 | | 25 GPIO20 + GPIO12 16 | | 25 GPIO19 + GPIO13 17 | | 24 GPIO18 + GND 18 | | 23 GND + GPIO14 19 | | 22 GPIO17 + GPIO15 20 |____|_|_|____| 21 GPIO16 + S G S + W N W + C D D + L I + K N +*/ + +// LEDs +#define PIN_LED (25u) + +// Serial +#define PIN_SERIAL1_TX (0u) +#define PIN_SERIAL1_RX (1u) + +#define PIN_SERIAL2_TX (8u) +#define PIN_SERIAL2_RX (9u) + +// SPI +#define PIN_SPI0_MISO (16u) +#define PIN_SPI0_MOSI (19u) +#define PIN_SPI0_SCK (18u) +#define PIN_SPI0_SS (17u) + +#define PIN_SPI1_MISO (12u) +#define PIN_SPI1_MOSI (15u) +#define PIN_SPI1_SCK (14u) +#define PIN_SPI1_SS (13u) + +// Wire +#define PIN_WIRE0_SDA (8u) +#define PIN_WIRE0_SCL (9u) + +#define PIN_WIRE1_SDA (6u) +#define PIN_WIRE1_SCL (7u) + +#define SERIAL_HOWMANY (3u) +#define SPI_HOWMANY (2u) +#define WIRE_HOWMANY (2u) + + +#include "../generic/common.h" diff --git a/variants/waveshare_rp2040_plus_4mb/pins_arduino.h b/variants/waveshare_rp2040_plus_4mb/pins_arduino.h new file mode 100644 index 000000000..3017dc107 --- /dev/null +++ b/variants/waveshare_rp2040_plus_4mb/pins_arduino.h @@ -0,0 +1,72 @@ +#pragma once + +// Waveshare RP2040 Plus +// https://www.waveshare.com/wiki/RP2040-Plus +// https://www.waveshare.com/w/upload/d/d1/RP2040_Plus.pdf +// https://www.waveshare.com/img/devkit/RP2040-Plus/RP2040-Plus-details-7.jpg +// + +/* + Pin# Pin# + ___(_____)___ + GPIO0 1 | *USB C* | 40 VBUS + GPIO1 2 | | 39 VSYS + GND 3 | | 38 GND + GPIO2 4 | | 37 3V3_EN + GPIO3 5 | | 36 3V3(OUT) + GPIO4 6 | | 35 ADC_VREF + GPIO5 7 | | 34 GPIO28 + GND 8 | | 33 GND + GPIO6 9 | | 32 GPIO27 + GPIO7 10 | | 31 GPIO26 + GPIO8 11 | | 30 RUN + GPIO9 12 | | 29 GPIO22 + GND 13 | | 28 GND + GPIO10 14 | | 27 GPIO21 + GPIO11 15 | | 25 GPIO20 + GPIO12 16 | | 25 GPIO19 + GPIO13 17 | | 24 GPIO18 + GND 18 | | 23 GND + GPIO14 19 | | 22 GPIO17 + GPIO15 20 |____|_|_|____| 21 GPIO16 + S G S + W N W + C D D + L I + K N +*/ + +// LEDs +#define PIN_LED (25u) + +// Serial +#define PIN_SERIAL1_TX (0u) +#define PIN_SERIAL1_RX (1u) + +#define PIN_SERIAL2_TX (8u) +#define PIN_SERIAL2_RX (9u) + +// SPI +#define PIN_SPI0_MISO (16u) +#define PIN_SPI0_MOSI (19u) +#define PIN_SPI0_SCK (18u) +#define PIN_SPI0_SS (17u) + +#define PIN_SPI1_MISO (12u) +#define PIN_SPI1_MOSI (15u) +#define PIN_SPI1_SCK (14u) +#define PIN_SPI1_SS (13u) + +// Wire +#define PIN_WIRE0_SDA (8u) +#define PIN_WIRE0_SCL (9u) + +#define PIN_WIRE1_SDA (6u) +#define PIN_WIRE1_SCL (7u) + +#define SERIAL_HOWMANY (3u) +#define SPI_HOWMANY (2u) +#define WIRE_HOWMANY (2u) + + +#include "../generic/common.h" diff --git a/variants/waveshare_rp2040_zero/pins_arduino.h b/variants/waveshare_rp2040_zero/pins_arduino.h new file mode 100644 index 000000000..d9c7340da --- /dev/null +++ b/variants/waveshare_rp2040_zero/pins_arduino.h @@ -0,0 +1,66 @@ +#pragma once + +// Waveshare RP2040 Zero +// https://www.waveshare.com/wiki/RP2040-Zero +// https://www.waveshare.com/w/upload/4/4c/RP2040_Zero.pdf +// https://www.waveshare.com/img/devkit/RP2040-Zero/RP2040-Zero-details-7.jpg +// +// https://www.mischianti.org/2022/09/19/waveshare-rp2040-zero-high-resolution-pinout-and-specs/ +// https://www.mischianti.org/wp-content/uploads/2022/09/Waveshare-rp2040-zero-Raspberry-Pi-Pico-alternative-pinout.jpg + +/* + Pin# Pin# + ___(_____)___ + 5v 1 | *USB C* | 23 GPIO0 + GND 2 | | 22 GPIO1 + 3.3v 3 | | 21 GPIO2 + GPIO29 4 | | 20 GPIO3 + GPIO28 5 | | 19 GPIO4 + GPIO27 6 | | 18 GPIO5 + GPIO26 7 | | 17 GPIO6 + GPIO15 8 | | 16 GPIO7 + GPIO14 9 |__|_|_|_|_|__| 15 GPIO8 + 1 1 1 1 1 + 0 1 2 3 4 + + Pin10 = GPIO13 + Pin11 = GPIO12 + Pin12 = GPIO11 + Pin13 = GPIO10 + Pin14 = GPIO9 +*/ + +// NeoPixel +#define PIN_NEOPIXEL (16u) +//#define LED_BUILTIN PIN_NEOPIXEL + +// Serial1 +#define PIN_SERIAL1_TX (0u) +#define PIN_SERIAL1_RX (1u) + +#define PIN_SERIAL2_TX (8u) +#define PIN_SERIAL2_RX (9u) + +// SPI +#define PIN_SPI0_MISO (4u) +#define PIN_SPI0_MOSI (3u) +#define PIN_SPI0_SCK (2u) +#define PIN_SPI0_SS (5u) + +#define PIN_SPI1_MISO (12u) +#define PIN_SPI1_MOSI (15u) +#define PIN_SPI1_SCK (14u) +#define PIN_SPI1_SS (13u) + +// Wire +#define PIN_WIRE0_SDA (4u) +#define PIN_WIRE0_SCL (5u) + +#define PIN_WIRE1_SDA (26u) +#define PIN_WIRE1_SCL (27u) + +#define SERIAL_HOWMANY (2u) +#define SPI_HOWMANY (2u) +#define WIRE_HOWMANY (2u) + +#include "../generic/common.h"