inet-mon/firmware/main/display.cpp
Ricardo (XenGi) Band 840909af66
nearly done
2026-07-17 00:08:48 +02:00

1414 lines
82 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* @file display.cpp
* @brief ST7789VW 240x240 LCD display driver using ESP-IDF esp_lcd API
*
* This driver uses the official ESP-IDF esp_lcd_panel_st7789 API on SPI3_HOST.
* The LCD is connected to dedicated SPI pins (GPIO40,41) separate from the
* W5500 Ethernet which uses SPI2_HOST (GPIO11,12,13).
*
* Pin mapping (verified from Waveshare ESP32-S3-LCD-1.3 schematics and demo):
* MOSI = GPIO41 (LCD data)
* SCLK = GPIO40 (LCD clock)
* CS = GPIO39 (chip select)
* DC = GPIO38 (data/command)
* RST = GPIO42 (reset)
* BL_EN = GPIO4 (backlight enable, active HIGH)
* BL_PWM = GPIO20 (backlight PWM brightness control)
*
* @note Backlight uses two pins: GPIO4 as digital enable, GPIO20 for PWM dimming.
*/
#include "display.h"
#include "diagnostics.h"
#include <stdio.h>
#include <string.h>
#include <math.h>
#include "esp_log.h"
#include "driver/spi_master.h"
#include "driver/gpio.h"
#include "driver/ledc.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_lcd_panel_io.h"
#include "esp_lcd_panel_vendor.h"
#include "esp_lcd_panel_ops.h"
static const char *TAG = "DISPLAY";
// ─── Correct Pin Mapping (Waveshare ESP32-S3-LCD-1.3 Arduino User_Setup.h) ──
#define PIN_LCD_MOSI ((gpio_num_t)41)
#define PIN_LCD_CLK ((gpio_num_t)40)
#define PIN_LCD_CS ((gpio_num_t)39)
#define PIN_LCD_DC ((gpio_num_t)38)
#define PIN_LCD_RST ((gpio_num_t)42)
#define PIN_LCD_BLK ((gpio_num_t)4) // Backlight enable, active HIGH
#define PIN_LCD_BL_PWM ((gpio_num_t)20) // Backlight PWM brightness
// Test each to find the actual backlight pin
#define PIN_LCD_BLK_CANDIDATES {4, 20, 22}
// The LCD uses a dedicated SPI bus (SPI3_HOST) separate from the W5500 Ethernet
// which uses SPI2_HOST. This avoids pin conflicts since the LCD uses GPIO40/41
// while the W5500 uses GPIO11/12/13.
#define LCD_SPI_HOST SPI3_HOST
// ─── Panel handles ──────────────────────────────────────────────────────────
static esp_lcd_panel_io_handle_t s_io_handle = NULL;
static esp_lcd_panel_handle_t s_panel_handle = NULL;
// ─── 8×8 Monospace Font (ASCII 32-126) ──────────────────────────────────────
static const uint8_t FONT8x8[96][8] = {
// 0x20 ' '
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
// 0x21 '!'
{ 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x18, 0x00 },
// 0x22 '"'
{ 0x6C, 0x6C, 0x6C, 0x00, 0x00, 0x00, 0x00, 0x00 },
// 0x23 '#'
{ 0x28, 0x28, 0xFE, 0x28, 0xFE, 0x28, 0x28, 0x00 },
// 0x24 '$'
{ 0x10, 0x3C, 0x50, 0x38, 0x14, 0x78, 0x10, 0x00 },
// 0x25 '%'
{ 0x62, 0x64, 0x08, 0x10, 0x26, 0x46, 0x00, 0x00 },
// 0x26 '&'
{ 0x30, 0x48, 0x30, 0x54, 0x88, 0x74, 0x00, 0x00 },
// 0x27 '''
{ 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00 },
// 0x28 '('
{ 0x04, 0x08, 0x10, 0x10, 0x10, 0x08, 0x04, 0x00 },
// 0x29 ')'
{ 0x20, 0x10, 0x08, 0x08, 0x08, 0x10, 0x20, 0x00 },
// 0x2A '*'
{ 0x00, 0x24, 0x18, 0x7E, 0x18, 0x24, 0x00, 0x00 },
// 0x2B '+' — repurposed as checkmark ✓
{ 0x00, 0x01, 0x02, 0x04, 0x88, 0x50, 0x20, 0x00 },
// 0x2C ','
{ 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x08, 0x10 },
// 0x2D '-'
{ 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x00 },
// 0x2E '.'
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00 },
// 0x2F '/'
{ 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x00, 0x00 },
// 0x30 '0'
{ 0x3C, 0x42, 0x46, 0x5A, 0x62, 0x42, 0x3C, 0x00 },
// 0x31 '1'
{ 0x10, 0x30, 0x50, 0x10, 0x10, 0x10, 0x7C, 0x00 },
// 0x32 '2'
{ 0x3C, 0x42, 0x02, 0x0C, 0x30, 0x40, 0x7E, 0x00 },
// 0x33 '3'
{ 0x3C, 0x42, 0x02, 0x1C, 0x02, 0x42, 0x3C, 0x00 },
// 0x34 '4'
{ 0x08, 0x18, 0x28, 0x48, 0xFE, 0x08, 0x08, 0x00 },
// 0x35 '5'
{ 0x7E, 0x40, 0x7C, 0x02, 0x02, 0x42, 0x3C, 0x00 },
// 0x36 '6'
{ 0x1C, 0x20, 0x40, 0x7C, 0x42, 0x42, 0x3C, 0x00 },
// 0x37 '7'
{ 0x7E, 0x02, 0x04, 0x08, 0x10, 0x10, 0x10, 0x00 },
// 0x38 '8'
{ 0x3C, 0x42, 0x42, 0x3C, 0x42, 0x42, 0x3C, 0x00 },
// 0x39 '9'
{ 0x3C, 0x42, 0x42, 0x3E, 0x02, 0x04, 0x38, 0x00 },
// 0x3A ':'
{ 0x00, 0x18, 0x18, 0x00, 0x18, 0x18, 0x00, 0x00 },
// 0x3B ';'
{ 0x00, 0x18, 0x18, 0x00, 0x18, 0x18, 0x08, 0x10 },
// 0x3C '<'
{ 0x04, 0x08, 0x10, 0x20, 0x10, 0x08, 0x04, 0x00 },
// 0x3D '='
{ 0x00, 0x00, 0x7E, 0x00, 0x7E, 0x00, 0x00, 0x00 },
// 0x3E '>'
{ 0x20, 0x10, 0x08, 0x04, 0x08, 0x10, 0x20, 0x00 },
// 0x3F '?'
{ 0x3C, 0x42, 0x02, 0x0C, 0x10, 0x00, 0x10, 0x00 },
// 0x40 '@'
{ 0x3C, 0x42, 0x4E, 0x52, 0x4E, 0x40, 0x3C, 0x00 },
// 0x41 'A'
{ 0x18, 0x24, 0x42, 0x7E, 0x42, 0x42, 0x42, 0x00 },
// 0x42 'B'
{ 0x7C, 0x42, 0x42, 0x7C, 0x42, 0x42, 0x7C, 0x00 },
// 0x43 'C'
{ 0x3C, 0x42, 0x40, 0x40, 0x40, 0x42, 0x3C, 0x00 },
// 0x44 'D'
{ 0x78, 0x44, 0x42, 0x42, 0x42, 0x44, 0x78, 0x00 },
// 0x45 'E'
{ 0x7E, 0x40, 0x40, 0x7C, 0x40, 0x40, 0x7E, 0x00 },
// 0x46 'F'
{ 0x7E, 0x40, 0x40, 0x7C, 0x40, 0x40, 0x40, 0x00 },
// 0x47 'G'
{ 0x3C, 0x42, 0x40, 0x4E, 0x42, 0x42, 0x3C, 0x00 },
// 0x48 'H'
{ 0x42, 0x42, 0x42, 0x7E, 0x42, 0x42, 0x42, 0x00 },
// 0x49 'I'
{ 0x7C, 0x10, 0x10, 0x10, 0x10, 0x10, 0x7C, 0x00 },
// 0x4A 'J'
{ 0x1E, 0x04, 0x04, 0x04, 0x04, 0x44, 0x38, 0x00 },
// 0x4B 'K'
{ 0x42, 0x44, 0x48, 0x70, 0x48, 0x44, 0x42, 0x00 },
// 0x4C 'L'
{ 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x7E, 0x00 },
// 0x4D 'M'
{ 0x42, 0x66, 0x5A, 0x5A, 0x42, 0x42, 0x42, 0x00 },
// 0x4E 'N'
{ 0x42, 0x62, 0x52, 0x4A, 0x46, 0x42, 0x42, 0x00 },
// 0x4F 'O'
{ 0x3C, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3C, 0x00 },
// 0x50 'P'
{ 0x7C, 0x42, 0x42, 0x7C, 0x40, 0x40, 0x40, 0x00 },
// 0x51 'Q'
{ 0x3C, 0x42, 0x42, 0x42, 0x4A, 0x44, 0x3A, 0x00 },
// 0x52 'R'
{ 0x7C, 0x42, 0x42, 0x7C, 0x48, 0x44, 0x42, 0x00 },
// 0x53 'S'
{ 0x3C, 0x42, 0x40, 0x3C, 0x02, 0x42, 0x3C, 0x00 },
// 0x54 'T'
{ 0xFE, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00 },
// 0x55 'U'
{ 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3C, 0x00 },
// 0x56 'V'
{ 0x42, 0x42, 0x42, 0x42, 0x24, 0x18, 0x18, 0x00 },
// 0x57 'W'
{ 0x42, 0x42, 0x42, 0x5A, 0x5A, 0x66, 0x42, 0x00 },
// 0x58 'X'
{ 0x42, 0x42, 0x24, 0x18, 0x24, 0x42, 0x42, 0x00 },
// 0x59 'Y'
{ 0x44, 0x44, 0x28, 0x10, 0x10, 0x10, 0x10, 0x00 },
// 0x5A 'Z'
{ 0x7E, 0x04, 0x08, 0x10, 0x20, 0x40, 0x7E, 0x00 },
// 0x5B '['
{ 0x3C, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x00 },
// 0x5C '\'
{ 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x00, 0x00 },
// 0x5D ']'
{ 0x3C, 0x04, 0x04, 0x04, 0x04, 0x04, 0x3C, 0x00 },
// 0x5E '^'
{ 0x10, 0x28, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00 },
// 0x5F '_'
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF },
// 0x60 '`'
{ 0x10, 0x08, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00 },
// 0x61 'a'
{ 0x00, 0x00, 0x3C, 0x02, 0x3E, 0x42, 0x3E, 0x00 },
// 0x62 'b'
{ 0x40, 0x40, 0x5C, 0x62, 0x42, 0x62, 0x5C, 0x00 },
// 0x63 'c'
{ 0x00, 0x00, 0x3C, 0x42, 0x40, 0x42, 0x3C, 0x00 },
// 0x64 'd'
{ 0x02, 0x02, 0x3A, 0x46, 0x42, 0x46, 0x3A, 0x00 },
// 0x65 'e'
{ 0x00, 0x00, 0x3C, 0x42, 0x7E, 0x40, 0x3C, 0x00 },
// 0x66 'f'
{ 0x1C, 0x22, 0x20, 0x7C, 0x20, 0x20, 0x20, 0x00 },
// 0x67 'g'
{ 0x00, 0x00, 0x3A, 0x46, 0x42, 0x46, 0x3A, 0x02 },
// 0x68 'h'
{ 0x40, 0x40, 0x5C, 0x62, 0x42, 0x42, 0x42, 0x00 },
// 0x69 'i'
{ 0x18, 0x00, 0x38, 0x08, 0x08, 0x08, 0x3E, 0x00 },
// 0x6A 'j'
{ 0x0C, 0x00, 0x1C, 0x04, 0x04, 0x04, 0x44, 0x38 },
// 0x6B 'k'
{ 0x40, 0x40, 0x44, 0x48, 0x70, 0x48, 0x44, 0x00 },
// 0x6C 'l'
{ 0x38, 0x08, 0x08, 0x08, 0x08, 0x08, 0x3E, 0x00 },
// 0x6D 'm'
{ 0x00, 0x00, 0xFC, 0x92, 0x92, 0x92, 0x92, 0x00 },
// 0x6E 'n'
{ 0x00, 0x00, 0x5C, 0x62, 0x42, 0x42, 0x42, 0x00 },
// 0x6F 'o'
{ 0x00, 0x00, 0x3C, 0x42, 0x42, 0x42, 0x3C, 0x00 },
// 0x70 'p'
{ 0x00, 0x00, 0x5C, 0x62, 0x42, 0x62, 0x5C, 0x40 },
// 0x71 'q'
{ 0x00, 0x00, 0x3A, 0x46, 0x42, 0x46, 0x3A, 0x02 },
// 0x72 'r'
{ 0x00, 0x00, 0x5C, 0x62, 0x40, 0x40, 0x40, 0x00 },
// 0x73 's'
{ 0x00, 0x00, 0x3E, 0x40, 0x3C, 0x02, 0x7C, 0x00 },
// 0x74 't'
{ 0x20, 0x20, 0x7C, 0x20, 0x20, 0x22, 0x1C, 0x00 },
// 0x75 'u'
{ 0x00, 0x00, 0x42, 0x42, 0x42, 0x46, 0x3A, 0x00 },
// 0x76 'v'
{ 0x00, 0x00, 0x44, 0x44, 0x28, 0x28, 0x10, 0x00 },
// 0x77 'w'
{ 0x00, 0x00, 0x82, 0x92, 0x92, 0x92, 0x6C, 0x00 },
// 0x78 'x'
{ 0x00, 0x00, 0x42, 0x24, 0x18, 0x24, 0x42, 0x00 },
// 0x79 'y'
{ 0x00, 0x00, 0x42, 0x42, 0x42, 0x46, 0x3A, 0x02 },
// 0x7A 'z'
{ 0x00, 0x00, 0x7E, 0x04, 0x18, 0x20, 0x7E, 0x00 },
// 0x7B '{'
{ 0x0C, 0x10, 0x10, 0x60, 0x10, 0x10, 0x0C, 0x00 },
// 0x7C '|'
{ 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x00 },
// 0x7D '}'
{ 0x30, 0x08, 0x08, 0x06, 0x08, 0x08, 0x30, 0x00 },
// 0x7E '~'
{ 0x00, 0x70, 0x88, 0x88, 0x70, 0x00, 0x00, 0x00 },
// 0xB0 '°' (degree symbol)
{ 0x3C, 0x42, 0x42, 0x3C, 0x00, 0x00, 0x00, 0x00 }
};
// ─── Ethernet RJ45 Plug Logo (64 × 64 RGB565 color, from eth_logo.png) ────
//
// Converted from original PNG composited on black background.
// Data is RGB565 big-endian (high byte first), 8192 bytes total.
#define LOGO_W 64
#define LOGO_H 64
static const uint8_t LOGO_ETH_COLOR[LOGO_W * LOGO_H * 2] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x5B, 0x2D, 0x9D, 0x56, 0xAD, 0xD9, 0xAD, 0xD9, 0xAD, 0xD9,
0xAD, 0xD9, 0xAD, 0xD9, 0xAD, 0xD9, 0xAD, 0xD9, 0xAD, 0xD9, 0xAD, 0xD9, 0xAD, 0xD9, 0xAD, 0xD9,
0xAD, 0xD9, 0xAD, 0xD9, 0xAD, 0xD9, 0xAD, 0xD9, 0xAD, 0xD9, 0xAD, 0xD9, 0xAD, 0xD9, 0xAD, 0xD9,
0xAD, 0xD9, 0xAD, 0xD9, 0xAD, 0xD9, 0xAD, 0xD9, 0xAD, 0xD9, 0xAD, 0xD9, 0xAD, 0xD9, 0xAD, 0xD9,
0xAD, 0xD9, 0xAD, 0xD9, 0xAD, 0xD9, 0xAD, 0xD9, 0xAD, 0xD9, 0xAD, 0xD9, 0xAD, 0xD9, 0xAD, 0xD9,
0xAD, 0xD9, 0xAD, 0xD9, 0xAD, 0xD9, 0xAD, 0xD9, 0xAD, 0xD9, 0xAD, 0xD9, 0xAD, 0xD9, 0xAD, 0xD9,
0xAD, 0xD9, 0xAD, 0xD9, 0xAD, 0xD9, 0xAD, 0xD9, 0xAD, 0xD9, 0xAD, 0xD9, 0xAD, 0xD9, 0xAD, 0xD9,
0xAD, 0xD9, 0xAD, 0xD9, 0xAD, 0xD9, 0x9D, 0x56, 0x5B, 0x2D, 0x08, 0x41, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x21, 0x95, 0x15, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B,
0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B,
0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B,
0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B,
0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B,
0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B,
0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B,
0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0x94, 0xF5, 0x00, 0x21, 0x00, 0x00,
0x00, 0x00, 0x5B, 0x2D, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B,
0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B,
0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B,
0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B,
0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B,
0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B,
0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B,
0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0x5B, 0x2D, 0x00, 0x00,
0x00, 0x00, 0x9D, 0x56, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B,
0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B,
0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B,
0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B,
0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B,
0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B,
0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B,
0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0x9D, 0x36, 0x00, 0x00,
0x00, 0x00, 0xAD, 0xD9, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B,
0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B,
0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B,
0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B,
0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B,
0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B,
0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B,
0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xAD, 0xD9, 0x00, 0x00,
0x00, 0x00, 0xAD, 0xD9, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B,
0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B,
0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B,
0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B,
0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B,
0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B,
0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B,
0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xAD, 0xD9, 0x00, 0x00,
0x00, 0x00, 0xAD, 0xD9, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B,
0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B,
0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B,
0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B,
0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B,
0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B,
0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B,
0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xAD, 0xD9, 0x00, 0x00,
0x00, 0x00, 0xAD, 0xD9, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B,
0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B,
0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B,
0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B,
0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B,
0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B,
0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B,
0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xAD, 0xD9, 0x00, 0x00,
0x00, 0x00, 0xAD, 0xD9, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B,
0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B,
0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B,
0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B,
0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B,
0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B,
0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B,
0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xAD, 0xD9, 0x00, 0x00,
0x00, 0x00, 0xAD, 0xD9, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B,
0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B,
0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B,
0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B,
0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B,
0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B,
0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B,
0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xAD, 0xD9, 0x00, 0x00,
0x00, 0x00, 0xAD, 0xD9, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x3B, 0xA5, 0x98,
0xA5, 0x98, 0xA5, 0x98, 0xA5, 0x98, 0xA5, 0x98, 0xA5, 0x98, 0xA5, 0x98, 0xA5, 0x98, 0xA5, 0x98,
0xA5, 0x98, 0xA5, 0x98, 0xA5, 0x98, 0xA5, 0x98, 0xA5, 0x98, 0xA5, 0x98, 0xA5, 0x98, 0xA5, 0x98,
0xA5, 0x98, 0xA5, 0x98, 0xA5, 0x98, 0xA5, 0x98, 0xA5, 0x98, 0xA5, 0x98, 0xA5, 0x98, 0xA5, 0x98,
0xA5, 0x98, 0xA5, 0x98, 0xA5, 0x98, 0xA5, 0x98, 0xA5, 0x98, 0xA5, 0x98, 0xA5, 0x98, 0xA5, 0x98,
0xA5, 0x98, 0xA5, 0x98, 0xA5, 0x98, 0xA5, 0x98, 0xA5, 0x98, 0xA5, 0x98, 0xA5, 0x98, 0xA5, 0x98,
0xA5, 0x98, 0xA5, 0x98, 0xA5, 0x98, 0xA5, 0x98, 0xA5, 0x98, 0xA5, 0x98, 0xA5, 0x98, 0xA5, 0x98,
0xA5, 0x98, 0xBE, 0x3B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xAD, 0xD9, 0x00, 0x00,
0x00, 0x00, 0xAD, 0xD9, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0x8C, 0xB5, 0x31, 0xEB,
0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB,
0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB,
0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB,
0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB,
0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB,
0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB,
0x31, 0xEB, 0x8C, 0xB5, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xAD, 0xD9, 0x00, 0x00,
0x00, 0x00, 0xAD, 0xD9, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0x84, 0x74, 0x31, 0xEB,
0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB,
0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB,
0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB,
0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB,
0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB,
0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB,
0x31, 0xEB, 0x84, 0x74, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xAD, 0xD9, 0x00, 0x00,
0x00, 0x00, 0xAD, 0xD9, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0x84, 0x74, 0x31, 0xEB,
0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB,
0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB,
0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB,
0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB,
0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB,
0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB,
0x31, 0xEB, 0x84, 0x74, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xAD, 0xD9, 0x00, 0x00,
0x00, 0x00, 0xAD, 0xD9, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0x84, 0x74, 0x31, 0xEB,
0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB,
0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB,
0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB,
0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB,
0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB,
0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB,
0x31, 0xEB, 0x84, 0x74, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xAD, 0xD9, 0x00, 0x00,
0x00, 0x00, 0xAD, 0xD9, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0x84, 0x74, 0x31, 0xEB,
0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x5A, 0x8B, 0xDD, 0x49, 0xBC, 0x8A, 0x31, 0xEB, 0x31, 0xEB,
0x31, 0xEB, 0x31, 0xEB, 0xBC, 0x8A, 0xDD, 0x49, 0x5A, 0x8B, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB,
0x83, 0x4B, 0xE5, 0x49, 0xA3, 0xEA, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x39, 0xEB, 0xD5, 0x09,
0xD5, 0x09, 0x39, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0xA3, 0xEA, 0xE5, 0x49, 0x83, 0x4B,
0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x5A, 0x8B, 0xDD, 0x49, 0xBC, 0x8A, 0x31, 0xEB, 0x31, 0xEB,
0x31, 0xEB, 0x31, 0xEB, 0xBC, 0x8A, 0xDD, 0x49, 0x5A, 0x8B, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB,
0x31, 0xEB, 0x84, 0x74, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xAD, 0xD9, 0x00, 0x00,
0x00, 0x00, 0xAD, 0xD9, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0x84, 0x74, 0x31, 0xEB,
0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x83, 0x4B, 0xED, 0x89, 0xDD, 0x29, 0x31, 0xEB, 0x31, 0xEB,
0x31, 0xEB, 0x31, 0xEB, 0xDD, 0x29, 0xED, 0x89, 0x83, 0x4B, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB,
0xAC, 0x0A, 0xED, 0x89, 0xC4, 0xAA, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x4A, 0x4B, 0xED, 0x89,
0xED, 0x89, 0x4A, 0x4B, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0xC4, 0xAA, 0xED, 0x89, 0xAC, 0x0A,
0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x83, 0x4B, 0xED, 0x89, 0xDD, 0x29, 0x31, 0xEB, 0x31, 0xEB,
0x31, 0xEB, 0x31, 0xEB, 0xDD, 0x29, 0xED, 0x89, 0x83, 0x4B, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB,
0x31, 0xEB, 0x84, 0x74, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xAD, 0xD9, 0x00, 0x00,
0x00, 0x00, 0xAD, 0xD9, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0x84, 0x74, 0x31, 0xEB,
0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x83, 0x4B, 0xED, 0x89, 0xDD, 0x29, 0x31, 0xEB, 0x31, 0xEB,
0x31, 0xEB, 0x31, 0xEB, 0xDD, 0x29, 0xED, 0x89, 0x83, 0x4B, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB,
0xAC, 0x0A, 0xED, 0x89, 0xC4, 0xAA, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x4A, 0x4B, 0xED, 0x89,
0xED, 0x89, 0x4A, 0x4B, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0xC4, 0xAA, 0xED, 0x89, 0xAC, 0x0A,
0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x83, 0x4B, 0xED, 0x89, 0xDD, 0x29, 0x31, 0xEB, 0x31, 0xEB,
0x31, 0xEB, 0x31, 0xEB, 0xDD, 0x29, 0xED, 0x89, 0x83, 0x4B, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB,
0x31, 0xEB, 0x84, 0x74, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xAD, 0xD9, 0x00, 0x00,
0x00, 0x00, 0xAD, 0xD9, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0x84, 0x74, 0x31, 0xEB,
0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x83, 0x4B, 0xED, 0x89, 0xDD, 0x29, 0x31, 0xEB, 0x31, 0xEB,
0x31, 0xEB, 0x31, 0xEB, 0xDD, 0x29, 0xED, 0x89, 0x83, 0x4B, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB,
0xAC, 0x0A, 0xED, 0x89, 0xC4, 0xAA, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x4A, 0x4B, 0xED, 0x89,
0xED, 0x89, 0x4A, 0x4B, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0xC4, 0xAA, 0xED, 0x89, 0xAC, 0x0A,
0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x83, 0x4B, 0xED, 0x89, 0xDD, 0x29, 0x31, 0xEB, 0x31, 0xEB,
0x31, 0xEB, 0x31, 0xEB, 0xDD, 0x29, 0xED, 0x89, 0x83, 0x4B, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB,
0x31, 0xEB, 0x84, 0x74, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xAD, 0xD9, 0x00, 0x00,
0x00, 0x00, 0xAD, 0xD9, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0x84, 0x74, 0x31, 0xEB,
0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x83, 0x4B, 0xED, 0x89, 0xDD, 0x29, 0x31, 0xEB, 0x31, 0xEB,
0x31, 0xEB, 0x31, 0xEB, 0xDD, 0x29, 0xED, 0x89, 0x83, 0x4B, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB,
0xAC, 0x0A, 0xED, 0x89, 0xC4, 0xAA, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x4A, 0x4B, 0xED, 0x89,
0xED, 0x89, 0x4A, 0x4B, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0xC4, 0xAA, 0xED, 0x89, 0xAC, 0x0A,
0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x83, 0x4B, 0xED, 0x89, 0xDD, 0x29, 0x31, 0xEB, 0x31, 0xEB,
0x31, 0xEB, 0x31, 0xEB, 0xDD, 0x29, 0xED, 0x89, 0x83, 0x4B, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB,
0x31, 0xEB, 0x84, 0x74, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xAD, 0xD9, 0x00, 0x00,
0x00, 0x00, 0xAD, 0xD9, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0x84, 0x74, 0x31, 0xEB,
0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x83, 0x4B, 0xED, 0x89, 0xDD, 0x29, 0x31, 0xEB, 0x31, 0xEB,
0x31, 0xEB, 0x31, 0xEB, 0xDD, 0x29, 0xED, 0x89, 0x83, 0x4B, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB,
0xAC, 0x0A, 0xED, 0x89, 0xC4, 0xAA, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x4A, 0x4B, 0xED, 0x89,
0xED, 0x89, 0x4A, 0x4B, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0xC4, 0xAA, 0xED, 0x89, 0xAC, 0x0A,
0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x83, 0x4B, 0xED, 0x89, 0xDD, 0x29, 0x31, 0xEB, 0x31, 0xEB,
0x31, 0xEB, 0x31, 0xEB, 0xDD, 0x29, 0xED, 0x89, 0x83, 0x4B, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB,
0x31, 0xEB, 0x84, 0x74, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xAD, 0xD9, 0x00, 0x00,
0x00, 0x00, 0xAD, 0xD9, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0x84, 0x74, 0x31, 0xEB,
0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x83, 0x4B, 0xED, 0x89, 0xDD, 0x29, 0x31, 0xEB, 0x31, 0xEB,
0x31, 0xEB, 0x31, 0xEB, 0xDD, 0x29, 0xED, 0x89, 0x83, 0x4B, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB,
0xAC, 0x0A, 0xED, 0x89, 0xC4, 0xAA, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x4A, 0x4B, 0xED, 0x89,
0xED, 0x89, 0x4A, 0x4B, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0xC4, 0xAA, 0xED, 0x89, 0xAC, 0x0A,
0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x83, 0x4B, 0xED, 0x89, 0xDD, 0x29, 0x31, 0xEB, 0x31, 0xEB,
0x31, 0xEB, 0x31, 0xEB, 0xDD, 0x29, 0xED, 0x89, 0x83, 0x4B, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB,
0x31, 0xEB, 0x84, 0x74, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xAD, 0xD9, 0x00, 0x00,
0x00, 0x00, 0xAD, 0xD9, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0x84, 0x74, 0x31, 0xEB,
0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x83, 0x4B, 0xED, 0x89, 0xDD, 0x29, 0x31, 0xEB, 0x31, 0xEB,
0x31, 0xEB, 0x31, 0xEB, 0xDD, 0x29, 0xED, 0x89, 0x83, 0x4B, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB,
0xAC, 0x0A, 0xED, 0x89, 0xC4, 0xAA, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x4A, 0x4B, 0xED, 0x89,
0xED, 0x89, 0x4A, 0x4B, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0xC4, 0xAA, 0xED, 0x89, 0xAC, 0x0A,
0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x83, 0x4B, 0xED, 0x89, 0xDD, 0x29, 0x31, 0xEB, 0x31, 0xEB,
0x31, 0xEB, 0x31, 0xEB, 0xDD, 0x29, 0xED, 0x89, 0x83, 0x4B, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB,
0x31, 0xEB, 0x84, 0x74, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xAD, 0xD9, 0x00, 0x00,
0x00, 0x00, 0xAD, 0xD9, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0x84, 0x74, 0x31, 0xEB,
0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x83, 0x4B, 0xED, 0x89, 0xDD, 0x29, 0x31, 0xEB, 0x31, 0xEB,
0x31, 0xEB, 0x31, 0xEB, 0xDD, 0x29, 0xED, 0x89, 0x83, 0x4B, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB,
0xAC, 0x0A, 0xED, 0x89, 0xC4, 0xAA, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x4A, 0x4B, 0xED, 0x89,
0xED, 0x89, 0x4A, 0x4B, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0xC4, 0xAA, 0xED, 0x89, 0xAC, 0x0A,
0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x83, 0x4B, 0xED, 0x89, 0xDD, 0x29, 0x31, 0xEB, 0x31, 0xEB,
0x31, 0xEB, 0x31, 0xEB, 0xDD, 0x29, 0xED, 0x89, 0x83, 0x4B, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB,
0x31, 0xEB, 0x84, 0x74, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xAD, 0xD9, 0x00, 0x00,
0x00, 0x00, 0xAD, 0xD9, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0x84, 0x74, 0x31, 0xEB,
0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x83, 0x2B, 0xED, 0x89, 0xDD, 0x29, 0x31, 0xEB, 0x31, 0xEB,
0x31, 0xEB, 0x31, 0xEB, 0xDD, 0x29, 0xED, 0x89, 0x83, 0x2B, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB,
0xA4, 0x0A, 0xED, 0x89, 0xC4, 0x8A, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x4A, 0x2B, 0xED, 0x89,
0xED, 0x89, 0x4A, 0x2B, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0xC4, 0x8A, 0xED, 0x89, 0xA4, 0x0A,
0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x83, 0x2B, 0xED, 0x89, 0xDD, 0x29, 0x31, 0xEB, 0x31, 0xEB,
0x31, 0xEB, 0x31, 0xEB, 0xDD, 0x29, 0xED, 0x89, 0x83, 0x2B, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB,
0x31, 0xEB, 0x84, 0x74, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xAD, 0xD9, 0x00, 0x00,
0x00, 0x00, 0xAD, 0xD9, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0x84, 0x74, 0x31, 0xEB,
0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x42, 0x2B, 0xB4, 0x6A, 0x93, 0xAA, 0x31, 0xEB, 0x31, 0xEB,
0x31, 0xEB, 0x31, 0xEB, 0x93, 0xAA, 0xB4, 0x6A, 0x42, 0x2B, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB,
0x62, 0x8B, 0xBC, 0x8A, 0x7B, 0x2B, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0xAC, 0x0A,
0xAC, 0x0A, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x7B, 0x2B, 0xBC, 0x8A, 0x62, 0x8B,
0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x42, 0x2B, 0xB4, 0x6A, 0x93, 0xAA, 0x31, 0xEB, 0x31, 0xEB,
0x31, 0xEB, 0x31, 0xEB, 0x93, 0xAA, 0xB4, 0x6A, 0x42, 0x2B, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB,
0x31, 0xEB, 0x84, 0x74, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xAD, 0xD9, 0x00, 0x00,
0x00, 0x00, 0xAD, 0xD9, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0x84, 0x74, 0x31, 0xEB,
0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB,
0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB,
0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB,
0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB,
0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB,
0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB,
0x31, 0xEB, 0x84, 0x74, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xAD, 0xD9, 0x00, 0x00,
0x00, 0x00, 0xAD, 0xD9, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0x84, 0x74, 0x31, 0xEB,
0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB,
0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB,
0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB,
0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB,
0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB,
0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB,
0x31, 0xEB, 0x84, 0x74, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xAD, 0xD9, 0x00, 0x00,
0x00, 0x00, 0xAD, 0xD9, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0x84, 0x74, 0x31, 0xEB,
0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB,
0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB,
0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB,
0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB,
0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB,
0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB,
0x31, 0xEB, 0x84, 0x74, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xAD, 0xD9, 0x00, 0x00,
0x00, 0x00, 0xAD, 0xD9, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0x84, 0x74, 0x31, 0xEB,
0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB,
0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB,
0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB,
0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB,
0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB,
0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB,
0x31, 0xEB, 0x84, 0x74, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xAD, 0xD9, 0x00, 0x00,
0x00, 0x00, 0xAD, 0xD9, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0x84, 0x74, 0x31, 0xEB,
0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB,
0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB,
0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB,
0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB,
0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB,
0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB,
0x31, 0xEB, 0x84, 0x74, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xAD, 0xD9, 0x00, 0x00,
0x00, 0x00, 0xAD, 0xD9, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0x84, 0x74, 0x31, 0xEB,
0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB,
0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB,
0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB,
0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB,
0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB,
0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB,
0x31, 0xEB, 0x84, 0x74, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xAD, 0xD9, 0x00, 0x00,
0x00, 0x00, 0xAD, 0xD9, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0x84, 0x74, 0x31, 0xEB,
0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB,
0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB,
0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB,
0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB,
0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB,
0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB,
0x31, 0xEB, 0x84, 0x74, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xAD, 0xD9, 0x00, 0x00,
0x00, 0x00, 0xAD, 0xD9, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0x84, 0x74, 0x31, 0xEB,
0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB,
0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB,
0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB,
0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB,
0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB,
0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB,
0x31, 0xEB, 0x84, 0x74, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xAD, 0xD9, 0x00, 0x00,
0x00, 0x00, 0xAD, 0xD9, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0x84, 0x74, 0x31, 0xEB,
0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB,
0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB,
0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB,
0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB,
0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB,
0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB,
0x31, 0xEB, 0x84, 0x74, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xAD, 0xD9, 0x00, 0x00,
0x00, 0x00, 0xAD, 0xD9, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0x84, 0x74, 0x31, 0xEB,
0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB,
0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB,
0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB,
0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB,
0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB,
0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB,
0x31, 0xEB, 0x84, 0x74, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xAD, 0xD9, 0x00, 0x00,
0x00, 0x00, 0xAD, 0xD9, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0x84, 0x74, 0x31, 0xEB,
0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB,
0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB,
0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB,
0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB,
0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB,
0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB,
0x31, 0xEB, 0x84, 0x74, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xAD, 0xD9, 0x00, 0x00,
0x00, 0x00, 0xAD, 0xD9, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0x84, 0x94, 0x31, 0xEB,
0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB,
0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB,
0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB,
0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB,
0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB,
0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB,
0x31, 0xEB, 0x84, 0x94, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xAD, 0xD9, 0x00, 0x00,
0x00, 0x00, 0xAD, 0xD9, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xB6, 0x1A, 0x94, 0xF5,
0x8C, 0xD5, 0x8C, 0xD5, 0x8C, 0xD5, 0x8C, 0xD5, 0x8C, 0xD5, 0x8C, 0xD5, 0x8C, 0xD5, 0x8C, 0xD5,
0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB,
0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB,
0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB,
0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB,
0x8C, 0xD5, 0x8C, 0xD5, 0x8C, 0xD5, 0x8C, 0xD5, 0x8C, 0xD5, 0x8C, 0xD5, 0x8C, 0xD5, 0x8C, 0xD5,
0x94, 0xF5, 0xB6, 0x1A, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xAD, 0xD9, 0x00, 0x00,
0x00, 0x00, 0xAD, 0xD9, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B,
0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B,
0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB,
0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB,
0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB,
0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB,
0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B,
0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xAD, 0xD9, 0x00, 0x00,
0x00, 0x00, 0xAD, 0xD9, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B,
0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B,
0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB,
0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB,
0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB,
0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB,
0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B,
0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xAD, 0xD9, 0x00, 0x00,
0x00, 0x00, 0xAD, 0xD9, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B,
0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B,
0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB,
0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB,
0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB,
0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB,
0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B,
0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xAD, 0xD9, 0x00, 0x00,
0x00, 0x00, 0xAD, 0xD9, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B,
0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B,
0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB,
0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB,
0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB,
0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB,
0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B,
0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xAD, 0xD9, 0x00, 0x00,
0x00, 0x00, 0xAD, 0xD9, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B,
0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B,
0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB,
0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB,
0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB,
0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB,
0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B,
0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xAD, 0xD9, 0x00, 0x00,
0x00, 0x00, 0xAD, 0xD9, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B,
0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B,
0x7C, 0x33, 0x5B, 0x0F, 0x5B, 0x0F, 0x5B, 0x0F, 0x42, 0x4C, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB,
0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB,
0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB,
0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x42, 0x4C, 0x5B, 0x0F, 0x5B, 0x0F, 0x5B, 0x0F, 0x7C, 0x33,
0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B,
0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xAD, 0xD9, 0x00, 0x00,
0x00, 0x00, 0xAD, 0xD9, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B,
0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B,
0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0x6B, 0xB1, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB,
0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB,
0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB,
0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x6B, 0xB1, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B,
0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B,
0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xAD, 0xD9, 0x00, 0x00,
0x00, 0x00, 0xAD, 0xD9, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B,
0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B,
0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0x6B, 0xB1, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB,
0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB,
0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB,
0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x6B, 0xB1, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B,
0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B,
0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xAD, 0xD9, 0x00, 0x00,
0x00, 0x00, 0xAD, 0xD9, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B,
0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B,
0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0x6B, 0xB1, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB,
0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB,
0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB,
0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x6B, 0xB1, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B,
0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B,
0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xAD, 0xD9, 0x00, 0x00,
0x00, 0x00, 0xAD, 0xD9, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B,
0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B,
0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0x6B, 0xB1, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB,
0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB,
0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB,
0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x6B, 0xB1, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B,
0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B,
0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xAD, 0xD9, 0x00, 0x00,
0x00, 0x00, 0xAD, 0xD9, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B,
0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B,
0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0x6B, 0xB1, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB,
0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB,
0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB,
0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x6B, 0xB1, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B,
0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B,
0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xAD, 0xD9, 0x00, 0x00,
0x00, 0x00, 0xAD, 0xD9, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B,
0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B,
0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0x7C, 0x13, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB,
0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB,
0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB,
0x31, 0xEB, 0x31, 0xEB, 0x31, 0xEB, 0x7C, 0x13, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B,
0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B,
0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xAD, 0xD9, 0x00, 0x00,
0x00, 0x00, 0xAD, 0xD9, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B,
0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B,
0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xB6, 0x3A, 0xA5, 0x98, 0xA5, 0x98, 0xA5, 0x98,
0xA5, 0x98, 0xA5, 0x98, 0xA5, 0x98, 0xA5, 0x98, 0xA5, 0x98, 0xA5, 0x98, 0xA5, 0x98, 0xA5, 0x98,
0xA5, 0x98, 0xA5, 0x98, 0xA5, 0x98, 0xA5, 0x98, 0xA5, 0x98, 0xA5, 0x98, 0xA5, 0x98, 0xA5, 0x98,
0xA5, 0x98, 0xA5, 0x98, 0xA5, 0x98, 0xB6, 0x3A, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B,
0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B,
0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xAD, 0xD9, 0x00, 0x00,
0x00, 0x00, 0xAD, 0xD9, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B,
0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B,
0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B,
0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B,
0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B,
0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B,
0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B,
0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xAD, 0xD9, 0x00, 0x00,
0x00, 0x00, 0xAD, 0xD9, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B,
0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B,
0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B,
0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B,
0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B,
0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B,
0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B,
0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xAD, 0xD9, 0x00, 0x00,
0x00, 0x00, 0xAD, 0xD9, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B,
0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B,
0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B,
0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B,
0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B,
0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B,
0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B,
0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xAD, 0xD9, 0x00, 0x00,
0x00, 0x00, 0xAD, 0xD9, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B,
0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B,
0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B,
0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B,
0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B,
0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B,
0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B,
0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xAD, 0xD9, 0x00, 0x00,
0x00, 0x00, 0xAD, 0xD9, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B,
0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B,
0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B,
0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B,
0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B,
0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B,
0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B,
0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xAD, 0xD9, 0x00, 0x00,
0x00, 0x00, 0xAD, 0xD9, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B,
0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B,
0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B,
0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B,
0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B,
0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B,
0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B,
0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xAD, 0xD9, 0x00, 0x00,
0x00, 0x00, 0x9D, 0x56, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B,
0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B,
0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B,
0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B,
0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B,
0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B,
0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B,
0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0x9D, 0x36, 0x00, 0x00,
0x00, 0x00, 0x5B, 0x2D, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B,
0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B,
0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B,
0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B,
0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B,
0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B,
0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B,
0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0x5B, 0x2D, 0x00, 0x00,
0x00, 0x00, 0x00, 0x21, 0x94, 0xF5, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B,
0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B,
0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B,
0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B,
0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B,
0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B,
0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B,
0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0xBE, 0x5B, 0x94, 0xF5, 0x00, 0x21, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x5B, 0x2D, 0x9D, 0x36, 0xAD, 0xD9, 0xAD, 0xD9, 0xAD, 0xD9,
0xAD, 0xD9, 0xAD, 0xD9, 0xAD, 0xD9, 0xAD, 0xD9, 0xAD, 0xD9, 0xAD, 0xD9, 0xAD, 0xD9, 0xAD, 0xD9,
0xAD, 0xD9, 0xAD, 0xD9, 0xAD, 0xD9, 0xAD, 0xD9, 0xAD, 0xD9, 0xAD, 0xD9, 0xAD, 0xD9, 0xAD, 0xD9,
0xAD, 0xD9, 0xAD, 0xD9, 0xAD, 0xD9, 0xAD, 0xD9, 0xAD, 0xD9, 0xAD, 0xD9, 0xAD, 0xD9, 0xAD, 0xD9,
0xAD, 0xD9, 0xAD, 0xD9, 0xAD, 0xD9, 0xAD, 0xD9, 0xAD, 0xD9, 0xAD, 0xD9, 0xAD, 0xD9, 0xAD, 0xD9,
0xAD, 0xD9, 0xAD, 0xD9, 0xAD, 0xD9, 0xAD, 0xD9, 0xAD, 0xD9, 0xAD, 0xD9, 0xAD, 0xD9, 0xAD, 0xD9,
0xAD, 0xD9, 0xAD, 0xD9, 0xAD, 0xD9, 0xAD, 0xD9, 0xAD, 0xD9, 0xAD, 0xD9, 0xAD, 0xD9, 0xAD, 0xD9,
0xAD, 0xD9, 0xAD, 0xD9, 0xAD, 0xD9, 0x9D, 0x36, 0x5B, 0x2D, 0x00, 0x21, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
};
// Total: 8192 bytes
// ─── Byte swapping ──────────────────────────────────────────────────────────
// The ST7789 RAMCTRL is configured for big-endian pixel data (high byte first).
// On the little-endian ESP32-S3, a uint16_t value like 0x07E0 (GREEN) is stored
// as bytes [0xE0, 0x07] in memory. When passed to esp_lcd_panel_draw_bitmap(),
// these bytes are sent directly over SPI, but the display in big-endian mode
// interprets the first byte as high byte, giving 0xE007 = dark red instead of
// green. The PIX() macro pre-swaps bytes so the display receives correct values.
#define PIX(v) __builtin_bswap16(v)
// ─── Low-level helpers ──────────────────────────────────────────────────────
/// Fill a rectangular region with a single 16-bit color, one row at a time.
static void disp_fill_region(int x0, int y0, int x1, int y1, uint16_t color)
{
int width = x1 - x0 + 1;
uint16_t row_buf[240];
uint16_t swapped = PIX(color);
for (int i = 0; i < width; i++) {
row_buf[i] = swapped;
}
for (int y = y0; y <= y1; y++) {
esp_lcd_panel_draw_bitmap(s_panel_handle, x0, y, x1 + 1, y + 1, row_buf);
}
}
/// Draw a single horizontal line from (x0, y) to (x1, y).
static void disp_draw_hspan(int x0, int y, int x1, uint16_t color)
{
int width = x1 - x0 + 1;
uint16_t row[240];
uint16_t swapped = PIX(color);
for (int i = 0; i < width; i++) {
row[i] = swapped;
}
esp_lcd_panel_draw_bitmap(s_panel_handle, x0, y, x0 + width, y + 1, row);
}
// ─── Public API ──────────────────────────────────────────────────────────────
void display_init(void)
{
ESP_LOGI(TAG, "Display init: MOSI=41 CLK=40 CS=39 DC=38 RST=42 BLK_EN=4 BL_PWM=20 on SPI3_HOST");
// --- Backlight enable (GPIO4, active HIGH, with pull-up) ---
gpio_config_t gpio_conf = {};
gpio_conf.intr_type = GPIO_INTR_DISABLE;
gpio_conf.mode = GPIO_MODE_OUTPUT;
gpio_conf.pin_bit_mask = ((uint64_t)0X01 << PIN_LCD_RST) | ((uint64_t)0X01 << PIN_LCD_BLK);
gpio_conf.pull_down_en = GPIO_PULLDOWN_DISABLE;
gpio_conf.pull_up_en = GPIO_PULLUP_ENABLE;
ESP_ERROR_CHECK_WITHOUT_ABORT(gpio_config(&gpio_conf));
gpio_set_level(PIN_LCD_BLK, 1);
// --- Backlight PWM (GPIO20, 30 kHz, 8-bit, ~50% duty) ---
ledc_timer_config_t timer_conf = {};
timer_conf.speed_mode = LEDC_LOW_SPEED_MODE;
timer_conf.duty_resolution = LEDC_TIMER_8_BIT;
timer_conf.timer_num = LEDC_TIMER_3;
timer_conf.freq_hz = 30 * 1000;
timer_conf.clk_cfg = LEDC_USE_RC_FAST_CLK;
ESP_ERROR_CHECK_WITHOUT_ABORT(ledc_timer_config(&timer_conf));
ledc_channel_config_t ledc_conf = {};
ledc_conf.gpio_num = PIN_LCD_BL_PWM;
ledc_conf.speed_mode = LEDC_LOW_SPEED_MODE;
ledc_conf.channel = LEDC_CHANNEL_1;
ledc_conf.intr_type = LEDC_INTR_DISABLE;
ledc_conf.timer_sel = LEDC_TIMER_3;
ledc_conf.duty = 128;
ledc_conf.hpoint = 0;
ledc_conf.flags.output_invert = 0;
ESP_ERROR_CHECK_WITHOUT_ABORT(ledc_channel_config(&ledc_conf));
ESP_LOGI(TAG, "Backlight PWM on GPIO20: duty=%d/255 (%d%%)", ledc_conf.duty,
(ledc_conf.duty * 100) / 255);
// --- Initialize the LCD SPI bus (SPI3_HOST, dedicated to LCD) ---
// This is a separate bus from the W5500 Ethernet (which uses SPI2_HOST).
// Only MOSI and CLK are needed (display write-only).
spi_bus_config_t buscfg;
memset(&buscfg, 0, sizeof(buscfg));
buscfg.mosi_io_num = PIN_LCD_MOSI;
buscfg.miso_io_num = -1; // No MISO (display write-only)
buscfg.sclk_io_num = PIN_LCD_CLK;
buscfg.quadwp_io_num = -1;
buscfg.quadhd_io_num = -1;
buscfg.max_transfer_sz = 240 * 2; // 1 row of RGB565 pixels
ESP_ERROR_CHECK(spi_bus_initialize(LCD_SPI_HOST, &buscfg, SPI_DMA_CH_AUTO));
// --- Create SPI panel IO ---
esp_lcd_panel_io_spi_config_t io_config;
memset(&io_config, 0, sizeof(io_config));
io_config.cs_gpio_num = PIN_LCD_CS;
io_config.dc_gpio_num = PIN_LCD_DC;
io_config.spi_mode = 0;
io_config.pclk_hz = 40 * 1000 * 1000; // 40 MHz
io_config.trans_queue_depth = 4;
io_config.lcd_cmd_bits = 8;
io_config.lcd_param_bits = 8;
ESP_ERROR_CHECK(
esp_lcd_new_panel_io_spi(LCD_SPI_HOST, &io_config, &s_io_handle)
);
// --- Create ST7789 panel ---
esp_lcd_panel_dev_config_t panel_config;
memset(&panel_config, 0, sizeof(panel_config));
panel_config.reset_gpio_num = PIN_LCD_RST;
panel_config.rgb_ele_order = LCD_RGB_ELEMENT_ORDER_RGB;
panel_config.bits_per_pixel = 16;
panel_config.data_endian = LCD_RGB_DATA_ENDIAN_BIG;
ESP_ERROR_CHECK(
esp_lcd_new_panel_st7789(s_io_handle, &panel_config, &s_panel_handle)
);
// --- Reset & init ---
ESP_ERROR_CHECK(esp_lcd_panel_reset(s_panel_handle));
ESP_ERROR_CHECK(esp_lcd_panel_init(s_panel_handle));
// Turn display on
ESP_ERROR_CHECK(esp_lcd_panel_disp_on_off(s_panel_handle, true));
// Enable INVON (color inversion). The Waveshare panel has a reversed
// polarizer that requires data inversion. INVON + the panel's physical
// inversion cancel out so RGB565 data displays with correct colors.
ESP_ERROR_CHECK(esp_lcd_panel_invert_color(s_panel_handle, true));
// Fill with black
display_fill(COLOR_BLACK);
// Quick self-test: flash red, green, then black
ESP_LOGI(TAG, "Self-test: RED");
display_fill(COLOR_RED);
vTaskDelay(pdMS_TO_TICKS(300));
ESP_LOGI(TAG, "Self-test: GREEN");
display_fill(COLOR_GREEN);
vTaskDelay(pdMS_TO_TICKS(300));
ESP_LOGI(TAG, "Self-test: BLACK");
display_fill(COLOR_BLACK);
ESP_LOGI(TAG, "Display initialized successfully");
}
void display_fill(uint16_t color)
{
disp_fill_region(0, 0, DISP_WIDTH - 1, DISP_HEIGHT - 1, color);
}
void display_pixel(int x, int y, uint16_t color)
{
if (x < 0 || x >= DISP_WIDTH || y < 0 || y >= DISP_HEIGHT) {
return;
}
uint16_t pixel = PIX(color);
esp_lcd_panel_draw_bitmap(s_panel_handle, x, y, x + 1, y + 1, &pixel);
}
void display_text(int x, int y, const char *text, uint16_t fg, uint16_t bg, int scale)
{
if (!text || scale < 1) return;
while (*text) {
char c = *text;
int idx;
if (c >= 32 && c <= 126) {
idx = c - 32;
} else if ((unsigned char)c == 176) {
idx = 95; // degree symbol
} else {
idx = 0;
}
const uint8_t *glyph = FONT8x8[idx];
int char_w = 8 * scale;
// Skip characters entirely left of the display
int char_end = x + char_w;
if (char_end < 0) {
x += char_w;
text++;
continue;
}
if (x >= DISP_WIDTH) {
// Past right edge, nothing more will fit
break;
}
for (int row = 0; row < 8; row++) {
uint8_t bits = glyph[row];
// Repeat each source row 'scale' times vertically
for (int rep = 0; rep < scale; rep++) {
int py = y + row * scale + rep;
if (py < 0 || py >= DISP_HEIGHT) continue;
// Build one output row: each source bit becomes 'scale' pixels wide
uint16_t pixel_row[8 * 4]; // max scale=4, width=32
for (int col = 0; col < 8; col++) {
uint16_t color = (bits & (1 << (7 - col))) ? fg : bg;
uint16_t swapped = PIX(color);
for (int s = 0; s < scale; s++) {
pixel_row[col * scale + s] = swapped;
}
}
// Clip the row to display width
int draw_w = char_w;
if (x + draw_w > DISP_WIDTH) {
draw_w = DISP_WIDTH - x;
}
esp_lcd_panel_draw_bitmap(s_panel_handle, x, py, x + draw_w, py + 1, pixel_row);
}
}
x += char_w;
text++;
}
}
void display_rect(int x0, int y0, int x1, int y1, uint16_t color)
{
if (x0 < 0) x0 = 0;
if (y0 < 0) y0 = 0;
if (x1 >= DISP_WIDTH) x1 = DISP_WIDTH - 1;
if (y1 >= DISP_HEIGHT) y1 = DISP_HEIGHT - 1;
if (x0 > x1 || y0 > y1) return;
disp_fill_region(x0, y0, x1, y1, color);
}
void display_dot_online(int x, int y, bool online)
{
uint16_t color = online ? COLOR_GREEN : COLOR_RED;
int cx = x + 8;
int cy = y + 8;
int r = 7;
for (int dy = -r; dy <= r; dy++) {
float dx_f = sqrtf((float)(r * r - dy * dy));
int dx = (int)(0.5f + dx_f);
int x1 = cx - dx;
int x2 = cx + dx;
if (x1 < 0) x1 = 0;
if (x2 >= DISP_WIDTH) x2 = DISP_WIDTH - 1;
int py = cy + dy;
if (py < 0 || py >= DISP_HEIGHT) continue;
disp_draw_hspan(x1, py, x2, color);
}
}
void display_splash(const char *title)
{
display_fill(COLOR_BLACK);
// Color Ethernet RJ45 plug logo (64x64 RGB565), drawn row by row
int logo_x = (DISP_WIDTH - LOGO_W) / 2;
const int row_bytes = LOGO_W * 2; // 128 bytes per row
for (int row = 0; row < LOGO_H; row++) {
const uint8_t *row_data = &LOGO_ETH_COLOR[row * row_bytes];
// Data is already in big-endian RGB565 format
esp_lcd_panel_draw_bitmap(s_panel_handle,
logo_x, 8 + row,
logo_x + LOGO_W, 8 + row + 1,
(const void *)row_data);
}
// Horizontal line below logo
display_rect(30, 82, DISP_WIDTH - 30, 83, COLOR_GREEN);
// Title centered below line
int tx = (DISP_WIDTH - (int)strlen(title) * 16) / 2;
display_text(tx, 100, title, COLOR_CYAN, COLOR_BLACK, 2);
}
void display_booting(bool link_done, bool dhcp_done, bool slaac_done)
{
display_fill(COLOR_BLACK);
// ── Header: centered "BOOTING" ──
{
char hdr[] = "BOOTING";
int hdr_w = strlen(hdr) * 16;
int hdr_x = (DISP_WIDTH - hdr_w) / 2;
if (hdr_x < 0) hdr_x = 0;
display_text(hdr_x, 4, hdr, COLOR_CYAN, COLOR_BLACK, 2);
}
// ── Green underline ──
display_rect(40, 28, DISP_WIDTH - 40, 29, COLOR_GREEN);
// ── [✓] Link ──
{
char line[16];
snprintf(line, sizeof(line), "[%c] Link", link_done ? '+' : ' ');
uint16_t c = link_done ? COLOR_GREEN : COLOR_YELLOW;
display_text(20, 48, line, c, COLOR_BLACK, 2);
}
// ── [✓] DHCP ──
{
char line[16];
snprintf(line, sizeof(line), "[%c] DHCP", dhcp_done ? '+' : ' ');
uint16_t c = dhcp_done ? COLOR_GREEN : COLOR_YELLOW;
display_text(20, 72, line, c, COLOR_BLACK, 2);
}
// ── [✓] SLAAC ──
{
char line[16];
snprintf(line, sizeof(line), "[%c] SLAAC", slaac_done ? '+' : ' ');
uint16_t c = slaac_done ? COLOR_GREEN : COLOR_YELLOW;
display_text(20, 96, line, c, COLOR_BLACK, 2);
}
}
void display_status(const struct test_results_t *results)
{
display_fill(COLOR_BLACK);
// Scale=2: 16x16px per char, 15 chars per line, line height=20px
// Scale=1: 8x8px per char, 30 chars per line, line height=12px
// We use scale=2 for headers/stats and scale=1 for IPv6 data (long addresses)
// Track current Y position
int y = 0;
// ── Line 0: Dot + centered ONLINE/OFFLINE ──
{
const char *status_label = results->link_up ? "ONLINE" : "OFFLINE";
uint16_t status_color = results->link_up ? COLOR_GREEN : COLOR_RED;
int label_w = strlen(status_label) * 16;
int combined_w = 16 + 4 + label_w; // dot(16) + gap(4) + text
int start_x = (DISP_WIDTH - combined_w) / 2;
if (start_x < 0) start_x = 0;
display_dot_online(start_x, y, results->link_up);
display_text(start_x + 20, y, status_label, status_color, COLOR_BLACK, 2);
// Thin cyan separator line under the status label
y += 20;
display_rect(40, y - 2, DISP_WIDTH - 40, y - 1, COLOR_CYAN);
y += 3; // 3px margin below the line
}
// ── Line 1: Latency + Loss: "Lat 50 Los 0" (15 chars = 240px) ──
{
char buf[24];
int lat = results->latency_ms;
float loss = results->packet_loss_pct;
if (lat >= 0) {
// Clamp to 9999
if (lat > 9999) lat = 9999;
if (loss >= 0.0f && loss <= 99.0f) {
snprintf(buf, sizeof(buf), "Lat %4d Los %2.0f", lat, (double)loss);
} else if (loss >= 0.0f) {
snprintf(buf, sizeof(buf), "Lat %4d Los --", lat);
} else {
snprintf(buf, sizeof(buf), "Lat %4d Los --", lat);
}
} else {
if (loss >= 0.0f && loss <= 99.0f) {
snprintf(buf, sizeof(buf), "Lat -- Los %2.0f", (double)loss);
} else {
snprintf(buf, sizeof(buf), "Lat -- Los --");
}
}
// 15 chars max: "Lat 50 Los 0" = 15
uint16_t c;
if (results->latency_v4_ok && results->latency_v6_ok) {
c = COLOR_GREEN;
} else if (results->latency_v4_ok || results->latency_v6_ok) {
c = COLOR_YELLOW;
} else {
c = COLOR_RED;
}
display_text(0, y, buf, c, COLOR_BLACK, 2);
y += 20;
}
// ── Line 2: Temperature ──
{
char buf[24];
if (results->temperature_c > -273.0f) {
float t = results->temperature_c;
if (t < -99.0f) t = -99.0f;
if (t > 999.0f) t = 999.0f;
snprintf(buf, sizeof(buf), "Temp %3.0f \260C", (double)t);
} else {
snprintf(buf, sizeof(buf), "Temp --");
}
display_text(0, y, buf, COLOR_WHITE, COLOR_BLACK, 2);
y += 20;
}
// ── Line 3: == IPv4 == section header ──
{
char hdr[] = "== IPv4 ==";
int hdr_w = strlen(hdr) * 16;
int hdr_x = (DISP_WIDTH - hdr_w) / 2;
if (hdr_x < 0) hdr_x = 0;
display_text(hdr_x, y, hdr, COLOR_CYAN, COLOR_BLACK, 2);
y += 20;
}
// ── Line 4: IPv4 address ──
{
const char *ip = results->ipv4 ? results->ipv4 : "--";
display_text(0, y, ip, results->has_ipv4 ? COLOR_WHITE : COLOR_YELLOW, COLOR_BLACK, 2);
y += 20;
}
// ── Line 5: IPv4 gateway ──
{
const char *gw = results->gateway_ip ? results->gateway_ip : "--";
display_text(0, y, gw, results->has_ipv4 ? COLOR_WHITE : COLOR_YELLOW, COLOR_BLACK, 2);
y += 20;
}
// ── Line 6: == IPv6 == section header ──
{
char hdr[] = "== IPv6 ==";
int hdr_w = strlen(hdr) * 16;
int hdr_x = (DISP_WIDTH - hdr_w) / 2;
if (hdr_x < 0) hdr_x = 0;
display_text(hdr_x, y, hdr, COLOR_CYAN, COLOR_BLACK, 2);
y += 20;
}
// ── Line 7: IPv6 link-local address (fe80::..., scale=1) ──
{
const char *ll = results->ipv6_ll ? results->ipv6_ll : "--";
bool has_v6 = (results->has_ipv6 && results->ipv6_ll && results->ipv6_ll[0] != '-');
display_text(0, y, ll, has_v6 ? COLOR_WHITE : COLOR_YELLOW, COLOR_BLACK, 1);
y += 12;
}
// ── Line 8: IPv6 global address (2xxx::..., scale=1, split if needed) ──
{
const char *gua = results->ipv6_gua ? results->ipv6_gua : "--";
bool has_gua = (results->has_ipv6 && results->ipv6_gua && results->ipv6_gua[0] != '-');
// Determine how many segments fit on one line (max 30 chars at scale=1)
// Each segment: up to 4 hex chars + 1 colon separator
// Split only if the address overflows the display width
int gua_len = (int)strlen(gua);
const int max_line = 30; // max chars at scale=1 (240px / 8)
if (has_gua && gua_len > max_line) {
// Find break point: place as many complete segments as fit
int last_colon = 0;
for (int i = 0; gua[i]; i++) {
if (gua[i] == ':') {
if (i + 1 <= max_line) {
last_colon = i; // this colon fits
} else {
break; // i is past max_line, use previous colon
}
}
}
if (last_colon > 0) {
// Print first part up to and including last_colon
char line1[32];
int len1 = last_colon; // includes the trailing colon
if (len1 > (int)sizeof(line1) - 1) len1 = sizeof(line1) - 1;
memcpy(line1, gua, len1);
line1[len1] = '\0';
display_text(0, y, line1, COLOR_WHITE, COLOR_BLACK, 1);
y += 12;
// Second part: everything after the colon
const char *part2 = gua + last_colon + 1;
display_text(0, y, part2, COLOR_WHITE, COLOR_BLACK, 1);
} else {
display_text(0, y, gua, COLOR_WHITE, COLOR_BLACK, 1);
}
} else {
display_text(0, y, gua, has_gua ? COLOR_WHITE : COLOR_YELLOW, COLOR_BLACK, 1);
}
y += 12;
}
// ── Line 9: IPv6 gateway (router's link-local, scale=1) ──
{
const char *gw6 = results->gateway6_ip ? results->gateway6_ip : "--";
bool has_gw6 = (results->has_ipv6 && results->gateway6_ip && results->gateway6_ip[0] != '-');
display_text(0, y, gw6, has_gw6 ? COLOR_WHITE : COLOR_YELLOW, COLOR_BLACK, 1);
y += 12;
}
// ── Line 10: DNS status (scale=2) ──
{
const char *status;
uint16_t c;
if (results->dns4_ok && results->dns6_ok) {
// Both IPv4 and IPv6 DNS servers returned records
status = "DNS OK";
c = COLOR_GREEN;
} else if (results->dns4_ok && !results->dns6_ok) {
// Only IPv4 DNS worked
status = "DNS v4 OK";
c = COLOR_YELLOW;
} else if (!results->dns4_ok && results->dns6_ok) {
// Only IPv6 DNS worked
status = "DNS v6 OK";
c = COLOR_YELLOW;
} else if (results->dns_timeout) {
status = "DNS FAIL";
c = COLOR_RED;
} else {
status = "DNS --";
c = COLOR_YELLOW;
}
display_text(0, y, status, c, COLOR_BLACK, 2);
y += 20;
}
// ── Line 11: RS25 site-to-site VPN status (scale=2) ──
{
const char *txt;
uint16_t c;
if (results->vpn_reachable) {
txt = "RS25 S2S OK";
c = COLOR_GREEN;
} else {
txt = "RS25 S2S --";
c = COLOR_RED;
}
display_text(0, y, txt, c, COLOR_BLACK, 2);
}
}
// ─── Progress screen ────────────────────────────────────────────────────────
// ─── Progress display state (for spinner-only updates) ──────────────────────
static int s_spinner_x = 0;
static int s_spinner_y = 0;
// ─── Test progress screen ───────────────────────────────────────────────────
void display_progress(const struct test_results_t *results,
int test_index, int frame)
{
display_fill(COLOR_BLACK);
// Top line: spinner + "Test: TestName"
const char *spinner = "|/-\\";
char spin_char[2] = { spinner[frame & 3], '\0' };
display_text(0, 0, spin_char, COLOR_GREEN, COLOR_BLACK, 2);
char running[32];
// test_index is the test just completed; show the next one as running
int next_idx = test_index + 1;
if (next_idx < 0) next_idx = 0;
if (next_idx >= DIAG_TEST_COUNT) {
// All tests done — keep showing the last one
next_idx = DIAG_TEST_COUNT - 1;
}
const char *test_name = g_diag_test_names[next_idx];
snprintf(running, sizeof(running), " Test: %s", test_name);
display_text(16, 0, running, COLOR_WHITE, COLOR_BLACK, 2);
// Completed tests with checkmark prefix
int y = 28;
for (int i = 0; i < results->tests_completed && i < DIAG_TEST_COUNT; i++) {
char line[34];
snprintf(line, sizeof(line), "+ %s", g_diag_test_names[i]);
display_text(0, y, line, COLOR_GREEN, COLOR_BLACK, 2);
y += 20;
}
// Save spinner position for partial updates
s_spinner_x = 0;
s_spinner_y = 0;
}
void display_update_spinner(int frame)
{
const char *spinner = "|/-\\";
char spin_char[2] = { spinner[frame & 3], '\0' };
// Clear the 16x16 area where the spinner sits, then redraw
display_rect(s_spinner_x, s_spinner_y, s_spinner_x + 15, s_spinner_y + 15, COLOR_BLACK);
display_text(s_spinner_x, s_spinner_y, spin_char, COLOR_GREEN, COLOR_BLACK, 2);
}
// ─── Failure screen ─────────────────────────────────────────────────────────
void display_failure(const struct test_results_t *results)
{
display_fill(COLOR_BLACK);
// Big red FAIL header
display_text(0, 0, "TEST FAILED", COLOR_RED, COLOR_BLACK, 2);
// Draw a red underline
display_rect(0, 20, DISP_WIDTH - 1, 21, COLOR_RED);
int y = 32;
// Show failed tests
if (!results->link_up) {
display_text(0, y, "Link: DOWN", COLOR_RED, COLOR_BLACK, 2);
y += 24;
}
if (!results->has_ipv4) {
display_text(0, y, "IPv4: none", COLOR_RED, COLOR_BLACK, 2);
y += 24;
}
if (!results->gateway_reachable_v4) {
display_text(0, y, "Gateway: unreachable", COLOR_RED, COLOR_BLACK, 2);
y += 24;
}
if (!results->uplink_reachable_v4) {
display_text(0, y, "Uplink IPv4: unreachable", COLOR_RED, COLOR_BLACK, 2);
y += 24;
}
if (!results->uplink_reachable_v6) {
display_text(0, y, "Uplink IPv6: unreachable", COLOR_RED, COLOR_BLACK, 2);
y += 24;
}
if (!results->dns_ok) {
display_text(0, y, "DNS: failed", COLOR_RED, COLOR_BLACK, 2);
y += 24;
}
if (y < DISP_HEIGHT - 48) {
display_text(0, DISP_HEIGHT - 40, "Retrying in 30s...", COLOR_YELLOW, COLOR_BLACK, 2);
}
}