diff --git a/Makefile b/Makefile index 8646c26..bf92750 100644 --- a/Makefile +++ b/Makefile @@ -127,8 +127,8 @@ CORE_SRCS = kernel/main.c kernel/task.c kernel/sync.c kernel/timer.c kernel/prin kernel/signal.c kernel/workqueue.c kernel/tsc.c kernel/vt_art.c \ kernel/sub/sub_runtime.c kernel/sub/sub_vm.c \ kernel/wait.c kernel/futex.c kernel/rcu.c kernel/ktest.c \ - lib/string.c lib/vsprintf.c lib/bitmap.c lib/rbtree.c lib/kfifo.c lib/hashtable.c \ - init/cmdline.c init/service.c usr/initramfs.c block/block.c block/elevator.c \ + lib/string.c lib/vsprintf.c lib/bitmap.c lib/rbtree.c lib/kfifo.c lib/hashtable.c lib/font8x8.c \ + init/cmdline.c init/service.c init/bootlogo.c init/logo_data.c usr/initramfs.c block/block.c block/elevator.c \ ipc/sem.c ipc/shm.c ipc/shm_posix.c ipc/pipe.c ipc/ipc.c ipc/msg.c \ crypto/sha256.c crypto/md5.c crypto/crc32.c crypto/prng.c sound/beep.c diff --git a/boot/stage2.asm b/boot/stage2.asm index e2c9627..0ef668e 100644 --- a/boot/stage2.asm +++ b/boot/stage2.asm @@ -83,30 +83,54 @@ start2: .mmap_store_done: ; ------------------------------------------------------------- - ; Step 3: Load Kernel from Disk to 0x10000 (Conventional RAM) - ; 12 chunks x 64 sectors = 768 sectors (384 KB) + ; Step 3: Load the kernel to 0x100000 (just above 1 MB) + ; + ; INT 13h can only land data below 1 MB, and staging the whole kernel in + ; conventional RAM caps it at roughly 576 KB before the load runs into + ; video memory at 0xA0000. So each 32 KB chunk is read into one fixed + ; low buffer at 0x10000 and copied straight up to its final address. + ; + ; The copy needs 32-bit offsets from real mode, which is what unreal mode + ; provides: enter protected mode just long enough to load a 4 GB-limit + ; descriptor, then drop back. A real-mode segment load afterwards rewrites + ; only the base and leaves that limit in the descriptor cache. ; ------------------------------------------------------------- mov si, msg_kernel_load call print_string_16 mov word [kernel_dap_off], 0x0000 - mov word [kernel_dap_seg], 0x1000 + mov word [kernel_dap_seg], KERNEL_STAGE_SEG mov dword [kernel_dap_lba], 16 mov dword [kernel_dap_lba + 4], 0 - mov cx, 24 ; 24 chunks * 64 sectors = 1536 sectors (768 KB) + mov dword [kernel_dest], 0x100000 + mov cx, KERNEL_CHUNKS .kernel_chunk_loop: push cx + + ; Read one chunk into the staging buffer. mov ah, 0x42 mov dl, [boot_drive] mov si, kernel_dap int 0x13 jc .kernel_disk_error - ; Advance LBA by 64 sectors - add dword [kernel_dap_lba], 64 - ; Advance Segment by 0x800 (64 sectors * 512 bytes = 32768 bytes = 0x800 paragraphs) - add word [kernel_dap_seg], 0x0800 + ; Relocate it above 1 MB. Unreal mode is re-established every pass, since + ; the BIOS disk call is free to reload the segment registers. + call enter_unreal_mode + + xor ax, ax + mov ds, ax + mov es, ax + mov esi, KERNEL_STAGE_ADDR + mov edi, [kernel_dest] + mov ecx, (KERNEL_CHUNK_SECTORS * 512) / 4 + a32 rep movsd + + ; Advance the source LBA and the destination address by one chunk. + add dword [kernel_dap_lba], KERNEL_CHUNK_SECTORS + add dword [kernel_dest], KERNEL_CHUNK_SECTORS * 512 + pop cx loop .kernel_chunk_loop @@ -196,11 +220,7 @@ pm_entry: mov ss, ax mov esp, 0x7C00 - ; Copy kernel from 0x10000 to 0x100000 (1MB mark) - 192 KB (384 sectors) - mov esi, 0x10000 - mov edi, 0x100000 - mov ecx, (1536 * 512) / 4 - rep movsd + ; The kernel was relocated to 0x100000 chunk by chunk during the load. ; Enable PAE in CR4 mov eax, cr4 @@ -247,6 +267,50 @@ lm_entry: ; Data Section ; ----------------------------------------------------------------- BITS 16 +; Kernel image layout. The image is a 2880-sector floppy and the kernel starts +; at LBA 16, so 44 chunks reads every remaining sector: a 1.375 MB ceiling that +; the loader can grow into without touching this file again. +KERNEL_CHUNK_SECTORS equ 64 +KERNEL_CHUNKS equ 44 +KERNEL_STAGE_SEG equ 0x1000 +KERNEL_STAGE_ADDR equ 0x10000 + +; ----------------------------------------------------------------------------- +; enter_unreal_mode +; +; Leaves the CPU in real mode with DS and ES carrying a 4 GB segment limit, so +; `a32 rep movsd` can reach memory above 1 MB. Clobbers EAX and BX. +; ----------------------------------------------------------------------------- +enter_unreal_mode: + cli + push ds + push es + + lgdt [gdt_descriptor] + + mov eax, cr0 + or al, 1 + mov cr0, eax + jmp $+2 ; Flush the prefetch queue + + mov bx, 0x10 ; Flat 32-bit data descriptor + mov ds, bx + mov es, bx + + and al, 0xFE + mov cr0, eax + jmp $+2 + + ; Popping restores the real-mode segment bases; the 4 GB limits loaded + ; above stay in the descriptor cache, which is what makes this "unreal". + pop es + pop ds + sti + ret + +align 4 +kernel_dest: dd 0x100000 + align 4 boot_drive: db 0 @@ -261,11 +325,11 @@ align 4 kernel_dap: db 0x10 db 0 - dw 64 ; 64 sectors per chunk (32 KB) + dw KERNEL_CHUNK_SECTORS ; Sectors per chunk (32 KB) kernel_dap_off: dw 0x0000 kernel_dap_seg: - dw 0x1000 + dw KERNEL_STAGE_SEG kernel_dap_lba: dq 16 diff --git a/drivers/video/canvas.c b/drivers/video/canvas.c index 9b5afdd..66110a9 100644 --- a/drivers/video/canvas.c +++ b/drivers/video/canvas.c @@ -1,4 +1,5 @@ #include +#include #include #include #include @@ -8,100 +9,6 @@ static uint32_t* back_buffer = NULL; static uint32_t screen_width = 320; static uint32_t screen_height = 200; -// Basic 8x8 font bitmap for ASCII characters (32..126) -static const uint8_t font8x8_basic[96][8] = { - {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // (space) - {0x18,0x3c,0x3c,0x18,0x18,0x00,0x18,0x00}, // ! - {0x66,0x66,0x24,0x00,0x00,0x00,0x00,0x00}, // " - {0x6c,0x6c,0xfe,0x6c,0xfe,0x6c,0x6c,0x00}, // # - {0x18,0x3e,0x60,0x3c,0x06,0x7c,0x18,0x00}, // $ - {0x00,0x63,0x66,0x0c,0x18,0x33,0x63,0x00}, // % - {0x38,0x6c,0x38,0x76,0xdc,0xcc,0x76,0x00}, // & - {0x18,0x18,0x30,0x00,0x00,0x00,0x00,0x00}, // ' - {0x0c,0x18,0x30,0x30,0x30,0x18,0x0c,0x00}, // ( - {0x30,0x18,0x0c,0x0c,0x0c,0x18,0x30,0x00}, // ) - {0x00,0x66,0x3c,0xff,0x3c,0x66,0x00,0x00}, // * - {0x00,0x18,0x18,0x7e,0x18,0x18,0x00,0x00}, // + - {0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x30}, // , - {0x00,0x00,0x00,0x7e,0x00,0x00,0x00,0x00}, // - - {0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00}, // . - {0x06,0x0c,0x18,0x30,0x60,0xc0,0x80,0x00}, // / - {0x7c,0xc6,0xce,0xd6,0xe6,0xc6,0x7c,0x00}, // 0 - {0x18,0x38,0x18,0x18,0x18,0x18,0x7e,0x00}, // 1 - {0x7c,0xc6,0x06,0x1c,0x30,0x66,0xfe,0x00}, // 2 - {0x7c,0xc6,0x06,0x3c,0x06,0xc6,0x7c,0x00}, // 3 - {0x1c,0x3c,0x6c,0xcc,0xfe,0x0c,0x1e,0x00}, // 4 - {0xfe,0xc0,0xfc,0x06,0x06,0xc6,0x7c,0x00}, // 5 - {0x7c,0xc6,0xc0,0xfc,0xc6,0xc6,0x7c,0x00}, // 6 - {0xfe,0x06,0x0c,0x18,0x30,0x30,0x30,0x00}, // 7 - {0x7c,0xc6,0xc6,0x7c,0xc6,0xc6,0x7c,0x00}, // 8 - {0x7c,0xc6,0xc6,0x7e,0x06,0xc6,0x7c,0x00}, // 9 - {0x00,0x18,0x18,0x00,0x18,0x18,0x00,0x00}, // : - {0x00,0x18,0x18,0x00,0x18,0x18,0x30,0x00}, // ; - {0x06,0x0c,0x18,0x30,0x18,0x0c,0x06,0x00}, // < - {0x00,0x00,0x7e,0x00,0x7e,0x00,0x00,0x00}, // = - {0x60,0x30,0x18,0x0c,0x18,0x30,0x60,0x00}, // > - {0x7c,0xc6,0x0c,0x18,0x18,0x00,0x18,0x00}, // ? - {0x7c,0xc6,0xde,0xde,0xdc,0xc0,0x7c,0x00}, // @ - {0x38,0x6c,0xc6,0xfe,0xc6,0xc6,0xc6,0x00}, // A - {0xfc,0x66,0x66,0x7c,0x66,0x66,0xfc,0x00}, // B - {0x3c,0x66,0xc0,0xc0,0xc0,0x66,0x3c,0x00}, // C - {0xf8,0x6c,0x66,0x66,0x66,0x6c,0xf8,0x00}, // D - {0xfe,0x62,0x68,0x78,0x68,0x62,0xfe,0x00}, // E - {0xfe,0x62,0x68,0x78,0x68,0x60,0xf0,0x00}, // F - {0x3c,0x66,0xc0,0xc0,0xce,0x66,0x3a,0x00}, // G - {0xc6,0xc6,0xc6,0xfe,0xc6,0xc6,0xc6,0x00}, // H - {0x7e,0x18,0x18,0x18,0x18,0x18,0x7e,0x00}, // I - {0x1e,0x0c,0x0c,0x0c,0xcc,0xcc,0x78,0x00}, // J - {0xe6,0x66,0x6c,0x78,0x6c,0x66,0xe6,0x00}, // K - {0xf0,0x60,0x60,0x60,0x62,0x66,0xfe,0x00}, // L - {0xc6,0xee,0xfe,0xfe,0xd6,0xc6,0xc6,0x00}, // M - {0xc6,0xe6,0xf6,0xde,0xce,0xc6,0xc6,0x00}, // N - {0x7c,0xc6,0xc6,0xc6,0xc6,0xc6,0x7c,0x00}, // O - {0xfc,0x66,0x66,0x7c,0x60,0x60,0xf0,0x00}, // P - {0x7c,0xc6,0xc6,0xc6,0xd6,0x7c,0x0e,0x00}, // Q - {0xfc,0x66,0x66,0x7c,0x6c,0x66,0xe6,0x00}, // R - {0x7c,0xc6,0x60,0x38,0x0c,0xc6,0x7c,0x00}, // S - {0x7e,0x18,0x18,0x18,0x18,0x18,0x18,0x00}, // T - {0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0x7c,0x00}, // U - {0xc6,0xc6,0xc6,0xc6,0x6c,0x38,0x10,0x00}, // V - {0xc6,0xc6,0xd6,0xfe,0xfe,0xee,0xc6,0x00}, // W - {0xc6,0x6c,0x38,0x38,0x6c,0xc6,0x00,0x00}, // X - {0x66,0x66,0x66,0x3c,0x18,0x18,0x3c,0x00}, // Y - {0xfe,0x06,0x0c,0x18,0x30,0x60,0xfe,0x00}, // Z - {0x3c,0x30,0x30,0x30,0x30,0x30,0x3c,0x00}, // [ - {0xc0,0x60,0x30,0x18,0x0c,0x06,0x02,0x00}, // backslash - {0x3c,0x0c,0x0c,0x0c,0x0c,0x0c,0x3c,0x00}, // ] - {0x10,0x38,0x6c,0xc6,0x00,0x00,0x00,0x00}, // ^ - {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff}, // _ - {0x30,0x18,0x0c,0x00,0x00,0x00,0x00,0x00}, // ` - {0x00,0x00,0x78,0x0c,0x7c,0xcc,0x76,0x00}, // a - {0xe0,0x60,0x7c,0x66,0x66,0x66,0xdc,0x00}, // b - {0x00,0x00,0x78,0xcc,0xc0,0xcc,0x78,0x00}, // c - {0x1c,0x0c,0x7c,0xcc,0xcc,0xcc,0x76,0x00}, // d - {0x00,0x00,0x78,0xcc,0xfc,0xc0,0x78,0x00}, // e - {0x38,0x6c,0x60,0xf0,0x60,0x60,0xf0,0x00}, // f - {0x00,0x00,0x76,0xcc,0xcc,0x7c,0x0c,0xf8}, // g - {0xe0,0x60,0x6c,0x76,0x66,0x66,0xe6,0x00}, // h - {0x18,0x00,0x38,0x18,0x18,0x18,0x3c,0x00}, // i - {0x0c,0x00,0x1c,0x0c,0x0c,0xcc,0xcc,0x78}, // j - {0xe0,0x60,0x66,0x6c,0x78,0x6c,0xe6,0x00}, // k - {0x38,0x18,0x18,0x18,0x18,0x18,0x3c,0x00}, // l - {0x00,0x00,0xec,0xfe,0xd6,0xd6,0xd6,0x00}, // m - {0x00,0x00,0xdc,0x66,0x66,0x66,0x66,0x00}, // n - {0x00,0x00,0x7c,0xc6,0xc6,0xc6,0x7c,0x00}, // o - {0x00,0x00,0xdc,0x66,0x66,0x7c,0x60,0xf0}, // p - {0x00,0x00,0x76,0xcc,0xcc,0x7c,0x0c,0x1e}, // q - {0x00,0x00,0xdc,0x76,0x60,0x60,0xf0,0x00}, // r - {0x00,0x00,0x7c,0xc0,0x78,0x0c,0xf8,0x00}, // s - {0x10,0x30,0x7c,0x30,0x30,0x34,0x18,0x00}, // t - {0x00,0x00,0xcc,0xcc,0xcc,0xcc,0x76,0x00}, // u - {0x00,0x00,0xc6,0xc6,0xc6,0x6c,0x38,0x00}, // v - {0x00,0x00,0xc6,0xd6,0xfe,0xfe,0x6c,0x00}, // w - {0x00,0x00,0xc6,0x6c,0x38,0x6c,0xc6,0x00}, // x - {0x00,0x00,0xc6,0xc6,0xce,0x76,0x06,0x7c}, // y - {0x00,0x00,0xfe,0x0c,0x38,0x60,0xfe,0x00}, // z -}; void canvas_init(void) { const fb_info_t* fb = fb_get_info(); @@ -192,7 +99,7 @@ void canvas_draw_circle(int cx, int cy, int r, uint32_t color, bool filled) { void canvas_draw_char(int x, int y, char c, uint32_t color, uint32_t bg_color) { if (c < 32 || c > 126) c = ' '; - const uint8_t* glyph = font8x8_basic[c - 32]; + const uint8_t* glyph = font8x8_glyph(c); for (int row = 0; row < 8; row++) { uint8_t line = glyph[row]; diff --git a/drivers/video/fb.c b/drivers/video/fb.c index a9b1f64..6db091a 100644 --- a/drivers/video/fb.c +++ b/drivers/video/fb.c @@ -1,4 +1,5 @@ #include +#include #include #include @@ -41,9 +42,22 @@ void fb_clear(uint32_t color) { } void fb_draw_char(uint32_t x, uint32_t y, char c, uint32_t fg, uint32_t bg) { - (void)c; - fb_draw_rect(x, y, 8, 16, bg); - fb_draw_rect(x + 2, y + 2, 4, 12, fg); + const uint8_t* glyph = font8x8_glyph(c); + + // A background of 0 means "leave what is already there", which lets the + // boot splash draw status text straight over its gradient. + bool opaque = (bg != 0); + + for (uint32_t row = 0; row < FONT8X8_HEIGHT; row++) { + uint8_t bits = glyph[row]; + for (uint32_t col = 0; col < FONT8X8_WIDTH; col++) { + if (bits & (0x80u >> col)) { + fb_put_pixel(x + col, y + row, fg); + } else if (opaque) { + fb_put_pixel(x + col, y + row, bg); + } + } + } } void fb_draw_string(uint32_t x, uint32_t y, const char* str, uint32_t fg, uint32_t bg) { diff --git a/include/init/bootlogo.h b/include/init/bootlogo.h new file mode 100644 index 0000000..b7865e7 --- /dev/null +++ b/include/init/bootlogo.h @@ -0,0 +1,49 @@ +#ifndef _INIT_BOOTLOGO_H +#define _INIT_BOOTLOGO_H + +#include +#include +#include + +// SUB-OS boot logo. +// +// The logo appears in two forms because the framebuffer does not exist for the +// first third of boot. Until the video driver is up, an ASCII rendition goes to +// the text console and the serial line; once fb_init() and bochs_vbe_init() +// have run, the real bitmap takes over as a graphical splash with a progress +// bar, and the remaining boot log continues on serial only. +// +// Both forms are generated from the same artwork by scripts/mklogo.py. + +// --- Generated asset (init/logo_data.c) ------------------------------------ +extern const int boot_logo_width; +extern const int boot_logo_height; +extern const uint32_t boot_logo_palette[16]; +// Bit N set means palette entry N is background and should not be drawn. +extern const uint16_t boot_logo_transparent_mask; +extern const uint8_t boot_logo_bitmap[]; +extern const char* const boot_logo_ascii[]; + +// --- Text console ---------------------------------------------------------- +// Draw the ASCII logo and version banner. Safe to call before any driver +// beyond printk is initialised. +void boot_logo_print_text(void); + +// --- Graphical splash ------------------------------------------------------ +// Take over the framebuffer. Returns false when no framebuffer is available, +// in which case the caller should keep logging to the text console. +bool boot_logo_splash_begin(void); + +// Update the splash. `percent` is clamped to 0..100; `status` may be NULL. +void boot_logo_splash_progress(int percent, const char* status); + +// Release the splash so the desktop (or the TTY) can own the screen again. +void boot_logo_splash_end(void); + +bool boot_logo_splash_active(void); + +// Draw the logo at an arbitrary position and integer scale, for callers that +// want the mark without the splash chrome (the desktop About box, say). +void boot_logo_draw(int x, int y, int scale); + +#endif // _INIT_BOOTLOGO_H diff --git a/include/kernel/printk.h b/include/kernel/printk.h index 3f107fd..cd0097b 100644 --- a/include/kernel/printk.h +++ b/include/kernel/printk.h @@ -4,6 +4,7 @@ #include #include #include +#include #include // Linux-compatible log level prefixes @@ -50,4 +51,20 @@ int kprintf(const char* fmt, ...); // Alias for compatibility void dmesg_dump(void); const char* dmesg_get_buffer(size_t* size_out); +// --------------------------------------------------------------------------- +// Console redirection +// +// While a sink is installed, printk output is handed to the callback instead +// of the text console, so a caller can run a subsystem that reports via printk +// and capture what it printed. The serial console and the dmesg ring still +// receive everything, which keeps a captured run debuggable. +// +// The sink must not itself call printk; re-entrant output is dropped. +// --------------------------------------------------------------------------- +typedef void (*printk_sink_fn_t)(const char* text, size_t len, void* ctx); + +void printk_set_sink(printk_sink_fn_t fn, void* ctx); +void printk_clear_sink(void); +bool printk_has_sink(void); + #endif // _KERNEL_PRINTK_H diff --git a/include/lib/font8x8.h b/include/lib/font8x8.h new file mode 100644 index 0000000..2973e2a --- /dev/null +++ b/include/lib/font8x8.h @@ -0,0 +1,23 @@ +#ifndef _LIB_FONT8X8_H +#define _LIB_FONT8X8_H + +#include + +// Shared 8x8 bitmap console font. +// +// The framebuffer console, the 2D canvas rasterizer and the desktop compositor +// all render text from this one table. Each glyph is 8 bytes, one per scanline, +// with the most significant bit at the left of the cell. + +#define FONT8X8_WIDTH 8 +#define FONT8X8_HEIGHT 8 +#define FONT8X8_FIRST 32 +#define FONT8X8_LAST 127 +#define FONT8X8_GLYPHS (FONT8X8_LAST - FONT8X8_FIRST + 1) + +extern const uint8_t font8x8_basic[FONT8X8_GLYPHS][FONT8X8_HEIGHT]; + +// Scanlines for `c`, substituting '?' for anything unprintable. +const uint8_t* font8x8_glyph(char c); + +#endif // _LIB_FONT8X8_H diff --git a/include/userland/shell.h b/include/userland/shell.h index 742c545..0f638c1 100644 --- a/include/userland/shell.h +++ b/include/userland/shell.h @@ -1,9 +1,29 @@ #ifndef _USERLAND_SHELL_H #define _USERLAND_SHELL_H +#include + #define MAX_COMMAND_LENGTH 256 void shell_init(void); void shell_run(void); +// Shared builtin dispatcher. +// +// Some commands (neofetch, calc, matrix, history, tty, ...) are shell builtins +// rather than LazyBox applets. Both the kernel TTY shell and the desktop +// terminal route through this so the two consoles accept the same vocabulary. +// +// `raw_cmd` is the untokenized line, which the argument-slurping builtins such +// as calc and hexdump need. Returns true if the command was recognised. +// +// `allow_blocking` is false for callers that must not be suspended -- the +// desktop compositor drives input from its own frame loop, so builtins that +// animate or wait for a key are refused there. +bool shell_execute_builtin(const char* raw_cmd, int argc, char** argv, bool allow_blocking); + +// True when the name is a builtin, regardless of whether it can run here. +bool shell_is_builtin(const char* name); +bool shell_builtin_blocks(const char* name); + #endif // _USERLAND_SHELL_H diff --git a/init/bootlogo.c b/init/bootlogo.c new file mode 100644 index 0000000..b6cd45e --- /dev/null +++ b/init/bootlogo.c @@ -0,0 +1,243 @@ +// SUB-OS Boot Logo & Splash Screen +// +// Two presentations of the same artwork, because the framebuffer only exists +// from step [5/14] onward: +// +// * boot_logo_print_text() -- ASCII rendition on the text console and the +// serial line, shown from the very first moments of the boot. +// * boot_logo_splash_*() -- the real bitmap on the framebuffer, with a +// progress bar, once the video driver is up. +// +// The bitmap is 4-bit palette indexed (init/logo_data.c, generated by +// scripts/mklogo.py), so 160x160 pixels cost 12.5 KB rather than 100 KB. + +#include +#include +#include +#include +#include +#include +#include +#include + +#define SPLASH_BG_TOP 0xFF0B132B +#define SPLASH_BG_BOTTOM 0xFF1C2541 +#define SPLASH_ACCENT 0xFF38BDF8 +#define SPLASH_ACCENT_LO 0xFF0284C7 +#define SPLASH_TEXT 0xFFF8FAFC +#define SPLASH_MUTED 0xFF94A3B8 +#define SPLASH_TRACK 0xFF1E293B +#define SPLASH_BORDER 0xFF475569 + +// Boot reaches the desktop within a few hundred milliseconds, so without a +// floor the logo would flash past unseen. Hold it briefly and animate the bar +// to completion during the hold, which also gives the splash a natural finish. +#define SPLASH_MIN_MS 1800 +#define SPLASH_FRAME_MS 20 + +static bool g_splash_active = false; +static uint64_t g_splash_start_ticks = 0; +static uint64_t g_splash_hold_ticks = 0; +static int g_logo_x = 0, g_logo_y = 0, g_logo_scale = 1; +static int g_bar_x = 0, g_bar_y = 0, g_bar_w = 0; +static int g_status_y = 0; +static int g_last_percent = -1; + +// --------------------------------------------------------------------------- +// Text console +// --------------------------------------------------------------------------- + +void boot_logo_print_text(void) { + printk("\n"); + for (int i = 0; boot_logo_ascii[i] != NULL; i++) { + printk(ANSI_BRIGHT_CYAN " %s\n" ANSI_RESET, boot_logo_ascii[i]); + } + printk("\n"); + printk(ANSI_BRIGHT_WHITE " S U B - O S\n" ANSI_RESET); + printk(ANSI_BRIGHT_BLACK " Modular Monolithic Kernel %s\n" ANSI_RESET, + SUBOS_VERSION_STRING); + printk("\n"); +} + +// --------------------------------------------------------------------------- +// Bitmap blitting +// --------------------------------------------------------------------------- + +// Unpack one 4-bit index. Two pixels share a byte, high nibble first. +static inline uint8_t logo_index_at(int px, int py) { + int linear = py * boot_logo_width + px; + uint8_t byte = boot_logo_bitmap[linear >> 1]; + return (linear & 1) ? (byte & 0x0F) : (byte >> 4); +} + +void boot_logo_draw(int x, int y, int scale) { + if (scale < 1) scale = 1; + + const fb_info_t* fb = fb_get_info(); + if (!fb || !fb->active) return; + + for (int py = 0; py < boot_logo_height; py++) { + for (int px = 0; px < boot_logo_width; px++) { + uint8_t index = logo_index_at(px, py); + + // Leave the artwork's transparent surround alone so the logo sits + // on the gradient rather than inside a flat rectangle. + if (boot_logo_transparent_mask & (1u << index)) continue; + + uint32_t color = boot_logo_palette[index]; + + if (scale == 1) { + fb_put_pixel((uint32_t)(x + px), (uint32_t)(y + py), color); + } else { + fb_draw_rect((uint32_t)(x + px * scale), (uint32_t)(y + py * scale), + (uint32_t)scale, (uint32_t)scale, color); + } + } + } +} + +// --------------------------------------------------------------------------- +// Splash screen +// --------------------------------------------------------------------------- + +static void draw_gradient(int width, int height) { + uint32_t top = SPLASH_BG_TOP, bottom = SPLASH_BG_BOTTOM; + + int tr = (top >> 16) & 0xFF, tg = (top >> 8) & 0xFF, tb = top & 0xFF; + int br = (bottom >> 16) & 0xFF, bg = (bottom >> 8) & 0xFF, bb = bottom & 0xFF; + + for (int y = 0; y < height; y++) { + int r = tr + ((br - tr) * y) / (height ? height : 1); + int g = tg + ((bg - tg) * y) / (height ? height : 1); + int b = tb + ((bb - tb) * y) / (height ? height : 1); + fb_draw_rect(0, (uint32_t)y, (uint32_t)width, 1, + 0xFF000000u | ((uint32_t)r << 16) | ((uint32_t)g << 8) | (uint32_t)b); + } +} + +static void draw_centered(int y, const char* text, uint32_t color, int screen_w) { + int width = (int)strlen(text) * 8; + fb_draw_string((uint32_t)((screen_w - width) / 2), (uint32_t)y, text, color, 0); +} + +bool boot_logo_splash_begin(void) { + const fb_info_t* fb = fb_get_info(); + if (!fb || !fb->active || !fb->address || fb->width == 0 || fb->height == 0) { + return false; + } + + int sw = (int)fb->width; + int sh = (int)fb->height; + + // Double the logo when the panel is tall enough to carry it; otherwise the + // splash would crowd out the progress bar. + g_logo_scale = (sh >= 560 && sw >= 640) ? 2 : 1; + int logo_px = boot_logo_width * g_logo_scale; + + g_logo_x = (sw - logo_px) / 2; + g_logo_y = (sh - logo_px) / 2 - 60; + if (g_logo_y < 12) g_logo_y = 12; + + g_bar_w = (sw * 45) / 100; + if (g_bar_w > 420) g_bar_w = 420; + g_bar_x = (sw - g_bar_w) / 2; + g_bar_y = g_logo_y + logo_px + 56; + g_status_y = g_bar_y + 26; + + draw_gradient(sw, sh); + boot_logo_draw(g_logo_x, g_logo_y, g_logo_scale); + + draw_centered(g_logo_y + logo_px + 18, "S U B - O S", SPLASH_TEXT, sw); + draw_centered(g_logo_y + logo_px + 34, SUBOS_VERSION_STRING, SPLASH_MUTED, sw); + + // Progress track + fb_draw_rect((uint32_t)g_bar_x, (uint32_t)g_bar_y, (uint32_t)g_bar_w, 12, SPLASH_TRACK); + fb_draw_rect((uint32_t)g_bar_x, (uint32_t)g_bar_y, (uint32_t)g_bar_w, 1, SPLASH_BORDER); + fb_draw_rect((uint32_t)g_bar_x, (uint32_t)(g_bar_y + 11), (uint32_t)g_bar_w, 1, SPLASH_BORDER); + fb_draw_rect((uint32_t)g_bar_x, (uint32_t)g_bar_y, 1, 12, SPLASH_BORDER); + fb_draw_rect((uint32_t)(g_bar_x + g_bar_w - 1), (uint32_t)g_bar_y, 1, 12, SPLASH_BORDER); + + draw_centered(sh - 20, "Modular Monolithic Kernel", 0xFF64748B, sw); + + g_splash_active = true; + g_last_percent = -1; + g_splash_start_ticks = pit_get_ticks(); + + // The PIT runs at 100 Hz, so one tick is 10 ms. + uint32_t hold_ms = SPLASH_MIN_MS; + const char* param = init_get_param("splashtime"); + if (param) { + int requested = atoi(param); + if (requested >= 0 && requested <= 10000) hold_ms = (uint32_t)requested; + } + g_splash_hold_ticks = hold_ms / 10; + + boot_logo_splash_progress(0, "Starting kernel subsystems"); + return true; +} + +void boot_logo_splash_progress(int percent, const char* status) { + if (!g_splash_active) return; + + const fb_info_t* fb = fb_get_info(); + if (!fb || !fb->active) return; + + if (percent < 0) percent = 0; + if (percent > 100) percent = 100; + + // The bar only ever grows, so repaint just the newly filled span. + int filled = ((g_bar_w - 2) * percent) / 100; + if (percent > g_last_percent) { + fb_draw_rect((uint32_t)(g_bar_x + 1), (uint32_t)(g_bar_y + 1), + (uint32_t)filled, 10, SPLASH_ACCENT); + // A darker leading edge gives the fill some depth. + if (filled > 2) { + fb_draw_rect((uint32_t)(g_bar_x + 1), (uint32_t)(g_bar_y + 8), + (uint32_t)filled, 3, SPLASH_ACCENT_LO); + } + g_last_percent = percent; + } + + if (status) { + int sw = (int)fb->width; + // Clear the previous status before writing the new one. + fb_draw_rect(0, (uint32_t)g_status_y, (uint32_t)sw, 10, SPLASH_BG_BOTTOM); + + char line[80]; + snprintf(line, sizeof(line), "%s ... %d%%", status, percent); + draw_centered(g_status_y, line, SPLASH_MUTED, sw); + } +} + +void boot_logo_splash_end(void) { + if (!g_splash_active) return; + + // Sweep whatever is left of the bar to 100% while waiting out the hold, so + // a fast boot still shows a complete progress animation rather than a jump. + uint64_t deadline = g_splash_start_ticks + g_splash_hold_ticks; + int start_percent = (g_last_percent < 0) ? 0 : g_last_percent; + + while (pit_get_ticks() < deadline) { + uint64_t now = pit_get_ticks(); + uint64_t elapsed = now - g_splash_start_ticks; + + int percent = start_percent; + if (g_splash_hold_ticks > 0) { + int span = 100 - start_percent; + percent = start_percent + (int)((elapsed * (uint64_t)span) / g_splash_hold_ticks); + } + if (percent > 100) percent = 100; + + boot_logo_splash_progress(percent, "Starting the desktop environment"); + pit_sleep(SPLASH_FRAME_MS); + } + + boot_logo_splash_progress(100, "Ready"); + + g_splash_active = false; + g_last_percent = -1; +} + +bool boot_logo_splash_active(void) { + return g_splash_active; +} diff --git a/init/logo_data.c b/init/logo_data.c new file mode 100644 index 0000000..243a9cf --- /dev/null +++ b/init/logo_data.c @@ -0,0 +1,862 @@ +// Generated by scripts/mklogo.py -- do not edit by hand. +// Source artwork: logo_SUB.png + +#include + +const int boot_logo_width = 160; +const int boot_logo_height = 160; + +// Palette entries that are background rather than artwork; the renderer +// skips these so the logo composites onto whatever is behind it. +const uint16_t boot_logo_transparent_mask = 0x7800; + +// 16-entry ARGB palette; index 0 is the wallpaper background. +const uint32_t boot_logo_palette[16] = { + 0xFFFEFDFD, + 0xFF77D4F6, + 0xFF1C94C6, + 0xFF232D32, + 0xFF211F1E, + 0xFF201F1F, + 0xFF201E1F, + 0xFF201E1E, + 0xFF201E1D, + 0xFF1E1E22, + 0xFF1D1819, + 0xFF0B142C, + 0xFF0B132C, + 0xFF0B132B, + 0xFF0A132C, + 0xFF141016, +}; + +// 160x160 pixels, two 4-bit indices per byte, row major. +const uint8_t boot_logo_bitmap[12800] = { + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDE, + 0xEE, 0xBB, 0xBB, 0x99, 0x99, 0x96, 0x55, 0x44, 0x44, 0x55, 0x69, 0x99, 0x99, 0xBB, 0xBB, 0xEE, + 0xED, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDE, 0xEC, 0xBB, + 0x99, 0x96, 0x44, 0x44, 0x88, 0x87, 0x77, 0x77, 0x77, 0x77, 0x78, 0x88, 0x44, 0x44, 0x69, 0x99, + 0xBB, 0xCE, 0xED, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xEC, 0xBB, 0x99, 0x44, + 0x44, 0x87, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x78, 0x44, + 0x44, 0x99, 0xBB, 0xCE, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDE, 0xBB, 0x99, 0x44, 0x48, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x84, 0x44, 0x99, 0xBB, 0xED, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDE, 0xEC, 0xB9, 0x94, 0x48, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x84, 0x49, 0x9B, 0xCE, 0xED, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xEB, 0xB9, 0x44, 0x87, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x75, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x78, 0x44, 0x9B, 0xBE, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xEB, 0x96, 0x48, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x75, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x76, 0x8A, 0x57, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x84, 0x69, 0xBE, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xEB, 0x94, 0x48, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x8A, 0x56, 0x77, 0x77, 0x77, 0x77, 0x77, 0x5A, 0x33, 0xA9, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x84, 0x49, 0xBE, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xEB, 0x94, 0x47, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x68, + 0x33, 0xA8, 0x57, 0x77, 0x77, 0x77, 0x77, 0x78, 0x52, 0x3A, 0x95, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x74, 0x49, 0xBE, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xEB, 0x94, 0x47, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x75, + 0xA2, 0x2A, 0xA9, 0x57, 0x77, 0x77, 0x77, 0x75, 0xA3, 0x23, 0xA8, 0x57, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x74, 0x49, 0xBE, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xEB, 0x94, 0x47, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x76, + 0x7A, 0x22, 0x3A, 0xA9, 0x57, 0x77, 0x77, 0x77, 0x9A, 0x22, 0x27, 0xA9, 0x57, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x74, 0x49, 0xBE, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDC, 0xB5, 0x47, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x58, 0xA2, 0x22, 0x3A, 0xA5, 0x57, 0x77, 0x77, 0x75, 0xA2, 0x22, 0x3A, 0x89, 0x77, 0x77, 0x77, + 0x77, 0x86, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x74, 0x5B, 0xCD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDE, 0xB9, 0x48, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x75, 0x8A, 0x22, 0x22, 0x3A, 0xA6, 0x95, 0x77, 0x75, 0x89, 0x22, 0x22, 0x9A, 0x75, 0x77, 0x77, + 0x77, 0x58, 0x67, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x84, 0x9B, 0xED, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xC9, 0x48, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x55, 0x55, 0x55, 0x55, 0x99, + 0x55, 0x58, 0xA2, 0x22, 0x22, 0x38, 0xAA, 0x55, 0x57, 0x5A, 0x32, 0x22, 0x23, 0x8A, 0x55, 0x77, + 0x5A, 0x33, 0xA6, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x84, 0x9C, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xEB, 0x94, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x8A, 0xAA, 0xAA, 0xAA, 0xAA, + 0xAA, 0x79, 0x9A, 0x32, 0x22, 0x22, 0x23, 0xAA, 0xA5, 0x59, 0xA3, 0x22, 0x22, 0x23, 0xAA, 0x55, + 0x9A, 0x22, 0xA9, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x49, 0xBE, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xEE, + 0xB4, 0x87, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x58, 0x32, 0x22, 0x22, 0x22, 0x22, + 0x33, 0xAA, 0xA4, 0xA3, 0x22, 0x22, 0x22, 0x23, 0x3A, 0xAA, 0x9A, 0x32, 0x22, 0x22, 0x23, 0xAA, + 0x9A, 0x32, 0x3A, 0x57, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x78, 0x4B, + 0xEE, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xB9, + 0x48, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x78, 0x93, 0x33, 0x22, 0x22, 0x22, + 0x22, 0x22, 0x33, 0x8A, 0xA3, 0x22, 0x22, 0x22, 0x22, 0x23, 0xAA, 0xA7, 0x22, 0x22, 0x22, 0x23, + 0xA8, 0xA2, 0x2A, 0x57, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x84, + 0x9B, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xEB, 0x94, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x8A, 0xAA, 0xA9, 0x22, 0x22, + 0x22, 0x22, 0x22, 0x23, 0x9F, 0x83, 0x22, 0x22, 0x22, 0x22, 0x23, 0x3A, 0xA2, 0x22, 0x22, 0x22, + 0x23, 0xF3, 0x22, 0xA9, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x49, 0xBE, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDE, 0xB5, 0x87, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x55, 0x59, 0x99, 0x99, 0x99, 0x99, 0x98, 0xF2, 0x22, + 0x22, 0x22, 0x22, 0x22, 0x23, 0x9F, 0x83, 0x22, 0x22, 0x22, 0x22, 0x22, 0x9F, 0x22, 0x22, 0x22, + 0x22, 0x3F, 0x22, 0x3A, 0x97, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x78, 0x5B, 0xED, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xEB, 0x48, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x55, 0x57, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0x32, 0x22, + 0x22, 0x22, 0x22, 0x22, 0x22, 0x23, 0x7A, 0x83, 0x22, 0x22, 0x22, 0x22, 0x23, 0xA2, 0x22, 0x22, + 0x22, 0x22, 0x32, 0x23, 0xA5, 0x57, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x84, 0xBE, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDE, 0x94, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x75, 0x97, 0xAA, 0xA8, 0x33, 0x33, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, + 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x23, 0xAA, 0x82, 0x22, 0x22, 0x22, 0x22, 0xA3, 0x22, 0x22, + 0x22, 0x22, 0x22, 0x22, 0x3A, 0x85, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x49, 0xED, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xE9, 0x47, 0x77, 0x77, + 0x77, 0x77, 0x75, 0x5A, 0xA8, 0x33, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, + 0x22, 0x22, 0x22, 0x22, 0xA3, 0x33, 0x22, 0x39, 0x8A, 0x32, 0x22, 0x23, 0x22, 0x2F, 0x22, 0x22, + 0x22, 0x22, 0x22, 0x22, 0x22, 0x8A, 0x97, 0x77, 0x77, 0x78, 0x55, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x74, 0x9E, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDE, 0x94, 0x77, 0x77, 0x77, + 0x77, 0x75, 0x5A, 0xA3, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, + 0x22, 0x22, 0x22, 0x22, 0x2F, 0x99, 0xA7, 0x39, 0x89, 0xA9, 0x22, 0x22, 0x83, 0x23, 0x82, 0x22, + 0x22, 0x22, 0x22, 0x22, 0x22, 0x23, 0xA9, 0x67, 0x77, 0x89, 0xAA, 0x57, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x49, 0xED, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xE9, 0x47, 0x77, 0x77, 0x77, + 0x75, 0x5A, 0xA3, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, + 0x22, 0x22, 0x23, 0x33, 0x37, 0x32, 0x23, 0x39, 0x8A, 0xAA, 0xAA, 0x83, 0x3A, 0xA9, 0x53, 0x22, + 0x22, 0x23, 0x22, 0x22, 0x22, 0x22, 0x3A, 0x65, 0x75, 0x83, 0x33, 0xA9, 0x67, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x74, 0x9E, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDE, 0x94, 0x77, 0x77, 0x77, 0x77, + 0x58, 0xA3, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x23, + 0x38, 0xFF, 0xFF, 0xFA, 0xAA, 0xA3, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x3A, 0xA9, 0x32, 0x22, + 0x22, 0x22, 0x32, 0x22, 0x22, 0x22, 0x22, 0xA7, 0x77, 0x5A, 0x32, 0x3A, 0x85, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x49, 0xED, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xE9, 0x47, 0x77, 0x77, 0x77, 0x76, + 0x83, 0x22, 0x23, 0x33, 0x33, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x23, 0x5F, 0xFA, + 0xA9, 0x32, 0x22, 0x23, 0xA3, 0x3A, 0xA2, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x3A, 0xA3, 0x32, + 0x22, 0x22, 0x3F, 0x32, 0x22, 0x22, 0x22, 0x2A, 0x57, 0x75, 0xA9, 0x22, 0xAA, 0x97, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x74, 0x9E, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDE, 0x94, 0x77, 0x77, 0x77, 0x77, 0x76, + 0x83, 0x3A, 0xAA, 0xAA, 0xAA, 0xA2, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x3A, 0xFA, 0x33, 0x23, + 0x32, 0x22, 0x22, 0x28, 0x22, 0x23, 0x8A, 0x32, 0x22, 0x22, 0x22, 0x22, 0x22, 0x93, 0x22, 0x22, + 0x22, 0x22, 0x2F, 0x33, 0x32, 0x22, 0x22, 0x23, 0xA5, 0x77, 0x58, 0xA2, 0x23, 0xA9, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x49, 0xED, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xEB, 0x47, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x5A, 0xA5, 0x95, 0x59, 0x9A, 0x32, 0x22, 0x22, 0x22, 0x22, 0x23, 0x5A, 0xA3, 0x22, 0x22, 0x29, + 0x22, 0x22, 0x22, 0x52, 0x22, 0x22, 0x23, 0xAA, 0x32, 0x22, 0x22, 0x23, 0x3A, 0x32, 0x22, 0x22, + 0x22, 0x22, 0x23, 0x72, 0x23, 0x22, 0x22, 0x22, 0xA9, 0x77, 0x75, 0x5A, 0x32, 0x3A, 0x55, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x74, 0xBE, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDE, 0xB4, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x75, 0x57, 0x75, 0x9A, 0xA3, 0x22, 0x22, 0x22, 0x22, 0x23, 0xAF, 0x33, 0x92, 0x22, 0x22, 0x32, + 0x22, 0x22, 0x2A, 0x32, 0x22, 0x23, 0x33, 0x89, 0xAA, 0x93, 0x32, 0x22, 0x3A, 0x32, 0x22, 0x22, + 0x22, 0x22, 0x22, 0x39, 0x39, 0xA2, 0x22, 0x23, 0xA9, 0x77, 0x77, 0x79, 0xF3, 0x22, 0xA7, 0x57, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x4B, 0xED, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDB, 0x58, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x75, 0x9A, 0xA3, 0x22, 0x22, 0x22, 0x22, 0x23, 0xAF, 0x32, 0x23, 0x22, 0x22, 0x23, 0x32, + 0x22, 0x33, 0xA5, 0x8A, 0xAA, 0xAA, 0xA8, 0x58, 0x8A, 0xA3, 0x32, 0x22, 0x22, 0xAF, 0x32, 0x22, + 0x22, 0x22, 0x22, 0x22, 0x22, 0x3A, 0x32, 0x22, 0xA7, 0x57, 0x75, 0x77, 0x9A, 0x32, 0x2A, 0x85, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x85, 0xBD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDE, 0xB9, 0x87, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x75, 0x5A, 0xA3, 0x22, 0x22, 0x22, 0x22, 0x23, 0xAA, 0x32, 0x22, 0x23, 0x22, 0x22, 0x2A, 0x33, + 0x8A, 0xAA, 0x57, 0x75, 0x59, 0x59, 0xAA, 0xA7, 0x33, 0x22, 0x22, 0x22, 0x33, 0x73, 0x33, 0x22, + 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x28, 0xA9, 0x58, 0x57, 0x79, 0xA3, 0x22, 0x88, + 0x57, 0x77, 0x77, 0x77, 0x77, 0x77, 0x78, 0x9B, 0xED, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDE, 0x94, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x75, + 0x5A, 0xA3, 0x22, 0x22, 0x22, 0x22, 0x23, 0xAF, 0xA3, 0x22, 0x22, 0x33, 0x22, 0x23, 0xA5, 0xAA, + 0x65, 0x55, 0x77, 0x77, 0x77, 0x85, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x3F, 0x22, 0x22, 0x22, + 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x3A, 0x83, 0x87, 0x77, 0x9A, 0x32, 0x2A, + 0x85, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x49, 0xED, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xEB, 0x47, 0x77, 0x77, 0x77, 0x77, 0x77, 0x75, 0x9A, + 0xA3, 0x22, 0x22, 0x22, 0x22, 0x22, 0x3F, 0x92, 0x32, 0x22, 0x22, 0x92, 0x23, 0xAA, 0x57, 0x55, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x68, 0x32, 0x22, 0x22, 0x22, 0x22, 0x22, 0x23, 0x32, 0x22, 0x22, + 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0xA3, 0x2A, 0x57, 0x79, 0xA2, 0x22, + 0xA8, 0x57, 0x77, 0x77, 0x77, 0x77, 0x77, 0x74, 0xBE, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xB4, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x98, 0xA3, + 0x22, 0x22, 0x22, 0x22, 0x22, 0x3A, 0xA3, 0x22, 0x32, 0x22, 0x23, 0xA9, 0xAA, 0x55, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x75, 0xAA, 0xA3, 0x32, 0x22, 0x22, 0x22, 0x23, 0xF2, 0x22, 0x22, + 0x22, 0x22, 0x3A, 0xAA, 0xA3, 0x32, 0x22, 0x22, 0x22, 0x22, 0x22, 0x23, 0xA5, 0x77, 0x5A, 0x22, + 0x2A, 0x75, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x4B, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDC, 0x98, 0x77, 0x77, 0x77, 0x77, 0x77, 0x55, 0xA9, 0x22, + 0x22, 0x22, 0x22, 0x22, 0x23, 0xA9, 0x22, 0x22, 0x32, 0x22, 0x3A, 0x68, 0x55, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x59, 0x6A, 0xAA, 0xAA, 0xAA, 0xAF, 0x33, 0x3A, 0x22, 0x22, + 0x22, 0x22, 0x2A, 0x99, 0x83, 0x33, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0xA5, 0x77, 0x65, 0xA2, + 0x22, 0xA5, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x89, 0xCD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xE9, 0x47, 0x77, 0x77, 0x77, 0x77, 0x75, 0x8A, 0x32, 0x22, + 0x22, 0x22, 0x22, 0x22, 0x9A, 0x52, 0x22, 0x23, 0x22, 0x23, 0xA5, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x75, 0x59, 0x95, 0x99, 0xA3, 0x22, 0x39, 0x93, 0x22, + 0x22, 0x22, 0x2A, 0x95, 0xA3, 0x22, 0x33, 0x22, 0x22, 0x22, 0x33, 0x22, 0x3A, 0x57, 0x75, 0x86, + 0x22, 0x2A, 0x97, 0x77, 0x77, 0x77, 0x77, 0x77, 0x74, 0x9E, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xB4, 0x77, 0x77, 0x77, 0x77, 0x77, 0x9A, 0x52, 0x22, 0x22, + 0x22, 0x22, 0x22, 0x2A, 0xA5, 0x32, 0x22, 0x23, 0x33, 0xAA, 0x97, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x75, 0x8A, 0x32, 0x22, 0x22, 0x22, 0x22, + 0x22, 0x22, 0x2A, 0x55, 0x83, 0x38, 0x22, 0x33, 0x22, 0x22, 0x22, 0x22, 0x3A, 0x57, 0x77, 0x5A, + 0x32, 0x23, 0xA9, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x4B, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDC, 0x98, 0x77, 0x77, 0x77, 0x77, 0x79, 0xA3, 0x22, 0x22, 0x22, + 0x22, 0x22, 0x22, 0xAA, 0x23, 0x32, 0x22, 0x2A, 0xAA, 0x55, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x68, 0x92, 0x22, 0x22, 0x22, 0x22, 0x22, + 0x22, 0x22, 0x23, 0xAA, 0x8A, 0xA8, 0x22, 0x22, 0x33, 0x22, 0x22, 0x22, 0x38, 0x57, 0x77, 0x79, + 0xA3, 0x22, 0x3A, 0x57, 0x77, 0x77, 0x77, 0x77, 0x77, 0x89, 0xCD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xE9, 0x47, 0x77, 0x77, 0x77, 0x77, 0x9A, 0x32, 0x22, 0x22, 0x22, + 0x22, 0x22, 0x3F, 0x52, 0x23, 0x22, 0x22, 0x3A, 0x55, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x5A, 0x32, 0x23, 0x39, 0xAA, 0xAA, 0x93, + 0x22, 0x22, 0x22, 0xA3, 0x36, 0x55, 0xAF, 0x32, 0x23, 0x33, 0x22, 0x22, 0xA5, 0x77, 0x77, 0x77, + 0x9A, 0x22, 0x29, 0x85, 0x77, 0x77, 0x77, 0x77, 0x77, 0x74, 0x9E, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDE, 0xB5, 0x87, 0x77, 0x77, 0x77, 0x79, 0xA3, 0x22, 0x22, 0x22, 0x22, + 0x22, 0x23, 0xF9, 0x22, 0x23, 0x22, 0x25, 0xA5, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x75, 0xAA, 0xAA, 0xA8, 0x55, 0x55, 0x8A, + 0xA3, 0x22, 0x22, 0x32, 0x3A, 0x57, 0x57, 0x33, 0xF2, 0x23, 0x32, 0x2A, 0x67, 0x77, 0x77, 0x77, + 0x75, 0xA2, 0x22, 0xA5, 0x77, 0x77, 0x77, 0x77, 0x77, 0x78, 0x5B, 0xED, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDE, 0x94, 0x77, 0x77, 0x77, 0x77, 0x9A, 0x32, 0x22, 0x22, 0x22, 0x22, + 0x22, 0x3A, 0x92, 0x22, 0x23, 0x22, 0xA8, 0x57, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x59, 0x95, 0x55, 0x77, 0x77, 0x55, + 0x5A, 0x82, 0x22, 0x29, 0x22, 0xA7, 0x75, 0xAA, 0x52, 0x23, 0x32, 0x88, 0x57, 0x77, 0x77, 0x77, + 0x75, 0xA3, 0x22, 0x3A, 0x97, 0x77, 0x77, 0x77, 0x77, 0x77, 0x49, 0xED, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDB, 0x47, 0x77, 0x77, 0x77, 0x75, 0xA3, 0x22, 0x3A, 0xA5, 0x22, 0x22, + 0x23, 0xAA, 0x32, 0x22, 0x23, 0x3A, 0x75, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x79, 0x8A, 0x22, 0x23, 0x22, 0xF9, 0x75, 0x58, 0x33, 0xAA, 0x5A, 0x85, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x9A, 0x32, 0x23, 0xA5, 0x77, 0x77, 0x77, 0x77, 0x77, 0x74, 0xBD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xE9, 0x87, 0x77, 0x77, 0x77, 0x5A, 0x32, 0x3A, 0xA9, 0xA2, 0x22, 0x22, + 0x2F, 0x33, 0x32, 0x22, 0x2A, 0xA5, 0x67, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x56, 0xA2, 0x22, 0x93, 0x23, 0xAA, 0x85, 0x8A, 0x55, 0x85, 0x57, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x75, 0xA2, 0x22, 0xA5, 0x77, 0x77, 0x77, 0x77, 0x77, 0x78, 0x9E, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xB4, 0x77, 0x77, 0x77, 0x77, 0x78, 0x33, 0xA9, 0x9A, 0x32, 0x22, 0x22, + 0xA7, 0x22, 0x32, 0x22, 0x3A, 0x97, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x75, 0xA3, 0x22, 0x23, 0x29, 0xA3, 0x98, 0x55, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x75, 0xA3, 0x22, 0x3A, 0x97, 0x77, 0x77, 0x77, 0x77, 0x77, 0x4B, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDE, 0x98, 0x77, 0x77, 0x77, 0x77, 0x89, 0x6A, 0x99, 0xA3, 0x22, 0x22, 0x2A, + 0xA2, 0x22, 0x32, 0x23, 0xA5, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x5A, 0x22, 0x23, 0x92, 0x22, 0xA5, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x9A, 0x22, 0x23, 0xA5, 0x77, 0x77, 0x77, 0x77, 0x77, 0x89, 0xED, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDB, 0x47, 0x77, 0x77, 0x77, 0x77, 0x78, 0x75, 0x9A, 0x32, 0x22, 0x22, 0x3F, + 0x22, 0x22, 0x32, 0x3A, 0x97, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x9A, 0x22, 0x22, 0x33, 0x23, 0xA5, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x58, 0x92, 0x22, 0xA5, 0x77, 0x77, 0x77, 0x77, 0x77, 0x74, 0xBD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xE9, 0x47, 0x77, 0x77, 0x77, 0x77, 0x77, 0x79, 0xA3, 0x22, 0x22, 0x23, 0xF3, + 0x22, 0x22, 0x32, 0xA9, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x75, 0xA3, 0x22, 0x22, 0x23, 0x39, 0x87, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x79, 0xA3, 0x22, 0x3A, 0x57, 0x77, 0x77, 0x77, 0x77, 0x74, 0x9E, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xB4, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x9A, 0x32, 0x22, 0x22, 0x2A, 0xA2, + 0x22, 0x22, 0xAA, 0x57, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x5A, 0x32, 0x22, 0x22, 0x22, 0x23, 0xA5, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x68, 0x22, 0x2A, 0x57, 0x77, 0x77, 0x77, 0x77, 0x77, 0x4B, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDE, 0x94, 0x77, 0x77, 0x77, 0x77, 0x77, 0x79, 0xA3, 0x22, 0x22, 0x22, 0xA9, 0xA2, + 0x22, 0x23, 0xA9, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x78, 0x99, 0x92, 0x22, 0x22, 0x3A, 0x57, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x5A, 0x32, 0x23, 0xA5, 0x77, 0x77, 0x77, 0x77, 0x77, 0x49, 0xED, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDB, 0x68, 0x77, 0x77, 0x77, 0x77, 0x77, 0x9A, 0x32, 0x22, 0x22, 0x23, 0xF2, 0x32, + 0x22, 0x29, 0x85, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x75, 0x83, 0x22, 0x22, 0x3A, 0xA5, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x82, 0x22, 0xA5, 0x77, 0x77, 0x77, 0x77, 0x77, 0x86, 0xBD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xEB, 0x47, 0x77, 0x77, 0x77, 0x77, 0x75, 0xA3, 0x22, 0x22, 0x22, 0x2F, 0x32, 0x23, + 0x22, 0x3A, 0x57, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x83, 0x33, 0x5A, 0xA5, 0x57, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x79, 0xA3, 0x22, 0x3A, 0x57, 0x77, 0x77, 0x77, 0x77, 0x74, 0xBE, 0xDD, 0xDD, + 0xDD, 0xDD, 0xC9, 0x87, 0x77, 0x77, 0x77, 0x77, 0x5A, 0x32, 0x22, 0x22, 0x22, 0xA8, 0x22, 0x23, + 0x22, 0xA9, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x78, 0xA8, 0x85, 0x57, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x76, 0x89, 0x22, 0x2A, 0x57, 0x77, 0x77, 0x77, 0x77, 0x78, 0x9C, 0xDD, 0xDD, + 0xDD, 0xDD, 0xB4, 0x77, 0x77, 0x77, 0x77, 0x75, 0x88, 0x22, 0x22, 0x22, 0x23, 0xF2, 0x22, 0x23, + 0x2A, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x56, 0x54, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x9A, 0x22, 0x23, 0xA5, 0x77, 0x77, 0x77, 0x77, 0x77, 0x4B, 0xDD, 0xDD, + 0xDD, 0xDE, 0x94, 0x77, 0x77, 0x77, 0x77, 0x75, 0xA2, 0x22, 0x22, 0x22, 0x2A, 0x32, 0x22, 0x23, + 0x88, 0x57, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x75, 0xAA, 0x47, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x5A, 0x32, 0x22, 0xA9, 0x77, 0x77, 0x77, 0x77, 0x77, 0x49, 0xED, 0xDD, + 0xDD, 0xDB, 0x98, 0x77, 0x77, 0x77, 0x77, 0x9A, 0x32, 0x22, 0x22, 0x22, 0x3A, 0x32, 0x22, 0x23, + 0xA5, 0x77, 0x77, 0x77, 0x74, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x44, 0x44, + 0x45, 0x55, 0x55, 0x55, 0x55, 0x47, 0x77, 0x77, 0x75, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x74, 0x5F, 0x33, 0xA4, 0x75, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x47, 0x77, 0x75, 0xA2, 0x22, 0x38, 0x57, 0x77, 0x77, 0x77, 0x77, 0x89, 0xBD, 0xDD, + 0xDD, 0xDB, 0x47, 0x77, 0x77, 0x77, 0x75, 0x83, 0x22, 0x22, 0x22, 0x22, 0xA5, 0x32, 0x22, 0x2A, + 0x57, 0x77, 0x77, 0x77, 0x5A, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, + 0xAA, 0xAA, 0xAF, 0xFF, 0xFF, 0xA5, 0x77, 0x77, 0x5F, 0x84, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x58, 0xF3, 0x03, 0xA4, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0x84, 0x77, 0x75, 0xA3, 0x22, 0x3A, 0x97, 0x77, 0x77, 0x77, 0x77, 0x74, 0xBD, 0xDD, + 0xDD, 0xE9, 0x47, 0x77, 0x77, 0x77, 0x79, 0xA2, 0x22, 0x22, 0x22, 0x23, 0xA2, 0x32, 0x22, 0x3A, + 0x57, 0x77, 0x77, 0x75, 0xF3, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x10, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x11, 0x11, 0x11, 0x15, 0x87, 0x45, 0xF3, 0x3F, 0x57, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x75, 0xA8, 0x10, 0x0A, 0x45, 0xA1, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, + 0x11, 0x11, 0x5A, 0x47, 0x76, 0x89, 0x22, 0x2A, 0x57, 0x77, 0x77, 0x77, 0x77, 0x74, 0x9E, 0xDD, + 0xDD, 0xC9, 0x87, 0x77, 0x77, 0x77, 0x5A, 0x32, 0x22, 0x22, 0x22, 0x2F, 0x32, 0x33, 0x22, 0xA5, + 0x77, 0x77, 0x77, 0x5F, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x3A, 0x45, 0x8F, 0x20, 0x3F, 0x57, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x5F, 0x30, 0x00, 0x1F, 0x58, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x1F, 0x57, 0x77, 0x9A, 0x22, 0x23, 0xA5, 0x77, 0x77, 0x77, 0x77, 0x78, 0x9C, 0xDD, + 0xDD, 0xB5, 0x77, 0x77, 0x77, 0x77, 0x5A, 0x22, 0x23, 0x22, 0x22, 0x3A, 0x22, 0x23, 0x23, 0xA5, + 0x77, 0x77, 0x75, 0xF3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x13, 0xF5, 0x5A, 0xA1, 0x00, 0x3A, 0x47, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x45, 0xF3, 0x00, 0x00, 0x2F, 0x5F, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x02, 0xF5, 0x77, 0x5A, 0x32, 0x22, 0xA9, 0x77, 0x77, 0x77, 0x77, 0x77, 0x5B, 0xDD, + 0xDE, 0xB4, 0x77, 0x77, 0x77, 0x75, 0xA3, 0x22, 0xA6, 0x22, 0x22, 0xA3, 0x22, 0x23, 0x3A, 0x57, + 0x77, 0x74, 0x5F, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x8A, 0x55, 0xF3, 0x10, 0x00, 0xA4, 0x77, 0x77, 0x77, 0x77, 0x77, 0x75, + 0x8F, 0x20, 0x00, 0x00, 0x3F, 0x5F, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x3F, 0x57, 0x68, 0x92, 0x22, 0xA5, 0x77, 0x77, 0x77, 0x77, 0x77, 0x4B, 0xED, + 0xDE, 0x94, 0x77, 0x77, 0x77, 0x79, 0xA2, 0x2A, 0xA3, 0x22, 0x23, 0xF2, 0x22, 0x23, 0xA5, 0x77, + 0x77, 0x58, 0xF2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x1F, 0x85, 0x5F, 0x30, 0x00, 0x01, 0xF5, 0x77, 0x77, 0x77, 0x77, 0x77, 0x5F, + 0x51, 0x00, 0x00, 0x00, 0x58, 0x5F, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x03, 0xA5, 0x75, 0xA2, 0x22, 0x3A, 0x57, 0x77, 0x77, 0x77, 0x77, 0x49, 0xED, + 0xDB, 0x98, 0x77, 0x77, 0x77, 0x5A, 0x32, 0x55, 0xA2, 0x22, 0x25, 0xA2, 0x22, 0x23, 0xA5, 0x77, + 0x75, 0xA8, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x03, 0xF5, 0x55, 0xF3, 0x00, 0x00, 0x03, 0xF5, 0x77, 0x77, 0x77, 0x77, 0x75, 0xF3, + 0x00, 0x00, 0x00, 0x01, 0xF5, 0x77, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, 0xF7, 0x45, 0xA3, 0x22, 0x3A, 0x57, 0x77, 0x77, 0x77, 0x77, 0x89, 0xBD, + 0xDB, 0x47, 0x77, 0x77, 0x77, 0x5A, 0x33, 0xA8, 0x32, 0x22, 0x2A, 0xA2, 0x22, 0x23, 0xA5, 0x77, + 0x5A, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x3F, 0x55, 0xAF, 0x20, 0x00, 0x00, 0x03, 0xA5, 0x77, 0x77, 0x77, 0x77, 0x5F, 0x30, + 0x00, 0x00, 0x00, 0x02, 0xF5, 0xA3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x1F, 0x55, 0xA3, 0x22, 0x2A, 0x57, 0x77, 0x77, 0x77, 0x77, 0x74, 0xBD, + 0xEB, 0x47, 0x77, 0x77, 0x77, 0x77, 0x38, 0x9A, 0x22, 0x22, 0x38, 0x33, 0x22, 0x28, 0x77, 0x74, + 0xA3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x03, 0xF5, 0x5A, 0x51, 0x00, 0x00, 0x00, 0x05, 0x87, 0x77, 0x77, 0x77, 0x75, 0xF3, 0x00, + 0x00, 0x00, 0x00, 0x03, 0xF5, 0xF3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x03, 0xA5, 0x58, 0x22, 0x25, 0x87, 0x77, 0x77, 0x77, 0x77, 0x74, 0xBE, + 0xE9, 0x47, 0x77, 0x77, 0x77, 0x77, 0x85, 0x85, 0x22, 0x22, 0xA3, 0x23, 0x22, 0x2A, 0x97, 0x75, + 0xF3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x5F, 0x54, 0xA3, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x57, 0x77, 0x77, 0x77, 0x75, 0xF1, 0x00, + 0x00, 0x00, 0x00, 0x03, 0xA5, 0xF1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x03, 0xA5, 0x9A, 0x22, 0x23, 0xA5, 0x77, 0x77, 0x77, 0x77, 0x74, 0x9E, + 0xE9, 0x47, 0x77, 0x77, 0x77, 0x77, 0x55, 0xA3, 0x22, 0x22, 0xF3, 0x23, 0x22, 0x3A, 0x57, 0x75, + 0xF1, 0x00, 0x00, 0x00, 0x01, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x10, 0x00, 0x00, 0x00, + 0x18, 0xA5, 0x77, 0xA0, 0x00, 0x00, 0x00, 0x00, 0x2F, 0x57, 0x77, 0x77, 0x77, 0x48, 0x50, 0x00, + 0x00, 0x00, 0x00, 0x1F, 0x54, 0xA2, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0A, 0x77, 0x5A, 0x32, 0x23, 0xA5, 0x77, 0x77, 0x77, 0x77, 0x74, 0x9E, + 0xB9, 0x87, 0x77, 0x77, 0x77, 0x77, 0x75, 0xA2, 0x22, 0x23, 0xF2, 0x22, 0x32, 0xA5, 0x77, 0x74, + 0xA0, 0x00, 0x00, 0x00, 0x03, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x20, 0x00, 0x00, 0x02, + 0xF8, 0x57, 0x5F, 0x30, 0x00, 0x00, 0x00, 0x00, 0x3F, 0x57, 0x77, 0x77, 0x77, 0x5F, 0x30, 0x00, + 0x00, 0x00, 0x00, 0x1F, 0x57, 0x4F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x30, + 0x00, 0x00, 0x00, 0x00, 0x1F, 0x57, 0x5A, 0x32, 0x22, 0xA9, 0x77, 0x77, 0x77, 0x77, 0x78, 0x9B, + 0xB6, 0x77, 0x77, 0x77, 0x77, 0x77, 0x5A, 0x32, 0x22, 0x27, 0x92, 0x22, 0x39, 0x85, 0x77, 0x4A, + 0x30, 0x00, 0x00, 0x00, 0x00, 0x2A, 0x55, 0x55, 0x55, 0x55, 0x55, 0x5F, 0x10, 0x00, 0x00, 0x3F, + 0x54, 0x77, 0x5F, 0x30, 0x00, 0x00, 0x00, 0x00, 0x58, 0x47, 0x77, 0x77, 0x77, 0x5F, 0x20, 0x00, + 0x00, 0x00, 0x00, 0x3F, 0x57, 0x75, 0x55, 0x55, 0x55, 0xF3, 0x37, 0x55, 0x55, 0x55, 0x55, 0xA0, + 0x00, 0x00, 0x00, 0x00, 0x2F, 0x57, 0x58, 0x32, 0x22, 0xA5, 0x77, 0x77, 0x77, 0x77, 0x77, 0x6B, + 0xB4, 0x77, 0x77, 0x77, 0x77, 0x77, 0x9A, 0x22, 0x22, 0x2F, 0x32, 0x22, 0x2A, 0x97, 0x77, 0x5F, + 0x30, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x57, 0x77, 0x77, 0x77, 0x74, 0x85, 0x00, 0x00, 0x03, 0xF5, + 0x77, 0x77, 0x5F, 0x10, 0x00, 0x00, 0x00, 0x01, 0xF5, 0x77, 0x77, 0x77, 0x77, 0x5F, 0x10, 0x00, + 0x00, 0x00, 0x00, 0x3A, 0x47, 0x77, 0x77, 0x77, 0x5F, 0x30, 0x3A, 0x47, 0x77, 0x77, 0x4A, 0x30, + 0x00, 0x00, 0x00, 0x00, 0x3F, 0x57, 0x76, 0x82, 0x22, 0x38, 0x57, 0x77, 0x77, 0x77, 0x77, 0x4B, + 0xB4, 0x77, 0x77, 0x77, 0x77, 0x75, 0x83, 0x22, 0x22, 0x3F, 0x22, 0x22, 0x2A, 0x97, 0x77, 0x5F, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x3F, 0x57, 0x77, 0x77, 0x77, 0x75, 0xA3, 0x00, 0x00, 0x3F, 0x57, + 0x77, 0x77, 0x4A, 0x00, 0x00, 0x00, 0x00, 0x02, 0xF5, 0x77, 0x77, 0x77, 0x77, 0x78, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xA4, 0x77, 0x77, 0x77, 0x45, 0xF3, 0x01, 0xF5, 0x77, 0x77, 0x77, 0x5F, 0x30, + 0x00, 0x00, 0x00, 0x00, 0x38, 0x47, 0x75, 0xA2, 0x22, 0x3A, 0x57, 0x77, 0x77, 0x77, 0x77, 0x4B, + 0x94, 0x77, 0x77, 0x77, 0x77, 0x79, 0xA3, 0x22, 0x22, 0x3F, 0x22, 0x22, 0x2A, 0x97, 0x77, 0x5F, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x3A, 0x47, 0x77, 0x77, 0x77, 0x75, 0xF3, 0x00, 0x03, 0xF5, 0x77, + 0x77, 0x74, 0xA3, 0x00, 0x00, 0x00, 0x00, 0x03, 0xF5, 0x77, 0x77, 0x77, 0x74, 0xA3, 0x00, 0x00, + 0x00, 0x00, 0x01, 0xF5, 0x77, 0x77, 0x75, 0x8F, 0x20, 0x02, 0xF5, 0x77, 0x77, 0x77, 0x5F, 0x10, + 0x00, 0x00, 0x00, 0x01, 0xF5, 0x77, 0x79, 0xA2, 0x22, 0x3A, 0x57, 0x77, 0x77, 0x77, 0x77, 0x49, + 0x94, 0x77, 0x77, 0x77, 0x77, 0x75, 0xA2, 0x22, 0x22, 0x9A, 0x92, 0x22, 0x3A, 0x57, 0x74, 0xA3, + 0x00, 0x00, 0x00, 0x00, 0x01, 0xA5, 0x77, 0x77, 0x77, 0x77, 0x75, 0xF1, 0x01, 0x8A, 0x57, 0x77, + 0x77, 0x75, 0xF3, 0x00, 0x00, 0x00, 0x00, 0x03, 0xA4, 0x77, 0x77, 0x77, 0x75, 0xF3, 0x00, 0x00, + 0x00, 0x00, 0x03, 0xF5, 0x77, 0x77, 0x5A, 0xA1, 0x00, 0x03, 0xF5, 0x77, 0x77, 0x77, 0x5F, 0x10, + 0x00, 0x00, 0x00, 0x01, 0xF5, 0x77, 0x79, 0xA3, 0x22, 0x3A, 0x97, 0x77, 0x77, 0x77, 0x77, 0x49, + 0x98, 0x77, 0x77, 0x77, 0x77, 0x5A, 0x32, 0x22, 0x22, 0xA3, 0x32, 0x22, 0x3A, 0x57, 0x75, 0xF3, + 0x00, 0x00, 0x00, 0x00, 0x01, 0xF5, 0x77, 0x77, 0x77, 0x77, 0x77, 0xA0, 0x1F, 0x85, 0x77, 0x77, + 0x77, 0x75, 0xF2, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x57, 0x77, 0x77, 0x77, 0x75, 0xF1, 0x00, 0x00, + 0x00, 0x00, 0x03, 0xA4, 0x77, 0x75, 0xF5, 0x10, 0x00, 0x03, 0xA4, 0x77, 0x77, 0x74, 0xA3, 0x00, + 0x00, 0x00, 0x00, 0x03, 0xF5, 0x77, 0x75, 0xA3, 0x22, 0x2A, 0x97, 0x77, 0x77, 0x77, 0x77, 0x89, + 0x98, 0x77, 0x77, 0x77, 0x77, 0x9A, 0x22, 0x22, 0x22, 0xF3, 0x29, 0x22, 0x98, 0x67, 0x75, 0xF2, + 0x00, 0x00, 0x00, 0x00, 0x03, 0xF5, 0x77, 0x77, 0x77, 0x77, 0x4A, 0x33, 0xF4, 0x47, 0x77, 0x77, + 0x77, 0x75, 0xF1, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x57, 0x77, 0x77, 0x77, 0x75, 0xF1, 0x00, 0x00, + 0x00, 0x00, 0x0A, 0x47, 0x77, 0x5F, 0x30, 0x00, 0x00, 0x1F, 0x57, 0x77, 0x77, 0x75, 0xF3, 0x00, + 0x00, 0x00, 0x00, 0x03, 0xA4, 0x78, 0x85, 0xA3, 0x22, 0x2A, 0x57, 0x77, 0x77, 0x77, 0x77, 0x89, + 0x98, 0x77, 0x77, 0x77, 0x77, 0x5A, 0x22, 0x22, 0x22, 0xF2, 0x23, 0x32, 0xA5, 0x77, 0x75, 0xF1, + 0x00, 0x00, 0x00, 0x00, 0x03, 0xA4, 0x77, 0x77, 0x77, 0x77, 0x77, 0x8F, 0x54, 0x77, 0x77, 0x77, + 0x77, 0x48, 0x50, 0x00, 0x00, 0x00, 0x00, 0x3F, 0x57, 0x77, 0x77, 0x77, 0x4A, 0x30, 0x00, 0x00, + 0x00, 0x00, 0x1F, 0x57, 0x75, 0xF3, 0x00, 0x00, 0x00, 0x1F, 0x57, 0x77, 0x77, 0x75, 0xF2, 0x00, + 0x00, 0x00, 0x00, 0x0A, 0x75, 0x89, 0x96, 0xA3, 0x22, 0x2A, 0x57, 0x77, 0x77, 0x77, 0x77, 0x89, + 0x67, 0x77, 0x77, 0x77, 0x75, 0xA3, 0x22, 0x22, 0x23, 0xF2, 0x22, 0x33, 0x85, 0x77, 0x48, 0x50, + 0x00, 0x00, 0x00, 0x00, 0x1F, 0x57, 0x77, 0x77, 0x77, 0x77, 0x77, 0x75, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x5A, 0x30, 0x00, 0x00, 0x00, 0x00, 0x3A, 0x47, 0x77, 0x77, 0x77, 0x5F, 0x30, 0x00, 0x00, + 0x00, 0x00, 0x3F, 0x57, 0x4F, 0x30, 0x00, 0x00, 0x00, 0x3F, 0x57, 0x77, 0x77, 0x75, 0xF1, 0x00, + 0x00, 0x00, 0x00, 0x1F, 0x55, 0xA3, 0x3A, 0x83, 0x22, 0x2A, 0x57, 0x77, 0x77, 0x77, 0x77, 0x76, + 0x57, 0x77, 0x77, 0x77, 0x75, 0xA3, 0x22, 0x22, 0x23, 0xA2, 0x22, 0x2A, 0x97, 0x77, 0x5F, 0x30, + 0x00, 0x00, 0x00, 0x00, 0x1F, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x54, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x5F, 0x30, 0x00, 0x00, 0x00, 0x00, 0x87, 0x77, 0x77, 0x77, 0x77, 0x5F, 0x20, 0x00, 0x00, + 0x00, 0x00, 0x3A, 0x54, 0xA2, 0x00, 0x00, 0x00, 0x00, 0x3A, 0x44, 0x55, 0x55, 0x57, 0x80, 0x00, + 0x00, 0x00, 0x00, 0x3F, 0x55, 0xA3, 0x2A, 0x83, 0x22, 0x28, 0x77, 0x77, 0x77, 0x77, 0x77, 0x75, + 0x57, 0x77, 0x77, 0x77, 0x79, 0xA2, 0x22, 0x22, 0x23, 0x52, 0x22, 0x29, 0x85, 0x77, 0x5F, 0x20, + 0x00, 0x00, 0x00, 0x00, 0x3F, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xFA, 0x57, 0x77, 0x77, 0x77, + 0x77, 0x5F, 0x10, 0x00, 0x00, 0x00, 0x01, 0xF5, 0x77, 0x77, 0x77, 0x77, 0x5F, 0x10, 0x00, 0x00, + 0x00, 0x00, 0x58, 0x5F, 0x30, 0x00, 0x00, 0x00, 0x00, 0x87, 0x58, 0xFF, 0xFF, 0xFF, 0x20, 0x00, + 0x00, 0x00, 0x00, 0x3A, 0x46, 0x89, 0x23, 0xA3, 0x22, 0x25, 0x87, 0x77, 0x77, 0x77, 0x77, 0x75, + 0x47, 0x77, 0x77, 0x77, 0x75, 0xA2, 0x22, 0x22, 0x29, 0x92, 0x22, 0x23, 0xA5, 0x77, 0x5F, 0x10, + 0x00, 0x00, 0x00, 0x00, 0x23, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0xA5, 0x77, 0x77, 0x77, + 0x77, 0x4A, 0x00, 0x00, 0x00, 0x00, 0x02, 0xF5, 0x77, 0x77, 0x77, 0x77, 0x85, 0x00, 0x00, 0x00, + 0x00, 0x01, 0xF5, 0x5F, 0x10, 0x00, 0x00, 0x00, 0x01, 0xF5, 0xA4, 0x33, 0x33, 0x31, 0x00, 0x00, + 0x00, 0x00, 0x01, 0xF5, 0x77, 0x7A, 0x23, 0xA9, 0x22, 0x25, 0x86, 0x77, 0x77, 0x77, 0x77, 0x74, + 0x47, 0x77, 0x77, 0x77, 0x58, 0x92, 0x22, 0x22, 0x29, 0xA2, 0x22, 0x23, 0xA5, 0x77, 0x85, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0x57, 0x77, 0x77, + 0x74, 0xA3, 0x00, 0x00, 0x00, 0x00, 0x03, 0xF5, 0x77, 0x77, 0x77, 0x75, 0xA3, 0x00, 0x00, 0x00, + 0x00, 0x02, 0xF5, 0x5F, 0x10, 0x00, 0x00, 0x00, 0x02, 0xFA, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x2F, 0x47, 0x77, 0x5A, 0x22, 0xA9, 0x22, 0x25, 0x86, 0x77, 0x77, 0x77, 0x77, 0x74, + 0x47, 0x77, 0x77, 0x77, 0x5A, 0x32, 0x22, 0x22, 0x25, 0xA3, 0x22, 0x23, 0xA5, 0x77, 0x5F, 0x10, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xF5, 0x77, 0x77, + 0x75, 0xF3, 0x00, 0x00, 0x00, 0x00, 0x05, 0x84, 0x77, 0x77, 0x77, 0x75, 0xF3, 0x00, 0x00, 0x00, + 0x00, 0x03, 0xF5, 0xA3, 0x00, 0x00, 0x00, 0x00, 0x03, 0xF3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x03, 0xF5, 0x77, 0x77, 0x5A, 0x22, 0xA8, 0x22, 0x27, 0x77, 0x77, 0x77, 0x77, 0x77, 0x74, + 0x47, 0x77, 0x77, 0x77, 0x5A, 0x32, 0x23, 0x22, 0x2A, 0x33, 0x32, 0x23, 0x85, 0x77, 0x4A, 0x70, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3A, 0x57, 0x77, + 0x75, 0xF1, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x57, 0x77, 0x77, 0x77, 0x75, 0xF1, 0x00, 0x00, 0x00, + 0x00, 0x03, 0xA5, 0xF3, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x3F, 0x57, 0x77, 0x77, 0x5A, 0x22, 0x5A, 0x22, 0x28, 0x67, 0x77, 0x77, 0x77, 0x77, 0x74, + 0x57, 0x77, 0x77, 0x77, 0x5A, 0x32, 0x29, 0x22, 0x2A, 0x32, 0x82, 0x29, 0x85, 0x77, 0x75, 0xF3, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xA5, 0x77, + 0x75, 0xF1, 0x00, 0x00, 0x00, 0x00, 0x2F, 0x57, 0x77, 0x77, 0x77, 0x74, 0xA0, 0x00, 0x00, 0x00, + 0x00, 0x1F, 0x55, 0xF2, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x03, 0xF5, 0x77, 0x77, 0x77, 0x5A, 0x22, 0x3A, 0x22, 0x2A, 0x57, 0x77, 0x77, 0x77, 0x77, 0x75, + 0x57, 0x77, 0x77, 0x77, 0x5A, 0x32, 0x33, 0x22, 0x2A, 0x32, 0x27, 0x23, 0x86, 0x77, 0x77, 0x5F, + 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xF7, 0x47, + 0x4A, 0x30, 0x00, 0x00, 0x00, 0x00, 0x3F, 0x57, 0x77, 0x77, 0x77, 0x4A, 0x30, 0x00, 0x00, 0x00, + 0x00, 0x1F, 0x55, 0xF1, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x0A, 0x44, 0x77, 0x77, 0x77, 0x5A, 0x22, 0x3F, 0x22, 0x2A, 0x57, 0x77, 0x77, 0x77, 0x77, 0x75, + 0x67, 0x77, 0x77, 0x77, 0x5A, 0x32, 0xA3, 0x22, 0x2A, 0x32, 0x22, 0xA9, 0x87, 0x77, 0x77, 0x75, + 0xF1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x47, + 0x5F, 0x30, 0x00, 0x00, 0x00, 0x00, 0x3A, 0x47, 0x77, 0x77, 0x77, 0x5F, 0x30, 0x00, 0x00, 0x00, + 0x00, 0x3F, 0x58, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0xF5, 0x77, 0x77, 0x77, 0x5A, 0x22, 0x3F, 0x32, 0x2A, 0x97, 0x77, 0x77, 0x77, 0x77, 0x76, + 0x98, 0x77, 0x77, 0x77, 0x5A, 0x22, 0xF3, 0x22, 0x2A, 0x32, 0x22, 0x3A, 0x57, 0x77, 0x77, 0x74, + 0x7A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xF5, + 0x5F, 0x20, 0x00, 0x00, 0x00, 0x00, 0xA4, 0x77, 0x77, 0x77, 0x77, 0x5F, 0x10, 0x00, 0x00, 0x00, + 0x00, 0x3A, 0x5A, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x2F, 0x57, 0x77, 0x77, 0x5A, 0x22, 0x3F, 0x32, 0x3A, 0x97, 0x77, 0x77, 0x77, 0x77, 0x89, + 0x98, 0x77, 0x77, 0x77, 0x5A, 0x22, 0xF3, 0x22, 0x2A, 0x32, 0x22, 0x2A, 0x57, 0x77, 0x77, 0x77, + 0x5A, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, + 0x5F, 0x10, 0x00, 0x00, 0x00, 0x01, 0xF5, 0x77, 0x77, 0x77, 0x77, 0x5F, 0x10, 0x00, 0x00, 0x00, + 0x00, 0xA7, 0x5F, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x03, 0xF5, 0x77, 0x77, 0x68, 0x22, 0x2F, 0x32, 0x3A, 0x57, 0x77, 0x77, 0x77, 0x77, 0x89, + 0x98, 0x77, 0x77, 0x77, 0x5A, 0x33, 0xF3, 0x22, 0x28, 0x32, 0x22, 0x23, 0x85, 0x77, 0x77, 0x77, + 0x75, 0xF3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xF5, + 0x85, 0x00, 0x00, 0x00, 0x00, 0x03, 0xF5, 0x77, 0x77, 0x77, 0x74, 0xA3, 0x00, 0x00, 0x00, 0x00, + 0x01, 0xF5, 0x5F, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x3A, 0x57, 0x76, 0x89, 0x22, 0x2F, 0x32, 0x3A, 0x57, 0x77, 0x77, 0x77, 0x77, 0x89, + 0x94, 0x77, 0x77, 0x77, 0x5A, 0x33, 0xF3, 0x22, 0x23, 0x82, 0x22, 0x23, 0xA5, 0x77, 0x77, 0x77, + 0x77, 0x5A, 0x53, 0x33, 0x55, 0x55, 0x55, 0x55, 0x53, 0x33, 0x00, 0x00, 0x00, 0x00, 0x02, 0xF5, + 0xA3, 0x00, 0x00, 0x00, 0x00, 0x03, 0xA5, 0x77, 0x77, 0x77, 0x75, 0xF3, 0x00, 0x00, 0x00, 0x00, + 0x03, 0xF5, 0x4A, 0x00, 0x00, 0x00, 0x00, 0x03, 0x83, 0x33, 0x33, 0x33, 0x35, 0x20, 0x00, 0x00, + 0x00, 0x00, 0x1F, 0x57, 0x75, 0x83, 0x22, 0x2F, 0x22, 0x58, 0x67, 0x77, 0x77, 0x77, 0x77, 0x49, + 0x94, 0x77, 0x77, 0x77, 0x5A, 0x33, 0xA3, 0x22, 0x23, 0xA3, 0x22, 0x23, 0xA5, 0x77, 0x77, 0x77, + 0x77, 0x75, 0x8A, 0xAA, 0x88, 0x88, 0x88, 0x88, 0x88, 0xF3, 0x00, 0x00, 0x00, 0x00, 0x03, 0xF5, + 0xF3, 0x00, 0x00, 0x00, 0x00, 0x08, 0x77, 0x77, 0x77, 0x77, 0x75, 0xF2, 0x00, 0x00, 0x00, 0x00, + 0x03, 0xA5, 0xA3, 0x00, 0x00, 0x00, 0x00, 0x03, 0xF8, 0xAA, 0xAA, 0xAA, 0xAA, 0xF0, 0x00, 0x00, + 0x00, 0x00, 0x2F, 0x57, 0x75, 0xA3, 0x22, 0x2F, 0x22, 0xA5, 0x77, 0x77, 0x77, 0x77, 0x77, 0x49, + 0xB4, 0x77, 0x77, 0x77, 0x78, 0x99, 0xA3, 0x22, 0x23, 0xAA, 0x32, 0x23, 0xA9, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x45, 0xF3, 0x00, 0x00, 0x00, 0x00, 0x05, 0x85, + 0xF1, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x57, 0x77, 0x77, 0x77, 0x75, 0xF1, 0x00, 0x00, 0x00, 0x00, + 0x05, 0x85, 0xF3, 0x00, 0x00, 0x00, 0x00, 0x04, 0x44, 0x44, 0x44, 0x44, 0x47, 0x50, 0x00, 0x00, + 0x00, 0x00, 0x3F, 0x57, 0x75, 0xA3, 0x22, 0x3F, 0x22, 0xA9, 0x77, 0x77, 0x77, 0x77, 0x77, 0x4B, + 0xB4, 0x77, 0x77, 0x77, 0x77, 0x85, 0xA3, 0x22, 0x23, 0xF2, 0x33, 0x22, 0xA9, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x75, 0xF2, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x57, + 0xA0, 0x00, 0x00, 0x00, 0x00, 0x2F, 0x57, 0x77, 0x77, 0x77, 0x48, 0x50, 0x00, 0x00, 0x00, 0x00, + 0x1F, 0x55, 0xF2, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x57, 0x77, 0x77, 0x77, 0x5A, 0x30, 0x00, 0x00, + 0x00, 0x00, 0x58, 0x47, 0x79, 0xA3, 0x22, 0x3F, 0x23, 0xA5, 0x77, 0x77, 0x77, 0x77, 0x77, 0x4B, + 0xB6, 0x77, 0x77, 0x77, 0x77, 0x75, 0x83, 0x22, 0x22, 0xF2, 0x23, 0x32, 0xA5, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x47, 0x77, 0x77, 0x77, 0x77, 0x77, 0x75, 0xF1, 0x00, 0x00, 0x00, 0x00, 0x2F, 0x5A, + 0x30, 0x00, 0x00, 0x00, 0x00, 0x3F, 0x57, 0x77, 0x77, 0x77, 0x5A, 0x30, 0x00, 0x00, 0x00, 0x00, + 0x2F, 0x55, 0xF1, 0x00, 0x00, 0x00, 0x00, 0x2F, 0x57, 0x77, 0x77, 0x77, 0x5F, 0x30, 0x00, 0x00, + 0x00, 0x01, 0xF5, 0x77, 0x79, 0xA2, 0x22, 0x3A, 0x23, 0x87, 0x77, 0x77, 0x77, 0x77, 0x77, 0x6B, + 0xB9, 0x87, 0x77, 0x77, 0x77, 0x77, 0x85, 0x22, 0x22, 0xF3, 0x22, 0x38, 0x97, 0x77, 0x77, 0x77, + 0x77, 0x75, 0xA8, 0x77, 0x77, 0x77, 0x77, 0x77, 0x48, 0x50, 0x00, 0x00, 0x00, 0x00, 0x3F, 0x5F, + 0x30, 0x00, 0x00, 0x00, 0x00, 0x58, 0x47, 0x77, 0x77, 0x77, 0x5F, 0x30, 0x00, 0x00, 0x00, 0x00, + 0x3F, 0x58, 0x50, 0x00, 0x00, 0x00, 0x00, 0x3F, 0x57, 0x77, 0x77, 0x77, 0x5F, 0x10, 0x00, 0x00, + 0x00, 0x02, 0xF5, 0x77, 0x75, 0xA2, 0x22, 0x39, 0x3A, 0x57, 0x77, 0x77, 0x77, 0x77, 0x78, 0x9B, + 0xE9, 0x47, 0x77, 0x77, 0x77, 0x77, 0x5A, 0x22, 0x22, 0xA3, 0x22, 0x23, 0xA5, 0x77, 0x77, 0x77, + 0x77, 0x5F, 0x35, 0x87, 0x77, 0x77, 0x77, 0x77, 0x5F, 0x30, 0x00, 0x00, 0x00, 0x00, 0x3A, 0x5F, + 0x10, 0x00, 0x00, 0x00, 0x01, 0xF5, 0x77, 0x77, 0x77, 0x77, 0x5F, 0x10, 0x00, 0x00, 0x00, 0x00, + 0x3A, 0x5A, 0x30, 0x00, 0x00, 0x00, 0x00, 0x58, 0x47, 0x77, 0x77, 0x77, 0x4A, 0x00, 0x00, 0x00, + 0x00, 0x03, 0xF5, 0x77, 0x68, 0x92, 0x22, 0x59, 0x38, 0x57, 0x77, 0x77, 0x77, 0x77, 0x74, 0x9E, + 0xE9, 0x47, 0x77, 0x77, 0x77, 0x77, 0x9A, 0x22, 0x22, 0x99, 0x22, 0x22, 0x3A, 0x57, 0x77, 0x77, + 0x75, 0xF3, 0x1A, 0x47, 0x77, 0x77, 0x77, 0x77, 0x5F, 0x20, 0x00, 0x00, 0x00, 0x00, 0xA5, 0x5A, + 0x00, 0x00, 0x00, 0x00, 0x02, 0xF5, 0x77, 0x77, 0x77, 0x77, 0x4A, 0x00, 0x00, 0x00, 0x00, 0x01, + 0xF5, 0x5F, 0x30, 0x00, 0x00, 0x00, 0x01, 0xF5, 0x77, 0x77, 0x77, 0x74, 0xA3, 0x00, 0x00, 0x00, + 0x00, 0x03, 0xA4, 0x77, 0x5A, 0x32, 0x22, 0xA5, 0x85, 0x77, 0x77, 0x77, 0x77, 0x77, 0x74, 0x9E, + 0xEB, 0x47, 0x77, 0x77, 0x77, 0x77, 0x5A, 0x32, 0x22, 0x3A, 0x22, 0x22, 0x2A, 0x97, 0x77, 0x77, + 0x5F, 0x30, 0x1F, 0x57, 0x77, 0x77, 0x77, 0x77, 0x5F, 0x10, 0x00, 0x00, 0x00, 0x01, 0xF5, 0xA3, + 0x00, 0x00, 0x00, 0x00, 0x03, 0xF5, 0x77, 0x77, 0x77, 0x74, 0xA3, 0x00, 0x00, 0x00, 0x00, 0x01, + 0xF5, 0x5F, 0x10, 0x00, 0x00, 0x00, 0x02, 0xF5, 0x77, 0x77, 0x77, 0x75, 0xF3, 0x00, 0x00, 0x00, + 0x00, 0x1A, 0x57, 0x77, 0x9A, 0x32, 0x22, 0xA9, 0x58, 0x87, 0x77, 0x77, 0x77, 0x77, 0x74, 0xBE, + 0xDB, 0x47, 0x77, 0x77, 0x77, 0x77, 0x5A, 0x32, 0x22, 0x2F, 0x22, 0x22, 0x28, 0x67, 0x77, 0x75, + 0xF3, 0x00, 0x3F, 0x57, 0x77, 0x77, 0x77, 0x77, 0x85, 0x00, 0x00, 0x00, 0x00, 0x03, 0xF5, 0xF3, + 0x00, 0x00, 0x00, 0x00, 0x03, 0xA4, 0x77, 0x77, 0x77, 0x75, 0xF3, 0x00, 0x00, 0x00, 0x00, 0x03, + 0xF5, 0x7A, 0x00, 0x00, 0x00, 0x00, 0x03, 0xF5, 0x77, 0x77, 0x77, 0x75, 0xF1, 0x00, 0x00, 0x00, + 0x00, 0x1F, 0x57, 0x77, 0x5A, 0x22, 0x23, 0xA9, 0xA3, 0x38, 0x67, 0x77, 0x77, 0x77, 0x74, 0xBD, + 0xDB, 0x98, 0x77, 0x77, 0x77, 0x77, 0x68, 0x92, 0x22, 0x2A, 0x32, 0x22, 0x23, 0xA5, 0x77, 0x5F, + 0x30, 0x00, 0x3A, 0x47, 0x77, 0x77, 0x77, 0x75, 0xA3, 0x00, 0x00, 0x00, 0x00, 0x03, 0xA5, 0xF2, + 0x00, 0x00, 0x00, 0x00, 0x1F, 0x57, 0x77, 0x77, 0x77, 0x75, 0xF2, 0x00, 0x00, 0x00, 0x00, 0x03, + 0xA5, 0xA3, 0x00, 0x00, 0x00, 0x00, 0x03, 0xA4, 0x77, 0x77, 0x77, 0x75, 0xF1, 0x00, 0x00, 0x00, + 0x00, 0x3F, 0x56, 0x76, 0x89, 0x22, 0x23, 0xA5, 0x52, 0x98, 0x77, 0x77, 0x77, 0x77, 0x89, 0xBD, + 0xDE, 0x94, 0x77, 0x77, 0x77, 0x77, 0x75, 0xA2, 0x22, 0x23, 0xA9, 0x22, 0x22, 0xA9, 0x75, 0xF3, + 0x00, 0x00, 0xA7, 0x77, 0x77, 0x77, 0x77, 0x75, 0xF3, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x75, 0xF1, + 0x00, 0x00, 0x00, 0x00, 0x2F, 0x57, 0x77, 0x77, 0x77, 0x75, 0xF1, 0x00, 0x00, 0x00, 0x00, 0x0A, + 0x45, 0xF3, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x47, 0x77, 0x77, 0x77, 0x4A, 0x30, 0x00, 0x00, 0x00, + 0x00, 0x3A, 0x58, 0x85, 0xA3, 0x22, 0x28, 0x9A, 0x32, 0xA9, 0x77, 0x77, 0x77, 0x77, 0x49, 0xED, + 0xDE, 0xB4, 0x77, 0x77, 0x77, 0x77, 0x75, 0xA3, 0x22, 0x23, 0xA3, 0x93, 0x22, 0xA6, 0x5F, 0x30, + 0x00, 0x01, 0xF5, 0x55, 0x55, 0x55, 0x55, 0x55, 0xF1, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x58, 0x50, + 0x00, 0x00, 0x00, 0x00, 0x3A, 0x55, 0x55, 0x55, 0x55, 0x54, 0x50, 0x00, 0x00, 0x00, 0x00, 0x1F, + 0x55, 0xF1, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x55, 0x55, 0x55, 0x55, 0x5F, 0x30, 0x00, 0x00, 0x00, + 0x00, 0xA5, 0x83, 0x95, 0xA2, 0x22, 0x2A, 0x57, 0x23, 0xA5, 0x77, 0x77, 0x77, 0x77, 0x4B, 0xED, + 0xDD, 0xB5, 0x77, 0x77, 0x77, 0x77, 0x75, 0xA3, 0x22, 0x22, 0xF3, 0x23, 0x32, 0x54, 0xF3, 0x00, + 0x00, 0x03, 0xFA, 0xFF, 0xFF, 0xFF, 0xFA, 0xAA, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x3F, 0x5F, 0x30, + 0x00, 0x00, 0x00, 0x00, 0x3F, 0xAA, 0xAA, 0xAF, 0xFA, 0xAF, 0x30, 0x00, 0x00, 0x00, 0x00, 0x3F, + 0x54, 0xA0, 0x00, 0x00, 0x00, 0x00, 0x3F, 0xAF, 0xFF, 0xFF, 0xFA, 0xAF, 0x10, 0x00, 0x00, 0x00, + 0x01, 0xF5, 0xA3, 0x3A, 0x92, 0x22, 0x3A, 0xA2, 0x23, 0xA5, 0x77, 0x77, 0x77, 0x77, 0x5B, 0xDD, + 0xDD, 0xC9, 0x87, 0x77, 0x77, 0x77, 0x77, 0x5A, 0x22, 0x22, 0x39, 0x22, 0x3F, 0x5F, 0x30, 0x00, + 0x00, 0x03, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x30, 0x00, 0x00, 0x00, 0x00, 0x3A, 0x5F, 0x20, + 0x00, 0x00, 0x00, 0x00, 0x13, 0x33, 0x33, 0x33, 0x33, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3A, + 0x5A, 0x30, 0x00, 0x00, 0x00, 0x00, 0x33, 0x33, 0x33, 0x33, 0x33, 0x31, 0x00, 0x00, 0x00, 0x00, + 0x03, 0xF9, 0xA2, 0x3F, 0x32, 0x22, 0x9A, 0x32, 0x2A, 0x57, 0x77, 0x77, 0x77, 0x78, 0x9C, 0xDD, + 0xDD, 0xE9, 0x47, 0x77, 0x77, 0x77, 0x77, 0x9A, 0x32, 0x22, 0x3F, 0x22, 0x35, 0xF3, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x58, 0x5F, 0x10, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA4, + 0x5F, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x03, 0xA9, 0xA2, 0x2F, 0x22, 0x22, 0xF3, 0x22, 0x3A, 0x57, 0x77, 0x77, 0x77, 0x74, 0x9E, 0xDD, + 0xDD, 0xDB, 0x47, 0x77, 0x77, 0x77, 0x77, 0x5A, 0x32, 0x22, 0x2A, 0x33, 0x8F, 0x30, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xF5, 0x85, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xA4, + 0x5F, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x07, 0x74, 0x82, 0x39, 0x22, 0x23, 0x92, 0x22, 0x58, 0x77, 0x77, 0x77, 0x77, 0x74, 0xBD, 0xDD, + 0xDD, 0xDB, 0x98, 0x77, 0x77, 0x77, 0x77, 0x75, 0xA2, 0x22, 0x23, 0xA4, 0xF3, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xA5, 0x85, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0x55, + 0xAA, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x2F, 0x5A, 0x32, 0x33, 0x22, 0x23, 0x22, 0x22, 0xA9, 0x77, 0x77, 0x77, 0x77, 0x89, 0xBD, 0xDD, + 0xDD, 0xDE, 0x94, 0x77, 0x77, 0x77, 0x77, 0x75, 0xA3, 0x22, 0x29, 0x5F, 0x30, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0x57, 0x5F, 0x30, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0xA5, 0x5A, + 0x51, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, + 0xF5, 0x9A, 0x22, 0x32, 0x22, 0x22, 0x22, 0x29, 0x85, 0x77, 0x77, 0x77, 0x77, 0x49, 0xED, 0xDD, + 0xDD, 0xDD, 0xB4, 0x77, 0x77, 0x77, 0x77, 0x77, 0x88, 0x22, 0x54, 0xF3, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xF5, 0x77, 0x75, 0xF2, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xAA, 0x55, 0xF3, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, + 0x57, 0x5A, 0x22, 0x22, 0x22, 0x22, 0x22, 0x2A, 0x97, 0x77, 0x77, 0x77, 0x77, 0x4B, 0xDD, 0xDD, + 0xDD, 0xDD, 0xC9, 0x87, 0x77, 0x77, 0x77, 0x77, 0x5A, 0x33, 0x8F, 0x30, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x4A, 0x57, 0x77, 0x77, 0x5F, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x85, 0x5F, 0x30, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xF5, + 0x75, 0xA3, 0x22, 0x22, 0x22, 0x22, 0x22, 0x98, 0x67, 0x77, 0x77, 0x77, 0x78, 0x9C, 0xDD, 0xDD, + 0xDD, 0xDD, 0xEB, 0x47, 0x77, 0x77, 0x77, 0x77, 0x75, 0xA4, 0xF3, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1A, 0xA5, 0x77, 0x77, 0x77, 0x5A, + 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xF4, 0x55, 0xF3, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0x57, + 0x79, 0xA2, 0x22, 0x22, 0x22, 0x22, 0x23, 0xA9, 0x77, 0x77, 0x77, 0x77, 0x74, 0xBE, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDB, 0x68, 0x77, 0x77, 0x77, 0x77, 0x78, 0x5F, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xF8, 0x57, 0x77, 0x77, 0x77, 0x75, + 0xF3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0x54, 0x4F, 0x30, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xF5, 0x77, + 0x58, 0x32, 0x22, 0x22, 0x22, 0x22, 0x2A, 0x57, 0x77, 0x77, 0x77, 0x77, 0x86, 0xBD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDE, 0x94, 0x77, 0x77, 0x77, 0x77, 0x75, 0xF3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2F, 0x75, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x5F, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xF5, 0x44, 0xF2, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0x57, 0x77, + 0x9A, 0x22, 0x22, 0x23, 0x32, 0x22, 0x3A, 0x57, 0x77, 0x77, 0x77, 0x77, 0x49, 0xED, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xB4, 0x77, 0x77, 0x77, 0x77, 0x4A, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xF5, 0x47, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x75, 0xF1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0x57, 0x5F, 0x30, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xF5, 0x88, 0x67, + 0x89, 0x22, 0x22, 0x2A, 0x22, 0x22, 0xA9, 0x77, 0x77, 0x77, 0x77, 0x77, 0x4B, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xE9, 0x47, 0x77, 0x77, 0x77, 0x78, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, + 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x5F, 0x54, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x7A, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x58, 0xA5, 0x77, 0x77, 0x35, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0xAA, 0x58, 0x93, 0x89, + 0xA2, 0x22, 0x22, 0xA2, 0x22, 0x28, 0x77, 0x77, 0x77, 0x77, 0x77, 0x74, 0x9E, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDB, 0x47, 0x77, 0x77, 0x77, 0x77, 0x8A, 0xAA, 0xA8, 0x88, 0x88, 0xAA, 0xA8, + 0x88, 0x87, 0x8A, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0x85, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x74, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x87, 0x57, 0x77, 0x77, 0xA8, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x45, 0x5A, 0x33, 0xA7, + 0x92, 0x22, 0x23, 0x32, 0x22, 0x3A, 0x57, 0x77, 0x77, 0x77, 0x77, 0x74, 0xBD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDE, 0x98, 0x77, 0x77, 0x77, 0x77, 0x74, 0x44, 0x5A, 0xAA, 0xAA, 0x45, 0x8A, + 0xAA, 0xAA, 0x85, 0x44, 0x44, 0x44, 0x44, 0x44, 0x47, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x47, 0x77, 0x77, 0x77, 0x74, 0x44, 0x44, + 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x77, 0x5A, 0x23, 0x8A, + 0x22, 0x22, 0x3F, 0x22, 0x23, 0xA9, 0x77, 0x77, 0x77, 0x77, 0x77, 0x89, 0xED, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xB4, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x72, 0x22, 0x22, 0xAA, 0x32, + 0x22, 0x22, 0x3A, 0x57, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x75, 0xA3, 0x28, 0xA3, + 0x22, 0x22, 0xF3, 0x22, 0x2A, 0x97, 0x77, 0x77, 0x77, 0x77, 0x77, 0x4B, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xE9, 0x87, 0x77, 0x77, 0x77, 0x77, 0x75, 0xA3, 0x22, 0x22, 0x2A, 0x32, + 0x22, 0x22, 0x28, 0x85, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x75, 0xA2, 0x2A, 0xA2, + 0x22, 0x2A, 0x32, 0x22, 0xA5, 0x77, 0x77, 0x77, 0x77, 0x77, 0x78, 0x9E, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDB, 0x47, 0x77, 0x77, 0x77, 0x77, 0x77, 0x5A, 0x22, 0x22, 0x23, 0xF3, + 0x22, 0x22, 0x22, 0x88, 0x57, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x9A, 0x32, 0x3F, 0x32, + 0x22, 0x3A, 0x22, 0x2A, 0x85, 0x77, 0x77, 0x77, 0x77, 0x77, 0x74, 0xBD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDE, 0x94, 0x77, 0x77, 0x77, 0x77, 0x77, 0x58, 0x52, 0x22, 0x22, 0x3A, + 0x32, 0x22, 0x22, 0x25, 0x55, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x75, 0xA3, 0x22, 0xA3, 0x22, + 0x23, 0xF2, 0x22, 0x88, 0x57, 0x77, 0x77, 0x77, 0x77, 0x77, 0x49, 0xED, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDE, 0xB5, 0x87, 0x77, 0x77, 0x77, 0x77, 0x75, 0xA3, 0x22, 0x22, 0x23, + 0xA8, 0x99, 0x33, 0x35, 0xA8, 0x57, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x75, 0xA2, 0x22, 0xA2, 0x22, + 0x3F, 0x32, 0x28, 0x85, 0x77, 0x77, 0x77, 0x77, 0x77, 0x78, 0x5B, 0xED, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xE9, 0x47, 0x77, 0x77, 0x77, 0x77, 0x77, 0x9A, 0x32, 0x22, 0x22, + 0x9A, 0x32, 0x22, 0x22, 0x23, 0xA9, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x9A, 0x32, 0x29, 0x22, 0x22, + 0xF3, 0x22, 0xA8, 0x57, 0x77, 0x77, 0x77, 0x77, 0x77, 0x74, 0x9E, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDC, 0x98, 0x77, 0x77, 0x77, 0x77, 0x77, 0x79, 0xA2, 0x22, 0x22, + 0x28, 0xA3, 0x22, 0x22, 0x22, 0x3A, 0x55, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x67, 0x77, 0x75, 0xA3, 0x22, 0x22, 0x22, 0x2F, + 0x92, 0x2A, 0x58, 0x87, 0x77, 0x77, 0x77, 0x77, 0x77, 0x89, 0xCD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xB4, 0x77, 0x77, 0x77, 0x77, 0x77, 0x76, 0x5A, 0x22, 0x22, + 0x22, 0xAF, 0x32, 0x22, 0x22, 0x23, 0xAA, 0x57, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x75, 0x87, 0x77, 0x57, 0xA2, 0x22, 0x22, 0x22, 0xA9, + 0x23, 0xA9, 0xA9, 0x98, 0x77, 0x77, 0x77, 0x77, 0x77, 0x4B, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xE9, 0x47, 0x77, 0x77, 0x77, 0x77, 0x77, 0x58, 0x82, 0x22, + 0x22, 0x28, 0xA3, 0x22, 0x22, 0x22, 0x23, 0x55, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x76, 0x5A, 0x35, 0x77, 0x9A, 0x22, 0x22, 0x22, 0x28, 0xA3, + 0x3A, 0x9A, 0x33, 0x87, 0x77, 0x77, 0x77, 0x77, 0x74, 0x9E, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDC, 0x98, 0x77, 0x77, 0x77, 0x77, 0x77, 0x75, 0xA9, 0x22, + 0x22, 0x22, 0x7A, 0x32, 0x22, 0x22, 0x23, 0xAA, 0x65, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x57, 0xA3, 0x3A, 0x59, 0xA3, 0x22, 0x22, 0x22, 0x9A, 0x98, + 0xA9, 0xA3, 0x29, 0x85, 0x77, 0x77, 0x77, 0x77, 0x89, 0xCD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xB4, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x5A, 0x32, + 0x22, 0x22, 0x29, 0xA7, 0x53, 0x33, 0x33, 0x33, 0x8A, 0x55, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x79, 0xAA, 0x22, 0xA7, 0x9A, 0x32, 0x22, 0x22, 0x28, 0xA5, 0x89, + 0x7A, 0x22, 0x3A, 0x57, 0x77, 0x77, 0x77, 0x77, 0x4B, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xEB, 0x47, 0x77, 0x77, 0x77, 0x77, 0x77, 0x75, 0xA3, + 0x22, 0x22, 0x22, 0x3A, 0xA2, 0x22, 0x22, 0x22, 0x23, 0xAA, 0x57, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x75, 0x5A, 0x32, 0x29, 0xA9, 0xA3, 0x22, 0x22, 0x22, 0xA8, 0x56, 0x9A, + 0x82, 0x23, 0xA5, 0x77, 0x77, 0x77, 0x77, 0x74, 0xBE, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDE, 0x94, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x5A, + 0x92, 0x22, 0x22, 0x23, 0xAA, 0x32, 0x22, 0x22, 0x22, 0x23, 0xA7, 0x57, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x75, 0x9A, 0xA3, 0x22, 0x3A, 0x9A, 0x32, 0x22, 0x22, 0x2A, 0x85, 0x98, 0xA3, + 0x22, 0x3A, 0x97, 0x77, 0x77, 0x77, 0x77, 0x49, 0xED, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDE, 0xB9, 0x87, 0x77, 0x77, 0x77, 0x77, 0x77, 0x75, + 0xA9, 0x22, 0x22, 0x22, 0x2A, 0xF3, 0x22, 0x22, 0x22, 0x22, 0x25, 0x87, 0x55, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x98, 0xA3, 0x22, 0x23, 0xA9, 0xA2, 0x22, 0x22, 0x23, 0xA5, 0x97, 0xA9, 0x22, + 0x29, 0xA9, 0x77, 0x77, 0x77, 0x77, 0x78, 0x9B, 0xED, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDB, 0x58, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x5A, 0x82, 0x22, 0x22, 0x22, 0x3F, 0xA2, 0x22, 0x22, 0x23, 0x35, 0x57, 0xAA, 0x69, 0x57, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x55, 0xA3, 0x22, 0x22, 0x2A, 0x8A, 0x22, 0x22, 0x22, 0x3A, 0x98, 0xA8, 0x32, 0x22, + 0x8A, 0x57, 0x77, 0x77, 0x77, 0x77, 0x85, 0xBD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDE, 0xB4, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x75, 0x8A, 0x22, 0x22, 0x22, 0x23, 0xAF, 0x33, 0x33, 0x32, 0x22, 0x22, 0x23, 0x8A, 0xA7, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x76, + 0x55, 0x85, 0x8A, 0x32, 0x22, 0x22, 0xAA, 0x32, 0x22, 0x22, 0x29, 0xA8, 0xA9, 0x32, 0x22, 0x3A, + 0x85, 0x77, 0x77, 0x77, 0x77, 0x77, 0x4B, 0xED, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xEB, 0x47, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x55, 0xA3, 0x22, 0x22, 0x22, 0x23, 0xAA, 0x92, 0x22, 0x22, 0x22, 0x22, 0x22, 0x39, 0x55, + 0x59, 0x55, 0x67, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x65, 0x58, + 0xAA, 0x9A, 0x92, 0x22, 0x22, 0x2A, 0xA3, 0x22, 0x22, 0x23, 0xFA, 0x83, 0x22, 0x22, 0x23, 0xA5, + 0x57, 0x77, 0x77, 0x77, 0x77, 0x74, 0xBE, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDE, 0x94, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x9A, 0x32, 0x22, 0x22, 0x22, 0x29, 0xAA, 0x32, 0x22, 0x22, 0x22, 0x22, 0x23, 0xAA, + 0xAA, 0xAA, 0x85, 0x77, 0x76, 0x66, 0x77, 0x77, 0x77, 0x77, 0x65, 0x55, 0x57, 0x55, 0x8A, 0xA5, + 0x32, 0x39, 0x22, 0x22, 0x23, 0xF9, 0x22, 0x22, 0x22, 0x3A, 0x32, 0x22, 0x22, 0x22, 0x8A, 0x97, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x49, 0xED, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xE9, 0x47, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x79, 0xAA, 0x32, 0x22, 0x22, 0x22, 0x37, 0xFA, 0x32, 0x22, 0x22, 0x23, 0x33, 0x22, + 0x22, 0x33, 0x7A, 0x55, 0x88, 0x88, 0x75, 0x57, 0x75, 0x55, 0x88, 0xAA, 0xA5, 0x8A, 0x93, 0x22, + 0x22, 0x92, 0x22, 0x23, 0xAA, 0x32, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x3A, 0x75, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x74, 0x9E, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDE, 0x94, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x55, 0xA3, 0x22, 0x22, 0x22, 0x22, 0x39, 0xFA, 0x33, 0x33, 0x32, 0x22, 0x22, + 0x22, 0x22, 0x22, 0x9A, 0x59, 0x99, 0x7A, 0xA9, 0x7A, 0xAA, 0x93, 0x33, 0x3A, 0x32, 0x22, 0x22, + 0x25, 0x22, 0x23, 0xAF, 0x32, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x3A, 0xA9, 0x67, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x49, 0xED, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xE9, 0x47, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x9A, 0xA3, 0x22, 0x22, 0x22, 0x22, 0x23, 0xFF, 0xA3, 0x22, 0x22, 0x22, + 0x22, 0x22, 0x23, 0x32, 0x22, 0x22, 0x22, 0x23, 0xA3, 0x22, 0x22, 0x22, 0x33, 0x22, 0x22, 0x22, + 0x82, 0x23, 0xFA, 0x32, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x3A, 0xA5, 0x57, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x74, 0x9E, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDE, 0x94, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x75, 0x5A, 0x32, 0x22, 0x22, 0x22, 0x22, 0x23, 0x5A, 0xF3, 0x32, 0x22, + 0x22, 0x29, 0x32, 0x22, 0x22, 0x22, 0x22, 0x33, 0x22, 0x22, 0x22, 0x29, 0x32, 0x22, 0x22, 0x29, + 0x88, 0xF8, 0x32, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x23, 0x3A, 0xA5, 0x57, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x49, 0xED, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xE9, 0x47, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x79, 0x8A, 0x32, 0x22, 0x22, 0x22, 0x22, 0x22, 0x3A, 0xFF, 0x93, + 0x33, 0xA2, 0x22, 0x22, 0x22, 0x22, 0x39, 0x22, 0x22, 0x22, 0x22, 0x92, 0x22, 0x22, 0x23, 0xAA, + 0x83, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x23, 0xAA, 0xA5, 0x57, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x74, 0x9E, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDE, 0x94, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x59, 0xAA, 0x32, 0x22, 0x22, 0x22, 0x22, 0x22, 0x23, 0x5F, + 0xFA, 0x93, 0x32, 0x22, 0x22, 0x23, 0x32, 0x22, 0x22, 0x22, 0x2A, 0x32, 0x33, 0xAF, 0xF8, 0x32, + 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x23, 0x3A, 0xAA, 0x59, 0x57, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x49, 0xED, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xEB, 0x48, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x55, 0xAA, 0x32, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, + 0x33, 0x9A, 0xFF, 0xFF, 0xAA, 0xAA, 0x33, 0x33, 0x33, 0x3A, 0xFA, 0xAF, 0xA9, 0x32, 0x22, 0x22, + 0x22, 0x22, 0x22, 0x22, 0x23, 0x38, 0xAA, 0xA5, 0x95, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x84, 0xBE, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDE, 0xB5, 0x87, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x55, 0xAA, 0x32, 0x22, 0x22, 0x22, 0x22, 0x22, + 0x22, 0x22, 0x22, 0x33, 0x33, 0x99, 0xAA, 0xAA, 0x89, 0x33, 0x33, 0x22, 0x22, 0x22, 0x22, 0x22, + 0x22, 0x22, 0x33, 0x9A, 0xAA, 0xA6, 0x55, 0x57, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x78, 0x5B, 0xED, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xEB, 0x94, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x59, 0xAA, 0x73, 0x22, 0x22, 0x22, 0x22, + 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x23, + 0x33, 0xAA, 0xAA, 0xAA, 0x85, 0x57, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x49, 0xBE, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xB9, + 0x48, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x59, 0x7A, 0xA3, 0x32, 0x22, 0x22, + 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x23, 0x39, + 0x58, 0x79, 0x33, 0x33, 0x38, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x84, + 0x9B, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xEE, + 0xB4, 0x87, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x75, 0x58, 0xAA, 0x33, 0x22, + 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, + 0x22, 0x22, 0x22, 0x23, 0x38, 0x67, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x78, 0x4B, + 0xEE, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xEB, 0x94, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x75, 0x55, 0x8A, 0xA8, + 0x33, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, + 0x22, 0x23, 0x39, 0xAA, 0x87, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x49, 0xBE, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xC9, 0x48, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x55, 0x96, + 0xAA, 0xAA, 0x93, 0x33, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x33, + 0x9A, 0xAA, 0xA8, 0x55, 0x67, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x84, 0x9C, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDE, 0xB9, 0x48, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x55, 0x95, 0x8A, 0xAA, 0xAA, 0xA5, 0x93, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x5A, 0xAA, 0xAA, + 0x85, 0x95, 0x57, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x84, 0x9B, 0xED, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDC, 0xB5, 0x47, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x65, 0x55, 0x95, 0x58, 0x8A, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xA8, 0x85, 0x59, 0x55, + 0x57, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x74, 0x5B, 0xCD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xEB, 0x94, 0x47, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x74, 0x49, 0xBE, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xEB, 0x94, 0x47, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x74, 0x49, 0xBE, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xEB, 0x94, 0x47, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x74, 0x49, 0xBE, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xEB, 0x94, 0x48, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x84, 0x49, 0xBE, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xEB, 0x96, 0x48, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x84, 0x69, 0xBE, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xEB, 0xB9, 0x44, 0x87, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x78, 0x44, 0x9B, 0xBE, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDE, 0xEC, 0xB9, 0x94, 0x48, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x84, 0x49, 0x9B, 0xCE, 0xED, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDE, 0xBB, 0x99, 0x44, 0x48, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x84, 0x44, 0x99, 0xBB, 0xED, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xEC, 0xBB, 0x99, 0x44, + 0x44, 0x87, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x78, 0x44, + 0x44, 0x99, 0xBB, 0xCE, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDE, 0xEC, 0xBB, + 0x99, 0x96, 0x44, 0x44, 0x88, 0x87, 0x77, 0x77, 0x77, 0x77, 0x78, 0x88, 0x44, 0x44, 0x69, 0x99, + 0xBB, 0xCE, 0xED, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDE, + 0xEE, 0xBB, 0xBB, 0x99, 0x99, 0x96, 0x55, 0x44, 0x44, 0x55, 0x69, 0x99, 0x99, 0xBB, 0xBB, 0xEE, + 0xED, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, +}; + +// ASCII rendition for the text console, before the framebuffer exists. +const char* const boot_logo_ascii[] = { + " .. .. ..", + " .........:.. . ...", + " .......:-=--:-:----::. .....", + " .. .:====---=:::-=::+=--: ... ..", + " ....:--=--:::.....:-:-+=:-=-:..:. ..", + " ...:==---:.. .....::--:.:--: .:: ..", + " . :---:: ..... .... .--. . :: ..", + " . .-=--: .......... .... .: ...... :- ..", + " ...:=:-: :+%%%%#%%#=:== . :+#.*%%%%%#+ -: ..", + " .. ---: =@@+===%%=.=%@: -%@+ =++==*@@- -...", + ".. :=:- .%%# :. .%@+ . *@%..=* *@#. -. ..", + "...=--- :%@%****-. +@%: :%@+.%@*=*#@*: :-: ..", + "...:--- .:+****@@+ %@* . *@%.=@%***%%*..-:. ..", + " ...=:-. .. -%%--@%: :%@* %%+ *%# .-....", + " .. --:.-#=:-:#@#.%%#:::*@%.=@%=::=@@- --:...", + " ...-=#@@@@@@%+..+%@@@@%+-=%@@@@@@#-.==-. .", + " . .-=---::-. . :-:::. :----::::..---. .", + " .. :--::. .... . :-::. ..", + " .. .:----:... . .. ...:::--:.....", + " .. .:-------:::.::.:::-===-:....", + " .. ..::------=-==--:.....", + " .. ............ .", + NULL +}; diff --git a/kernel/main.c b/kernel/main.c index 49864e2..b8a41a0 100644 --- a/kernel/main.c +++ b/kernel/main.c @@ -87,6 +87,7 @@ #include #include #include +#include #include #include #include @@ -128,8 +129,17 @@ static void subos_modular_core_boot(void) { tsc_init(); printk(ANSI_BRIGHT_GREEN "OK\n" ANSI_RESET); + // The framebuffer exists from here on. This kernel boots to a text console, + // so the graphical splash is opt-in via `splash` on the command line -- + // raising it by default would hide the very console we are about to use. + // The ASCII logo printed at the top of boot covers the default case. + if (init_has_param("splash") && !init_has_param("nosplash")) { + boot_logo_splash_begin(); + } + // Network Subsystem, NetFilter, HTTPD & SSH Server printk(KERN_INFO "[6/14] Initializing Network Stack, NetFilter, HTTPD & SSHD... "); + boot_logo_splash_progress(40, "Bringing up the network stack"); filter_init(); httpd_init(); sshd_init(); @@ -166,6 +176,7 @@ static void subos_modular_core_boot(void) { // Crypto, Certificates, LSM Security, Authentication, Namespaces, Rust, SUB-Lang & C++ Subsystems printk(KERN_INFO "[8/14] Initializing Rust, C++ Core, SUB-Lang Engine, Keyring & Auth... "); + boot_logo_splash_progress(55, "Starting Rust, C++ and SUB-Lang engines"); rust_kernel_init(); cpp_kernel_init(); sub_kernel_init(); @@ -178,6 +189,7 @@ static void subos_modular_core_boot(void) { // Concurrency Primitives: Wait Queues, Futexes & Tiny RCU printk(KERN_INFO "[9/14] Initializing Wait Queues, Futex Hash & Tiny RCU... "); + boot_logo_splash_progress(65, "Initializing concurrency primitives"); wait_subsystem_init(); futex_init(); rcu_init(); @@ -196,6 +208,7 @@ static void subos_modular_core_boot(void) { // Virtual File System & Multi-Filesystem Support printk(KERN_INFO "[11/14] Mounting Virtual File System (VFS, devfs, procfs, sysfs)... "); + boot_logo_splash_progress(78, "Mounting the virtual file system"); vfs_init(); sysfs_init(); kobject_subsystem_init(); @@ -206,6 +219,7 @@ static void subos_modular_core_boot(void) { // Kernel Core: Signals, Modules, Syscalls, Tracing, Syslog, Metrics, Crond & Systemd printk(KERN_INFO "[12/14] Initializing Syslog, Metrics, Cron, Tracing, BPF & Services... "); + boot_logo_splash_progress(88, "Starting kernel services"); signal_init(); workqueue_init(); syscall_init(); @@ -220,6 +234,7 @@ static void subos_modular_core_boot(void) { // Preemptive Multi-Tasking & Userland printk(KERN_INFO "[13/14] Initializing Preemptive Task Scheduler & LazyBox... "); + boot_logo_splash_progress(95, "Starting the scheduler and userland"); sched_init(); lazybox_init(); ktest_init(); @@ -231,6 +246,9 @@ static void subos_modular_core_boot(void) { arch_enable_interrupts(); printk(ANSI_BRIGHT_GREEN "ACTIVE\n" ANSI_RESET); + // Return the screen to the console before handing over to the shell. + boot_logo_splash_end(); + // Launch Shell shell_run(); @@ -245,6 +263,8 @@ void kernel_main(void* memory_map, uint64_t memory_map_count) { serial_init(); printk_init(); + boot_logo_print_text(); + printk(ANSI_BRIGHT_CYAN "=================================================================\n" ANSI_RESET); printk(ANSI_BRIGHT_CYAN " SUB-OS 64-Bit [%s] Modular Monolithic Kernel %s\n" ANSI_RESET, arch_get_name(), kernel_get_version()); printk(ANSI_BRIGHT_CYAN "=================================================================\n\n" ANSI_RESET); @@ -276,6 +296,8 @@ void kernel_main_aarch64(void) { arch_early_init(); printk_init(); + boot_logo_print_text(); + printk(ANSI_BRIGHT_CYAN "=================================================================\n" ANSI_RESET); printk(ANSI_BRIGHT_CYAN " SUB-OS 64-Bit [%s] Modular Monolithic Kernel %s\n" ANSI_RESET, arch_get_name(), kernel_get_version()); printk(ANSI_BRIGHT_CYAN "=================================================================\n\n" ANSI_RESET); diff --git a/kernel/printk.c b/kernel/printk.c index 3758158..1c114af 100644 --- a/kernel/printk.c +++ b/kernel/printk.c @@ -12,6 +12,26 @@ static size_t dmesg_head = 0; static size_t dmesg_total = 0; static spinlock_t printk_lock = SPINLOCK_INIT; +// Console redirection state. `sink_active` guards against a sink that calls +// printk itself, which would otherwise recurse until the stack ran out. +static printk_sink_fn_t sink_fn = NULL; +static void* sink_ctx = NULL; +static bool sink_active = false; + +void printk_set_sink(printk_sink_fn_t fn, void* ctx) { + sink_fn = fn; + sink_ctx = ctx; +} + +void printk_clear_sink(void) { + sink_fn = NULL; + sink_ctx = NULL; +} + +bool printk_has_sink(void) { + return sink_fn != NULL; +} + void printk_init(void) { memset(dmesg_buffer, 0, sizeof(dmesg_buffer)); dmesg_head = 0; @@ -42,8 +62,14 @@ int vprintk(const char* fmt, va_list args) { len -= 2; } - // 1. Output to active TTY console - tty_write(display_ptr, (size_t)len); + // 1. Output to the active TTY console, or to the installed sink instead. + if (sink_fn && !sink_active) { + sink_active = true; + sink_fn(display_ptr, (size_t)len, sink_ctx); + sink_active = false; + } else if (!sink_fn) { + tty_write(display_ptr, (size_t)len); + } // 2. Output to serial console (COM1 on x86, PL011 on ARM/AArch64) #if defined(__aarch64__) || defined(__arm__) || defined(__armv8i__) diff --git a/lib/font8x8.c b/lib/font8x8.c new file mode 100644 index 0000000..296d76c --- /dev/null +++ b/lib/font8x8.c @@ -0,0 +1,117 @@ +// Shared 8x8 bitmap console font for SUB-OS +// +// One source of truth for the framebuffer console, the 2D canvas rasterizer +// and the desktop compositor. Covers printable ASCII 32..127; one byte per +// scanline, most significant bit leftmost. + +#include + +const uint8_t font8x8_basic[FONT8X8_GLYPHS][FONT8X8_HEIGHT] = { + {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // space + {0x18,0x3c,0x3c,0x18,0x18,0x00,0x18,0x00}, // ! + {0x66,0x66,0x24,0x00,0x00,0x00,0x00,0x00}, // " + {0x6c,0x6c,0xfe,0x6c,0xfe,0x6c,0x6c,0x00}, // # + {0x18,0x3e,0x60,0x3c,0x06,0x7c,0x18,0x00}, // $ + {0x00,0x63,0x66,0x0c,0x18,0x33,0x63,0x00}, // % + {0x38,0x6c,0x38,0x76,0xdc,0xcc,0x76,0x00}, // & + {0x18,0x18,0x30,0x00,0x00,0x00,0x00,0x00}, // ' + {0x0c,0x18,0x30,0x30,0x30,0x18,0x0c,0x00}, // ( + {0x30,0x18,0x0c,0x0c,0x0c,0x18,0x30,0x00}, // ) + {0x00,0x66,0x3c,0xff,0x3c,0x66,0x00,0x00}, // * + {0x00,0x18,0x18,0x7e,0x18,0x18,0x00,0x00}, // + + {0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x30}, // + {0x00,0x00,0x00,0x7e,0x00,0x00,0x00,0x00}, // - + {0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00}, // . + {0x06,0x0c,0x18,0x30,0x60,0xc0,0x80,0x00}, // / + {0x7c,0xc6,0xce,0xd6,0xe6,0xc6,0x7c,0x00}, // 0 + {0x18,0x38,0x18,0x18,0x18,0x18,0x7e,0x00}, // 1 + {0x7c,0xc6,0x06,0x1c,0x30,0x66,0xfe,0x00}, // 2 + {0x7c,0xc6,0x06,0x3c,0x06,0xc6,0x7c,0x00}, // 3 + {0x1c,0x3c,0x6c,0xcc,0xfe,0x0c,0x1e,0x00}, // 4 + {0xfe,0xc0,0xfc,0x06,0x06,0xc6,0x7c,0x00}, // 5 + {0x7c,0xc6,0xc0,0xfc,0xc6,0xc6,0x7c,0x00}, // 6 + {0xfe,0x06,0x0c,0x18,0x30,0x30,0x30,0x00}, // 7 + {0x7c,0xc6,0xc6,0x7c,0xc6,0xc6,0x7c,0x00}, // 8 + {0x7c,0xc6,0xc6,0x7e,0x06,0xc6,0x7c,0x00}, // 9 + {0x00,0x18,0x18,0x00,0x18,0x18,0x00,0x00}, // : + {0x00,0x18,0x18,0x00,0x18,0x18,0x30,0x00}, // ; + {0x06,0x0c,0x18,0x30,0x18,0x0c,0x06,0x00}, // < + {0x00,0x00,0x7e,0x00,0x7e,0x00,0x00,0x00}, // = + {0x60,0x30,0x18,0x0c,0x18,0x30,0x60,0x00}, // > + {0x7c,0xc6,0x0c,0x18,0x18,0x00,0x18,0x00}, // ? + {0x7c,0xc6,0xde,0xde,0xdc,0xc0,0x7c,0x00}, // @ + {0x38,0x6c,0xc6,0xfe,0xc6,0xc6,0xc6,0x00}, // A + {0xfc,0x66,0x66,0x7c,0x66,0x66,0xfc,0x00}, // B + {0x3c,0x66,0xc0,0xc0,0xc0,0x66,0x3c,0x00}, // C + {0xf8,0x6c,0x66,0x66,0x66,0x6c,0xf8,0x00}, // D + {0xfe,0x62,0x68,0x78,0x68,0x62,0xfe,0x00}, // E + {0xfe,0x62,0x68,0x78,0x68,0x60,0xf0,0x00}, // F + {0x3c,0x66,0xc0,0xc0,0xce,0x66,0x3e,0x00}, // G + {0xc6,0xc6,0xc6,0xfe,0xc6,0xc6,0xc6,0x00}, // H + {0x3c,0x18,0x18,0x18,0x18,0x18,0x3c,0x00}, // I + {0x1e,0x0c,0x0c,0x0c,0xcc,0xcc,0x78,0x00}, // J + {0xe6,0x66,0x6c,0x78,0x6c,0x66,0xe6,0x00}, // K + {0xf0,0x60,0x60,0x60,0x62,0x66,0xfe,0x00}, // L + {0xc6,0xee,0xfe,0xd6,0xc6,0xc6,0xc6,0x00}, // M + {0xc6,0xe6,0xf6,0xde,0xce,0xc6,0xc6,0x00}, // N + {0x7c,0xc6,0xc6,0xc6,0xc6,0xc6,0x7c,0x00}, // O + {0xfc,0x66,0x66,0x7c,0x60,0x60,0xf0,0x00}, // P + {0x7c,0xc6,0xc6,0xc6,0xd6,0xde,0x7c,0x06}, // Q + {0xfc,0x66,0x66,0x7c,0x6c,0x66,0xe6,0x00}, // R + {0x7c,0xc6,0x60,0x38,0x0c,0xc6,0x7c,0x00}, // S + {0x7e,0x18,0x18,0x18,0x18,0x18,0x18,0x00}, // T + {0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0x7c,0x00}, // U + {0xc6,0xc6,0xc6,0xc6,0xc6,0x6c,0x38,0x00}, // V + {0xc6,0xc6,0xc6,0xd6,0xfe,0xee,0xc6,0x00}, // W + {0xc6,0xc6,0x6c,0x38,0x6c,0xc6,0xc6,0x00}, // X + {0x66,0x66,0x66,0x3c,0x18,0x18,0x18,0x00}, // Y + {0xfe,0x06,0x0c,0x18,0x30,0x60,0xfe,0x00}, // Z + {0x3c,0x30,0x30,0x30,0x30,0x30,0x3c,0x00}, // [ + {0xc0,0x60,0x30,0x18,0x0c,0x06,0x02,0x00}, // backslash + {0x3c,0x0c,0x0c,0x0c,0x0c,0x0c,0x3c,0x00}, // ] + {0x10,0x38,0x6c,0xc6,0x00,0x00,0x00,0x00}, // ^ + {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff}, // _ + {0x30,0x18,0x0c,0x00,0x00,0x00,0x00,0x00}, // ` + {0x00,0x00,0x78,0x0c,0x7c,0xcc,0x76,0x00}, // a + {0xe0,0x60,0x7c,0x66,0x66,0x66,0xdc,0x00}, // b + {0x00,0x00,0x78,0xcc,0xc0,0xcc,0x78,0x00}, // c + {0x1c,0x0c,0x7c,0xcc,0xcc,0xcc,0x76,0x00}, // d + {0x00,0x00,0x78,0xcc,0xfc,0xc0,0x78,0x00}, // e + {0x38,0x6c,0x60,0xf0,0x60,0x60,0xf0,0x00}, // f + {0x00,0x00,0x76,0xcc,0xcc,0x7c,0x0c,0xf8}, // g + {0xe0,0x60,0x6c,0x76,0x66,0x66,0xe6,0x00}, // h + {0x18,0x00,0x38,0x18,0x18,0x18,0x3c,0x00}, // i + {0x0c,0x00,0x1c,0x0c,0x0c,0xcc,0xcc,0x78}, // j + {0xe0,0x60,0x66,0x6c,0x78,0x6c,0xe6,0x00}, // k + {0x38,0x18,0x18,0x18,0x18,0x18,0x3c,0x00}, // l + {0x00,0x00,0xec,0xfe,0xd6,0xc6,0xc6,0x00}, // m + {0x00,0x00,0xdc,0x66,0x66,0x66,0x66,0x00}, // n + {0x00,0x00,0x7c,0xc6,0xc6,0xc6,0x7c,0x00}, // o + {0x00,0x00,0xdc,0x66,0x66,0x7c,0x60,0xf0}, // p + {0x00,0x00,0x76,0xcc,0xcc,0x7c,0x0c,0x1e}, // q + {0x00,0x00,0xdc,0x76,0x60,0x60,0xf0,0x00}, // r + {0x00,0x00,0x7c,0xc0,0x78,0x0c,0xf8,0x00}, // s + {0x10,0x30,0x7c,0x30,0x30,0x34,0x18,0x00}, // t + {0x00,0x00,0xcc,0xcc,0xcc,0xcc,0x76,0x00}, // u + {0x00,0x00,0xc6,0xc6,0xc6,0x6c,0x38,0x00}, // v + {0x00,0x00,0xc6,0xc6,0xd6,0xfe,0x6c,0x00}, // w + {0x00,0x00,0xc6,0x6c,0x38,0x6c,0xc6,0x00}, // x + {0x00,0x00,0xcc,0xcc,0xcc,0x7c,0x0c,0xf8}, // y + {0x00,0x00,0xfc,0x18,0x30,0x60,0xfc,0x00}, // z + {0x0e,0x18,0x18,0x70,0x18,0x18,0x0e,0x00}, // { + {0x18,0x18,0x18,0x00,0x18,0x18,0x18,0x00}, // | + {0x70,0x18,0x18,0x0e,0x18,0x18,0x70,0x00}, // } + {0x76,0xdc,0x00,0x00,0x00,0x00,0x00,0x00}, // ~ + {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // DEL +}; + +const uint8_t* font8x8_glyph(char c) { + // Compare as unsigned: `char` is signed here, so a high-bit byte such as a + // CP437 box-drawing character would otherwise test as negative. + unsigned char uc = (unsigned char)c; + + // Anything outside the printable range renders as a question mark, which is + // more legible than a blank when a driver passes raw bytes straight through. + if (uc < FONT8X8_FIRST || uc > FONT8X8_LAST) uc = '?'; + return font8x8_basic[uc - FONT8X8_FIRST]; +} diff --git a/scripts/mklogo.py b/scripts/mklogo.py new file mode 100755 index 0000000..905b522 --- /dev/null +++ b/scripts/mklogo.py @@ -0,0 +1,154 @@ +#!/usr/bin/env python3 +"""Generate the SUB-OS boot logo asset from a source image. + +Emits init/logo_data.c: a 4-bit palette-indexed bitmap plus the ARGB palette +and an ASCII-art rendition used before the framebuffer is up. + + python3 scripts/mklogo.py ~/Pictures/logo_SUB.png + +Re-run this whenever the source artwork changes; init/logo_data.c is generated +and should not be hand-edited. +""" + +import sys +import os +from PIL import Image + +SIZE = 160 # Bitmap edge length in pixels +COLORS = 16 # Palette entries, one nibble per pixel +BACKGROUND = (11, 19, 43) # 0xFF0B132B, the desktop wallpaper's top gradient stop +ASCII_W = 46 # Text-mode logo width in characters +ASCII_RAMP = " .:-=+*#%@" + + +def build_bitmap(path): + img = Image.open(path).convert("RGBA") + + # Composite onto the wallpaper colour so the logo's transparent surround + # blends into the splash instead of turning black. + canvas = Image.new("RGB", img.size, BACKGROUND) + canvas.paste(img, (0, 0), img) + + canvas = canvas.resize((SIZE, SIZE), Image.LANCZOS) + + # Dithering would scatter isolated palette indices through flat areas and + # look like noise at this size, so quantize with it disabled. + quant = canvas.quantize(colors=COLORS, dither=Image.NONE) + + raw_palette = quant.getpalette()[: COLORS * 3] + palette = [tuple(raw_palette[i * 3 : i * 3 + 3]) for i in range(COLORS)] + indices = list(quant.getdata()) + return palette, indices + + +def build_ascii(path): + img = Image.open(path).convert("RGBA") + canvas = Image.new("RGB", img.size, BACKGROUND) + canvas.paste(img, (0, 0), img) + + # Console cells are about twice as tall as they are wide. + height = max(1, ASCII_W // 2) + small = canvas.convert("L").resize((ASCII_W, height), Image.LANCZOS) + + pixels = list(small.getdata()) + lo, hi = min(pixels), max(pixels) + span = max(1, hi - lo) + + rows = [] + for y in range(height): + row = [] + for x in range(ASCII_W): + level = (pixels[y * ASCII_W + x] - lo) * (len(ASCII_RAMP) - 1) // span + row.append(ASCII_RAMP[level]) + rows.append("".join(row).rstrip()) + while rows and not rows[0]: + rows.pop(0) + while rows and not rows[-1]: + rows.pop() + return rows + + +def transparent_mask(palette): + """Bitmask of palette entries close enough to the background to skip. + + The source art has a transparent surround, which the compositing step turns + into the background colour. Quantization then spreads that flat area across + several near-identical entries, and drawing them would stamp a visible + rectangle over whatever the logo sits on. Marking them lets the renderer + skip those pixels so only the logo itself is painted. + """ + mask = 0 + br, bg, bb = BACKGROUND + for i, (r, g, b) in enumerate(palette): + if abs(r - br) + abs(g - bg) + abs(b - bb) <= 12: + mask |= 1 << i + return mask + + +def emit(path, palette, indices, ascii_rows, out_path): + packed = [] + for i in range(0, len(indices), 2): + hi = indices[i] & 0x0F + lo = indices[i + 1] & 0x0F if i + 1 < len(indices) else 0 + packed.append((hi << 4) | lo) + + lines = [] + lines.append("// Generated by scripts/mklogo.py -- do not edit by hand.") + lines.append("// Source artwork: %s" % os.path.basename(path)) + lines.append("") + lines.append('#include ') + lines.append("") + lines.append("const int boot_logo_width = %d;" % SIZE) + lines.append("const int boot_logo_height = %d;" % SIZE) + lines.append("") + lines.append("// Palette entries that are background rather than artwork; the renderer") + lines.append("// skips these so the logo composites onto whatever is behind it.") + lines.append("const uint16_t boot_logo_transparent_mask = 0x%04X;" + % transparent_mask(palette)) + lines.append("") + lines.append("// 16-entry ARGB palette; index 0 is the wallpaper background.") + lines.append("const uint32_t boot_logo_palette[%d] = {" % COLORS) + for r, g, b in palette: + lines.append(" 0xFF%02X%02X%02X," % (r, g, b)) + lines.append("};") + lines.append("") + lines.append("// %dx%d pixels, two 4-bit indices per byte, row major." % (SIZE, SIZE)) + lines.append("const uint8_t boot_logo_bitmap[%d] = {" % len(packed)) + for i in range(0, len(packed), 16): + chunk = ", ".join("0x%02X" % b for b in packed[i : i + 16]) + lines.append(" %s," % chunk) + lines.append("};") + lines.append("") + lines.append("// ASCII rendition for the text console, before the framebuffer exists.") + lines.append("const char* const boot_logo_ascii[] = {") + for row in ascii_rows: + lines.append(' "%s",' % row.replace("\\", "\\\\").replace('"', '\\"')) + lines.append(" NULL") + lines.append("};") + lines.append("") + + with open(out_path, "w") as fh: + fh.write("\n".join(lines)) + + return len(packed), len(ascii_rows) + + +def main(): + if len(sys.argv) < 2: + print(__doc__) + return 1 + + src = os.path.expanduser(sys.argv[1]) + out = sys.argv[2] if len(sys.argv) > 2 else "init/logo_data.c" + + palette, indices = build_bitmap(src) + ascii_rows = build_ascii(src) + nbytes, nrows = emit(src, palette, indices, ascii_rows, out) + + print("%s: %dx%d bitmap, %d palette entries, %d bytes packed, %d ASCII rows" + % (out, SIZE, SIZE, len(palette), nbytes, nrows)) + return 0 + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/userland/lazybox/shell.c b/userland/lazybox/shell.c index a83b034..dabdb8a 100644 --- a/userland/lazybox/shell.c +++ b/userland/lazybox/shell.c @@ -250,6 +250,80 @@ static void cmd_matrix(void) { tty_clear(); } +// Builtins that animate or block on a keypress; a caller driving its own +// input loop (the desktop compositor) cannot afford to be suspended in one. +static const char* const g_blocking_builtins[] = { "matrix", "reboot", "shutdown", "poweroff", NULL }; + +bool shell_is_builtin(const char* name) { + if (!name) return false; + static const char* const names[] = { + "help", "neofetch", "version", "calc", "hexdump", "matrix", "beep", + "tty", "history", "clear", "cls", "reboot", "shutdown", "poweroff", NULL + }; + for (int i = 0; names[i]; i++) { + if (strcmp(names[i], name) == 0) return true; + } + return false; +} + +bool shell_builtin_blocks(const char* name) { + if (!name) return false; + for (int i = 0; g_blocking_builtins[i]; i++) { + if (strcmp(g_blocking_builtins[i], name) == 0) return true; + } + return false; +} + +bool shell_execute_builtin(const char* raw_cmd, int argc, char** argv, bool allow_blocking) { + if (argc < 1 || !argv || !argv[0]) return false; + if (!raw_cmd) raw_cmd = ""; + + if (!allow_blocking && shell_builtin_blocks(argv[0])) { + printk(ANSI_YELLOW "%s is not available from this console.\n" ANSI_RESET, argv[0]); + return true; + } + + if (strcmp(argv[0], "help") == 0) { + cmd_help(); + } else if (strcmp(argv[0], "neofetch") == 0 || strcmp(argv[0], "version") == 0) { + cmd_neofetch(); + } else if (strcmp(argv[0], "calc") == 0) { + cmd_calc(raw_cmd + 4); + } else if (strcmp(argv[0], "hexdump") == 0) { + cmd_hexdump(raw_cmd + 7); + } else if (strcmp(argv[0], "matrix") == 0) { + cmd_matrix(); + } else if (strcmp(argv[0], "beep") == 0) { + speaker_beep(587, 100); + } else if (strcmp(argv[0], "tty") == 0) { + if (argc >= 2 && argv[1][0] >= '1' && argv[1][0] <= '4') { + tty_switch(argv[1][0] - '1'); + } else { + printk("Active TTY: tty%d (Switch with 'tty 1-4' or Alt+F1-F4)\n", tty_get_current() + 1); + } + } else if (strcmp(argv[0], "history") == 0) { + for (int i = 0; i < history_count; i++) { + int idx = (history_head - history_count + i + HISTORY_SIZE) % HISTORY_SIZE; + printk(" %2d: %s\n", i + 1, history[idx]); + } + } else if (strcmp(argv[0], "clear") == 0 || strcmp(argv[0], "cls") == 0) { + tty_clear(); + } else if (strcmp(argv[0], "reboot") == 0) { + printk(ANSI_YELLOW "Rebooting...\n" ANSI_RESET); + pit_sleep(200); + outb(0x64, 0xFE); + } else if (strcmp(argv[0], "shutdown") == 0 || strcmp(argv[0], "poweroff") == 0) { + printk(ANSI_YELLOW "System halted.\n" ANSI_RESET); + outw(0x604, 0x2000); + outw(0xB004, 0x2000); + while (1) hlt(); + } else { + return false; + } + + return true; +} + static void shell_process(const char* cmd) { while (*cmd == ' ') cmd++; if (*cmd == '\0') return; @@ -284,42 +358,8 @@ static void shell_process(const char* cmd) { return; } - // 2. Builtins - if (strcmp(argv[0], "help") == 0) { - cmd_help(); - } else if (strcmp(argv[0], "neofetch") == 0 || strcmp(argv[0], "version") == 0) { - cmd_neofetch(); - } else if (strcmp(argv[0], "calc") == 0) { - cmd_calc(cmd + 4); - } else if (strcmp(argv[0], "hexdump") == 0) { - cmd_hexdump(cmd + 7); - } else if (strcmp(argv[0], "matrix") == 0) { - cmd_matrix(); - } else if (strcmp(argv[0], "beep") == 0) { - speaker_beep(587, 100); - } else if (strcmp(argv[0], "tty") == 0) { - if (argc >= 2 && argv[1][0] >= '1' && argv[1][0] <= '4') { - tty_switch(argv[1][0] - '1'); - } else { - printk("Active TTY: tty%d (Switch with 'tty 1-4' or Alt+F1-F4)\n", tty_get_current() + 1); - } - } else if (strcmp(argv[0], "history") == 0) { - for (int i = 0; i < history_count; i++) { - int idx = (history_head - history_count + i + HISTORY_SIZE) % HISTORY_SIZE; - printk(" %2d: %s\n", i + 1, history[idx]); - } - } else if (strcmp(argv[0], "clear") == 0 || strcmp(argv[0], "cls") == 0) { - tty_clear(); - } else if (strcmp(argv[0], "reboot") == 0) { - printk(ANSI_YELLOW "Rebooting...\n" ANSI_RESET); - pit_sleep(200); - outb(0x64, 0xFE); - } else if (strcmp(argv[0], "shutdown") == 0 || strcmp(argv[0], "poweroff") == 0) { - printk(ANSI_YELLOW "System halted.\n" ANSI_RESET); - outw(0x604, 0x2000); - outw(0xB004, 0x2000); - while (1) hlt(); - } else { + // 2. Builtins (shared with the desktop terminal) + if (!shell_execute_builtin(cmd, argc, argv, true)) { printk(ANSI_RED "Unknown command: %s. Type 'help' or 'lazybox'.\n" ANSI_RESET, argv[0]); } }