diff --git a/include/bitmaps.h b/include/bitmaps.h new file mode 100644 index 0000000..257f658 --- /dev/null +++ b/include/bitmaps.h @@ -0,0 +1,7 @@ +const uint16_t qrcode_bmp[] PROGMEM = {0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x2020,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x2020,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x2020,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x2020,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x2020,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x2020,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x2020,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x2020,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x2020,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff,0xffff,0xffff,0xffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xf800,0x0,0x7e0,0x0,0x1f,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,}; +const uint16_t main_app_bmp[] PROGMEM = {0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x39c7,0x738e,0x7bef,0x7bef,0x7bef,0x7bef,0x7bef,0x7bef,0x7bef,0x7bef,0x7bef,0x7bef,0x7bef,0x7bef,0x7bef,0x7bef,0x7bef,0x7bef,0x7bef,0x7bef,0x7bef,0x7bef,0x7bef,0x7bef,0x7bef,0x7bef,0x7bef,0x7bef,0x7bef,0x7bef,0x7bef,0x7bef,0x7bef,0x7bef,0x7bef,0x7bef,0x7bef,0x7bef,0x738e,0x39c7,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x2104,0xbdd7,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xbdd7,0x2104,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x2104,0xe71c,0xffff,0xef7d,0x9cf3,0x6b6d,0x5aeb,0x5aeb,0x5aeb,0x5aeb,0x5aeb,0x5aeb,0x5aeb,0x5aeb,0x5aeb,0x5aeb,0x5aeb,0x5aeb,0x5aeb,0x5aeb,0x5aeb,0x5aeb,0x5aeb,0x5aeb,0x5aeb,0x5aeb,0x5aeb,0x5aeb,0x5aeb,0x5aeb,0x5aeb,0x5aeb,0x5aeb,0x5aeb,0x5aeb,0x5aeb,0x5aeb,0x5aeb,0x5aeb,0x5aeb,0x6b6d,0x9cf3,0xef7d,0xffff,0xe71c,0x2104,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x20,0xc638,0xffff,0xbdf7,0x2104,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x2104,0xc618,0xffff,0xc638,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x6b6d,0xffff,0xd6ba,0x841,0x0,0x21,0x21,0x21,0x20,0x20,0x20,0x20,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x20,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x20,0x20,0x0,0x20,0x20,0x0,0x841,0xd6ba,0xffff,0x632c,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xc638,0xffff,0x4a69,0x0,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x20e3,0x6ac9,0x8bac,0x93ed,0xa40d,0xac0d,0xabec,0x93ab,0x5a68,0x1061,0x0,0x0,0x0,0x0,0x0,0x20,0x0,0x528a,0xffff,0xb5b6,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x861,0xf79e,0xf7be,0x10a2,0x0,0x62,0x1acf,0x1af0,0x1a8e,0x122c,0x988,0xc4,0x41,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x840,0x72ea,0xbd10,0xee34,0xfed7,0xfef7,0xfef6,0xeed7,0x8e79,0x8679,0xe6d7,0xfed6,0xe5f4,0x7b4b,0x0,0x0,0x0,0x0,0x0,0x0,0x10a2,0xffdf,0xdedb,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x861,0xffdf,0xdefb,0x20,0x0,0x8c4,0x3dff,0x3e3f,0x3e1f,0x3dff,0x3dbf,0x359f,0x353d,0x2c58,0x1b10,0x11c9,0x83,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x6aa9,0xe593,0xfed7,0xfeb7,0xfe96,0xf655,0xfe55,0xbe36,0xd99,0x59a,0x59a,0x599,0xae36,0xfe95,0xfef7,0x72e9,0x0,0x0,0x0,0x0,0x0,0x20,0xe73c,0xdefb,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x861,0xffdf,0xdedb,0x20,0x0,0xa4,0x357e,0x35bf,0x359f,0x35bf,0x35bf,0x3dbf,0x3ddf,0x3dff,0x3e1f,0x3ddf,0x355e,0x23d5,0x11ea,0x41,0x0,0x0,0x0,0x10a2,0xbcb0,0xded2,0x5ea7,0x3e64,0x6668,0xde73,0xfe76,0xf675,0x2dd9,0x5ba,0x5ba,0x5ba,0x5ba,0x1db9,0xe655,0xfed6,0xb48f,0x0,0x0,0x0,0x0,0x0,0x20,0xe71c,0xdefb,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x861,0xffdf,0xdefb,0x20,0x0,0xc4,0x359e,0x3dbf,0x35bf,0x35bf,0x35bf,0x35bf,0x35bf,0x35bf,0x359f,0x35bf,0x3ddf,0x3e1f,0x3dff,0x351c,0x2310,0x42,0x2924,0xe5b3,0xe6d3,0x1661,0x660,0x680,0x680,0x3664,0xf674,0xee76,0x5b9,0x5ba,0x5ba,0x5ba,0x5ba,0x5ba,0xce36,0xfed6,0xa44e,0x0,0x0,0x0,0x0,0x0,0x20,0xe71c,0xdefb,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x861,0xffdf,0xdefb,0x20,0x0,0xc4,0x359e,0x3dbf,0x35bf,0x3dbf,0x3dbf,0x3dbf,0x35bf,0x3dbf,0x35bf,0x35bf,0x35bf,0x359f,0x35bf,0x3ddf,0x361f,0x555a,0xe5f3,0xfeb8,0x7e4a,0x680,0xe80,0xe80,0xe80,0x680,0xae6e,0xfe76,0x2dd9,0x5ba,0x5ba,0x5ba,0x5ba,0x15b9,0xee55,0xfed6,0x5a47,0x0,0x0,0x0,0x0,0x0,0x20,0xe71c,0xdefb,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x861,0xffdf,0xdefb,0x20,0x0,0xc4,0x357e,0x3dbf,0x35bf,0x35bf,0x35bf,0x35bf,0x3dbf,0x35bf,0x3dbf,0x35bf,0x35bf,0x35bf,0x3dbf,0x35bf,0x45be,0xde77,0xfe95,0xfe56,0x7e6a,0x680,0xe80,0x680,0xe80,0x680,0x9e6d,0xfe76,0xb636,0x5ba,0x59a,0x59a,0x5ba,0xa616,0xfed6,0xa44e,0x0,0x0,0x0,0x0,0x0,0x0,0x20,0xe71c,0xdefb,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x861,0xffdf,0xdefb,0x20,0x0,0xc4,0x35bf,0x3ddf,0x3ddf,0x3dbf,0x35bf,0x359f,0x359f,0x35bf,0x35bf,0x35bf,0x3dbf,0x3dbf,0x3dbf,0x2dbf,0xb639,0xfe74,0xf675,0xfe76,0xc670,0x680,0x680,0x680,0x680,0x1e82,0xe673,0xfe76,0xfe75,0xce56,0x7e17,0x7e17,0xc636,0xfe95,0xf655,0x18c2,0x0,0x0,0x0,0x0,0x0,0x0,0x20,0xe71c,0xdefb,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x861,0xffdf,0xdefb,0x20,0x0,0xa3,0x2cda,0x353d,0x355d,0x359f,0x3ddf,0x3e1f,0x3dff,0x3ddf,0x35bf,0x359f,0x35bf,0x3dbf,0x2dbf,0x65dd,0xfe75,0xfe75,0xfe76,0xfe76,0xfe76,0xa66e,0x2e83,0x1681,0x3e85,0xc671,0xfe76,0xf675,0xfe75,0xfe75,0xfe95,0xfe95,0xfe75,0xf675,0xfe75,0x93cc,0x20c2,0x0,0x0,0x0,0x0,0x0,0x20,0xe71c,0xdefb,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x861,0xffdf,0xdefb,0x20,0x0,0x0,0x20,0x21,0x41,0x8e5,0x11ca,0x1aaf,0x23f6,0x353d,0x3ddf,0x3e1f,0x3ddf,0x3d9f,0x359f,0xbe38,0xfe96,0xf674,0xf650,0xfe73,0xfe76,0xfe76,0xf675,0xe674,0xfe75,0xfe76,0xfe75,0xfe75,0xfe75,0xf675,0xf675,0xf675,0xf675,0xfe75,0xfe75,0xff17,0xfeb6,0xb4af,0x41a5,0x0,0x0,0x0,0x20,0xe71c,0xdefb,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x861,0xffdf,0xdefb,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x42,0x11a9,0x2393,0x353d,0x35ff,0x4dff,0xee57,0xfe4f,0xf602,0xf600,0xf601,0xf64c,0xf676,0xfe75,0xfe76,0xfe75,0xf675,0xfe75,0xfe75,0xfe75,0xfe75,0xfe75,0xfe75,0xfe75,0xfe75,0xfe96,0xac4e,0x730a,0x9bed,0xf634,0x836b,0x0,0x0,0x20,0xe71c,0xdefb,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x861,0xffdf,0xdefb,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x62,0xa4d,0x6d39,0xfe94,0xf602,0xf600,0xf600,0xf600,0xf600,0xf651,0xfe76,0xfe75,0xfe75,0xfe75,0xfe75,0xfe75,0xfe75,0xfe75,0xfe75,0xfe75,0xf675,0xfeb6,0x8bac,0x0,0x0,0x0,0x41c5,0xfeb6,0x41c5,0x0,0x20,0xe71c,0xdefb,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x861,0xffdf,0xdefb,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x72ea,0xfed2,0xede0,0xf600,0xf600,0xf601,0xf600,0xf62b,0xfe77,0xfe75,0xfe75,0xfe75,0xfe75,0xfe75,0xfe75,0xfe75,0xfe75,0xfe75,0xfe95,0xf655,0x2103,0x0,0x20,0x0,0x0,0xcd51,0x836b,0x0,0x840,0xe71c,0xdefb,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x861,0xffdf,0xdefb,0x20,0x0,0x0,0x21,0x21,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x20,0x0,0x7b2b,0xfef4,0xede0,0xf600,0xf601,0xf600,0xf600,0xf64e,0xfe76,0xfe75,0xfe75,0xfe75,0xfe75,0xfe75,0xfe75,0xfe75,0xfe75,0xfe55,0xfe75,0xf655,0x20e3,0x0,0x20,0x0,0x0,0xc510,0x62a8,0x0,0x820,0xe71c,0xdefb,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x861,0xffdf,0xdefb,0x20,0x0,0xa3,0x351c,0x351c,0x2c99,0x23d5,0x1af0,0x11a9,0x62,0x0,0x0,0x0,0x20,0x0,0x72e9,0xfef7,0xf62b,0xf600,0xf600,0xf600,0xf628,0xfe96,0xfe96,0xfe96,0xfe75,0xfe75,0xfe75,0xfe75,0xfe75,0xfed7,0xfeb6,0xfed7,0xfe96,0xfeb6,0x8b8b,0x0,0x0,0x0,0x41c6,0xe5f4,0x20c2,0x0,0x20,0xe71c,0xdefb,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x861,0xffdf,0xdefb,0x20,0x0,0xc4,0x35bf,0x3dff,0x3dff,0x3e1f,0x3e1f,0x3ddf,0x355d,0x23d5,0x122b,0x62,0x0,0x0,0x5227,0xfeb6,0xf676,0xf650,0xf62b,0xf64f,0xfe96,0xfe13,0xf5af,0xfe12,0xfe96,0xfe75,0xfe75,0xfe95,0xfe75,0xf46d,0xf308,0xf38a,0xfdd3,0xfe96,0xfe96,0xac6e,0x5a68,0x834b,0xfe95,0x93ed,0x0,0x0,0x20,0xe71c,0xdefb,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x861,0xffdf,0xdefb,0x20,0x0,0xc4,0x357e,0x3dbf,0x359f,0x359f,0x359f,0x35bf,0x3ddf,0x3e1f,0x3e1f,0x351c,0x1a8e,0x0,0x1040,0xee14,0xfe95,0xfe76,0xfe77,0xfe97,0xf54d,0xf3a0,0xf3a0,0xf3a0,0xf52b,0xfe96,0xfe75,0xfeb6,0xf38a,0xf080,0xf0c0,0xf080,0xf1c3,0xfe13,0xfe96,0xfed6,0xfeb6,0xff37,0xd572,0x820,0x0,0x0,0x20,0xe71c,0xdefb,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x861,0xffdf,0xdefb,0x20,0x0,0xc4,0x359e,0x3dbf,0x35bf,0x3dbf,0x35bf,0x35bf,0x35bf,0x359f,0x359f,0x3ddf,0x3e1f,0x34fb,0x9ca,0xa40d,0xfed6,0xf655,0xfe95,0xf612,0xf3a0,0xf380,0xf3a0,0xf3a0,0xf380,0xf5d0,0xfeb6,0xfe14,0xf141,0xf100,0xf120,0xf120,0xf0c0,0xf4ae,0xfed6,0xf634,0xfe96,0xee14,0x2923,0x0,0x0,0x0,0x20,0xe71c,0xdefb,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x861,0xffdf,0xdefb,0x20,0x0,0xc4,0x359e,0x3dbf,0x35bf,0x3dbf,0x35bf,0x35bf,0x35bf,0x35bf,0x35bf,0x35bf,0x359f,0x3dff,0x35df,0x4cb8,0xee14,0xfe75,0xf696,0xf58f,0xf380,0xf3a0,0xf3a0,0xf3a0,0xf380,0xf56d,0xfeb7,0xfe13,0xf141,0xf100,0xf120,0xf120,0xf0c0,0xf48e,0xf6b6,0xfeb6,0xee34,0x41a5,0x0,0x0,0x0,0x0,0x20,0xe71c,0xdefb,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x861,0xffdf,0xdefb,0x20,0x0,0xc4,0x357e,0x35bf,0x359f,0x359f,0x35bf,0x35bf,0x3dbf,0x35bf,0x35bf,0x3dbf,0x3dbf,0x35bf,0x3dbf,0x2ddf,0x7ddb,0xfe75,0xfe96,0xf612,0xf3a0,0xf380,0xf3a0,0xf3a0,0xf380,0xf5d0,0xfe96,0xfeb6,0xf36a,0xf080,0xf0c0,0xf080,0xf1a3,0xf5f3,0xfef7,0xd592,0x3144,0x0,0x0,0x0,0x0,0x0,0x20,0xe71c,0xdefb,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x861,0xffdf,0xdefb,0x20,0x0,0xc4,0x35bf,0x3e1f,0x3e1f,0x3e1f,0x3ddf,0x35bf,0x359f,0x35bf,0x3dbf,0x35bf,0x35bf,0x3dbf,0x35bf,0x3dbf,0x2dbf,0x85fb,0xf675,0xfeb6,0xf56d,0xeba0,0xf380,0xf3a0,0xf50b,0xfe96,0xfe75,0xfe75,0xf655,0xf42d,0xf2c7,0xf369,0xfdd2,0xfeb6,0x9c0d,0x1061,0x0,0x0,0x0,0x0,0x0,0x0,0x20,0xe71c,0xdefb,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x861,0xffdf,0xdefb,0x20,0x0,0x21,0x11ca,0x124c,0x1af0,0x23d5,0x351c,0x3ddf,0x3e1f,0x35bf,0x359f,0x35bf,0x3dbf,0x3dbf,0x35bf,0x3dbf,0x3dbf,0x2dbf,0x5ddd,0xc5d5,0xfe75,0xfe94,0xfdd0,0xfe12,0xfe96,0xfe95,0xfe75,0xfe75,0xfe75,0xfed6,0xfeb5,0xf6d7,0xbe58,0x663f,0x126d,0x0,0x20,0x0,0x0,0x0,0x0,0x0,0x20,0xe71c,0xdefb,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x861,0xffdf,0xdefb,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x20,0x988,0x23d5,0x3dbf,0x3e1f,0x35bf,0x35bf,0x3dbf,0x3dbf,0x35bf,0x3dbf,0x3dbf,0x35bf,0x357e,0x4aec,0x93ac,0xe5f4,0xee55,0xf654,0xf655,0xf675,0xf696,0xee76,0xce37,0x8dfb,0x5ddd,0x359f,0x35df,0x351c,0x41,0x0,0x0,0x0,0x0,0x0,0x0,0x20,0xe71c,0xdefb,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x861,0xffdf,0xdefb,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x926,0x23f5,0x3ddf,0x3ddf,0x359f,0x3dbf,0x35bf,0x35bf,0x35bf,0x3dbf,0x3dff,0x24db,0x21,0x820,0x18a2,0x20e3,0x20e3,0x2104,0x44fa,0x4dff,0x35bf,0x2dbf,0x35bf,0x3dbf,0x3d9f,0x3e1f,0x1a6d,0x0,0x0,0x0,0x0,0x0,0x0,0x20,0xe71c,0xdefb,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x861,0xffdf,0xdefb,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x11a9,0x353d,0x3dff,0x359f,0x3dbf,0x35bf,0x3dbf,0x3dbf,0x359f,0x3e1f,0x2c16,0x0,0x0,0x0,0x0,0x0,0x9eb,0x35ff,0x35bf,0x3dbf,0x3dbf,0x3dbf,0x35bf,0x3dff,0x2cba,0x0,0x0,0x0,0x0,0x0,0x0,0x20,0xe71c,0xdefb,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x861,0xffdf,0xdefb,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xa3,0x2cda,0x3dff,0x359f,0x3dbf,0x35bf,0x35bf,0x3dbf,0x359f,0x3e1f,0x124c,0x0,0x20,0x0,0x0,0x0,0x2cb9,0x3dff,0x35bf,0x35bf,0x3dbf,0x35bf,0x35bf,0x3ddf,0x967,0x0,0x0,0x0,0x0,0x0,0x20,0xe71c,0xdefb,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x861,0xffdf,0xdefb,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x62,0x2cda,0x3dff,0x359f,0x3dbf,0x35bf,0x3dbf,0x35bf,0x3ddf,0x353d,0x62,0x0,0x0,0x0,0x0,0x122c,0x3dff,0x35bf,0x35bf,0x35bf,0x35bf,0x359f,0x3e1f,0x2352,0x0,0x0,0x0,0x0,0x0,0x20,0xe71c,0xdefb,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x861,0xffdf,0xdefb,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xc4,0x355d,0x3ddf,0x35bf,0x3dbf,0x35bf,0x3dbf,0x359f,0x3e1f,0x1af0,0x0,0x0,0x0,0x0,0x41,0x351c,0x3ddf,0x35bf,0x3dbf,0x35bf,0x35bf,0x3ddf,0x351c,0x41,0x0,0x0,0x0,0x0,0x20,0xe71c,0xdefb,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x861,0xffdf,0xdefb,0x20,0x0,0x0,0x0,0x0,0x20,0x988,0x1a8e,0x122c,0x906,0x0,0x0,0x0,0x0,0x0,0x0,0x11ea,0x3dff,0x35bf,0x35bf,0x35bf,0x35bf,0x35bf,0x3ddf,0x355d,0x82,0x0,0x0,0x0,0x0,0x1b31,0x3e1f,0x359f,0x35bf,0x35bf,0x35bf,0x3dbf,0x3dbf,0x947,0x0,0x0,0x0,0x0,0x20,0xe71c,0xdefb,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x861,0xffdf,0xdefb,0x20,0x0,0x0,0x0,0x926,0x2cba,0x3ddf,0x3e1f,0x3dff,0x35bf,0x2373,0x21,0x0,0x0,0x0,0x0,0x0,0x23b4,0x3e1f,0x359f,0x3dbf,0x35bf,0x35bf,0x359f,0x3e1f,0x1a6d,0x0,0x0,0x0,0x0,0x926,0x3dbf,0x3dbf,0x35bf,0x35bf,0x35bf,0x359f,0x3e1f,0x1aae,0x0,0x0,0x0,0x0,0x20,0xe71c,0xdefb,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x861,0xffdf,0xdefb,0x20,0x0,0x0,0x8e5,0x359e,0x3dff,0x35bf,0x359f,0x359f,0x35bf,0x3e3f,0x23f6,0x0,0x0,0x0,0x0,0x0,0xa3,0x357e,0x3ddf,0x35bf,0x3dbf,0x3dbf,0x35bf,0x3dff,0x2c78,0x0,0x0,0x0,0x0,0x20,0x34fb,0x3ddf,0x35bf,0x35bf,0x3dbf,0x359f,0x3e1f,0x23f6,0x0,0x0,0x0,0x0,0x20,0xe71c,0xdefb,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x861,0xffdf,0xdefb,0x20,0x0,0x0,0x2416,0x3e1f,0x359f,0x35bf,0x35bf,0x35bf,0x35bf,0x359f,0x3e1f,0x120b,0x0,0x0,0x0,0x0,0x0,0x1b31,0x3e1f,0x359f,0x35bf,0x35bf,0x35bf,0x3dbf,0x359f,0x8e5,0x0,0x0,0x0,0x0,0x2394,0x3e1f,0x359f,0x3dbf,0x35bf,0x35bf,0x3ddf,0x351c,0x21,0x0,0x0,0x0,0x20,0xe71c,0xdefb,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x861,0xffdf,0xdefb,0x20,0x0,0x42,0x355d,0x3ddf,0x35bf,0x35bf,0x35bf,0x35bf,0x3dbf,0x359f,0x3e1f,0x2393,0x0,0x0,0x0,0x0,0x0,0x905,0x35bf,0x3dbf,0x35bf,0x35bf,0x35bf,0x359f,0x3dff,0x124c,0x0,0x0,0x0,0x0,0x126d,0x3e1f,0x359f,0x35bf,0x3dbf,0x35bf,0x3dbf,0x359e,0xa3,0x0,0x0,0x0,0x20,0xe71c,0xdefb,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x861,0xffdf,0xdefb,0x20,0x0,0xa4,0x357e,0x3dbf,0x35bf,0x35bf,0x3dbf,0x3dbf,0x35bf,0x35bf,0x3ddf,0x2c99,0x0,0x0,0x0,0x0,0x0,0x0,0x2c79,0x3dff,0x35bf,0x3dbf,0x3dbf,0x359f,0x3e1f,0x2393,0x0,0x0,0x0,0x0,0x988,0x3dbf,0x35bf,0x35bf,0x3dbf,0x35bf,0x35bf,0x3dbf,0x988,0x0,0x0,0x0,0x20,0xe71c,0xdefb,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x861,0xffdf,0xdefb,0x20,0x0,0x83,0x357e,0x3dbf,0x35bf,0x35bf,0x3dbf,0x35bf,0x35bf,0x359f,0x3dff,0x2c16,0x0,0x0,0x0,0x0,0x0,0x0,0x1b11,0x3e1f,0x359f,0x35bf,0x35bf,0x35bf,0x3dff,0x2c78,0x0,0x0,0x0,0x0,0xa3,0x359e,0x3dbf,0x35bf,0x3dbf,0x35bf,0x359f,0x3dff,0x124c,0x0,0x0,0x0,0x20,0xe71c,0xdefb,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x861,0xffdf,0xdedb,0x20,0x0,0x0,0x2cba,0x3dff,0x359f,0x35bf,0x35bf,0x35bf,0x35bf,0x359f,0x3e1f,0x1aaf,0x0,0x0,0x0,0x0,0x0,0x0,0x11eb,0x3dff,0x35bf,0x35bf,0x35bf,0x35bf,0x3ddf,0x353d,0x21,0x0,0x0,0x0,0x21,0x351c,0x3ddf,0x35bf,0x35bf,0x35bf,0x359f,0x3e1f,0x1acf,0x0,0x20,0x0,0x20,0xdefb,0xdefb,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x861,0xffdf,0xe73c,0x841,0x0,0x0,0x988,0x3dff,0x3ddf,0x35bf,0x35bf,0x35bf,0x359f,0x3e1f,0x2cda,0x21,0x0,0x0,0x0,0x0,0x0,0x0,0x926,0x359f,0x3dbf,0x35bf,0x35bf,0x35bf,0x3dbf,0x359e,0xa3,0x0,0x0,0x0,0x0,0x2c99,0x3ddf,0x359f,0x35bf,0x35bf,0x359f,0x3e3f,0x1af0,0x0,0x20,0x0,0x20,0xef5d,0xdefb,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x861,0xf79e,0xffff,0x18e3,0x0,0x0,0x0,0x1aaf,0x35bf,0x3ddf,0x3ddf,0x3ddf,0x3ddf,0x351c,0x906,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x82,0x359f,0x3dff,0x3ddf,0x3ddf,0x3ddf,0x3ddf,0x3dbf,0x926,0x0,0x0,0x0,0x0,0x2c58,0x3e1f,0x3ddf,0x3ddf,0x3ddf,0x3dbf,0x3e5f,0x1b10,0x0,0x20,0x0,0x2104,0xffff,0xd6ba,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xbdd7,0xffff,0x5aeb,0x0,0x20,0x0,0x0,0x8c4,0x11c9,0x11a9,0x11c9,0x989,0x41,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x988,0x11c9,0x11a9,0x11a9,0x11a9,0x11a9,0x11a9,0x62,0x0,0x0,0x0,0x0,0x926,0x11ca,0x11a9,0x11a9,0x11a9,0x11a9,0x11ca,0x8e5,0x0,0x20,0x0,0x630c,0xffff,0xb596,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x528a,0xffff,0xef5d,0x2945,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x2945,0xef5d,0xffff,0x5aeb,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xb5b6,0xffff,0xef5d,0x5acb,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x5acb,0xef5d,0xffff,0xb596,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1082,0xc638,0xffff,0xffff,0xdefb,0xad55,0x9cd3,0x9cd3,0x9cd3,0x9cd3,0x9cd3,0x9cd3,0x9cd3,0x9cd3,0x9cd3,0x9cd3,0x9cd3,0x9cd3,0x9cd3,0x9cd3,0x9cd3,0x9cd3,0x9cd3,0x9cd3,0x9cd3,0x9cd3,0x9cd3,0x9cd3,0x9cd3,0x9cd3,0x9cd3,0x9cd3,0x9cd3,0x9cd3,0x9cd3,0x9cd3,0x9cd3,0x9cd3,0x9cd3,0x9cd3,0xad75,0xdefb,0xffff,0xffff,0xc618,0x861,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x20,0x7bef,0xe73c,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xe73c,0x7bef,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x841,0x3186,0x4228,0x4a49,0x4a49,0x4a49,0x4a49,0x4a49,0x4a49,0x4a49,0x4a49,0x4a49,0x4a49,0x4a49,0x4a49,0x4a49,0x4a49,0x4a49,0x4a49,0x4a49,0x4a49,0x4a49,0x4a49,0x4a49,0x4a49,0x4a49,0x4a49,0x4a49,0x4a49,0x4a49,0x4a49,0x4a49,0x4a49,0x4a49,0x4a49,0x4a49,0x4a49,0x4228,0x3186,0x841,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x10a2,0x841,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x10a2,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x3186,0xad75,0xce59,0x9cd3,0x18c3,0x0,0xe71c,0x5acb,0x0,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x18e3,0xef5d,0x31a6,0x0,0x0,0x0,0x841,0x8430,0xc638,0xb5b6,0x4a49,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x2945,0x18e3,0x0,0x0,0x0,0x2965,0xffff,0xb5b6,0x6b4d,0xdefb,0xbdd7,0x0,0xef7d,0x630c,0x0,0x0,0x10a2,0x2104,0x0,0x0,0x20,0x1082,0x0,0x0,0x1082,0x20,0x0,0x20,0x18e3,0x2104,0xf7be,0x39c7,0x0,0x0,0x0,0xbdf7,0xef7d,0x738e,0xa514,0xffdf,0x2945,0x0,0x18c3,0x2945,0x0,0x0,0x20,0x861,0x0,0x2124,0x0,0x0,0x10a2,0x0,0x0,0x0,0x10a2,0x0,0x0,0x2124,0x18e3,0x0,0x0,0xa514,0xd6ba,0xe73c,0x630c,0x0,0x0,0x9cd3,0xdefb,0x0,0x0,0x1082,0x2945,0x0,0xef5d,0x630c,0x0,0x7bef,0xf79e,0xf79e,0xbdd7,0x0,0x39e7,0xef7d,0x861,0x1082,0xef7d,0x31a6,0x1082,0xdedb,0xf79e,0xc638,0xf7be,0x31a6,0x0,0x0,0x39c7,0xffff,0x31a6,0x0,0x0,0x31a6,0x0,0x8410,0xe73c,0xdefb,0xbdd7,0x0,0x4a49,0xe73c,0xb596,0xffdf,0xc618,0x20,0xd69a,0x8410,0x0,0x52aa,0xe71c,0x2124,0xbdf7,0xdedb,0xe73c,0x6b4d,0x861,0xffff,0x73ae,0x2965,0x10a2,0x0,0x0,0xbdf7,0xad55,0x0,0x841,0x0,0x0,0x20,0xef7d,0x52aa,0x18c3,0xffff,0x52aa,0x1082,0xffdf,0x738e,0x3186,0xffff,0x1082,0x10a2,0xffff,0x2965,0x8430,0xf79e,0x861,0x6b6d,0xffff,0x3186,0x0,0x0,0x5aeb,0xffdf,0x861,0x0,0x20,0x0,0x0,0x4a69,0x31a6,0x630c,0xffff,0x18e3,0x4228,0xffff,0x4a49,0x2965,0xffff,0x2945,0x7bcf,0xe71c,0x0,0xb596,0xad75,0x0,0x630c,0x18e3,0xbdf7,0xce59,0x0,0x5aeb,0xdedb,0xdefb,0x52aa,0x0,0x0,0xb596,0xc618,0x0,0x0,0x20,0x2124,0x20,0xef7d,0x4a49,0x4208,0xffdf,0x0,0x0,0xb596,0xa514,0x31a6,0xf7be,0x20,0x861,0xf7be,0x3186,0xad55,0xad55,0x0,0x10a2,0xf7be,0x31a6,0x0,0x0,0x4a69,0xffff,0x18c3,0x0,0x0,0x2124,0x20,0x5aeb,0xbdd7,0xa514,0xf79e,0x2104,0x4228,0xf7be,0x0,0x841,0xf7be,0x39e7,0x18c3,0xf7be,0x4228,0xe73c,0x4a49,0x0,0x9cd3,0xad55,0xc638,0xc618,0x1082,0x5aeb,0x861,0xad75,0xe71c,0x0,0x0,0x52aa,0xffff,0x5aeb,0x861,0x9cd3,0xdedb,0x20,0xf79e,0x6b4d,0x18c3,0xffff,0x5aeb,0x10a2,0xffdf,0x738e,0x2945,0xffff,0x2965,0x5acb,0xffff,0x2945,0x8430,0xf79e,0x1082,0x738e,0xffff,0x31a6,0x0,0x0,0x841,0xef7d,0xad75,0x10a2,0x4a69,0xf7be,0x4a69,0xffdf,0x6b6d,0x3186,0xffff,0x2965,0x4a49,0xffdf,0x841,0x1082,0xffdf,0x4a49,0x0,0xbdd7,0xf7be,0xd69a,0x0,0x630c,0xffff,0x841,0x9cf3,0xdedb,0x73ae,0xbdd7,0xe73c,0xe71c,0x632c,0x0,0x0,0x0,0x7bef,0xf79e,0xef7d,0xe73c,0x4a49,0x0,0xa514,0xf79e,0x861,0x738e,0xf79e,0xf79e,0xb5b6,0x841,0x20,0xc618,0xf7be,0xad75,0xe73c,0x31a6,0x1082,0xd6ba,0xf79e,0xb5b6,0xe73c,0x31a6,0x0,0x20,0x0,0x39c7,0xdedb,0xef7d,0xf7be,0x8c71,0x0,0x9cf3,0xef5d,0xa514,0xd69a,0xa534,0x4228,0xe73c,0x20,0x861,0xef5d,0x4228,0x0,0x5acb,0xffff,0x7bef,0x0,0x2945,0xdedb,0xd69a,0x9cf3,0xef5d,0x20,0x0,0x2104,0x10a2,0x0,0x0,0x0,0x0,0x0,0x861,0x2104,0x0,0x0,0x0,0x0,0x18e3,0x20,0x0,0x1082,0x18e3,0x0,0x0,0x0,0x0,0x18e3,0x0,0x841,0x20,0x0,0x20,0x18e3,0x0,0x841,0x0,0x0,0x0,0x0,0x0,0x0,0x18e3,0x1082,0x0,0x0,0x0,0x2104,0x20,0x0,0x1082,0x0,0x861,0x0,0x0,0x861,0x0,0x0,0x0,0x841,0x0,0x0,0x0,0x861,0x2104,0x0,0x861,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x2945,0x2945,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x18e3,0xf7be,0xf7be,0x18e3,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x73ae,0xe71c,0xef5d,0x738e,0x0,0x861,0x7bcf,0x52aa,0xa514,0x7bcf,0x0,0x841,0x7bcf,0x52aa,0xa514,0x7bcf,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xd69a,0x6b6d,0x7bcf,0xd69a,0x0,0x10a2,0xffff,0xd6ba,0x8c71,0xffff,0x7bef,0x20,0xffff,0xd6ba,0x8c71,0xffff,0x8410,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x2124,0xffff,0x5acb,0x632c,0xffff,0x2104,0x841,0xffdf,0x528a,0x0,0x94b2,0xd69a,0x841,0xf7be,0x528a,0x0,0x94b2,0xd6ba,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x20,0x0,0x738e,0xffff,0xe71c,0xe71c,0xffff,0x6b4d,0x0,0xffff,0x52aa,0x0,0x9cd3,0xd69a,0x841,0xffdf,0x52aa,0x0,0x94b2,0xd6ba,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xef5d,0x9cd3,0x0,0x0,0xa534,0xe73c,0x1082,0xffdf,0xd6ba,0x94b2,0xffff,0x73ae,0x0,0xffff,0xd6ba,0x94b2,0xffff,0x7bcf,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x861,0x8410,0x2124,0x0,0x0,0x2945,0x7bef,0x2104,0xe73c,0x7bef,0x9cf3,0x738e,0x0,0x1082,0xef5d,0x7bef,0x9cf3,0x738e,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1082,0xffff,0x4208,0x0,0x0,0x0,0x10a2,0xffff,0x4208,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x20,0x0,0x0,0x0,0x0,0x0,0x841,0x8410,0x2124,0x0,0x20,0x0,0x841,0x8410,0x2124,0x0,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xf800,0x0,0x7e0,0x0,0x1f,0x0,}; +const uint16_t settings_app_bmp[] PROGMEM = {0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x39c7,0x738e,0x7bef,0x7bef,0x7bef,0x7bef,0x7bef,0x7bef,0x7bef,0x7bef,0x7bef,0x7bef,0x7bef,0x7bef,0x7bef,0x7bef,0x7bef,0x7bef,0x7bef,0x7bef,0x7bef,0x7bef,0x7bef,0x7bef,0x7bef,0x7bef,0x7bef,0x7bef,0x7bef,0x7bef,0x7bef,0x7bef,0x7bef,0x7bef,0x7bef,0x7bef,0x7bef,0x7bef,0x738e,0x39c7,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x2104,0xbdd7,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xbdd7,0x2104,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x2104,0xe71c,0xffff,0xef7d,0x9cf3,0x6b6d,0x5aeb,0x5aeb,0x5aeb,0x5aeb,0x5aeb,0x5aeb,0x5aeb,0x5aeb,0x5aeb,0x5aeb,0x5aeb,0x5aeb,0x5aeb,0x5aeb,0x5aeb,0x5aeb,0x5aeb,0x5aeb,0x5aeb,0x5aeb,0x5aeb,0x5aeb,0x5aeb,0x5aeb,0x5aeb,0x5aeb,0x5aeb,0x5aeb,0x5aeb,0x5aeb,0x5aeb,0x5aeb,0x5aeb,0x5aeb,0x6b6d,0x9cf3,0xef7d,0xffff,0xe71c,0x2104,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x20,0xc638,0xffff,0xbdf7,0x2104,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x2104,0xc618,0xffff,0xc638,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x6b6d,0xffff,0xd6ba,0x841,0x0,0x20,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x20,0x20,0x0,0x841,0xd6ba,0xffff,0x632c,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xc638,0xffff,0x4a69,0x0,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x20,0x0,0x528a,0xffff,0xb5b6,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x861,0xf79e,0xf7be,0x10a2,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x840,0x32ea,0x26c,0x26b,0x26b,0x26b,0x26b,0x26b,0x26b,0x28b,0x20c,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x10a2,0xffdf,0xdedb,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x861,0xffdf,0xdefb,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x3162,0x5d51,0x415,0x454,0x434,0x434,0x434,0x434,0x434,0x454,0xbb5,0x64,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x20,0xe73c,0xdefb,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x861,0xffdf,0xdedb,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x4a64,0x6530,0x3b3,0x3f2,0x3f3,0x413,0x413,0x3f3,0x3f2,0x412,0xb95,0x8c8,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x20,0xe71c,0xdefb,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x861,0xffdf,0xdefb,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x6b05,0x6d91,0x3b3,0x413,0x3d2,0x3d2,0x3d2,0x3d2,0x3f3,0x412,0xb96,0x10eb,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x20,0xe71c,0xdefb,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x861,0xffdf,0xdefb,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x20,0x0,0x8385,0x75b1,0x3b3,0x412,0xe4,0x0,0x0,0xe4,0x3f3,0x412,0x1396,0x18cc,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x20,0xe71c,0xdefb,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x861,0xffdf,0xdefb,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x5ae5,0xa4c8,0x3183,0x0,0x0,0x0,0x0,0x0,0xa487,0x7590,0x3d3,0x3d2,0x41,0x0,0x0,0x21,0x3d2,0x432,0x1376,0x1930,0x0,0x0,0x0,0x0,0x0,0x886,0x2172,0x10ea,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x20,0xe71c,0xdefb,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x861,0xffdf,0xdefb,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x8a1,0xe66b,0xff8b,0xff0b,0xbd69,0x5aa5,0x41,0x41,0x7ba7,0xfeca,0x6510,0x3f4,0x370,0x0,0x0,0x0,0x0,0x370,0x433,0xb74,0x31b8,0x192e,0x21,0x21,0x10ca,0x2174,0x31ba,0x39bb,0x29b7,0x42,0x0,0x0,0x0,0x0,0x0,0x0,0x20,0xe71c,0xdefb,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x861,0xffdf,0xdefb,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x8c27,0xff6b,0xf6aa,0xfeca,0xff2b,0xff6b,0xd60a,0xcdea,0xff6b,0xff0a,0x5cef,0x414,0x30e,0x0,0x0,0x0,0x0,0x30e,0x453,0xb54,0x3199,0x39bb,0x2996,0x2996,0x39bb,0x31ba,0x3199,0x3198,0x39bb,0x192f,0x0,0x0,0x0,0x0,0x0,0x0,0x20,0xe71c,0xdefb,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x861,0xffdf,0xdefb,0x20,0x0,0x0,0x0,0x0,0x0,0x2983,0xff0b,0xfeeb,0xfeeb,0xff0b,0xfeeb,0xfeaa,0xff0b,0xff2b,0xf6aa,0xff0a,0x6571,0x3f4,0x229,0x0,0x0,0x0,0x0,0x20a,0x453,0xb95,0x3199,0x3198,0x319a,0x319a,0x3198,0x3199,0x319a,0x3199,0x3199,0x31b9,0x885,0x0,0x0,0x0,0x0,0x0,0x20,0xe71c,0xdefb,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x861,0xffdf,0xdefb,0x20,0x0,0x0,0x0,0x0,0x0,0xb529,0xff4b,0xfeca,0xff0b,0xcdea,0xf6ab,0xff6b,0xff0b,0xfeca,0xff2b,0xf6cb,0x3b09,0x83,0x0,0x0,0x0,0x0,0x0,0x0,0xc3,0x1ec,0x31b9,0x319a,0x3198,0x3199,0x39bb,0x31b9,0x29b6,0x3199,0x3199,0x39ba,0x2173,0x0,0x0,0x0,0x0,0x0,0x20,0xe71c,0xdefb,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x861,0xffdf,0xdefb,0x20,0x0,0x0,0x0,0x0,0x4a64,0xff4c,0xfeca,0xff2b,0xd60a,0x41,0x2122,0x83e7,0xe64a,0xff6c,0xcdca,0x2122,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x85,0x2996,0x39bb,0x2997,0x192f,0x64,0x41,0x2996,0x319a,0x3199,0x31bb,0x8c9,0x0,0x0,0x0,0x0,0x20,0xe71c,0xdefb,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x861,0xffdf,0xdefb,0x20,0x0,0x0,0x0,0x41,0xd60a,0xff2b,0xfeca,0xff2b,0x5285,0x0,0x0,0x0,0x881,0x5ac5,0x10a1,0x0,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x43,0x10ea,0x42,0x0,0x0,0x0,0x10ca,0x31ba,0x3199,0x319a,0x2996,0x21,0x0,0x0,0x0,0x20,0xe71c,0xdefb,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x861,0xffdf,0xdefb,0x20,0x0,0x0,0x0,0x7ba7,0xff4b,0xfeca,0xff2b,0xcdea,0x0,0x0,0x20,0x0,0x0,0x0,0x0,0x20,0x0,0x0,0x146,0x28c,0x32f,0x32f,0x2ac,0x167,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x29b6,0x319a,0x3199,0x31bb,0x190d,0x0,0x0,0x0,0x20,0xe71c,0xdefb,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x861,0xffdf,0xdefb,0x20,0x0,0x0,0x40,0xde4b,0xff4b,0xfeca,0xfeeb,0xfeeb,0x9468,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x62,0x30e,0x434,0x434,0x433,0x433,0x434,0x434,0x350,0xc3,0x0,0x0,0x0,0x0,0x0,0x0,0x21,0x1950,0x31b9,0x3199,0x3199,0x39bb,0x29b7,0x21,0x0,0x0,0x20,0xe71c,0xdefb,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x861,0xffdf,0xdefb,0x20,0x0,0x0,0x0,0x2963,0xcdca,0xff6b,0xfeca,0xfeeb,0xff6b,0xcdca,0x2142,0x0,0x0,0x0,0x0,0x18a0,0x3c2f,0x434,0x3f2,0x3f2,0x3f3,0x3f3,0x3f2,0x3f2,0x453,0xb73,0x64,0x0,0x0,0x0,0x0,0x885,0x2996,0x39bb,0x3199,0x3199,0x39bb,0x2995,0x885,0x0,0x0,0x0,0x20,0xe71c,0xdefb,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x861,0xffdf,0xdefb,0x20,0x0,0x0,0x0,0x0,0x40,0x9468,0xff4c,0xff0b,0xfeca,0xff2b,0xfeeb,0x39e3,0x0,0x20,0x0,0x9427,0x75b1,0x3b3,0x413,0x413,0x3f3,0x3f3,0x3f3,0x3f3,0x412,0x1396,0x2173,0x0,0x0,0x0,0x8a7,0x31da,0x319a,0x3199,0x3199,0x31bb,0x1950,0x20,0x0,0x0,0x0,0x0,0x20,0xe71c,0xdefb,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x861,0xffdf,0xdefb,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x5ae5,0xf6ab,0xfeeb,0xfeca,0xff4b,0x5285,0x0,0x0,0x861,0xf68a,0x6530,0x3d3,0x413,0x3f3,0x413,0x413,0x3f3,0x3f3,0x412,0xb74,0x31b9,0x885,0x0,0x0,0x10ea,0x31db,0x3199,0x3199,0x31b8,0x10eb,0x0,0x0,0x0,0x0,0x0,0x0,0x20,0xe71c,0xdefb,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x861,0xffdf,0xdefb,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x83c6,0xff6b,0xfeca,0xfecb,0x2163,0x0,0x0,0x2983,0xff0a,0x6510,0x3d3,0x413,0x413,0x413,0x413,0x413,0x3f3,0x412,0xb74,0x31da,0x10ea,0x0,0x0,0x885,0x31b9,0x3199,0x39bb,0x18ed,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x20,0xe71c,0xdefb,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x861,0xffdf,0xdefb,0x20,0x0,0x0,0x0,0x0,0x0,0x20,0x0,0x7b85,0xff6b,0xfeca,0xf6cb,0x1902,0x0,0x0,0x3a04,0xff2b,0x6510,0x3d3,0x413,0x413,0x413,0x413,0x413,0x3f3,0x412,0xb74,0x31db,0x10eb,0x0,0x0,0x64,0x31b9,0x3199,0x39bb,0x18cc,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x20,0xe71c,0xdefb,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x861,0xffdf,0xdefb,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x9c47,0xff4b,0xfeca,0xfecb,0x2983,0x0,0x0,0x2142,0xff0a,0x6530,0x3d3,0x413,0x413,0x413,0x413,0x413,0x3f3,0x412,0xb74,0x31ba,0x8e9,0x0,0x0,0x8a6,0x31b9,0x3199,0x39bb,0x190f,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x20,0xe71c,0xdefb,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x861,0xffdf,0xdefb,0x20,0x0,0x0,0x0,0x0,0x0,0x20,0x9c68,0xff0b,0xfeeb,0xfeca,0xff8c,0x5ae6,0x0,0x0,0x0,0xde0a,0x6d50,0x3d3,0x413,0x3f3,0x413,0x413,0x3f3,0x3f3,0x412,0xb74,0x31b8,0x42,0x0,0x0,0x110b,0x39db,0x3198,0x3199,0x31ba,0x1950,0x0,0x0,0x0,0x0,0x0,0x0,0x20,0xe71c,0xdefb,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x861,0xffdf,0xdefb,0x20,0x0,0x0,0x0,0x0,0x2143,0xcdea,0xff6b,0xfeca,0xfeca,0xff6b,0xcdea,0x2142,0x0,0x20,0x0,0x6b25,0x6db1,0x3b3,0x413,0x413,0x3f3,0x3f3,0x413,0x3f3,0x412,0x1396,0x1950,0x0,0x0,0x0,0x865,0x2996,0x39bb,0x3199,0x3199,0x39bb,0x2995,0x64,0x0,0x0,0x0,0x0,0x20,0xe71c,0xdefb,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x861,0xffdf,0xdefb,0x20,0x0,0x0,0x0,0x5ae5,0xf6cb,0xff2b,0xfeca,0xff0b,0xff4c,0x9468,0x20,0x0,0x0,0x0,0x0,0x820,0x234c,0x434,0x413,0x3f2,0x3f3,0x3f3,0x3f2,0x3f3,0x454,0x2f0,0x1,0x0,0x0,0x0,0x0,0x21,0x1950,0x31db,0x3199,0x3199,0x31ba,0x31b9,0x10c9,0x0,0x0,0x0,0x20,0xe71c,0xdefb,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x861,0xffdf,0xdefb,0x20,0x0,0x0,0x40,0xe64b,0xff2b,0xfeca,0xfeeb,0xeeab,0x5ac5,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x22a,0x413,0x454,0x434,0x434,0x454,0x413,0x28c,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x10ea,0x31b8,0x3199,0x3199,0x399a,0x29b6,0x0,0x0,0x0,0x20,0xe71c,0xdefb,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x861,0xffdf,0xdefb,0x20,0x0,0x0,0x0,0x5285,0xff4b,0xfeca,0xff0b,0xd60a,0x0,0x0,0x20,0x0,0x0,0x0,0x0,0x20,0x0,0x0,0xc3,0x22a,0x2ad,0x2cd,0x22a,0xe4,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x20,0x29b6,0x319a,0x3199,0x31ba,0x8a8,0x0,0x0,0x0,0x20,0xe71c,0xdefb,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x861,0xffdf,0xdefb,0x20,0x0,0x0,0x0,0x0,0xbd49,0xff4b,0xfeca,0xff6b,0x7386,0x0,0x0,0x0,0x31c3,0x9c88,0x31a3,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x8a7,0x1951,0x886,0x0,0x0,0x0,0x190d,0x39bb,0x3198,0x39ba,0x2172,0x0,0x0,0x0,0x0,0x20,0xe71c,0xdefb,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x861,0xffdf,0xdefb,0x20,0x0,0x0,0x0,0x0,0x31a3,0xff0b,0xfeea,0xff0b,0xee8b,0x2163,0x5285,0xc589,0xff0b,0xff6b,0xeeab,0x52a5,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x110c,0x31ba,0x39bb,0x31ba,0x2194,0x10c9,0x885,0x31b8,0x3199,0x3199,0x31b9,0x64,0x0,0x0,0x0,0x0,0x20,0xe71c,0xdefb,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x861,0xffdf,0xdefb,0x20,0x0,0x0,0x0,0x0,0x0,0x9447,0xff6b,0xfeca,0xfeeb,0xf6cb,0xff4b,0xff2b,0xfeca,0xf6aa,0xff0b,0xff4b,0x53ec,0x126,0x41,0x0,0x0,0x0,0x0,0x41,0x166,0xa8f,0x31da,0x3199,0x3198,0x3199,0x31ba,0x31ba,0x31b9,0x3199,0x3199,0x39bb,0x192e,0x0,0x0,0x0,0x0,0x0,0x20,0xe71c,0xdefb,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x861,0xffdf,0xdefb,0x20,0x0,0x0,0x0,0x0,0x0,0x10c1,0xee8b,0xff0b,0xfeeb,0xfeeb,0xfeca,0xfeea,0xff4b,0xff4b,0xfeca,0xfeea,0x6550,0x435,0x28b,0x0,0x0,0x0,0x0,0x28c,0x474,0xb95,0x3199,0x3199,0x31bb,0x39ba,0x3199,0x3198,0x3199,0x3199,0x319a,0x29b7,0x42,0x0,0x0,0x0,0x0,0x0,0x20,0xe71c,0xdefb,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x861,0xffdf,0xdefb,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x6b26,0xff4b,0xfeca,0xff0b,0xff6b,0xfeeb,0x9c88,0x9c68,0xff4c,0xff2a,0x5cef,0x3f4,0x30e,0x0,0x0,0x0,0x0,0x32f,0x433,0xb54,0x319a,0x31da,0x1930,0x2151,0x31b9,0x39bb,0x3199,0x3198,0x31bb,0x10ea,0x0,0x0,0x0,0x0,0x0,0x0,0x20,0xe71c,0xdefb,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x861,0xffdf,0xdefb,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xcdea,0xff8c,0xde2a,0x83c7,0x2122,0x0,0x0,0x4224,0xe64a,0x6530,0x3f4,0x390,0x20,0x0,0x0,0x20,0x391,0x433,0xb75,0x2996,0x8c8,0x0,0x0,0x64,0x192f,0x2997,0x39dc,0x2194,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x20,0xe71c,0xdefb,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x861,0xffdf,0xdefb,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x39c3,0x6305,0x61,0x0,0x0,0x0,0x20,0x0,0x9426,0x7590,0x3d3,0x3d2,0x20,0x0,0x0,0x41,0x3d2,0x412,0x1396,0x190e,0x0,0x0,0x0,0x0,0x0,0x21,0x10eb,0x886,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x20,0xe71c,0xdefb,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x861,0xffdf,0xdefb,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x20,0x0,0x8365,0x7591,0x3b3,0x412,0x1a7,0x104,0x104,0x1c8,0x3f3,0x412,0x1396,0x10ec,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x20,0xe71c,0xdefb,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x861,0xffdf,0xdefb,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x62e5,0x6d71,0x3b3,0x413,0x413,0x413,0x413,0x413,0x3f3,0x412,0xb96,0x10ea,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x20,0xe71c,0xdefb,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x861,0xffdf,0xdedb,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x4224,0x5d30,0x3d3,0x3f2,0x3f3,0x3f3,0x3f3,0x3f3,0x3f3,0x412,0xb95,0x8c7,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x20,0xdefb,0xdefb,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x861,0xffdf,0xe73c,0x841,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x2921,0x5d31,0x414,0x434,0x434,0x434,0x434,0x434,0x434,0x454,0xb94,0x43,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x20,0xef5d,0xdefb,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x861,0xf79e,0xffff,0x18e3,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x820,0x19e6,0x187,0x187,0x187,0x187,0x187,0x187,0x187,0x187,0x147,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x2104,0xffff,0xd6ba,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xbdd7,0xffff,0x5aeb,0x0,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x20,0x0,0x630c,0xffff,0xb596,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x528a,0xffff,0xef5d,0x2945,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x2945,0xef5d,0xffff,0x5aeb,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xb5b6,0xffff,0xef5d,0x5acb,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x5acb,0xef5d,0xffff,0xb596,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1082,0xc638,0xffff,0xffff,0xdefb,0xad55,0x9cd3,0x9cd3,0x9cd3,0x9cd3,0x9cd3,0x9cd3,0x9cd3,0x9cd3,0x9cd3,0x9cd3,0x9cd3,0x9cd3,0x9cd3,0x9cd3,0x9cd3,0x9cd3,0x9cd3,0x9cd3,0x9cd3,0x9cd3,0x9cd3,0x9cd3,0x9cd3,0x9cd3,0x9cd3,0x9cd3,0x9cd3,0x9cd3,0x9cd3,0x9cd3,0x9cd3,0x9cd3,0x9cd3,0x9cd3,0xad75,0xdefb,0xffff,0xffff,0xc618,0x861,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x20,0x7bef,0xe73c,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xe73c,0x7bef,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x841,0x3186,0x4228,0x4a49,0x4a49,0x4a49,0x4a49,0x4a49,0x4a49,0x4a49,0x4a49,0x4a49,0x4a49,0x4a49,0x4a49,0x4a49,0x4a49,0x4a49,0x4a49,0x4a49,0x4a49,0x4a49,0x4a49,0x4a49,0x4a49,0x4a49,0x4a49,0x4a49,0x4a49,0x4a49,0x4a49,0x4a49,0x4a49,0x4a49,0x4a49,0x4a49,0x4a49,0x4228,0x3186,0x841,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1082,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x73ae,0xb596,0xb5b6,0xa514,0x39e7,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x20,0xef5d,0x6b4d,0x0,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xd69a,0xdefb,0x738e,0xb5b6,0xffff,0x52aa,0x0,0x0,0x861,0x2965,0x20,0x0,0x10a2,0x0,0x0,0x0,0x1082,0x20,0x5aeb,0x2945,0x0,0x0,0x2104,0x18c3,0x0,0x0,0x0,0x18c3,0x2945,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xce79,0x8c71,0x0,0x0,0xad55,0xdefb,0x0,0x4a49,0xdefb,0xd6ba,0xce79,0x18e3,0xce59,0x8410,0x0,0x528a,0xe71c,0x10a2,0xce59,0x5aeb,0x0,0xad75,0xf79e,0xf7be,0x8c71,0x0,0x7bef,0xdefb,0xdedb,0xad75,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xce79,0x9cd3,0x0,0x0,0x6b4d,0xf7be,0x841,0xe73c,0xa514,0x10a2,0xf79e,0x8430,0x738e,0xe71c,0x0,0xb596,0xad75,0x0,0xf79e,0x5acb,0x52aa,0xffff,0x2104,0x39e7,0x5aeb,0x2124,0xffff,0x630c,0x31a6,0xffff,0x528a,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xce79,0x9492,0x0,0x0,0x8430,0xe73c,0x10a2,0xf7be,0xbdf7,0xa514,0xb5b6,0x5aeb,0x18c3,0xf7be,0x4228,0xe73c,0x4a49,0x0,0xef5d,0x4a69,0x8430,0xce79,0x0,0x0,0x0,0x528a,0xffff,0xa534,0xa534,0xad75,0x39e7,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xce79,0xad75,0x10a2,0x52aa,0xffff,0x8c71,0x0,0xef5d,0x9cd3,0x0,0x738e,0x31a6,0x0,0xbdd7,0xf7be,0xd69a,0x20,0x0,0xef7d,0x52aa,0x528a,0xffff,0x2124,0x4a49,0x94b2,0x2945,0xffff,0x5acb,0x10a2,0x7bcf,0x1082,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xb596,0xffdf,0xe73c,0xef5d,0x9492,0x841,0x0,0x4a49,0xe73c,0xef5d,0xdefb,0x31a6,0x0,0x52aa,0xffff,0x7bef,0x0,0x20,0xdedb,0x630c,0x0,0xa534,0xf79e,0xf79e,0x8410,0x0,0x7bcf,0xef7d,0xef7d,0xbdf7,0x861,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x841,0x861,0x861,0x20,0x0,0x0,0x0,0x0,0x20,0x2104,0x0,0x0,0x0,0x0,0x841,0x0,0x0,0x0,0x861,0x20,0x0,0x0,0x18c3,0x1082,0x0,0x0,0x0,0x1082,0x2104,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x39e7,0x4a49,0x1082,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x20,0x0,0x0,0x0,0x0,0x1082,0x9492,0x2945,0x0,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x841,0xbdf7,0xef7d,0xe73c,0xef7d,0x2124,0x0,0x0,0x0,0x0,0x0,0x0,0x528a,0x6b6d,0x0,0x0,0x6b4d,0x5acb,0x0,0x18c3,0xc618,0x39e7,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x841,0x2124,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x4a49,0xffff,0x2104,0x0,0x4208,0x1082,0x0,0x39e7,0xa534,0x9cf3,0x18c3,0x2945,0xef7d,0xf79e,0x8430,0x5aeb,0xffdf,0xe71c,0x8410,0x1082,0x7bcf,0x18c3,0x2124,0x73ae,0x5acb,0xad55,0x52aa,0x0,0x0,0x6b6d,0x9cd3,0xbdd7,0x7bef,0x0,0x6b6d,0xad75,0x7bef,0x841,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x18e3,0xef7d,0xd69a,0x8410,0x2945,0x0,0x31a6,0xf79e,0x73ae,0xad55,0xce79,0x2965,0xd6ba,0xe71c,0x7bcf,0x52aa,0xe73c,0xd69a,0x73ae,0x18e3,0xffff,0x39e7,0x4228,0xffff,0xa534,0xad55,0xffff,0x1082,0x5aeb,0xf79e,0x5aeb,0xef7d,0x39e7,0x52aa,0xffdf,0x6b6d,0x9cd3,0x18c3,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x18e3,0x9cd3,0xdefb,0xffff,0x31a6,0x7bcf,0xffff,0x738e,0x9cd3,0xffff,0x0,0x9492,0xb5b6,0x0,0x0,0xbdd7,0x9492,0x0,0x10a2,0xf7be,0x31a6,0x4208,0xffff,0x20,0x0,0xffdf,0x31a6,0x630c,0xdedb,0x2124,0xef7d,0x632c,0x39c7,0xf79e,0x9cf3,0x4228,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x18c3,0x39e7,0x0,0x0,0xe73c,0x8c71,0x738e,0xf7be,0x4a69,0x4a69,0x5acb,0x0,0xa534,0xb5b6,0x0,0x0,0xc638,0x94b2,0x0,0x10a2,0xf7be,0x31a6,0x4208,0xf79e,0x20,0x1082,0xf79e,0x39e7,0x18c3,0xd6ba,0xb596,0x73ae,0x0,0x0,0x31a6,0x8410,0xffff,0x5aeb,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x4228,0xffff,0xbdf7,0xad55,0xffff,0x52aa,0x2124,0xffdf,0x9cd3,0xa514,0xb596,0x0,0x7bcf,0xffff,0xa514,0x861,0x94b2,0xffdf,0x8c51,0x2104,0xffff,0x39e7,0x4a49,0xffff,0x20,0x1082,0xffff,0x39c7,0x4228,0xffdf,0x9cf3,0x7bef,0x10a2,0x632c,0xce59,0x6b6d,0xffdf,0x5aeb,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x39e7,0x9cd3,0xa534,0x52aa,0x0,0x0,0x31a6,0xa514,0x9cf3,0x3186,0x0,0x861,0x7bef,0x9cd3,0x10a2,0x1082,0x8c71,0x8c71,0x10a2,0x7bcf,0x18e3,0x2104,0x7bcf,0x0,0x20,0x7bcf,0x18e3,0x7bef,0xb5b6,0x7bef,0xd69a,0xdedb,0x18c3,0x7bcf,0xad75,0x630c,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xef5d,0xb596,0x31a6,0xb5b6,0xd6ba,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x20,0x0,0x0,0x0,0x0,0x0,0x20,0x20,0x0,0x0,0x0,0x0,0x20,0x0,0x0,0x20,0x0,0x0,0x20,0x0,0x0,0x20,0x0,0x0,0x20,0x0,0x2965,0x9cd3,0xad55,0x8c71,0x18e3,0x0,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xf800,0x0,0x7e0,0x0,0x1f,0x0,}; +const uint16_t information_app_bmp[] PROGMEM = {0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1904,0x31e8,0x3a49,0x3a49,0x3a49,0x3a49,0x3a49,0x3a4a,0x3a4a,0x3a4a,0x3a2a,0x3a2a,0x3a2a,0x3a2a,0x3a2a,0x3a2a,0x3a2a,0x3a2a,0x3a2a,0x3a2a,0x3a2a,0x3a2a,0x3a2a,0x3a2a,0x3a2a,0x3a2a,0x3a2a,0x3a2a,0x3a2a,0x3a0a,0x3a0a,0x3a0a,0x3a0a,0x3a0a,0x3a0a,0x420a,0x3a0a,0x31c9,0x18e4,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x3a28,0xbe39,0xffdf,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffdf,0xc619,0x39e9,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x636d,0xffff,0xffff,0xf7df,0xc6fd,0xa65b,0x9e3b,0xa63b,0xa63b,0xa63b,0xa63b,0xa63b,0xa63b,0xa61b,0xa61b,0xa61b,0xa61b,0xa61b,0xa61b,0xa61b,0xa5fb,0xa5fc,0xa5fc,0xa5fc,0xa5fc,0xa5fc,0xaddc,0xaddc,0xaddc,0xaddc,0xaddc,0xaddc,0xaddc,0xadbc,0xadbc,0xadbc,0xadbc,0xadbc,0xadbc,0xadbc,0xce9e,0xf7bf,0xffff,0xffff,0x6b6f,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x3a29,0xffff,0xffff,0xae7b,0x1c35,0x3b3,0x373,0x353,0x353,0x353,0x334,0x334,0x314,0x314,0x314,0x2f4,0x2f4,0xad5,0xad5,0xab5,0xab5,0xab5,0xa95,0xa95,0x1276,0x1276,0x1276,0x1256,0x1256,0x1236,0x1236,0x1a17,0x1a17,0x1a17,0x19f7,0x19f7,0x19d7,0x19d7,0x21d8,0x21b8,0x21b8,0x29d8,0x4279,0xb5dd,0xffff,0xffff,0x528b,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x21,0xcedb,0xffff,0x9e5a,0x393,0x3b3,0xbb4,0xbb4,0xbb4,0xb94,0xb94,0xb74,0x1374,0x1375,0x1355,0x1355,0x1335,0x1335,0x1335,0x1315,0x1b16,0x1af6,0x1af6,0x1af6,0x1ad6,0x1ad6,0x1ab6,0x22b6,0x22b7,0x2297,0x2297,0x2297,0x2277,0x2277,0x2257,0x2a57,0x2a58,0x2a38,0x2a38,0x2a18,0x2a18,0x2a18,0x29f8,0x29b8,0x2178,0xad7c,0xffff,0xd6bc,0x21,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x42aa,0xffff,0xe79e,0x1414,0x3b3,0xbd4,0x3b4,0xbb4,0xb94,0xb94,0xb74,0xb74,0xb74,0xb55,0x1355,0x1335,0x1335,0x1335,0x1315,0x1315,0x12f5,0x1af6,0x1af6,0x1ad6,0x1ad6,0x1ad6,0x1ab6,0x22b6,0x22b6,0x2297,0x2277,0x2277,0x2277,0x2257,0x2257,0x2257,0x2a38,0x2a38,0x2a18,0x2a18,0x2a18,0x29f8,0x29f8,0x31f9,0x29b8,0x3a39,0xef5e,0xffff,0x422a,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x20,0x0,0x7bef,0xffff,0xa67a,0x3b3,0xbd3,0x3b3,0x3b4,0xbb4,0xb94,0xb94,0xb74,0xb74,0xb74,0xb54,0x1355,0x1335,0x1335,0x1335,0x1315,0x1315,0x12f5,0x12f6,0x1af6,0x1ad6,0x1ad6,0x1ad6,0x1ab6,0x1277,0x1277,0x1a97,0x2297,0x2277,0x2277,0x2257,0x2257,0x2237,0x2238,0x2a38,0x2a18,0x2a18,0x29f8,0x29f8,0x29f8,0x29d8,0x31f9,0x2978,0xb59c,0xffff,0x6b4f,0x0,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x20,0x0,0x7bef,0xffff,0x6d98,0x392,0xbd4,0x3b3,0x3b4,0xbb4,0xb94,0xb94,0xb74,0xb74,0xb74,0xb54,0x1355,0x1335,0x1335,0x1335,0x1315,0x1315,0x12f5,0x12f6,0x1af6,0x1ad6,0x1ad6,0x1297,0x22d6,0x53b4,0x5394,0x22b6,0x1a57,0x2277,0x2277,0x2257,0x2257,0x2257,0x2238,0x2a38,0x2a18,0x2a18,0x29f8,0x29f8,0x29f8,0x29d8,0x31f9,0x2158,0x8c5b,0xffff,0x6b4f,0x0,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x20,0x0,0x7bef,0xffff,0x6577,0x392,0xbd3,0x3b3,0x3b4,0xbb4,0xb94,0xb94,0xb74,0xb74,0xb74,0xb54,0x1355,0x1335,0x1335,0x1335,0x1315,0x1315,0x12f5,0x12f6,0x1af6,0x1af6,0x12b6,0x5bf3,0xe66c,0xfeeb,0xfeeb,0xde4c,0x5bb3,0x1237,0x2277,0x2257,0x2257,0x2237,0x2238,0x2a38,0x2a18,0x2a18,0x29f8,0x29f8,0x29f8,0x29d8,0x31f9,0x2158,0x7c1b,0xffff,0x6b4f,0x0,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x20,0x0,0x7bef,0xffff,0x6578,0x392,0xbd3,0x3b3,0x3b4,0xbb4,0xb94,0xb94,0xb74,0xb74,0xb74,0xb54,0x1355,0x1335,0x1335,0x1335,0x1315,0x1315,0x12f5,0x12f6,0x1af6,0x12b6,0x4bb4,0xfeeb,0xff0a,0xfeeb,0xfeeb,0xff2a,0xf6cb,0x4315,0x1a57,0x2277,0x2257,0x2237,0x2a38,0x2a38,0x2a18,0x2a18,0x29f8,0x29f8,0x29f8,0x29d8,0x31f9,0x2158,0x841b,0xffff,0x6b4f,0x0,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x20,0x0,0x7bef,0xffff,0x6578,0x392,0xbd3,0x3b3,0x3b4,0xbb4,0xb94,0xb94,0xb74,0xb74,0xb74,0xb54,0x1355,0x1335,0x1335,0x1335,0x1315,0x1315,0x12f5,0x12f6,0x1af6,0xab6,0xad6f,0xff2a,0xfecb,0xfeeb,0xfeeb,0xfecb,0xff4a,0xa4f0,0x1218,0x2277,0x2257,0x2237,0x2238,0x2a38,0x2a18,0x2a18,0x29f8,0x29f8,0x29f8,0x29d8,0x31f9,0x2158,0x841b,0xffff,0x6b4f,0x0,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x20,0x0,0x7bef,0xffff,0x6578,0x392,0xbd3,0x3b3,0x3b4,0xbb4,0xb94,0xb94,0xb74,0xb74,0xb74,0xb54,0x1355,0x1335,0x1335,0x1335,0x1315,0x1315,0x12f5,0x1af6,0x1af6,0x1ad6,0xcded,0xff0a,0xfeeb,0xfeeb,0xfeeb,0xfeeb,0xff2a,0xbdae,0x1a57,0x2257,0x2257,0x2257,0x2238,0x2a38,0x2a18,0x2a18,0x29f8,0x29f8,0x29f8,0x29d8,0x31f9,0x2158,0x841b,0xffff,0x6b4f,0x0,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x20,0x0,0x7bef,0xffff,0x6578,0x392,0xbd3,0x3b3,0x3b4,0xbb4,0xb94,0xb94,0xb74,0xb74,0xb74,0xb54,0x1355,0x1335,0x1335,0x1335,0x1315,0x1315,0x12f5,0x1af6,0x1af6,0x12b6,0xb58e,0xff2a,0xfecb,0xfeeb,0xfeeb,0xfecb,0xff2a,0xb54f,0x1a38,0x2277,0x2257,0x2237,0x2238,0x2a38,0x2a18,0x2a18,0x29f8,0x29f8,0x29f8,0x29d8,0x31f9,0x2158,0x841b,0xffff,0x6b4f,0x0,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x20,0x0,0x7bef,0xffff,0x6578,0x392,0xbd3,0x3b3,0x3b4,0xbb4,0xb94,0xb94,0xb74,0xb74,0xb74,0xb54,0x1355,0x1335,0x1335,0x1335,0x1315,0x1315,0x12f5,0x12f6,0x1af6,0xab6,0x5bf3,0xff2a,0xff0a,0xfecb,0xfecb,0xff0a,0xff2a,0x63b3,0x1a38,0x2277,0x2257,0x2237,0x2a38,0x2a38,0x2a18,0x2a18,0x29f8,0x29f8,0x29f8,0x29d8,0x31f9,0x2158,0x841b,0xffff,0x6b4f,0x0,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x20,0x0,0x7bef,0xffff,0x6578,0x392,0xbd3,0x3b3,0x3b4,0xbb4,0xb94,0xb94,0xb74,0xb74,0xb74,0xb54,0x1355,0x1335,0x1335,0x1335,0x1315,0x1315,0x12f5,0x12f6,0x1af6,0x1af6,0x12b6,0x7c71,0xfecb,0xff4a,0xff2a,0xf6ab,0x7c52,0x1a57,0x2277,0x2257,0x2257,0x2237,0x2238,0x2a38,0x2a18,0x2a18,0x29f8,0x29f8,0x29f8,0x29d8,0x31f9,0x2158,0x841b,0xffff,0x6b4f,0x0,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x20,0x0,0x7bef,0xffff,0x6578,0x392,0xbd3,0x3b3,0x3b4,0xbb4,0xb94,0xb94,0xb74,0xb74,0xb74,0xb54,0x1355,0x1335,0x1335,0x1335,0x1315,0x1315,0x12f5,0x12f6,0x1af6,0x1ad6,0x1ad6,0xa97,0x3b54,0x8cd1,0x7452,0x32f5,0x1257,0x2277,0x2277,0x2257,0x2257,0x2257,0x2238,0x2a38,0x2a18,0x2a18,0x29f8,0x29f8,0x29f8,0x29d8,0x31f9,0x2158,0x841b,0xffff,0x6b4f,0x0,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x20,0x0,0x7bef,0xffff,0x6578,0x392,0xbd3,0x3b3,0x3b4,0xbb4,0xb94,0xb94,0xb74,0xb74,0xb74,0xb54,0x1355,0x1335,0x1335,0x1335,0x1315,0x1315,0x12f5,0x12f6,0x1af6,0x1af6,0x1ad6,0x22d6,0x1297,0xa57,0x1257,0x1a77,0x2297,0x2277,0x2277,0x2257,0x2257,0x2237,0x2238,0x2a38,0x2a18,0x2a18,0x29f8,0x29f8,0x29f8,0x29d8,0x31f9,0x2158,0x841b,0xffff,0x6b4f,0x0,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x20,0x0,0x7bef,0xffff,0x6578,0x392,0xbd3,0x3b3,0x3b4,0xbb4,0xb94,0xb94,0xb74,0xb74,0xb74,0xb54,0x1355,0x1335,0x1335,0x1335,0x1315,0x1315,0x12f5,0x12f6,0x1af6,0x12b6,0xa97,0x1296,0x1ab6,0x22d6,0x22b6,0x2297,0x2277,0x2277,0x2277,0x2257,0x2257,0x2237,0x2a38,0x2a38,0x2a18,0x2a18,0x29f8,0x29f8,0x29f8,0x29d8,0x31f9,0x2158,0x841b,0xffff,0x6b4f,0x0,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x20,0x0,0x7bef,0xffff,0x6578,0x392,0xbd3,0x3b3,0x3b4,0xbb4,0xb94,0xb94,0xb74,0xb74,0xb74,0xb54,0x1355,0x1335,0x1335,0x1335,0x1315,0x1315,0x12f5,0x12f6,0x1af5,0x9510,0x7c91,0x4374,0x22b6,0x1277,0x1277,0x2297,0x2277,0x2277,0x2277,0x2257,0x2257,0x2237,0x2238,0x2a38,0x2a18,0x2a18,0x29f8,0x29f8,0x29f8,0x29d8,0x31f9,0x2158,0x841b,0xffff,0x6b4f,0x0,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x20,0x0,0x7bef,0xffff,0x6578,0x392,0xbd3,0x3b3,0x3b4,0xbb4,0xb94,0xb94,0xb74,0xb74,0xb74,0xb54,0x1355,0x1335,0x1335,0x1335,0x1315,0x1315,0x1b15,0x12d6,0x3b94,0xff0a,0xff2a,0xfecb,0xd62d,0xa52f,0x5bd3,0x1a97,0x2297,0x2277,0x2277,0x2257,0x2257,0x2257,0x2238,0x2a38,0x2a18,0x2a18,0x29f8,0x29f8,0x29f8,0x29d8,0x31f9,0x2158,0x841b,0xffff,0x6b4f,0x0,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x20,0x0,0x7bef,0xffff,0x6578,0x392,0xbd3,0x3b3,0x3b4,0xbb4,0xb94,0xb94,0xb74,0xb74,0xb74,0xb54,0x1355,0x1335,0x1335,0x1335,0x1315,0x1315,0x1b15,0x2b6,0x7491,0xff0a,0xfecb,0xfeeb,0xff0a,0xff89,0xa52f,0x1257,0x2297,0x2277,0x2277,0x2257,0x2257,0x2237,0x2238,0x2a38,0x2a18,0x2a18,0x29f8,0x29f8,0x29f8,0x29d8,0x31f9,0x2158,0x841b,0xffff,0x6b4f,0x0,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x20,0x0,0x7bef,0xffff,0x6578,0x392,0xbd3,0x3b3,0x3b4,0xbb4,0xb94,0xb94,0xb74,0xb74,0xb74,0xb54,0x1355,0x1335,0x1335,0x1335,0x1315,0x1315,0x1b15,0xad6,0xad6f,0xff2a,0xfecb,0xfeeb,0xfeeb,0xff0a,0x63f3,0x1257,0x2297,0x2277,0x2277,0x2257,0x2257,0x2237,0x2a38,0x2a38,0x2a18,0x2a18,0x29f8,0x29f8,0x29f8,0x29d8,0x31f9,0x2158,0x841b,0xffff,0x6b4f,0x0,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x20,0x0,0x7bef,0xffff,0x6578,0x392,0xbd3,0x3b3,0x3b4,0xbb4,0xb94,0xb94,0xb74,0xb74,0xb74,0xb54,0x1355,0x1335,0x1335,0x1335,0x1315,0x1315,0x12f6,0x1b15,0xe66c,0xff0a,0xfeeb,0xfeeb,0xfeea,0xf6ab,0x3315,0x1a77,0x2297,0x2277,0x2277,0x2257,0x2257,0x2237,0x2238,0x2a38,0x2a18,0x2a18,0x29f8,0x29f8,0x29f8,0x29d8,0x31f9,0x2158,0x841b,0xffff,0x6b4f,0x0,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x20,0x0,0x7bef,0xffff,0x6578,0x392,0xbd3,0x3b3,0x3b4,0xbb4,0xb94,0xb94,0xb74,0xb74,0xb74,0xb54,0x1355,0x1335,0x1335,0x1335,0x1315,0x1315,0xad6,0x4bd3,0xfeeb,0xfeeb,0xfeeb,0xfeeb,0xff2a,0xc5ce,0x1a97,0x2297,0x2297,0x2277,0x2277,0x2257,0x2257,0x2257,0x2238,0x2a38,0x2a18,0x2a18,0x29f8,0x29f8,0x29f8,0x29d8,0x31f9,0x2158,0x841b,0xffff,0x6b4f,0x0,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x20,0x0,0x7bef,0xffff,0x6578,0x392,0xbd3,0x3b3,0x3b4,0xbb4,0xb94,0xb94,0xb74,0xb74,0xb74,0xb54,0x1355,0x1335,0x1335,0x1335,0x1315,0x1b15,0x2b6,0x84d0,0xff2a,0xfeeb,0xfeeb,0xfecb,0xff2a,0x8cd0,0xa57,0x2296,0x2277,0x2277,0x2277,0x2257,0x2257,0x2237,0x2238,0x2a38,0x2a18,0x2a18,0x29f8,0x29f8,0x29f8,0x29d8,0x31f9,0x2158,0x841b,0xffff,0x6b4f,0x0,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x20,0x0,0x7bef,0xffff,0x6578,0x392,0xbd3,0x3b3,0x3b4,0xbb4,0xb94,0xb94,0xb74,0xb74,0xb74,0xb54,0x1355,0x1335,0x1335,0x1335,0x1315,0x1315,0x12f6,0xbdce,0xff2a,0xfeeb,0xfeeb,0xfeeb,0xff0a,0x5bd3,0x1277,0x2296,0x2277,0x2277,0x2277,0x2257,0x2257,0x2237,0x2a38,0x2a38,0x2a18,0x2a18,0x29f8,0x29f8,0x29f8,0x29d8,0x31f9,0x2158,0x841b,0xffff,0x6b4f,0x0,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x20,0x0,0x7bef,0xffff,0x6578,0x392,0xbd3,0x3b3,0x3b4,0xbb4,0xb94,0xb94,0xb74,0xb74,0xb74,0xb54,0x1355,0x1335,0x1335,0x1335,0x1315,0x12f5,0x2355,0xeeab,0xff0a,0xfeeb,0xfeeb,0xff0a,0xee8c,0x2af6,0x1a97,0x2297,0x2277,0x2277,0x2277,0x2257,0x2257,0x2237,0x2238,0x2a38,0x2a18,0x2a18,0x29f8,0x29f8,0x29f8,0x29d8,0x31f9,0x2158,0x841b,0xffff,0x6b4f,0x0,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x20,0x0,0x7bef,0xffff,0x6578,0x392,0xbd3,0x3b3,0x3b4,0xbb4,0xb94,0xb94,0xb74,0xb74,0xb74,0xb54,0x1355,0x1335,0x1335,0x1335,0x1335,0xad6,0x5c12,0xff0a,0xfeeb,0xfeeb,0xfeeb,0xff2a,0xb58e,0x1297,0x22b6,0x2297,0x2277,0x2277,0x2277,0x2257,0x2257,0x2257,0x2238,0x2a38,0x2a18,0x2a18,0x29f8,0x29f8,0x29f8,0x29d8,0x31f9,0x2158,0x841b,0xffff,0x6b4f,0x0,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x20,0x0,0x7bef,0xffff,0x6578,0x392,0xbd3,0x3b3,0x3b4,0xbb4,0xb94,0xb94,0xb74,0xb74,0xb74,0xb54,0x1355,0x1335,0x1335,0x1335,0x1b35,0x2d6,0x9510,0xff2a,0xfecb,0xfeeb,0xfeeb,0xff2a,0x8491,0xa57,0x22b6,0x2297,0x2277,0x2277,0x2277,0x2257,0x2257,0x2237,0x2238,0x2a38,0x2a18,0x2a18,0x29f8,0x29f8,0x29f8,0x29d8,0x31f9,0x2158,0x841b,0xffff,0x6b4f,0x0,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x20,0x0,0x7bef,0xffff,0x6578,0x392,0xbd3,0x3b3,0x3b4,0xbb4,0xb94,0xb94,0xb74,0xb74,0xb74,0xb54,0x1355,0x1335,0x1335,0x1335,0x1315,0x1315,0xce0d,0xff0a,0xfeeb,0xfeeb,0xfeeb,0xfeeb,0x4b94,0x1277,0x22b6,0x2297,0x2277,0x2277,0x2277,0x2257,0x2257,0x2237,0x2a38,0x2a38,0x2a18,0x2a18,0x29f8,0x29f8,0x29f8,0x29d8,0x31f9,0x2158,0x841b,0xffff,0x6b4f,0x0,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x20,0x0,0x7bef,0xffff,0x6578,0x392,0xbd3,0x3b3,0x3b4,0xbb4,0xb94,0xb94,0xb74,0xb74,0xb74,0xb54,0x1355,0x1335,0x1335,0x1335,0xb15,0x2b74,0xf6cb,0xfeeb,0xfeeb,0xfeeb,0xff0a,0xde4c,0x22d6,0x1a96,0x2296,0x2297,0x2277,0x2277,0x2277,0x2257,0x2257,0x2237,0x2238,0x2a38,0x2a18,0x2a18,0x29f8,0x29f8,0x29f8,0x29d8,0x31f9,0x2158,0x841b,0xffff,0x6b4f,0x0,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x20,0x0,0x7bef,0xffff,0x6578,0x392,0xbd3,0x3b3,0x3b4,0xbb4,0xb94,0xb94,0xb74,0xb74,0xb74,0xb54,0x1355,0x1335,0x1335,0x1335,0x2d6,0x6471,0xff0a,0xfeeb,0xfeeb,0xfecb,0xff2a,0xa54f,0x1277,0x22b6,0x1a96,0x2297,0x2277,0x2277,0x2277,0x2257,0x2257,0x2257,0x2238,0x2a38,0x2a18,0x2a18,0x29f8,0x29f8,0x29f8,0x29d8,0x31f9,0x2158,0x841b,0xffff,0x6b4f,0x0,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x20,0x0,0x7bef,0xffff,0x6578,0x392,0xbd3,0x3b3,0x3b4,0xbb4,0xb94,0xb94,0xb74,0xb74,0xb74,0xb54,0x1355,0x1335,0x1335,0x1335,0x2f6,0x9d4f,0xff2a,0xfecb,0xfeeb,0xfeeb,0xff2a,0x7452,0xa77,0x22b6,0x1a96,0x2297,0x2277,0x2277,0x2277,0x2257,0x2257,0x2237,0x2238,0x2a38,0x2a18,0x2a18,0x29f8,0x29f8,0x29f8,0x29d8,0x31f9,0x2158,0x841b,0xffff,0x6b4f,0x0,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x20,0x0,0x7bef,0xffff,0x6578,0x392,0xbd3,0x3b3,0x3b4,0xbb4,0xb94,0xb94,0xb74,0xb74,0xb74,0xb54,0x1355,0x1335,0x1335,0x1335,0x1b35,0xde4c,0xff0a,0xfeeb,0xfeeb,0xfeeb,0xfecb,0x3b55,0x1296,0x1ab6,0x1a96,0x2297,0x2277,0x2277,0x2277,0x2257,0x2257,0x2237,0x2a38,0x2a38,0x2a18,0x2a18,0x29f8,0x29f8,0x29f8,0x29d8,0x31f9,0x2158,0x841b,0xffff,0x6b4f,0x0,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x20,0x0,0x7bef,0xffff,0x6578,0x392,0xbd3,0x3b3,0x3b4,0xbb4,0xb94,0xb94,0xb74,0xb74,0xb74,0xb54,0x1355,0x1335,0x1335,0xb15,0x3bd3,0xfeeb,0xfeeb,0xfeeb,0xfeeb,0xff0a,0xd60d,0x1ab6,0x1ab6,0x1ab6,0x1a96,0x2297,0x2277,0x2277,0x2277,0x2257,0x2257,0x2237,0x2238,0x2a38,0x2a18,0x2a18,0x29f8,0x29f8,0x29f8,0x29d8,0x31f9,0x2158,0x841b,0xffff,0x6b4f,0x0,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x20,0x0,0x7bef,0xffff,0x6578,0x392,0xbd3,0x3b3,0x3b4,0xbb4,0xb94,0xb94,0xb74,0xb74,0xb74,0xb54,0x1355,0x1335,0x1355,0x2f6,0x74b1,0xff2a,0xfeeb,0xfeeb,0xfecb,0xff2a,0x9d10,0xa77,0x22d6,0x1ab6,0x1a96,0x2297,0x2277,0x2277,0x2277,0x2257,0x2257,0x2257,0x2238,0x2a38,0x2a18,0x2a18,0x29f8,0x29f8,0x29f8,0x29d8,0x31f9,0x2158,0x841b,0xffff,0x6b4f,0x0,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x20,0x0,0x7bef,0xffff,0x6578,0x392,0xbd3,0x3b3,0x3b4,0xbb4,0xb94,0xb94,0xb74,0xb74,0xb74,0xb54,0x1355,0x1335,0x1335,0xb15,0xad8e,0xff2a,0xfeeb,0xfeeb,0xfeeb,0xff0a,0x6412,0xa97,0x22b6,0x1ab6,0x1a96,0x2297,0x2277,0x2277,0x2277,0x2257,0x2257,0x2237,0x2238,0x2a38,0x2a18,0x2a18,0x29f8,0x29f8,0x29f8,0x29d8,0x31f9,0x2158,0x841b,0xffff,0x6b4f,0x0,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x20,0x0,0x7bef,0xffff,0x6578,0x392,0xbd3,0x3b3,0x3b4,0xbb4,0xb94,0xb94,0xb74,0xb74,0xb74,0xb54,0x1355,0x1355,0xb35,0x1b55,0xe68c,0xff0a,0xfeeb,0xfeeb,0xfeea,0xf6ab,0x2b35,0x12b6,0x1ab6,0x1ab6,0x1a96,0x2297,0x2277,0x2277,0x2277,0x2257,0x2257,0x2237,0x2a38,0x2a38,0x2a18,0x2a18,0x29f8,0x29f8,0x29f8,0x29d8,0x31f9,0x2158,0x841b,0xffff,0x6b4f,0x0,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x20,0x0,0x7bef,0xffff,0x6578,0x392,0xbd3,0x3b3,0x3b4,0xbb4,0xb94,0xb94,0xb74,0xb74,0xb74,0xb54,0x1355,0x1355,0xb15,0x43f3,0xfeeb,0xfeeb,0xfeeb,0xfeeb,0xff2a,0xc5ce,0x12b6,0x1ad6,0x1ab6,0x1ab6,0x1a96,0x2297,0x2277,0x2277,0x2277,0x2257,0x2257,0x2237,0x2238,0x2a38,0x2a18,0x2a18,0x29f8,0x29f8,0x29f8,0x29d8,0x31f9,0x2158,0x841b,0xffff,0x6b4f,0x0,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x20,0x0,0x7bef,0xffff,0x6578,0x392,0xbd3,0x3b3,0x3b4,0xbb4,0xb94,0xb94,0xb74,0xb74,0xb74,0xb54,0x1355,0x1355,0x2f6,0x952f,0xff4a,0xfeeb,0xfeeb,0xf6cb,0xff2a,0x8cd0,0xa97,0x1ad6,0x1ab6,0x1ab6,0x1a96,0x2297,0x2277,0x2277,0x2277,0x2257,0x2257,0x2257,0x2238,0x2a38,0x2a18,0x2a18,0x29f8,0x29f8,0x29f8,0x29d8,0x31f9,0x2158,0x841b,0xffff,0x6b4f,0x0,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x20,0x0,0x7bef,0xffff,0x6577,0x392,0xbd3,0x3b3,0x3b4,0xbb4,0xb94,0xb94,0xb74,0xb74,0xb74,0xb54,0x1355,0x1355,0xb15,0x6c91,0xde4c,0xf6cb,0xff2a,0xff2a,0xff0a,0x53d3,0x1296,0x1ad6,0x1ab6,0x1ab6,0x1a96,0x2297,0x2277,0x2277,0x2277,0x2257,0x2257,0x2237,0x2238,0x2a38,0x2a18,0x2a18,0x29f8,0x29f8,0x29f8,0x29d8,0x31f9,0x2158,0x841b,0xffff,0x6b4f,0x0,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x20,0x0,0x7bef,0xffff,0x6d78,0x392,0xbd3,0x3b3,0x3b4,0xbb4,0xb94,0xb94,0xb74,0xb74,0xb74,0xb54,0x1355,0x1335,0x1335,0xb15,0x1315,0x3394,0x6c91,0xad8e,0xce0d,0x2315,0x12b6,0x1ad6,0x1ab6,0x1ab6,0x1a96,0x2297,0x2277,0x2277,0x2277,0x2257,0x2257,0x2237,0x2a38,0x2a38,0x2a18,0x2a18,0x29f8,0x29f8,0x29f8,0x29d8,0x31f9,0x2158,0x843b,0xffff,0x6b4f,0x0,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x20,0x0,0x7bf0,0xffff,0x85f9,0x392,0xbd4,0x3b3,0x3b4,0xbb4,0xb94,0xb94,0xb74,0xb74,0xb74,0xb54,0x1355,0x1335,0x1335,0x1335,0x1315,0xaf6,0x2b6,0xad6,0x1af6,0x1ad6,0x1ad6,0x1ab6,0x1ab6,0x1ab6,0x1a96,0x2297,0x2277,0x2277,0x2277,0x2257,0x2257,0x2237,0x2238,0x2a38,0x2a18,0x2a18,0x29f8,0x29f8,0x29f8,0x29d8,0x31f9,0x2158,0x9cfc,0xffff,0x6b4f,0x0,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x530c,0xffff,0xc6fc,0x3d3,0x3d3,0xbd4,0x3b4,0xbb4,0xb94,0xb94,0xb74,0xb74,0xb74,0xb54,0x1355,0x1335,0x1335,0x1335,0x1315,0x1315,0x1b15,0x1af5,0x12f6,0x1ad6,0x1ad6,0x1ab6,0x1ab6,0x1ab6,0x1a96,0x2297,0x2277,0x2277,0x2277,0x2257,0x2257,0x2257,0x2238,0x2a38,0x2a18,0x2a18,0x29f8,0x29f8,0x29f8,0x31f9,0x31d9,0x29b9,0xce9d,0xffff,0x4a6c,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x882,0xe75d,0xffff,0x7598,0x372,0x3b3,0xbb4,0xbb4,0xbb4,0xb94,0xb94,0x1394,0x1375,0x1375,0x1355,0x1355,0x1355,0x1335,0x1b35,0x1b15,0x1b16,0x1b16,0x1af6,0x1af6,0x1af6,0x1ad6,0x22d6,0x22b6,0x22b7,0x22b7,0x2297,0x2297,0x2277,0x2a77,0x2a77,0x2a58,0x2a58,0x2a38,0x2a38,0x2a38,0x2a18,0x3218,0x31f8,0x29d8,0x1938,0x8c7b,0xffff,0xe73d,0x862,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x636e,0xffff,0xffdf,0x7598,0xbd4,0x373,0x353,0x353,0x353,0x333,0x333,0x314,0x314,0x2f4,0x2f4,0x2f4,0x2d4,0x2d4,0x2b5,0x2b5,0xa95,0xa95,0xa95,0xa75,0xa75,0xa56,0xa56,0x1256,0x1236,0x1236,0x1216,0x1216,0x11f7,0x11f7,0x19d7,0x19d7,0x19d7,0x19b7,0x19b7,0x1998,0x1998,0x2198,0x31f9,0x8c7b,0xffdf,0xffff,0x6b4e,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x7c51,0xffff,0xffff,0xdf5d,0x961a,0x6538,0x6538,0x6518,0x6518,0x6518,0x6518,0x6d18,0x6cf8,0x6cf8,0x6cf8,0x6cf8,0x6cd9,0x6cd9,0x6cd9,0x6cd9,0x6cb9,0x6cb9,0x6cb9,0x6cb9,0x7499,0x7499,0x7499,0x7499,0x747a,0x747a,0x747a,0x747a,0x745a,0x745a,0x745a,0x745a,0x7c3a,0x7c3a,0x7c3a,0x7c3a,0xa57c,0xe71e,0xffff,0xffff,0x8432,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x52ec,0xd6fc,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xdedc,0x5acc,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x41,0x426a,0x73cf,0x8410,0x8410,0x8410,0x8410,0x8410,0x8410,0x8410,0x8410,0x8410,0x8410,0x8410,0x8410,0x8410,0x8410,0x8410,0x8410,0x8410,0x8410,0x8410,0x8410,0x8410,0x8410,0x8410,0x8410,0x8410,0x8410,0x8410,0x8410,0x8410,0x8410,0x8410,0x8410,0x8410,0x8410,0x8410,0x73af,0x422a,0x21,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1082,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x73ae,0xb596,0xb5b6,0xa514,0x39e7,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x20,0xef5d,0x6b4d,0x0,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xd69a,0xdefb,0x738e,0xb5b6,0xffff,0x52aa,0x0,0x0,0x861,0x2965,0x20,0x0,0x10a2,0x0,0x0,0x0,0x1082,0x20,0x5aeb,0x2945,0x0,0x0,0x2104,0x18c3,0x0,0x0,0x0,0x18c3,0x2945,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xce79,0x8c71,0x0,0x0,0xad55,0xdefb,0x0,0x4a49,0xdefb,0xd6ba,0xce79,0x18e3,0xce59,0x8410,0x0,0x528a,0xe71c,0x10a2,0xce59,0x5aeb,0x0,0xad75,0xf79e,0xf7be,0x8c71,0x0,0x7bef,0xdefb,0xdedb,0xad75,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xce79,0x9cd3,0x0,0x0,0x6b4d,0xf7be,0x841,0xe73c,0xa514,0x10a2,0xf79e,0x8430,0x738e,0xe71c,0x0,0xb596,0xad75,0x0,0xf79e,0x5acb,0x52aa,0xffff,0x2104,0x39e7,0x5aeb,0x2124,0xffff,0x630c,0x31a6,0xffff,0x528a,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xce79,0x9492,0x0,0x0,0x8430,0xe73c,0x10a2,0xf7be,0xbdf7,0xa514,0xb5b6,0x5aeb,0x18c3,0xf7be,0x4228,0xe73c,0x4a49,0x0,0xef5d,0x4a69,0x8430,0xce79,0x0,0x0,0x0,0x528a,0xffff,0xa534,0xa534,0xad75,0x39e7,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xce79,0xad75,0x10a2,0x52aa,0xffff,0x8c71,0x0,0xef5d,0x9cd3,0x0,0x738e,0x31a6,0x0,0xbdd7,0xf7be,0xd69a,0x20,0x0,0xef7d,0x52aa,0x528a,0xffff,0x2124,0x4a49,0x94b2,0x2945,0xffff,0x5acb,0x10a2,0x7bcf,0x1082,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xb596,0xffdf,0xe73c,0xef5d,0x9492,0x841,0x0,0x4a49,0xe73c,0xef5d,0xdefb,0x31a6,0x0,0x52aa,0xffff,0x7bef,0x0,0x20,0xdedb,0x630c,0x0,0xa534,0xf79e,0xf79e,0x8410,0x0,0x7bcf,0xef7d,0xef7d,0xbdf7,0x861,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x841,0x861,0x861,0x20,0x0,0x0,0x0,0x0,0x20,0x2104,0x0,0x0,0x0,0x0,0x841,0x0,0x0,0x0,0x861,0x20,0x0,0x0,0x18c3,0x1082,0x0,0x0,0x0,0x1082,0x2104,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x18c3,0x2945,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1082,0x8430,0xb5b6,0x39c7,0x0,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x20,0x0,0x4228,0x8c51,0x0,0x0,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x20,0x0,0x8c51,0xd6ba,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x73ae,0xf7be,0x6b6d,0x3186,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x9492,0x10a2,0x0,0x630c,0xb5b6,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x18c3,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x20,0x0,0x8c71,0xdefb,0x0,0x4a49,0x632c,0x738e,0xa534,0x2965,0x10a2,0xdedb,0xe71c,0x7bef,0x10a2,0x18c3,0x9492,0xad55,0x4228,0x0,0x2965,0x738e,0x632c,0x73ae,0x2945,0x738e,0x630c,0xad55,0x39e7,0x52aa,0xad75,0x4228,0x0,0x18e3,0x8c51,0xad75,0x5aeb,0x0,0x8c71,0xffff,0xbdf7,0x4a69,0x2965,0x738e,0x0,0x0,0x6b4d,0xad75,0x73ae,0x20,0x0,0x6b4d,0x52aa,0x8c51,0x94b2,0x9cf3,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x20,0x0,0x8c51,0xdefb,0x0,0x9492,0xffff,0x8c51,0xd69a,0xdedb,0x10a2,0xce59,0xef7d,0x8c71,0x2965,0xd6ba,0xce59,0x9cd3,0xffff,0x31a6,0x4228,0xffff,0xd69a,0x6b6d,0x528a,0xffff,0xa514,0xbdf7,0xffff,0x9cf3,0xc618,0xf79e,0x0,0x7bef,0xad55,0x7bcf,0xffff,0x3186,0x7bcf,0xffff,0xb5b6,0x39c7,0x738e,0xf7be,0x0,0x8430,0xffdf,0x8c51,0xf79e,0x9cf3,0x0,0xd6ba,0xf79e,0x8410,0xf7be,0xce59,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x20,0x0,0x8c51,0xdefb,0x0,0x8c51,0xdedb,0x0,0x4208,0xffff,0x0,0x7bcf,0xce79,0x0,0x4208,0xffff,0x1082,0x0,0xce59,0x94b2,0x39c7,0xffff,0x18e3,0x0,0x4a69,0xffdf,0x0,0x3186,0xffff,0x0,0x2945,0xffdf,0x1082,0x861,0x5aeb,0x8c51,0xffff,0x4a49,0x0,0xf7be,0x2945,0x0,0x73ae,0xdedb,0x0,0xe73c,0x7bcf,0x0,0x630c,0xf7be,0x0,0xce59,0x9cd3,0x0,0x8c71,0xc638,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x20,0x0,0x8c51,0xdedb,0x0,0x8c71,0xc638,0x0,0x528a,0xf79e,0x0,0x8430,0xd69a,0x0,0x4a49,0xffff,0x1082,0x0,0xce59,0x94b2,0x39e7,0xf79e,0x861,0x0,0x4a69,0xf79e,0x0,0x4a49,0xf79e,0x20,0x4208,0xf79e,0x1082,0xb596,0xbdd7,0x39e7,0xef7d,0x39c7,0x10a2,0xffff,0x3186,0x0,0x738e,0xdedb,0x0,0xe73c,0x7bef,0x0,0x630c,0xf7be,0x0,0xce59,0x8c51,0x0,0x94b2,0xdedb,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x20,0x0,0x94b2,0xf79e,0x0,0x9cf3,0xdefb,0x0,0x5acb,0xffff,0x0,0x9492,0xe71c,0x0,0x841,0xdedb,0xce79,0xa514,0xffff,0x3186,0x4a49,0xffff,0x1082,0x0,0x5acb,0xffff,0x0,0x4a69,0xffff,0x20,0x4208,0xffff,0x10a2,0xce79,0xbdf7,0x6b6d,0xffff,0xa534,0x20,0xef7d,0xdedb,0x4a49,0x738e,0xf7be,0x0,0x8410,0xffdf,0x8c71,0xf79e,0x9cd3,0x0,0xe73c,0x9cd3,0x0,0xa514,0x632c,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x4228,0x6b6d,0x0,0x4a49,0x632c,0x0,0x2945,0x7bef,0x0,0x4208,0x6b4d,0x0,0x0,0x18c3,0x8c71,0xa514,0x4208,0x0,0x2945,0x7bcf,0x20,0x0,0x2945,0x7bcf,0x0,0x2104,0x7bef,0x0,0x18e3,0x7bef,0x20,0x2945,0xa514,0x6b4d,0x4a49,0x8410,0x0,0x39e7,0xad55,0x528a,0x3186,0x738e,0x0,0x0,0x632c,0xad55,0x738e,0x0,0x0,0x6b4d,0x4228,0x0,0x4a49,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x20,0x0,0x0,0x0,0x0,0x0,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x20,0x20,0x0,0x0,0x0,0x20,0x0,0x0,0x0,0x20,0x0,0x0,0x20,0x0,0x0,0x20,0x0,0x0,0x20,0x0,0x0,0x20,0x0,0x0,0x20,0x0,0x0,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xf800,0x0,0x7e0,0x0,0x1f,0x0,}; +const uint16_t main_app_bmp2[] PROGMEM = {0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x39c7,0x738e,0x7bef,0x7bef,0x7bef,0x7bef,0x7bef,0x7bef,0x7bef,0x7bef,0x7bef,0x7bef,0x7bef,0x7bef,0x7bef,0x7bef,0x7bef,0x7bef,0x7bef,0x7bef,0x7bef,0x7bef,0x7bef,0x7bef,0x7bef,0x7bef,0x7bef,0x7bef,0x7bef,0x7bef,0x7bef,0x7bef,0x7bef,0x7bef,0x7bef,0x7bef,0x7bef,0x7bef,0x738e,0x39c7,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x2104,0xbdd7,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xbdd7,0x2104,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x2104,0xe71c,0xffff,0xef7d,0x9cf3,0x6b6d,0x5aeb,0x5aeb,0x5aeb,0x5aeb,0x5aeb,0x5aeb,0x5aeb,0x5aeb,0x5aeb,0x5aeb,0x5aeb,0x5aeb,0x5aeb,0x5aeb,0x5aeb,0x5aeb,0x5aeb,0x5aeb,0x5aeb,0x5aeb,0x5aeb,0x5aeb,0x5aeb,0x5aeb,0x5aeb,0x5aeb,0x5aeb,0x5aeb,0x5aeb,0x5aeb,0x5aeb,0x5aeb,0x5aeb,0x5aeb,0x6b6d,0x9cf3,0xef7d,0xffff,0xe71c,0x2104,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x20,0xc638,0xffff,0xbdf7,0x2104,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x2104,0xc618,0xffff,0xc638,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x6b6d,0xffff,0xd6ba,0x841,0x0,0x20,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x20,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x20,0x20,0x0,0x20,0x20,0x0,0x841,0xd6ba,0xffff,0x632c,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xc638,0xffff,0x4a69,0x0,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x20e3,0x6ac9,0x8bac,0x93ed,0xa40d,0xac0d,0xabec,0x93ab,0x5a68,0x1061,0x0,0x0,0x0,0x0,0x0,0x20,0x0,0x528a,0xffff,0xb5b6,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x861,0xf79e,0xf7be,0x10a2,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x840,0x72ea,0xbd10,0xee34,0xfed7,0xfef7,0xfef6,0xeed7,0x8e79,0x8679,0xe6d7,0xfed6,0xe5f4,0x7b4b,0x0,0x0,0x0,0x0,0x0,0x0,0x10a2,0xffdf,0xdedb,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x861,0xffdf,0xdefb,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x6aa9,0xe593,0xfed7,0xfeb7,0xfe96,0xf655,0xfe55,0xbe36,0xd99,0x59a,0x59a,0x599,0xae36,0xfe95,0xfef7,0x72e9,0x0,0x0,0x0,0x0,0x0,0x20,0xe73c,0xdefb,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x861,0xffdf,0xdedb,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x10a2,0xbcb0,0xded2,0x5ea7,0x3e64,0x6668,0xde73,0xfe76,0xf675,0x2dd9,0x5ba,0x5ba,0x5ba,0x5ba,0x1db9,0xe655,0xfed6,0xb48f,0x0,0x0,0x0,0x0,0x0,0x20,0xe71c,0xdefb,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x861,0xffdf,0xdefb,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x2923,0xe5b3,0xe6d3,0x1661,0x660,0x680,0x680,0x3664,0xf674,0xee76,0x5b9,0x5ba,0x5ba,0x5ba,0x5ba,0x5ba,0xce36,0xfed6,0xa44e,0x0,0x0,0x0,0x0,0x0,0x20,0xe71c,0xdefb,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x861,0xffdf,0xdefb,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x2923,0xe5f3,0xfeb8,0x7e4a,0x680,0xe80,0xe80,0xe80,0x680,0xae6e,0xfe76,0x2dd9,0x5ba,0x5ba,0x5ba,0x5ba,0x15b9,0xee55,0xfed6,0x5a47,0x0,0x0,0x0,0x0,0x0,0x20,0xe71c,0xdefb,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x861,0xffdf,0xdefb,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1061,0xd572,0xfed6,0xfe56,0x7e6a,0x680,0xe80,0x680,0xe80,0x680,0x9e6d,0xfe76,0xb636,0x5ba,0x59a,0x59a,0x5ba,0xa616,0xfed6,0xa44e,0x0,0x0,0x0,0x0,0x0,0x0,0x20,0xe71c,0xdefb,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x861,0xffdf,0xdefb,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x9c0d,0xfef7,0xf654,0xfe76,0xc670,0x680,0x680,0x680,0x680,0x1e82,0xe673,0xfe76,0xfe75,0xce56,0x7e17,0x7e17,0xc636,0xfe95,0xf655,0x18c2,0x0,0x0,0x0,0x0,0x0,0x0,0x20,0xe71c,0xdefb,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x861,0xffdf,0xdefb,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x3985,0xfe75,0xfe75,0xfe76,0xfe76,0xfe76,0xa66e,0x2e83,0x1681,0x3e85,0xc671,0xfe76,0xf675,0xfe75,0xfe75,0xfe95,0xfe95,0xfe75,0xf675,0xfe75,0x93cc,0x20c2,0x0,0x0,0x0,0x0,0x0,0x20,0xe71c,0xdefb,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x861,0xffdf,0xdefb,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xac6e,0xfed7,0xf653,0xf650,0xfe73,0xfe76,0xfe76,0xf675,0xe674,0xfe75,0xfe76,0xfe75,0xfe75,0xfe75,0xf675,0xf675,0xf675,0xf675,0xfe75,0xfe75,0xff17,0xfeb6,0xb4af,0x41a5,0x0,0x0,0x0,0x20,0xe71c,0xdefb,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x861,0xffdf,0xdefb,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x18a2,0xe5f4,0xfe6f,0xf602,0xf600,0xf601,0xf64c,0xf676,0xfe75,0xfe76,0xfe75,0xf675,0xfe75,0xfe75,0xfe75,0xfe75,0xfe75,0xfe75,0xfe75,0xfe75,0xfe96,0xac4e,0x730a,0x9bed,0xf634,0x836b,0x0,0x0,0x20,0xe71c,0xdefb,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x861,0xffdf,0xdefb,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x49e6,0xfe94,0xf602,0xf600,0xf600,0xf600,0xf600,0xf651,0xfe76,0xfe75,0xfe75,0xfe75,0xfe75,0xfe75,0xfe75,0xfe75,0xfe75,0xfe75,0xf675,0xfeb6,0x8bac,0x0,0x0,0x0,0x41c5,0xfeb6,0x41c5,0x0,0x20,0xe71c,0xdefb,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x861,0xffdf,0xdefb,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x72ea,0xfed2,0xede0,0xf600,0xf600,0xf601,0xf600,0xf62b,0xfe77,0xfe75,0xfe75,0xfe75,0xfe75,0xfe75,0xfe75,0xfe75,0xfe75,0xfe75,0xfe95,0xf655,0x2103,0x0,0x20,0x0,0x0,0xcd51,0x836b,0x0,0x840,0xe71c,0xdefb,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x861,0xffdf,0xdefb,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x20,0x0,0x7b0a,0xfef4,0xede0,0xf600,0xf601,0xf600,0xf600,0xf64e,0xfe76,0xfe75,0xfe75,0xfe75,0xfe75,0xfe75,0xfe75,0xfe75,0xfe75,0xfe55,0xfe75,0xf655,0x20e3,0x0,0x20,0x0,0x0,0xc510,0x62a8,0x0,0x820,0xe71c,0xdefb,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x861,0xffdf,0xdefb,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x730a,0xfef7,0xf62b,0xf600,0xf600,0xf600,0xf628,0xfe96,0xfe96,0xfe96,0xfe75,0xfe75,0xfe75,0xfe75,0xfe75,0xfed7,0xfeb6,0xfed7,0xfe96,0xfeb6,0x8b8b,0x0,0x0,0x0,0x41c6,0xe5f4,0x20c2,0x0,0x20,0xe71c,0xdefb,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x861,0xffdf,0xdefb,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x11c9,0x1bb5,0x7559,0xfe95,0xf676,0xf651,0xf62b,0xf64f,0xfe96,0xfe13,0xf5af,0xfe12,0xfe96,0xfe75,0xfe75,0xfe95,0xfe75,0xf46d,0xf308,0xf38a,0xfdd3,0xfe96,0xfe96,0xac6e,0x5a68,0x834b,0xfe95,0x93ed,0x0,0x0,0x20,0xe71c,0xdefb,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x861,0xffdf,0xdefb,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x905,0x2c58,0x3dff,0x35ff,0x4dff,0xee76,0xfe75,0xfe76,0xfe77,0xfe97,0xf54d,0xf3a0,0xf3a0,0xf3a0,0xf52b,0xfe96,0xfe75,0xfeb6,0xf38a,0xf080,0xf0c0,0xf080,0xf1c3,0xfe13,0xfe96,0xfed6,0xfeb6,0xff37,0xd572,0x820,0x0,0x0,0x20,0xe71c,0xdefb,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x861,0xffdf,0xdefb,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x11c9,0x359f,0x3dff,0x3ddf,0x3dff,0x2d3d,0xb5d6,0xfe95,0xf655,0xfe95,0xf612,0xf3a0,0xf380,0xf3a0,0xf3a0,0xf380,0xf5d0,0xfeb6,0xfe14,0xf141,0xf100,0xf120,0xf120,0xf0c0,0xf4ae,0xfed6,0xf634,0xfe96,0xee14,0x2923,0x0,0x0,0x0,0x20,0xe71c,0xdefb,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x861,0xffdf,0xdefb,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x967,0x3ddf,0x3dbf,0x3dff,0x34fc,0x124c,0x42,0x2103,0xee34,0xfe95,0xf696,0xf58f,0xf380,0xf3a0,0xf3a0,0xf3a0,0xf380,0xf56d,0xfeb7,0xfe13,0xf141,0xf100,0xf120,0xf120,0xf0c0,0xf48e,0xf6b6,0xfeb6,0xee34,0x41a5,0x0,0x0,0x0,0x0,0x20,0xe71c,0xdefb,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x861,0xffdf,0xdefb,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x21,0x34fb,0x3ddf,0x3dff,0x2c16,0x41,0x0,0x0,0x0,0x5a68,0xfeb6,0xfe96,0xf5f2,0xf3a0,0xf380,0xf3a0,0xf3a0,0xf380,0xf5d0,0xfe96,0xfeb6,0xf36a,0xf080,0xf0c0,0xf080,0xf1a2,0xfdf3,0xfef7,0xd592,0x3144,0x0,0x0,0x0,0x0,0x0,0x20,0xe71c,0xdefb,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x861,0xffdf,0xdefb,0x20,0x0,0x0,0x0,0x0,0x0,0x20,0x0,0x1a8e,0x3e1f,0x3ddf,0x2c79,0x0,0x0,0x0,0x0,0x0,0x0,0x5a68,0xf655,0xfef7,0xf54d,0xeba0,0xf380,0xf3a0,0xf52b,0xfe96,0xfe75,0xfe75,0xf655,0xf42c,0xf2a6,0xf369,0xfe14,0xfeb6,0x93ed,0x1061,0x0,0x0,0x0,0x0,0x0,0x0,0x20,0xe71c,0xdefb,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x861,0xffdf,0xdefb,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x2cba,0x3dff,0x35bf,0x906,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x3144,0xbcd0,0xfeb6,0xfe74,0xfdd0,0xfe12,0xfe96,0xfe75,0xfe75,0xfe95,0xfe96,0xff17,0xff17,0xf6b6,0xacaf,0x3964,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x20,0xe71c,0xdefb,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x861,0xffdf,0xdefb,0x20,0x0,0x0,0x0,0x0,0x0,0x11a9,0x23d5,0x35bf,0x3dff,0x2c37,0x0,0x0,0x0,0x0,0x0,0x8c4,0x2c17,0x8e4,0x0,0x0,0x41a5,0x93ed,0xddf4,0xf676,0xf676,0xf675,0xf655,0xee34,0xee14,0xc4f0,0x72c9,0x2903,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x20,0xe71c,0xdefb,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x861,0xffdf,0xdefb,0x20,0x0,0x0,0x0,0xc4,0x2c57,0x3dff,0x3dff,0x359f,0x3e5f,0x1acf,0x0,0x0,0x0,0x0,0x83,0x2cdb,0x3e3f,0x2cdb,0x8a3,0x0,0x0,0x0,0x800,0x3330,0x561f,0x55ff,0x32ad,0x1860,0x10a2,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x20,0xe71c,0xdefb,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x861,0xffdf,0xdefb,0x20,0x0,0x0,0xc4,0x353d,0x3dff,0x3dbf,0x3ddf,0x357e,0x353d,0x11ea,0x0,0x20,0x0,0x83,0x2cfb,0x3dff,0x359e,0x3dff,0x2cfb,0x83,0x0,0x21,0x0,0x122c,0x35ff,0x35ff,0x12cf,0x0,0x0,0x0,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x20,0xe71c,0xdefb,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x861,0xffdf,0xdefb,0x20,0x0,0x0,0x2c79,0x3dff,0x3dbf,0x355d,0x126d,0xa4,0x21,0x0,0x0,0x0,0x83,0x2cdb,0x3dff,0x359f,0x3dbf,0x359f,0x3dff,0x2cdb,0x83,0x0,0x0,0x122c,0x3dff,0x3d9f,0x3d9f,0x34fb,0x1b31,0x62,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x20,0xe71c,0xdefb,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x861,0xffdf,0xdefb,0x21,0x0,0x122c,0x3dff,0x3ddf,0x351c,0xa3,0x0,0x0,0x0,0x0,0x0,0x83,0x2cdb,0x3dff,0x35bf,0x3ddf,0x35bf,0x3ddf,0x35bf,0x3dff,0x2cda,0x83,0x0,0x124d,0x3e5f,0x3dff,0x3dff,0x3ddf,0x3e1f,0x351c,0x8e4,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x20,0xe71c,0xdefb,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x861,0xffdf,0xdefb,0x20,0x0,0x2c79,0x3dff,0x3dbf,0x11a9,0x0,0x20,0x0,0x0,0x0,0x20,0x2cdb,0x3e1f,0x3ddf,0x353c,0x355d,0x3ddf,0x355d,0x353c,0x3ddf,0x3e1f,0x2cdb,0x0,0x988,0x2c58,0x2c16,0x2cda,0x3ddf,0x3dbf,0x3dff,0x2cdb,0x21,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x20,0xe71c,0xdefb,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x861,0xffdf,0xdefb,0x0,0x62,0x357e,0x3dff,0x2cba,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1a6d,0x3e1f,0x2cdb,0x905,0x2cda,0x3e1f,0x2cda,0x905,0x34fb,0x3e1f,0x1a6d,0x0,0x0,0x0,0x0,0x0,0x968,0x351c,0x3dbf,0x3e1f,0x1af0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x20,0xe71c,0xdefb,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x861,0xffdf,0xdefb,0x0,0xe5,0x359f,0x3e1f,0x23f6,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x11ea,0xa4,0x0,0x351c,0x3dff,0x351c,0x0,0xc4,0x11ea,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x947,0x35bf,0x3ddf,0x34fb,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x20,0xe71c,0xdefb,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x861,0xffdf,0xdefb,0x0,0xc4,0x359f,0x3dff,0x2c58,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x41,0x34fb,0x3dff,0x34fb,0x41,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x2c57,0x3dff,0x357e,0xc4,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x20,0xe71c,0xdefb,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x861,0xffdf,0xdefb,0x0,0x41,0x355d,0x3ddf,0x355d,0x21,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x21,0x34fb,0x3dff,0x34fb,0x21,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x23f6,0x3e1f,0x359e,0x905,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x20,0xe71c,0xdefb,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x861,0xffdf,0xdefb,0x20,0x0,0x2416,0x3dff,0x3ddf,0x1aae,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x21,0x34fb,0x3dff,0x34fb,0x21,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x41,0x353c,0x3ddf,0x357e,0x62,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x20,0xe71c,0xdefb,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x861,0xffdf,0xdefb,0x21,0x0,0x11a9,0x3dff,0x35bf,0x35bf,0x124d,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x21,0x34fb,0x3dff,0x34fb,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x2352,0x3dff,0x3dff,0x2c16,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x20,0xe71c,0xdefb,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x861,0xffdf,0xdefb,0x20,0x0,0x0,0x1b32,0x3e3f,0x359f,0x3dff,0x23f6,0x120b,0x926,0x8e5,0x8e5,0x8e5,0x41,0x0,0x21,0x34fb,0x3dff,0x351c,0x906,0x8e5,0x8e5,0x8e5,0x8e5,0x8e5,0x8e5,0x8e5,0x11ca,0x2c37,0x3ddf,0x35bf,0x3dff,0x988,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x20,0xe71c,0xdefb,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x861,0xffdf,0xdedb,0x20,0x0,0x0,0x0,0x23b4,0x3e1f,0x3ddf,0x3dff,0x3ddf,0x359f,0x357e,0x357e,0x359f,0x967,0x0,0x0,0x2c99,0x3dff,0x359e,0x357e,0x357e,0x357e,0x357e,0x357e,0x357e,0x357e,0x357e,0x3ddf,0x3dff,0x3ddf,0x3e1f,0x1af0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x20,0xdefb,0xdefb,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x861,0xffdf,0xe73c,0x841,0x0,0x0,0x0,0x0,0x126d,0x34fb,0x3ddf,0x3e1f,0x3e1f,0x3e1f,0x3e1f,0x3e3f,0x988,0x0,0x0,0x120b,0x3dff,0x3e1f,0x3e1f,0x3e1f,0x3e1f,0x3e1f,0x3e1f,0x3e1f,0x3e1f,0x3e1f,0x3e1f,0x3dff,0x355d,0x126d,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x20,0xef5d,0xdefb,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x861,0xf79e,0xffff,0x18e3,0x0,0x0,0x0,0x0,0x0,0x21,0x11ca,0x1b10,0x2372,0x2373,0x2373,0x2373,0x8e4,0x0,0x0,0x0,0x989,0x2352,0x2373,0x2373,0x2373,0x2373,0x2373,0x2373,0x2373,0x2373,0x1b31,0x122c,0x62,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x2104,0xffff,0xd6ba,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xbdd7,0xffff,0x5aeb,0x0,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x20,0x0,0x630c,0xffff,0xb596,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x528a,0xffff,0xef5d,0x2945,0x0,0x0,0x0,0x0,0x0,0x20,0x20,0x20,0x20,0x20,0x20,0x0,0x0,0x0,0x0,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x2945,0xef5d,0xffff,0x5aeb,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xb5b6,0xffff,0xef5d,0x5acb,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x5acb,0xef5d,0xffff,0xb596,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1082,0xc638,0xffff,0xffff,0xdefb,0xad55,0x9cd3,0x9cd3,0x9cd3,0x9cd3,0x9cd3,0x9cd3,0x9cd3,0x9cd3,0x9cd3,0x9cd3,0x9cd3,0x9cd3,0x9cd3,0x9cd3,0x9cd3,0x9cd3,0x9cd3,0x9cd3,0x9cd3,0x9cd3,0x9cd3,0x9cd3,0x9cd3,0x9cd3,0x9cd3,0x9cd3,0x9cd3,0x9cd3,0x9cd3,0x9cd3,0x9cd3,0x9cd3,0x9cd3,0x9cd3,0xad75,0xdefb,0xffff,0xffff,0xc618,0x861,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x20,0x7bef,0xe73c,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xe73c,0x7bef,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x841,0x3186,0x4228,0x4a49,0x4a49,0x4a49,0x4a49,0x4a49,0x4a49,0x4a49,0x4a49,0x4a49,0x4a49,0x4a49,0x4a49,0x4a49,0x4a49,0x4a49,0x4a49,0x4a49,0x4a49,0x4a49,0x4a49,0x4a49,0x4a49,0x4a49,0x4a49,0x4a49,0x4a49,0x4a49,0x4a49,0x4a49,0x4a49,0x4a49,0x4a49,0x4a49,0x4a49,0x4228,0x3186,0x841,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x10a2,0x841,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x10a2,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x3186,0xad75,0xce59,0x9cd3,0x18c3,0x0,0xe71c,0x5acb,0x0,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x18e3,0xef5d,0x31a6,0x0,0x0,0x0,0x841,0x8430,0xc638,0xb5b6,0x4a49,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x2945,0x18e3,0x0,0x0,0x0,0x2965,0xffff,0xb5b6,0x6b4d,0xdefb,0xbdd7,0x0,0xef7d,0x630c,0x0,0x0,0x10a2,0x2104,0x0,0x0,0x20,0x1082,0x0,0x0,0x1082,0x20,0x0,0x20,0x18e3,0x2104,0xf7be,0x39c7,0x0,0x0,0x0,0xbdf7,0xef7d,0x738e,0xa514,0xffdf,0x2945,0x0,0x18c3,0x2945,0x0,0x0,0x20,0x861,0x0,0x2124,0x0,0x0,0x10a2,0x0,0x0,0x0,0x10a2,0x0,0x0,0x2124,0x18e3,0x0,0x0,0xa514,0xd6ba,0xe73c,0x630c,0x0,0x0,0x9cd3,0xdefb,0x0,0x0,0x1082,0x2945,0x0,0xef5d,0x630c,0x0,0x7bef,0xf79e,0xf79e,0xbdd7,0x0,0x39e7,0xef7d,0x861,0x1082,0xef7d,0x31a6,0x1082,0xdedb,0xf79e,0xc638,0xf7be,0x31a6,0x0,0x0,0x39c7,0xffff,0x31a6,0x0,0x0,0x31a6,0x0,0x8410,0xe73c,0xdefb,0xbdd7,0x0,0x4a49,0xe73c,0xb596,0xffdf,0xc618,0x20,0xd69a,0x8410,0x0,0x52aa,0xe71c,0x2124,0xbdf7,0xdedb,0xe73c,0x6b4d,0x861,0xffff,0x73ae,0x2965,0x10a2,0x0,0x0,0xbdf7,0xad55,0x0,0x841,0x0,0x0,0x20,0xef7d,0x52aa,0x18c3,0xffff,0x52aa,0x1082,0xffdf,0x738e,0x3186,0xffff,0x1082,0x10a2,0xffff,0x2965,0x8430,0xf79e,0x861,0x6b6d,0xffff,0x3186,0x0,0x0,0x5aeb,0xffdf,0x861,0x0,0x20,0x0,0x0,0x4a69,0x31a6,0x630c,0xffff,0x18e3,0x4228,0xffff,0x4a49,0x2965,0xffff,0x2945,0x7bcf,0xe71c,0x0,0xb596,0xad75,0x0,0x630c,0x18e3,0xbdf7,0xce59,0x0,0x5aeb,0xdedb,0xdefb,0x52aa,0x0,0x0,0xb596,0xc618,0x0,0x0,0x20,0x2124,0x20,0xef7d,0x4a49,0x4208,0xffdf,0x0,0x0,0xb596,0xa514,0x31a6,0xf7be,0x20,0x861,0xf7be,0x3186,0xad55,0xad55,0x0,0x10a2,0xf7be,0x31a6,0x0,0x0,0x4a69,0xffff,0x18c3,0x0,0x0,0x2124,0x20,0x5aeb,0xbdd7,0xa514,0xf79e,0x2104,0x4228,0xf7be,0x0,0x841,0xf7be,0x39e7,0x18c3,0xf7be,0x4228,0xe73c,0x4a49,0x0,0x9cd3,0xad55,0xc638,0xc618,0x1082,0x5aeb,0x861,0xad75,0xe71c,0x0,0x0,0x52aa,0xffff,0x5aeb,0x861,0x9cd3,0xdedb,0x20,0xf79e,0x6b4d,0x18c3,0xffff,0x5aeb,0x10a2,0xffdf,0x738e,0x2945,0xffff,0x2965,0x5acb,0xffff,0x2945,0x8430,0xf79e,0x1082,0x738e,0xffff,0x31a6,0x0,0x0,0x841,0xef7d,0xad75,0x10a2,0x4a69,0xf7be,0x4a69,0xffdf,0x6b6d,0x3186,0xffff,0x2965,0x4a49,0xffdf,0x841,0x1082,0xffdf,0x4a49,0x0,0xbdd7,0xf7be,0xd69a,0x0,0x630c,0xffff,0x841,0x9cf3,0xdedb,0x73ae,0xbdd7,0xe73c,0xe71c,0x632c,0x0,0x0,0x0,0x7bef,0xf79e,0xef7d,0xe73c,0x4a49,0x0,0xa514,0xf79e,0x861,0x738e,0xf79e,0xf79e,0xb5b6,0x841,0x20,0xc618,0xf7be,0xad75,0xe73c,0x31a6,0x1082,0xd6ba,0xf79e,0xb5b6,0xe73c,0x31a6,0x0,0x20,0x0,0x39c7,0xdedb,0xef7d,0xf7be,0x8c71,0x0,0x9cf3,0xef5d,0xa514,0xd69a,0xa534,0x4228,0xe73c,0x20,0x861,0xef5d,0x4228,0x0,0x5acb,0xffff,0x7bef,0x0,0x2945,0xdedb,0xd69a,0x9cf3,0xef5d,0x20,0x0,0x2104,0x10a2,0x0,0x0,0x0,0x0,0x0,0x861,0x2104,0x0,0x0,0x0,0x0,0x18e3,0x20,0x0,0x1082,0x18e3,0x0,0x0,0x0,0x0,0x18e3,0x0,0x841,0x20,0x0,0x20,0x18e3,0x0,0x841,0x0,0x0,0x0,0x0,0x0,0x0,0x18e3,0x1082,0x0,0x0,0x0,0x2104,0x20,0x0,0x1082,0x0,0x861,0x0,0x0,0x861,0x0,0x0,0x0,0x841,0x0,0x0,0x0,0x861,0x2104,0x0,0x861,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x2945,0x2945,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x18e3,0xf7be,0xf7be,0x18e3,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x73ae,0xe71c,0xef5d,0x738e,0x0,0x861,0x7bcf,0x52aa,0xa514,0x7bcf,0x0,0x841,0x7bcf,0x52aa,0xa514,0x7bcf,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xd69a,0x6b6d,0x7bcf,0xd69a,0x0,0x10a2,0xffff,0xd6ba,0x8c71,0xffff,0x7bef,0x20,0xffff,0xd6ba,0x8c71,0xffff,0x8410,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x2124,0xffff,0x5acb,0x632c,0xffff,0x2104,0x841,0xffdf,0x528a,0x0,0x94b2,0xd69a,0x841,0xf7be,0x528a,0x0,0x94b2,0xd6ba,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x20,0x0,0x738e,0xffff,0xe71c,0xe71c,0xffff,0x6b4d,0x0,0xffff,0x52aa,0x0,0x9cd3,0xd69a,0x841,0xffdf,0x52aa,0x0,0x94b2,0xd6ba,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xef5d,0x9cd3,0x0,0x0,0xa534,0xe73c,0x1082,0xffdf,0xd6ba,0x94b2,0xffff,0x73ae,0x0,0xffff,0xd6ba,0x94b2,0xffff,0x7bcf,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x861,0x8410,0x2124,0x0,0x0,0x2945,0x7bef,0x2104,0xe73c,0x7bef,0x9cf3,0x738e,0x0,0x1082,0xef5d,0x7bef,0x9cf3,0x738e,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1082,0xffff,0x4208,0x0,0x0,0x0,0x10a2,0xffff,0x4208,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x20,0x0,0x0,0x0,0x0,0x0,0x841,0x8410,0x2124,0x0,0x20,0x0,0x841,0x8410,0x2124,0x0,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xf800,0x0,0x7e0,0x0,0x1f,0x0,}; + + diff --git a/include/canvasClient.h b/include/canvasClient.h deleted file mode 100644 index e8e0c0a..0000000 --- a/include/canvasClient.h +++ /dev/null @@ -1,106 +0,0 @@ -#ifndef __CANVAS_CLIENT_H__ -#define __CANVAS_CLIENT_H__ - -#include "Arduino.h" -#include "WiFiS3.h" - -#include "constants.h" -#include "helper.h" - -#include "widgets/canvas.h" -#include "compressor.h" - -#include "stdint.h" - -class CanvasClient { - - constexpr static unsigned CLIENT_BUFFER_LEN = 4096; - constexpr static unsigned ROW_BUFFER_LEN = 512; - - constexpr static unsigned MAX_SSID_LEN = 64; - constexpr static unsigned MAX_PASS_LEN = 64; - - constexpr static unsigned IP_LEN = 15; - - struct client_buffer_t { - - uint8_t bytes[CLIENT_BUFFER_LEN]; - unsigned size = 0; - unsigned totalSent = 0; - - bool has_space(unsigned insertsize) { - - return (size + insertsize) <= CLIENT_BUFFER_LEN; - } - - void append(const uint8_t *insertbytes, unsigned insertsize) { - - memcpy(&bytes[size], insertbytes, insertsize); - size += insertsize; - } - - bool flush(WiFiClient *client) { - - if (size == 0) { - return true; - } - - unsigned sent = client->write(bytes, size); - if (sent != size) { - return false; - } - totalSent += sent; - - size = 0; - return true; - } - }; - - union row_buffer_t { - uint16_t color[ROW_BUFFER_LEN]; - uint8_t code[ROW_BUFFER_LEN]; - }; - - static client_buffer_t client_buffer; - static row_buffer_t rowbuf; - static Compressor compressor; - - Canvas *canvas; - - char ssid[MAX_SSID_LEN]; - char pass[MAX_PASS_LEN]; - - char serverIP[IP_LEN]; - uint16_t serverPort; - - WiFiClient client; - -public: - - enum ConnectionStatus { - NO_MODULE, - NO_CONNECTION, - CONNECTION - }; - - CanvasClient(Canvas *canvas); - - void setSSID(const char SSID[]); - void setPass(const char PASS[]); - void setServer(const char serverIp[], const uint16_t port); - - ConnectionStatus connect(uint16_t maxAttempt); - void disconnect(); - - void loadCanvas(uint8_t id, Compressor *compressed); - void saveCanvas(uint8_t id, Compressor *compressed); - -private: - -}; - -void handleConnection(); -void transmitCanvas(); -void loadCanvas(); - -#endif diff --git a/include/compressor.h b/include/compressor.h deleted file mode 100644 index c882499..0000000 --- a/include/compressor.h +++ /dev/null @@ -1,160 +0,0 @@ -#ifndef __COMPRESSOR_H__ -#define __COMPRESSOR_H__ - -#include "Arduino.h" -#include "WiFiS3.h" - -#include "constants.h" -#include "helper.h" - -#include "stdint.h" - -struct segment_t { - uint16_t code: 4; - uint16_t size: 11; - uint16_t flag: 1; //todo -}; - -struct count_info_t { - uint16_t segmentCount: 6; - uint16_t pixelCount: 10; -}; - -static_assert(sizeof(segment_t) == sizeof(uint16_t)); -static_assert(sizeof(count_info_t) == sizeof(uint16_t)); - -template -class Compressor { - - segment_t segments[MAX_SEGMENTS]; - count_info_t segmentInfo; - -public: - - unsigned compress(uint8_t *codes, unsigned count); - unsigned uncompress(uint8_t *codes); - - bool pushSegment(uint16_t segment); - - void clear(); - - unsigned getPrefixSize() const; - unsigned getSegmentCount() const; - - template - void transfer(Compressor *other); - - const uint16_t *getRawSegmentAr() const; - -private: - -}; - -template -unsigned Compressor::compress(uint8_t *codes, unsigned count) { - - unsigned finished = 0; - - for (unsigned l = 0, r; l < count; l = r) { - for (r = 1 + l; r <= count; ++r) { - if (r == count || codes[l] != codes[r]) { - break; - } - } - - if (++finished > MAX_SEGMENTS) { - - segmentInfo.pixelCount = l; - segmentInfo.segmentCount = finished - 1; - - return l; - } - - segments[finished - 1].code = codes[l]; - segments[finished - 1].size = r - l; - } - - segmentInfo.pixelCount = count; - segmentInfo.segmentCount = finished; - - return count; -} - -template -unsigned Compressor::uncompress(uint8_t *codes) { - - const unsigned segmentCount = segmentInfo.segmentCount; - const unsigned pixelCount = segmentInfo.pixelCount; - - if (segmentCount == 0) { - return 0; - } - - for (unsigned s = 0, idx = 0; s < segmentCount; ++s) { - - uint8_t code = segments[s].code; - unsigned size = segments[s].size; - - while (size--) { - codes[idx++] = code; - } - } - - return pixelCount; -} - -template -bool Compressor::pushSegment(uint16_t segment) { - - uint8_t segmentCount = segmentInfo.segmentCount; - uint16_t pixelCount = segmentInfo.pixelCount; - - if (segmentCount >= MAX_SEGMENTS) { - return false; - } - - *(uint16_t *)&segments[segmentCount] = segment; - - pixelCount += segments[segmentCount].size; - segmentCount += 1; - - return true; -} - -template -void Compressor::clear() { - - segmentInfo.segmentCount = 0; - segmentInfo.pixelCount = 0; -} - -template -unsigned Compressor::getPrefixSize() const { - return segmentInfo.pixelCount; -} - -template -unsigned Compressor::getSegmentCount() const { - return segmentInfo.segmentCount; -} - -template -template -void Compressor::transfer(Compressor *other) { - - segmentInfo.pixelCount = other->getPrefixSize(); - segmentInfo.segmentCount = other->getSegmentCount(); - - for (unsigned s = 0; s < other->getSegmentCount(); ++s) { - segments[s] = other->getRawSegmentAr()[s]; - } - - // memcpy(segments, other->getRawSegmentAr(), sizeof(uint16_t) * segmentInfo.segmentCount); -} - -template -const uint16_t *Compressor::getRawSegmentAr() const { - return (const uint16_t *)segments; -} - -#endif diff --git a/include/constants.h b/include/constants.h index ec05bdc..6273aca 100644 --- a/include/constants.h +++ b/include/constants.h @@ -15,100 +15,67 @@ constexpr uint16_t WHITE = 0xFFFF; constexpr uint16_t GRAY = 0x520A; constexpr uint16_t BLACK = 0x0000; -constexpr unsigned DISPLAY_WIDTH = 320; -constexpr unsigned DISPLAY_HEIGHT = 480; +constexpr uint16_t blend_color(uint16_t color1, uint16_t color2, unsigned d) { + + uint32_t b1 = (color1 >> 0) & 0x1F; + uint32_t b2 = (color2 >> 0) & 0x1F; + + uint32_t g1 = (color1 >> 5) & 0x3F; + uint32_t g2 = (color2 >> 5) & 0x3F; + + uint32_t r1 = (color1 >> 11) & 0x1F; + uint32_t r2 = (color2 >> 11) & 0x1F; + + uint32_t b = ((b2 * d) + (b1 * (256 - d))) / 256; + uint32_t g = ((g2 * d) + (g1 * (256 - d))) / 256; + uint32_t r = ((r2 * d) + (r1 * (256 - d))) / 256; + + return (r << 11) | (g << 5) | (b << 0); +} + +constexpr uint16_t code_2_color(uint8_t code) { + + switch(code) { + case 0: return RED; + case 1: return GREEN; + case 2: return BLUE; + case 3: return CYAN; + case 4: return MAGENTA; + case 5: return YELLOW; + case 6: return WHITE; + case 7: return GRAY; + case 8: return BLACK; + } +} + +constexpr uint8_t color_2_code(uint16_t color) { + + switch(color) { + case RED: return 0; + case GREEN: return 1; + case BLUE: return 2; + case CYAN: return 3; + case MAGENTA: return 4; + case YELLOW: return 5; + case WHITE: return 6; + case GRAY: return 7; + case BLACK: return 8; + } +} + // touch constants constexpr unsigned PRESSURE_LEFT = 10; constexpr unsigned PRESSURE_RIGHT = 1400; -const int XP = 8; -const int XM = A2; -const int YP = A3; -const int YM = 9; - -// UNO R4 MINIMA -const int XBEGIN = 177; -const int XEND = 863; -const int YBEGIN = 121; -const int YEND = 950; +constexpr int XP = 8; +constexpr int XM = A2; +constexpr int YP = A3; +constexpr int YM = 9; // application constants -constexpr unsigned CANVAS_X = 4; -constexpr unsigned CANVAS_Y = 10; - -constexpr unsigned CANVAS_W = 312; -constexpr unsigned CANVAS_H = 332; - -constexpr unsigned CANVAS_BUFFER_W = 32; -constexpr unsigned CANVAS_BUFFER_H = 32; - -constexpr unsigned CANVAS_BUFFER_MAX_SEGMENTS = 18; -constexpr unsigned CLIENT_BUFFER_MAX_SEGMENTS = 105; - - -// constexpr unsigned COLOR_SELECTOR_X = 40; -// constexpr unsigned COLOR_SELECTOR_Y = CANVAS_Y + CANVAS_H + 30; -constexpr unsigned COLOR_SELECTOR_X = 12; -constexpr unsigned COLOR_SELECTOR_Y = CANVAS_Y + CANVAS_H + 7; - -constexpr unsigned THICKNESS_SELECTOR_X = 145; -constexpr unsigned THICKNESS_SELECTOR_Y = COLOR_SELECTOR_Y - 3; - - -const unsigned LOAD_X = THICKNESS_SELECTOR_X; -const unsigned LOAD_Y = COLOR_SELECTOR_Y + 35; - -const unsigned LOAD_W = 72; -const unsigned LOAD_H = 24; - -const uint16_t LOAD_C = BLUE; - - -const unsigned SAVE_X = LOAD_X; -const unsigned SAVE_Y = LOAD_Y + 32; - -const unsigned SAVE_W = LOAD_W; -const unsigned SAVE_H = LOAD_H; - -const uint16_t SAVE_C = GREEN; - - -const unsigned CLEAR_X = LOAD_X + LOAD_W + 4; -const unsigned CLEAR_Y = LOAD_Y; - -const unsigned CLEAR_W = SAVE_W; -const unsigned CLEAR_H = SAVE_H; - -const uint16_t CLEAR_C = RED; - - -const unsigned INFO_X = CLEAR_X; -const unsigned INFO_Y = SAVE_Y; - -const unsigned INFO_W = SAVE_W; -const unsigned INFO_H = SAVE_H; - -const uint16_t INFO_C = CYAN; - -const unsigned CONNECT_X = LOAD_X; -const unsigned CONNECT_Y = SAVE_Y + 32; - -const unsigned CONNECT_W = 4 + (SAVE_W * 2); -const unsigned CONNECT_H = SAVE_H; - -const uint16_t CONNECT_C = WHITE; - - -const unsigned NUM_SLOTS = 6; - -const unsigned SLOT_MENU_X = COLOR_SELECTOR_X + 20; -const unsigned SLOT_MENU_Y = COLOR_SELECTOR_Y + 20; - -const unsigned SLOT_MENU_W = SAVE_W * 3; -const unsigned SLOT_MENU_H = (SAVE_H * 9) / 2; - +constexpr unsigned MAX_WIFI_RETRY = 2; #endif \ No newline at end of file diff --git a/include/helper.h b/include/helper.h deleted file mode 100644 index b44fb48..0000000 --- a/include/helper.h +++ /dev/null @@ -1,8 +0,0 @@ -#include "stdint.h" - -uint16_t code2color(uint8_t code); -uint8_t color2code(uint16_t clr); - -bool inRange(unsigned value, unsigned lo, unsigned hi); - -uint32_t distance(uint32_t x0, uint32_t y0, uint32_t x1, uint32_t y1); diff --git a/include/touch.h b/include/touch.h deleted file mode 100644 index fce687b..0000000 --- a/include/touch.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef __TOUCH_H__ -#define __TOUCH_H__ - -void toDisplayMode(); -void convertTouchCoors(unsigned tx, unsigned ty, unsigned *xptr, unsigned *yptr); -void getTouchCoors(unsigned *xptr, unsigned *yptr); - -#endif diff --git a/include/touchscreen_driver.h b/include/touchscreen_driver.h new file mode 100644 index 0000000..c1c6ff3 --- /dev/null +++ b/include/touchscreen_driver.h @@ -0,0 +1,168 @@ +#ifndef __ARDUINO_WIFI_TFT_LCD_CANVAS_APP_TOUCHSCREEN_DRIVER_H__ +#define __ARDUINO_WIFI_TFT_LCD_CANVAS_APP_TOUCHSCREEN_DRIVER_H__ + +#include "Arduino.h" +#include "TouchScreen.h" + +class Touchscreen { + + // UNO R4 MINIMA + constexpr static unsigned XBEGIN = 177; + constexpr static unsigned XEND = 863; + constexpr static unsigned YBEGIN = 121; + constexpr static unsigned YEND = 950; + + TouchScreen ts; + TSPoint p; + + int xp; + int yp; + int xm; + int ym; + + unsigned pressure_lo {10}; + unsigned pressure_hi {1400}; + + unsigned width {320}; + unsigned height {480}; + + + bool is_pressed {false}; + bool press_available {false}; + bool release_available {false}; + + unsigned press_x {0}; + unsigned press_y {0}; + + unsigned release_x {0}; + unsigned release_y {0}; + + unsigned cur_x {0}; + unsigned cur_y {0}; + +public: + + Touchscreen() = delete; + + Touchscreen(int xp, int yp, int xm, int ym) + : xp {xp} + , yp {yp} + , xm {xm} + , ym {ym} + , ts(xp, yp, xm, ym, 300) + {} + + void set_dimensions(unsigned w, unsigned h) { + width = w; + height = h; + } + + void set_pressure(unsigned plo, unsigned phi) { + pressure_lo = plo; + pressure_hi = phi; + } + + bool get_press(unsigned *x, unsigned *y) { + + if (!press_available) { + return false; + } + + press_available = false; + + *x = press_x; + *y = press_y; + + return true; + } + + bool get_release(unsigned *x, unsigned *y) { + + if (!release_available) { + return false; + } + + release_available = false; + + *x = release_x; + *y = release_y; + + return true; + } + + bool get_stylus_position(unsigned *x, unsigned *y) { + + if (!is_pressed) { + return false; + } + + *x = cur_x; + *y = cur_y; + + return true; + } + + void read_screen() { + + unsigned x, y; + bool flag {false}; + + p = ts.getPoint(); + if (pressure_lo <= p.z && p.z <= pressure_hi) { + + x = p.x, y = p.y; + convert(&x, &y); + + flag = true; + } + + if (!flag && is_pressed) { // new release + + is_pressed = false; + release_available = true; + + release_x = press_x; + release_y = press_y; + } + else if (flag) { + if (is_pressed) { // slide (should be ignored) + + release_available = false; + press_available = false; + } + else { // new press + + is_pressed = true; + press_available = true; + + press_x = x; + press_y = y; + } + + cur_x = x; + cur_y = y; + } + + reset(); + } + +private: + + void reset() { + pinMode(xp, OUTPUT); + pinMode(yp, OUTPUT); + pinMode(xm, OUTPUT); + pinMode(ym, OUTPUT); + } + + void convert(unsigned *x, unsigned *y) { + + *x = constrain(*x, XBEGIN, XEND); + *y = constrain(*y, YBEGIN, YEND); + + *x = map(*x, XBEGIN, XEND, 0, width - 1); + *y = map(*y, YBEGIN, YEND, height - 1, 0); + } +}; + +#endif diff --git a/include/widgets/app.h b/include/widgets/app.h new file mode 100644 index 0000000..b504b73 --- /dev/null +++ b/include/widgets/app.h @@ -0,0 +1,110 @@ +#ifndef __ARDUINO_WIFI_TFT_LCD_CANVAS_APP_WIDGETS_APP_H__ +#define __ARDUINO_WIFI_TFT_LCD_CANVAS_APP_WIDGETS_APP_H__ + +#include "Adafruit_GFX.h" +#include "MCUFRIEND_kbv.h" + +#include "vector" +#include "set" + +#include "widget.h" +#include "frame.h" + +class View; + +class App : public BasicWidget, public DrawableWidget { + +protected: + +#ifdef READ_PIXEL_ENABLED + using display_t = MCUFRIEND_kbv; +#else + using display_t = Adafruit_GFX; +#endif + + display_t *display {nullptr}; + + std::vector views; + View *active_view {nullptr}; + + RingQueue event_queue; + RingQueue dirty_widgets; + +public: + + static App *create(MCUFRIEND_kbv *displayPtr); + + App *add_view(View *child); + + App *make_active_view(View *child); + View *get_active_view() const; + + RingQueueInterface *get_event_queue(); + App *push_event(const InteractiveWidget::callback_event_t &event); + + App *execute_event_logic(); + App *collect_dirty_widgets(); + App *update_dirty_widgets(); + + // BasicWidget overrides + + BasicWidget *get_parent() override; + + unsigned get_x() const override; + unsigned get_y() const override; + + unsigned get_absolute_x() const override; + unsigned get_absolute_y() const override; + + unsigned get_width() const override; + unsigned get_height() const override; + + bool get_dirty() const override; + bool get_visibility_changed() const override; + + void set_dirty() override; + void set_visibility_changed() override; + + void draw() override; + void clear() override; + + bool get_intersection(unsigned x, unsigned y) const override; + bool get_intersection(BasicWidget *other) const override; + + bool propagate_press(unsigned x, unsigned y) override; + bool propagate_release(unsigned x, unsigned y) override; + + bool get_visibility() const override; + void set_visibility(bool new_visibility) override; + + // Drawable overrides + + App *set_at(unsigned x, unsigned y, uint16_t color) override; + uint16_t get_at(unsigned x, unsigned y) const override; + + App *draw_line(unsigned x0, unsigned y0, unsigned x1, unsigned y1, uint16_t color) override; + + App *draw_rect(unsigned x0, unsigned y0, unsigned w, unsigned h, uint16_t color) override; + App *fill_rect(unsigned x0, unsigned y0, unsigned w, unsigned h, uint16_t color) override; + + App *draw_round_rect(unsigned x, unsigned y, unsigned w, unsigned h, unsigned r, uint16_t color) override; + App *fill_round_rect(unsigned x, unsigned y, unsigned w, unsigned h, unsigned r, uint16_t color) override; + + App *draw_circle(unsigned x, unsigned y, unsigned r, uint16_t color) override; + App *fill_circle(unsigned x, unsigned y, unsigned r, uint16_t color) override; + + App *get_text_bounds(const char *text, unsigned text_size, unsigned x, unsigned y, int16_t *x1, int16_t *y1, uint16_t *w, uint16_t *h) override; + + App *set_font(const GFXfont *f); + + App *print(const char *text, unsigned x, unsigned y, unsigned text_size, uint16_t fg_color) override; + App *print_opaque(const char *text, unsigned x, unsigned y, unsigned text_size, uint16_t fg_color, uint16_t bg_color) override; + + App *draw_rgb_bitmap(unsigned x, unsigned y, const uint16_t *data, unsigned width, unsigned height); + +protected: + + App(MCUFRIEND_kbv *display); +}; + +#endif diff --git a/include/widgets/bitmap.h b/include/widgets/bitmap.h new file mode 100644 index 0000000..aba0b86 --- /dev/null +++ b/include/widgets/bitmap.h @@ -0,0 +1,102 @@ +#ifndef __ARDUINO_WIFI_TFT_LCD_CANVAS_APP_WIDGETS_BITMAP_H__ +#define __ARDUINO_WIFI_TFT_LCD_CANVAS_APP_WIDGETS_BITMAP_H__ + +#include "widget.h" +#include "frame.h" + +class Bitmap : public BasicWidget, public InteractiveWidget { + +protected: + + constexpr static unsigned DEBOUNCE_THRESH = 150; + + Frame *parent {nullptr}; + + bool dirty {false}; + bool visibility_changed {false}; + + bool visible {true}; + bool pressed {false}; + bool enabled {true}; + + unsigned widget_x {0}; + unsigned widget_y {0}; + + unsigned widget_absolute_x {0}; + unsigned widget_absolute_y {0}; + + unsigned widget_w {0}; + unsigned widget_h {0}; + + unsigned last_press_epoch {0}; + + const uint16_t *data; + + callback_t on_press {nullptr}; + callback_t on_release {nullptr}; + + unsigned *args; + + RingQueueInterface *event_queue; + +public: + + static Bitmap *create(Frame *parent, const uint16_t *data, unsigned x, unsigned y, unsigned width, unsigned height); + + // BasicWidget overrides + + Frame *get_parent(); + + unsigned get_x() const override; + unsigned get_y() const override; + + unsigned get_absolute_x() const override; + unsigned get_absolute_y() const override; + + unsigned get_width() const override; + unsigned get_height() const override; + + bool get_dirty() const override; + bool get_visibility_changed() const override; + + void set_dirty() override; + void set_visibility_changed() override; + + void draw() override; + void clear() override; + + bool get_intersection(unsigned x, unsigned y) const override; + bool get_intersection(BasicWidget *other) const override; + + bool propagate_press(unsigned x, unsigned y) override; + bool propagate_release(unsigned x, unsigned y) override; + + bool get_visibility() const override; + void set_visibility(bool new_visibility) override; + + // InteractiveWidget overrides + + Bitmap *set_onpress(callback_t callback) override; + Bitmap *reset_onpress() override; + + Bitmap *set_onrelease(callback_t callback) override; + Bitmap *reset_onrelease() override; + + Bitmap *set_event_queue(RingQueueInterface *new_event_queue) override; + Bitmap *reset_event_queue() override; + + Bitmap *set_args(unsigned *new_args) override; + Bitmap *reset_args() override; + unsigned *get_args() override; + + bool is_pressed() const override; + + Bitmap *set_interactable(bool new_state) override; + bool get_interactable() const override; + +protected: + + Bitmap(Frame *parent, const uint16_t *data, unsigned x, unsigned y, unsigned width, unsigned height); +}; + +#endif \ No newline at end of file diff --git a/include/widgets/button.h b/include/widgets/button.h index 650f2d3..4726cad 100644 --- a/include/widgets/button.h +++ b/include/widgets/button.h @@ -1,37 +1,197 @@ -#ifndef __WIDGETS_BUTTON_H__ -#define __WIDGETS_BUTTON_H__ +#ifndef __ARDUINO_WIFI_TFT_LCD_CANVAS_APP_WIDGETS_BUTTON_H__ +#define __ARDUINO_WIFI_TFT_LCD_CANVAS_APP_WIDGETS_BUTTON_H__ #include "widget.h" +#include "frame.h" -class Button : Widget { +class ButtonStyle { - MCUFRIEND_kbv *tft; +protected: - unsigned x; - unsigned y; + constexpr static unsigned DEFAULT_TEXT_SIZE = 3; - unsigned w; - unsigned h; + constexpr static unsigned DEFAULT_BORDER_RADIUS = 4; + constexpr static unsigned DEFAULT_BORDER_W = 2; + constexpr static uint16_t DEFAULT_BORDER_COLOR = blend_color(WHITE, GRAY, 100); - uint16_t color; + constexpr static uint16_t DEFAULT_BG_COLOR = BLACK; + constexpr static uint16_t DEFAULT_FG_COLOR = WHITE; - char *msg; +public: + + enum HorizontalAlignment { + CENTER_ALIGN = 0, + LEFT_ALIGN = 1, + RIGHT_ALIGN = 2 + }; + + enum VerticalAlignment { + MIDDLE_ALIGN = 0, + TOP_ALIGN = 1, + BOTTOM_ALIGN = 2 + }; + + HorizontalAlignment h_align {HorizontalAlignment::CENTER_ALIGN}; + VerticalAlignment v_align {VerticalAlignment::MIDDLE_ALIGN}; + unsigned text_size {DEFAULT_TEXT_SIZE}; + + unsigned border_radius {DEFAULT_BORDER_RADIUS}; + unsigned border_w {DEFAULT_BORDER_W}; + uint16_t border_color {DEFAULT_BORDER_COLOR}; + + uint16_t bg_color {DEFAULT_BG_COLOR}; + uint16_t fg_color {DEFAULT_FG_COLOR}; + + uint16_t pressed_bg_color {blend_color(DEFAULT_BG_COLOR, BLACK, 100)}; + uint16_t pressed_fg_color {blend_color(DEFAULT_FG_COLOR, BLACK, 100)}; + uint16_t pressed_border_color {blend_color(DEFAULT_BORDER_COLOR, BLACK, 100)}; + + ButtonStyle *set_horizontal_alignment(HorizontalAlignment new_h_align); + HorizontalAlignment get_horizontal_alignment() const; + + ButtonStyle *set_vertical_alignment(VerticalAlignment new_v_align); + VerticalAlignment get_vertical_alignment() const; + + ButtonStyle *set_text_size(unsigned new_text_size); + unsigned get_text_size() const; + + ButtonStyle *set_border_radius(unsigned new_border_radius); + unsigned get_border_radius() const; + + ButtonStyle *set_border_width(unsigned new_border_w); + unsigned get_border_width() const; + + ButtonStyle *set_border_color(uint16_t new_border_color); + uint16_t get_border_color() const; + + ButtonStyle *set_fg_color(uint16_t new_fg_color); + uint16_t get_fg_color() const; + + ButtonStyle *set_bg_color(uint16_t new_bg_color); + uint16_t get_bg_color() const; + + ButtonStyle *set_pressed_bg_color(uint16_t new_pressed_bg_color); + uint16_t get_pressed_bg_color() const; + + ButtonStyle *set_pressed_fg_color(uint16_t new_pressed_fg_color); + uint16_t get_pressed_fg_color() const; + + ButtonStyle *set_pressed_border_color(uint16_t new_pressed_border_color); + uint16_t get_pressed_border_color() const; +}; + +class Button : public BasicWidget, public InteractiveWidget { + +protected: + + constexpr static unsigned DEBOUNCE_THRESH = 200; + + constexpr static unsigned DEFAULT_WIDTH = 64; + constexpr static unsigned DEFAULT_HEIGHT = 32; + + // constexpr static unsigned DEFAULT_text_size = 2; + constexpr static uint16_t DEFAULT_BG_COLOR = BLACK; + constexpr static uint16_t DEFAULT_FG_COLOR = WHITE; + + Frame *parent {nullptr}; + + bool dirty {false}; + bool visibility_changed {false}; + + bool pressed {false}; + bool visible {true}; + bool enabled {true}; + + unsigned widget_x {0}; + unsigned widget_y {0}; + + unsigned widget_absolute_x {0}; + unsigned widget_absolute_y {0}; + + unsigned widget_w {0}; + unsigned widget_h {0}; + + String message; + + callback_t on_press {nullptr}; + callback_t on_release {nullptr}; + + unsigned *args {nullptr}; + + RingQueueInterface *event_queue; + + ButtonStyle style; + + unsigned last_press_epoch {0}; public: - Button(unsigned x, unsigned y, unsigned w, unsigned h, uint16_t color, char *msg, MCUFRIEND_kbv *tft); + Button() = delete; + + static Button *create(Frame *parent, unsigned x, unsigned y, unsigned width, unsigned height); + static Button *create(Frame *parent, unsigned x, unsigned y); + + Button *set_message(const char *messagePtr); + String get_message() const; + + ButtonStyle *get_style(); + + // BasicWidget overrides + + Frame *get_parent() override; + + unsigned get_x() const override; + unsigned get_y() const override; + + unsigned get_absolute_x() const override; + unsigned get_absolute_y() const override; + + unsigned get_width() const override; + unsigned get_height() const override; + + bool get_dirty() const override; + bool get_visibility_changed() const override; + + void set_dirty() override; + void set_visibility_changed() override; + + void draw() override; + void clear() override; + + bool get_intersection(unsigned x, unsigned y) const override; + bool get_intersection(BasicWidget *other) const override; + + bool propagate_press(unsigned x, unsigned y) override; + bool propagate_release(unsigned x, unsigned y) override; + + bool get_visibility() const override; + void set_visibility(bool new_visibility) override; + + // InteractiveWidget overrides + + Button *set_onpress(callback_t callback) override; + Button *reset_onpress() override; + + Button *set_onrelease(callback_t callback) override; + Button *reset_onrelease() override; + + Button *set_event_queue(RingQueueInterface *new_event_queue) override; + Button *reset_event_queue() override; - void draw() const override; - void clear() const override; + Button *set_args(unsigned *new_args) override; + Button *reset_args() override; + unsigned *get_args() override; - bool update(unsigned touchX, unsigned touchY) override; + bool is_pressed() const override; - unsigned height() const override; - unsigned width() const override; + Button *set_interactable(bool new_state) override; + bool get_interactable() const override; -private: +protected: + Button(Frame *parent, unsigned x, unsigned y, unsigned width, unsigned height); + void render_text(); }; #endif diff --git a/include/widgets/buttonGrid.h b/include/widgets/buttonGrid.h deleted file mode 100644 index 6699391..0000000 --- a/include/widgets/buttonGrid.h +++ /dev/null @@ -1,55 +0,0 @@ -#ifndef __WIDGETS_BUTTON_GRID_H__ -#define __WIDGETS_BUTTON_GRID_H__ - -#include "constants.h" -#include "widget.h" - -class ButtonGrid : Widget { - - static constexpr char *msg = "SLOT"" "; - - static constexpr unsigned CLOSE_X = 3; - static constexpr unsigned CLOSE_Y = 3; - static constexpr unsigned CLOSE_W = 13; - - static constexpr unsigned HPAD = 23; - static constexpr unsigned VPAD = 8; - - static constexpr uint16_t BUTTON_C = WHITE; - - MCUFRIEND_kbv *tft; - - unsigned x; - unsigned y; - - unsigned w; - unsigned h; - - unsigned cc; - unsigned rc; - - unsigned button_w; - unsigned button_h; - - unsigned slot; - -public: - - ButtonGrid(unsigned x, unsigned y, unsigned w, unsigned h, unsigned cc, unsigned rc, unsigned button_w, unsigned button_h, MCUFRIEND_kbv *tft); - - void draw() const override; - void clear() const override; - - bool update(unsigned touch_x, unsigned touch_y) override; - - unsigned height() const override; - unsigned width() const override; - - unsigned getSlot() const; - -private: - - -}; - -#endif diff --git a/include/widgets/canvas.h b/include/widgets/canvas.h deleted file mode 100644 index 698da42..0000000 --- a/include/widgets/canvas.h +++ /dev/null @@ -1,48 +0,0 @@ -#ifndef __WIDGETS_CANVAS_H__ -#define __WIDGETS_CANVAS_H__ - -#include "widget.h" - -class Canvas : Widget { - - MCUFRIEND_kbv *tft; - - unsigned x; - unsigned y; - - unsigned w; - unsigned h; - - unsigned thickness; - uint16_t color; - -public: - - Canvas(unsigned x, unsigned y, unsigned w, unsigned h, MCUFRIEND_kbv *tft); - - void draw() const override; - void clear() const override; - - bool update(unsigned touch_x, unsigned touch_y) override; - - unsigned height() const override; - unsigned width() const override; - - unsigned heightInternal() const; - unsigned widthInternal() const; - - void setThickness(unsigned curThickness); - void setColor(uint16_t curColor); - - void clearDrawing(); - - uint16_t readPixel(unsigned r, unsigned c) const; - void writePixel(unsigned r, unsigned c, uint16_t color); - - -private: - - -}; - -#endif diff --git a/include/widgets/colorSelector.h b/include/widgets/colorSelector.h deleted file mode 100644 index 1a0471d..0000000 --- a/include/widgets/colorSelector.h +++ /dev/null @@ -1,49 +0,0 @@ -#ifndef __WIDGETS_COLOR_SELECTOR_H__ -#define __WIDGETS_COLOR_SELECTOR_H__ - -#include "widget.h" - -#include "constants.h" - -class ColorSelector : Widget { - - constexpr static uint16_t COLORS[3][3] { - {RED, GREEN, BLUE}, - {CYAN, MAGENTA, YELLOW}, - {WHITE, GRAY, BLACK} - }; - - constexpr static unsigned HPAD = 12; - constexpr static unsigned VPAD = 14; - constexpr static unsigned PAINT_RADIUS = 12; - - constexpr static unsigned HEIGHT = (6*PAINT_RADIUS) + (4*HPAD); - constexpr static unsigned WIDTH = (6*PAINT_RADIUS) + (4*VPAD); - - MCUFRIEND_kbv *tft; - - unsigned x; - unsigned y; - - uint16_t curColor; - -public: - - ColorSelector(unsigned x, unsigned y, MCUFRIEND_kbv *tft); - - void draw() const override; - void clear() const override; - - bool update(unsigned touch_x, unsigned touch_y) override; - - unsigned height() const; - unsigned width() const; - - uint16_t getColor() const; - -private: - - -}; - -#endif diff --git a/include/widgets/colorselector.h b/include/widgets/colorselector.h new file mode 100644 index 0000000..e32bdb3 --- /dev/null +++ b/include/widgets/colorselector.h @@ -0,0 +1,107 @@ +#ifndef __ARDUINO_WIFI_TFT_LCD_CANVAS_APP_WIDGETS_COLOR_SELECTOR_H__ +#define __ARDUINO_WIFI_TFT_LCD_CANVAS_APP_WIDGETS_COLOR_SELECTOR_H__ + +#include "widget.h" +#include "frame.h" + +class ColorSelector : public BasicWidget, public InteractiveWidget { + +protected: + + constexpr static unsigned PAINT_RADIUS = 12; + constexpr static unsigned H_PAD = 12; + constexpr static unsigned V_PAD = 12; + + constexpr static unsigned WIDTH = (H_PAD * (3 + 1)) + (PAINT_RADIUS * (3 * 2)); + constexpr static unsigned HEIGHT = (V_PAD * (3 + 1)) + (PAINT_RADIUS * (3 * 2)); + + Frame *parent {nullptr}; + + bool dirty {false}; + bool visibility_changed {false}; + + bool visible {true}; + bool pressed {false}; + bool enabled {true}; + + unsigned widget_x {0}; + unsigned widget_y {0}; + + unsigned widget_absolute_x {0}; + unsigned widget_absolute_y {0}; + + uint16_t colors[9] {}; + + callback_t on_press {nullptr}; + callback_t on_release {nullptr}; + + RingQueueInterface *event_queue {nullptr}; + + unsigned *args {nullptr}; + +public: + + ColorSelector() = delete; + + static ColorSelector *create(Frame *parent, unsigned x, unsigned y); + + ColorSelector *set_color(unsigned pos, uint16_t new_color); + uint16_t get_color(unsigned pos) const; + + // BasicWidget overrides + + Frame *get_parent() override; + + unsigned get_x() const override; + unsigned get_y() const override; + + unsigned get_absolute_x() const override; + unsigned get_absolute_y() const override; + + unsigned get_width() const override; + unsigned get_height() const override; + + bool get_dirty() const override; + bool get_visibility_changed() const override; + + void set_dirty() override; + void set_visibility_changed() override; + + void draw() override; + void clear() override; + + bool get_intersection(unsigned x, unsigned y) const override; + bool get_intersection(BasicWidget *other) const override; + + bool propagate_press(unsigned x, unsigned y) override; + bool propagate_release(unsigned x, unsigned y) override; + + bool get_visibility() const override; + void set_visibility(bool new_visibility) override; + + // InteractiveWidget overrides + + ColorSelector *set_onpress(callback_t callback) override; + ColorSelector *reset_onpress() override; + + ColorSelector *set_onrelease(callback_t callback) override; + ColorSelector *reset_onrelease() override; + + ColorSelector *set_event_queue(RingQueueInterface *new_event_queue) override; + ColorSelector *reset_event_queue() override; + + ColorSelector *set_args(unsigned *new_args) override; + ColorSelector *reset_args() override; + unsigned *get_args() override; + + bool is_pressed() const override; + + ColorSelector *set_interactable(bool new_state) override; + bool get_interactable() const override; + +protected: + + ColorSelector(Frame *parent, unsigned x, unsigned y); +}; + +#endif diff --git a/include/widgets/drawablecanvas.h b/include/widgets/drawablecanvas.h new file mode 100644 index 0000000..a126189 --- /dev/null +++ b/include/widgets/drawablecanvas.h @@ -0,0 +1,260 @@ +#ifndef __ARDUINO_WIFI_TFT_LCD_CANVAS_APP_WIDGETS_DRAWABLE_CANVAS_H__ +#define __ARDUINO_WIFI_TFT_LCD_CANVAS_APP_WIDGETS_DRAWABLE_CANVAS_H__ + +#include "widget.h" +#include "frame.h" + +#include "WiFiS3.h" +#include "cstring" + +class BufferedWiFiWriter { + +friend class DrawableCanvas; + +protected: + + constexpr static unsigned BUFFER_CAPACITY = 1024; + + WiFiClient *client; + uint8_t buf[BUFFER_CAPACITY]; + + unsigned used {0}; + bool flag {true}; + +public: + + signed connect(WiFiClient *ptr, const char *server_ip, const uint16_t server_port) { + client = ptr; + return client->connect(IPAddress(server_ip), server_port); + } + + void write(const uint8_t *bytes, unsigned len) { + + unsigned n; + + while (len > 0) { + + if (used == BUFFER_CAPACITY) { + flush(); + } + + n = min(len, BUFFER_CAPACITY - used); + for (const uint8_t *ptr = bytes; ptr != &bytes[n]; ++ptr) { + buf[used++] = *ptr; + } + len -= n; + bytes += n; + } + } + + void flush() { + + unsigned n; + + n = client->write(buf, used); + if (n != used) { + flag = false; + } + used = 0; + } + + void stop() { + flush(); + client->flush(); + client->stop(); + + client = nullptr; + } +}; + +class Compressor { + +public: + + struct segment_t { + uint16_t code: 4; + uint16_t size: 11; + uint16_t flag: 1; + }; + static_assert(sizeof(segment_t) == sizeof(uint16_t)); + + struct canvas_row_t { + uint16_t segment_count: 6; + uint16_t pixel_count: 10; + segment_t *segments; + }; + + static unsigned compress(canvas_row_t *row, unsigned max_segments, uint8_t *raw_data, unsigned raw_data_len) { + + unsigned finished = 0; + + for (unsigned l = 0, r; l < raw_data_len; l = r) { + for (r = 1 + l; r <= raw_data_len; ++r) { + if (r == raw_data_len || raw_data[l] != raw_data[r]) { + break; + } + } + + if (++finished > max_segments) { + row->pixel_count = l; + row->segment_count = finished - 1; + + return l; + } + + row->segments[finished - 1].code = raw_data[l]; + row->segments[finished - 1].size = r - l; + } + + row->pixel_count = raw_data_len; + row->segment_count = finished; + + return raw_data_len; + } + + static unsigned uncompress(canvas_row_t *row, uint8_t *raw_data, unsigned raw_data_len) { + + uint8_t code; + unsigned size; + + if (row->segment_count == 0) { + return 0; + } + + for (unsigned s = 0, idx = 0; s < row->segment_count; ++s) { + + code = row->segments[s].code; + size = row->segments[s].size; + + while (size--) { + raw_data[idx++] = code; + } + } + + return row->pixel_count; + } +}; + +class DrawableCanvas : public BasicWidget { + +public: + + constexpr static unsigned WIDTH = 312; + constexpr static unsigned HEIGHT = 312; + + constexpr static uint16_t DRAWABLE_W = WIDTH - 2; + constexpr static uint16_t DRAWABLE_H = HEIGHT - 2; + constexpr static unsigned MAX_INLINE_COMPRESSED_SEGMENTS = 7; + +protected: + + constexpr static unsigned BUFFER_WIDTH = 28; + constexpr static unsigned BUFFER_HEIGHT = 28; + + Frame *parent {nullptr}; + + bool dirty {false}; + bool visibility_changed {false}; + + bool visible {true}; + + unsigned widget_x {0}; + unsigned widget_y {0}; + + unsigned widget_absolute_x {0}; + unsigned widget_absolute_y {0}; + + uint16_t pen_color {0}; + unsigned pen_size {0}; + + char server_ip[16] {0}; + uint16_t server_port {0}; + + GFXcanvas1 drawing_buffer; + + Compressor::canvas_row_t compressed_rows[DRAWABLE_H]; + Compressor::canvas_row_t cur_row; + + InteractiveWidget::callback_t on_success {nullptr}; + InteractiveWidget::callback_t on_connection_failure {nullptr}; + InteractiveWidget::callback_t on_communication_failure {nullptr}; + + unsigned *args {nullptr}; + + RingQueueInterface *event_queue {nullptr}; + +public: + + DrawableCanvas() = delete; + + static DrawableCanvas *create(Frame *parent, unsigned x, unsigned y); + + DrawableCanvas *set_pen_color(uint16_t new_color); + uint16_t get_pen_color() const; + + DrawableCanvas *set_pen_size(uint16_t new_size); + unsigned get_pen_size() const; + + DrawableCanvas *set_server_addr(const char *new_server_ip, const uint16_t new_server_port); + + DrawableCanvas *draw_at(unsigned x, unsigned y); + DrawableCanvas *clear_canvas(); + + DrawableCanvas *set_success_callback(InteractiveWidget::callback_t cb); + DrawableCanvas *reset_success_callback(); + + DrawableCanvas *set_connection_failure_callback(InteractiveWidget::callback_t cb); + DrawableCanvas *reset_connection_failure_callback(); + + DrawableCanvas *set_communication_failure_callback(InteractiveWidget::callback_t cb); + DrawableCanvas *reset_communication_failure_callback(); + + DrawableCanvas *set_args(unsigned *new_args); + DrawableCanvas *reset_args(); + unsigned *get_args() const; + + DrawableCanvas *set_event_queue(RingQueueInterface *new_event_queue); + DrawableCanvas *reset_event_queue(); + + bool save_to_server(uint8_t slot); + bool load_from_server(uint8_t slot); + + // BasicWidget overrides + + Frame *get_parent() override; + + unsigned get_x() const override; + unsigned get_y() const override; + + unsigned get_absolute_x() const override; + unsigned get_absolute_y() const override; + + unsigned get_width() const override; + unsigned get_height() const override; + + bool get_dirty() const override; + bool get_visibility_changed() const override; + + void set_dirty() override; + void set_visibility_changed() override; + + void draw() override; + void clear() override; + + bool get_intersection(unsigned x, unsigned y) const override; + bool get_intersection(BasicWidget *other) const override; + + bool propagate_press(unsigned x, unsigned y) override; + bool propagate_release(unsigned x, unsigned y) override; + + bool get_visibility() const override; + void set_visibility(bool new_visibility) override; + +protected: + + DrawableCanvas(Frame *parent, unsigned x, unsigned y); + + void reset_compressed(); +}; + +#endif \ No newline at end of file diff --git a/include/widgets/frame.h b/include/widgets/frame.h new file mode 100644 index 0000000..9ea0f3c --- /dev/null +++ b/include/widgets/frame.h @@ -0,0 +1,26 @@ +#ifndef __ARDUINO_WIFI_TFT_LCD_CANVAS_APP_WIDGETS_FRAME_H__ +#define __ARDUINO_WIFI_TFT_LCD_CANVAS_APP_WIDGETS_FRAME_H__ + +#include "widget.h" + +class Frame : public BasicWidget, public DrawableWidget { + +public: + + virtual Frame *add_child(BasicWidget *child) = 0; + virtual unsigned get_children_count() const = 0; + + virtual Frame *send_front(BasicWidget *child, unsigned amt) = 0; + virtual Frame *send_back(BasicWidget *child, unsigned amt) = 0; + + virtual void collect_dirty_widgets(RingQueueInterface *dirty_widgets) = 0; //! this method should only be used by the app/view + + virtual void collect_overlapped_widgets(BasicWidget *dirty, BasicWidget *child, RingQueueInterface *overlapping_widgets) = 0; //! this method should only be used by the app/view + virtual void collect_underlapped_widgets(BasicWidget *child, RingQueueInterface *overlapping_widgets) = 0; //! this method should only be used by the app/view + + // BasicWidget overrides + + virtual bool is_frame() const override { return true; } +}; + +#endif \ No newline at end of file diff --git a/include/widgets/keyboard.h b/include/widgets/keyboard.h new file mode 100644 index 0000000..85f2744 --- /dev/null +++ b/include/widgets/keyboard.h @@ -0,0 +1,126 @@ +#ifndef __ARDUINO_WIFI_TFT_LCD_CANVAS_APP_WIDGETS_KEYBOARD_H__ +#define __ARDUINO_WIFI_TFT_LCD_CANVAS_APP_WIDGETS_KEYBOARD_H__ + +#include "widget.h" +#include "window.h" +#include "button.h" + +class Keyboard : public Window, public InteractiveWidget { + +public: + + constexpr static unsigned NUM_ROWS = 5; + constexpr static unsigned NUM_KEYS[NUM_ROWS] = { + 10, + 10, + 9, + 7, + 2 + }; + constexpr static unsigned NUM_KEYS_TOTAL = 38; + static_assert(NUM_KEYS[0] + NUM_KEYS[1] + NUM_KEYS[2] + NUM_KEYS[3] + NUM_KEYS[4] == NUM_KEYS_TOTAL); + static_assert(sizeof(NUM_KEYS) / sizeof(NUM_KEYS[0]) == NUM_ROWS); + + constexpr static const char *KEYBOARD_KEYS[3][5][10] { + { + {"1", "2", "3", "4", "5", "6", "7", "8", "9", "0"}, + {"q", "w", "e", "r", "t", "y", "u", "i", "o", "p"}, + {"a", "s", "d", "f", "g", "h", "j", "k", "l"}, + {"z", "x", "c", "v", "b", "n", "m"}, + {",", "."}, + }, + { + {"1", "2", "3", "4", "5", "6", "7", "8", "9", "0"}, + {"Q", "W", "E", "R", "T", "Y", "U", "I", "O", "P"}, + {"A", "S", "D", "F", "G", "H", "J", "K", "L"}, + {"Z", "X", "C", "V", "B", "N", "M"}, + {",", "."}, + }, + { + {"1", "2", "3", "4", "5", "6", "7", "8", "9", "0"}, + {"+", "=", "/", "_", "<", ">", "[", "]", "{", "}"}, + {"@", "#", "$", "%", "^", "&", "*", "(", ")"}, + {"-", "'", "\"", ":", ";", "!", "?"}, + {",", "."}, + } + }; + + struct keyboard_state_t { + uint16_t key; + union { + struct { + uint8_t backspace: 1; + uint8_t shift: 1; + uint8_t exit: 1; + }; + uint8_t special; + }; + }; + +protected: + + constexpr static unsigned DEBOUNCE_THRESH = 200; + + bool pressed {false}; + bool enabled {true}; + + Button *exit {nullptr}; + Button *shift {nullptr}; + Button *space {nullptr}; + Button *backspace {nullptr}; + + Button *keys[NUM_KEYS_TOTAL]; + + unsigned shift_i {0}; + + keyboard_state_t press_info {}; + keyboard_state_t release_info {}; + + callback_t on_press {nullptr}; + callback_t on_release {nullptr}; + + RingQueueInterface *event_queue {nullptr}; + + unsigned *args {nullptr}; + + unsigned last_press_epoch {0}; + +public: + + static Keyboard *create(Frame *parent); + + Keyboard *set_shift_index(unsigned new_shift_i); + unsigned get_shift_index() const; + + bool propagate_press(unsigned x, unsigned y) override; + bool propagate_release(unsigned x, unsigned y) override; + + // InteractiveWidget overrides + + Keyboard *set_onpress(callback_t callback) override; + Keyboard *reset_onpress() override; + + Keyboard *set_onrelease(callback_t callback) override; + Keyboard *reset_onrelease() override; + + Keyboard *set_event_queue(RingQueueInterface *new_event_queue) override; + Keyboard *reset_event_queue() override; + + Keyboard *set_args(unsigned *new_args) override; + Keyboard *reset_args() override; + unsigned *get_args() override; + + bool is_pressed() const; + + Keyboard *set_interactable(bool new_state) override; + bool get_interactable() const override; + + +protected: + + Keyboard(Frame *parent); + + void assign_keys(); +}; + +#endif diff --git a/include/widgets/label.h b/include/widgets/label.h new file mode 100644 index 0000000..641c853 --- /dev/null +++ b/include/widgets/label.h @@ -0,0 +1,150 @@ +#ifndef __ARDUINO_WIFI_TFT_LCD_CANVAS_APP_WIDGETS_LABEL_H__ +#define __ARDUINO_WIFI_TFT_LCD_CANVAS_APP_WIDGETS_LABEL_H__ + +#include "Arduino.h" + +#include "widget.h" +#include "frame.h" + +class LabelStyle { + +protected: + + constexpr static unsigned DEFAULT_TEXT_SIZE = 3; + + constexpr static unsigned DEFAULT_BORDER_RADIUS = 4; + constexpr static unsigned DEFAULT_BORDER_W = 2; + constexpr static uint16_t DEFAULT_BORDER_COLOR = blend_color(WHITE, GRAY, 100); + + constexpr static uint16_t DEFAULT_BG_COLOR = BLACK; + constexpr static uint16_t DEFAULT_FG_COLOR = WHITE; + +public: + + enum HorizontalAlignment { + CENTER_ALIGN = 0, + LEFT_ALIGN = 1, + RIGHT_ALIGN = 2 + }; + + enum VerticalAlignment { + MIDDLE_ALIGN = 0, + TOP_ALIGN = 1, + BOTTOM_ALIGN = 2 + }; + + HorizontalAlignment h_align {HorizontalAlignment::CENTER_ALIGN}; + VerticalAlignment v_align {VerticalAlignment::MIDDLE_ALIGN}; + unsigned text_size {DEFAULT_TEXT_SIZE}; + + unsigned border_radius {DEFAULT_BORDER_RADIUS}; + unsigned border_w {DEFAULT_BORDER_W}; + uint16_t border_color {DEFAULT_BORDER_COLOR}; + + uint16_t bg_color {DEFAULT_BG_COLOR}; + uint16_t fg_color {DEFAULT_FG_COLOR}; + + LabelStyle *set_horizontal_alignment(HorizontalAlignment new_h_align); + HorizontalAlignment get_horizontal_alignment() const; + + LabelStyle *set_vertical_alignment(VerticalAlignment new_v_align); + VerticalAlignment get_vertical_alignment() const; + + LabelStyle *set_text_size(unsigned new_text_size); + unsigned get_text_size() const; + + LabelStyle *set_border_radius(unsigned new_border_radius); + unsigned get_border_radius() const; + + LabelStyle *set_border_width(unsigned new_border_w); + unsigned get_border_width() const; + + LabelStyle *set_border_color(uint16_t new_border_color); + uint16_t get_border_color() const; + + LabelStyle *set_fg_color(uint16_t new_fg_color); + uint16_t get_fg_color() const; + + LabelStyle *set_bg_color(uint16_t new_bg_color); + uint16_t get_bg_color() const; +}; + +class Label : public BasicWidget { + +protected: + + Frame *parent {nullptr}; + + bool dirty {false}; + bool visibility_changed {false}; + + bool visible {true}; + + unsigned widget_x {0}; + unsigned widget_y {0}; + + unsigned widget_absolute_x {0}; + unsigned widget_absolute_y {0}; + + unsigned widget_w {0}; + unsigned widget_h {0}; + + String message {""}; + + LabelStyle style; + +public: + + static Label *create(Frame *parent, unsigned x, unsigned y, unsigned width, unsigned height); + + Label() = delete; + + Label *set_message(const char msg_ptr[]); + String get_message() const; + + unsigned get_message_len() const; + + Label *append_to_message(char ch); + Label *pop_from_message(); + + LabelStyle *get_style(); + + // BasicWidget overrides + + Frame *get_parent() override; + + unsigned get_x() const override; + unsigned get_y() const override; + + unsigned get_absolute_x() const override; + unsigned get_absolute_y() const override; + + unsigned get_width() const override; + unsigned get_height() const override; + + bool get_dirty() const override; + bool get_visibility_changed() const override; + + void set_dirty() override; + void set_visibility_changed() override; + + void draw() override; + void clear() override; + + bool get_intersection(unsigned x, unsigned y) const override; + bool get_intersection(BasicWidget *other) const override; + + bool propagate_press(unsigned x, unsigned y) override; + bool propagate_release(unsigned x, unsigned y) override; + + bool get_visibility() const override; + void set_visibility(bool new_visibility) override; + +protected: + + Label(Frame *parent, unsigned x, unsigned y, unsigned width, unsigned height); + + void render_text(); +}; + +#endif \ No newline at end of file diff --git a/include/widgets/pensizeselector.h b/include/widgets/pensizeselector.h new file mode 100644 index 0000000..cfda025 --- /dev/null +++ b/include/widgets/pensizeselector.h @@ -0,0 +1,114 @@ +#ifndef __ARDUINO_WIFI_TFT_LCD_CANVAS_APP_WIDGETS_PEN_SIZE_SELECTOR_H__ +#define __ARDUINO_WIFI_TFT_LCD_CANVAS_APP_WIDGETS_PEN_SIZE_SELECTOR_H__ + +#include "widget.h" +#include "frame.h" + +class PenSizeSelector : public BasicWidget, public InteractiveWidget { + +protected: + + constexpr static unsigned H_PAD = 17; + + constexpr static unsigned WIDTH = 8 * H_PAD; + constexpr static unsigned HEIGHT = 29; + + Frame *parent {nullptr}; + + bool dirty {false}; + bool visibility_changed {false}; + + bool visible {true}; + bool pressed {false}; + bool enabled {true}; + + unsigned widget_x {0}; + unsigned widget_y {0}; + + unsigned widget_absolute_x {0}; + unsigned widget_absolute_y {0}; + + uint16_t color {}; + uint16_t sizes[4] {}; + + unsigned active_size {0}; + + callback_t on_press {nullptr}; + callback_t on_release {nullptr}; + + RingQueueInterface *event_queue {nullptr}; + + unsigned *args {nullptr}; + +public: + + PenSizeSelector() = delete; + + static PenSizeSelector *create(Frame *parent, unsigned x, unsigned y); + + PenSizeSelector *set_size(unsigned pos, uint16_t new_size); + uint16_t get_size(unsigned pos) const; + + PenSizeSelector *set_active_size(unsigned pos); + uint16_t get_active_size() const; + + PenSizeSelector *set_color(uint16_t new_color); + uint16_t get_color() const; + + // BasicWidget overrides + + Frame *get_parent() override; + + unsigned get_x() const override; + unsigned get_y() const override; + + unsigned get_absolute_x() const override; + unsigned get_absolute_y() const override; + + unsigned get_width() const override; + unsigned get_height() const override; + + bool get_dirty() const override; + bool get_visibility_changed() const override; + + void set_dirty() override; + void set_visibility_changed() override; + + void draw() override; + void clear() override; + + bool get_intersection(unsigned x, unsigned y) const override; + bool get_intersection(BasicWidget *other) const override; + + bool propagate_press(unsigned x, unsigned y) override; + bool propagate_release(unsigned x, unsigned y) override; + + bool get_visibility() const override; + void set_visibility(bool new_visibility) override; + + // InteractiveWidget overrides + + PenSizeSelector *set_onpress(callback_t callback) override; + PenSizeSelector *reset_onpress() override; + + PenSizeSelector *set_onrelease(callback_t callback) override; + PenSizeSelector *reset_onrelease() override; + + PenSizeSelector *set_event_queue(RingQueueInterface *new_event_queue) override; + PenSizeSelector *reset_event_queue() override; + + PenSizeSelector *set_args(unsigned *new_args) override; + PenSizeSelector *reset_args() override; + unsigned *get_args() override; + + bool is_pressed() const override; + + PenSizeSelector *set_interactable(bool new_state) override; + bool get_interactable() const override; + +protected: + + PenSizeSelector(Frame *parent, unsigned x, unsigned y); +}; + +#endif diff --git a/include/widgets/textbox.h b/include/widgets/textbox.h new file mode 100644 index 0000000..59dd913 --- /dev/null +++ b/include/widgets/textbox.h @@ -0,0 +1,60 @@ +#ifndef __ARDUINO_WIFI_TFT_LCD_CANVAS_APP_WIDGETS_TEXTBOX_H__ +#define __ARDUINO_WIFI_TFT_LCD_CANVAS_APP_WIDGETS_TEXTBOX_H__ + +#include "label.h" + +class TextBox : public Label, public InteractiveWidget { + +protected: + + constexpr static unsigned DEBOUNCE_THRESH = 200; + + RingQueueInterface *event_queue; + + bool pressed {false}; + bool enabled {true}; + + unsigned *args {nullptr}; + + callback_t on_press {}; + callback_t on_release {}; + + unsigned last_press_epoch {0}; + +public: + + TextBox() = delete; + + static TextBox *create(Frame *parent, unsigned x, unsigned y, unsigned width, unsigned height); + + // Label overrides + + bool propagate_press(unsigned x, unsigned y) override; + bool propagate_release(unsigned x, unsigned y) override; + + // InteractiveWidget overrides + + TextBox *set_onpress(callback_t callback) override; + TextBox *reset_onpress() override; + + TextBox *set_onrelease(callback_t callback) override; + TextBox *reset_onrelease() override; + + TextBox *set_event_queue(RingQueueInterface *new_event_queue) override; + TextBox *reset_event_queue() override; + + TextBox *set_args(unsigned *new_args) override; + TextBox *reset_args() override; + unsigned *get_args() override; + + bool is_pressed() const override; + + TextBox *set_interactable(bool new_state) override; + bool get_interactable() const override; + +protected: + + TextBox(Frame *parent, unsigned x, unsigned y, unsigned width, unsigned height); +}; + +#endif diff --git a/include/widgets/thicknessSelector.h b/include/widgets/thicknessSelector.h deleted file mode 100644 index 40c31a3..0000000 --- a/include/widgets/thicknessSelector.h +++ /dev/null @@ -1,44 +0,0 @@ -#ifndef __WIDGETS_THICKNESS_SELECTOR_H__ -#define __WIDGETS_THICKNESS_SELECTOR_H__ - -#include "widget.h" - -class ThicknessSelector : Widget { - - static constexpr unsigned RADII[4] = {3, 5, 7, 9}; - static constexpr unsigned PAD = 17; - - static constexpr unsigned HEIGHT = 33; - static constexpr unsigned WIDTH = 8 * PAD; - - MCUFRIEND_kbv *tft; - - unsigned x; - unsigned y; - - uint16_t color; - unsigned curSelected; - -public: - - ThicknessSelector(unsigned x, unsigned y, MCUFRIEND_kbv *tft); - - void setColor(uint16_t clr); - - void draw() const override; - void clear() const override; - - bool update(unsigned touch_x, unsigned touch_y) override; - - unsigned height() const override; - unsigned width() const override; - - uint16_t getThickness() const; - -private: - - -}; - - -#endif diff --git a/include/widgets/view.h b/include/widgets/view.h new file mode 100644 index 0000000..66752cf --- /dev/null +++ b/include/widgets/view.h @@ -0,0 +1,98 @@ +#ifndef __ARDUINO_WIFI_TFT_LCD_CANVAS_APP_WIDGETS_VIEW_H__ +#define __ARDUINO_WIFI_TFT_LCD_CANVAS_APP_WIDGETS_VIEW_H__ + +#include "vector" + +#include "frame.h" +#include "app.h" + +class View : public Frame { + + friend class App; + +protected: + + App *app {nullptr}; + bool dirty {false}; + + std::vector children; + +public: + + View() = delete; + + static View *create(App *parent); + + // BasicWidget overrides + + App *get_parent() override; + + unsigned get_x() const override; + unsigned get_y() const override; + + unsigned get_absolute_x() const override; + unsigned get_absolute_y() const override; + + unsigned get_width() const override; + unsigned get_height() const override; + + bool get_dirty() const override; + bool get_visibility_changed() const override; + + void set_dirty() override; + void set_visibility_changed() override; + + void draw() override; + void clear() override; + + bool get_intersection(unsigned x, unsigned y) const override; + bool get_intersection(BasicWidget *other) const override; + + bool propagate_press(unsigned x, unsigned y) override; + bool propagate_release(unsigned x, unsigned y) override; + + bool get_visibility() const override; + void set_visibility(bool new_visibility) override; + + // Frame overrides + + View *set_at(unsigned x, unsigned y, uint16_t color) override; + uint16_t get_at(unsigned x, unsigned y) const override; + + View *draw_line(unsigned x0, unsigned y0, unsigned x1, unsigned y1, uint16_t color) override; + + View *draw_rect(unsigned x, unsigned y, unsigned w, unsigned h, uint16_t color) override; + View *fill_rect(unsigned x, unsigned y, unsigned w, unsigned h, uint16_t color) override; + + View *draw_round_rect(unsigned x, unsigned y, unsigned w, unsigned h, unsigned r, uint16_t color) override; + View *fill_round_rect(unsigned x, unsigned y, unsigned w, unsigned h, unsigned r, uint16_t color) override; + + View *draw_circle(unsigned x, unsigned y, unsigned r, uint16_t color) override; + View *fill_circle(unsigned x, unsigned y, unsigned r, uint16_t color) override; + + View *get_text_bounds(const char *text, unsigned text_size, unsigned x, unsigned y, int16_t *x1, int16_t *y1, uint16_t *w, uint16_t *h) override; + + View *print(const char *text, unsigned x, unsigned y, unsigned text_size, uint16_t fg_color) override; + View *print_opaque(const char *text, unsigned x, unsigned y, unsigned text_size, uint16_t fg_color, uint16_t bg_color) override; + + View *set_font(const GFXfont *f); + + View *draw_rgb_bitmap(unsigned x, unsigned y, const uint16_t *data, unsigned width, unsigned height); + + View *add_child(BasicWidget *child) override; + unsigned get_children_count() const override; + + View *send_front(BasicWidget *child, unsigned amt) override; + View *send_back(BasicWidget *child, unsigned amt) override; + + void collect_dirty_widgets(RingQueueInterface *dirty_widgets) override; + void collect_overlapped_widgets(BasicWidget *dirty, BasicWidget *child, RingQueueInterface *overlapping_widgets) override; + // void collect_intersecting_widgets(BasicWidget *dirty, BasicWidget *child, RingQueueInterface *overlapping_widgets) override; + void collect_underlapped_widgets(BasicWidget *child, RingQueueInterface *overlapping_widgets) override; + +protected: + + View(App *parent); +}; + +#endif diff --git a/include/widgets/widget.h b/include/widgets/widget.h index 8047cae..6d056b8 100644 --- a/include/widgets/widget.h +++ b/include/widgets/widget.h @@ -1,21 +1,165 @@ -#ifndef __WIDGETS_WIDGET_H__ -#define __WIDGETS_WIDGET_H__ +#ifndef __ARDUINO_WIFI_TFT_LCD_CANVAS_APP_WIDGETS_WIDGET_H__ +#define __ARDUINO_WIFI_TFT_LCD_CANVAS_APP_WIDGETS_WIDGET_H__ #include "Arduino.h" #include "Adafruit_GFX.h" -#include "MCUFRIEND_kbv.h" +#include "constants.h" -class Widget { +#include "functional" +#include "queue" + +#include "Fonts/PlusJakartaSans6pt7b.h" // size 1 +#include "Fonts/PlusJakartaSans9pt7b.h" // size 2 +#include "Fonts/PlusJakartaSans15pt7b.h" // size 3 +#include "Fonts/PlusJakartaSans21pt7b.h" // size 4 + +#define FUNCTION_PTR_CALLBACK +#define READ_PIXEL_ENABLED + +#define font_1 (&PlusJakartaSans_SemiBold6pt7b) +#define font_2 (&PlusJakartaSans_SemiBold9pt7b) +#define font_3 (&PlusJakartaSans_SemiBold15pt7b) +#define font_4 (&PlusJakartaSans_SemiBold21pt7b) + +template +class RingQueueInterface { + +public: + + virtual void push(const T &e) = 0; + virtual const T &front() = 0; + virtual void pop() = 0; + virtual unsigned get_size() const = 0; +}; + +template +class RingQueue : public RingQueueInterface { + +protected: + + T arr[CAPACITY]; + unsigned head = 0; + unsigned tail = 0; + unsigned size = 0; public: - virtual void draw() const; - virtual void clear() const; + void push(const T &e) override { + arr[head] = e; + (head += 1) %= CAPACITY; + ++size; + } + + const T &front() override { + return arr[tail]; + } + + void pop() override { + (tail += 1) %= CAPACITY; + --size; + } + + unsigned get_size() const override { + return size; + } +}; + +class BasicWidget { + +public: + + virtual BasicWidget *get_parent() = 0; + + virtual unsigned get_x() const = 0; + virtual unsigned get_y() const = 0; + + virtual unsigned get_absolute_x() const = 0; + virtual unsigned get_absolute_y() const = 0; + + virtual unsigned get_width() const = 0; + virtual unsigned get_height() const = 0; + + virtual bool get_dirty() const = 0; + virtual bool get_visibility_changed() const = 0; + + virtual void set_dirty() = 0; + virtual void set_visibility_changed() = 0; + + virtual void draw() = 0; + virtual void clear() = 0; + + virtual bool get_intersection(unsigned x, unsigned y) const = 0; + virtual bool get_intersection(BasicWidget *other) const = 0; + + virtual bool propagate_press(unsigned x, unsigned y) = 0; + virtual bool propagate_release(unsigned x, unsigned y) = 0; + + virtual bool get_visibility() const = 0; + virtual void set_visibility(bool new_visibility) = 0; + + virtual bool is_frame() const { return false; } +}; + +class InteractiveWidget { + +public: + +#ifdef FUNCTION_PTR_CALLBACK + using callback_t = void (*)(unsigned *); +#else + using callback_t = std::function; +#endif + + struct callback_event_t { + callback_t cb; + unsigned *args; + }; + + virtual InteractiveWidget *set_onpress(callback_t cb) = 0; + virtual InteractiveWidget *reset_onpress() = 0; + + virtual InteractiveWidget *set_onrelease(callback_t cb) = 0; + virtual InteractiveWidget *reset_onrelease() = 0; + + virtual InteractiveWidget *set_event_queue(RingQueueInterface *new_event_queue) = 0; + virtual InteractiveWidget *reset_event_queue() = 0; + + virtual InteractiveWidget *set_args(unsigned *new_args) = 0; + virtual InteractiveWidget *reset_args() = 0; + virtual unsigned *get_args() = 0; + + virtual bool is_pressed() const = 0; + + virtual InteractiveWidget *set_interactable(bool new_state) = 0; + virtual bool get_interactable() const = 0; +}; + +class DrawableWidget { + +public: + + virtual DrawableWidget *set_at(unsigned x, unsigned y, uint16_t color) = 0; + virtual uint16_t get_at(unsigned x, unsigned y) const = 0; + + virtual DrawableWidget *draw_line(unsigned x0, unsigned y0, unsigned x1, unsigned y1, uint16_t color) = 0; + + virtual DrawableWidget *draw_rect(unsigned x, unsigned y, unsigned w, unsigned h, uint16_t color) = 0; + virtual DrawableWidget *fill_rect(unsigned x, unsigned y, unsigned w, unsigned h, uint16_t color) = 0; + + virtual DrawableWidget *draw_round_rect(unsigned x, unsigned y, unsigned w, unsigned h, unsigned r, uint16_t color) = 0; + virtual DrawableWidget *fill_round_rect(unsigned x, unsigned y, unsigned w, unsigned h, unsigned r, uint16_t color) = 0; + + virtual DrawableWidget *draw_circle(unsigned x, unsigned y, unsigned r, uint16_t color) = 0; + virtual DrawableWidget *fill_circle(unsigned x, unsigned y, unsigned r, uint16_t color) = 0; + + virtual DrawableWidget *get_text_bounds(const char *text, unsigned text_size, unsigned x, unsigned y, int16_t *x1, int16_t *y1, uint16_t *w, uint16_t *h) = 0; + + virtual DrawableWidget *set_font(const GFXfont *f) = 0; - virtual bool update(unsigned touch_x, unsigned touch_y); + virtual DrawableWidget *print(const char *text, unsigned x, unsigned y, unsigned text_size, uint16_t fg_color) = 0; + virtual DrawableWidget *print_opaque(const char *text, unsigned x, unsigned y, unsigned text_size, uint16_t fg_color, uint16_t bg_color) = 0; - virtual unsigned height() const; - virtual unsigned width() const; + virtual DrawableWidget *draw_rgb_bitmap(unsigned x, unsigned y, const uint16_t *data, unsigned width, unsigned height) = 0; }; #endif diff --git a/include/widgets/window.h b/include/widgets/window.h new file mode 100644 index 0000000..843af8b --- /dev/null +++ b/include/widgets/window.h @@ -0,0 +1,146 @@ +#ifndef __ARDUINO_WIFI_TFT_LCD_CANVAS_APP_WIDGETS_WINDOW_H__ +#define __ARDUINO_WIFI_TFT_LCD_CANVAS_APP_WIDGETS_WINDOW_H__ + +#include "widget.h" +#include "frame.h" + +#include "vector" +#include "algorithm" + +class WindowStyle { + +protected: + + constexpr static uint16_t DEFAULT_BG_COLOR = BLACK; + constexpr static uint16_t DEFAULT_BORDER_COLOR = WHITE; + + constexpr static unsigned DEFAULT_BORDER_WIDTH = 1; + constexpr static unsigned DEFAULT_BORDER_RADIUS = 0; + +public: + + uint16_t bg_color {DEFAULT_BG_COLOR}; + uint16_t border_color {DEFAULT_BORDER_COLOR}; + + unsigned border_w {DEFAULT_BORDER_WIDTH}; + unsigned border_radius {DEFAULT_BORDER_RADIUS}; + + WindowStyle *set_bg_color(uint16_t new_color); + uint16_t get_bg_color() const; + + WindowStyle *set_border_color(uint16_t new_color); + uint16_t get_border_color() const; + + WindowStyle *set_border_width(unsigned new_border_width); + unsigned get_border_width() const; + + WindowStyle *set_border_radius(unsigned new_border_radius); + unsigned get_border_radius() const; +}; + +class Window : public Frame { + +protected: + + Frame *parent {nullptr}; + + bool dirty {false}; + bool visibility_changed {false}; + + bool visible {true}; + + unsigned widget_x {0}; + unsigned widget_y {0}; + + unsigned widget_absolute_x {0}; + unsigned widget_absolute_y {0}; + + unsigned widget_w {0}; + unsigned widget_h {0}; + + std::vector children; + + WindowStyle style; + +public: + + Window() = delete; + + static Window *create(Frame *parent, unsigned x, unsigned y, unsigned width, unsigned height); + + WindowStyle *get_style(); + + // BasicWidget overrides + + Frame *get_parent() override; + + unsigned get_x() const override; + unsigned get_y() const override; + + unsigned get_absolute_x() const override; + unsigned get_absolute_y() const override; + + unsigned get_width() const override; + unsigned get_height() const override; + + bool get_dirty() const override; + bool get_visibility_changed() const override; + + void set_dirty() override; + void set_visibility_changed() override; + + void draw() override; + void clear() override; + + bool get_intersection(unsigned x, unsigned y) const override; + bool get_intersection(BasicWidget *other) const override; + + bool propagate_press(unsigned x, unsigned y) override; + bool propagate_release(unsigned x, unsigned y) override; + + bool get_visibility() const override; + void set_visibility(bool new_visibility) override; + + // Frame overrides + + Window *set_at(unsigned x, unsigned y, uint16_t color) override; + uint16_t get_at(unsigned x, unsigned y) const override; + + Window *draw_line(unsigned x0, unsigned y0, unsigned x1, unsigned y1, uint16_t color) override; + + Window *draw_rect(unsigned x, unsigned y, unsigned w, unsigned h, uint16_t color) override; + Window *fill_rect(unsigned x, unsigned y, unsigned w, unsigned h, uint16_t color) override; + + Window *draw_round_rect(unsigned x, unsigned y, unsigned w, unsigned h, unsigned r, uint16_t color) override; + Window *fill_round_rect(unsigned x, unsigned y, unsigned w, unsigned h, unsigned r, uint16_t color) override; + + Window *draw_circle(unsigned x, unsigned y, unsigned r, uint16_t color) override; + Window *fill_circle(unsigned x, unsigned y, unsigned r, uint16_t codlor) override; + + Window *get_text_bounds(const char *text, unsigned text_size, unsigned x, unsigned y, int16_t *x1, int16_t *y1, uint16_t *w, uint16_t *h) override; + + Window *set_font(const GFXfont *f); + + Window *print(const char *text, unsigned x, unsigned y, unsigned text_size, uint16_t fg_color) override; + Window *print_opaque(const char *text, unsigned x, unsigned y, unsigned text_size, uint16_t fg_color, uint16_t bg_color) override; + + Window *draw_rgb_bitmap(unsigned x, unsigned y, const uint16_t *data, unsigned width, unsigned height); + + Window *add_child(BasicWidget *child) override; + unsigned get_children_count() const override; + + Window *send_front(BasicWidget *child, unsigned amt) override; + Window *send_back(BasicWidget *child, unsigned amt) override; + + void collect_dirty_widgets(RingQueueInterface *dirty_widgets) override; + void collect_overlapped_widgets(BasicWidget *dirty, BasicWidget *child, RingQueueInterface *overlapping_widgets) override; + // void collect_intersecting_widgets(BasicWidget *dirty, BasicWidget *child, RingQueueInterface *overlapping_widgets) override; + void collect_underlapped_widgets(BasicWidget *child, RingQueueInterface *overlapping_widgets) override; + + +protected: + + Window(Frame *parent, unsigned x, unsigned y, unsigned width, unsigned height); +}; + +#endif diff --git a/platformio.ini b/platformio.ini index 6f9583d..d9fd54c 100644 --- a/platformio.ini +++ b/platformio.ini @@ -9,11 +9,11 @@ ; https://docs.platformio.org/page/projectconf.html [env:uno_r4_wifi] -platform = renesas-ra +platform = https://github.com/platformio/platform-renesas-ra.git board = uno_r4_wifi framework = arduino lib_deps = adafruit/Adafruit GFX Library@^1.11.9 adafruit/Adafruit TouchScreen@^1.1.5 https://github.com/slviajero/MCUFRIEND_kbv.git - ; prenticedavid/MCUFRIEND_kbv +; build_type=debug diff --git a/src/canvasClient.cpp b/src/canvasClient.cpp deleted file mode 100644 index eda1caf..0000000 --- a/src/canvasClient.cpp +++ /dev/null @@ -1,181 +0,0 @@ -#include "canvasClient.h" - -CanvasClient::client_buffer_t CanvasClient::client_buffer; -CanvasClient::row_buffer_t CanvasClient::rowbuf; - -Compressor CanvasClient::compressor; - -CanvasClient::CanvasClient(Canvas *canvas) - : canvas {canvas} -{} - -void CanvasClient::setSSID(const char SSID[]) { - - strncpy(ssid, SSID, CanvasClient::MAX_SSID_LEN); -} - -void CanvasClient::setPass(const char PASS[]) { - - strncpy(pass, PASS, CanvasClient::MAX_PASS_LEN); -} - -void CanvasClient::setServer(const char serverIp[], const uint16_t port) { - - strncpy(serverIP, serverIp, IP_LEN); - serverPort = port; -} - -CanvasClient::ConnectionStatus CanvasClient::connect(uint16_t maxAttempt) { - - signed status = WL_IDLE_STATUS; - - if (WiFi.status() == WL_NO_MODULE) { - return NO_MODULE; - } - - while (maxAttempt--) { - - status = WiFi.begin(ssid, pass); - - delay(2500); - - if (status == WL_CONNECTED) { - return CONNECTION; - } - } - - return NO_CONNECTION; -} - -void CanvasClient::disconnect() { - - WiFi.end(); -} - -void CanvasClient::loadCanvas(uint8_t id, Compressor *compressed) { - - uint16_t imageHeight = canvas->heightInternal(); - uint16_t imageWidth = canvas->widthInternal(); - - if (!client.connect(IPAddress(serverIP), serverPort)) { - Serial.println("Connection Failed"); - return; - } - - client.write("\x02", 1); - client.write(&id, 1); - client.write((const char *)&imageHeight, sizeof(imageHeight)); - client.write((const char *)&imageWidth, sizeof(imageWidth)); - - client.flush(); - - for (unsigned row = 0; row < imageHeight; ++row) { - - while (!client.available()); - uint8_t mode = client.read(); - - if (mode == 0) { - - for (unsigned col = 0; col < imageWidth; ++col) { - - while (!client.available()); - rowbuf.code[col] = client.read(); - } - } - else { - - uint8_t lo, hi, code; - uint16_t segment, size; - - compressor.clear(); - for (unsigned s = 0, idx = 0; s < mode; ++s) { - - while (!client.available()); - lo = client.read(); - - while (!client.available()); - hi = client.read(); - - compressor.pushSegment(((uint16_t)hi << 8) | (uint16_t)lo); - - segment = ((uint16_t)hi << 8) | (uint16_t)lo; - code = ((segment_t *)&segment)->code; - size = ((segment_t *)&segment)->size; - - while (size--) { - rowbuf.code[idx++] = code; - } - } - } - - for (unsigned j = 0; j < imageWidth; ++j) { - canvas->writePixel(row, j, code2color(rowbuf.code[j])); - } - compressed[row].compress(rowbuf.code, imageWidth); - } - - client.stop(); -} - -void CanvasClient::saveCanvas(uint8_t id, Compressor *compressed) { - - uint16_t imageHeight = canvas->heightInternal(); - uint16_t imageWidth = canvas->widthInternal(); - - if (client.connect(IPAddress(serverIP), serverPort) == 0) { - Serial.println("Connection Failed"); - return; - } - - client_buffer.append((const uint8_t *)"\x01", 1); - client_buffer.append(&id, 1); - - client_buffer.append((const uint8_t *)&imageHeight, 2); - client_buffer.append((const uint8_t *)&imageWidth, 2); - - for (unsigned i = 0; i < imageHeight; ++i) { - - bool compressable; - - for (unsigned j = compressed[i].uncompress(rowbuf.code); j < imageWidth; ++j) { - rowbuf.code[j] = color2code(canvas->readPixel(i, j)); - } - compressable = compressor.compress(rowbuf.code, imageWidth); - - if (compressable) { - - uint8_t numSegments = compressor.getSegmentCount(); - unsigned size = numSegments * sizeof(uint16_t); - - if (!client_buffer.has_space(1 + size)) { - if (!client_buffer.flush(&client)) { - client.stop(); - Serial.println("error"); - return; - } - } - client_buffer.append(&numSegments, 1); - client_buffer.append((const uint8_t *)compressor.getRawSegmentAr(), size); - } - else { - - if (!client_buffer.has_space(1 + imageWidth)) { - if (!client_buffer.flush(&client)) { - client.stop(); - Serial.println("error"); - return; - } - } - client_buffer.append((const uint8_t *)"\x00", 1); - client_buffer.append(rowbuf.code, imageWidth); - } - } - - if (!client_buffer.flush(&client)) { - client.stop(); - Serial.println("error"); - return; - } - client.flush(); - client.stop(); -} diff --git a/src/helper.cpp b/src/helper.cpp deleted file mode 100644 index 9e723a2..0000000 --- a/src/helper.cpp +++ /dev/null @@ -1,64 +0,0 @@ -#include "helper.h" -#include "constants.h" - -uint16_t code2color(uint8_t code) { - - switch (code) { - - case 0: - return RED; - case 1: - return GREEN; - case 2: - return BLUE; - case 3: - return CYAN; - case 4: - return MAGENTA; - case 5: - return YELLOW; - case 6: - return WHITE; - case 7: - return GRAY; - case 8: - return BLACK; - } -} - -uint8_t color2code(uint16_t clr) { - - switch (clr) { - - case RED: - return 0; - case GREEN: - return 1; - case BLUE: - return 2; - case CYAN: - return 3; - case MAGENTA: - return 4; - case YELLOW: - return 5; - case WHITE: - return 6; - case GRAY: - return 7; - case BLACK: - return 8; - } -} - -bool inRange(unsigned value, unsigned lo, unsigned hi) { - return lo <= value && value <= hi; -} - -uint32_t distance(uint32_t x0, uint32_t y0, uint32_t x1, uint32_t y1) { - - uint32_t i = (x0 > x1) ? (x0 - x1) : (x1 - x0); - uint32_t j = (y0 > y1) ? (y0 - y1) : (y1 - y0); - - return sqrt(i*i + j*j); -} diff --git a/src/main.cpp b/src/main.cpp index b025610..7a71636 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,212 +1,1204 @@ #include "Arduino.h" +#include "WiFiS3.h" + #include "Adafruit_GFX.h" #include "MCUFRIEND_kbv.h" #include "constants.h" -#include "helper.h" -#include "arduino_secrets.h" +#include "bitmaps.h" -#include "touch.h" +#include "touchscreen_driver.h" -#include "widgets/canvas.h" -#include "widgets/colorSelector.h" -#include "widgets/thicknessSelector.h" -#include "widgets/buttonGrid.h" +#include "widgets/app.h" +#include "widgets/view.h" +#include "widgets/drawablecanvas.h" +#include "widgets/colorselector.h" +#include "widgets/pensizeselector.h" +#include "widgets/keyboard.h" +#include "widgets/window.h" #include "widgets/button.h" +#include "widgets/label.h" +#include "widgets/textbox.h" +#include "widgets/bitmap.h" -#include "compressor.h" +MCUFRIEND_kbv tft; -#include "canvasClient.h" +Touchscreen ts(XP, YP, XM, YM); +App *app; -MCUFRIEND_kbv tft; +// startup view -Canvas canvas(CANVAS_X, CANVAS_Y, CANVAS_W, CANVAS_H, &tft); -ColorSelector colorSelector(COLOR_SELECTOR_X, COLOR_SELECTOR_Y, &tft); -ThicknessSelector thicknessSelector(THICKNESS_SELECTOR_X, THICKNESS_SELECTOR_Y, &tft); -ButtonGrid slotSelector(SLOT_MENU_X, SLOT_MENU_Y, SLOT_MENU_W, SLOT_MENU_H, 2, 3, LOAD_W, LOAD_H, &tft); +View *startup_view; -Button loadButton(LOAD_X, LOAD_Y, LOAD_W, LOAD_H, LOAD_C, "LOAD", &tft); -Button saveButton(SAVE_X, SAVE_Y, SAVE_W, SAVE_H, SAVE_C, "SAVE", &tft); -Button clearButton(CLEAR_X, CLEAR_Y, CLEAR_W, CLEAR_H, CLEAR_C, "CLEAR", &tft); -Button infoButton(INFO_X, INFO_Y, INFO_W, INFO_H, INFO_C, "INFO", &tft); -Button connectButton(CONNECT_X, CONNECT_Y, CONNECT_W, CONNECT_H, CONNECT_C, "CONNECT", &tft); +Label *startup_title; -CanvasClient client(&canvas); +Window *apps_window; +Bitmap *canvas_app_icon; +Bitmap *settings_app_icon; +Bitmap *information_app_icon; -GFXcanvas1 canvasBuffer(CANVAS_BUFFER_W, CANVAS_BUFFER_H); +// main view -Compressor compressed[CANVAS_H - 2]; -uint8_t rawCode[CANVAS_W - 2] {}; +View *main_view; -void clearCompressedCanvas(); +Button *main_back_button; +Label *main_title; -void executeSlotSelection(CanvasClient *client, void (CanvasClient::*method)(uint8_t, Compressor *)); -void drawLowerWidgets(); +DrawableCanvas *canvas; -void setup(void) { +Window *tools_window; - // Use Serial Monitor for debugging - Serial.begin(9600); - tft.begin(0x9486); +ColorSelector *color_selector; +PenSizeSelector *size_selector; + +Button *save_button; +Button *load_button; + +Button *connection_button; +Button *information_button; + +Button *clear_button; + +Window *slot_selection_window; +Button *slot_exit_button; +Button *slot_buttons[6]; + +TextBox *communication_status_label; + +struct slot_button_args_t { + unsigned number; + Button *caller; +}; + +// connection view + +View *connection_view; + +Button *connection_back_button; +Label *connection_title; + +Window *connection_form_window; + +Label *ssid_label; +TextBox *ssid_box; + +Label *pass_label; +TextBox *pass_box; + +Label *addr_label; +TextBox *addr_box; + +Button *connect_button; +Label *status_label; + +Keyboard *keyboard; + +// information view + +View *information_view; + +Button *information_back_button; +Label *information_title; + +Window *information_form_window; + +Label *ssid_readonly_label; +Label *ssid_readonly_box; + +Label *ip_addr_label; +Label *ip_addr_box; + +Bitmap *dumblebots_qrcode; +Label *dumblebots_website_label; + +[[noreturn]] void err(const char msg[]); + + +// main view + +void switch_to_startup(unsigned *args); +void switch_to_connection(unsigned *args); +void switch_to_information(unsigned *args); +void switch_to_main(unsigned *args); + +void select_color_cb(unsigned *args); +void select_pen_size_cb(unsigned *args); + +void clear_button_cb(unsigned *args); - client.setSSID(SECRET_SSID); - client.setPass(SECRET_PASS); - client.setServer(SERVER_IP, 5005); - client.connect(8); +void open_slot_selection(unsigned *args); +void exit_slot_selection(unsigned *args); +void slot_selection_cb(unsigned *args); - tft.fillScreen(BLACK); +void server_connection_failure_cb(unsigned *args); +void server_communication_failure_cb(unsigned *args); +void server_success_cb(unsigned *args); - canvas.draw(); - drawLowerWidgets(); +// connection view - clearCompressedCanvas(); +void open_keyboard(unsigned *args); + +void ssid_box_edit_cb(unsigned *args); +void pass_box_edit_cb(unsigned *args); +void addr_box_edit_cb(unsigned *args); + +void connect_cb(unsigned *args); +void try_connect(unsigned *args); +bool verify_server(); + +// information view + +void init_startup_view() { + + startup_view = View::create(app); + if (startup_view == nullptr) { + err("Error while creating startup view"); + } + + startup_title = Label::create(startup_view, 30, 1, app->get_width() - 30 - 10, 27); + if (startup_title == nullptr) { + err("Error while creating startup title"); + } + + apps_window = Window::create(startup_view, 5, 30, app->get_width() - 10, app->get_height() - 45); + if (apps_window == nullptr) { + err("Error while creating apps window"); + } + + canvas_app_icon = Bitmap::create(apps_window, main_app_bmp2, 30, 30, 64, 92); + if (canvas_app_icon == nullptr) { + err("Error while creating canvas app icon"); + } + + settings_app_icon = Bitmap::create(apps_window, settings_app_bmp, canvas_app_icon->get_x() + canvas_app_icon->get_width() + 30, canvas_app_icon->get_y(), 64, 92); + if (settings_app_icon == nullptr) { + err("Error while creating settings app icon"); + } + + information_app_icon = Bitmap::create(apps_window, information_app_bmp, settings_app_icon->get_x() + settings_app_icon->get_width() + 30, settings_app_icon->get_y(), 64, 92); + if (information_app_icon == nullptr) { + err("Error while creating information app icon"); + } + + startup_title + ->set_message("Apps") + ->get_style() + ->set_text_size(2) + ->set_border_width(0) + ->set_border_radius(0); + + apps_window + ->get_style() + ->set_border_radius(3); + + canvas_app_icon + ->set_event_queue(app->get_event_queue()) + ->set_onrelease(switch_to_main); + + settings_app_icon + ->set_event_queue(app->get_event_queue()) + ->set_onrelease(switch_to_connection); + + information_app_icon + ->set_event_queue(app->get_event_queue()) + ->set_onrelease(switch_to_information); } -void loop(void) { +void init_main_view() { + + main_view = View::create(app); + if (main_view == nullptr) { + err("Error while creating main view"); + } + + main_back_button = Button::create(main_view, 3, 15 - 12, 24, 24); + if (main_back_button == nullptr) { + err("Error while creating main back button"); + } - unsigned widgetUpdateTime = 0; + main_title = Label::create(main_view, 30, 1, app->get_width() - 30 - 10, 27); + if (main_title == nullptr) { + err("Error while creating main title"); + } - widgetUpdateTime = 0; + canvas = DrawableCanvas::create(main_view, 4, 30); + if (canvas == nullptr) { + err("Error while creating canvas"); + } - unsigned x, y; - getTouchCoors(&x, &y); + tools_window = Window::create(main_view, 5, 345, app->get_width() - 10, app->get_height() - 345 - 5); + if (tools_window == nullptr) { + err("Error while creating tools window"); + } - { - const uint16_t thickness = thicknessSelector.getThickness(); - const uint16_t color = colorSelector.getColor(); - const uint8_t code = color2code(color); + color_selector = ColorSelector::create(tools_window, 2, 2); + if (color_selector == nullptr) { + err("Error while creating color selector"); + } - canvas.setThickness(thickness); - canvas.setColor(color); + size_selector = PenSizeSelector::create(tools_window, color_selector->get_x() + color_selector->get_width() + 18, 11); + if (size_selector == nullptr) { + err("Error while creating pen size selector"); + } - if (canvas.update(x, y)) { + save_button = Button::create(tools_window, color_selector->get_x() + color_selector->get_width() + 3, size_selector->get_y() + size_selector->get_height() + 3, 64, 30); + if (save_button == nullptr) { + err("Error while creating save button"); + } - const uint16_t canvasX = x - CANVAS_X - 1; - const uint16_t canvasY = y - CANVAS_Y - 1; + load_button = Button::create(tools_window, save_button->get_x() + save_button->get_width() + 3, save_button->get_y(), 64, 30); + if (load_button == nullptr) { + err("Error while creating load button"); + } - const uint16_t row_lo = canvasY - thickness; - const uint16_t row_hi = canvasY + thickness; + connection_button = Button::create(tools_window, color_selector->get_x() + color_selector->get_width() + 3, save_button->get_y() + save_button->get_height() + 3, 64, 30); + if (connection_button == nullptr) { + err("Error while creating connection button"); + } - const uint16_t col_lo = canvasX - thickness; - const uint16_t col_hi = canvasX + thickness; + information_button = Button::create(tools_window, connection_button->get_x() + connection_button->get_width() + 3, connection_button->get_y(), 64, 30); + if (information_button == nullptr) { + err("Error while creating information button"); + } - canvasBuffer.fillRect(0, 0, CANVAS_BUFFER_W, CANVAS_BUFFER_H, 0); - canvasBuffer.fillCircle(thickness, thickness, thickness, 1); + clear_button = Button::create(tools_window, load_button->get_x() + load_button->get_width() + 3, load_button->get_y(), 40, 3 + (30 * 2)); + if (clear_button == nullptr) { + err("Error while creating clear button"); + } - for (unsigned i = row_lo, col_end; i <= row_hi; ++i) { + slot_selection_window = Window::create(tools_window, 16, 16, 280, 100); + if (slot_selection_window == nullptr) { + err("Error while creating slot selection window"); + } - if (compressed[i].getPrefixSize()-1 < col_lo) { - continue; - } - compressed[i].uncompress(rawCode); + slot_exit_button = Button::create(slot_selection_window, 2, 2, 13, 13); + if (slot_exit_button == nullptr) { + err("Error while creating slot exit button"); + } - for (unsigned j = col_lo; j <= col_hi; ++j) { + for (unsigned c = 0, i = 0; c < 3; ++c) { + for (unsigned r = 0; r < 2; ++r, ++i) { + slot_buttons[i] = Button::create(slot_selection_window, (80 * c) + (5 * c) + 16, (34 * r) + (6 * r) + 16, 80, 32); + if (slot_buttons[i] == nullptr) { + err("Error while creating slot buttons"); + } + } + } - if (canvasBuffer.getPixel(j - col_lo, i - row_lo)) { - rawCode[j] = code; - col_end = j; - } - } + communication_status_label = TextBox::create(slot_selection_window, 14, 12, slot_selection_window->get_width() - 28, slot_selection_window->get_height() - 24); + if (communication_status_label == nullptr) { + err("Error while creating communication status label"); + } - compressed[i].compress(rawCode, col_end); + main_back_button + ->set_onrelease(switch_to_startup) + ->set_event_queue(app->get_event_queue()) + ->set_message("x") + ->get_style() + ->set_text_size(2) + ->set_bg_color(RED) + ->set_fg_color(BLACK) + ->set_pressed_bg_color(blend_color(RED, BLACK, 160)) + ->set_pressed_fg_color(WHITE) + ->set_border_width(0) + ->set_border_radius(14); + + main_title + ->set_message("Canvas App") + ->get_style() + ->set_text_size(2) + ->set_border_width(0) + ->set_border_radius(0); + + canvas + ->set_event_queue(app->get_event_queue()) + ->set_connection_failure_callback(server_connection_failure_cb) + ->set_communication_failure_callback(server_communication_failure_cb) + ->set_success_callback(server_success_cb); + + tools_window + ->get_style() + ->set_border_radius(3); + + color_selector + ->set_color(0, RED)->set_color(1, GREEN)->set_color(2, BLUE) + ->set_color(3, CYAN)->set_color(4, MAGENTA)->set_color(5, YELLOW) + ->set_color(6, WHITE)->set_color(7, GRAY)->set_color(8, BLACK) + ->set_event_queue(app->get_event_queue()) + ->set_onrelease(select_color_cb); + + size_selector + ->set_size(0, 3)->set_size(1, 5)->set_size(2, 7)->set_size(3, 9) + ->set_event_queue(app->get_event_queue()) + ->set_onrelease(select_pen_size_cb); + + save_button + ->set_message("Save") + ->set_args((unsigned *)save_button) + ->set_onrelease(open_slot_selection) + ->set_event_queue(app->get_event_queue()) + ->get_style() + ->set_text_size(2) + ->set_bg_color(GREEN) + ->set_pressed_bg_color(blend_color(GREEN, BLACK, 128)) + ->set_fg_color(BLACK) + ->set_pressed_fg_color(WHITE) + ->set_border_color(GREEN) + ->set_pressed_border_color(blend_color(GREEN, BLACK, 128)); + + load_button + ->set_message("Load") + ->set_args((unsigned *)load_button) + ->set_onrelease(open_slot_selection) + ->set_event_queue(app->get_event_queue()) + ->get_style() + ->set_text_size(2) + ->set_bg_color(blend_color(BLUE, CYAN, 64)) + ->set_pressed_bg_color(blend_color(BLUE, BLACK, 128)) + ->set_fg_color(BLACK) + ->set_pressed_fg_color(WHITE) + ->set_border_color(blend_color(BLUE, CYAN, 64)) + ->set_pressed_border_color(blend_color(BLUE, BLACK, 128)); + + connection_button + ->set_message("WiFi") + ->set_onrelease(switch_to_connection) + ->set_event_queue(app->get_event_queue()) + ->get_style() + ->set_text_size(2); + + information_button + ->set_message("Info") + ->set_onrelease(switch_to_information) + ->set_event_queue(app->get_event_queue()) + ->get_style() + ->set_text_size(2); + + clear_button + ->set_message("C") + ->set_onrelease(clear_button_cb) + ->set_event_queue(app->get_event_queue()) + ->get_style() + ->set_text_size(4) + ->set_bg_color(RED) + ->set_pressed_bg_color(blend_color(RED, BLACK, 160)) + ->set_fg_color(BLACK) + ->set_pressed_fg_color(WHITE) + ->set_border_color(RED) + ->set_pressed_border_color(blend_color(RED, BLACK, 160)) + ->set_border_radius(7); + + slot_selection_window + ->get_style() + ->set_border_radius(3); + + slot_exit_button + ->set_onrelease(exit_slot_selection) + ->set_event_queue(app->get_event_queue()) + ->get_style() + ->set_border_width(0) + ->set_border_radius(6) + ->set_bg_color(RED) + ->set_pressed_bg_color(blend_color(RED, BLACK, 160)); + + for (unsigned c = 0, i = 0; c < 3; ++c) { + for (unsigned r = 0; r < 2; ++r, ++i) { + + char buffer[] = "Slot ""\x00\x00"; + itoa((r * 3) + c + 1, &buffer[5], 10); + + slot_buttons[i] + ->set_message(buffer) + ->set_onrelease(slot_selection_cb) + ->set_event_queue(app->get_event_queue()) + ->get_style() + ->set_text_size(2) + ->set_border_width(0); + + unsigned *args = (unsigned *)new (std::nothrow) slot_button_args_t { + .number = (r * 3) + c + 1, + .caller = nullptr + }; + if (args == nullptr) { + err("Error while creatings args for slot buttons"); } + slot_buttons[i]->set_args(args); } } + slot_buttons[0]->get_style()->set_bg_color(blend_color(RED, YELLOW, 128))->set_pressed_bg_color(blend_color(blend_color(RED, YELLOW, 128), BLACK, 128)); + slot_buttons[2]->get_style()->set_bg_color(blend_color(GREEN, CYAN, 128))->set_pressed_bg_color(blend_color(blend_color(GREEN, CYAN, 128), BLACK, 128)); + slot_buttons[4]->get_style()->set_bg_color(blend_color(BLUE, MAGENTA, 128))->set_pressed_bg_color(blend_color(blend_color(BLUE, MAGENTA, 128), BLACK, 128)); + + slot_buttons[1]->get_style()->set_bg_color(blend_color(RED, MAGENTA, 128))->set_pressed_bg_color(blend_color(blend_color(RED, MAGENTA, 128), BLACK, 128)); + slot_buttons[3]->get_style()->set_bg_color(blend_color(GREEN, YELLOW, 128))->set_pressed_bg_color(blend_color(blend_color(GREEN, YELLOW, 128), BLACK, 128)); + slot_buttons[5]->get_style()->set_bg_color(blend_color(BLUE, CYAN, 128))->set_pressed_bg_color(blend_color(blend_color(BLUE, CYAN, 128), BLACK, 128)); + + communication_status_label + ->set_event_queue(app->get_event_queue()) + ->set_onrelease(exit_slot_selection) + ->get_style() + ->set_text_size(2) + ->set_border_radius(0) + ->set_border_width(0); + + tools_window->send_front(slot_selection_window, 0); + + slot_selection_window->send_front(communication_status_label, 0); + + communication_status_label->set_visibility(false); + slot_selection_window->set_visibility(false); + communication_status_label->clear(); + slot_selection_window->clear(); +} - if (colorSelector.update(x, y)) { +void init_connection_view() { - thicknessSelector.setColor(colorSelector.getColor()); - thicknessSelector.draw(); + connection_view = View::create(app); + if (connection_view == nullptr) { + err("Error while creating connection view"); } - if (thicknessSelector.update(x, y)) { - thicknessSelector.draw(); + connection_back_button = Button::create(connection_view, 3, 15 - 12, 24, 24); + if (connection_back_button == nullptr) { + err("Error while creating connection back button"); } - if (loadButton.update(x, y)) { + connection_title = Label::create(connection_view, 30, 1, app->get_width() - 30 - 10, 27); + if (connection_title == nullptr) { + err("Error while creating connection title"); + } - slotSelector.draw(); + keyboard = Keyboard::create(connection_view); + if (keyboard == nullptr) { + err("ERror while creating keyboard"); + } - delay(300); + connection_form_window = Window::create(connection_view, 5, 30, app->get_width() - 10, app->get_height() - 45); + if (connection_form_window == nullptr) { + err("Error while creating connection form window"); + } - for (;;) { + ssid_label = Label::create(connection_form_window, 10, 10, connection_form_window->get_width() - 20, 30); + if (ssid_label == nullptr) { + err("Error while creating ssid label"); + } + ssid_box = TextBox::create(connection_form_window, 10, 47 - 4, connection_form_window->get_width() - 20, 34); + if (ssid_box == nullptr) { + err("Error while creating ssid box"); + } + + pass_label = Label::create(connection_form_window, 10, 90, connection_form_window->get_width() - 20, 30); + if (pass_label == nullptr) { + err("Error while creating pass_label"); + } + pass_box = TextBox::create(connection_form_window, 10, 127 - 4, connection_form_window->get_width() - 20, 34); + if (pass_box == nullptr) { + err("Error while creating pass box"); + } - getTouchCoors(&x, &y); + addr_label = Label::create(connection_form_window, 10, 170, connection_form_window->get_width() - 20, 30); + if (addr_label == nullptr) { + err("Error while creating addr label"); + } + addr_box = TextBox::create(connection_form_window, 10, 207 - 4, connection_form_window->get_width() - 20, 34); + if (addr_box == nullptr) { + err("Error while creating addr box"); + } - if (slotSelector.update(x, y)) { + connect_button = Button::create(connection_form_window, 10, 260, connection_form_window->get_width() - 20, 40); + if (connect_button == nullptr) { + err("Error while creating connect button"); + } - executeSlotSelection(&client, &CanvasClient::loadCanvas); - break; - } + status_label = Label::create(connection_form_window, 10, connection_form_window->get_height() - 30 - 5, connection_form_window->get_width() - 20, 30); + if (status_label == nullptr) { + err("Error while creating status label"); + } - delay(5); + connection_back_button + ->set_onrelease(switch_to_startup) + ->set_event_queue(app->get_event_queue()) + ->set_message("x") + ->get_style() + ->set_text_size(2) + ->set_bg_color(RED) + ->set_fg_color(BLACK) + ->set_pressed_bg_color(blend_color(RED, BLACK, 160)) + ->set_pressed_fg_color(WHITE) + ->set_border_width(0) + ->set_border_radius(14); + + connection_title + ->set_message("Manage Connection") + ->get_style() + ->set_text_size(2) + ->set_border_width(0) + ->set_border_radius(0); + + keyboard + ->set_event_queue(app->get_event_queue()) + ->set_visibility(false); + keyboard->clear(); + + connection_form_window + ->get_style() + ->set_border_radius(3); + + ssid_label + ->set_message("WiFi SSID:") + ->get_style() + ->set_text_size(2) + ->set_horizontal_alignment(LabelStyle::HorizontalAlignment::LEFT_ALIGN) + ->set_border_radius(0) + ->set_border_width(0); + + ssid_box + ->set_event_queue(app->get_event_queue()) + ->set_onrelease(open_keyboard) + ->set_args((unsigned *)ssid_box) + ->get_style() + ->set_text_size(2) + ->set_horizontal_alignment(LabelStyle::HorizontalAlignment::LEFT_ALIGN) + ->set_border_radius(2) + ->set_border_width(2) + ->set_bg_color(blend_color(BLACK, BLUE, 18)); + + pass_label + ->set_message("WiFi Password:") + ->get_style() + ->set_text_size(2) + ->set_horizontal_alignment(LabelStyle::HorizontalAlignment::LEFT_ALIGN) + ->set_border_radius(0) + ->set_border_width(0); + + pass_box + ->set_event_queue(app->get_event_queue()) + ->set_onrelease(open_keyboard) + ->set_args((unsigned *)pass_box) + ->get_style() + ->set_text_size(2) + ->set_horizontal_alignment(LabelStyle::HorizontalAlignment::LEFT_ALIGN) + ->set_border_radius(2) + ->set_border_width(2) + ->set_bg_color(blend_color(BLACK, BLUE, 18)); + + addr_label + ->set_message("Server IP:port") + ->get_style() + ->set_text_size(2) + ->set_horizontal_alignment(LabelStyle::HorizontalAlignment::LEFT_ALIGN) + ->set_border_radius(0) + ->set_border_width(0); + + addr_box + ->set_event_queue(app->get_event_queue()) + ->set_onrelease(open_keyboard) + ->set_args((unsigned *)addr_box) + ->get_style() + ->set_text_size(2) + ->set_horizontal_alignment(LabelStyle::HorizontalAlignment::LEFT_ALIGN) + ->set_border_radius(2) + ->set_border_width(2) + ->set_bg_color(blend_color(BLACK, BLUE, 18)); + + connect_button + ->set_message("Connect") + ->set_event_queue(app->get_event_queue()) + ->set_onrelease(connect_cb) + ->get_style() + ->set_text_size(2) + ->set_border_radius(20) + ->set_border_width(0) + ->set_bg_color(blend_color(BLUE, CYAN, 192)) + ->set_fg_color(BLACK) + ->set_pressed_bg_color(blend_color(BLUE, CYAN, 128)) + ->set_pressed_fg_color(WHITE); + + status_label + ->set_message("NOT CONNECTED") + ->get_style() + ->set_text_size(2) + ->set_border_radius(0) + ->set_border_width(0) + ->set_fg_color(GRAY); + + connection_view->send_front(keyboard, 0); + + { // optimization + signed status = WiFi.status(); + if (status == WL_NO_MODULE) { + status_label + ->set_message("NO WIFI MODULE") + ->get_style() + ->set_fg_color(RED); } } +} - if (saveButton.update(x, y)) { +void init_information_view() { - slotSelector.draw(); + information_view = View::create(app); + if (information_view == nullptr) { + err("Error while creating information view"); + } - delay(300); + information_back_button = Button::create(information_view, 3, 15 - 12, 24, 24); + if (information_back_button == nullptr) { + err("Error while creating information back button"); + } - for (;;) { + information_title = Label::create(information_view, 30, 3, app->get_width() - 30 - 10, 25); + if (information_title == nullptr) { + err("Error while creating information title"); + } - getTouchCoors(&x, &y); + information_form_window = Window::create(information_view, 5, 30, app->get_width() - 10, app->get_height() - 45); + if (information_form_window == nullptr) { + err("Error while creating information form window"); + } - if (slotSelector.update(x, y)) { + ssid_readonly_label = Label::create(information_form_window, 12, 20, (information_form_window->get_width() - 24) / 2 - 30, 35); + if (ssid_readonly_label == nullptr) { + err("Error while creating ssid readonly label"); + } - executeSlotSelection(&client, &CanvasClient::saveCanvas); - break; - } + ssid_readonly_box = Label::create(information_form_window, ssid_readonly_label->get_x() + ssid_readonly_label->get_width() - 1, ssid_readonly_label->get_y(), information_form_window->get_width() - ssid_readonly_label->get_x() - ssid_readonly_label->get_width() - 12, 35); + if (ssid_readonly_box == nullptr) { + err("Error while creating ssid readonly label"); + } + + ip_addr_label = Label::create(information_form_window, ssid_readonly_label->get_x(), ssid_readonly_box->get_y() + ssid_readonly_box->get_height() - 1, ssid_readonly_label->get_width(), ssid_readonly_label->get_height()); + if (ip_addr_label == nullptr) { + err("Error while creating ssid readonly label"); + } + + ip_addr_box = Label::create(information_form_window, ssid_readonly_box->get_x(), ip_addr_label->get_y(), ssid_readonly_box->get_width(), ssid_readonly_box->get_height()); + if (ip_addr_box == nullptr) { + err("Error while creating ssid readonly label"); + } + + dumblebots_qrcode = Bitmap::create(information_form_window, qrcode_bmp, (information_form_window->get_width() - 135) / 2, information_form_window->get_height() - 135 - 30, 135, 135); + if (dumblebots_qrcode == nullptr) { + err("Error while creating dumblebots qrcode"); + } + dumblebots_website_label = Label::create(information_form_window, 10, information_form_window->get_height() - 25, information_form_window->get_width() - 20, 20); + if (dumblebots_website_label == nullptr) { + err("Error while creating dumblebots website label"); + } + + information_back_button + ->set_onrelease(switch_to_startup) + ->set_event_queue(app->get_event_queue()) + ->set_message("x") + ->get_style() + ->set_text_size(2) + ->set_bg_color(RED) + ->set_fg_color(BLACK) + ->set_pressed_bg_color(blend_color(RED, BLACK, 160)) + ->set_pressed_fg_color(WHITE) + ->set_border_width(0) + ->set_border_radius(14); + + information_title + ->set_message("Information") + ->get_style() + ->set_text_size(2) + ->set_border_width(0) + ->set_border_radius(0); + + information_form_window + ->get_style() + ->set_border_radius(3); + + ssid_readonly_label + ->set_message("WiFi SSID ") + ->get_style() + ->set_text_size(2) + ->set_horizontal_alignment(LabelStyle::HorizontalAlignment::RIGHT_ALIGN) + ->set_border_radius(0) + ->set_border_width(1); + + ssid_readonly_box + ->get_style() + ->set_text_size(2) + ->set_horizontal_alignment(LabelStyle::HorizontalAlignment::CENTER_ALIGN) + ->set_border_radius(0) + ->set_border_width(1); + + ip_addr_label + ->set_message("IP Address ") + ->get_style() + ->set_text_size(2) + ->set_horizontal_alignment(LabelStyle::HorizontalAlignment::RIGHT_ALIGN) + ->set_border_radius(0) + ->set_border_width(1); + + ip_addr_box + ->get_style() + ->set_text_size(2) + ->set_horizontal_alignment(LabelStyle::HorizontalAlignment::CENTER_ALIGN) + ->set_border_radius(0) + ->set_border_width(1); + + dumblebots_website_label + ->set_message("Powered by https://dumblebots.com") + ->get_style() + ->set_text_size(1) + ->set_border_radius(0) + ->set_border_width(0); + + information_form_window->send_back(dumblebots_qrcode, 100); +} + +void setup() { + + // HeapStats_t stats; + + Serial.begin(9600); + + // Serial.println("-----"); + // vPortGetHeapStats(&stats); + // Serial.print("Available Heap Space: "); Serial.println(stats.xAvailableHeapSpaceInBytes); + // Serial.print("Minimum Ever Free Bytes: "); Serial.println(stats.xMinimumEverFreeBytesRemaining); + // Serial.print("Number of Free blocks: "); Serial.println(stats.xNumberOfFreeBlocks); + // Serial.print("Number of successful allocs: "); Serial.println(stats.xNumberOfSuccessfulAllocations); + // Serial.print("Number of successful frees: "); Serial.println(stats.xNumberOfSuccessfulFrees); + // Serial.print("Size of largest free block: "); Serial.println(stats.xSizeOfLargestFreeBlockInBytes); + // Serial.print("Size of smallest free block: "); Serial.println(stats.xSizeOfSmallestFreeBlockInBytes); + // Serial.println("-----"); + + tft.begin(0x9486); + + ts.set_dimensions(tft.width(), tft.height()); + ts.set_pressure(PRESSURE_LEFT, PRESSURE_RIGHT); + + app = App::create(&tft); + if (app == nullptr) { + err("Error while creating app"); + } + + init_startup_view(); + init_main_view(); + init_connection_view(); + init_information_view(); + + app->make_active_view(startup_view); + app->draw(); + + // Serial.println("-----"); + // vPortGetHeapStats(&stats); + // Serial.print("Available Heap Space: "); Serial.println(stats.xAvailableHeapSpaceInBytes); + // Serial.print("Minimum Ever Free Bytes: "); Serial.println(stats.xMinimumEverFreeBytesRemaining); + // Serial.print("Number of Free blocks: "); Serial.println(stats.xNumberOfFreeBlocks); + // Serial.print("Number of successful allocs: "); Serial.println(stats.xNumberOfSuccessfulAllocations); + // Serial.print("Number of successful frees: "); Serial.println(stats.xNumberOfSuccessfulFrees); + // Serial.print("Size of largest free block: "); Serial.println(stats.xSizeOfLargestFreeBlockInBytes); + // Serial.print("Size of smallest free block: "); Serial.println(stats.xSizeOfSmallestFreeBlockInBytes); + // Serial.println("-----"); +} + +void loop() { + + bool press, release; + unsigned px, py, rx, ry; - delay(5); + ts.read_screen(); + + press = ts.get_press(&px, &py); + release = ts.get_release(&rx, &ry); + + if (release) { + app->propagate_release(rx, ry); + } + if (press) { + app->propagate_press(px, py); + } + + app + ->collect_dirty_widgets() + ->update_dirty_widgets() + ->execute_event_logic(); + + { + if (app->get_active_view() == main_view && ts.get_stylus_position(&px, &py)) { + canvas->draw_at(px, py); } } - if (clearButton.update(x, y)) { - canvas.clearDrawing(); - clearCompressedCanvas(); + delay(1); +} + +[[noreturn]] +void err(const char msg[]) { + + Serial.println(msg); + for (;;); +} + +void switch_to_startup(unsigned *args) { + connection_back_button->set_onrelease(switch_to_startup); + information_back_button->set_onrelease(switch_to_startup); + app->make_active_view(startup_view); +} + +void switch_to_connection(unsigned *args) { + + signed status = WiFi.status(); + + if (status == WL_CONNECTED) { + status_label + ->set_message("CONNECTED") + ->get_style() + ->set_fg_color(GREEN); + } + else { + status_label + ->set_message("NOT CONNECTED") + ->get_style() + ->set_fg_color(GRAY); } - if (infoButton.update(x, y)) { + keyboard->set_visibility(false); + app->make_active_view(connection_view); +} + +void switch_to_information(unsigned *args) { + + signed status = WiFi.status(); + char buffer[64]; + + if (status == WL_CONNECTED) { + ssid_box->get_message().toCharArray(buffer, sizeof(buffer) / sizeof(buffer[0]), 0); + + ssid_readonly_box + ->set_message(buffer) + ->get_style() + ->set_fg_color(WHITE); + + WiFi.localIP().toString().toCharArray(buffer, sizeof(buffer) / sizeof(buffer[0]), 0); + + ip_addr_box + ->set_message(buffer) + ->get_style() + ->set_fg_color(WHITE); } + else { + + ssid_readonly_box + ->set_message("Not Connected") + ->get_style() + ->set_fg_color(RED); - widgetUpdateTime = (micros() - widgetUpdateTime) / 1000; - if (widgetUpdateTime < 10) { // 100 frames per second - delay(10 - widgetUpdateTime); + ip_addr_box + ->set_message("-") + ->get_style() + ->set_fg_color(RED); } + + app->make_active_view(information_view); +} + +void switch_to_main(unsigned *args) { + canvas->set_pen_color(RED); + size_selector->set_color(RED); + connection_back_button->set_onrelease(switch_to_main); + information_back_button->set_onrelease(switch_to_main); + app->make_active_view(main_view); +} + +void select_color_cb(unsigned *args) { + size_selector->set_color(*(uint16_t *)args); + canvas->set_pen_color(*(uint16_t *)args); +} + +void select_pen_size_cb(unsigned *args) { + canvas->set_pen_size(*args); +} + +void clear_button_cb(unsigned *args) { + canvas->clear_canvas(); } -void clearCompressedCanvas() { - memset(rawCode, 8, sizeof(rawCode)); - for (unsigned i = 0; i < CANVAS_H-2; ++i) { - compressed[i].compress(rawCode, CANVAS_W-2); +void open_slot_selection(unsigned *args) { + + slot_button_args_t *button_args; + + for (auto &button : slot_buttons) { + button_args = (slot_button_args_t *)button->get_args(); + button_args->caller = (Button *)args; } + + slot_selection_window->set_visibility(true); + communication_status_label->set_visibility(false); } -void executeSlotSelection(CanvasClient *client, void (CanvasClient::*method)(uint8_t, Compressor *)) { +void exit_slot_selection(unsigned *args) { + slot_selection_window->set_visibility(false); +} + +void slot_selection_cb(unsigned *args) { - uint8_t selectedSlot = slotSelector.getSlot(); + slot_button_args_t *info = (slot_button_args_t *)args; - if (selectedSlot != 0) { - (client->*method)(selectedSlot, compressed); + if (info->caller == save_button) { + canvas->set_args((unsigned *)info->caller); + canvas->save_to_server(info->number); } + else { + canvas->set_args((unsigned *)info->caller); + canvas->load_from_server(info->number); + } +} - slotSelector.clear(); - drawLowerWidgets(); +void server_connection_failure_cb(unsigned *args) { + + communication_status_label + ->set_message("FAILED TO CONNECT") + ->get_style() + ->set_fg_color(RED); + + communication_status_label->set_visibility(true); +} + +void server_communication_failure_cb(unsigned *args) { + + communication_status_label + ->set_message("COMMUNICATION INTERRUPTED") + ->get_style() + ->set_fg_color(RED); + + communication_status_label->set_visibility(true); +} + +void server_success_cb(unsigned *args) { + + communication_status_label + ->set_message((args == (unsigned *)save_button) ? "IMAGE SAVED" : "IMAGE LOADED") + ->get_style() + ->set_fg_color(GREEN); + + communication_status_label->set_visibility(true); +} + +void open_keyboard(unsigned *args) { + + keyboard->set_visibility(true); + keyboard->set_shift_index(0); + + if (args == (unsigned *)ssid_box) { + keyboard->set_onrelease(ssid_box_edit_cb); + } + else if (args == (unsigned *)pass_box) { + keyboard->set_onrelease(pass_box_edit_cb); + } + else if (args == (unsigned *)addr_box) { + keyboard->set_onrelease(addr_box_edit_cb); + } +} + +void ssid_box_edit_cb(unsigned *args) { + + Keyboard::keyboard_state_t *info = (Keyboard::keyboard_state_t *)args; + + if (info->special != 0) { + if (info->backspace != 0) { + ssid_box->pop_from_message(); + } + return; + } + if (ssid_box->get_message_len() < 16) { + ssid_box->append_to_message((char)(info->key)); + } } -void drawLowerWidgets() { +void pass_box_edit_cb(unsigned *args) { + + Keyboard::keyboard_state_t *info = (Keyboard::keyboard_state_t *)args; + + if (info->special != 0) { + if (info->backspace != 0) { + pass_box->pop_from_message(); + } + return; + } + if (pass_box->get_message_len() < 16) { + pass_box->append_to_message((char)(info->key)); + } +} + +void addr_box_edit_cb(unsigned *args) { + + Keyboard::keyboard_state_t *info = (Keyboard::keyboard_state_t *)args; - colorSelector.draw(); - thicknessSelector.draw(); + if (info->special != 0) { + if (info->backspace != 0) { + addr_box->pop_from_message(); + } + return; + } + + if ((addr_box->get_message_len() < (15 + 1 + 5)) + && (info->key == '.' + || info->key == ':' + || ('0' <= info->key && info->key <= '9'))) { + addr_box->append_to_message((char)(info->key)); + } +} + +void connect_cb(unsigned *args) { + + signed status = WL_IDLE_STATUS; + + if (WiFi.status() == WL_NO_MODULE) { + status_label + ->set_message("NO WIFI MODULE") + ->get_style() + ->set_fg_color(RED); + + return; + } + if (!verify_server()) { + status_label + ->set_message("INVALID IP/PORT") + ->get_style() + ->set_fg_color(RED); + + canvas->set_server_addr("", 0); + return; + } + + status_label + ->set_message("CONNECTING...") + ->get_style() + ->set_fg_color(BLUE); + + keyboard->set_visibility(false); + + //! + app + ->collect_dirty_widgets() + ->update_dirty_widgets(); + + app->push_event({try_connect, nullptr}); +} + +bool verify_server() { + + char addr[15 + 1 + 5 + 1]; + unsigned addr_len; + + char *ip; + char *port; + char *delim; + + unsigned server_port; + + addr_box->get_message().toCharArray(addr, sizeof(addr) / sizeof(addr[0])); + addr_len = addr_box->get_message_len(); + + if (addr_len == 0) { + return false; + } + + delim = strchr(addr, ':'); + if (delim == NULL + || delim == addr + || delim == &addr[addr_len - 1]) { + return false; + } + + ip = addr; + port = delim + 1; + *delim = NULL; + + { + signed temp; + temp = atoi(port); + + if (temp < 0 || temp > 65535) { + return false; + } + + server_port = temp; + } + { + char *saveptr; + unsigned num_dots; + unsigned len; + signed temp; + + for (char *ptr = ip; *ptr != NULL; ++ptr) { + if (*ptr == '.') { + ++num_dots; + } + } + + if (num_dots != 3) { + return false; + } + + for (char *ptr = strtok_r(ip, ".", &saveptr); ptr != nullptr; ptr = strtok_r(NULL, ".", &saveptr)) { + + if (ptr != ip) { + *(ptr - 1) = '.'; + } + + len = strlen(ptr); + temp = atoi(ptr); + + if (len == 0 || temp < 0 || temp > 255) { + return false; + } + + if (len > 1 && ptr[0] == '0') { + return false; + } + + for (char *subptr = ptr; subptr != &ptr[len]; ++subptr) { + if (*subptr < '0' || *subptr > '9') { + return false; + } + } + } + } + + canvas->set_server_addr(ip, server_port); + return true; +} + +void try_connect(unsigned *args) { + + char ssid[17]; + char pass[17]; + + ssid_box->get_message().toCharArray(ssid, sizeof(ssid) / sizeof(ssid[0])); + pass_box->get_message().toCharArray(pass, sizeof(pass) / sizeof(pass[0])); + + signed status = WL_IDLE_STATUS; + unsigned attempts_left = MAX_WIFI_RETRY; + + while (attempts_left--) { + + status = WiFi.begin(ssid, pass); + + delay(250); + + if (status == WL_CONNECTED) { + + status_label + ->set_message("CONNECTED") + ->get_style() + ->set_fg_color(GREEN); + + return; + } + } - loadButton.draw(); - saveButton.draw(); - clearButton.draw(); - infoButton.draw(); - connectButton.draw(); + status_label + ->set_message("FAILED TO CONNECT") + ->get_style() + ->set_fg_color(RED); } diff --git a/src/touch.cpp b/src/touch.cpp deleted file mode 100644 index a51ab05..0000000 --- a/src/touch.cpp +++ /dev/null @@ -1,44 +0,0 @@ -#include "Arduino.h" -#include "TouchScreen.h" - -#include "constants.h" -#include "helper.h" - -#include "touch.h" - -TouchScreen ts = TouchScreen(XP, YP, XM, YM, 300); - -void toDisplayMode() { - - pinMode(XM, OUTPUT); - pinMode(XP, OUTPUT); - pinMode(YM, OUTPUT); - pinMode(YP, OUTPUT); -} - -void convertTouchCoors(unsigned tx, unsigned ty, unsigned *xptr, unsigned *yptr) { - - tx = constrain(tx, XBEGIN, XEND); - ty = constrain(ty, YBEGIN, YEND); - - tx = map(tx, XBEGIN, XEND, 0, 319); - ty = map(ty, YBEGIN, YEND, 479, 0); - - *xptr = tx; - *yptr = ty; -} - -void getTouchCoors(unsigned *xptr, unsigned *yptr) { - - TSPoint p; - - for (;;) { - - p = ts.getPoint(); - if (inRange(p.z, PRESSURE_LEFT, PRESSURE_RIGHT)) { - break; - } - } - convertTouchCoors(p.x, p.y, xptr, yptr); - toDisplayMode(); -} diff --git a/src/widgets/app.cpp b/src/widgets/app.cpp new file mode 100644 index 0000000..d4855a1 --- /dev/null +++ b/src/widgets/app.cpp @@ -0,0 +1,245 @@ +#include "algorithm" + +#include "widgets/app.h" +#include "widgets/view.h" + +App::App(MCUFRIEND_kbv *display) +: display {display} +{ + clear(); +} + +App *App::create(MCUFRIEND_kbv *display) { + App *app = new (std::nothrow) App(display); + return app; +} + +App *App::add_view(View *child) { + views.emplace_back(child); + return this; +} + +App *App::make_active_view(View *child) { + + if (std::find(views.begin(), views.end(), child) == views.end()) { + return this; + } + active_view = child; + active_view->set_dirty(); //todo all my children should be marked as clean (including bounding box and visibility and stuff) (possibly use force_clean method) + clear(); + + return this; +} + +View *App::get_active_view() const { + return active_view; +} + +RingQueueInterface *App::get_event_queue() { + return &event_queue; +} + +App *App::push_event(const InteractiveWidget::callback_event_t &event) { + event_queue.push(event); +} + +App *App::execute_event_logic() { + + InteractiveWidget::callback_t cb; + unsigned *args; + + while (event_queue.get_size() != 0) { + + cb = event_queue.front().cb; + args = event_queue.front().args; + + cb(args); + + event_queue.pop(); + } + + return this; +} + +App *App::collect_dirty_widgets() { + + if (active_view->get_dirty()) { + dirty_widgets.push(active_view); + } + else { + ((View *)active_view)->collect_dirty_widgets(&dirty_widgets); + } + + return this; +} + +App *App::update_dirty_widgets() { + + while (dirty_widgets.get_size() != 0) { + + BasicWidget *dirty; + BasicWidget *parent; + BasicWidget *child; + + dirty = dirty_widgets.front(); + dirty_widgets.pop(); + + if (dirty->get_visibility()) { + + dirty->draw(); + + child = dirty; + parent = dirty->get_parent(); + + while (parent != this) { + ((Frame *)parent)->collect_overlapped_widgets(dirty, child, &dirty_widgets); + + child = parent; + parent = parent->get_parent(); + } + } + else { + + dirty->clear(); + + child = dirty; + parent = dirty->get_parent(); + + ((Frame *)parent)->collect_underlapped_widgets(dirty, &dirty_widgets); + + while (parent != this) { + ((Frame *)parent)->collect_overlapped_widgets(dirty, child, &dirty_widgets); + + child = parent; + parent = parent->get_parent(); + } + } + } + + return this; +} + +// BasicWidget overrides + +BasicWidget *App::get_parent() { return nullptr; } + +unsigned App::get_x() const { return 0; } +unsigned App::get_y() const { return 0; } + +unsigned App::get_absolute_x() const { return 0; } +unsigned App::get_absolute_y() const { return 0; } + +unsigned App::get_width() const { return display->width(); } +unsigned App::get_height() const { return display->height(); } + +bool App::get_dirty() const { return false; } +bool App::get_visibility_changed() const { return false; } + +void App::set_dirty() { return; } +void App::set_visibility_changed() { return; } + +void App::draw() { active_view->draw(); } + +void App::clear() { display->fillRect(0, 0, display->width(), display->height(), BLACK); } + +bool App::get_intersection(unsigned int x, unsigned int y) const { return true; } +bool App::get_intersection(BasicWidget *other) const { return true; } + +bool App::propagate_press(unsigned x, unsigned y) { return active_view->propagate_press(x, y); } +bool App::propagate_release(unsigned x, unsigned y) { return active_view->propagate_release(x, y); } + +bool App::get_visibility() const { return true; } +void App::set_visibility(bool new_visibility) { return; } + +// Frame overrides + +App *App::set_at(unsigned int x, unsigned int y, uint16_t color) { + display->writePixel(x, y, color); + return this; +} + +uint16_t App::get_at(unsigned int x, unsigned int y) const { + +#ifdef READ_PIXEL_ENABLED + return display->readPixel(x, y); +#else + return 0; +#endif +} + +App *App::draw_line(unsigned int x0, unsigned int y0, unsigned int x1, unsigned int y1, uint16_t color) { + display->drawLine(x0, y0, x1, y1, color); + return this; +} + +App *App::draw_rect(unsigned int x0, unsigned int y0, unsigned int w, unsigned int h, uint16_t color) { + display->drawRect(x0, y0, w, h, color); + return this; +} + +App *App::fill_rect(unsigned int x0, unsigned int y0, unsigned int w, unsigned int h, uint16_t color) { + display->fillRect(x0, y0, w, h, color); + return this; +} + +App *App::draw_round_rect(unsigned int x, unsigned int y, unsigned int w, unsigned int h, unsigned int r, uint16_t color) { + display->drawRoundRect(x, y, w, h, r, color); + return this; +} + +App *App::fill_round_rect(unsigned int x, unsigned int y, unsigned int w, unsigned int h, unsigned int r, uint16_t color) { + display->fillRoundRect(x, y, w, h, r, color); + return this; +} + +App *App::draw_circle(unsigned int x, unsigned int y, unsigned int r, uint16_t color) { + display->drawCircle(x, y, r, color); + return this; +} + +App *App::fill_circle(unsigned int x, unsigned int y, unsigned int r, uint16_t color) { + display->fillCircle(x, y, r, color); + return this; +} + +App *App::get_text_bounds(const char *text, unsigned int text_size, unsigned int x, unsigned int y, int16_t *x1, int16_t *y1, + uint16_t *w, uint16_t *h) { + display->setTextSize(text_size); + display->getTextBounds(text, x, y, x1, y1, w, h); + return this; +} + +App *App::set_font(const GFXfont *f) { + display->setFont(f); + return this; +} + +App *App::print(const char *text, unsigned int x, unsigned int y, unsigned int text_size, uint16_t fg_color) { + + display->setCursor(x, y); + display->setTextColor(fg_color); + display->setTextSize(text_size); + + display->print(text); + + return this; +} + +App *App::print_opaque(const char *text, unsigned int x, unsigned int y, unsigned int text_size, uint16_t fg_color, + uint16_t bg_color) { + + display->setCursor(x, y); + display->setTextColor(fg_color, bg_color); + display->setTextSize(text_size); + + display->print(text); + + return this; +} + +App *App::draw_rgb_bitmap(unsigned x, unsigned y, const uint16_t *data, unsigned width, unsigned height) { + + display->drawRGBBitmap(x, y, data, width, height); + return this; +} + diff --git a/src/widgets/bitmap.cpp b/src/widgets/bitmap.cpp new file mode 100644 index 0000000..12927d2 --- /dev/null +++ b/src/widgets/bitmap.cpp @@ -0,0 +1,209 @@ +#include "widgets/bitmap.h" + +Bitmap::Bitmap(Frame *parent, const uint16_t *data, unsigned x, unsigned y, unsigned width, unsigned height) + : parent {parent} + , data {data} + , widget_x {x} + , widget_y {y} + , widget_absolute_x { x + parent->get_absolute_x() } + , widget_absolute_y { y + parent->get_absolute_x() } + , widget_w {width} + , widget_h {height} +{} + +Bitmap *Bitmap::create(Frame *parent, const uint16_t *data, unsigned x, unsigned y, unsigned width, unsigned height) { + Bitmap *bitmap = new (std::nothrow) Bitmap(parent, data, x, y, width, height); + if (bitmap != nullptr) { + parent->add_child(bitmap); + } + return bitmap; +} + +// BasicWidget overrides + +Frame *Bitmap::get_parent() { return parent; } + +unsigned Bitmap::get_x() const { return widget_x; } +unsigned Bitmap::get_y() const { return widget_y; } + +unsigned Bitmap::get_absolute_x() const { return widget_absolute_x; } +unsigned Bitmap::get_absolute_y() const { return widget_absolute_y; } + +unsigned Bitmap::get_width() const { return widget_w; } +unsigned Bitmap::get_height() const { return widget_h; } + +bool Bitmap::get_dirty() const { return dirty; } +bool Bitmap::get_visibility_changed() const { return visibility_changed; } + +void Bitmap::set_dirty() { dirty = true; } +void Bitmap::set_visibility_changed() { visibility_changed = true; } + +void Bitmap::draw() { + + dirty = false; + visibility_changed = false; + + parent->draw_rgb_bitmap(widget_x, widget_y, data, widget_w, widget_h); +} + +void Bitmap::clear() { + + dirty = false; + visibility_changed = false; + + parent->fill_rect(widget_x, widget_y, widget_w, widget_h, BLACK); +} + +bool Bitmap::get_intersection(unsigned int x, unsigned int y) const { + return (widget_x <= x && x <= (widget_x + widget_w)) + && (widget_y <= y && y <= (widget_y + widget_h)); +} + +bool Bitmap::get_intersection(BasicWidget *other) const { + + unsigned x0 = other->get_absolute_x(); + unsigned y0 = other->get_absolute_y(); + + unsigned x1 = x0 + other->get_width(); + unsigned y1 = y0 + other->get_height(); + + if (( + (widget_absolute_x <= x0 && x0 <= (widget_absolute_x + widget_w)) + || (widget_absolute_x <= x1 && x1 <= (widget_absolute_x + widget_w)) + ) + && ( + (widget_absolute_y <= y0 && y0 <= (widget_absolute_y + widget_h)) + || (widget_absolute_y <= y1 && y1 <= (widget_absolute_y + widget_h)) + )) { + return true; + } + + if (( + (x0 <= widget_absolute_x && widget_absolute_x <= x1) + || (x0 <= (widget_absolute_x + widget_w) && (widget_absolute_x + widget_w) <= x1) + ) + && ( + (y0 <= widget_absolute_y && widget_absolute_y <= y1) + || (y0 <= (widget_absolute_y + widget_h) && (widget_absolute_y + widget_h) <= y1) + )) { + return true; + } + + return false; +} + +bool Bitmap::propagate_press(unsigned x, unsigned y) { + + if (!get_intersection(x, y)) { + return false; + } + if (pressed || !enabled) { + return true; + } + + unsigned cur_epoch = millis(); + if ((cur_epoch - last_press_epoch) < DEBOUNCE_THRESH) { + return true; + } + last_press_epoch = cur_epoch; + + dirty = true; + pressed = true; + + if (event_queue != nullptr && on_press != nullptr) { + event_queue->push({on_press, args}); + } + + return true; +} + +bool Bitmap::propagate_release(unsigned x, unsigned y) { + + if (!get_intersection(x, y)) { + return false; + } + if (!pressed) { + return true; + } + + dirty = true; + pressed = false; + + if (event_queue != nullptr && on_release != nullptr) { + event_queue->push({on_release, args}); + } + + return true; +} + +bool Bitmap::get_visibility() const { return visible; } + +void Bitmap::set_visibility(bool new_visibility) { + + if (visible == new_visibility) { + return; + } + + dirty = true; + visibility_changed = true; + + visible = new_visibility; +} + +// InteractiveWidget overrides + +Bitmap *Bitmap::set_onpress(callback_t callback) { + on_press = callback; + return this; +} + +Bitmap *Bitmap::reset_onpress() { + on_press = nullptr; + return this; +} + +Bitmap *Bitmap::set_onrelease(callback_t callback) { + on_release = callback; + return this; +} + +Bitmap *Bitmap::reset_onrelease() { + on_release = nullptr; + return this; +} + +Bitmap *Bitmap::set_event_queue(RingQueueInterface *new_event_queue) { + event_queue = new_event_queue; + return this; +} + +Bitmap *Bitmap::reset_event_queue() { + event_queue = nullptr; + return this; +} + +Bitmap *Bitmap::set_args(unsigned *new_args) { + args = new_args; + return this; +} + +Bitmap *Bitmap::reset_args() { + args = nullptr; + return this; +} + +unsigned *Bitmap::get_args() { return args; } + +bool Bitmap::is_pressed() const { return pressed; } + +Bitmap *Bitmap::set_interactable(bool new_state) { + if (new_state == enabled) { + return this; + } + + dirty = true; + new_state = new_state; + return this; +} + +bool Bitmap::get_interactable() const { return enabled; } diff --git a/src/widgets/button.cpp b/src/widgets/button.cpp index 83c1b3c..5c5cb22 100644 --- a/src/widgets/button.cpp +++ b/src/widgets/button.cpp @@ -1,46 +1,455 @@ #include "widgets/button.h" -#include "constants.h" -#include "helper.h" - -Button::Button(unsigned x, unsigned y, unsigned w, unsigned h, uint16_t color, char *msg, MCUFRIEND_kbv *tft) - : x {x} - , y {y} - , w {w} - , h {h} - , color {color} - , msg {msg} - , tft {tft} + +Button::Button(Frame *parent, unsigned x, unsigned y, unsigned width, unsigned height) + : parent {parent} + , widget_x {x} + , widget_y {y} + , widget_absolute_x { x + parent->get_absolute_x() } + , widget_absolute_y { y + parent->get_absolute_y() } + , widget_w {width} + , widget_h {height} {} -void Button::draw() const { +Button *Button::create(Frame *parent, unsigned x, unsigned y, unsigned width, unsigned height) { + Button *button = new (std::nothrow) Button(parent, x, y, width, height); + if (button != nullptr) { + parent->add_child(button); + } + return button; +} + +Button *Button::create(Frame *parent, unsigned x, unsigned y) { + Button *button = new (std::nothrow) Button(parent, x, y, DEFAULT_WIDTH, DEFAULT_HEIGHT); + if (button != nullptr) { + parent->add_child(button); + } + return button; +} + +Button *Button::set_message(const char *messagePtr) { + dirty = true; + message = messagePtr; + return this; +} + +String Button::get_message() const { return message; } + +ButtonStyle *Button::get_style() { + dirty = true; + return &style; +} + +// BasicWidget overrides + +Frame *Button::get_parent() { return parent; } + +unsigned Button::get_x() const { return widget_x; } +unsigned Button::get_y() const { return widget_y; } + +unsigned Button::get_absolute_x() const { return widget_absolute_x; } +unsigned Button::get_absolute_y() const { return widget_absolute_y; } + +unsigned Button::get_width() const { return widget_w; } +unsigned Button::get_height() const { return widget_h; } + +bool Button::get_dirty() const { return dirty; } +bool Button::get_visibility_changed() const { return visibility_changed; } - tft->drawRect(x, y, w, h, color); +void Button::set_dirty() { dirty = true; } +void Button::set_visibility_changed() { visibility_changed = true; } - tft->setCursor(x, y); - tft->setTextColor(color, BLACK); - tft->setTextSize(2); +void Button::draw() { - tft->print(msg); + dirty = false; + visibility_changed = false; + + if (style.border_radius != 0) { + if (style.border_w != 0) { + parent->fill_round_rect( + widget_x, + widget_y, + widget_w, + widget_h, + style.border_radius, + (pressed) + ? style.pressed_border_color + : style.border_color + ); + } + parent->fill_round_rect( + widget_x + style.border_w, + widget_y + style.border_w, + widget_w - 2*style.border_w, + widget_h - 2*style.border_w, + style.border_radius, + (pressed) + ? style.pressed_bg_color + : style.bg_color + ); + } + else { + if (style.border_w != 0) { + parent->fill_rect( + widget_x, + widget_y, + widget_w, + widget_h, + (pressed) + ? style.pressed_border_color + : style.border_color + ); + } + parent->fill_rect( + widget_x + style.border_w, + widget_y + style.border_w, + widget_w - 2*style.border_w, + widget_h - 2*style.border_w, + (pressed) + ? style.pressed_bg_color + : style.bg_color + ); + } + + render_text(); } -void Button::clear() const { +void Button::clear() { + + dirty = false; + visibility_changed = false; - tft->fillRect(x, y, w, h, BLACK); + parent->fill_rect(widget_x, widget_y, widget_w, widget_h, BLACK); } -bool Button::update(unsigned touch_x, unsigned touch_y) { +bool Button::get_intersection(unsigned int x, unsigned int y) const { + return (widget_x <= x && x <= (widget_x + widget_w)) + && (widget_y <= y && y <= (widget_y + widget_h)); +} + +bool Button::get_intersection(BasicWidget *other) const { + + unsigned x0 = other->get_absolute_x(); + unsigned y0 = other->get_absolute_y(); + + unsigned x1 = x0 + other->get_width(); + unsigned y1 = y0 + other->get_height(); - if (!inRange(touch_x, x, x + w) || !inRange(touch_y, y, y + h)) { + if (( + (widget_absolute_x <= x0 && x0 <= (widget_absolute_x + widget_w)) + || (widget_absolute_x <= x1 && x1 <= (widget_absolute_x + widget_w)) + ) + && ( + (widget_absolute_y <= y0 && y0 <= (widget_absolute_y + widget_h)) + || (widget_absolute_y <= y1 && y1 <= (widget_absolute_y + widget_h)) + )) { + return true; + } + + if (( + (x0 <= widget_absolute_x && widget_absolute_x <= x1) + || (x0 <= (widget_absolute_x + widget_w) && (widget_absolute_x + widget_w) <= x1) + ) + && ( + (y0 <= widget_absolute_y && widget_absolute_y <= y1) + || (y0 <= (widget_absolute_y + widget_h) && (widget_absolute_y + widget_h) <= y1) + )) { + return true; + } + + return false; +} + +bool Button::propagate_press(unsigned x, unsigned y) { + + if (!get_intersection(x, y)) { return false; } + if (pressed || !enabled) { + return true; + } + + { + unsigned cur_epoch = millis(); + if ((cur_epoch - last_press_epoch) < DEBOUNCE_THRESH) { + return true; + } + last_press_epoch = cur_epoch; + } + + dirty = true; + + pressed = true; + if (event_queue != nullptr && on_press != nullptr) { + event_queue->push({on_press, args}); + } return true; } -unsigned Button::height() const { - return h; +bool Button::propagate_release(unsigned x, unsigned y) { + + if (!get_intersection(x, y)) { + return false; + } + if (!pressed) { + return true; + } + + dirty = true; + + pressed = false; + if (event_queue != nullptr && on_release != nullptr) { + event_queue->push({on_release, args}); + } + + return true; +} + +bool Button::get_visibility() const { return visible; } + +void Button::set_visibility(bool new_visibility) { + + if (visible == new_visibility) { + return; + } + + dirty = true; + visibility_changed = true; + + visible = new_visibility; +} + +// void Button::render_text() { + +// int16_t x1, y1; +// uint16_t w1, h1; + +// parent->get_text_bounds( +// message.c_str(), +// style.text_size, +// 0, +// 0, +// &x1, +// &y1, +// &w1, +// &h1 +// ); +// parent->print( +// message.c_str(), +// (style.h_align == ButtonStyle::HorizontalAlignment::CENTER_ALIGN) +// ? (2*widget_x + widget_w - w1) / 2 +// : (style.h_align == ButtonStyle::HorizontalAlignment::LEFT_ALIGN) +// ? widget_x + style.border_w +// : widget_x + widget_w - style.border_w - w1, +// (style.v_align == ButtonStyle::VerticalAlignment::MIDDLE_ALIGN) +// ? (2*widget_y + widget_h - h1) / 2 +// : (style.v_align == ButtonStyle::VerticalAlignment::TOP_ALIGN) +// ? widget_y + style.border_w +// : widget_y + widget_h - style.border_w - h1, +// style.text_size, +// (pressed) +// ? style.pressed_fg_color +// : style.fg_color +// ); +// } + +void Button::render_text() { + + int16_t x1, y1; + uint16_t w1, h1; + + switch (style.text_size) { + case 1: + parent->set_font(font_1); + break; + case 2: + parent->set_font(font_2); + break; + case 3: + parent->set_font(font_3); + break; + default: + parent->set_font(font_4); + break; + } + + parent->get_text_bounds(message.c_str(), 1, 0, 0, &x1, &y1, &w1, &h1); + + parent->print( + message.c_str(), + (style.h_align == ButtonStyle::HorizontalAlignment::CENTER_ALIGN) + ? (2*widget_x + widget_w - w1) / 2 + : (style.h_align == ButtonStyle::HorizontalAlignment::LEFT_ALIGN) + ? widget_x + style.border_w + : widget_x + widget_w - style.border_w - w1, + ((style.v_align == ButtonStyle::VerticalAlignment::MIDDLE_ALIGN) + ? (2*widget_y + widget_h - h1) / 2 + : (style.v_align == ButtonStyle::VerticalAlignment::TOP_ALIGN) + ? widget_y + style.border_w + : widget_y + widget_h - style.border_w - h1) + h1, + 1, //style.text_size, + (pressed) + ? style.pressed_fg_color + : style.fg_color + ); +} + +// InteractiveWidget overrides + +Button *Button::set_onpress(callback_t callback) { + on_press = callback; + return this; +} + +Button *Button::reset_onpress() { + on_press = nullptr; + return this; +} + +Button *Button::set_onrelease(callback_t callback) { + on_release = callback; + return this; +} + +Button *Button::reset_onrelease() { + on_release = nullptr; + return this; +} + +Button *Button::set_event_queue(RingQueueInterface *new_event_queue) { + event_queue = new_event_queue; + return this; +} + +Button *Button::reset_event_queue() { + event_queue = nullptr; + return this; +} + +Button *Button::set_args(unsigned *new_args) { + args = new_args; + return this; +} + +Button *Button::reset_args() { + args = nullptr; + return this; +} + +unsigned *Button::get_args() { return args; } + +bool Button::is_pressed() const { return pressed; } + +Button *Button::set_interactable(bool new_state) { + if (new_state == enabled) { + return this; + } + + dirty = true; + new_state = new_state; + return this; +} + +bool Button::get_interactable() const { return enabled; } + +// Button Style + +ButtonStyle *ButtonStyle::set_horizontal_alignment(ButtonStyle::HorizontalAlignment new_h_align) { + h_align = new_h_align; + return this; +} + +ButtonStyle::HorizontalAlignment ButtonStyle::get_horizontal_alignment() const { + return h_align; +} + +ButtonStyle *ButtonStyle::set_vertical_alignment(ButtonStyle::VerticalAlignment new_v_align) { + v_align = new_v_align; + return this; +} + +ButtonStyle::VerticalAlignment ButtonStyle::get_vertical_alignment() const { + return v_align; +} + +ButtonStyle *ButtonStyle::set_text_size(unsigned int new_text_size) { + text_size = new_text_size; + return this; +} + +unsigned ButtonStyle::get_text_size() const { + return text_size; +} + +ButtonStyle *ButtonStyle::set_border_radius(unsigned int new_border_radius) { + border_radius = new_border_radius; + return this; +} + +unsigned ButtonStyle::get_border_radius() const { + return border_radius; +} + +ButtonStyle *ButtonStyle::set_border_width(unsigned int new_border_w) { + border_w = new_border_w; + return this; +} + +unsigned ButtonStyle::get_border_width() const { + return border_w; +} + +ButtonStyle *ButtonStyle::set_border_color(uint16_t new_border_color) { + border_color = new_border_color; + return this; +} + +uint16_t ButtonStyle::get_border_color() const { + return border_color; +} + +ButtonStyle *ButtonStyle::set_fg_color(uint16_t new_fg_color) { + fg_color = new_fg_color; + return this; +} + +uint16_t ButtonStyle::get_fg_color() const { + return fg_color; +} + +ButtonStyle *ButtonStyle::set_bg_color(uint16_t new_bg_color) { + bg_color = new_bg_color; + return this; +} + +uint16_t ButtonStyle::get_bg_color() const { + return bg_color; +} + +ButtonStyle *ButtonStyle::set_pressed_bg_color(uint16_t new_pressed_bg_color) { + + pressed_bg_color = new_pressed_bg_color; + return this; +} + +uint16_t ButtonStyle::get_pressed_bg_color() const { + return pressed_bg_color; +} + +ButtonStyle *ButtonStyle::set_pressed_fg_color(uint16_t new_pressed_fg_color) { + pressed_fg_color = new_pressed_fg_color; + return this; +} + +uint16_t ButtonStyle::get_pressed_fg_color() const { + return pressed_fg_color; +} + +ButtonStyle *ButtonStyle::set_pressed_border_color(uint16_t new_pressed_border_color) { + pressed_border_color = new_pressed_border_color; + return this; } -unsigned Button::width() const { - return w; +uint16_t ButtonStyle::get_pressed_border_color() const { + return pressed_border_color; } diff --git a/src/widgets/buttonGrid.cpp b/src/widgets/buttonGrid.cpp deleted file mode 100644 index b021dfa..0000000 --- a/src/widgets/buttonGrid.cpp +++ /dev/null @@ -1,94 +0,0 @@ -#include "widgets/buttonGrid.h" -#include "constants.h" -#include "helper.h" - -ButtonGrid::ButtonGrid(unsigned x, unsigned y, unsigned w, unsigned h, unsigned cc, unsigned rc, unsigned button_w, unsigned button_h, MCUFRIEND_kbv *tft) - : x {x} - , y {y} - , w {w} - , h {h} - , cc {cc} - , rc {rc} - , button_w {button_w} - , button_h {button_h} - , tft {tft} - , slot {} -{} - -void ButtonGrid::draw() const { - - unsigned i, j; - - tft->fillRect(x, y, w, h, BLACK); - tft->drawRect(x, y, w, h, GRAY); - - tft->fillRoundRect(x + CLOSE_X, y + CLOSE_Y, CLOSE_W, CLOSE_W, CLOSE_W / 2, RED); - - tft->setTextColor(WHITE, BLACK); - tft->setTextSize(2); - - for (unsigned r = 0; r < rc; ++r) { - - for (unsigned c = 0; c < cc; ++c) { - - j = y + VPAD + (button_h + VPAD)*r; - i = x + HPAD + (button_w + HPAD)*c; - - tft->drawRect(i, j, button_w, button_h, WHITE); - - tft->setCursor(i, j); - - tft->print(msg); - tft->print(1 + r + (c * rc)); - - // delay(2000); - } - } -} - -bool ButtonGrid::update(unsigned touch_x, unsigned touch_y) { - - if (inRange(touch_x, x + CLOSE_X, x + CLOSE_X + CLOSE_W) - && inRange(touch_y, y + CLOSE_Y, y + CLOSE_Y + CLOSE_W)) { // close this menu - - slot = 0; - return true; - } - - for (unsigned r = 0; r < rc; ++r) { - for (unsigned c = 0; c < cc; ++c) { - - if (inRange( - touch_x, - x + HPAD + (button_w + HPAD)*c, - x + (button_w + HPAD)*(c + 1)) && - inRange( - touch_y, - y + VPAD + (button_h + VPAD)*r, - y + (button_h + VPAD)*(r + 1))) { - - slot = 1 + r + (c * rc); - return true; - } - } - } - - return false; -} - -void ButtonGrid::clear() const { - - tft->fillRect(x, y, w, h, BLACK); -} - -unsigned ButtonGrid::height() const { - return h; -} - -unsigned ButtonGrid::width() const { - return w; -} - -unsigned ButtonGrid::getSlot() const { - return slot; -} diff --git a/src/widgets/canvas.cpp b/src/widgets/canvas.cpp deleted file mode 100644 index 0027a51..0000000 --- a/src/widgets/canvas.cpp +++ /dev/null @@ -1,71 +0,0 @@ -#include "widgets/canvas.h" -#include "constants.h" -#include "helper.h" - -Canvas::Canvas(unsigned x, unsigned y, unsigned w, unsigned h, MCUFRIEND_kbv *tft) - : x {x} - , y {y} - , w {w} - , h {h} - , tft {tft} - , thickness {} - , color {} -{} - -void Canvas::draw() const { - tft->drawRect(x, y, w, h, WHITE); -} - -void Canvas::clear() const { - tft->fillRect(x, y, w, h, BLACK); -} - -bool Canvas::update(unsigned touch_x, unsigned touch_y) { - - if (inRange(touch_x, x + thickness + 2, x + w - thickness - 2) - && inRange(touch_y, y + thickness + 2, y + h - thickness - 2)) { - - tft->fillCircle(touch_x, touch_y, thickness, color); - return true; - } - return false; -} - -unsigned Canvas::height() const { - return h; -} - -unsigned Canvas::width() const { - return w; -} - -unsigned Canvas::heightInternal() const { - return h - 2; -} - -unsigned Canvas::widthInternal() const { - return w - 2; -} - -void Canvas::setThickness(unsigned curThickness) { - thickness = curThickness; -} - -void Canvas::setColor(uint16_t curColor) { - color = curColor; -} - -void Canvas::clearDrawing() { - tft->fillRect(x + 1, y + 1, w - 2, h - 2, BLACK); -} - - -uint16_t Canvas::readPixel(unsigned r, unsigned c) const { - - return tft->readPixel(x + c + 1, y + r + 1); -} - -void Canvas::writePixel(unsigned r, unsigned c, uint16_t color) { - - tft->writePixel(x + c + 1, y + r + 1, color); -} diff --git a/src/widgets/colorSelector.cpp b/src/widgets/colorSelector.cpp deleted file mode 100644 index 1d38e41..0000000 --- a/src/widgets/colorSelector.cpp +++ /dev/null @@ -1,72 +0,0 @@ -#include "widgets/colorSelector.h" -#include "constants.h" -#include "helper.h" - -ColorSelector::ColorSelector(unsigned x, unsigned y, MCUFRIEND_kbv *tft) - : x {x} - , y {y} - , tft {tft} - , curColor {WHITE} -{} - - -void ColorSelector::draw() const { - - unsigned i, j; - uint16_t color; - - for (unsigned r = 0; r < 3; ++r) { - - j = y + (VPAD + PAINT_RADIUS)*(r + 1) + PAINT_RADIUS*r; - - for (unsigned c = 0; c < 3; ++c) { - - i = x + (HPAD + PAINT_RADIUS)*(c + 1) + PAINT_RADIUS*c; - color = COLORS[r][c]; - - tft->fillCircle(i, j, PAINT_RADIUS, color); - tft->drawCircle(i, j, PAINT_RADIUS + 3, WHITE); - } - } -} - -void ColorSelector::clear() const { - tft->fillRect(x, y, WIDTH, HEIGHT, BLACK); -} - -bool ColorSelector::update(unsigned touch_x, unsigned touch_y) { - - unsigned i, j; - uint32_t d; - - for (unsigned r = 0; r < 3; ++r) { - - j = y + (VPAD + PAINT_RADIUS)*(r + 1) + PAINT_RADIUS*r; - - for (unsigned c = 0; c < 3; ++c) { - - i = x + (HPAD + PAINT_RADIUS)*(c + 1) + PAINT_RADIUS*c; - - d = distance(i, j, touch_x, touch_y); - if (d <= PAINT_RADIUS) { - - curColor = COLORS[r][c]; - return true; - } - } - } - - return false; -} - -unsigned ColorSelector::height() const { - return HEIGHT; -} - -unsigned ColorSelector::width() const { - return WIDTH; -} - -uint16_t ColorSelector::getColor() const { - return curColor; -} diff --git a/src/widgets/colorselector.cpp b/src/widgets/colorselector.cpp new file mode 100644 index 0000000..a00a679 --- /dev/null +++ b/src/widgets/colorselector.cpp @@ -0,0 +1,276 @@ +#include "widgets/colorselector.h" + +ColorSelector::ColorSelector(Frame *parent, unsigned x, unsigned y) + : parent {parent} + , widget_x {x} + , widget_y {y} + , widget_absolute_x {x + parent->get_absolute_x() } + , widget_absolute_y {y + parent->get_absolute_y() } +{} + +ColorSelector *ColorSelector::create(Frame *parent, unsigned x, unsigned y) { + ColorSelector *colorselector = new (std::nothrow) ColorSelector(parent, x, y); + if (colorselector != nullptr) { + parent->add_child(colorselector); + } + return colorselector; +} + +ColorSelector *ColorSelector::set_color(unsigned pos, uint16_t new_color) { + if (pos > sizeof(colors) / sizeof(colors[0])) { + return this; + } + + if (new_color == colors[pos]) { + return this; + } + + dirty = true; + colors[pos] = new_color; + return this; +} + +uint16_t ColorSelector::get_color(unsigned pos) const { + if (pos > sizeof(colors) / sizeof(colors[0])) { + return 0; + } + return colors[pos]; +} + +// BasicWidget overrides + +Frame *ColorSelector::get_parent() { return parent; } + +unsigned ColorSelector::get_x() const { return widget_x; } +unsigned ColorSelector::get_y() const { return widget_y; } + +unsigned ColorSelector::get_absolute_x() const { return widget_absolute_x; } +unsigned ColorSelector::get_absolute_y() const { return widget_absolute_y; } + +unsigned ColorSelector::get_width() const { return WIDTH; } +unsigned ColorSelector::get_height() const { return HEIGHT; } + +bool ColorSelector::get_dirty() const { return dirty; } +bool ColorSelector::get_visibility_changed() const { visibility_changed; } + +void ColorSelector::set_dirty() { dirty = true; } +void ColorSelector::set_visibility_changed() { visibility_changed = true; } + +void ColorSelector::draw() { + + unsigned x, y; + + dirty = false; + visibility_changed = false; + + for (unsigned c = 0; c < 3; ++c) { + + x = widget_x + (H_PAD * (c + 1)) + (PAINT_RADIUS * (2*c + 1)); + for (unsigned r = 0; r < 3; ++r) { + + y = widget_y + (V_PAD * (r + 1)) + (PAINT_RADIUS * (2*r + 1)); + + parent->fill_circle(x, y, PAINT_RADIUS, colors[(3 * r) + c]); + parent->draw_circle(x, y, PAINT_RADIUS + 3, WHITE); + } + } +} +void ColorSelector::clear() { + + dirty = false; + visibility_changed = false; + + parent->fill_rect(widget_x, widget_y, WIDTH, HEIGHT, BLACK); +} + +bool ColorSelector::get_intersection(unsigned x, unsigned y) const { + return (widget_x <= x && x <= (widget_x + WIDTH)) + && (widget_y <= y && y <= (widget_y + HEIGHT)); +} + +bool ColorSelector::get_intersection(BasicWidget *other) const { + + unsigned x0 = other->get_absolute_x(); + unsigned y0 = other->get_absolute_y(); + + unsigned x1 = x0 + other->get_width(); + unsigned y1 = y0 + other->get_height(); + + if (( + (widget_absolute_x <= x0 && x0 <= (widget_absolute_x + WIDTH)) + || (widget_absolute_x <= x1 && x1 <= (widget_absolute_x + WIDTH)) + ) + && ( + (widget_absolute_y <= y0 && y0 <= (widget_absolute_y + HEIGHT)) + || (widget_absolute_y <= y1 && y1 <= (widget_absolute_y + HEIGHT)) + )) { + return true; + } + + if (( + (x0 <= widget_absolute_x && widget_absolute_x <= x1) + || (x0 <= (widget_absolute_x + WIDTH) && (widget_absolute_x + WIDTH) <= x1) + ) + && ( + (y0 <= widget_absolute_y && widget_absolute_y <= y1) + || (y0 <= (widget_absolute_y + HEIGHT) && (widget_absolute_y + HEIGHT) <= y1) + )) { + return true; + } + + return false; +} + +bool ColorSelector::propagate_press(unsigned x, unsigned y) { + + unsigned x1, y1; + + if (!get_intersection(x, y)) { + return false; + } + + if (pressed || !enabled) { + return true; + } + + pressed = true; + + x -= widget_x; + y -= widget_y; + + for (unsigned c = 0; c < 3; ++c) { + + x1 = (H_PAD * (c + 1)) + (PAINT_RADIUS * (2*c + 1)); + x1 = (x1 > x) ? (x1 - x) : (x - x1); + x1 *= x1; + for (unsigned r = 0; r < 3; ++r) { + + y1 = (V_PAD * (r + 1)) + (PAINT_RADIUS * (2*r + 1)); + y1 = (y1 > y) ? (y1 - y) : (y - y1); + y1 *= y1; + + if ((x1 + y1) > (PAINT_RADIUS * PAINT_RADIUS)) { + continue;; + } + + if (event_queue != nullptr && on_press != nullptr) { + event_queue->push({on_press, (unsigned *)&colors[(r * 3) + c]}); + } + break; + } + } + + return true; +} +bool ColorSelector::propagate_release(unsigned x, unsigned y) { + + unsigned x1, y1; + + if (!get_intersection(x, y)) { + return false; + } + + if (!pressed) { + return true; + } + + pressed = false; + + x -= widget_x; + y -= widget_y; + + for (unsigned c = 0; c < 3; ++c) { + + x1 = (H_PAD * (c + 1)) + (PAINT_RADIUS * (2*c + 1)); + x1 = (x1 > x) ? (x1 - x) : (x - x1); + x1 *= x1; + for (unsigned r = 0; r < 3; ++r) { + + y1 = (V_PAD * (r + 1)) + (PAINT_RADIUS * (2*r + 1)); + y1 = (y1 > y) ? (y1 - y) : (y - y1); + y1 *= y1; + + if ((x1 + y1) > (PAINT_RADIUS * PAINT_RADIUS)) { + continue;; + } + + if (event_queue != nullptr && on_release != nullptr) { + event_queue->push({on_release, (unsigned *)&colors[(r * 3) + c]}); + } + break; + } + } + + return true; +} + +bool ColorSelector::get_visibility() const { return visible; } +void ColorSelector::set_visibility(bool new_visibility) { + + if (visible == new_visibility) { + return; + } + + dirty = true; + visibility_changed = true; + + visible = new_visibility; +} + +// InteractiveWidget overrides + +ColorSelector *ColorSelector::set_onpress(callback_t callback) { + on_press = callback; + return this; +} + +ColorSelector *ColorSelector::reset_onpress() { + on_press = nullptr; + return this; +} + +ColorSelector *ColorSelector::set_onrelease(callback_t callback) { + on_release = callback; + return this; +} + +ColorSelector *ColorSelector::reset_onrelease() { + on_release = nullptr; + return this; +} + +ColorSelector *ColorSelector::set_event_queue(RingQueueInterface *new_event_queue) { + event_queue = new_event_queue; + return this; +} + +ColorSelector *ColorSelector::reset_event_queue() { + event_queue = nullptr; + return this; +} + +ColorSelector *ColorSelector::set_args(unsigned *new_args) { + args = new_args; + return this; +} + +ColorSelector *ColorSelector::reset_args() { + args = nullptr; + return this; +} + +unsigned *ColorSelector::get_args() { return args; } + +bool ColorSelector::is_pressed() const { return pressed; } + +ColorSelector *ColorSelector::set_interactable(bool new_state) { + if (new_state == enabled) { + return this; + } + + dirty = true; + new_state = new_state; + return this; +} + +bool ColorSelector::get_interactable() const { return enabled; } diff --git a/src/widgets/drawablecanvas.cpp b/src/widgets/drawablecanvas.cpp new file mode 100644 index 0000000..373a5f2 --- /dev/null +++ b/src/widgets/drawablecanvas.cpp @@ -0,0 +1,396 @@ +#include "widgets/drawablecanvas.h" + +static Compressor::segment_t segments1[(DrawableCanvas::DRAWABLE_W + 1) / 2]; +static Compressor::segment_t segments2[DrawableCanvas::DRAWABLE_H][DrawableCanvas::MAX_INLINE_COMPRESSED_SEGMENTS]; +static WiFiClient sock; + +DrawableCanvas::DrawableCanvas(Frame *parent, unsigned x, unsigned y) + : parent {parent} + , pen_color {BLACK} + , pen_size {3} + , widget_x {x} + , widget_y {y} + , widget_absolute_x { x + parent->get_absolute_x() } + , widget_absolute_y { y + parent->get_absolute_y() } + , drawing_buffer(BUFFER_WIDTH, BUFFER_HEIGHT) +{} + +DrawableCanvas *DrawableCanvas::create(Frame *parent, unsigned x, unsigned y) { + + DrawableCanvas *canvas = new (std::nothrow) DrawableCanvas(parent, x, y); + if (canvas == nullptr) { + return canvas; + } + + canvas->cur_row.segments = segments1; + for (unsigned r = 0, offset = 0; r < DRAWABLE_H; ++r, offset += MAX_INLINE_COMPRESSED_SEGMENTS) { + canvas->compressed_rows[r].segments = segments2[r]; + + canvas->compressed_rows[r].pixel_count = DRAWABLE_W; + canvas->compressed_rows[r].segment_count = 1; + canvas->compressed_rows[r].segments[0].code = color_2_code(BLACK); + canvas->compressed_rows[r].segments[0].size = DRAWABLE_W; + } + + sock.setTimeout(8'000); + + parent->add_child(canvas); + return canvas; +} + +DrawableCanvas *DrawableCanvas::set_pen_color(uint16_t new_color) { + pen_color = new_color; + return this; +} +uint16_t DrawableCanvas::get_pen_color() const { return pen_color; } + +DrawableCanvas *DrawableCanvas::set_server_addr(const char *new_server_ip, const uint16_t new_server_port) { + + std::memset(server_ip, 0, sizeof(server_ip)); + std::strncpy(server_ip, new_server_ip, 16); + + server_port = new_server_port; + + return this; +} + +DrawableCanvas *DrawableCanvas::set_pen_size(uint16_t new_size) { + pen_size = new_size; + return this; +} +unsigned DrawableCanvas::get_pen_size() const { return pen_size; } + +DrawableCanvas *DrawableCanvas::draw_at(unsigned x, unsigned y) { + + unsigned col_l, col_h, row_l, row_h; + uint8_t code; + uint8_t raw_pixels[DRAWABLE_W]; + + if (((x - pen_size - 1) <= widget_x) + || ((x + pen_size + 1) >= (widget_x + WIDTH))) { + return this; + } + + if (((y - pen_size - 1) <= widget_y) + || ((y + pen_size + 1) >= (widget_y + HEIGHT))) { + return this; + } + + parent->fill_circle(x, y, pen_size, pen_color); + + drawing_buffer.fillRect(0, 0, BUFFER_WIDTH, BUFFER_HEIGHT, 0); + drawing_buffer.fillCircle(pen_size, pen_size, pen_size, 1); + + x -= widget_x; + y -= widget_y; + + col_l = x - pen_size; + col_h = x + pen_size; + + row_l = y - pen_size; + row_h = y + pen_size; + + code = color_2_code(pen_color); + + for (unsigned r = row_l, final_pixel; r <= row_h; ++r) { + + if (compressed_rows[r].pixel_count < col_l) { + continue; + } + Compressor::uncompress(&compressed_rows[r], raw_pixels, DRAWABLE_W); + final_pixel = compressed_rows[r].pixel_count - 1; + + for (unsigned c = col_l; c <= col_h; ++c) { + + if (!drawing_buffer.getPixel(c - col_l, r - row_l)) { + continue; + } + raw_pixels[c] = code; + final_pixel = max(final_pixel, c); + } + Compressor::compress(&compressed_rows[r], MAX_INLINE_COMPRESSED_SEGMENTS, raw_pixels, final_pixel + 1); + } + + return this; +} + +DrawableCanvas *DrawableCanvas::clear_canvas() { + parent->fill_rect(widget_x + 1, widget_y + 1, WIDTH - 2, HEIGHT - 2, BLACK); + reset_compressed(); + return this; +} + +DrawableCanvas *DrawableCanvas::set_success_callback(InteractiveWidget::callback_t cb) { + on_success = cb; + return this; +} +DrawableCanvas *DrawableCanvas::reset_success_callback() { + on_success = nullptr; + return this; +} + +DrawableCanvas *DrawableCanvas::set_connection_failure_callback(InteractiveWidget::callback_t cb) { + on_connection_failure = cb; + return this; +} +DrawableCanvas *DrawableCanvas::reset_connection_failure_callback() { + on_connection_failure = nullptr; + return this; +} + +DrawableCanvas *DrawableCanvas::set_communication_failure_callback(InteractiveWidget::callback_t cb) { + on_communication_failure = cb; + return this; +} +DrawableCanvas *DrawableCanvas::reset_communication_failure_callback() { + on_communication_failure = nullptr; + return this; +} + +DrawableCanvas *DrawableCanvas::set_args(unsigned *new_args) { + args = new_args; + return this; +} +DrawableCanvas *DrawableCanvas::reset_args() { + args = nullptr; + return this; +} +unsigned *DrawableCanvas::get_args() const { return args; } + +DrawableCanvas *DrawableCanvas::set_event_queue(RingQueueInterface *new_event_queue) { + event_queue = new_event_queue; + return this; +} +DrawableCanvas *DrawableCanvas::reset_event_queue() { + event_queue = nullptr; + return this; +} + +bool DrawableCanvas::save_to_server(uint8_t slot) { + + constexpr static unsigned MAX_SEGMENTS = (DRAWABLE_W + 1) / 2; + uint8_t codes[DRAWABLE_W]; + + BufferedWiFiWriter client; + + if (strnlen(server_ip, 16) == 0 || !client.connect(&sock, server_ip, server_port)) { + + if (event_queue != nullptr && on_connection_failure != nullptr) { + event_queue->push({on_connection_failure, args}); + } + return false; + } + + client.write((uint8_t *)"\x01", 1); + client.write((uint8_t *)&slot, 1); + client.write((uint8_t *)&DRAWABLE_H, 2); + client.write((uint8_t *)&DRAWABLE_W, 2); + + if (!client.flag) { + if (event_queue != nullptr && on_communication_failure != nullptr) { + event_queue->push({on_communication_failure, args}); + } + client.stop(); + return false; + } + + for (unsigned r = 0; r < DRAWABLE_H; ++r) { + + Compressor::uncompress(&compressed_rows[r], codes, DRAWABLE_W); + for (unsigned c = compressed_rows[r].pixel_count; c < DRAWABLE_W; ++c) { + codes[c] = color_2_code(parent->get_at(widget_x + 1 + c, widget_y + 1 + r)); + } + Compressor::compress(&cur_row, MAX_SEGMENTS, codes, DRAWABLE_W); + + if (cur_row.pixel_count == DRAWABLE_W) { + + uint8_t segment_count = cur_row.segment_count; + client.write(&segment_count, 1); + client.write((uint8_t *)(cur_row.segments), sizeof(Compressor::segment_t) * segment_count); + } + else { + + client.write((uint8_t *)"\x00", 1); + client.write(codes, DRAWABLE_W); + } + + if (!client.flag) { + if (event_queue != nullptr && on_communication_failure != nullptr) { + event_queue->push({on_communication_failure, args}); + } + client.stop(); + return false; + } + } + + if (event_queue != nullptr && on_success != nullptr) { + event_queue->push({on_success, args}); + } + + client.stop(); + return true; +} + +bool DrawableCanvas::load_from_server(uint8_t slot) { + + uint8_t codes[DRAWABLE_W]; + + if (strnlen(server_ip, 16) == 0 || !sock.connect(IPAddress(server_ip), server_port)) { + if (event_queue != nullptr && on_connection_failure != nullptr) { + event_queue->push({on_connection_failure, args}); + } + sock.stop(); + return false; + } + + sock.write((uint8_t *)"\x02", 1); + sock.write(&slot, 1); + sock.write((uint8_t *)&DRAWABLE_H, 2); + sock.write((uint8_t *)&DRAWABLE_W, 2); + sock.write((uint8_t *)&DRAWABLE_W, 2); + + for (unsigned r = 0; r < DRAWABLE_H; ++r) { + + signed status = sock.readBytes(codes, DRAWABLE_W); + + if (status != DRAWABLE_W) { + if (event_queue != nullptr && on_communication_failure != nullptr) { + event_queue->push({on_communication_failure, args}); + } + + sock.stop(); + return false; + } + + if (r % 10 == 0) { + sock.write("\x00", 1); + } + + for (unsigned c = 0; c < DRAWABLE_W; ++c) { + parent->set_at(widget_x + 1 + c, widget_y + 1 + r, code_2_color(codes[c])); + } + Compressor::compress(&compressed_rows[r], MAX_INLINE_COMPRESSED_SEGMENTS, codes, DRAWABLE_W); + } + + if (event_queue != nullptr && on_success != nullptr) { + event_queue->push({on_success, args}); + } + + sock.write("\x00", 1); + sock.flush(); + + sock.stop(); + return true; +} + +// BasicWidget overrides + +Frame *DrawableCanvas::get_parent() { return parent; } + +unsigned DrawableCanvas::get_x() const { return widget_x; } +unsigned DrawableCanvas::get_y() const { return widget_y; } + +unsigned DrawableCanvas::get_absolute_x() const { return widget_absolute_x; } +unsigned DrawableCanvas::get_absolute_y() const { return widget_absolute_y; } + +unsigned DrawableCanvas::get_width() const { return WIDTH; } +unsigned DrawableCanvas::get_height() const { return HEIGHT; } + +bool DrawableCanvas::get_dirty() const { return dirty; } +bool DrawableCanvas::get_visibility_changed() const { return visibility_changed; } + +void DrawableCanvas::set_dirty() { dirty = true; } +void DrawableCanvas::set_visibility_changed() { visibility_changed = true; } + +void DrawableCanvas::draw() { + + dirty = false; + visibility_changed = false; + + reset_compressed(); + + parent->fill_rect(widget_x, widget_y, WIDTH, HEIGHT, BLACK); + parent->draw_rect(widget_x, widget_y, WIDTH, HEIGHT, WHITE); +} +void DrawableCanvas::clear() { + + dirty = false; + visibility_changed = false; + + parent->fill_rect(widget_x, widget_y, WIDTH, HEIGHT, BLACK); +} + +bool DrawableCanvas::get_intersection(unsigned x, unsigned y) const { + return (widget_x <= x && x <= (widget_x + WIDTH)) + && (widget_y <= y && y <= (widget_y + HEIGHT)); +} + +bool DrawableCanvas::get_intersection(BasicWidget *other) const { + + unsigned x0 = other->get_absolute_x(); + unsigned y0 = other->get_absolute_y(); + + unsigned x1 = x0 + other->get_width(); + unsigned y1 = y0 + other->get_height(); + + if (( + (widget_absolute_x <= x0 && x0 <= (widget_absolute_x + WIDTH)) + || (widget_absolute_x <= x1 && x1 <= (widget_absolute_x + WIDTH)) + ) + && ( + (widget_absolute_y <= y0 && y0 <= (widget_absolute_y + HEIGHT)) + || (widget_absolute_y <= y1 && y1 <= (widget_absolute_y + HEIGHT)) + )) { + return true; + } + + if (( + (x0 <= widget_absolute_x && widget_absolute_x <= x1) + || (x0 <= (widget_absolute_x + WIDTH) && (widget_absolute_x + WIDTH) <= x1) + ) + && ( + (y0 <= widget_absolute_y && widget_absolute_y <= y1) + || (y0 <= (widget_absolute_y + HEIGHT) && (widget_absolute_y + HEIGHT) <= y1) + )) { + return true; + } + + return false; +} + +bool DrawableCanvas::propagate_press(unsigned x, unsigned y) { + + if (!get_intersection(x, y)) { + return false; + } + + return true; +} +bool DrawableCanvas::propagate_release(unsigned x, unsigned y) { + + if (!get_intersection(x, y)) { + return false; + } + + return true; +} + +bool DrawableCanvas::get_visibility() const { return visible; } +void DrawableCanvas::set_visibility(bool new_visibility) { + if (new_visibility == visible) { + return; + } + + dirty = true; + visibility_changed = true; + visible = new_visibility; +} + +void DrawableCanvas::reset_compressed() { //todo this is to be used in many places, not just clear + for (unsigned r = 0; r < DRAWABLE_H; ++r) { + compressed_rows[r].pixel_count = DRAWABLE_W; + compressed_rows[r].segment_count = 1; + compressed_rows[r].segments[0].code = color_2_code(BLACK); + compressed_rows[r].segments[0].size = DRAWABLE_W; + } +} diff --git a/src/widgets/keyboard.cpp b/src/widgets/keyboard.cpp new file mode 100644 index 0000000..1300a7e --- /dev/null +++ b/src/widgets/keyboard.cpp @@ -0,0 +1,322 @@ +#include "widgets/keyboard.h" + +Keyboard::Keyboard(Frame *parent) +: Window(parent, 0, parent->get_height() - 160, parent->get_width(), 160) +{ + (&style) + ->set_bg_color(GRAY) + ->set_border_radius(0) + ->set_border_width(0); + + exit = Button::create(this, 3, 136, 20, 20); + + shift = Button::create(this, 17, (32 * 3) + 1, 62 + 1, 31); + space = Button::create(this, 32 + 32 - 5, (32 * 4) + 1, 32 * 6, 31); + backspace = Button::create(this, (9 * 32) + 1 - 5, (32 * 4) + 1, 31, 31); + + exit + ->set_message("X") + ->get_style() + ->set_text_size(1) + ->set_bg_color(RED) + ->set_fg_color(BLACK) + ->set_border_width(0) + ->set_border_radius(10); + + shift + ->set_message("~") + ->get_style() + ->set_bg_color(blend_color(GRAY, BLACK, 100)) + ->set_pressed_bg_color(blend_color(GRAY, BLACK, 200)) + ->set_fg_color(WHITE) + ->set_pressed_fg_color(WHITE) + ->set_border_width(1) + ->set_border_radius(2) + ->set_text_size(2); + + space + ->set_message(" ") + ->get_style() + ->set_bg_color(blend_color(GRAY, BLACK, 100)) + ->set_pressed_bg_color(blend_color(GRAY, BLACK, 200)) + ->set_fg_color(WHITE) + ->set_pressed_fg_color(WHITE) + ->set_border_width(1) + ->set_border_radius(2) + ->set_text_size(2); + + backspace + ->set_message("<<") + ->get_style() + ->set_bg_color(blend_color(GRAY, BLACK, 100)) + ->set_pressed_bg_color(blend_color(GRAY, BLACK, 200)) + ->set_fg_color(WHITE) + ->set_pressed_fg_color(WHITE) + ->set_border_width(1) + ->set_border_radius(2) + ->set_text_size(2); + + + for (unsigned i = 0, idx = 0; i < NUM_ROWS; ++i) { + for (unsigned j = 0; j < NUM_KEYS[i]; ++j, ++idx) { + + if (i <= 1) { + keys[idx] = Button::create(this, (32 * j) + 1, (32 * i) + 1, 31, 31); + } + else if (i <= 2) { + keys[idx] = Button::create(this, (32 * j) + 17, (32 * i) + 1, 31, 31); + } + else if (i <= 3) { + keys[idx] = Button::create(this, (32 * j) + 17 + 64, (32 * i) + 1, 31, 31); + } + else { + keys[idx] = Button::create(this, ((j == 0) ? 32 : (8 * 32) + 1) - 5, (32 * i) + 1, 31, 31); + } + + keys[idx] + ->set_message(KEYBOARD_KEYS[0][i][j]) + ->get_style() + ->set_bg_color(blend_color(GRAY, BLACK, 100)) + ->set_pressed_bg_color(blend_color(GRAY, BLACK, 200)) + ->set_fg_color(WHITE) + ->set_pressed_fg_color(WHITE) + ->set_border_width(1) + ->set_border_radius(2) + ->set_text_size(2); + } + } +} + +void Keyboard::assign_keys() { + + for (unsigned i = 1, idx = NUM_KEYS[0]; i < (NUM_ROWS-1); ++i) { + for (unsigned j = 0; j < NUM_KEYS[i]; ++j, ++idx) { + keys[idx]->set_message(KEYBOARD_KEYS[shift_i][i][j]); + } + } +} + +Keyboard *Keyboard::create(Frame *parent) { + + Keyboard *keyboard = new (std::nothrow) Keyboard(parent); + if (keyboard != nullptr) { + parent->add_child(keyboard); + } + return keyboard; +} + +Keyboard *Keyboard::set_shift_index(unsigned new_shift_i) { + shift_i = new_shift_i; + assign_keys(); + dirty = true; +} + +unsigned Keyboard::get_shift_index() const { return shift_i; } + +bool Keyboard::propagate_press(unsigned x, unsigned y) { + + if (!get_intersection(x, y)) { + return false; + } + + if (pressed || !enabled) { + return true; + } + + { + unsigned cur_epoch = millis(); + if ((cur_epoch - last_press_epoch) < DEBOUNCE_THRESH) { + return true; + } + last_press_epoch = cur_epoch; + } + + x -= widget_x; + y -= widget_y; + + press_info.special = 0; + + pressed = true; + + if (shift->propagate_press(x, y)) { + + press_info.shift = 1; + if (event_queue != nullptr && on_press != nullptr) { + event_queue->push({on_press, (unsigned *)&press_info}); + } + return true; + } + + if (space->propagate_press(x, y)) { + + press_info.key = ' '; + if (event_queue != nullptr && on_press != nullptr) { + event_queue->push({on_press, (unsigned *)&press_info}); + } + return true; + } + + if (backspace->propagate_press(x, y)) { + + press_info.backspace = 1; + if (event_queue != nullptr && on_press != nullptr) { + event_queue->push({on_press, (unsigned *)&press_info}); + } + return true; + } + + if (exit->propagate_press(x, y)) { + + press_info.exit = 1; + if (event_queue != nullptr && on_press != nullptr) { + event_queue->push({on_press, (unsigned *)&press_info}); + } + return true; + } + + for (unsigned i = 0, idx = 0; i < NUM_ROWS; ++i) { + for (unsigned j = 0; j < NUM_KEYS[i]; ++j, ++idx) { + if (keys[idx]->propagate_press(x, y)) { + + press_info.key = KEYBOARD_KEYS[shift_i][i][j][0]; + if (event_queue != nullptr && on_press != nullptr) { + event_queue->push({on_press, (unsigned *)&press_info}); + } + return true; + } + } + } + + return true; +} + +bool Keyboard::propagate_release(unsigned x, unsigned y) { + + if (!get_intersection(x, y)) { + return false; + } + + if (!pressed) { + return true; + } + + x -= widget_x; + y -= widget_y; + + pressed = false; + + release_info.special = 0; + + if (shift->propagate_release(x, y)) { + + (++shift_i) %= 3; + assign_keys(); + + release_info.shift = 1; + if (event_queue != nullptr && on_release != nullptr) { + event_queue->push({on_release, (unsigned *)&release_info}); + } + return true; + } + + if (space->propagate_release(x, y)) { + + release_info.key = ' '; + if (event_queue != nullptr && on_release != nullptr) { + event_queue->push({on_release, (unsigned *)&release_info}); + } + return true; + } + + if (backspace->propagate_release(x, y)) { + + release_info.backspace = 1; + if (event_queue != nullptr && on_release != nullptr) { + event_queue->push({on_release, (unsigned *)&release_info}); + } + return true; + } + + if (exit->propagate_release(x, y)) { + + release_info.exit = 1; + if (event_queue != nullptr && on_release != nullptr) { + event_queue->push({on_release, (unsigned *)&release_info}); + } + + set_visibility(false); + return true; + } + + for (unsigned i = 0, idx = 0; i < NUM_ROWS; ++i) { + for (unsigned j = 0; j < NUM_KEYS[i]; ++j, ++idx) { + if (keys[idx]->propagate_release(x, y)) { + release_info.key = KEYBOARD_KEYS[shift_i][i][j][0]; + if (event_queue != nullptr && on_release != nullptr) { + event_queue->push({on_release, (unsigned *)&release_info}); + } + return true; + } + } + } + + return true; +} + +// InteractiveWidget overrides + +Keyboard *Keyboard::set_onpress(callback_t callback) { + on_press = callback; + return this; +} + +Keyboard *Keyboard::reset_onpress() { + on_press = nullptr; + return this; +} + +Keyboard *Keyboard::set_onrelease(callback_t callback) { + on_release = callback; + return this; +} + +Keyboard *Keyboard::reset_onrelease() { + on_release = nullptr; + return this; +} + +Keyboard *Keyboard::set_event_queue(RingQueueInterface *new_event_queue) { + event_queue = new_event_queue; + return this; +} + +Keyboard *Keyboard::reset_event_queue() { + event_queue = nullptr; + return this; +} + +Keyboard *Keyboard::set_args(unsigned *new_args) { + args = new_args; + return this; +} + +Keyboard *Keyboard::reset_args() { + args = nullptr; + return this; +} + +unsigned *Keyboard::get_args() { return args; } + +bool Keyboard::is_pressed() const { return pressed; } + +Keyboard *Keyboard::set_interactable(bool new_state) { + if (new_state == enabled) { + return this; + } + + dirty = true; + enabled = new_state; + return this; +} + +bool Keyboard::get_interactable() const { return enabled; } diff --git a/src/widgets/label.cpp b/src/widgets/label.cpp new file mode 100644 index 0000000..e761f71 --- /dev/null +++ b/src/widgets/label.cpp @@ -0,0 +1,362 @@ +#include "widgets/label.h" + +Label::Label(Frame *parent, unsigned x, unsigned y, unsigned width, unsigned height) + : parent {parent} + , widget_x {x} + , widget_y {y} + , widget_absolute_x { x + parent->get_absolute_x() } + , widget_absolute_y { y + parent->get_absolute_y() } + , widget_w {width} + , widget_h {height} +{} + +Label *Label::create(Frame *parent, unsigned x, unsigned y, unsigned width, unsigned height) { + Label *label = new (std::nothrow) Label(parent, x, y, width, height); + if (label != nullptr) { + parent->add_child(label); + } + return label; +} + +Label *Label::set_message(const char msg_ptr[]) { + dirty = true; + message = msg_ptr; + + // render_text(); + + return this; +} + +String Label::get_message() const { + return message; +} + +unsigned Label::get_message_len() const { + return message.length(); +} + +Label *Label::append_to_message(char ch) { + dirty = true; + message += ch; + + // render_text(); + + return this; +} + +Label *Label::pop_from_message() { + + if (message.length() <= 0) { + return this; + } + + dirty = true; + message.remove(message.length() - 1); + + // render_text(); + + return this; +} + +LabelStyle *Label::get_style() { + dirty = true; + return &style; +} + +// BasicWidget overrides + +Frame *Label::get_parent() { return parent; } + +unsigned Label::get_x() const { return widget_x; } +unsigned Label::get_y() const { return widget_y; } + +unsigned Label::get_absolute_x() const { return widget_absolute_x; } +unsigned Label::get_absolute_y() const { return widget_absolute_y; } + +unsigned Label::get_width() const { return widget_w; } +unsigned Label::get_height() const { return widget_h; } + +bool Label::get_dirty() const { return dirty; } +bool Label::get_visibility_changed() const { return visibility_changed; } + +void Label::set_dirty() { dirty = true; } +void Label::set_visibility_changed() { visibility_changed = true; } + +void Label::draw() { + + dirty = false; + visibility_changed = false; + + if (style.border_radius != 0) { + if (style.border_w != 0) { + parent->fill_round_rect( + widget_x, + widget_y, + widget_w, + widget_h, + style.border_radius, + style.border_color + ); + } + parent->fill_round_rect( + widget_x + style.border_w, + widget_y + style.border_w, + widget_w - 2*style.border_w, + widget_h - 2*style.border_w, + style.border_radius, + style.bg_color + ); + } + else { + if (style.border_w != 0) { + parent->fill_rect( + widget_x, + widget_y, + widget_w, + widget_h, + style.border_color + ); + } + parent->fill_rect( + widget_x + style.border_w, + widget_y + style.border_w, + widget_w - 2*style.border_w, + widget_h - 2*style.border_w, + style.bg_color + ); + } + + render_text(); +} + +void Label::clear() { + + dirty = false; + visibility_changed = false; + + parent->fill_rect(widget_x, widget_y, widget_w, widget_h, BLACK); +} + +bool Label::get_intersection(unsigned x, unsigned y) const { + return (widget_x <= x && x <= (widget_x + widget_w)) + && (widget_y <= y && y <= (widget_y + widget_h)); +} + +bool Label::get_intersection(BasicWidget *other) const { + + unsigned x0 = other->get_absolute_x(); + unsigned y0 = other->get_absolute_y(); + + unsigned x1 = x0 + other->get_width(); + unsigned y1 = y0 + other->get_height(); + + if (( + (widget_absolute_x <= x0 && x0 <= (widget_absolute_x + widget_w)) + || (widget_absolute_x <= x1 && x1 <= (widget_absolute_x + widget_w)) + ) + && ( + (widget_absolute_y <= y0 && y0 <= (widget_absolute_y + widget_h)) + || (widget_absolute_y <= y1 && y1 <= (widget_absolute_y + widget_h)) + )) { + return true; + } + + if (( + (x0 <= widget_absolute_x && widget_absolute_x <= x1) + || (x0 <= (widget_absolute_x + widget_w) && (widget_absolute_x + widget_w) <= x1) + ) + && ( + (y0 <= widget_absolute_y && widget_absolute_y <= y1) + || (y0 <= (widget_absolute_y + widget_h) && (widget_absolute_y + widget_h) <= y1) + )) { + return true; + } + + return false; +} + +bool Label::propagate_press(unsigned x, unsigned y) { + + if (!get_intersection(x, y)) { + return false; + } + + return true; +} + +bool Label::propagate_release(unsigned x, unsigned y) { + + if (!get_intersection(x, y)) { + return false; + } + + return true; +} + +bool Label::get_visibility() const { return visible; } +void Label::set_visibility(bool new_visibility) { + + if (visible == new_visibility) { + return; + } + + dirty = true; + visibility_changed = true; + + visible = new_visibility; +} + +// void Label::render_text() { + +// int16_t x1, y1; +// uint16_t w1, h1; + +// parent->get_text_bounds( +// message.c_str(), +// style.text_size, +// 0, +// 0, +// &x1, +// &y1, +// &w1, +// &h1 +// ); + +// parent->print( +// message.c_str(), +// (style.h_align == LabelStyle::HorizontalAlignment::CENTER_ALIGN) +// ? (2*widget_x + widget_w - w1) / 2 +// : (style.h_align == LabelStyle::HorizontalAlignment::LEFT_ALIGN) +// ? widget_x + style.border_w +// : widget_x + widget_w - style.border_w - w1, +// (style.v_align == LabelStyle::VerticalAlignment::MIDDLE_ALIGN) +// ? (2*widget_y + widget_h - h1) / 2 +// : (style.v_align == LabelStyle::VerticalAlignment::TOP_ALIGN) +// ? widget_y + style.border_w +// : widget_y + widget_h - style.border_w - h1, +// style.text_size, +// style.fg_color +// ); +// } + +void Label::render_text() { + + int16_t x1, y1; + uint16_t w1, h1; + + switch (style.text_size) { + case 1: + parent->set_font(font_1); + break; + case 2: + parent->set_font(font_2); + break; + case 3: + parent->set_font(font_3); + break; + default: + parent->set_font(font_4); + break; + } + + parent->get_text_bounds( + message.c_str(), + 1, + 0, + 0, + &x1, + &y1, + &w1, + &h1 + ); + + parent->print( + message.c_str(), + (style.h_align == LabelStyle::HorizontalAlignment::CENTER_ALIGN) + ? (2*widget_x + widget_w - w1) / 2 + : (style.h_align == LabelStyle::HorizontalAlignment::LEFT_ALIGN) + ? widget_x + style.border_w + : widget_x + widget_w - style.border_w - w1, + ((style.v_align == LabelStyle::VerticalAlignment::MIDDLE_ALIGN) + ? (2*widget_y + widget_h - h1) / 2 + : (style.v_align == LabelStyle::VerticalAlignment::TOP_ALIGN) + ? widget_y + style.border_w + : widget_y + widget_h - style.border_w - h1) + h1, + 1,// style.text_size, + style.fg_color + ); +} + +// Label Style + +LabelStyle *LabelStyle::set_horizontal_alignment(LabelStyle::HorizontalAlignment new_h_align) { + h_align = new_h_align; + return this; +} + +LabelStyle::HorizontalAlignment LabelStyle::get_horizontal_alignment() const { + return h_align; +} + +LabelStyle *LabelStyle::set_vertical_alignment(LabelStyle::VerticalAlignment new_v_align) { + v_align = new_v_align; + return this; +} + +LabelStyle::VerticalAlignment LabelStyle::get_vertical_alignment() const { + return v_align; +} + +LabelStyle *LabelStyle::set_text_size(unsigned int new_text_size) { + text_size = new_text_size; + return this; +} + +unsigned LabelStyle::get_text_size() const { + return text_size; +} + +LabelStyle *LabelStyle::set_border_radius(unsigned int new_border_radius) { + border_radius = new_border_radius; + return this; +} + +unsigned LabelStyle::get_border_radius() const { + return border_radius; +} + +LabelStyle *LabelStyle::set_border_width(unsigned int new_border_w) { + border_w = new_border_w; + return this; +} + +unsigned LabelStyle::get_border_width() const { + return border_w; +} + +LabelStyle *LabelStyle::set_border_color(uint16_t new_border_color) { + border_color = new_border_color; + return this; +} + +uint16_t LabelStyle::get_border_color() const { + return border_color; +} + +LabelStyle *LabelStyle::set_fg_color(uint16_t new_fg_color) { + fg_color = new_fg_color; + return this; +} + +uint16_t LabelStyle::get_fg_color() const { + return fg_color; +} + +LabelStyle *LabelStyle::set_bg_color(uint16_t new_bg_color) { + bg_color = new_bg_color; + return this; +} + +uint16_t LabelStyle::get_bg_color() const { + return bg_color; +} diff --git a/src/widgets/pensizeselector.cpp b/src/widgets/pensizeselector.cpp new file mode 100644 index 0000000..cd60e3c --- /dev/null +++ b/src/widgets/pensizeselector.cpp @@ -0,0 +1,297 @@ +#include "widgets/pensizeselector.h" + +PenSizeSelector::PenSizeSelector(Frame *parent, unsigned x, unsigned y) + : parent {parent} + , widget_x {x} + , widget_y {y} + , widget_absolute_x {x + parent->get_absolute_x() } + , widget_absolute_y {y + parent->get_absolute_y() } +{} + +PenSizeSelector *PenSizeSelector::create(Frame *parent, unsigned x, unsigned y) { + PenSizeSelector *pensizeselector = new (std::nothrow) PenSizeSelector(parent, x, y); + if (pensizeselector != nullptr) { + parent->add_child(pensizeselector); + } + return pensizeselector; +} + +PenSizeSelector *PenSizeSelector::set_size(unsigned pos, uint16_t new_size) { + if (pos > sizeof(sizes) / sizeof(sizes[0])) { + return this; + } + + dirty = true; + sizes[pos] = new_size; + return this; +} + +uint16_t PenSizeSelector::get_size(unsigned pos) const { + if (pos > sizeof(sizes) / sizeof(sizes[0])) { + return 0; + } + + return sizes[pos]; +} + +PenSizeSelector *PenSizeSelector::set_active_size(unsigned pos) { + if (pos > sizeof(sizes) / sizeof(sizes[0])) { + return this; + } + + dirty = true; + active_size = pos; + return this; +} +uint16_t PenSizeSelector::get_active_size() const { return sizes[active_size]; } + +PenSizeSelector *PenSizeSelector::set_color(uint16_t new_color) { + if (new_color == color) { + return this; + } + + dirty = true; + color = new_color; + return this; +} + +uint16_t PenSizeSelector::get_color() const { + return color; +} + +// BasicWidget overrides + +Frame *PenSizeSelector::get_parent() { return parent; } + +unsigned PenSizeSelector::get_x() const { return widget_x; } +unsigned PenSizeSelector::get_y() const { return widget_y; } + +unsigned PenSizeSelector::get_absolute_x() const { return widget_absolute_x; } +unsigned PenSizeSelector::get_absolute_y() const { return widget_absolute_y; } + +unsigned PenSizeSelector::get_width() const { return WIDTH; } +unsigned PenSizeSelector::get_height() const { return HEIGHT; } + +bool PenSizeSelector::get_dirty() const { return dirty; } +bool PenSizeSelector::get_visibility_changed() const { return visibility_changed; } + +void PenSizeSelector::set_dirty() { dirty = true; } +void PenSizeSelector::set_visibility_changed() { visibility_changed = true; } + +void PenSizeSelector::draw() { + + unsigned x, y, s; + + dirty = false; + visibility_changed = false; + + for (unsigned c = 0; c < 4; ++c) { + + x = widget_x + (2*c + 1) * H_PAD; + y = widget_y + (HEIGHT / 2); + + s = sizes[c]; + + parent->fill_circle(x, y, s, (color == BLACK) + ? (blend_color(blend_color(BLACK, WHITE, 12), BLUE, 10)) + : (color)); + + parent->draw_circle(x, y, s + 3, (c == active_size) + ? WHITE + : BLACK); + } +} +void PenSizeSelector::clear() { + + dirty = false; + visibility_changed = false; + + parent->fill_rect(widget_x, widget_y, WIDTH, HEIGHT, BLACK); +} + +bool PenSizeSelector::get_intersection(unsigned x, unsigned y) const { + + return (widget_x <= x && x <= (widget_x + WIDTH)) + && (widget_y <= y && y <= (widget_y + HEIGHT)); +} + +bool PenSizeSelector::get_intersection(BasicWidget *other) const { + + unsigned x0 = other->get_absolute_x(); + unsigned y0 = other->get_absolute_y(); + + unsigned x1 = x0 + other->get_width(); + unsigned y1 = y0 + other->get_height(); + + if (( + (widget_absolute_x <= x0 && x0 <= (widget_absolute_x + WIDTH)) + || (widget_absolute_x <= x1 && x1 <= (widget_absolute_x + WIDTH)) + ) + && ( + (widget_absolute_y <= y0 && y0 <= (widget_absolute_y + HEIGHT)) + || (widget_absolute_y <= y1 && y1 <= (widget_absolute_y + HEIGHT)) + )) { + return true; + } + + if (( + (x0 <= widget_absolute_x && widget_absolute_x <= x1) + || (x0 <= (widget_absolute_x + WIDTH) && (widget_absolute_x + WIDTH) <= x1) + ) + && ( + (y0 <= widget_absolute_y && widget_absolute_y <= y1) + || (y0 <= (widget_absolute_y + HEIGHT) && (widget_absolute_y + HEIGHT) <= y1) + )) { + return true; + } + + return false; +} + +bool PenSizeSelector::propagate_press(unsigned x, unsigned y) { + + unsigned x1, y1; + + if (!get_intersection(x, y)) { + return false; + } + + if (pressed || !enabled) { + return true; + } + + pressed = true; + + x -= widget_x; + y -= widget_y; + + y1 = HEIGHT / 2; + y1 = (y1 > y) ? (y1 - y) : (y - y1); + y1 *= y1; + + for (unsigned c = 0; c < 4; ++c) { + + x1 = (2*c + 1) * H_PAD; + x1 = (x1 > x) ? (x1 - x) : (x - x1); + x1 *= x1; + + if ((x1 + y1) > ((2+sizes[c]) * (2+sizes[c]))) { + continue; + } + + if (event_queue != nullptr && on_press != nullptr) { + event_queue->push({on_press, (unsigned *)&sizes[active_size]}); + } + break; + } + + return true; +} +bool PenSizeSelector::propagate_release(unsigned x, unsigned y) { + + unsigned x1, y1; + + if (!get_intersection(x, y)) { + return false; + } + + if (!pressed) { + return true; + } + + pressed = false; + + x -= widget_x; + y -= widget_y; + + y1 = HEIGHT / 2; + y1 = (y1 > y) ? (y1 - y) : (y - y1); + y1 *= y1; + + for (unsigned c = 0; c < 4; ++c) { + + x1 = (2*c + 1) * H_PAD; + x1 = (x1 > x) ? (x1 - x) : (x - x1); + x1 *= x1; + + if ((x1 + y1) > ((2+sizes[c]) * (2+sizes[c]))) { + continue; + } + + set_active_size(c); + if (event_queue != nullptr && on_release != nullptr) { + event_queue->push({on_release, (unsigned *)&sizes[active_size]}); + } + break; + } + + return true; +} + +bool PenSizeSelector::get_visibility() const { return visible; } +void PenSizeSelector::set_visibility(bool new_visibility) { + if (visible == new_visibility) { + return; + } + + dirty = true; + visibility_changed = true; + + visible = new_visibility; +} + +// InteractiveWidget overrides + +PenSizeSelector *PenSizeSelector::set_onpress(callback_t callback) { + on_press = callback; + return this; +} +PenSizeSelector *PenSizeSelector::reset_onpress() { + on_press = nullptr; + return this; +} + +PenSizeSelector *PenSizeSelector::set_onrelease(callback_t callback) { + on_release = callback; + return this; +} +PenSizeSelector *PenSizeSelector::reset_onrelease() { + on_release = nullptr; + return this; +} + +PenSizeSelector *PenSizeSelector::set_event_queue(RingQueueInterface *new_event_queue) { + event_queue = new_event_queue; + return this; +} + +PenSizeSelector *PenSizeSelector::reset_event_queue() { + event_queue = nullptr; + return this; +} + +PenSizeSelector *PenSizeSelector::set_args(unsigned *new_args) { + args = new_args; + return this; +} + +PenSizeSelector *PenSizeSelector::reset_args() { + args = nullptr; + return this; +} + +unsigned *PenSizeSelector::get_args() { return args; } + +bool PenSizeSelector::is_pressed() const { return pressed; } + +PenSizeSelector *PenSizeSelector::set_interactable(bool new_state) { + if (new_state == enabled) { + return this; + } + + dirty = true; + new_state = new_state; + return this; +} + +bool PenSizeSelector::get_interactable() const { return enabled; } \ No newline at end of file diff --git a/src/widgets/textbox.cpp b/src/widgets/textbox.cpp new file mode 100644 index 0000000..1b0edef --- /dev/null +++ b/src/widgets/textbox.cpp @@ -0,0 +1,119 @@ +#include "widgets/textbox.h" + +TextBox::TextBox(Frame *parent, unsigned x, unsigned y, unsigned width, unsigned height) + : Label(parent, x, y, width, height) +{} + +TextBox *TextBox::create(Frame *parent, unsigned x, unsigned y, unsigned width, unsigned height) { + TextBox *textbox = new (std::nothrow) TextBox(parent, x, y, width, height); + if (textbox != nullptr) { + parent->add_child(textbox); + } + return textbox; +} + +bool TextBox::propagate_press(unsigned x, unsigned y) { + + if (!get_intersection(x, y)) { + return false; + } + + if (pressed || !enabled) { + return true; + } + + { + unsigned cur_epoch = millis(); + if ((cur_epoch - last_press_epoch) < DEBOUNCE_THRESH) { + return true; + } + last_press_epoch = cur_epoch; + } + + dirty = true; + pressed = true; + + if (event_queue != nullptr && on_press != nullptr) { + event_queue->push({on_press, args}); + } + + return true; +} + +bool TextBox::propagate_release(unsigned x, unsigned y) { + + if (!get_intersection(x, y)) { + return false; + } + + if (!pressed) { + return true; + } + + dirty = true; + pressed = false; + + if (event_queue != nullptr && on_release != nullptr) { + event_queue->push({on_release, args}); + } + + return true; +} + +// InteractiveWidget overrides + +TextBox *TextBox::set_onpress(callback_t callback) { + on_press = callback; + return this; +} + +TextBox *TextBox::reset_onpress() { + on_press = nullptr; + return this; +} + +TextBox *TextBox::set_onrelease(callback_t callback) { + on_release = callback; + return this; +} + +TextBox *TextBox::reset_onrelease() { + on_release = nullptr; + return this; +} + +TextBox *TextBox::set_event_queue(RingQueueInterface *new_event_queue) { + event_queue = new_event_queue; + return this; +} + +TextBox *TextBox::reset_event_queue() { + event_queue = nullptr; + return this; +} + +TextBox *TextBox::set_args(unsigned *new_args) { + args = new_args; + return this; +} + +TextBox *TextBox::reset_args() { + args = nullptr; + return this; +} + +unsigned *TextBox::get_args() { return args; } + +bool TextBox::is_pressed() const { return pressed; } + +TextBox *TextBox::set_interactable(bool new_state) { + if (new_state == enabled) { + return this; + } + + dirty = true; + new_state = new_state; + return this; +} + +bool TextBox::get_interactable() const { return enabled; } diff --git a/src/widgets/thicknessSelector.cpp b/src/widgets/thicknessSelector.cpp deleted file mode 100644 index 104393a..0000000 --- a/src/widgets/thicknessSelector.cpp +++ /dev/null @@ -1,75 +0,0 @@ -#include "widgets/thicknessSelector.h" -#include "constants.h" -#include "helper.h" - -ThicknessSelector::ThicknessSelector(unsigned x, unsigned y, MCUFRIEND_kbv *tft) - : x {x} - , y {y} - , curSelected {RADII[0]} - , tft {tft} -{} - -void ThicknessSelector::setColor(uint16_t clr) { - color = clr; -} - -void ThicknessSelector::draw() const { - - unsigned i, j, t; - - for (unsigned c = 0; c < 4; ++c) { - - i = x + (2*c + 1)*PAD; - j = y + HEIGHT/2; - t = RADII[c]; - - (color == BLACK) - ? tft->fillCircle(i, j, t, TFT_DARKGREY) - : tft->fillCircle(i, j, t, color); - - (t == curSelected) - ? tft->drawCircle(i, j, t + 3, WHITE) - : tft->drawCircle(i, j, t + 3, BLACK); - } -} - -void ThicknessSelector::clear() const { - tft->fillRect(x, y, WIDTH, HEIGHT, BLACK); -} - -bool ThicknessSelector::update(unsigned touch_x, unsigned touch_y) { - - unsigned i, j, t, d; - - for (unsigned c = 0; c < 4; ++c) { - - i = x + (2*c + 1)*PAD; - j = y + HEIGHT/2; - t = RADII[c]; - - d = distance(i, j, touch_x, touch_y); - - // the pen is in this color if the distance between its centre - // and the pen is less than the radius of the paint - if (d <= t) { - - curSelected = t; - - return true; - } - } - - return false; -} - -unsigned ThicknessSelector::height() const { - return HEIGHT; -} - -unsigned ThicknessSelector::width() const { - return WIDTH; -} - -uint16_t ThicknessSelector::getThickness() const { - return curSelected; -} diff --git a/src/widgets/view.cpp b/src/widgets/view.cpp new file mode 100644 index 0000000..96edc8c --- /dev/null +++ b/src/widgets/view.cpp @@ -0,0 +1,287 @@ +#include "algorithm" +#include "widgets/view.h" + +View::View(App *app) + : app {app} +{ + app->add_view(this); +} + +View *View::create(App *app) { + View *view = new View(app); + return view; +} + +// BasicWidget overrides + +App *View::get_parent() { return app; } + +unsigned View::get_x() const { return 0; } +unsigned View::get_y() const { return 0; } + +unsigned View::get_absolute_x() const { return 0; } +unsigned View::get_absolute_y() const { return 0; } + +unsigned View::get_width() const { return app->get_width(); } +unsigned View::get_height() const { return app->get_height(); } + +bool View::get_dirty() const { return dirty; } +bool View::get_visibility_changed() const { return false; } + +void View::set_dirty() { dirty = true; } +void View::set_visibility_changed() { return; } + +void View::draw() { + + dirty = false; + + for (auto it = children.rbegin(); it != children.rend(); ++it) { + + BasicWidget *child = *it; + + if (child->get_visibility()) { + child->draw(); + } + } +} + +void View::clear() { + + dirty = false; + app->clear(); +} + +bool View::get_intersection(unsigned int x, unsigned int y) const { return true; } +bool View::get_intersection(BasicWidget *other) const { return true; } + +bool View::propagate_press(unsigned x, unsigned y) { + + for (auto &child : children) { + if (child->get_visibility() && child->propagate_press(x, y)) { + break; + } + } + + return true; +} + +bool View::propagate_release(unsigned x, unsigned y) { + + for (auto &child : children) { + if (child->get_visibility() && child->propagate_release(x, y)) { + break; + } + } + + return true; +} + +bool View::get_visibility() const { return true; } +void View::set_visibility(bool new_visibility) { return; } + +// Frame Overrides + +View *View::set_at(unsigned int x, unsigned int y, uint16_t color) { + app->set_at(x, y, color); + return this; +} + +uint16_t View::get_at(unsigned int x, unsigned int y) const { + return app->get_at(x, y); +} + +View *View::draw_line(unsigned int x0, unsigned int y0, unsigned int x1, unsigned int y1, uint16_t color) { + app->draw_line(x0, y0, x0, y0, color); + return this; +} + +View *View::draw_rect(unsigned int x, unsigned int y, unsigned int w, unsigned int h, uint16_t color) { + app->draw_rect(x, y, w, h, color); + return this; +} + +View *View::fill_rect(unsigned int x, unsigned int y, unsigned int w, unsigned int h, uint16_t color) { + app->fill_rect(x, y, w, h, color); + return this; +} + +View *View::draw_round_rect(unsigned int x, unsigned int y, unsigned int w, unsigned int h, unsigned int r, + uint16_t color) { + app->draw_round_rect(x, y, w, h, r, color); + return this; +} + +View *View::fill_round_rect(unsigned int x, unsigned int y, unsigned int w, unsigned int h, unsigned int r, + uint16_t color) { + app->fill_round_rect(x, y, w, h, r, color); + return this; +} + +View *View::draw_circle(unsigned int x, unsigned int y, unsigned int r, uint16_t color) { + app->draw_circle(x, y, r, color); + return this; +} + +View *View::fill_circle(unsigned int x, unsigned int y, unsigned int r, uint16_t color) { + app->fill_circle(x, y, r, color); + return this; +} + +View *View::get_text_bounds(const char *text, unsigned int text_size, unsigned int x, unsigned int y, int16_t *x1, + int16_t *y1, uint16_t *w, uint16_t *h) { + app->get_text_bounds(text, text_size, x, y, x1, y1, w, h); + return this; +} + +View *View::set_font(const GFXfont *f) { + app->set_font(f); + return this; +} + +View *View::print(const char *text, unsigned int x, unsigned int y, unsigned int text_size, uint16_t fg_color) { + app->print(text, x, y, text_size, fg_color); + return this; +} + +View *View::print_opaque(const char *text, unsigned int x, unsigned int y, unsigned int text_size, uint16_t fg_color, + uint16_t bg_color) { + app->print_opaque(text, x, y, text_size, fg_color, bg_color); + return this; +} + +View *View::draw_rgb_bitmap(unsigned x, unsigned y, const uint16_t *data, unsigned width, unsigned height) { + app->draw_rgb_bitmap(x, y, data, width, height); + return this; +} + +View *View::add_child(BasicWidget *child) { + + children.emplace_back(child); + return this; +} + +unsigned View::get_children_count() const { return children.size(); } + +View *View::send_front(BasicWidget *child, unsigned amt) { + + unsigned cur_z, new_z; + std::vector::iterator it; + + it = std::find(children.begin(), children.end(), child); + if (it == children.end()) { + return this; + } + + cur_z = it - children.begin(); + new_z = (amt == 0) + ? 0 + : cur_z - min(amt, cur_z); + + if (cur_z == new_z) { + return this; + } + + for (unsigned i = cur_z; i > new_z; --i) { + children[i] = children[i - 1]; + } + children[new_z] = child; + child->set_dirty(); + + return this; +} + +View *View::send_back(BasicWidget *child, unsigned amt) { + + unsigned cur_z, new_z; + std::vector::iterator it; + + it = std::find(children.begin(), children.end(), child); + if (it == children.end()) { + return this; + } + + cur_z = it - children.begin(); + new_z = (amt == 0) + ? children.size() - 1 + : min(children.size() - 1, cur_z + amt); + + if (cur_z == new_z) { + return this; + } + + for (unsigned i = cur_z; i < new_z; ++i) { + children[i] = children[i + 1]; + } + children[new_z] = child; + child->set_dirty(); + + return this; +} + +void View::collect_dirty_widgets(RingQueueInterface *dirty_widgets) { + + BasicWidget *child; + + for (auto it = children.rbegin(); it != children.rend(); ++it) { + + child = *it; + + if (child->get_dirty()) { + dirty_widgets->push(child); + continue; + } + + if (child->get_visibility() && child->is_frame()) { + ((Frame *)child)->collect_dirty_widgets(dirty_widgets); + } + } +} + +void View::collect_overlapped_widgets(BasicWidget *dirty, BasicWidget *child, RingQueueInterface *overlapping_widgets) { + + std::vector::reverse_iterator it; + BasicWidget *current; + + it = std::find(children.rbegin(), children.rend(), child); + if (it == children.rend()) { + return; + } + + for (++it; it != children.rend(); ++it) { + current = *it; + + if (current->get_dirty() || !current->get_visibility()) { + continue; + } + + // if (dirty->get_intersection(current)) { + if (current->get_intersection(dirty)) { + current->set_dirty(); + overlapping_widgets->push(current); + } + } +} + +void View::collect_underlapped_widgets(BasicWidget *child, RingQueueInterface *overlapping_widgets) { + + BasicWidget *current; + + for (auto it = children.rbegin(); it != children.rend(); ++it) { + + current = *it; + + if (current == child) { + break; + } + + if (current->get_dirty() || !current->get_visibility()) { + continue; + } + + // if (dirty->get_intersection(current)) { + if (current->get_intersection(child)) { + current->set_dirty(); + overlapping_widgets->push(current); + } + } +} diff --git a/src/widgets/window.cpp b/src/widgets/window.cpp new file mode 100644 index 0000000..e5b33b9 --- /dev/null +++ b/src/widgets/window.cpp @@ -0,0 +1,487 @@ +#include "widgets/window.h" + +Window::Window(Frame *parent, unsigned x, unsigned y, unsigned width, unsigned height) + : parent {parent} + , widget_x {x} + , widget_y {y} + , widget_absolute_x {x + parent->get_absolute_x()} + , widget_absolute_y {y + parent->get_absolute_y()} + , widget_w {width} + , widget_h {height} +{} + +Window *Window::create(Frame *parent, unsigned x, unsigned y, unsigned width, unsigned height) { + Window *window = new Window(parent, x, y, width, height); + if (window != nullptr) { + parent->add_child(window); + } + return window; +} + +WindowStyle *Window::get_style() { + + dirty = true; + return &style; +} + +// BasicWidget overrides + +Frame *Window::get_parent() { return parent; } + +unsigned Window::get_x() const { return widget_x; } +unsigned Window::get_y() const { return widget_y; } + +unsigned Window::get_absolute_x() const { return widget_absolute_x; } +unsigned Window::get_absolute_y() const { return widget_absolute_y; } + +unsigned Window::get_width() const { return widget_w; } +unsigned Window::get_height() const { return widget_h; } + +bool Window::get_dirty() const { return dirty; } +bool Window::get_visibility_changed() const { return visibility_changed; } + +void Window::set_dirty() { dirty = true; } +void Window::set_visibility_changed() { visibility_changed = true; } + +void Window::draw() { + + dirty = false; + visibility_changed = false; + + if (style.border_radius != 0) { + if (style.border_w > 1) { + parent->fill_round_rect( + widget_x, + widget_y, + widget_w, + widget_h, + style.border_radius, + style.border_color + ); + parent->fill_round_rect( + widget_x + style.border_w, + widget_y + style.border_w, + widget_w - 2*style.border_w, + widget_h - 2*style.border_w, + style.border_radius, + style.bg_color + ); + } + if (style.border_w == 1) { + parent->fill_round_rect( + widget_x, + widget_y, + widget_w, + widget_h, + style.border_radius, + style.bg_color + ); + parent->draw_round_rect( + widget_x, + widget_y, + widget_w, + widget_h, + style.border_radius, + style.border_color + ); + } + else { + parent->fill_round_rect( + widget_x + style.border_w, + widget_y + style.border_w, + widget_w - 2*style.border_w, + widget_h - 2*style.border_w, + style.border_radius, + style.bg_color + ); + } + } + else { + if (style.border_w > 1) { + parent->fill_rect( + widget_x, + widget_y, + widget_w, + widget_h, + style.border_color + ); + parent->fill_rect( + widget_x + style.border_w, + widget_y + style.border_w, + widget_w - 2*style.border_w, + widget_h - 2*style.border_w, + style.bg_color + ); + } + if (style.border_w == 1) { + parent->fill_rect( + widget_x, + widget_y, + widget_w, + widget_h, + style.bg_color + ); + parent->draw_rect( + widget_x, + widget_y, + widget_w, + widget_h, + style.border_color + ); + } + else { + parent->fill_rect( + widget_x, + widget_y, + widget_w, + widget_h, + style.bg_color + ); + } + } + + for (auto it = children.rbegin(); it != children.rend(); ++it) { + + BasicWidget *child = *it; + + if (child->get_visibility()) { + child->draw(); + } + } +} + +void Window::clear() { + + dirty = false; + visibility_changed = false; + + parent->fill_rect(widget_x, widget_y, widget_w, widget_h, BLACK); +} + +bool Window::get_intersection(unsigned int x, unsigned int y) const { + return (widget_x <= x && x <= (widget_x + widget_w)) + && (widget_y <= y && y <= (widget_y + widget_h)); +} + +bool Window::get_intersection(BasicWidget *other) const { + + unsigned x0 = other->get_absolute_x(); + unsigned y0 = other->get_absolute_y(); + + unsigned x1 = x0 + other->get_width(); + unsigned y1 = y0 + other->get_height(); + + if (( + (widget_absolute_x <= x0 && x0 <= (widget_absolute_x + widget_w)) + || (widget_absolute_x <= x1 && x1 <= (widget_absolute_x + widget_w)) + ) + && ( + (widget_absolute_y <= y0 && y0 <= (widget_absolute_y + widget_h)) + || (widget_absolute_y <= y1 && y1 <= (widget_absolute_y + widget_h)) + )) { + return true; + } + + if (( + (x0 <= widget_absolute_x && widget_absolute_x <= x1) + || (x0 <= (widget_absolute_x + widget_w) && (widget_absolute_x + widget_w) <= x1) + ) + && ( + (y0 <= widget_absolute_y && widget_absolute_y <= y1) + || (y0 <= (widget_absolute_y + widget_h) && (widget_absolute_y + widget_h) <= y1) + )) { + return true; + } + + return false; +} + +bool Window::propagate_press(unsigned x, unsigned y) { + + if (!get_intersection(x, y)) { + return false; + } + + x -= widget_x; + y -= widget_y; + + for (auto &child : children) { + if (child->get_visibility() && child->propagate_press(x, y)) { + break; + } + } + + return true; +} + +bool Window::propagate_release(unsigned x, unsigned y) { + + if (!get_intersection(x, y)) { + return false; + } + + x -= widget_x; + y -= widget_y; + + for (auto &child : children) { + if (child->get_visibility() && child->propagate_release(x, y)) { + break; + } + } + + return true; +} + +bool Window::get_visibility() const { return visible; } + +void Window::set_visibility(bool new_visibility) { + + if (visible == new_visibility) { + return; + } + + dirty = true; + visibility_changed = true; + + visible = new_visibility; +} + +// Frame overrides + +Window *Window::set_at(unsigned int x, unsigned int y, uint16_t color) { + parent->set_at(widget_x + x, widget_y + y, color); + return this; +} + +uint16_t Window::get_at(unsigned int x, unsigned int y) const { return parent->get_at(widget_x + x, widget_y + y); } + +Window *Window::draw_line(unsigned int x0, unsigned int y0, unsigned int x1, unsigned int y1, uint16_t color) { + parent->draw_line(widget_x + x0, widget_y + y0, widget_x + x0, widget_y + y0, color); + return this; +} + +Window *Window::draw_rect(unsigned int x, unsigned int y, unsigned int w, unsigned int h, uint16_t color) { + parent->draw_rect(widget_x + x, widget_y + y, w, h, color); + return this; +} + +Window *Window::fill_rect(unsigned int x, unsigned int y, unsigned int w, unsigned int h, uint16_t color) { + parent->fill_rect(widget_x + x, widget_y + y, w, h, color); + return this; +} + +Window *Window::draw_round_rect(unsigned int x, unsigned int y, unsigned int w, unsigned int h, unsigned int r, uint16_t color) { + parent->draw_round_rect(widget_x + x, widget_y + y, w, h, r, color); + return this; +} + +Window *Window::fill_round_rect(unsigned int x, unsigned int y, unsigned int w, unsigned int h, unsigned int r, uint16_t color) { + parent->fill_round_rect(widget_x + x, widget_y + y, w, h, r, color); + return this; +} + +Window *Window::draw_circle(unsigned int x, unsigned int y, unsigned int r, uint16_t color) { + parent->draw_circle(widget_x + x, widget_y + y, r, color); + return this; +} + +Window *Window::fill_circle(unsigned int x, unsigned int y, unsigned int r, uint16_t color) { + parent->fill_circle(widget_x + x, widget_y + y, r, color); + return this; +} + +Window *Window::get_text_bounds(const char *text, unsigned int text_size, unsigned int x, unsigned int y, int16_t *x1, + int16_t *y1, uint16_t *w, uint16_t *h) { + parent->get_text_bounds(text, text_size, widget_x + x, widget_y + y, x1, y1, w, h); + *x1 -= widget_x; + *y1 -= widget_y; + + return this; +} + +Window *Window::set_font(const GFXfont *f) { + parent->set_font(f); + return this; +} + +Window *Window::print(const char *text, unsigned int x, unsigned int y, unsigned int text_size, uint16_t fg_color) { + parent->print(text, widget_x + x, widget_y + y, text_size, fg_color); + return this; +} + +Window *Window::print_opaque(const char *text, unsigned int x, unsigned int y, unsigned int text_size, uint16_t fg_color, + uint16_t bg_color) { + parent->print_opaque(text, widget_x + x, widget_y + y, text_size, fg_color, bg_color); + return this; +} + +Window *Window::draw_rgb_bitmap(unsigned x, unsigned y, const uint16_t *data, unsigned width, unsigned height) { + parent->draw_rgb_bitmap(x + widget_x, y + widget_y, data, width, height); + return this; +} + +Window *Window::add_child(BasicWidget *child) { + + children.emplace_back(child); + return this; +} + +unsigned Window::get_children_count() const { return children.size(); } + +Window *Window::send_front(BasicWidget *child, unsigned amt) { + + unsigned cur_z, new_z; + std::vector::iterator it; + + it = std::find(children.begin(), children.end(), child); + if (it == children.end()) { + return this; + } + + cur_z = it - children.begin(); + new_z = (amt == 0) + ? 0 + : cur_z - min(amt, cur_z); + + if (cur_z == new_z) { + return this; + } + + for (unsigned i = cur_z; i > new_z; --i) { + children[i] = children[i - 1]; + } + children[new_z] = child; + child->set_dirty(); + + return this; +} + +Window *Window::send_back(BasicWidget *child, unsigned amt) { + + unsigned cur_z, new_z; + std::vector::iterator it; + + it = std::find(children.begin(), children.end(), child); + if (it == children.end()) { + return this; + } + + cur_z = it - children.begin(); + new_z = (amt == 0) + ? children.size() - 1 + : min(children.size() - 1, cur_z + amt); + + if (cur_z == new_z) { + return this; + } + + for (unsigned i = cur_z; i < new_z; ++i) { + children[i] = children[i + 1]; + } + children[new_z] = child; + child->set_dirty(); + + return this; +} + +void Window::collect_dirty_widgets(RingQueueInterface *dirty_widgets) { + + BasicWidget *child; + + for (auto it = children.rbegin(); it != children.rend(); ++it) { + + child = *it; + + if (child->get_dirty()) { + dirty_widgets->push(child); + continue; + } + + if (child->get_visibility() && child->is_frame()) { + ((Frame *)child)->collect_dirty_widgets(dirty_widgets); + } + } +} + +void Window::collect_overlapped_widgets(BasicWidget *dirty, BasicWidget *child, RingQueueInterface *overlapping_widgets) { + + std::vector::reverse_iterator it; + BasicWidget *current; + + it = std::find(children.rbegin(), children.rend(), child); + if (it == children.rend()) { + return; + } + + for (++it; it != children.rend(); ++it) { + current = *it; + + if (current->get_dirty() || !current->get_visibility()) { + continue; + } + // if (dirty->get_intersection(current)) { + if (current->get_intersection(dirty)) { + current->set_dirty(); + overlapping_widgets->push(current); + } + } +} + +void Window::collect_underlapped_widgets(BasicWidget *child, RingQueueInterface *overlapping_widgets) { + + BasicWidget *current; + + for (auto it = children.rbegin(); it != children.rend(); ++it) { + + current = *it; + + if (current == child) { + break; + } + + if (current->get_dirty() || !current->get_visibility()) { + continue; + } + + // if (dirty->get_intersection(current)) { + if (current->get_intersection(child)) { + current->set_dirty(); + overlapping_widgets->push(current); + } + } +} + +WindowStyle *WindowStyle::set_bg_color(uint16_t new_color) { + bg_color = new_color; +} + +uint16_t WindowStyle::get_bg_color() const { + return bg_color; +} + +WindowStyle *WindowStyle::set_border_color(uint16_t new_color) { + border_color = new_color; + return this; +} + +uint16_t WindowStyle::get_border_color() const { + return border_color; +} + +WindowStyle *WindowStyle::set_border_width(unsigned new_border_width) { + border_w = new_border_width; + return this; +} + +unsigned WindowStyle::get_border_width() const { + return border_w; +} + +WindowStyle *WindowStyle::set_border_radius(unsigned new_border_radius) { + border_radius = new_border_radius; + return this; +} + +unsigned WindowStyle::get_border_radius() const { + return border_radius; +}