├── .github └── FUNDING.yml ├── .gitignore ├── LICENSE ├── README.md ├── examples ├── 2x1Screens │ ├── text │ │ ├── text.ino │ │ └── xtrchr30pt7b.h │ └── text_circle_animation │ │ ├── text_circle_animation.ino │ │ └── xtrchr30pt7b.h ├── 2x2Screens │ ├── breakout │ │ └── breakout.ino │ └── image │ │ ├── image.ino │ │ ├── spacedock_480x480.h │ │ └── spaceship_480x480.h ├── 3x3Screens │ └── clocks │ │ ├── SecondWorldDemoRegular40pt7b.h │ │ ├── clock_1.h │ │ ├── clock_2.h │ │ ├── clock_3.h │ │ └── clocks.ino └── 4x1Screens │ ├── ballcourt │ ├── ballcourt.h │ └── ballcourt.ino │ ├── font_test │ ├── Star_Trek_Enterprise_Future80pt7b.h │ ├── Starjedi32pt7b.h │ ├── font_test.ino │ └── raidercrusader48pt7b.h │ ├── gameoflife │ ├── BebasNeue_Regular13pt7b.h │ └── gameoflife.ino │ ├── image │ ├── image.ino │ ├── newyork_960x240.h │ └── night_earth_960x240.h │ ├── maze │ └── maze.ino │ ├── pong │ ├── Fun_Games20pt7b.h │ ├── Fun_Games40pt7b.h │ └── pong.ino │ └── tetris │ └── tetris.ino ├── font_test.h ├── fonts ├── Aurebesh_Bold32pt7b.h ├── BebasNeue_Regular13pt7b.h ├── Bombing40pt7b.h ├── Fun_Games20pt7b.h ├── Fun_Games40pt7b.h ├── SecondWorldDemoRegular40pt7b.h ├── Star_Trek_Enterprise_Future80pt7b.h ├── Starjedi32pt7b.h ├── raidercrusader48pt7b.h └── xtrchr30pt7b.h ├── image_test.h ├── images ├── ballcourt.h ├── bazar_960x240.h ├── clock_1.h ├── clock_2.h ├── clock_3.h ├── console_960x240.h ├── highway_720x480.h ├── spacebattle_960x240.h ├── spacedock_480x480.h └── spaceship_480x480.h ├── keywords.txt ├── library.properties ├── oldino ├── src └── virtualScreen.h └── virtualScreen.ino /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | custom: https://www.buymeacoffee.com/thelastoutpostworkshop 4 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | build 2 | sounds 3 | secrets.h 4 | .vscode -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 thelastoutpostworkshop 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # VirtualScreen: An Arduino Library for Auto-Spanning Adafruit GFX Graphics Across Multiple Displays / Screens 2 | 3 | **Seamlessly Integrate Multiple Displays with Ease: A User-Friendly Approach to Expansive Graphics**.
4 | 5 | Buy Me A Coffee 6 | 7 | 8 | 9 | ## Youtube Tutorial 10 | [](https://youtu.be/eCfeJh9Pyns) 11 | 12 | ## Installation 13 | ### Installation Arduino IDE (Version 2) 14 | 15 | - Install the **VirtualDisplay Library with the Arduino IDE Library Manager**, it will also install the [TFT_eSPI library](https://github.com/Bodmer/TFT_eSPI) serving as driver for the displays. 16 | 17 | 18 | ## Usage 19 | >ℹ️ There are many examples and display layout included with the library `File > Examples > VirtualDisplay`
20 | ```c 21 | #include 22 | 23 | VirtualDisplay *tft; 24 | ScreenBuilder screens; 25 | 26 | void setup() 27 | { 28 | Serial.begin(115200); 29 | 30 | // Adjust this setup according to your actual screen configuration 31 | screens.addRow({{6, 0}, {7, 0}}); 32 | 33 | tft = new VirtualDisplay(screens.width(), screens.height(), &screens); 34 | tft->begin(); 35 | 36 | // Use any Adafruit GFX Graphics functions 37 | tft->setTextColor(TFT_CYAN); 38 | tft->setCursor(0,90); 39 | tft->print("Virtual Display"); 40 | 41 | tft->output(); // Use this function to output the result on the screens 42 | } 43 | ``` 44 | ## Display Layout 45 | >ℹ️ You can only use display of the same resolution
46 | 47 | Add rows of screens (display) by using the ``` addRow() ``` function.
48 | A screen is definded by ``` {int chip_select_pin, int rotation} ```
49 | ```screens.addRow({{6, 0}, {7, 0}}); ``` adds a row of two screens of rotation 0, the first screen has a chip select on pin 6, and the other has the chip select on pin 7. 50 | 51 | ## Driver Setup for your Display 52 | - You have to setup the driver in the [TFT_eSPI library](https://github.com/Bodmer/TFT_eSPI) configuration files for your display type, see my tutorial on how to do it. 53 | 54 | ## Display supported 55 | - Any 16 bit-color display supported by the [TFT_eSPI library](https://github.com/Bodmer/TFT_eSPI) 56 | 57 | ## Recommended ESP32 58 | - Spanning graphics across multiple displays requires a fair amount of memory, use an **ESP32 with PSRAM**. 59 | - The [ESP32-S3 N16R2](https://amzn.to/3TsziTh) is a good choice. 60 | 61 | ## Graphics functions 62 | >ℹ️ You can use any graphics functions from the [Adafruit GFX library](https://learn.adafruit.com/adafruit-gfx-graphics-library/graphics-primitives)
63 | Here are other graphics functions built in the VirtualScreen Library : 64 | 65 | | Graphics functions | Description | 66 | |---------|-------------| 67 | |output() | Output to the screens according to your screen layout | 68 | |highlightArea(int16_t x, int16_t y, int16_t width, int16_t height, float intensity) | Highlight a specified area of the canvas with adjustable intensity | 69 | |highlightArea(int16_t centerX, int16_t centerY, int16_t radius, float intensity) | Highlight a circular area of the canvas with adjustable intensity | 70 | |color565(uint8_t r, uint8_t g, uint8_t b) | Convert RGB Color to a 565 color code | 71 | |readRect(int16_t x, int16_t y, int16_t width, int16_t height, uint16_t *buffer) | Read an image area into buffer (must be allocated before calling the function) | 72 | 73 | 74 | ## Performance 75 | The library will redraw a display only if its content has changed, so avoid redrawing the entire canvas if you can. 76 | 77 | ## Contributors 78 | Contributors are welcomed! If you want to submit pull requests, [here is how you can do it](https://docs.github.com/en/get-started/exploring-projects-on-github/contributing-to-a-project). 79 | -------------------------------------------------------------------------------- /examples/2x1Screens/text/text.ino: -------------------------------------------------------------------------------- 1 | // Screen Layout : 2 screens on a single row 2 | // See the tutorial : https://youtu.be/eCfeJh9Pyns 3 | // 4 | 5 | #include 6 | #include "xtrchr30pt7b.h" 7 | 8 | VirtualDisplay *tft; 9 | ScreenBuilder screens; 10 | 11 | void setup() 12 | { 13 | Serial.begin(115200); 14 | 15 | // Adjust this setup according to your actual screen layout 16 | screens.addRow({{6, 0}, {7, 0}}); 17 | 18 | tft = new VirtualDisplay(screens.width(), screens.height(), &screens); 19 | tft->begin(); 20 | 21 | tft->setFont(&xtrchr30pt7b); 22 | tft->setTextColor(TFT_CYAN); 23 | tft->setCursor(0,90); 24 | tft->print("Virtual Display"); 25 | tft->output(); 26 | } 27 | 28 | void loop() 29 | { 30 | } 31 | 32 | -------------------------------------------------------------------------------- /examples/2x1Screens/text_circle_animation/text_circle_animation.ino: -------------------------------------------------------------------------------- 1 | // Screen Layout : 2 screens on a single row 2 | // See the tutorial : https://youtu.be/eCfeJh9Pyns 3 | // 4 | 5 | #include "virtualScreen.h" 6 | #include "xtrchr30pt7b.h" 7 | 8 | VirtualDisplay *tft; 9 | ScreenBuilder screens; 10 | 11 | void setup() 12 | { 13 | Serial.begin(115200); 14 | 15 | // Adjust this setup according to your actual screen layout 16 | screens.addRow({{6, 0}, {7, 0}}); 17 | 18 | tft = new VirtualDisplay(screens.width(), screens.height(), &screens); 19 | tft->begin(); 20 | 21 | tft->setFont(&xtrchr30pt7b); 22 | tft->fillScreen(0xfaa0); 23 | tft->drawRoundRect(10, 10, tft->width() - 20, tft->height() - 20, 25, TFT_CYAN); 24 | tft->drawRoundRect(20, 20, tft->width() - 40, tft->height() - 40, 25, TFT_CYAN); 25 | tft->setTextColor(TFT_CYAN); 26 | tft->setCursor(80, 140); 27 | tft->print("Amazing!"); 28 | tft->output(); 29 | } 30 | 31 | void loop() 32 | { 33 | static bool toggleColor = false; 34 | tft->fillCircle(400, tft->height()/2, 30, toggleColor ? TFT_YELLOW : 0xfaa0); 35 | tft->output(); 36 | delay(400); 37 | toggleColor = !toggleColor; 38 | } 39 | -------------------------------------------------------------------------------- /examples/2x2Screens/breakout/breakout.ino: -------------------------------------------------------------------------------- 1 | // Screen Layout : 2x2 Grid, two screens on each row 2 | // See the tutorial : https://youtu.be/eCfeJh9Pyns 3 | // 4 | 5 | #include "virtualScreen.h" 6 | 7 | VirtualDisplay *tft; 8 | ScreenBuilder screens; 9 | 10 | void setup() 11 | { 12 | Serial.begin(115200); 13 | 14 | // Adjust this setup according to your actual screen layout 15 | screens.addRow({{6, 0}, {7, 0}}); 16 | screens.addRow({{16, 2}, {15, 2}}); 17 | 18 | tft = new VirtualDisplay(screens.width(), screens.height(), &screens); 19 | tft->begin(); 20 | 21 | tft->fillScreen(TFT_BLACK); 22 | tft->output(); 23 | setupGame(); 24 | } 25 | 26 | void loop() 27 | { 28 | updateGame(); 29 | drawBricks(); 30 | drawPaddle(); 31 | drawBall(); 32 | 33 | tft->output(); 34 | } 35 | 36 | // Game settings 37 | const int paddleWidth = 40; 38 | const int paddleHeight = 15; 39 | const int ballRadius = 10; 40 | const int brickWidth = 40; 41 | const int brickHeight = 20; 42 | const int numRows = 7; 43 | const int numCols = 10; // Adjust based on your display size 44 | 45 | // Game state 46 | int paddleX; 47 | int ballX, ballY; 48 | int ballVelocityX = 10, ballVelocityY = -10; 49 | bool bricks[numRows][numCols]; // True if the brick is still there 50 | 51 | int prevPaddleX; 52 | int prevBallX, prevBallY; 53 | bool prevBricks[numRows][numCols]; // To track changes in bricks 54 | 55 | // Initialize game state 56 | void setupGame() 57 | { 58 | paddleX = prevPaddleX = (tft->width() - paddleWidth) / 2; 59 | ballX = prevBallX = tft->width() / 2; 60 | ballY = prevBallY = tft->height() - 30; // Start the ball above the paddle 61 | memset(bricks, true, sizeof(bricks)); // Initialize all bricks as visible 62 | 63 | // Initially mark all previous bricks as not present to ensure they are drawn initially 64 | memset(prevBricks, false, sizeof(prevBricks)); // Force drawing of all bricks initially 65 | 66 | // Draw initial game state 67 | drawBricks(); // Draw all bricks initially 68 | drawPaddle(); 69 | drawBall(); 70 | tft->output(); // Update the display after initial setup 71 | } 72 | 73 | uint16_t calculateRowColor(int row, int totalRows) { 74 | // Define the midpoint for the transition from red to orange, then orange to green 75 | float midpoint = 0.5f; 76 | float progress = (float)row / (totalRows - 1); // Progress from 0.0 (top) to 1.0 (bottom) 77 | 78 | uint8_t red, green; 79 | 80 | // Calculate the RGB components based on the row's position 81 | if (progress <= midpoint) { 82 | // Transition from red to orange in the first half 83 | red = 31; // Maximum red value for the entire first half 84 | green = (progress / midpoint) * 31; // Scale green up to 31 (to get orange) at the midpoint 85 | } else { 86 | // Transition from orange to green in the second half 87 | red = (1.0f - (progress - midpoint) / midpoint) * 31; // Scale red down to 0 past the midpoint 88 | green = 31 + ((progress - midpoint) / midpoint) * (63 - 31); // Continue scaling green from 31 to 63 89 | } 90 | 91 | // Combine the components into a 16-bit color value 92 | return (red << 11) | (green << 5); 93 | } 94 | 95 | void drawPaddle() 96 | { 97 | // Clear the previous paddle position 98 | tft->fillRect(prevPaddleX, tft->height() - paddleHeight - 1, paddleWidth, paddleHeight, TFT_BLACK); 99 | // Draw the new paddle position 100 | tft->fillRect(paddleX, tft->height() - paddleHeight - 1, paddleWidth, paddleHeight, TFT_CYAN); 101 | prevPaddleX = paddleX; // Update the previous paddle position 102 | } 103 | 104 | void drawBall() 105 | { 106 | // Clear the previous ball position 107 | tft->fillCircle(prevBallX, prevBallY, ballRadius, TFT_BLACK); 108 | // Draw the new ball position 109 | tft->fillCircle(ballX, ballY, ballRadius, TFT_YELLOW); 110 | prevBallX = ballX; // Update the previous ball position 111 | prevBallY = ballY; 112 | } 113 | 114 | void drawBricks() { 115 | for (int row = 0; row < numRows; ++row) { 116 | // Calculate the color for the current row 117 | uint16_t rowColor = calculateRowColor(row, numRows); 118 | 119 | for (int col = 0; col < numCols; ++col) { 120 | // Draw only if the brick status has changed 121 | if (bricks[row][col] != prevBricks[row][col]) { 122 | int x = col * (brickWidth + 5); 123 | int y = row * (brickHeight + 5); 124 | if (bricks[row][col]) { 125 | tft->fillRect(x, y, brickWidth, brickHeight, rowColor); // Use the row-specific color 126 | } else { 127 | tft->fillRect(x, y, brickWidth, brickHeight, TFT_BLACK); // Clear the brick if it was hit 128 | } 129 | prevBricks[row][col] = bricks[row][col]; // Update the tracked brick status 130 | } 131 | } 132 | } 133 | } 134 | 135 | 136 | void updateGame() 137 | { 138 | // Move the paddle automatically by following the ball 139 | paddleX = ballX - paddleWidth / 2; 140 | 141 | // Update ball position 142 | ballX += ballVelocityX; 143 | ballY += ballVelocityY; 144 | 145 | // Collision detection with the walls 146 | if (ballX <= 0 || ballX >= tft->width()) 147 | ballVelocityX = -ballVelocityX; 148 | if (ballY <= 0) 149 | ballVelocityY = -ballVelocityY; 150 | 151 | // Collision detection with the paddle 152 | int paddleTopY = tft->height() - paddleHeight - 1; // Y position of the top of the paddle 153 | if (ballY + ballVelocityY > paddleTopY - ballRadius && // Check if moving past the paddle's top edge 154 | ballY < paddleTopY + paddleHeight && // And is within paddle's height range 155 | ballX + ballVelocityX > paddleX - ballRadius && // Check if within paddle's left edge 156 | ballX + ballVelocityX < paddleX + paddleWidth + ballRadius) 157 | { // And within paddle's right edge 158 | ballVelocityY = -ballVelocityY; // Reverse Y direction 159 | ballY = paddleTopY - ballRadius; // Adjust ball position to avoid sticking or multiple collisions 160 | } 161 | 162 | // Collision detection with bricks 163 | for (int row = 0; row < numRows; ++row) 164 | { 165 | for (int col = 0; col < numCols; ++col) 166 | { 167 | if (bricks[row][col]) 168 | { // If the brick is there 169 | int brickX = col * (brickWidth + 5); 170 | int brickY = row * (brickHeight + 5); 171 | 172 | // Expanded collision detection area to account for the ball's radius 173 | if (ballX + ballRadius > brickX && ballX - ballRadius < brickX + brickWidth && 174 | ballY + ballRadius > brickY && ballY - ballRadius < brickY + brickHeight) 175 | { 176 | 177 | // Determine collision direction 178 | float middleX = brickX + brickWidth / 2; 179 | float middleY = brickY + brickHeight / 2; 180 | float deltaX = ballX - middleX; 181 | float deltaY = ballY - middleY; 182 | 183 | // Remove the brick 184 | bricks[row][col] = false; 185 | 186 | // Determine if collision is more horizontal or vertical 187 | // and reverse the appropriate velocity component 188 | if (fabs(deltaX) > fabs(deltaY)) 189 | { 190 | if (ballX < middleX) 191 | { // Hit was from the left 192 | ballVelocityX = -abs(ballVelocityX); 193 | } 194 | else 195 | { // Hit was from the right 196 | ballVelocityX = abs(ballVelocityX); 197 | } 198 | } 199 | else 200 | { 201 | if (ballY < middleY) 202 | { // Hit was from above 203 | ballVelocityY = -abs(ballVelocityY); 204 | } 205 | else 206 | { // Hit was from below 207 | ballVelocityY = abs(ballVelocityY); 208 | } 209 | } 210 | } 211 | } 212 | } 213 | } 214 | } 215 | -------------------------------------------------------------------------------- /examples/2x2Screens/image/image.ino: -------------------------------------------------------------------------------- 1 | // Screen Layout : 2x2 Grid, two screens on each row 2 | // See the tutorial : https://youtu.be/eCfeJh9Pyns 3 | // 4 | 5 | #include "virtualScreen.h" 6 | #include "spaceship_480x480.h" 7 | #include "spacedock_480x480.h" 8 | 9 | VirtualDisplay *tft; 10 | ScreenBuilder screens; 11 | 12 | void setup() 13 | { 14 | Serial.begin(115200); 15 | 16 | // Adjust this setup according to your actual screen layout 17 | screens.addRow({{6, 0}, {7, 0}}); 18 | screens.addRow({{16, 2}, {15, 2}}); 19 | 20 | tft = new VirtualDisplay(screens.width(), screens.height(), &screens); 21 | tft->begin(); 22 | 23 | tft->fillScreen(TFT_BLACK); 24 | tft->drawRGBBitmap(0, 0, (uint16_t *)spaceship_480x480, spaceship_480x480_width, spaceship_480x480_height); 25 | tft->output(); 26 | delay(5000); 27 | tft->drawRGBBitmap(0, 0, (uint16_t *)spacedock_480x480, spacedock_480x480_width, spacedock_480x480_height); 28 | tft->output(); 29 | } 30 | 31 | void loop() 32 | { 33 | } 34 | 35 | -------------------------------------------------------------------------------- /examples/3x3Screens/clocks/clocks.ino: -------------------------------------------------------------------------------- 1 | #include "virtualScreen.h" 2 | // Screen Layout : 3x2 Grid, three screens on each row 3 | // See the tutorial : https://youtu.be/eCfeJh9Pyns 4 | // 5 | 6 | #include "clock_1.h" 7 | #include "clock_2.h" 8 | #include "clock_3.h" 9 | #include "SecondWorldDemoRegular40pt7b.h" 10 | 11 | VirtualDisplay *tft; 12 | ScreenBuilder screens; 13 | 14 | void setup() 15 | { 16 | Serial.begin(115200); 17 | 18 | // Adjust this setup according to your actual screen layout 19 | // 6 screens, 3 on each row 20 | screens.addRow({{7, 2}, {6, 2}, {15, 2}}); 21 | screens.addRow({{16, 0}, {11, 0}, {9, 0}}); 22 | 23 | tft = new VirtualDisplay(screens.width(), screens.height(), &screens); 24 | tft->begin(); 25 | 26 | 27 | tft->fillScreen(TFT_BLACK); 28 | tft->pushImage(0, 0, clock1_width, clock1_height, (uint16_t *)clock1); 29 | tft->pushImage(240, 0, clock2_width, clock2_height, (uint16_t *)clock2); 30 | tft->pushImage(480, 0, clock3_width, clock3_height, (uint16_t *)clock3); 31 | tft->setFont(&SecondWorldDemoRegular40pt7b); 32 | tft->setTextColor(0xef48); 33 | tft->setCursor(50, 385); 34 | tft->print("Very Strange Clocks"); 35 | } 36 | 37 | unsigned long lastUpdateTime = 0; 38 | const long updateInterval = 1000; // Update every second 39 | 40 | void loop() 41 | { 42 | tft->highlightArea(360, 120, 50, 0.5f); 43 | 44 | tft->output(); 45 | tft->pushImage(240, 0, clock2_width, clock2_height, (uint16_t *)clock2); 46 | tft->output(); 47 | 48 | unsigned long currentMillis = millis(); 49 | if (currentMillis - lastUpdateTime >= updateInterval) 50 | { 51 | lastUpdateTime = currentMillis; 52 | 53 | // Assuming you have a way to get the current time in seconds 54 | int seconds = (currentMillis / 1000) % 60; // Simulated for demonstration 55 | 56 | tft->pushImage(0, 0, clock1_width, clock1_height, (uint16_t *)clock1); 57 | 58 | // Draw the new seconds hand 59 | drawSecondsHand(seconds, TFT_RED); // White color for the hand 60 | 61 | tft->output(); // Update the display with the changes 62 | } 63 | } 64 | 65 | void drawSecondsHand(int seconds, uint16_t color) { 66 | float angle = (seconds - 15) * (2 * M_PI / 60); // Convert seconds to angle 67 | int16_t centerX = 120, centerY = 120; // Center of the clock 68 | int16_t length = 60; // Length of the seconds hand 69 | 70 | // Tip of the seconds hand 71 | int16_t endX = centerX + length * cos(angle); 72 | int16_t endY = centerY + length * sin(angle); 73 | 74 | // Width of the base of the triangle hand 75 | int16_t handWidth = 10; 76 | 77 | // Calculate the two additional points for the base of the triangle 78 | float baseAngle = angle + M_PI / 2; // Perpendicular to the hand direction 79 | int16_t baseOffsetX = handWidth * cos(baseAngle) / 2; 80 | int16_t baseOffsetY = handWidth * sin(baseAngle) / 2; 81 | 82 | int16_t basePoint1X = centerX + baseOffsetX; 83 | int16_t basePoint1Y = centerY + baseOffsetY; 84 | int16_t basePoint2X = centerX - baseOffsetX; 85 | int16_t basePoint2Y = centerY - baseOffsetY; 86 | 87 | // Define points array for triangle 88 | int16_t points[6] = {endX, endY, basePoint1X, basePoint1Y, basePoint2X, basePoint2Y}; 89 | 90 | // Draw the triangle 91 | tft->fillTriangle(points[0], points[1], points[2], points[3], points[4], points[5], color); 92 | } 93 | 94 | -------------------------------------------------------------------------------- /examples/4x1Screens/ballcourt/ballcourt.ino: -------------------------------------------------------------------------------- 1 | // Screen Layout : 4 screens on a single row 2 | // See the tutorial : https://youtu.be/eCfeJh9Pyns 3 | // 4 | 5 | #include "virtualScreen.h" 6 | #include "ballcourt.h" 7 | 8 | VirtualDisplay *tft; 9 | 10 | void setup() 11 | { 12 | Serial.begin(115200); 13 | 14 | ScreenBuilder screens; 15 | // Adjust this setup according to your actual screen layout 16 | screens.addRow({{16, 0}, {15, 0}, {6, 0}, {7, 0}}); 17 | 18 | tft = new VirtualDisplay(screens.width(), screens.height(), &screens); 19 | tft->begin(); 20 | 21 | // Start the bouncing ball animation 22 | runBouncingBall(); 23 | } 24 | 25 | void loop() 26 | { 27 | } 28 | 29 | class BouncingBall 30 | { 31 | private: 32 | float x, y; // Ball's position 33 | float vx, vy; // Ball's velocity 34 | float gravity; // Gravity effect 35 | float elasticity; // Bounce reduction factor 36 | int ballRadius; // Ball radius 37 | int captureRadius; // Slightly larger to ensure clean edges 38 | int rotation = 0; 39 | 40 | uint16_t *backgroundBuffer; // Buffer for storing background 41 | 42 | public: 43 | BouncingBall() 44 | { 45 | ballRadius = 20; 46 | captureRadius = ballRadius + 4; 47 | x = ballRadius + 5; 48 | y = tft->height() / 2; 49 | vx = 10; // Initial horizontal velocity 50 | vy = 0; // Initial vertical velocity 51 | gravity = 0.8; // Adjust as needed 52 | elasticity = 1; // Adjust as needed (between 0 and 1) 53 | backgroundBuffer = new uint16_t[(captureRadius * 2) * (captureRadius * 2)]; // Allocate memory for background buffer 54 | } 55 | 56 | ~BouncingBall() 57 | { 58 | if (backgroundBuffer) 59 | { 60 | delete[] backgroundBuffer; // Free memory when done 61 | } 62 | } 63 | 64 | void update() 65 | { 66 | // Logic to update ball position and handle collisions 67 | vy += gravity; 68 | x += vx; 69 | y += vy; 70 | 71 | if (x <= ballRadius || x >= tft->width() - ballRadius) 72 | { 73 | vx = -vx; 74 | x += vx; 75 | } 76 | 77 | if (y <= ballRadius || y >= tft->height() - ballRadius) 78 | { 79 | vy = -vy * elasticity; 80 | y += vy; 81 | } 82 | rotation += vx / 3.0; // Adjust rotation speed based on velocity 83 | } 84 | 85 | void init() 86 | { 87 | tft->readRect(x - captureRadius, y - captureRadius, captureRadius * 2, captureRadius * 2, backgroundBuffer); 88 | } 89 | 90 | void draw() 91 | { 92 | 93 | // Erase the ball at the current position by restoring the background 94 | tft->pushImage(x - captureRadius, y - captureRadius, captureRadius * 2, captureRadius * 2, backgroundBuffer); 95 | 96 | // Update position for the next frame 97 | update(); 98 | 99 | // Capture the background at the new position, slightly larger area 100 | tft->readRect(x - captureRadius, y - captureRadius, captureRadius * 2, captureRadius * 2, backgroundBuffer); 101 | 102 | // Draw the ball at the new position 103 | tft->fillCircle(x, y, ballRadius, 0xf5e5); 104 | } 105 | }; 106 | 107 | void runBouncingBall() 108 | { 109 | BouncingBall ball; 110 | 111 | tft->fillScreen(TFT_BLACK); 112 | tft->drawRGBBitmap(0, 0, (uint16_t *)ballcourt, ballcourt_width, ballcourt_height); 113 | ball.init(); 114 | while (true) 115 | { 116 | ball.draw(); 117 | tft->output(); // Update the virtual display 118 | } 119 | } 120 | -------------------------------------------------------------------------------- /examples/4x1Screens/font_test/font_test.ino: -------------------------------------------------------------------------------- 1 | // Screen Layout : 4 screens on a single row 2 | // See the tutorial : https://youtu.be/eCfeJh9Pyns 3 | // 4 | 5 | 6 | #include "virtualScreen.h" 7 | #include "Starjedi32pt7b.h" 8 | #include "raidercrusader48pt7b.h" 9 | #include "Star_Trek_Enterprise_Future80pt7b.h" 10 | 11 | VirtualDisplay *tft; 12 | 13 | void setup() 14 | { 15 | Serial.begin(115200); 16 | 17 | ScreenBuilder screens; 18 | 19 | // 4 sreens on one row 20 | screens.addRow({{16, 0}, {15, 0}, {6, 0}, {7, 0}}); 21 | 22 | tft = new VirtualDisplay(screens.width(), screens.height(), &screens); 23 | tft->begin(); 24 | 25 | 26 | tft->fillScreen(TFT_BLACK); 27 | tft->drawRect(10, 20, tft->width() - 50, tft->height() - 50, TFT_GREEN); 28 | tft->drawRect(12, 23, tft->width() - 48, tft->height() - 48, TFT_GREEN); 29 | tft->drawRoundRect(20, 50, tft->width() - 80, tft->height() - 100, 20, TFT_CYAN); 30 | printCenteredText(tft, "Star Wars Yoda Jedi", &Starjedi32pt7b, 0x00ff0c); 31 | tft->output(); 32 | delay(5000); 33 | tft->fillScreen(TFT_BLACK); 34 | printCenteredText(tft, "We are Crusaders!", &raidercrusader48pt7b, 0x17bb); 35 | tft->output(); 36 | delay(5000); 37 | tft->fillScreen(TFT_BLACK); 38 | printCenteredText(tft, "Star Trek Kirk", &Star_Trek_Enterprise_Future80pt7b, 0x3728); 39 | tft->output(); 40 | } 41 | 42 | void loop() 43 | { 44 | } 45 | 46 | void printCenteredText(VirtualDisplay *tft, const String &text, const GFXfont *font, uint16_t color) 47 | { 48 | 49 | tft->setFont(font); 50 | tft->setTextColor(color); 51 | 52 | int16_t x1, y1; 53 | uint16_t w, h; 54 | tft->getTextBounds(text, 0, 0, &x1, &y1, &w, &h); // Calculate the bounds of the text 55 | 56 | int x = (tft->width() - w) / 2; // Calculate the x position to center the text 57 | int y = (tft->height() + h) / 2; // Center vertically 58 | 59 | tft->setCursor(x, y); 60 | tft->println(text); 61 | } 62 | 63 | -------------------------------------------------------------------------------- /examples/4x1Screens/gameoflife/BebasNeue_Regular13pt7b.h: -------------------------------------------------------------------------------- 1 | const uint8_t BebasNeue_Regular13pt7bBitmaps[] PROGMEM = { 2 | 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xB6, 0x07, 0xFC, 0xEF, 0xDB, 0xB6, 0x6C, 3 | 0xC9, 0x80, 0x19, 0x86, 0x61, 0x98, 0x66, 0x7F, 0xDF, 0xF3, 0xB8, 0xCC, 4 | 0x33, 0x0C, 0xC7, 0xF9, 0xFE, 0xFF, 0x8C, 0xC7, 0x71, 0xDC, 0x67, 0x19, 5 | 0x80, 0x18, 0x18, 0x7E, 0xFF, 0xE7, 0xE3, 0xE0, 0xF0, 0x78, 0x3C, 0x1E, 6 | 0x0F, 0x07, 0xE7, 0xE7, 0xE7, 0xFF, 0x7E, 0x18, 0x18, 0x70, 0x67, 0xC6, 7 | 0x36, 0x31, 0xB1, 0x8D, 0x98, 0x6C, 0xC3, 0x64, 0x1B, 0x60, 0xFB, 0x73, 8 | 0xB7, 0xC1, 0xB6, 0x09, 0x30, 0xC9, 0x86, 0x4C, 0x62, 0x63, 0x1B, 0x18, 9 | 0xF9, 0x83, 0x80, 0x3E, 0x3F, 0x3F, 0x9C, 0x0E, 0x07, 0x1B, 0x8C, 0xFF, 10 | 0x3F, 0xBF, 0xF8, 0xDC, 0x6E, 0x37, 0x1B, 0x9D, 0xFE, 0xFF, 0x3D, 0xC0, 11 | 0xFF, 0xEC, 0x80, 0x1B, 0xDF, 0xCE, 0x73, 0x9C, 0xE7, 0x39, 0xCE, 0x73, 12 | 0x9C, 0xE7, 0x3E, 0xF3, 0x80, 0x87, 0xBC, 0x73, 0x9C, 0xE7, 0x39, 0xCE, 13 | 0x73, 0x9C, 0xE7, 0x39, 0xFF, 0xEE, 0x00, 0x0E, 0x03, 0x04, 0x45, 0xD7, 14 | 0xFF, 0xC3, 0x81, 0xB0, 0xEE, 0x31, 0x80, 0x18, 0x0C, 0x06, 0x1F, 0xFF, 15 | 0xFF, 0xFC, 0x60, 0x30, 0x18, 0x00, 0xFF, 0xAD, 0x80, 0xFF, 0xFE, 0xFF, 16 | 0x80, 0x01, 0xC0, 0x60, 0x38, 0x0C, 0x07, 0x01, 0xC0, 0x60, 0x38, 0x0C, 17 | 0x03, 0x01, 0xC0, 0x60, 0x38, 0x0C, 0x03, 0x01, 0xC0, 0x60, 0x38, 0x00, 18 | 0x3C, 0x7F, 0xFF, 0xE7, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 19 | 0xE3, 0xE3, 0xE7, 0xFF, 0x7F, 0x3C, 0x0C, 0x7F, 0xFF, 0xFC, 0x71, 0xC7, 20 | 0x1C, 0x71, 0xC7, 0x1C, 0x71, 0xC7, 0x1C, 0x70, 0x3C, 0x7F, 0xFF, 0xE7, 21 | 0xE3, 0xE7, 0x07, 0x07, 0x0E, 0x1C, 0x3C, 0x78, 0x70, 0xE0, 0xE0, 0xFF, 22 | 0xFF, 0xFF, 0x3C, 0x7E, 0xFF, 0xE7, 0xE7, 0x07, 0x07, 0x1F, 0x1C, 0x1E, 23 | 0x07, 0x07, 0xC7, 0xC7, 0xE7, 0xFF, 0x7E, 0x3C, 0x07, 0x81, 0xE0, 0xF8, 24 | 0x3E, 0x0F, 0x87, 0xE1, 0xB8, 0xEE, 0x33, 0x9C, 0xE7, 0x39, 0x8E, 0xFF, 25 | 0xFF, 0xFF, 0xFC, 0x0E, 0x03, 0x80, 0xE0, 0xFF, 0xFF, 0xFF, 0xE0, 0xE0, 26 | 0xE4, 0xFF, 0xFF, 0xE7, 0xE7, 0x03, 0x03, 0xE3, 0xE3, 0xE7, 0xFF, 0x7F, 27 | 0x3C, 0x3C, 0x7F, 0xFF, 0xE3, 0xE3, 0xE0, 0xE4, 0xFF, 0xFF, 0xE7, 0xE3, 28 | 0xE3, 0xE3, 0xE3, 0xE3, 0xFF, 0x7F, 0x3E, 0xFF, 0xFF, 0xFF, 0x07, 0x07, 29 | 0x06, 0x0E, 0x0E, 0x0E, 0x1C, 0x1C, 0x1C, 0x18, 0x38, 0x38, 0x38, 0x70, 30 | 0x70, 0x3C, 0x7F, 0xFF, 0xE7, 0xE3, 0xE3, 0xE7, 0xFF, 0x7E, 0xFF, 0xE7, 31 | 0xE3, 0xE3, 0xE3, 0xE3, 0xFF, 0xFF, 0x3E, 0x3C, 0x7E, 0xFF, 0xE7, 0xE7, 32 | 0xE7, 0xE7, 0xE7, 0xE7, 0xFF, 0x7F, 0x27, 0x07, 0xC7, 0xE7, 0xFF, 0x7E, 33 | 0x3C, 0xFF, 0x80, 0x00, 0x03, 0xFE, 0xFF, 0x80, 0x00, 0x03, 0xFE, 0xB4, 34 | 0x03, 0x0F, 0x3C, 0xF0, 0xE0, 0x7C, 0x1F, 0x03, 0xFF, 0xFF, 0xFF, 0x00, 35 | 0xFF, 0xFF, 0xFF, 0xC0, 0xF0, 0x3E, 0x0F, 0x07, 0x3E, 0xF8, 0xC0, 0x3E, 36 | 0x3F, 0x9F, 0xCC, 0x7E, 0x3F, 0x1C, 0x0C, 0x0E, 0x0E, 0x07, 0x07, 0x03, 37 | 0x81, 0x80, 0x00, 0x00, 0x38, 0x1C, 0x0E, 0x00, 0x00, 0x40, 0x07, 0xF8, 38 | 0x1F, 0xFC, 0x3C, 0x1E, 0x38, 0x07, 0x71, 0x37, 0x67, 0xB3, 0xE7, 0xF3, 39 | 0xC6, 0x73, 0xCE, 0x73, 0xCE, 0x73, 0xCE, 0x73, 0xCE, 0x76, 0xCE, 0xFE, 40 | 0xCF, 0xFC, 0xE7, 0x78, 0xE0, 0x00, 0x70, 0x08, 0x3F, 0xF8, 0x1F, 0xF8, 41 | 0x07, 0xE0, 0x1E, 0x07, 0x81, 0xE0, 0x7C, 0x3F, 0x0F, 0xC3, 0xF0, 0xCC, 42 | 0x33, 0x0C, 0xE7, 0x39, 0xCE, 0x7F, 0x9F, 0xE6, 0x19, 0x87, 0x61, 0xF8, 43 | 0x70, 0xFE, 0x7F, 0xBF, 0xDC, 0xEE, 0x37, 0x1B, 0x9D, 0xFE, 0xFE, 0x7F, 44 | 0xB9, 0xDC, 0x7E, 0x3F, 0x1F, 0x8F, 0xFE, 0xFF, 0x7F, 0x00, 0x3C, 0x7E, 45 | 0xFF, 0xE7, 0xE7, 0xE7, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE7, 0xE7, 0xE7, 46 | 0xE7, 0xFF, 0x7E, 0x3C, 0xFE, 0x7F, 0xBF, 0xDC, 0x6E, 0x3F, 0x1F, 0x8F, 47 | 0xC7, 0xE3, 0xF1, 0xF8, 0xFC, 0x7E, 0x3F, 0x1F, 0x8D, 0xFE, 0xFF, 0x7F, 48 | 0x00, 0xFF, 0xFF, 0xFF, 0xE0, 0xE0, 0xE0, 0xE0, 0xFE, 0xFE, 0xFE, 0xE0, 49 | 0xE0, 0xE0, 0xE0, 0xE0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0E, 0x1C, 50 | 0x38, 0x7E, 0xFD, 0xFB, 0x87, 0x0E, 0x1C, 0x38, 0x70, 0xE1, 0xC0, 0x3C, 51 | 0x7E, 0xFF, 0xE7, 0xE3, 0xE3, 0xE0, 0xE0, 0xEF, 0xEF, 0xEF, 0xE3, 0xE3, 52 | 0xE3, 0xE7, 0xFF, 0x7E, 0x3C, 0xE3, 0xF1, 0xF8, 0xFC, 0x7E, 0x3F, 0x1F, 53 | 0x8F, 0xFF, 0xFF, 0xFF, 0xF8, 0xFC, 0x7E, 0x3F, 0x1F, 0x8F, 0xC7, 0xE3, 54 | 0xF1, 0xC0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0x1C, 0x71, 0xC7, 55 | 0x1C, 0x71, 0xC7, 0x1C, 0x71, 0xC7, 0x1C, 0x71, 0xFF, 0xFB, 0xC0, 0xE3, 56 | 0xF1, 0xB9, 0xDC, 0xCE, 0xE7, 0x73, 0xF1, 0xF8, 0xFC, 0x7F, 0x3F, 0x9D, 57 | 0xCE, 0x77, 0x3B, 0x9D, 0xC7, 0xE3, 0xF1, 0xC0, 0xE1, 0xC3, 0x87, 0x0E, 58 | 0x1C, 0x38, 0x70, 0xE1, 0xC3, 0x87, 0x0E, 0x1C, 0x38, 0x7F, 0xFF, 0xFC, 59 | 0xF0, 0xFF, 0x1F, 0xF1, 0xFF, 0x9F, 0xF9, 0xFD, 0x9F, 0xD9, 0xFD, 0x9F, 60 | 0xDB, 0x7D, 0xB7, 0xDB, 0x7C, 0xF7, 0xCF, 0x7C, 0xF7, 0xCE, 0x7C, 0xE7, 61 | 0xCE, 0x7C, 0xE7, 0xF3, 0xF9, 0xFC, 0xFE, 0x7F, 0xBF, 0xDF, 0xEF, 0xF7, 62 | 0xFF, 0xF7, 0xFB, 0xFD, 0xFE, 0x7F, 0x3F, 0x9F, 0xCF, 0xE3, 0xF1, 0xC0, 63 | 0x3C, 0x7F, 0xFF, 0xE7, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 64 | 0xE3, 0xE3, 0xE7, 0xFF, 0x7F, 0x3C, 0xFC, 0xFF, 0xFF, 0xE7, 0xE3, 0xE3, 65 | 0xE3, 0xE7, 0xFF, 0xFE, 0xF0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 66 | 0x3C, 0x3F, 0xBF, 0xDC, 0xEE, 0x37, 0x1B, 0x8D, 0xC6, 0xE3, 0x71, 0xB8, 67 | 0xDC, 0x6E, 0x37, 0x1B, 0x9D, 0xFE, 0x7F, 0x1F, 0xC0, 0xE0, 0x10, 0xFE, 68 | 0x7F, 0xBF, 0xDC, 0xEE, 0x37, 0x1B, 0x8D, 0xCE, 0xFE, 0x7F, 0x3F, 0xDC, 69 | 0xEE, 0x37, 0x1B, 0x8D, 0xC6, 0xE3, 0x71, 0x80, 0x3C, 0xFE, 0xFF, 0xC7, 70 | 0xC7, 0xE0, 0xE0, 0x70, 0x78, 0x3C, 0x1E, 0x0F, 0x07, 0xC7, 0xC7, 0xFF, 71 | 0xFE, 0x7C, 0xFF, 0xFF, 0xFF, 0xE3, 0x81, 0xC0, 0xE0, 0x70, 0x38, 0x1C, 72 | 0x0E, 0x07, 0x03, 0x81, 0xC0, 0xE0, 0x70, 0x38, 0x1C, 0x0E, 0x00, 0xE3, 73 | 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 74 | 0xE3, 0xE7, 0xFF, 0x7E, 0x3C, 0xE1, 0xB0, 0xD8, 0xEE, 0x77, 0x3B, 0x9D, 75 | 0xCC, 0xE6, 0x33, 0x19, 0x8F, 0xC7, 0xE3, 0xF1, 0xF0, 0xF8, 0x3C, 0x1E, 76 | 0x0F, 0x00, 0xE3, 0x9D, 0x8E, 0x76, 0x79, 0xD9, 0xE6, 0x67, 0x99, 0xDE, 77 | 0x67, 0x79, 0x9D, 0xE6, 0x76, 0xD9, 0xDB, 0x67, 0x6F, 0x8D, 0xBE, 0x3E, 78 | 0xF8, 0xF3, 0xC3, 0xCF, 0x0F, 0x3C, 0x3C, 0xF0, 0xF3, 0xC0, 0xF1, 0xDC, 79 | 0x67, 0x38, 0xCE, 0x3B, 0x0F, 0xC1, 0xF0, 0x78, 0x1E, 0x07, 0x81, 0xE0, 80 | 0x7C, 0x3F, 0x0C, 0xC7, 0x39, 0xCE, 0x61, 0xF8, 0x70, 0xE1, 0xDC, 0x67, 81 | 0x39, 0xCE, 0x33, 0x0E, 0xC3, 0xF0, 0x78, 0x1E, 0x07, 0x80, 0xC0, 0x30, 82 | 0x0C, 0x03, 0x00, 0xC0, 0x30, 0x0C, 0x03, 0x00, 0x7F, 0xBF, 0xDF, 0xE0, 83 | 0xE0, 0x70, 0x70, 0x38, 0x1C, 0x1C, 0x0E, 0x0E, 0x07, 0x03, 0x83, 0x81, 84 | 0xC1, 0xFF, 0xFF, 0xFF, 0xC0, 0xFF, 0xFF, 0xCE, 0x73, 0x9C, 0xE7, 0x39, 85 | 0xCE, 0x73, 0x9C, 0xE7, 0x3F, 0xFF, 0x80, 0xE0, 0x18, 0x07, 0x00, 0xC0, 86 | 0x30, 0x0E, 0x01, 0x80, 0x70, 0x0C, 0x03, 0x00, 0xE0, 0x18, 0x07, 0x00, 87 | 0xC0, 0x30, 0x0E, 0x01, 0x80, 0x70, 0xFF, 0xFE, 0x73, 0x9C, 0xE7, 0x39, 88 | 0xCE, 0x73, 0x9C, 0xE7, 0x39, 0xFF, 0xFF, 0x80, 0x0C, 0x07, 0x81, 0xE0, 89 | 0xEC, 0x33, 0x1C, 0x6E, 0x1C, 0xFF, 0xFF, 0xFF, 0xE3, 0x8E, 0x1E, 0x07, 90 | 0x81, 0xE0, 0x7C, 0x3F, 0x0F, 0xC3, 0xF0, 0xCC, 0x33, 0x0C, 0xE7, 0x39, 91 | 0xCE, 0x7F, 0x9F, 0xE6, 0x19, 0x87, 0x61, 0xF8, 0x70, 0xFE, 0x7F, 0xBF, 92 | 0xDC, 0xEE, 0x37, 0x1B, 0x9D, 0xFE, 0xFE, 0x7F, 0xB9, 0xDC, 0x7E, 0x3F, 93 | 0x1F, 0x8F, 0xFE, 0xFF, 0x7F, 0x00, 0x3C, 0x7E, 0xFF, 0xE7, 0xE7, 0xE7, 94 | 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE7, 0xE7, 0xE7, 0xE7, 0xFF, 0x7E, 0x3C, 95 | 0xFE, 0x7F, 0xBF, 0xDC, 0x6E, 0x3F, 0x1F, 0x8F, 0xC7, 0xE3, 0xF1, 0xF8, 96 | 0xFC, 0x7E, 0x3F, 0x1F, 0x8D, 0xFE, 0xFF, 0x7F, 0x00, 0xFF, 0xFF, 0xFF, 97 | 0xE0, 0xE0, 0xE0, 0xE0, 0xFE, 0xFE, 0xFE, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 98 | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0E, 0x1C, 0x38, 0x7E, 0xFD, 0xFB, 99 | 0x87, 0x0E, 0x1C, 0x38, 0x70, 0xE1, 0xC0, 0x3C, 0x7E, 0xFF, 0xE7, 0xE3, 100 | 0xE3, 0xE0, 0xE0, 0xEF, 0xEF, 0xEF, 0xE3, 0xE3, 0xE3, 0xE7, 0xFF, 0x7E, 101 | 0x3C, 0xE3, 0xF1, 0xF8, 0xFC, 0x7E, 0x3F, 0x1F, 0x8F, 0xFF, 0xFF, 0xFF, 102 | 0xF8, 0xFC, 0x7E, 0x3F, 0x1F, 0x8F, 0xC7, 0xE3, 0xF1, 0xC0, 0xFF, 0xFF, 103 | 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0x1C, 0x71, 0xC7, 0x1C, 0x71, 0xC7, 0x1C, 104 | 0x71, 0xC7, 0x1C, 0x71, 0xFF, 0xFB, 0xC0, 0xE3, 0xF1, 0xB9, 0xDC, 0xCE, 105 | 0xE7, 0x73, 0xF1, 0xF8, 0xFC, 0x7F, 0x3F, 0x9D, 0xCE, 0x77, 0x3B, 0x9D, 106 | 0xC7, 0xE3, 0xF1, 0xC0, 0xE1, 0xC3, 0x87, 0x0E, 0x1C, 0x38, 0x70, 0xE1, 107 | 0xC3, 0x87, 0x0E, 0x1C, 0x38, 0x7F, 0xFF, 0xFC, 0xF0, 0xFF, 0x1F, 0xF1, 108 | 0xFF, 0x9F, 0xF9, 0xFD, 0x9F, 0xD9, 0xFD, 0x9F, 0xDB, 0x7D, 0xB7, 0xDB, 109 | 0x7C, 0xF7, 0xCF, 0x7C, 0xF7, 0xCE, 0x7C, 0xE7, 0xCE, 0x7C, 0xE7, 0xF3, 110 | 0xF9, 0xFC, 0xFE, 0x7F, 0xBF, 0xDF, 0xEF, 0xF7, 0xFF, 0xF7, 0xFB, 0xFD, 111 | 0xFE, 0x7F, 0x3F, 0x9F, 0xCF, 0xE3, 0xF1, 0xC0, 0x3C, 0x7F, 0xFF, 0xE7, 112 | 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE7, 0xFF, 113 | 0x7F, 0x3C, 0xFC, 0xFF, 0xFF, 0xE7, 0xE3, 0xE3, 0xE3, 0xE7, 0xFF, 0xFE, 114 | 0xF0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0x3C, 0x3F, 0xBF, 0xDC, 115 | 0xEE, 0x37, 0x1B, 0x8D, 0xC6, 0xE3, 0x71, 0xB8, 0xDC, 0x6E, 0x37, 0x1B, 116 | 0x9D, 0xFE, 0x7F, 0x1F, 0xC0, 0xE0, 0x10, 0xFE, 0x7F, 0xBF, 0xDC, 0xEE, 117 | 0x37, 0x1B, 0x8D, 0xCE, 0xFE, 0x7F, 0x3F, 0xDC, 0xEE, 0x37, 0x1B, 0x8D, 118 | 0xC6, 0xE3, 0x71, 0x80, 0x3C, 0xFE, 0xFF, 0xC7, 0xC7, 0xE0, 0xE0, 0x70, 119 | 0x78, 0x3C, 0x1E, 0x0F, 0x07, 0xC7, 0xC7, 0xFF, 0xFE, 0x7C, 0xFF, 0xFF, 120 | 0xFF, 0xE3, 0x81, 0xC0, 0xE0, 0x70, 0x38, 0x1C, 0x0E, 0x07, 0x03, 0x81, 121 | 0xC0, 0xE0, 0x70, 0x38, 0x1C, 0x0E, 0x00, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 122 | 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE7, 0xFF, 0x7E, 123 | 0x3C, 0xE1, 0xB0, 0xD8, 0xEE, 0x77, 0x3B, 0x9D, 0xCC, 0xE6, 0x33, 0x19, 124 | 0x8F, 0xC7, 0xE3, 0xF1, 0xF0, 0xF8, 0x3C, 0x1E, 0x0F, 0x00, 0xE3, 0x9D, 125 | 0x8E, 0x76, 0x79, 0xD9, 0xE6, 0x67, 0x99, 0xDE, 0x67, 0x79, 0x9D, 0xE6, 126 | 0x76, 0xD9, 0xDB, 0x67, 0x6F, 0x8D, 0xBE, 0x3E, 0xF8, 0xF3, 0xC3, 0xCF, 127 | 0x0F, 0x3C, 0x3C, 0xF0, 0xF3, 0xC0, 0xF1, 0xDC, 0x67, 0x38, 0xCE, 0x3B, 128 | 0x0F, 0xC1, 0xF0, 0x78, 0x1E, 0x07, 0x81, 0xE0, 0x7C, 0x3F, 0x0C, 0xC7, 129 | 0x39, 0xCE, 0x61, 0xF8, 0x70, 0xE1, 0xDC, 0x67, 0x39, 0xCE, 0x33, 0x0E, 130 | 0xC3, 0xF0, 0x78, 0x1E, 0x07, 0x80, 0xC0, 0x30, 0x0C, 0x03, 0x00, 0xC0, 131 | 0x30, 0x0C, 0x03, 0x00, 0x7F, 0xBF, 0xDF, 0xE0, 0xE0, 0x70, 0x70, 0x38, 132 | 0x1C, 0x1C, 0x0E, 0x0E, 0x07, 0x03, 0x83, 0x81, 0xC1, 0xFF, 0xFF, 0xFF, 133 | 0xC0, 0x19, 0xDE, 0xE7, 0x39, 0xCE, 0x77, 0x39, 0xC7, 0x39, 0xCE, 0x73, 134 | 0x9E, 0xF3, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 135 | 0xE0, 0x87, 0x3C, 0xE7, 0x39, 0xCE, 0x71, 0xCE, 0x77, 0x39, 0xCE, 0x73, 136 | 0xBD, 0xEE, 0x00, 0x10, 0x9F, 0xFF, 0xF9, 0x1C }; 137 | 138 | const GFXglyph BebasNeue_Regular13pt7bGlyphs[] PROGMEM = { 139 | { 0, 1, 1, 4, 0, 0 }, // 0x20 ' ' 140 | { 1, 3, 18, 5, 1, -17 }, // 0x21 '!' 141 | { 8, 7, 6, 9, 1, -17 }, // 0x22 '"' 142 | { 14, 10, 18, 10, 0, -17 }, // 0x23 '#' 143 | { 37, 8, 20, 10, 1, -18 }, // 0x24 '$' 144 | { 57, 13, 18, 15, 1, -17 }, // 0x25 '%' 145 | { 87, 9, 18, 11, 1, -17 }, // 0x26 '&' 146 | { 108, 3, 6, 5, 1, -17 }, // 0x27 ''' 147 | { 111, 5, 21, 7, 1, -19 }, // 0x28 '(' 148 | { 125, 5, 21, 7, 1, -19 }, // 0x29 ')' 149 | { 139, 10, 9, 11, 0, -17 }, // 0x2A '*' 150 | { 151, 9, 9, 10, 1, -12 }, // 0x2B '+' 151 | { 162, 3, 6, 5, 1, -2 }, // 0x2C ',' 152 | { 165, 5, 3, 7, 1, -10 }, // 0x2D '-' 153 | { 167, 3, 3, 5, 1, -2 }, // 0x2E '.' 154 | { 169, 10, 18, 10, 0, -17 }, // 0x2F '/' 155 | { 192, 8, 18, 10, 1, -17 }, // 0x30 '0' 156 | { 210, 6, 18, 10, 2, -17 }, // 0x31 '1' 157 | { 224, 8, 18, 10, 1, -17 }, // 0x32 '2' 158 | { 242, 8, 18, 10, 1, -17 }, // 0x33 '3' 159 | { 260, 10, 18, 10, 0, -17 }, // 0x34 '4' 160 | { 283, 8, 18, 10, 1, -17 }, // 0x35 '5' 161 | { 301, 8, 18, 10, 1, -17 }, // 0x36 '6' 162 | { 319, 8, 18, 10, 1, -17 }, // 0x37 '7' 163 | { 337, 8, 18, 10, 1, -17 }, // 0x38 '8' 164 | { 355, 8, 18, 10, 1, -17 }, // 0x39 '9' 165 | { 373, 3, 13, 5, 1, -12 }, // 0x3A ':' 166 | { 378, 3, 16, 5, 1, -12 }, // 0x3B ';' 167 | { 384, 8, 8, 10, 1, -12 }, // 0x3C '<' 168 | { 392, 8, 7, 10, 1, -12 }, // 0x3D '=' 169 | { 399, 8, 8, 10, 1, -12 }, // 0x3E '>' 170 | { 407, 9, 18, 9, 0, -17 }, // 0x3F '?' 171 | { 428, 16, 21, 18, 1, -18 }, // 0x40 '@' 172 | { 470, 10, 18, 10, 0, -17 }, // 0x41 'A' 173 | { 493, 9, 18, 10, 1, -17 }, // 0x42 'B' 174 | { 514, 8, 18, 10, 1, -17 }, // 0x43 'C' 175 | { 532, 9, 18, 10, 1, -17 }, // 0x44 'D' 176 | { 553, 8, 18, 9, 1, -17 }, // 0x45 'E' 177 | { 571, 7, 18, 9, 1, -17 }, // 0x46 'F' 178 | { 587, 8, 18, 10, 1, -17 }, // 0x47 'G' 179 | { 605, 9, 18, 11, 1, -17 }, // 0x48 'H' 180 | { 626, 3, 18, 5, 1, -17 }, // 0x49 'I' 181 | { 633, 6, 18, 7, 0, -17 }, // 0x4A 'J' 182 | { 647, 9, 18, 11, 1, -17 }, // 0x4B 'K' 183 | { 668, 7, 18, 9, 1, -17 }, // 0x4C 'L' 184 | { 684, 12, 18, 14, 1, -17 }, // 0x4D 'M' 185 | { 711, 9, 18, 11, 1, -17 }, // 0x4E 'N' 186 | { 732, 8, 18, 10, 1, -17 }, // 0x4F 'O' 187 | { 750, 8, 18, 10, 1, -17 }, // 0x50 'P' 188 | { 768, 9, 20, 10, 1, -17 }, // 0x51 'Q' 189 | { 791, 9, 18, 10, 1, -17 }, // 0x52 'R' 190 | { 812, 8, 18, 9, 1, -17 }, // 0x53 'S' 191 | { 830, 9, 18, 9, 0, -17 }, // 0x54 'T' 192 | { 851, 8, 18, 10, 1, -17 }, // 0x55 'U' 193 | { 869, 9, 18, 10, 0, -17 }, // 0x56 'V' 194 | { 890, 14, 18, 14, 0, -17 }, // 0x57 'W' 195 | { 922, 10, 18, 10, 0, -17 }, // 0x58 'X' 196 | { 945, 10, 18, 10, 0, -17 }, // 0x59 'Y' 197 | { 968, 9, 18, 9, 0, -17 }, // 0x5A 'Z' 198 | { 989, 5, 21, 7, 1, -19 }, // 0x5B '[' 199 | { 1003, 10, 18, 10, 0, -17 }, // 0x5C '\' 200 | { 1026, 5, 21, 7, 1, -19 }, // 0x5D ']' 201 | { 1040, 10, 7, 10, 0, -17 }, // 0x5E '^' 202 | { 1049, 8, 3, 8, 0, 0 }, // 0x5F '_' 203 | { 1052, 5, 3, 13, 3, -21 }, // 0x60 '`' 204 | { 1054, 10, 18, 10, 0, -17 }, // 0x61 'a' 205 | { 1077, 9, 18, 10, 1, -17 }, // 0x62 'b' 206 | { 1098, 8, 18, 10, 1, -17 }, // 0x63 'c' 207 | { 1116, 9, 18, 10, 1, -17 }, // 0x64 'd' 208 | { 1137, 8, 18, 9, 1, -17 }, // 0x65 'e' 209 | { 1155, 7, 18, 9, 1, -17 }, // 0x66 'f' 210 | { 1171, 8, 18, 10, 1, -17 }, // 0x67 'g' 211 | { 1189, 9, 18, 11, 1, -17 }, // 0x68 'h' 212 | { 1210, 3, 18, 5, 1, -17 }, // 0x69 'i' 213 | { 1217, 6, 18, 7, 0, -17 }, // 0x6A 'j' 214 | { 1231, 9, 18, 11, 1, -17 }, // 0x6B 'k' 215 | { 1252, 7, 18, 9, 1, -17 }, // 0x6C 'l' 216 | { 1268, 12, 18, 14, 1, -17 }, // 0x6D 'm' 217 | { 1295, 9, 18, 11, 1, -17 }, // 0x6E 'n' 218 | { 1316, 8, 18, 10, 1, -17 }, // 0x6F 'o' 219 | { 1334, 8, 18, 10, 1, -17 }, // 0x70 'p' 220 | { 1352, 9, 20, 10, 1, -17 }, // 0x71 'q' 221 | { 1375, 9, 18, 10, 1, -17 }, // 0x72 'r' 222 | { 1396, 8, 18, 9, 1, -17 }, // 0x73 's' 223 | { 1414, 9, 18, 9, 0, -17 }, // 0x74 't' 224 | { 1435, 8, 18, 10, 1, -17 }, // 0x75 'u' 225 | { 1453, 9, 18, 10, 0, -17 }, // 0x76 'v' 226 | { 1474, 14, 18, 14, 0, -17 }, // 0x77 'w' 227 | { 1506, 10, 18, 10, 0, -17 }, // 0x78 'x' 228 | { 1529, 10, 18, 10, 0, -17 }, // 0x79 'y' 229 | { 1552, 9, 18, 9, 0, -17 }, // 0x7A 'z' 230 | { 1573, 5, 21, 7, 1, -19 }, // 0x7B '{' 231 | { 1587, 3, 25, 13, 5, -19 }, // 0x7C '|' 232 | { 1597, 5, 21, 7, 1, -19 }, // 0x7D '}' 233 | { 1611, 10, 4, 10, 0, -10 } }; // 0x7E '~' 234 | 235 | const GFXfont BebasNeue_Regular13pt7b PROGMEM = { 236 | (uint8_t *)BebasNeue_Regular13pt7bBitmaps, 237 | (GFXglyph *)BebasNeue_Regular13pt7bGlyphs, 238 | 0x20, 0x7E, 31 }; 239 | 240 | // Approx. 2288 bytes 241 | -------------------------------------------------------------------------------- /examples/4x1Screens/gameoflife/gameoflife.ino: -------------------------------------------------------------------------------- 1 | // Screen Layout : 4 screens on a single row 2 | // See the tutorial : https://youtu.be/eCfeJh9Pyns 3 | // 4 | 5 | #include "virtualScreen.h" 6 | #include "BebasNeue_Regular13pt7b.h" 7 | 8 | VirtualDisplay *tft; 9 | ScreenBuilder screens; 10 | 11 | void setup() 12 | { 13 | Serial.begin(115200); 14 | 15 | // Adjust this setup according to your actual screen layout 16 | screens.addRow({{16, 0}, {15, 0}, {6, 0}, {7, 0}}); 17 | 18 | tft = new VirtualDisplay(screens.width(), screens.height(), &screens); 19 | tft->begin(); 20 | 21 | 22 | gameOfLife(); 23 | } 24 | 25 | void loop() 26 | { 27 | } 28 | 29 | int gridWidth; // Width of the grid 30 | int gridHeight; // Height of the grid 31 | bool **currentGrid; 32 | bool **nextGrid; 33 | const int squareSize = 10; 34 | const int statsWidth = 240; // Width of the stats area on the left, adjust as needed 35 | int aliveCellsCount = 0; 36 | int changeRate = 0; 37 | const uint16_t statsBgColor = 0x3186; 38 | std::vector populationHistory; 39 | 40 | void gameOfLife() 41 | { 42 | tft->fillScreen(TFT_BLACK); 43 | setupGameOfLife(); // Initialize the game 44 | for (int i = 0; i < 1000; i++) 45 | { // Run for 1000 generations 46 | updateGameOfLife(); // Update the grid 47 | drawGameOfLife(); // Draw the grid 48 | drawStats(i); // Draw the stats with the current generation 49 | drawPopulationGraph(); 50 | 51 | delay(100); // Delay between generations 52 | } 53 | cleanupGameOfLife(); // Clean up the dynamically allocated memory 54 | } 55 | 56 | void setupGameOfLife() 57 | { 58 | gridWidth = (tft->width() - statsWidth) / squareSize; // Adjusted for stats area 59 | gridHeight = tft->height() / squareSize; 60 | 61 | // Allocate memory for the grids 62 | currentGrid = new bool *[gridHeight]; 63 | nextGrid = new bool *[gridHeight]; 64 | for (int y = 0; y < gridHeight; y++) 65 | { 66 | currentGrid[y] = new bool[gridWidth]; 67 | nextGrid[y] = new bool[gridWidth]; 68 | } 69 | 70 | // Randomly initialize the currentGrid 71 | for (int y = 0; y < gridHeight; y++) 72 | { 73 | for (int x = 0; x < gridWidth; x++) 74 | { 75 | currentGrid[y][x] = esp_random() % 2; // Randomly alive or dead 76 | } 77 | } 78 | } 79 | 80 | void cleanupGameOfLife() 81 | { 82 | for (int y = 0; y < gridHeight; y++) 83 | { 84 | delete[] currentGrid[y]; 85 | delete[] nextGrid[y]; 86 | } 87 | delete[] currentGrid; 88 | delete[] nextGrid; 89 | } 90 | 91 | void updateGameOfLife() 92 | { 93 | int newAliveCellsCount = 0; 94 | int newChangeRate = 0; 95 | 96 | // Apply Game of Life rules to update the grid 97 | for (int y = 0; y < gridHeight; y++) 98 | { 99 | for (int x = 0; x < gridWidth; x++) 100 | { 101 | int aliveNeighbors = 0; 102 | 103 | // Count alive neighbors 104 | for (int i = -1; i <= 1; i++) 105 | { 106 | for (int j = -1; j <= 1; j++) 107 | { 108 | if (i == 0 && j == 0) 109 | { 110 | continue; // Skip the current cell 111 | } 112 | int nx = x + j; 113 | int ny = y + i; 114 | if (nx >= 0 && nx < gridWidth && ny >= 0 && ny < gridHeight && currentGrid[ny][nx]) 115 | { 116 | aliveNeighbors++; 117 | } 118 | } 119 | } 120 | 121 | // Apply the rules of the Game of Life 122 | bool newState = currentGrid[y][x]; 123 | if (currentGrid[y][x] && (aliveNeighbors < 2 || aliveNeighbors > 3)) 124 | { 125 | newState = false; // Cell dies 126 | } 127 | else if (!currentGrid[y][x] && aliveNeighbors == 3) 128 | { 129 | newState = true; // Cell becomes alive 130 | } 131 | 132 | if (newState != currentGrid[y][x]) 133 | { 134 | newChangeRate++; // Increment change rate if cell state changes 135 | } 136 | 137 | if (newState) 138 | { 139 | newAliveCellsCount++; // Count alive cells 140 | } 141 | 142 | nextGrid[y][x] = newState; 143 | } 144 | } 145 | 146 | // Copy nextGrid to currentGrid for the next iteration and update stats 147 | for (int y = 0; y < gridHeight; y++) 148 | { 149 | for (int x = 0; x < gridWidth; x++) 150 | { 151 | currentGrid[y][x] = nextGrid[y][x]; 152 | } 153 | } 154 | 155 | aliveCellsCount = newAliveCellsCount; 156 | populationHistory.push_back(newAliveCellsCount); 157 | changeRate = newChangeRate; 158 | } 159 | 160 | void drawGameOfLife() 161 | { 162 | for (int y = 0; y < gridHeight; y++) 163 | { 164 | for (int x = 0; x < gridWidth; x++) 165 | { 166 | uint16_t color = currentGrid[y][x] ? 0x07e0 : TFT_BLACK; 167 | tft->fillRect(x * squareSize + statsWidth, y * squareSize, squareSize, squareSize, color); 168 | } 169 | } 170 | tft->output(); 171 | } 172 | void drawPopulationGraph() 173 | { 174 | int graphWidth = statsWidth - 10; // Width of the graph, leaving some margin 175 | int graphHeight = 50; // Height of the graph, adjust as needed 176 | int graphX = 5; // X position of the graph 177 | int graphY = tft->height() - graphHeight - 10; // Y position, placed at the bottom 178 | int titleHeight = 15; // Height for the title area 179 | 180 | // Clear the area for the graph and title 181 | tft->fillRect(graphX, graphY - titleHeight, graphWidth, graphHeight + titleHeight, statsBgColor); 182 | 183 | // Draw the title for the graph 184 | tft->setTextColor(0x07fb); 185 | tft->setCursor(8, graphY - titleHeight); // Set position for the title 186 | tft->print("Population Over Time"); 187 | 188 | // Check if there is enough data to draw the graph 189 | if (populationHistory.size() < 2) 190 | return; 191 | 192 | // Calculate the scaling factor for the graph 193 | int maxPopulation = *std::max_element(populationHistory.begin(), populationHistory.end()); 194 | float scaleY = static_cast(graphHeight) / maxPopulation; 195 | float scaleX = static_cast(graphWidth) / (populationHistory.size() - 1); 196 | 197 | // Draw the graph line 198 | for (size_t i = 0; i < populationHistory.size() - 1; ++i) 199 | { 200 | int x0 = graphX + i * scaleX; 201 | int y0 = graphY + graphHeight - populationHistory[i] * scaleY; 202 | int x1 = graphX + (i + 1) * scaleX; 203 | int y1 = graphY + graphHeight - populationHistory[i + 1] * scaleY; 204 | tft->drawLine(x0, y0, x1, y1, TFT_YELLOW); 205 | } 206 | } 207 | 208 | void drawStats(int generation) 209 | { 210 | // Clear the stats area 211 | tft->fillRect(0, 0, statsWidth, tft->height(), statsBgColor); 212 | 213 | tft->setTextColor(0x07fb); 214 | tft->setFont(&BebasNeue_Regular13pt7b); 215 | tft->setCursor(8, 30); 216 | tft->print("Generation:"); 217 | tft->setTextColor(TFT_WHITE); 218 | tft->print(generation); 219 | tft->setTextColor(0x07fb); 220 | tft->setCursor(8, 60); 221 | tft->print("Alive: "); 222 | tft->setTextColor(TFT_WHITE); 223 | tft->print(aliveCellsCount); 224 | tft->setCursor(8, 90); 225 | tft->setTextColor(0x07fb); 226 | tft->print("Change: "); 227 | tft->setTextColor(TFT_WHITE); 228 | tft->print(changeRate); 229 | } 230 | -------------------------------------------------------------------------------- /examples/4x1Screens/image/image.ino: -------------------------------------------------------------------------------- 1 | // Screen Layout : 4 screens on a single row 2 | // See the tutorial : https://youtu.be/eCfeJh9Pyns 3 | // 4 | 5 | #include "virtualScreen.h" 6 | #include "night_earth_960x240.h" 7 | #include "newyork_960x240.h" 8 | 9 | 10 | VirtualDisplay *tft; 11 | ScreenBuilder screens; 12 | 13 | void setup() 14 | { 15 | Serial.begin(115200); 16 | 17 | // Adjust this setup according to your actual screen layout 18 | screens.addRow({{16, 0}, {15, 0}, {6, 0}, {7, 0}}); 19 | 20 | 21 | tft = new VirtualDisplay(screens.width(), screens.height(), &screens); 22 | tft->begin(); 23 | 24 | tft->fillScreen(TFT_BLACK); 25 | tft->drawRGBBitmap(0, 0, (uint16_t *)night_earth, night_earth_width, night_earth_height); 26 | tft->output(); 27 | delay(5000); 28 | tft->fillScreen(TFT_BLACK); 29 | tft->drawRGBBitmap(0, 0, (uint16_t *)newyork, newyork_width, newyork_height); 30 | tft->output(); 31 | } 32 | 33 | 34 | void loop() 35 | { 36 | } 37 | -------------------------------------------------------------------------------- /examples/4x1Screens/maze/maze.ino: -------------------------------------------------------------------------------- 1 | // Screen Layout : 4 screens on a single row 2 | // See the tutorial : https://youtu.be/eCfeJh9Pyns 3 | // 4 | 5 | #include "virtualScreen.h" 6 | #include 7 | #include 8 | #include // For std::pair 9 | 10 | VirtualDisplay *tft; 11 | ScreenBuilder screens; 12 | 13 | void setup() 14 | { 15 | Serial.begin(115200); 16 | 17 | // Adjust this setup according to your actual screen layout 18 | screens.addRow({{16, 0}, {15, 0}, {6, 0}, {7, 0}}); 19 | 20 | tft = new VirtualDisplay(screens.width(), screens.height(), &screens); 21 | tft->begin(); 22 | 23 | playMaze(); 24 | } 25 | 26 | void loop() 27 | { 28 | } 29 | 30 | struct Cell 31 | { 32 | bool visited = false; 33 | bool topWall = true; 34 | bool bottomWall = true; 35 | bool leftWall = true; 36 | bool rightWall = true; 37 | }; 38 | 39 | const int cellSize = 30; // Global cell size in pixels 40 | const int paddingSize = 5; // Total padding in pixels, adjust as needed 41 | 42 | std::vector> maze; 43 | int mazeWidth; // Maze width in cells 44 | int mazeHeight; // Maze height in cells 45 | 46 | void playMaze() 47 | { 48 | tft->fillScreen(TFT_BLACK); 49 | setupMaze(); 50 | } 51 | 52 | std::vector> solveMaze() 53 | { 54 | std::stack> stack; 55 | std::vector> visited(mazeHeight, std::vector(mazeWidth, false)); 56 | std::vector> path; 57 | 58 | // Start from an edge, for example, (0, 0) 59 | stack.push({0, 0}); 60 | visited[0][0] = true; 61 | 62 | while (!stack.empty()) 63 | { 64 | auto [x, y] = stack.top(); 65 | path.push_back({x, y}); // Add to path 66 | 67 | // Check if the center is reached 68 | if (x == mazeWidth / 2 && y == mazeHeight / 2) 69 | { 70 | return path; // Return the path to the center 71 | } 72 | 73 | // Find unvisited neighbors without walls in between 74 | std::vector> unvisitedNeighbors; 75 | if (x > 0 && !visited[y][x - 1] && !maze[y][x].leftWall) 76 | { 77 | unvisitedNeighbors.push_back({x - 1, y}); 78 | } 79 | if (y > 0 && !visited[y - 1][x] && !maze[y][x].topWall) 80 | { 81 | unvisitedNeighbors.push_back({x, y - 1}); 82 | } 83 | if (x < mazeWidth - 1 && !visited[y][x + 1] && !maze[y][x].rightWall) 84 | { 85 | unvisitedNeighbors.push_back({x + 1, y}); 86 | } 87 | if (y < mazeHeight - 1 && !visited[y + 1][x] && !maze[y][x].bottomWall) 88 | { 89 | unvisitedNeighbors.push_back({x, y + 1}); 90 | } 91 | 92 | if (!unvisitedNeighbors.empty()) 93 | { 94 | auto [nextX, nextY] = unvisitedNeighbors.back(); 95 | visited[nextY][nextX] = true; 96 | stack.push({nextX, nextY}); 97 | } 98 | else 99 | { 100 | stack.pop(); 101 | path.pop_back(); // Remove from path if it's a dead end 102 | } 103 | } 104 | return path; // In case the center can't be reached, return the attempted path 105 | } 106 | 107 | void generateMaze() 108 | { 109 | std::stack> stack; 110 | 111 | // Start from the center of the maze 112 | int centerX = mazeWidth / 2; 113 | int centerY = mazeHeight / 2; 114 | maze[centerY][centerX].visited = true; 115 | stack.push({centerX, centerY}); 116 | 117 | while (!stack.empty()) 118 | { 119 | auto [x, y] = stack.top(); 120 | std::vector> unvisitedNeighbors; 121 | 122 | // Check unvisited neighbors 123 | if (x > 0 && !maze[y][x - 1].visited) 124 | { 125 | unvisitedNeighbors.push_back({x - 1, y}); 126 | } 127 | if (y > 0 && !maze[y - 1][x].visited) 128 | { 129 | unvisitedNeighbors.push_back({x, y - 1}); 130 | } 131 | if (x < mazeWidth - 1 && !maze[y][x + 1].visited) 132 | { 133 | unvisitedNeighbors.push_back({x + 1, y}); 134 | } 135 | if (y < mazeHeight - 1 && !maze[y + 1][x].visited) 136 | { 137 | unvisitedNeighbors.push_back({x, y + 1}); 138 | } 139 | 140 | if (!unvisitedNeighbors.empty()) 141 | { 142 | // Randomly select a neighbor 143 | auto [nextX, nextY] = unvisitedNeighbors[esp_random() % unvisitedNeighbors.size()]; 144 | 145 | // Remove the wall between the current cell and the chosen cell 146 | if (nextX == x + 1) 147 | { 148 | maze[y][x].rightWall = false; 149 | maze[nextY][nextX].leftWall = false; 150 | } 151 | else if (nextX == x - 1) 152 | { 153 | maze[y][x].leftWall = false; 154 | maze[nextY][nextX].rightWall = false; 155 | } 156 | else if (nextY == y + 1) 157 | { 158 | maze[y][x].bottomWall = false; 159 | maze[nextY][nextX].topWall = false; 160 | } 161 | else if (nextY == y - 1) 162 | { 163 | maze[y][x].topWall = false; 164 | maze[nextY][nextX].bottomWall = false; 165 | } 166 | 167 | maze[nextY][nextX].visited = true; 168 | stack.push({nextX, nextY}); 169 | } 170 | else 171 | { 172 | stack.pop(); 173 | } 174 | } 175 | } 176 | void drawMaze(const std::vector> &path) 177 | { 178 | for (int y = 0; y < mazeHeight; y++) 179 | { 180 | for (int x = 0; x < mazeWidth; x++) 181 | { 182 | // Calculate the top left corner of the cell 183 | int x0 = x * cellSize; 184 | int y0 = y * cellSize; 185 | 186 | // Draw the walls of the cell 187 | if (maze[y][x].topWall) 188 | { 189 | tft->drawLine(x0, y0, x0 + cellSize, y0, TFT_WHITE); // Top wall 190 | } 191 | if (maze[y][x].bottomWall) 192 | { 193 | tft->drawLine(x0, y0 + cellSize, x0 + cellSize, y0 + cellSize, TFT_WHITE); // Bottom wall 194 | } 195 | if (maze[y][x].leftWall) 196 | { 197 | tft->drawLine(x0, y0, x0, y0 + cellSize, TFT_WHITE); // Left wall 198 | } 199 | if (maze[y][x].rightWall) 200 | { 201 | tft->drawLine(x0 + cellSize, y0, x0 + cellSize, y0 + cellSize, TFT_WHITE); // Right wall 202 | } 203 | } 204 | } 205 | 206 | // Draw the solution path in yellow 207 | for (size_t i = 0; i < path.size() - 1; ++i) 208 | { 209 | // Coordinates of the current cell 210 | int x0 = path[i].first * cellSize + cellSize / 2; 211 | int y0 = path[i].second * cellSize + cellSize / 2; 212 | 213 | // Coordinates of the next cell 214 | int x1 = path[i + 1].first * cellSize + cellSize / 2; 215 | int y1 = path[i + 1].second * cellSize + cellSize / 2; 216 | 217 | // Check if the next cell is a direct neighbor of the current cell 218 | bool isNeighbor = (path[i].first == path[i + 1].first && abs(path[i].second - path[i + 1].second) == 1) || 219 | (path[i].second == path[i + 1].second && abs(path[i].first - path[i + 1].first) == 1); 220 | 221 | // Draw line only if the next cell is a neighbor 222 | if (isNeighbor) 223 | { 224 | tft->drawLine(x0, y0, x1, y1, TFT_YELLOW); 225 | tft->output(); 226 | } 227 | } 228 | if (!path.empty()) 229 | { 230 | // Get the coordinates of the last cell in the path 231 | auto [lastX, lastY] = path.back(); 232 | int centerX = lastX * cellSize + cellSize / 2; 233 | int centerY = lastY * cellSize + cellSize / 2; 234 | 235 | // Draw a yellow circle at the end of the path 236 | int radius = cellSize / 4; // Radius of the circle 237 | tft->fillCircle(centerX, centerY, radius, TFT_YELLOW); 238 | } 239 | 240 | tft->output(); 241 | } 242 | 243 | void setupMaze() 244 | { 245 | // Adjusted dimensions to account for padding 246 | mazeWidth = (tft->width() - paddingSize) / cellSize; // Ensure odd number 247 | mazeHeight = (tft->height() - paddingSize) / cellSize; // Ensure odd number 248 | 249 | // Ensure dimensions are odd numbers 250 | if (mazeWidth % 2 == 0) 251 | { 252 | mazeWidth--; 253 | } 254 | if (mazeHeight % 2 == 0) 255 | { 256 | mazeHeight--; 257 | } 258 | 259 | // Allocate memory for the maze grid 260 | maze.resize(mazeHeight, std::vector(mazeWidth)); 261 | 262 | // Generate and draw the maze 263 | generateMaze(); 264 | auto path = solveMaze(); 265 | 266 | drawMaze(path); 267 | } 268 | -------------------------------------------------------------------------------- /examples/4x1Screens/pong/Fun_Games20pt7b.h: -------------------------------------------------------------------------------- 1 | const uint8_t Fun_Games20pt7bBitmaps[] PROGMEM = { 2 | 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xEF, 0x38, 3 | 0xC2, 0x10, 0x7F, 0xFF, 0xFF, 0xC0, 0xEF, 0xDF, 0xBF, 0x7E, 0xFD, 0xFB, 4 | 0x80, 0x01, 0x80, 0x80, 0x03, 0x83, 0xC0, 0x1E, 0x0E, 0x00, 0x70, 0x38, 5 | 0x01, 0xC0, 0xE0, 0x07, 0x03, 0x80, 0x1C, 0x1E, 0x1F, 0xFF, 0xFF, 0x7F, 6 | 0xFF, 0xFD, 0xFF, 0xFF, 0xF0, 0x38, 0x1C, 0x00, 0xE0, 0xF0, 0x03, 0x83, 7 | 0x80, 0x1E, 0x0E, 0x00, 0x78, 0x38, 0x01, 0xC0, 0xE0, 0x07, 0x03, 0x80, 8 | 0x1C, 0x1E, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0x38, 9 | 0x1C, 0x00, 0xE0, 0x70, 0x03, 0x83, 0xC0, 0x0E, 0x0E, 0x00, 0x78, 0x38, 10 | 0x01, 0xC0, 0xE0, 0x07, 0x03, 0x80, 0x00, 0x0F, 0x00, 0x00, 0x0F, 0x00, 11 | 0x00, 0x0F, 0x00, 0x00, 0x0F, 0x00, 0x01, 0xFF, 0xFE, 0x03, 0xFF, 0xFC, 12 | 0x07, 0xFF, 0xF8, 0x07, 0xFF, 0xF0, 0x0F, 0xFF, 0xF0, 0x0F, 0x80, 0x00, 13 | 0x1F, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x7F, 0xFF, 0xFF, 14 | 0x7F, 0xFF, 0xFF, 0x7F, 0xFF, 0xFF, 0x7F, 0xFF, 0xFF, 0x7F, 0xFF, 0xFF, 15 | 0x00, 0x00, 0x3F, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x7C, 16 | 0x00, 0x00, 0xF8, 0x0F, 0xFF, 0xF8, 0x1F, 0xFF, 0xF0, 0x3F, 0xFF, 0xF0, 17 | 0x3F, 0xFF, 0xE0, 0x7F, 0xFF, 0xC0, 0x80, 0x0F, 0x00, 0x00, 0x0F, 0x00, 18 | 0x00, 0x0F, 0x00, 0x00, 0x0F, 0x00, 0xFC, 0x1F, 0xF8, 0x3B, 0xF0, 0xF7, 19 | 0xE1, 0xEF, 0xC7, 0x9F, 0x8F, 0x00, 0x3C, 0x00, 0x78, 0x01, 0xE0, 0x03, 20 | 0xC0, 0x0F, 0x00, 0x1E, 0x00, 0x78, 0x00, 0xF0, 0x03, 0xC0, 0x07, 0x80, 21 | 0x1E, 0x00, 0x3C, 0x00, 0x7B, 0xF1, 0xE7, 0xE3, 0xCF, 0xCF, 0x1F, 0x9E, 22 | 0x3F, 0x78, 0x7E, 0xFF, 0xFF, 0xE3, 0xFF, 0xFF, 0x8F, 0xFF, 0xFE, 0x3F, 23 | 0xFF, 0xF8, 0xFF, 0xFF, 0xE3, 0xE0, 0x00, 0x0F, 0x80, 0x00, 0x3E, 0x00, 24 | 0x00, 0xF8, 0x00, 0x03, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 25 | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0x3E, 0x3E, 0x00, 0xF8, 0xF8, 26 | 0x03, 0xE3, 0xE0, 0x0F, 0x8F, 0xC0, 0x3E, 0x3F, 0xFF, 0xF8, 0x7F, 0xFF, 27 | 0xE0, 0xFF, 0xFF, 0x81, 0xFF, 0xFE, 0x01, 0xFF, 0xF8, 0xFF, 0xFF, 0xF8, 28 | 0x07, 0xFF, 0x0F, 0xFE, 0x3F, 0xFC, 0x7F, 0xF0, 0xFF, 0xE0, 0xFC, 0x00, 29 | 0xF8, 0x00, 0xF8, 0x00, 0xF8, 0x00, 0xF8, 0x00, 0xF8, 0x00, 0xF8, 0x00, 30 | 0xF8, 0x00, 0xF8, 0x00, 0xF8, 0x00, 0xF8, 0x00, 0xF8, 0x00, 0xF8, 0x00, 31 | 0xF8, 0x00, 0xF8, 0x00, 0xF8, 0x00, 0xF8, 0x00, 0xF8, 0x00, 0xF8, 0x00, 32 | 0xFC, 0x00, 0xFF, 0xE0, 0x7F, 0xF0, 0x3F, 0xFC, 0x0F, 0xFE, 0x07, 0xFF, 33 | 0xFF, 0xE0, 0x7F, 0xF0, 0x1F, 0xFC, 0x0F, 0xFE, 0x07, 0xFF, 0x00, 0x3F, 34 | 0x00, 0x1F, 0x00, 0x1F, 0x00, 0x1F, 0x00, 0x1F, 0x00, 0x1F, 0x00, 0x1F, 35 | 0x00, 0x1F, 0x00, 0x1F, 0x00, 0x1F, 0x00, 0x1F, 0x00, 0x1F, 0x00, 0x1F, 36 | 0x00, 0x1F, 0x00, 0x1F, 0x00, 0x1F, 0x00, 0x1F, 0x00, 0x1F, 0x00, 0x1F, 37 | 0x00, 0x3F, 0x07, 0xFF, 0x0F, 0xFE, 0x1F, 0xFC, 0x7F, 0xF0, 0xFF, 0xE0, 38 | 0x0C, 0x0B, 0x47, 0xF8, 0xFC, 0xFF, 0xFF, 0xF3, 0xF1, 0xFE, 0x2D, 0x03, 39 | 0x00, 0x00, 0xF8, 0x00, 0x07, 0xC0, 0x00, 0x3E, 0x00, 0x01, 0xF0, 0x00, 40 | 0x0F, 0x80, 0x00, 0x7C, 0x00, 0x03, 0xE0, 0x00, 0x1F, 0x00, 0xFF, 0xFF, 41 | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 42 | 0x7C, 0x00, 0x03, 0xE0, 0x00, 0x1F, 0x00, 0x00, 0xF8, 0x00, 0x07, 0xC0, 43 | 0x00, 0x3E, 0x00, 0x01, 0xF0, 0x00, 0x0F, 0x80, 0x00, 0xFF, 0xFF, 0xFF, 44 | 0xFB, 0xDC, 0xC4, 0x20, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 45 | 0x80, 0xFF, 0xFF, 0xFF, 0x80, 0x00, 0x18, 0x00, 0x70, 0x03, 0xC0, 0x0E, 46 | 0x00, 0x78, 0x01, 0xC0, 0x07, 0x00, 0x3C, 0x00, 0xE0, 0x07, 0x80, 0x1C, 47 | 0x00, 0xF0, 0x03, 0x80, 0x0E, 0x00, 0x78, 0x01, 0xC0, 0x0F, 0x00, 0x38, 48 | 0x01, 0xE0, 0x07, 0x00, 0x1C, 0x00, 0xF0, 0x03, 0x80, 0x1E, 0x00, 0x70, 49 | 0x01, 0xC0, 0x0F, 0x00, 0x38, 0x00, 0x60, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 50 | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0x00, 0x7F, 51 | 0xE0, 0x03, 0xFF, 0x00, 0x1F, 0xF8, 0x00, 0xFF, 0xC0, 0x07, 0xFE, 0x00, 52 | 0x3F, 0xF0, 0x01, 0xFF, 0x80, 0x0F, 0xFC, 0x00, 0x7F, 0xE0, 0x03, 0xFF, 53 | 0x00, 0x1F, 0xF8, 0x00, 0xFF, 0xC0, 0x07, 0xFE, 0x00, 0x3F, 0xFF, 0xFF, 54 | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 55 | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC1, 0xF0, 0x7C, 0x1F, 0x07, 0xC1, 0xF0, 56 | 0x7C, 0x1F, 0x07, 0xC1, 0xF0, 0x7C, 0x1F, 0x07, 0xC1, 0xF0, 0x7C, 0x1F, 57 | 0x07, 0xC1, 0xF0, 0x7C, 0x1F, 0x07, 0xC0, 0xF0, 0x1C, 0x03, 0x00, 0xC0, 58 | 0x10, 0xFF, 0xFF, 0x80, 0xFF, 0xFF, 0x80, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 59 | 0x00, 0xFF, 0xFE, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x7C, 60 | 0x00, 0x00, 0xFD, 0xFF, 0xFF, 0xFB, 0xFF, 0xFF, 0xF7, 0xFF, 0xFF, 0xEF, 61 | 0xFF, 0xFF, 0xDF, 0xFF, 0xFF, 0xBE, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x7C, 62 | 0x00, 0x00, 0xFC, 0x00, 0x00, 0xF8, 0x00, 0x01, 0xFF, 0xFF, 0x01, 0xFF, 63 | 0xFF, 0x01, 0xFF, 0xFF, 0x03, 0xFF, 0xFF, 0x03, 0xFF, 0xFF, 0xFF, 0xFF, 64 | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0x00, 0x07, 65 | 0xC0, 0x00, 0xF8, 0x00, 0x1F, 0x00, 0x03, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 66 | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC0, 0x00, 0xF8, 0x00, 0x1F, 67 | 0x00, 0x03, 0xE0, 0x00, 0x7C, 0x00, 0x1F, 0x87, 0xFF, 0xF1, 0xFF, 0xFC, 68 | 0x7F, 0xFF, 0x0F, 0xFF, 0xC3, 0xFF, 0xE0, 0xF8, 0x03, 0xFF, 0x00, 0x7F, 69 | 0xE0, 0x0F, 0xFC, 0x01, 0xFF, 0x80, 0x3F, 0xF0, 0x07, 0xFE, 0x00, 0xFF, 70 | 0xC0, 0x1F, 0xF8, 0x03, 0xFF, 0x00, 0x7F, 0xE0, 0x0F, 0xFC, 0x01, 0xFF, 71 | 0x80, 0x3F, 0xF0, 0x07, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 72 | 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0x01, 0xF0, 0x00, 0x3E, 0x00, 0x07, 0xC0, 73 | 0x00, 0xF8, 0x00, 0x1F, 0x00, 0x03, 0xE0, 0x00, 0x3C, 0x00, 0x03, 0x80, 74 | 0x00, 0x30, 0x00, 0x06, 0x00, 0x00, 0x40, 0x00, 0x08, 0x07, 0xFF, 0xFE, 75 | 0x1F, 0xFF, 0xF8, 0x7F, 0xFF, 0xE1, 0xFF, 0xFF, 0x83, 0xFF, 0xFE, 0x0F, 76 | 0xE0, 0x00, 0x3F, 0x80, 0x00, 0x7E, 0x00, 0x00, 0xFF, 0xFF, 0xFD, 0xFF, 77 | 0xFF, 0xFB, 0xFF, 0xFF, 0xF7, 0xFF, 0xFF, 0xEF, 0xFF, 0xFF, 0xC0, 0x00, 78 | 0x1F, 0x80, 0x00, 0x7F, 0x00, 0x00, 0xFC, 0x00, 0x03, 0xF0, 0x00, 0x07, 79 | 0xE0, 0x00, 0x0F, 0x80, 0x7F, 0xFF, 0x01, 0xFF, 0xFC, 0x07, 0xFF, 0xF8, 80 | 0x1F, 0xFF, 0xE0, 0x7F, 0xFF, 0xC0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xBF, 81 | 0xFF, 0xF9, 0xFF, 0xFF, 0x8F, 0xFF, 0xF8, 0x7C, 0x00, 0x03, 0xE0, 0x00, 82 | 0x1F, 0x00, 0x00, 0xF8, 0x00, 0x07, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 83 | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE0, 0x03, 0xFF, 0x00, 0x1F, 84 | 0xF8, 0x00, 0xFF, 0xC0, 0x07, 0xFE, 0x00, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 85 | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE7, 86 | 0xFF, 0xF8, 0x7F, 0xFF, 0x0F, 0xFF, 0xE0, 0xFF, 0xF8, 0x00, 0x1F, 0x00, 87 | 0x03, 0xE0, 0x00, 0x7C, 0x00, 0x1F, 0x00, 0x03, 0xE0, 0x00, 0x7C, 0x00, 88 | 0x1F, 0x80, 0x03, 0xE0, 0x00, 0x7C, 0x00, 0x0F, 0x80, 0x03, 0xE0, 0x00, 89 | 0x7C, 0x00, 0x0F, 0x80, 0x01, 0xF0, 0x00, 0x7C, 0x00, 0x0F, 0x80, 0x01, 90 | 0xF0, 0x00, 0x7E, 0x00, 0x0F, 0x80, 0x01, 0xF0, 0x00, 0x1E, 0x00, 0x03, 91 | 0x80, 0x00, 0x30, 0x00, 0x02, 0x00, 0x00, 0x40, 0x00, 0xFF, 0xFF, 0xFF, 92 | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0x00, 93 | 0x7F, 0xE0, 0x03, 0xFF, 0x00, 0x1F, 0xF8, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 94 | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE0, 0x03, 95 | 0xFF, 0x00, 0x1F, 0xF8, 0x00, 0xFF, 0xC0, 0x07, 0xFE, 0x00, 0x3F, 0xFF, 96 | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 97 | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 98 | 0xFF, 0xFC, 0x00, 0x7F, 0xE0, 0x03, 0xFF, 0x00, 0x1F, 0xF8, 0x00, 0xFF, 99 | 0xC0, 0x07, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 100 | 0xFF, 0xFF, 0xFF, 0xE0, 0x00, 0x1F, 0x00, 0x00, 0xF8, 0x00, 0x07, 0xC0, 101 | 0x00, 0x3E, 0x3F, 0xFF, 0xF1, 0xFF, 0xFF, 0x9F, 0xFF, 0xFD, 0xFF, 0xFF, 102 | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 103 | 0x00, 0xFF, 0xFF, 0xFF, 0x80, 0xFF, 0xFF, 0xFF, 0x80, 0x00, 0x00, 0x00, 104 | 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xDC, 0xC4, 0x20, 0x00, 0x08, 105 | 0x01, 0xC0, 0x3E, 0x03, 0xF0, 0x7F, 0x87, 0xF0, 0xFF, 0x1F, 0xE0, 0xFC, 106 | 0x07, 0xC0, 0x38, 0x01, 0xF0, 0x0F, 0xC0, 0x7F, 0x80, 0xFF, 0x01, 0xFC, 107 | 0x07, 0xF8, 0x0F, 0xC0, 0x1E, 0x00, 0x70, 0x00, 0x80, 0xFF, 0xFF, 0xFF, 108 | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0x00, 0x00, 0x3F, 109 | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 110 | 0x80, 0x07, 0x00, 0x3E, 0x01, 0xF8, 0x0F, 0xF0, 0x1F, 0xC0, 0x7F, 0x80, 111 | 0xFF, 0x01, 0xF8, 0x07, 0xC0, 0x0E, 0x01, 0xF0, 0x1F, 0x83, 0xFC, 0x7F, 112 | 0x87, 0xF0, 0xFF, 0x07, 0xE0, 0x3C, 0x01, 0xC0, 0x08, 0x00, 0x00, 0xFF, 113 | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0x00, 114 | 0x07, 0xC0, 0x00, 0xF8, 0x00, 0x1F, 0x00, 0x03, 0xE0, 0x3F, 0xFC, 0x07, 115 | 0xFF, 0x80, 0xFF, 0xF0, 0x1F, 0xFE, 0x03, 0xFF, 0xC0, 0x00, 0x00, 0x00, 116 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x1F, 117 | 0x00, 0x03, 0xE0, 0x00, 0x7C, 0x00, 0x0F, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 118 | 0xFF, 0xFF, 0xFF, 0xFE, 0x00, 0x07, 0xE0, 0x00, 0x7E, 0x3F, 0xC7, 0xE3, 119 | 0xFC, 0x7E, 0x30, 0xC7, 0xE3, 0x3C, 0x7E, 0x37, 0xC7, 0xE3, 0xEC, 0x7E, 120 | 0x3C, 0xC7, 0xE3, 0x8C, 0x7E, 0x38, 0xC7, 0xE3, 0x00, 0x7E, 0x20, 0x07, 121 | 0xE4, 0x00, 0x7E, 0x00, 0x07, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 122 | 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 123 | 0xFF, 0xFF, 0xFC, 0x00, 0x7F, 0xE0, 0x03, 0xFF, 0x03, 0x1F, 0xF8, 0x3C, 124 | 0xFF, 0xC1, 0xF7, 0xFE, 0x1F, 0xFF, 0xF1, 0xFD, 0xFF, 0x9F, 0xCF, 0xFD, 125 | 0xFC, 0x7F, 0xEF, 0xC3, 0xFF, 0xFC, 0x1F, 0xFF, 0xE0, 0xFF, 0xFE, 0x07, 126 | 0xFF, 0xE0, 0x3F, 0xFE, 0x01, 0xFF, 0xF0, 0x0F, 0xFF, 0x00, 0x7F, 0xF0, 127 | 0x03, 0xFF, 0x00, 0x1F, 0xF8, 0x00, 0x07, 0x80, 0x00, 0x38, 0x00, 0x01, 128 | 0x80, 0x00, 0x08, 0x00, 0x00, 0x40, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 129 | 0xFF, 0xBF, 0xFF, 0xFD, 0xFF, 0xFF, 0xCF, 0xFF, 0xFC, 0x7C, 0x03, 0xE3, 130 | 0xE0, 0x3E, 0x1F, 0x03, 0xE0, 0xF8, 0x7F, 0xFF, 0xC3, 0xFF, 0xFE, 0x1F, 131 | 0xFF, 0xF0, 0xFF, 0xFF, 0x87, 0xFF, 0xFC, 0x01, 0xFF, 0xE0, 0x0F, 0xDF, 132 | 0x00, 0xFC, 0xF8, 0x0F, 0xC7, 0xC0, 0xFE, 0x3E, 0x07, 0xE1, 0xF0, 0x7E, 133 | 0x0F, 0x87, 0xE0, 0x7C, 0x7F, 0x03, 0xE3, 0xF0, 0x1F, 0x3F, 0x00, 0x03, 134 | 0xF0, 0x00, 0x3F, 0x80, 0x01, 0xF8, 0x00, 0x1F, 0x80, 0x00, 0xF8, 0x00, 135 | 0x03, 0xC0, 0x00, 0x04, 0x00, 0x00, 0x07, 0xFF, 0xF1, 0xFF, 0xFE, 0x3F, 136 | 0xFF, 0xC7, 0xFF, 0xF8, 0xFF, 0xFF, 0x0F, 0xC0, 0x00, 0xF8, 0x00, 0x0F, 137 | 0x80, 0x00, 0xF8, 0x00, 0x0F, 0x80, 0x00, 0xF8, 0x00, 0x0F, 0x80, 0x00, 138 | 0xF8, 0x00, 0x0F, 0x80, 0x00, 0xF8, 0x00, 0x0F, 0x80, 0x3E, 0xF8, 0x03, 139 | 0xEF, 0x80, 0x3E, 0xF8, 0x03, 0xEF, 0xFF, 0xFE, 0xFF, 0xFF, 0xEF, 0xFF, 140 | 0xFE, 0xFF, 0xFF, 0xEF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 141 | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x07, 0xFE, 0x00, 0xFF, 0xC0, 142 | 0x1F, 0xF8, 0x03, 0xFF, 0x00, 0x7F, 0xE0, 0x0F, 0xFC, 0x01, 0xFF, 0x80, 143 | 0x3F, 0xF0, 0x07, 0xFE, 0x00, 0xFF, 0xC0, 0x1F, 0xF8, 0x03, 0xFF, 0x00, 144 | 0x7F, 0xE0, 0x1F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFD, 0xFF, 0xFF, 0x3F, 0xFF, 145 | 0xC7, 0xFF, 0xE0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 146 | 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 147 | 0xFC, 0xFF, 0xF0, 0xFF, 0xE0, 0xFF, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 148 | 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 149 | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 150 | 0xFF, 0xFF, 0xFE, 0x00, 0x0F, 0x80, 0x03, 0xE0, 0x00, 0xF8, 0x00, 0x3F, 151 | 0xFF, 0xFF, 0xFF, 0xF3, 0xFF, 0xF8, 0xFF, 0xF8, 0x3F, 0xFC, 0x0F, 0x80, 152 | 0x03, 0xE0, 0x00, 0xF8, 0x00, 0x3E, 0x00, 0x0F, 0x80, 0x03, 0xE0, 0x00, 153 | 0xF8, 0x00, 0x3E, 0x00, 0x0F, 0x80, 0x03, 0xE0, 0x00, 0x07, 0xFF, 0xF1, 154 | 0xFF, 0xFE, 0x3F, 0xFF, 0xC7, 0xFF, 0xF8, 0xFF, 0xFF, 0x0F, 0xC0, 0x00, 155 | 0xF8, 0x00, 0x0F, 0x80, 0x00, 0xF8, 0x1F, 0xFF, 0x83, 0xFF, 0xF8, 0x7F, 156 | 0xFF, 0x8F, 0xFF, 0xF9, 0xFF, 0xFF, 0xA0, 0x1F, 0xF8, 0x01, 0xFF, 0x80, 157 | 0x1F, 0xF8, 0x01, 0xFF, 0x80, 0x1F, 0xF8, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 158 | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x08, 159 | 0x00, 0x00, 0x40, 0x00, 0x06, 0x00, 0x00, 0x70, 0x00, 0x07, 0x80, 0x00, 160 | 0x7F, 0xE0, 0x03, 0xFF, 0x00, 0x1F, 0xF8, 0x00, 0xFF, 0xC0, 0x07, 0xFE, 161 | 0x00, 0x3F, 0xF0, 0x01, 0xFF, 0x80, 0x0F, 0xFC, 0x00, 0x7F, 0xE0, 0x03, 162 | 0xFF, 0x00, 0x1F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 163 | 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0x00, 0x7F, 0xE0, 0x03, 0xFF, 0x00, 0x1F, 164 | 0xF8, 0x00, 0xFF, 0xC0, 0x07, 0xFE, 0x00, 0x3F, 0xF0, 0x01, 0xFF, 0x80, 165 | 0x0F, 0xFC, 0x00, 0x7F, 0xE0, 0x00, 0x0F, 0x00, 0x00, 0x38, 0x00, 0x00, 166 | 0xC0, 0x00, 0x02, 0x00, 0x00, 0x10, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 167 | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFB, 168 | 0xDE, 0x71, 0x84, 0x20, 0x7F, 0xFE, 0x7F, 0xFC, 0x7F, 0xF8, 0x7F, 0xF0, 169 | 0x7F, 0xE0, 0x07, 0xC0, 0x0F, 0x80, 0x1F, 0x00, 0x3E, 0x00, 0x7C, 0x00, 170 | 0xF8, 0x01, 0xF0, 0x03, 0xF0, 0x07, 0xE0, 0x0F, 0xE0, 0x1F, 0xE0, 0x3F, 171 | 0xE0, 0x7F, 0xE0, 0xFF, 0xC1, 0xFF, 0x83, 0xFF, 0x07, 0xFE, 0x0F, 0xFC, 172 | 0xFF, 0xFF, 0xFF, 0xFF, 0xFB, 0xFF, 0xC7, 0xFC, 0x0F, 0xE0, 0x1E, 0x00, 173 | 0x30, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x07, 0x00, 0x00, 0x3E, 0x00, 174 | 0x00, 0xFC, 0xF8, 0x07, 0xE3, 0xE0, 0x3F, 0x8F, 0x81, 0xFC, 0x3E, 0x0F, 175 | 0xE0, 0xF8, 0x7F, 0x03, 0xE3, 0xF8, 0x0F, 0x9F, 0xC0, 0x3E, 0xFE, 0x00, 176 | 0xFF, 0xF0, 0x03, 0xFF, 0x80, 0x0F, 0xFC, 0x00, 0x3F, 0xF8, 0x00, 0xFF, 177 | 0xE0, 0x03, 0xFF, 0xC0, 0x0F, 0xFF, 0x80, 0x3F, 0x7F, 0x00, 0xF8, 0xFC, 178 | 0x03, 0xE1, 0xF8, 0x0F, 0x87, 0xF0, 0x3E, 0x0F, 0xC0, 0xF8, 0x1F, 0x83, 179 | 0xE0, 0x7F, 0x0F, 0x80, 0xFC, 0x3E, 0x01, 0xF8, 0xF8, 0x03, 0xF1, 0xE0, 180 | 0x0F, 0xC3, 0x80, 0x1F, 0x86, 0x00, 0x3F, 0x18, 0x00, 0xFC, 0x20, 0x01, 181 | 0xE0, 0x80, 0x02, 0x00, 0x80, 0x00, 0x38, 0x00, 0x0F, 0x80, 0x03, 0xE0, 182 | 0x00, 0xF8, 0x00, 0x3E, 0x00, 0x0F, 0x80, 0x03, 0xE0, 0x00, 0xF8, 0x00, 183 | 0x3E, 0x00, 0x0F, 0x80, 0x03, 0xE0, 0x00, 0xF8, 0x00, 0x3E, 0x00, 0x0F, 184 | 0x80, 0x03, 0xE0, 0x00, 0xF8, 0x00, 0x3E, 0x00, 0x0F, 0x80, 0x03, 0xE0, 185 | 0x00, 0xF8, 0x00, 0x3E, 0x00, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 186 | 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0x80, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x70, 187 | 0x00, 0x00, 0x7C, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x7F, 0xC0, 0x00, 0x7F, 188 | 0xE0, 0x00, 0x3F, 0xF8, 0x00, 0x3F, 0xFE, 0x00, 0x3F, 0xFF, 0x80, 0x3F, 189 | 0xFF, 0xC0, 0x1F, 0xFF, 0xF0, 0x1F, 0xFF, 0xFC, 0x1F, 0xFF, 0xFE, 0x1F, 190 | 0xFF, 0xFF, 0x8F, 0xFF, 0xF7, 0xEF, 0xDF, 0xFB, 0xFF, 0xEF, 0xFC, 0xFF, 191 | 0xE7, 0xFE, 0x3F, 0xE3, 0xFF, 0x0F, 0xE1, 0xFF, 0x87, 0xF0, 0xFF, 0xC1, 192 | 0xF0, 0x7F, 0xE0, 0x70, 0x3F, 0xF0, 0x10, 0x1F, 0xF8, 0x00, 0x0F, 0xFC, 193 | 0x00, 0x07, 0xFE, 0x00, 0x03, 0xE0, 0x80, 0x00, 0x10, 0x00, 0x03, 0x00, 194 | 0x00, 0x70, 0x01, 0xFF, 0x00, 0x3F, 0xF0, 0x07, 0xFE, 0x00, 0xFF, 0xE0, 195 | 0x1F, 0xFE, 0x03, 0xFF, 0xE0, 0x7F, 0xFE, 0x0F, 0xFF, 0xE1, 0xFF, 0xFE, 196 | 0x3F, 0xFF, 0xE7, 0xFE, 0xFE, 0xFF, 0xCF, 0xDF, 0xF8, 0xFF, 0xFF, 0x0F, 197 | 0xFF, 0xE1, 0xFF, 0xFC, 0x1F, 0xFF, 0x81, 0xFF, 0xF0, 0x1F, 0xFE, 0x01, 198 | 0xFF, 0xC0, 0x1F, 0xF8, 0x01, 0xFF, 0x00, 0x3F, 0xE0, 0x03, 0x80, 0x00, 199 | 0x30, 0x00, 0x02, 0x00, 0x00, 0x40, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 200 | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0x00, 0x7F, 0xE0, 0x03, 201 | 0xFF, 0x00, 0x1F, 0xF8, 0x00, 0xFF, 0xC0, 0x07, 0xFE, 0x00, 0x3F, 0xF0, 202 | 0x01, 0xFF, 0x80, 0x0F, 0xFC, 0x00, 0x7F, 0xE0, 0x03, 0xFF, 0x00, 0x1F, 203 | 0xF8, 0x00, 0xFF, 0xC0, 0x07, 0xFE, 0x00, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 204 | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 205 | 0xFF, 0xFF, 0xEF, 0xFF, 0xFF, 0xBF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFB, 0xE0, 206 | 0x03, 0xEF, 0x80, 0x1F, 0xBE, 0x00, 0x7C, 0xF8, 0x01, 0xF3, 0xE0, 0x07, 207 | 0xCF, 0xFF, 0xFF, 0x3F, 0xFF, 0xFC, 0xFF, 0xFF, 0xF3, 0xFF, 0xFF, 0x8F, 208 | 0xFF, 0xFE, 0x3E, 0x00, 0x00, 0xF8, 0x00, 0x03, 0xE0, 0x00, 0x0F, 0x80, 209 | 0x00, 0x3E, 0x00, 0x00, 0xF8, 0x00, 0x03, 0xE0, 0x00, 0x0F, 0x80, 0x00, 210 | 0x3E, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 211 | 0xFF, 0xFF, 0xFF, 0xF0, 0x07, 0xFE, 0x00, 0xFF, 0xC0, 0x1F, 0xF8, 0x03, 212 | 0xFF, 0x00, 0x7F, 0xE0, 0x0F, 0xFC, 0x01, 0xFF, 0x80, 0x3F, 0xF0, 0x07, 213 | 0xFE, 0x00, 0xFF, 0xC0, 0x1F, 0xF8, 0x03, 0xFF, 0x00, 0x7F, 0xF0, 0x0F, 214 | 0xFF, 0xFF, 0xF7, 0xFF, 0xFE, 0x7F, 0xFF, 0xC7, 0xFF, 0xF8, 0x3F, 0xFF, 215 | 0x03, 0xFC, 0x00, 0x3F, 0xC0, 0x03, 0xFC, 0x00, 0x1F, 0xE0, 0x01, 0xF8, 216 | 0x00, 0x1E, 0x00, 0x01, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xEF, 0xFF, 217 | 0xFF, 0xBF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFB, 0xE0, 0x03, 0xEF, 0x80, 0x1F, 218 | 0xBE, 0x00, 0x7C, 0xF8, 0x01, 0xF3, 0xE0, 0x07, 0xCF, 0xBF, 0xFF, 0x3E, 219 | 0x7F, 0xFC, 0xF8, 0xFF, 0xF3, 0xE3, 0xFF, 0x8F, 0x87, 0xFE, 0x3E, 0x1F, 220 | 0x00, 0xF8, 0x3E, 0x03, 0xE0, 0xFC, 0x0F, 0x81, 0xF0, 0x3E, 0x03, 0xE0, 221 | 0xF8, 0x0F, 0x83, 0xE0, 0x1F, 0x0F, 0x80, 0x7E, 0x3E, 0x00, 0xF8, 0x00, 222 | 0x03, 0xE0, 0x00, 0x07, 0x00, 0x00, 0x08, 0x00, 0x00, 0x40, 0x03, 0xFF, 223 | 0xFE, 0x0F, 0xFF, 0xF8, 0x1F, 0xFF, 0xE0, 0x7F, 0xFF, 0x81, 0xFF, 0xFE, 224 | 0x03, 0xF0, 0x00, 0x0F, 0xC0, 0x00, 0x1F, 0x00, 0x00, 0x7E, 0x00, 0x00, 225 | 0xFF, 0xFF, 0xFD, 0xFF, 0xFF, 0xFB, 0xFF, 0xFF, 0xF7, 0xFF, 0xFF, 0xEF, 226 | 0xFF, 0xFF, 0xC0, 0x00, 0x0F, 0x80, 0x00, 0x3F, 0x00, 0x00, 0x7C, 0x00, 227 | 0x01, 0xF8, 0x00, 0x07, 0xE0, 0xFF, 0xFF, 0x81, 0xFF, 0xFF, 0x07, 0xFF, 228 | 0xFC, 0x1F, 0xFF, 0xF8, 0x7F, 0xFF, 0xE0, 0x03, 0xFF, 0xFF, 0xE1, 0xFF, 229 | 0xFF, 0xF0, 0x7F, 0xFF, 0xFC, 0x1F, 0xFF, 0xFF, 0x0F, 0xFF, 0xFF, 0x80, 230 | 0x00, 0x3E, 0x00, 0x00, 0x07, 0xC0, 0x00, 0x00, 0xF8, 0x00, 0x00, 0x1F, 231 | 0x00, 0x00, 0x03, 0xE0, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x0F, 0x80, 0x00, 232 | 0x01, 0xF0, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x07, 0xC0, 0x00, 0x00, 0xF8, 233 | 0x00, 0x00, 0x1F, 0x00, 0x00, 0x03, 0xE0, 0x00, 0x00, 0x7C, 0x00, 0x00, 234 | 0x0F, 0x80, 0x00, 0x01, 0xF0, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x07, 0xC0, 235 | 0x00, 0x00, 0xF8, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x01, 0xE0, 0x00, 0x00, 236 | 0x1C, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x30, 0x00, 0x00, 0x02, 0x00, 237 | 0x00, 0xF8, 0x00, 0xFF, 0xC0, 0x07, 0xFE, 0x00, 0x3F, 0xF0, 0x01, 0xFF, 238 | 0x80, 0x0F, 0xFC, 0x00, 0x7F, 0xE0, 0x03, 0xFF, 0x00, 0x1F, 0xF8, 0x00, 239 | 0xFF, 0xC0, 0x07, 0xFE, 0x00, 0x3F, 0xF0, 0x01, 0xFF, 0x80, 0x0F, 0xFC, 240 | 0x00, 0x7F, 0xE0, 0x03, 0xFF, 0x00, 0x1F, 0xF8, 0x00, 0xFF, 0xC0, 0x07, 241 | 0xFE, 0x00, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 242 | 0xFF, 0xFF, 0xFF, 0xFF, 0xF8, 0x00, 0x1F, 0x80, 0x01, 0xF8, 0x00, 0x3F, 243 | 0x80, 0x07, 0xF8, 0x00, 0xFF, 0x80, 0x1F, 0xF8, 0x03, 0xFF, 0x80, 0x7F, 244 | 0xF8, 0x07, 0xEF, 0x80, 0xFC, 0xF8, 0x1F, 0x8F, 0x83, 0xF0, 0xF8, 0x7F, 245 | 0x0F, 0x8F, 0xE0, 0xF9, 0xFC, 0x0F, 0xBF, 0x80, 0xFB, 0xF0, 0x0F, 0xFE, 246 | 0x00, 0xFF, 0xC0, 0x0F, 0xFC, 0x00, 0xFF, 0x80, 0x0F, 0xF0, 0x00, 0xFE, 247 | 0x00, 0x0F, 0xC0, 0x00, 0xF8, 0x00, 0x0F, 0x00, 0x00, 0xF0, 0x00, 0x0E, 248 | 0x00, 0x00, 0xC0, 0x00, 0x08, 0x00, 0x00, 0x80, 0x00, 0x00, 0xF8, 0x00, 249 | 0x0F, 0xFC, 0x00, 0x07, 0xFE, 0x02, 0x03, 0xFF, 0x01, 0x81, 0xFF, 0x81, 250 | 0xC0, 0xFF, 0xC1, 0xF0, 0x7F, 0xE1, 0xFC, 0x3F, 0xF1, 0xFF, 0x1F, 0xF8, 251 | 0xFF, 0x8F, 0xFC, 0xFF, 0xE7, 0xFE, 0xFF, 0xFB, 0xFF, 0xFE, 0xFF, 0xFF, 252 | 0xFE, 0x3F, 0xFF, 0xFE, 0x0F, 0xFF, 0xFF, 0x07, 0xFF, 0xFF, 0x01, 0xFF, 253 | 0xFF, 0x00, 0x7F, 0xFF, 0x00, 0x1F, 0xFF, 0x80, 0x0F, 0xFF, 0x80, 0x03, 254 | 0xFF, 0x80, 0x00, 0xFF, 0x80, 0x00, 0x3F, 0xC0, 0x00, 0x1F, 0xC0, 0x00, 255 | 0x07, 0xC0, 0x00, 0x01, 0xC0, 0x00, 0x00, 0x60, 0x00, 0x00, 0x20, 0xFC, 256 | 0x00, 0x7F, 0x7E, 0x00, 0x7E, 0x3F, 0x00, 0xFC, 0x3F, 0x81, 0xFC, 0x1F, 257 | 0x83, 0xF8, 0x0F, 0xC3, 0xF0, 0x07, 0xE7, 0xE0, 0x07, 0xFF, 0xE0, 0x03, 258 | 0xFF, 0xC0, 0x01, 0xFF, 0x80, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 259 | 0x7E, 0x00, 0x00, 0xFF, 0x00, 0x01, 0xFF, 0x80, 0x03, 0xFF, 0xC0, 0x03, 260 | 0xFF, 0xC0, 0x07, 0xE7, 0xE0, 0x0F, 0xC3, 0xF0, 0x1F, 0xC3, 0xF8, 0x1F, 261 | 0x81, 0xF8, 0x3F, 0x00, 0xFC, 0x7E, 0x00, 0x7E, 0xFE, 0x00, 0x7F, 0xFE, 262 | 0x00, 0x7F, 0x7E, 0x00, 0x7E, 0x3F, 0x00, 0xFC, 0x1F, 0x81, 0xF8, 0x1F, 263 | 0xC3, 0xF8, 0x0F, 0xC3, 0xF0, 0x07, 0xE7, 0xE0, 0x03, 0xFF, 0xC0, 0x03, 264 | 0xFF, 0xC0, 0x01, 0xFF, 0x80, 0x00, 0xFF, 0x00, 0x00, 0x7E, 0x00, 0x00, 265 | 0x7E, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x7E, 0x00, 0x00, 266 | 0x7E, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x7E, 0x00, 0x00, 267 | 0x7E, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x7E, 0x00, 0x00, 268 | 0x7C, 0x00, 0x00, 0x78, 0x00, 0x00, 0x70, 0x00, 0x00, 0x40, 0x00, 0xFF, 269 | 0xFF, 0xDF, 0xFF, 0xFB, 0xFF, 0xFF, 0x7F, 0xFF, 0xEF, 0xFF, 0xFC, 0x00, 270 | 0x7F, 0x00, 0x0F, 0xC0, 0x03, 0xF8, 0x00, 0xFE, 0x00, 0x3F, 0x80, 0x07, 271 | 0xE0, 0x01, 0xFC, 0x00, 0x7F, 0x00, 0x1F, 0xC0, 0x03, 0xF0, 0x00, 0xFC, 272 | 0x00, 0x3F, 0x80, 0x0F, 0xE0, 0x01, 0xF8, 0x00, 0x7F, 0xFF, 0xFF, 0xFF, 273 | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xCF, 274 | 0xFE, 0x3F, 0xF0, 0xFF, 0x83, 0xE0, 0x0F, 0x80, 0x3E, 0x00, 0xF8, 0x03, 275 | 0xE0, 0x0F, 0x80, 0x3E, 0x00, 0xF8, 0x03, 0xE0, 0x0F, 0x80, 0x3E, 0x00, 276 | 0xF8, 0x03, 0xE0, 0x0F, 0x80, 0x3E, 0x00, 0xF8, 0x03, 0xE0, 0x0F, 0x80, 277 | 0x3E, 0x00, 0xF8, 0x03, 0xFE, 0x0F, 0xFC, 0x3F, 0xF8, 0xFF, 0xF3, 0xFF, 278 | 0xF0, 0x60, 0x03, 0x80, 0x0F, 0x00, 0x1C, 0x00, 0x70, 0x01, 0xE0, 0x03, 279 | 0x80, 0x0F, 0x00, 0x1C, 0x00, 0x70, 0x00, 0xE0, 0x03, 0x80, 0x0F, 0x00, 280 | 0x1C, 0x00, 0x78, 0x00, 0xE0, 0x03, 0x80, 0x0F, 0x00, 0x1C, 0x00, 0x78, 281 | 0x00, 0xE0, 0x03, 0xC0, 0x07, 0x00, 0x1C, 0x00, 0x78, 0x00, 0xE0, 0x03, 282 | 0xC0, 0x07, 0x00, 0x18, 0xFF, 0xFC, 0xFF, 0xF1, 0xFF, 0xC3, 0xFF, 0x07, 283 | 0xFC, 0x01, 0xF0, 0x07, 0xC0, 0x1F, 0x00, 0x7C, 0x01, 0xF0, 0x07, 0xC0, 284 | 0x1F, 0x00, 0x7C, 0x01, 0xF0, 0x07, 0xC0, 0x1F, 0x00, 0x7C, 0x01, 0xF0, 285 | 0x07, 0xC0, 0x1F, 0x00, 0x7C, 0x01, 0xF0, 0x07, 0xC0, 0x1F, 0x00, 0x7C, 286 | 0x1F, 0xF0, 0xFF, 0xC7, 0xFF, 0x3F, 0xFF, 0xFF, 0xF0, 0x01, 0xF8, 0x00, 287 | 0x3F, 0x80, 0x03, 0xFC, 0x00, 0x7F, 0xE0, 0x0F, 0x9E, 0x00, 0xF1, 0xF0, 288 | 0x1F, 0x0F, 0x01, 0xE0, 0xF8, 0x3E, 0x07, 0xC7, 0xC0, 0x3C, 0x78, 0x03, 289 | 0xEF, 0x80, 0x1E, 0xF0, 0x01, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 290 | 0xE0, 0xF1, 0xE3, 0x8F, 0x1C, 0x30, 0xC1, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 291 | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0x00, 0x7F, 0xE0, 292 | 0x03, 0xFF, 0x03, 0x1F, 0xF8, 0x3C, 0xFF, 0xC1, 0xF7, 0xFE, 0x1F, 0xFF, 293 | 0xF1, 0xFD, 0xFF, 0x9F, 0xCF, 0xFD, 0xFC, 0x7F, 0xEF, 0xC3, 0xFF, 0xFC, 294 | 0x1F, 0xFF, 0xE0, 0xFF, 0xFE, 0x07, 0xFF, 0xE0, 0x3F, 0xFE, 0x01, 0xFF, 295 | 0xF0, 0x0F, 0xFF, 0x00, 0x7F, 0xF0, 0x03, 0xFF, 0x00, 0x1F, 0xF8, 0x00, 296 | 0x07, 0x80, 0x00, 0x38, 0x00, 0x01, 0x80, 0x00, 0x08, 0x00, 0x00, 0x40, 297 | 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xBF, 0xFF, 0xFD, 0xFF, 0xFF, 298 | 0xCF, 0xFF, 0xFC, 0x7C, 0x03, 0xE3, 0xE0, 0x3E, 0x1F, 0x03, 0xE0, 0xF8, 299 | 0x7F, 0xFF, 0xC3, 0xFF, 0xFE, 0x1F, 0xFF, 0xF0, 0xFF, 0xFF, 0x87, 0xFF, 300 | 0xFC, 0x01, 0xFF, 0xE0, 0x0F, 0xDF, 0x00, 0xFC, 0xF8, 0x0F, 0xC7, 0xC0, 301 | 0xFE, 0x3E, 0x07, 0xE1, 0xF0, 0x7E, 0x0F, 0x87, 0xE0, 0x7C, 0x7F, 0x03, 302 | 0xE3, 0xF0, 0x1F, 0x3F, 0x00, 0x03, 0xF0, 0x00, 0x3F, 0x80, 0x01, 0xF8, 303 | 0x00, 0x1F, 0x80, 0x00, 0xF8, 0x00, 0x03, 0xC0, 0x00, 0x04, 0x00, 0x00, 304 | 0x07, 0xFF, 0xF1, 0xFF, 0xFE, 0x3F, 0xFF, 0xC7, 0xFF, 0xF8, 0xFF, 0xFF, 305 | 0x0F, 0xC0, 0x00, 0xF8, 0x00, 0x0F, 0x80, 0x00, 0xF8, 0x00, 0x0F, 0x80, 306 | 0x00, 0xF8, 0x00, 0x0F, 0x80, 0x00, 0xF8, 0x00, 0x0F, 0x80, 0x00, 0xF8, 307 | 0x00, 0x0F, 0x80, 0x3E, 0xF8, 0x03, 0xEF, 0x80, 0x3E, 0xF8, 0x03, 0xEF, 308 | 0xFF, 0xFE, 0xFF, 0xFF, 0xEF, 0xFF, 0xFE, 0xFF, 0xFF, 0xEF, 0xFF, 0xFE, 309 | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 310 | 0xF0, 0x07, 0xFE, 0x00, 0xFF, 0xC0, 0x1F, 0xF8, 0x03, 0xFF, 0x00, 0x7F, 311 | 0xE0, 0x0F, 0xFC, 0x01, 0xFF, 0x80, 0x3F, 0xF0, 0x07, 0xFE, 0x00, 0xFF, 312 | 0xC0, 0x1F, 0xF8, 0x03, 0xFF, 0x00, 0x7F, 0xE0, 0x1F, 0xFF, 0xFF, 0xFF, 313 | 0xFF, 0xFD, 0xFF, 0xFF, 0x3F, 0xFF, 0xC7, 0xFF, 0xE0, 0xFF, 0xFF, 0xFF, 314 | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 315 | 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFC, 0xFF, 0xF0, 0xFF, 0xE0, 0xFF, 316 | 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 317 | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 318 | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0x00, 0x0F, 0x80, 319 | 0x03, 0xE0, 0x00, 0xF8, 0x00, 0x3F, 0xFF, 0xFF, 0xFF, 0xF3, 0xFF, 0xF8, 320 | 0xFF, 0xF8, 0x3F, 0xFC, 0x0F, 0x80, 0x03, 0xE0, 0x00, 0xF8, 0x00, 0x3E, 321 | 0x00, 0x0F, 0x80, 0x03, 0xE0, 0x00, 0xF8, 0x00, 0x3E, 0x00, 0x0F, 0x80, 322 | 0x03, 0xE0, 0x00, 0x07, 0xFF, 0xF1, 0xFF, 0xFE, 0x3F, 0xFF, 0xC7, 0xFF, 323 | 0xF8, 0xFF, 0xFF, 0x0F, 0xC0, 0x00, 0xF8, 0x00, 0x0F, 0x80, 0x00, 0xF8, 324 | 0x1F, 0xFF, 0x83, 0xFF, 0xF8, 0x7F, 0xFF, 0x8F, 0xFF, 0xF9, 0xFF, 0xFF, 325 | 0xA0, 0x1F, 0xF8, 0x01, 0xFF, 0x80, 0x1F, 0xF8, 0x01, 0xFF, 0x80, 0x1F, 326 | 0xF8, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 327 | 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x08, 0x00, 0x00, 0x40, 0x00, 0x06, 0x00, 328 | 0x00, 0x70, 0x00, 0x07, 0x80, 0x00, 0x7F, 0xE0, 0x03, 0xFF, 0x00, 0x1F, 329 | 0xF8, 0x00, 0xFF, 0xC0, 0x07, 0xFE, 0x00, 0x3F, 0xF0, 0x01, 0xFF, 0x80, 330 | 0x0F, 0xFC, 0x00, 0x7F, 0xE0, 0x03, 0xFF, 0x00, 0x1F, 0xFF, 0xFF, 0xFF, 331 | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0x00, 332 | 0x7F, 0xE0, 0x03, 0xFF, 0x00, 0x1F, 0xF8, 0x00, 0xFF, 0xC0, 0x07, 0xFE, 333 | 0x00, 0x3F, 0xF0, 0x01, 0xFF, 0x80, 0x0F, 0xFC, 0x00, 0x7F, 0xE0, 0x00, 334 | 0x0F, 0x00, 0x00, 0x38, 0x00, 0x00, 0xC0, 0x00, 0x02, 0x00, 0x00, 0x10, 335 | 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 336 | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFB, 0xDE, 0x71, 0x84, 0x20, 0x7F, 0xFE, 337 | 0x7F, 0xFC, 0x7F, 0xF8, 0x7F, 0xF0, 0x7F, 0xE0, 0x07, 0xC0, 0x0F, 0x80, 338 | 0x1F, 0x00, 0x3E, 0x00, 0x7C, 0x00, 0xF8, 0x01, 0xF0, 0x03, 0xF0, 0x07, 339 | 0xE0, 0x0F, 0xE0, 0x1F, 0xE0, 0x3F, 0xE0, 0x7F, 0xE0, 0xFF, 0xC1, 0xFF, 340 | 0x83, 0xFF, 0x07, 0xFE, 0x0F, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFB, 0xFF, 341 | 0xC7, 0xFC, 0x0F, 0xE0, 0x1E, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x80, 342 | 0x00, 0x07, 0x00, 0x00, 0x3E, 0x00, 0x00, 0xFC, 0xF8, 0x07, 0xE3, 0xE0, 343 | 0x3F, 0x8F, 0x81, 0xFC, 0x3E, 0x0F, 0xE0, 0xF8, 0x7F, 0x03, 0xE3, 0xF8, 344 | 0x0F, 0x9F, 0xC0, 0x3E, 0xFE, 0x00, 0xFF, 0xF0, 0x03, 0xFF, 0x80, 0x0F, 345 | 0xFC, 0x00, 0x3F, 0xF8, 0x00, 0xFF, 0xE0, 0x03, 0xFF, 0xC0, 0x0F, 0xFF, 346 | 0x80, 0x3F, 0x7F, 0x00, 0xF8, 0xFC, 0x03, 0xE1, 0xF8, 0x0F, 0x87, 0xF0, 347 | 0x3E, 0x0F, 0xC0, 0xF8, 0x1F, 0x83, 0xE0, 0x7F, 0x0F, 0x80, 0xFC, 0x3E, 348 | 0x01, 0xF8, 0xF8, 0x03, 0xF1, 0xE0, 0x0F, 0xC3, 0x80, 0x1F, 0x86, 0x00, 349 | 0x3F, 0x18, 0x00, 0xFC, 0x20, 0x01, 0xE0, 0x80, 0x02, 0x00, 0x80, 0x00, 350 | 0x38, 0x00, 0x0F, 0x80, 0x03, 0xE0, 0x00, 0xF8, 0x00, 0x3E, 0x00, 0x0F, 351 | 0x80, 0x03, 0xE0, 0x00, 0xF8, 0x00, 0x3E, 0x00, 0x0F, 0x80, 0x03, 0xE0, 352 | 0x00, 0xF8, 0x00, 0x3E, 0x00, 0x0F, 0x80, 0x03, 0xE0, 0x00, 0xF8, 0x00, 353 | 0x3E, 0x00, 0x0F, 0x80, 0x03, 0xE0, 0x00, 0xF8, 0x00, 0x3E, 0x00, 0x0F, 354 | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0x80, 355 | 0x00, 0x00, 0xC0, 0x00, 0x00, 0x70, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x7F, 356 | 0x00, 0x00, 0x7F, 0xC0, 0x00, 0x7F, 0xE0, 0x00, 0x3F, 0xF8, 0x00, 0x3F, 357 | 0xFE, 0x00, 0x3F, 0xFF, 0x80, 0x3F, 0xFF, 0xC0, 0x1F, 0xFF, 0xF0, 0x1F, 358 | 0xFF, 0xFC, 0x1F, 0xFF, 0xFE, 0x1F, 0xFF, 0xFF, 0x8F, 0xFF, 0xF7, 0xEF, 359 | 0xDF, 0xFB, 0xFF, 0xEF, 0xFC, 0xFF, 0xE7, 0xFE, 0x3F, 0xE3, 0xFF, 0x0F, 360 | 0xE1, 0xFF, 0x87, 0xF0, 0xFF, 0xC1, 0xF0, 0x7F, 0xE0, 0x70, 0x3F, 0xF0, 361 | 0x10, 0x1F, 0xF8, 0x00, 0x0F, 0xFC, 0x00, 0x07, 0xFE, 0x00, 0x03, 0xE0, 362 | 0x80, 0x00, 0x10, 0x00, 0x03, 0x00, 0x00, 0x70, 0x01, 0xFF, 0x00, 0x3F, 363 | 0xF0, 0x07, 0xFE, 0x00, 0xFF, 0xE0, 0x1F, 0xFE, 0x03, 0xFF, 0xE0, 0x7F, 364 | 0xFE, 0x0F, 0xFF, 0xE1, 0xFF, 0xFE, 0x3F, 0xFF, 0xE7, 0xFE, 0xFE, 0xFF, 365 | 0xCF, 0xDF, 0xF8, 0xFF, 0xFF, 0x0F, 0xFF, 0xE1, 0xFF, 0xFC, 0x1F, 0xFF, 366 | 0x81, 0xFF, 0xF0, 0x1F, 0xFE, 0x01, 0xFF, 0xC0, 0x1F, 0xF8, 0x01, 0xFF, 367 | 0x00, 0x3F, 0xE0, 0x03, 0x80, 0x00, 0x30, 0x00, 0x02, 0x00, 0x00, 0x40, 368 | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 369 | 0xFF, 0xFC, 0x00, 0x7F, 0xE0, 0x03, 0xFF, 0x00, 0x1F, 0xF8, 0x00, 0xFF, 370 | 0xC0, 0x07, 0xFE, 0x00, 0x3F, 0xF0, 0x01, 0xFF, 0x80, 0x0F, 0xFC, 0x00, 371 | 0x7F, 0xE0, 0x03, 0xFF, 0x00, 0x1F, 0xF8, 0x00, 0xFF, 0xC0, 0x07, 0xFE, 372 | 0x00, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 373 | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xEF, 0xFF, 0xFF, 0xBF, 374 | 0xFF, 0xFE, 0xFF, 0xFF, 0xFB, 0xE0, 0x03, 0xEF, 0x80, 0x1F, 0xBE, 0x00, 375 | 0x7C, 0xF8, 0x01, 0xF3, 0xE0, 0x07, 0xCF, 0xFF, 0xFF, 0x3F, 0xFF, 0xFC, 376 | 0xFF, 0xFF, 0xF3, 0xFF, 0xFF, 0x8F, 0xFF, 0xFE, 0x3E, 0x00, 0x00, 0xF8, 377 | 0x00, 0x03, 0xE0, 0x00, 0x0F, 0x80, 0x00, 0x3E, 0x00, 0x00, 0xF8, 0x00, 378 | 0x03, 0xE0, 0x00, 0x0F, 0x80, 0x00, 0x3E, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 379 | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x07, 0xFE, 380 | 0x00, 0xFF, 0xC0, 0x1F, 0xF8, 0x03, 0xFF, 0x00, 0x7F, 0xE0, 0x0F, 0xFC, 381 | 0x01, 0xFF, 0x80, 0x3F, 0xF0, 0x07, 0xFE, 0x00, 0xFF, 0xC0, 0x1F, 0xF8, 382 | 0x03, 0xFF, 0x00, 0x7F, 0xF0, 0x0F, 0xFF, 0xFF, 0xF7, 0xFF, 0xFE, 0x7F, 383 | 0xFF, 0xC7, 0xFF, 0xF8, 0x3F, 0xFF, 0x03, 0xFC, 0x00, 0x3F, 0xC0, 0x03, 384 | 0xFC, 0x00, 0x1F, 0xE0, 0x01, 0xF8, 0x00, 0x1E, 0x00, 0x01, 0x80, 0xFF, 385 | 0xFF, 0xFF, 0xFF, 0xFF, 0xEF, 0xFF, 0xFF, 0xBF, 0xFF, 0xFE, 0xFF, 0xFF, 386 | 0xFB, 0xE0, 0x03, 0xEF, 0x80, 0x1F, 0xBE, 0x00, 0x7C, 0xF8, 0x01, 0xF3, 387 | 0xE0, 0x07, 0xCF, 0xBF, 0xFF, 0x3E, 0x7F, 0xFC, 0xF8, 0xFF, 0xF3, 0xE3, 388 | 0xFF, 0x8F, 0x87, 0xFE, 0x3E, 0x1F, 0x00, 0xF8, 0x3E, 0x03, 0xE0, 0xFC, 389 | 0x0F, 0x81, 0xF0, 0x3E, 0x03, 0xE0, 0xF8, 0x0F, 0x83, 0xE0, 0x1F, 0x0F, 390 | 0x80, 0x7E, 0x3E, 0x00, 0xF8, 0x00, 0x03, 0xE0, 0x00, 0x07, 0x00, 0x00, 391 | 0x08, 0x00, 0x00, 0x40, 0x03, 0xFF, 0xFE, 0x0F, 0xFF, 0xF8, 0x1F, 0xFF, 392 | 0xE0, 0x7F, 0xFF, 0x81, 0xFF, 0xFE, 0x03, 0xF0, 0x00, 0x0F, 0xC0, 0x00, 393 | 0x1F, 0x00, 0x00, 0x7E, 0x00, 0x00, 0xFF, 0xFF, 0xFD, 0xFF, 0xFF, 0xFB, 394 | 0xFF, 0xFF, 0xF7, 0xFF, 0xFF, 0xEF, 0xFF, 0xFF, 0xC0, 0x00, 0x0F, 0x80, 395 | 0x00, 0x3F, 0x00, 0x00, 0x7C, 0x00, 0x01, 0xF8, 0x00, 0x07, 0xE0, 0xFF, 396 | 0xFF, 0x81, 0xFF, 0xFF, 0x07, 0xFF, 0xFC, 0x1F, 0xFF, 0xF8, 0x7F, 0xFF, 397 | 0xE0, 0x03, 0xFF, 0xFF, 0xE1, 0xFF, 0xFF, 0xF0, 0x7F, 0xFF, 0xFC, 0x1F, 398 | 0xFF, 0xFF, 0x0F, 0xFF, 0xFF, 0x80, 0x00, 0x3E, 0x00, 0x00, 0x07, 0xC0, 399 | 0x00, 0x00, 0xF8, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x03, 0xE0, 0x00, 0x00, 400 | 0x7C, 0x00, 0x00, 0x0F, 0x80, 0x00, 0x01, 0xF0, 0x00, 0x00, 0x3E, 0x00, 401 | 0x00, 0x07, 0xC0, 0x00, 0x00, 0xF8, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x03, 402 | 0xE0, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x0F, 0x80, 0x00, 0x01, 0xF0, 0x00, 403 | 0x00, 0x3E, 0x00, 0x00, 0x07, 0xC0, 0x00, 0x00, 0xF8, 0x00, 0x00, 0x1F, 404 | 0x00, 0x00, 0x01, 0xE0, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x01, 0x80, 0x00, 405 | 0x00, 0x30, 0x00, 0x00, 0x02, 0x00, 0x00, 0xF8, 0x00, 0xFF, 0xC0, 0x07, 406 | 0xFE, 0x00, 0x3F, 0xF0, 0x01, 0xFF, 0x80, 0x0F, 0xFC, 0x00, 0x7F, 0xE0, 407 | 0x03, 0xFF, 0x00, 0x1F, 0xF8, 0x00, 0xFF, 0xC0, 0x07, 0xFE, 0x00, 0x3F, 408 | 0xF0, 0x01, 0xFF, 0x80, 0x0F, 0xFC, 0x00, 0x7F, 0xE0, 0x03, 0xFF, 0x00, 409 | 0x1F, 0xF8, 0x00, 0xFF, 0xC0, 0x07, 0xFE, 0x00, 0x3F, 0xFF, 0xFF, 0xFF, 410 | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF8, 0x00, 411 | 0x1F, 0x80, 0x01, 0xF8, 0x00, 0x3F, 0x80, 0x07, 0xF8, 0x00, 0xFF, 0x80, 412 | 0x1F, 0xF8, 0x03, 0xFF, 0x80, 0x7F, 0xF8, 0x07, 0xEF, 0x80, 0xFC, 0xF8, 413 | 0x1F, 0x8F, 0x83, 0xF0, 0xF8, 0x7F, 0x0F, 0x8F, 0xE0, 0xF9, 0xFC, 0x0F, 414 | 0xBF, 0x80, 0xFB, 0xF0, 0x0F, 0xFE, 0x00, 0xFF, 0xC0, 0x0F, 0xFC, 0x00, 415 | 0xFF, 0x80, 0x0F, 0xF0, 0x00, 0xFE, 0x00, 0x0F, 0xC0, 0x00, 0xF8, 0x00, 416 | 0x0F, 0x00, 0x00, 0xF0, 0x00, 0x0E, 0x00, 0x00, 0xC0, 0x00, 0x08, 0x00, 417 | 0x00, 0x80, 0x00, 0x00, 0xF8, 0x00, 0x0F, 0xFC, 0x00, 0x07, 0xFE, 0x02, 418 | 0x03, 0xFF, 0x01, 0x81, 0xFF, 0x81, 0xC0, 0xFF, 0xC1, 0xF0, 0x7F, 0xE1, 419 | 0xFC, 0x3F, 0xF1, 0xFF, 0x1F, 0xF8, 0xFF, 0x8F, 0xFC, 0xFF, 0xE7, 0xFE, 420 | 0xFF, 0xFB, 0xFF, 0xFE, 0xFF, 0xFF, 0xFE, 0x3F, 0xFF, 0xFE, 0x0F, 0xFF, 421 | 0xFF, 0x07, 0xFF, 0xFF, 0x01, 0xFF, 0xFF, 0x00, 0x7F, 0xFF, 0x00, 0x1F, 422 | 0xFF, 0x80, 0x0F, 0xFF, 0x80, 0x03, 0xFF, 0x80, 0x00, 0xFF, 0x80, 0x00, 423 | 0x3F, 0xC0, 0x00, 0x1F, 0xC0, 0x00, 0x07, 0xC0, 0x00, 0x01, 0xC0, 0x00, 424 | 0x00, 0x60, 0x00, 0x00, 0x20, 0xFC, 0x00, 0x7F, 0x7E, 0x00, 0x7E, 0x3F, 425 | 0x00, 0xFC, 0x3F, 0x81, 0xFC, 0x1F, 0x83, 0xF8, 0x0F, 0xC3, 0xF0, 0x07, 426 | 0xE7, 0xE0, 0x07, 0xFF, 0xE0, 0x03, 0xFF, 0xC0, 0x01, 0xFF, 0x80, 0x00, 427 | 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x7E, 0x00, 0x00, 0xFF, 0x00, 0x01, 428 | 0xFF, 0x80, 0x03, 0xFF, 0xC0, 0x03, 0xFF, 0xC0, 0x07, 0xE7, 0xE0, 0x0F, 429 | 0xC3, 0xF0, 0x1F, 0xC3, 0xF8, 0x1F, 0x81, 0xF8, 0x3F, 0x00, 0xFC, 0x7E, 430 | 0x00, 0x7E, 0xFE, 0x00, 0x7F, 0xFE, 0x00, 0x7F, 0x7E, 0x00, 0x7E, 0x3F, 431 | 0x00, 0xFC, 0x1F, 0x81, 0xF8, 0x1F, 0xC3, 0xF8, 0x0F, 0xC3, 0xF0, 0x07, 432 | 0xE7, 0xE0, 0x03, 0xFF, 0xC0, 0x03, 0xFF, 0xC0, 0x01, 0xFF, 0x80, 0x00, 433 | 0xFF, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x7E, 0x00, 0x00, 434 | 0x7E, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x7E, 0x00, 0x00, 435 | 0x7E, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x7E, 0x00, 0x00, 436 | 0x7E, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x78, 0x00, 0x00, 437 | 0x70, 0x00, 0x00, 0x40, 0x00, 0xFF, 0xFF, 0xDF, 0xFF, 0xFB, 0xFF, 0xFF, 438 | 0x7F, 0xFF, 0xEF, 0xFF, 0xFC, 0x00, 0x7F, 0x00, 0x0F, 0xC0, 0x03, 0xF8, 439 | 0x00, 0xFE, 0x00, 0x3F, 0x80, 0x07, 0xE0, 0x01, 0xFC, 0x00, 0x7F, 0x00, 440 | 0x1F, 0xC0, 0x03, 0xF0, 0x00, 0xFC, 0x00, 0x3F, 0x80, 0x0F, 0xE0, 0x01, 441 | 0xF8, 0x00, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 442 | 0xFF, 0xFF, 0x00, 0xFF, 0xE0, 0x7F, 0xF8, 0x1F, 0xFE, 0x07, 0xFF, 0x01, 443 | 0xFF, 0xC0, 0x3F, 0x00, 0x07, 0xC0, 0x00, 0xF8, 0x00, 0x1F, 0x00, 0x03, 444 | 0xE0, 0x00, 0x7C, 0x00, 0x0F, 0x80, 0x0F, 0xF0, 0x01, 0xFE, 0x00, 0x3F, 445 | 0xC0, 0x07, 0xF8, 0x00, 0xFF, 0x00, 0x03, 0xE0, 0x00, 0x7C, 0x00, 0x0F, 446 | 0x80, 0x01, 0xF0, 0x00, 0x3E, 0x00, 0x07, 0xC0, 0x00, 0xF8, 0x00, 0x1F, 447 | 0x80, 0x03, 0xFF, 0x80, 0x3F, 0xF8, 0x03, 0xFF, 0xC0, 0x1F, 0xFC, 0x01, 448 | 0xFF, 0xC0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0xFF, 449 | 0xE0, 0x0F, 0xFF, 0x00, 0xFF, 0xF0, 0x07, 0xFF, 0x00, 0x7F, 0xF0, 0x00, 450 | 0x7E, 0x00, 0x07, 0xC0, 0x00, 0xF8, 0x00, 0x1F, 0x00, 0x03, 0xE0, 0x00, 451 | 0x7C, 0x00, 0x0F, 0x80, 0x01, 0xFE, 0x00, 0x3F, 0xC0, 0x07, 0xF8, 0x00, 452 | 0xFF, 0x00, 0x1F, 0xE0, 0x03, 0xE0, 0x00, 0x7C, 0x00, 0x0F, 0x80, 0x01, 453 | 0xF0, 0x00, 0x3E, 0x00, 0x07, 0xC0, 0x00, 0xF8, 0x00, 0x3F, 0x00, 0xFF, 454 | 0xE0, 0x3F, 0xF8, 0x1F, 0xFE, 0x07, 0xFF, 0x01, 0xFF, 0xC0, 0x00, 0x3F, 455 | 0x00, 0x0F, 0xF8, 0x03, 0xFF, 0xC3, 0x30, 0xFF, 0xF4, 0x07, 0xFC, 0x00, 456 | 0x1F, 0x00 }; 457 | 458 | const GFXglyph Fun_Games20pt7bGlyphs[] PROGMEM = { 459 | { 0, 1, 1, 10, 0, 0 }, // 0x20 ' ' 460 | { 1, 5, 26, 9, 2, -25 }, // 0x21 '!' 461 | { 18, 7, 7, 11, 2, -23 }, // 0x22 '"' 462 | { 25, 22, 28, 25, 2, -25 }, // 0x23 '#' 463 | { 102, 24, 32, 27, 1, -27 }, // 0x24 '$' 464 | { 198, 15, 24, 18, 2, -23 }, // 0x25 '%' 465 | { 243, 22, 24, 25, 2, -23 }, // 0x26 '&' 466 | { 309, 3, 7, 6, 2, -23 }, // 0x27 ''' 467 | { 312, 16, 30, 19, 2, -23 }, // 0x28 '(' 468 | { 372, 16, 30, 20, 2, -23 }, // 0x29 ')' 469 | { 432, 10, 10, 13, 2, -24 }, // 0x2A '*' 470 | { 445, 21, 21, 23, 1, -23 }, // 0x2B '+' 471 | { 501, 5, 11, 9, 2, -4 }, // 0x2C ',' 472 | { 508, 13, 5, 17, 2, -12 }, // 0x2D '-' 473 | { 517, 5, 5, 9, 2, -4 }, // 0x2E '.' 474 | { 521, 14, 29, 18, 2, -27 }, // 0x2F '/' 475 | { 572, 21, 24, 25, 2, -23 }, // 0x30 '0' 476 | { 635, 10, 30, 14, 2, -23 }, // 0x31 '1' 477 | { 673, 23, 24, 27, 2, -23 }, // 0x32 '2' 478 | { 742, 19, 24, 23, 2, -23 }, // 0x33 '3' 479 | { 799, 19, 31, 23, 2, -23 }, // 0x34 '4' 480 | { 873, 23, 24, 27, 2, -23 }, // 0x35 '5' 481 | { 942, 21, 24, 25, 2, -23 }, // 0x36 '6' 482 | { 1005, 19, 30, 20, 0, -23 }, // 0x37 '7' 483 | { 1077, 21, 24, 25, 2, -23 }, // 0x38 '8' 484 | { 1140, 21, 24, 25, 2, -23 }, // 0x39 '9' 485 | { 1203, 5, 21, 9, 2, -20 }, // 0x3A ':' 486 | { 1217, 5, 27, 9, 2, -20 }, // 0x3B ';' 487 | { 1234, 13, 21, 16, 2, -23 }, // 0x3C '<' 488 | { 1269, 19, 11, 23, 2, -18 }, // 0x3D '=' 489 | { 1296, 13, 21, 16, 1, -23 }, // 0x3E '>' 490 | { 1331, 19, 24, 23, 2, -23 }, // 0x3F '?' 491 | { 1388, 20, 21, 24, 2, -23 }, // 0x40 '@' 492 | { 1441, 21, 30, 25, 2, -23 }, // 0x41 'A' 493 | { 1520, 21, 31, 25, 2, -23 }, // 0x42 'B' 494 | { 1602, 20, 24, 24, 2, -23 }, // 0x43 'C' 495 | { 1662, 19, 24, 23, 2, -23 }, // 0x44 'D' 496 | { 1719, 16, 24, 20, 2, -23 }, // 0x45 'E' 497 | { 1767, 18, 24, 22, 2, -23 }, // 0x46 'F' 498 | { 1821, 20, 24, 24, 2, -23 }, // 0x47 'G' 499 | { 1881, 21, 36, 25, 2, -29 }, // 0x48 'H' 500 | { 1976, 5, 31, 9, 2, -24 }, // 0x49 'I' 501 | { 1996, 15, 31, 18, 2, -23 }, // 0x4A 'J' 502 | { 2055, 22, 35, 23, 2, -27 }, // 0x4B 'K' 503 | { 2152, 18, 27, 22, 2, -26 }, // 0x4C 'L' 504 | { 2213, 25, 27, 29, 2, -26 }, // 0x4D 'M' 505 | { 2298, 19, 30, 23, 2, -26 }, // 0x4E 'N' 506 | { 2370, 21, 24, 25, 2, -23 }, // 0x4F 'O' 507 | { 2433, 22, 24, 25, 2, -23 }, // 0x50 'P' 508 | { 2499, 19, 31, 23, 2, -23 }, // 0x51 'Q' 509 | { 2573, 22, 28, 24, 2, -23 }, // 0x52 'R' 510 | { 2650, 23, 24, 27, 2, -23 }, // 0x53 'S' 511 | { 2719, 27, 30, 27, 0, -23 }, // 0x54 'T' 512 | { 2821, 21, 24, 25, 2, -23 }, // 0x55 'U' 513 | { 2884, 20, 31, 23, 2, -23 }, // 0x56 'V' 514 | { 2962, 25, 27, 29, 2, -23 }, // 0x57 'W' 515 | { 3047, 24, 24, 28, 2, -23 }, // 0x58 'X' 516 | { 3119, 24, 28, 28, 2, -23 }, // 0x59 'Y' 517 | { 3203, 19, 24, 22, 2, -23 }, // 0x5A 'Z' 518 | { 3260, 14, 30, 17, 2, -23 }, // 0x5B '[' 519 | { 3313, 14, 29, 18, 2, -27 }, // 0x5C '\' 520 | { 3364, 14, 30, 17, 1, -23 }, // 0x5D ']' 521 | { 3417, 20, 13, 24, 2, -23 }, // 0x5E '^' 522 | { 3450, 17, 3, 20, 2, 4 }, // 0x5F '_' 523 | { 3457, 6, 8, 9, 2, -29 }, // 0x60 '`' 524 | { 3463, 21, 30, 25, 2, -23 }, // 0x61 'a' 525 | { 3542, 21, 31, 25, 2, -23 }, // 0x62 'b' 526 | { 3624, 20, 24, 24, 2, -23 }, // 0x63 'c' 527 | { 3684, 19, 24, 23, 2, -23 }, // 0x64 'd' 528 | { 3741, 16, 24, 20, 2, -23 }, // 0x65 'e' 529 | { 3789, 18, 24, 22, 2, -23 }, // 0x66 'f' 530 | { 3843, 20, 24, 24, 2, -23 }, // 0x67 'g' 531 | { 3903, 21, 36, 25, 2, -29 }, // 0x68 'h' 532 | { 3998, 5, 31, 9, 2, -24 }, // 0x69 'i' 533 | { 4018, 15, 31, 18, 2, -23 }, // 0x6A 'j' 534 | { 4077, 22, 35, 23, 2, -27 }, // 0x6B 'k' 535 | { 4174, 18, 27, 22, 2, -26 }, // 0x6C 'l' 536 | { 4235, 25, 27, 29, 2, -26 }, // 0x6D 'm' 537 | { 4320, 19, 30, 23, 2, -26 }, // 0x6E 'n' 538 | { 4392, 21, 24, 25, 2, -23 }, // 0x6F 'o' 539 | { 4455, 22, 24, 25, 2, -23 }, // 0x70 'p' 540 | { 4521, 19, 31, 23, 2, -23 }, // 0x71 'q' 541 | { 4595, 22, 28, 24, 2, -23 }, // 0x72 'r' 542 | { 4672, 23, 24, 27, 2, -23 }, // 0x73 's' 543 | { 4741, 27, 30, 27, 0, -23 }, // 0x74 't' 544 | { 4843, 21, 24, 25, 2, -23 }, // 0x75 'u' 545 | { 4906, 20, 31, 23, 2, -23 }, // 0x76 'v' 546 | { 4984, 25, 27, 29, 2, -23 }, // 0x77 'w' 547 | { 5069, 24, 24, 28, 2, -23 }, // 0x78 'x' 548 | { 5141, 24, 28, 28, 2, -23 }, // 0x79 'y' 549 | { 5225, 19, 24, 22, 2, -23 }, // 0x7A 'z' 550 | { 5282, 19, 30, 23, 2, -23 }, // 0x7B '{' 551 | { 5354, 2, 34, 6, 2, -26 }, // 0x7C '|' 552 | { 5363, 19, 30, 23, 2, -23 }, // 0x7D '}' 553 | { 5435, 19, 6, 23, 2, -19 } }; // 0x7E '~' 554 | 555 | const GFXfont Fun_Games20pt7b PROGMEM = { 556 | (uint8_t *)Fun_Games20pt7bBitmaps, 557 | (GFXglyph *)Fun_Games20pt7bGlyphs, 558 | 0x20, 0x7E, 40 }; 559 | 560 | // Approx. 6122 bytes 561 | -------------------------------------------------------------------------------- /examples/4x1Screens/pong/pong.ino: -------------------------------------------------------------------------------- 1 | // Screen Layout : 4 screens on a single row 2 | // See the tutorial : https://youtu.be/eCfeJh9Pyns 3 | // 4 | 5 | #include "virtualScreen.h" 6 | #include "Fun_Games20pt7b.h" 7 | #include "Fun_Games40pt7b.h" 8 | 9 | VirtualDisplay *tft; 10 | ScreenBuilder screens; 11 | 12 | void setup() 13 | { 14 | Serial.begin(115200); 15 | 16 | // Adjust this setup according to your actual screen layout 17 | screens.addRow({{16, 0}, {15, 0}, {6, 0}, {7, 0}}); 18 | 19 | tft = new VirtualDisplay(screens.width(), screens.height(), &screens); 20 | tft->begin(); 21 | 22 | 23 | playPong(); 24 | } 25 | 26 | void loop() 27 | { 28 | } 29 | 30 | const int messageAreaWidth = 240; // Width of the message area on the left 31 | const int scoreAreaHeight = 50; // Height of the score area at the top 32 | 33 | void playPong() 34 | { 35 | const int paddleWidth = 20; 36 | const int paddleHeight = 50; 37 | const int ballSize = 8; 38 | int ballX, ballY; // Ball position 39 | int ballVelocityX = 12, ballVelocityY = 12; // Ball velocity 40 | int leftPaddleY, rightPaddleY; // Paddle positions 41 | 42 | // Initialize ball and paddles positions 43 | ballX = messageAreaWidth + (tft->width() - messageAreaWidth) / 2; 44 | ballY = scoreAreaHeight + (tft->height() - scoreAreaHeight) / 2; 45 | leftPaddleY = rightPaddleY = scoreAreaHeight + (tft->height() - scoreAreaHeight - paddleHeight) / 2; 46 | 47 | tft->fillScreen(TFT_BLACK); // Clear the screen 48 | drawScores(10, 10); 49 | drawMessage("Pong"); 50 | tft->output(); 51 | while (true) 52 | { 53 | // Clear the previous positions of the ball and paddles 54 | tft->fillRect(messageAreaWidth, leftPaddleY, paddleWidth, paddleHeight, TFT_BLACK); // Clear Left paddle 55 | tft->fillRect(tft->width() - paddleWidth, rightPaddleY, paddleWidth, paddleHeight, TFT_BLACK); // Clear Right paddle 56 | tft->fillCircle(ballX, ballY, ballSize, TFT_BLACK); 57 | 58 | // Update ball position 59 | ballX += ballVelocityX; 60 | ballY += ballVelocityY; 61 | 62 | // Check for ball collisions with the top and bottom of the screen 63 | if (ballY <= scoreAreaHeight + (ballSize * 2 + 5) || ballY >= tft->height() - ballSize) 64 | { 65 | ballVelocityY = -ballVelocityY; 66 | } 67 | 68 | // Update paddles position to follow the ball 69 | leftPaddleY = ballY - paddleHeight / 2; 70 | rightPaddleY = ballY - paddleHeight / 2; 71 | 72 | // Keep paddles within the screen bounds 73 | leftPaddleY = max(scoreAreaHeight, min(tft->height() - paddleHeight, leftPaddleY)); 74 | rightPaddleY = max(scoreAreaHeight, min(tft->height() - paddleHeight, rightPaddleY)); 75 | 76 | // Check for ball collisions with the paddles 77 | if ((ballX <= messageAreaWidth + paddleWidth + ballSize * 2 && ballY >= leftPaddleY && ballY <= leftPaddleY + paddleHeight) || 78 | (ballX >= tft->width() - paddleWidth - ballSize && ballY >= rightPaddleY && ballY <= rightPaddleY + paddleHeight)) 79 | { 80 | ballVelocityX = -ballVelocityX; 81 | ballVelocityY += esp_random() % 5; 82 | } 83 | 84 | // Draw the updated game state 85 | tft->fillRect(messageAreaWidth, leftPaddleY, paddleWidth, paddleHeight, 0xf818); // Left paddle 86 | tft->fillRect(tft->width() - paddleWidth, rightPaddleY, paddleWidth, paddleHeight, 0x07e6); // Right paddle 87 | tft->fillCircle(ballX, ballY, ballSize, 0xe7e0); // Ball 88 | 89 | // Update the display 90 | tft->output(); 91 | } 92 | } 93 | 94 | void drawScores(int leftScore, int rightScore) 95 | { 96 | // Clear the score area 97 | tft->fillRoundRect(messageAreaWidth, 0, tft->width() - messageAreaWidth, scoreAreaHeight, 20, 0x17bb); 98 | 99 | // Set text properties and display scores 100 | tft->setTextColor(TFT_BLACK); 101 | tft->setFont(&Fun_Games20pt7b); 102 | tft->setCursor(messageAreaWidth + 3, 35); 103 | tft->print("Player 1: "); 104 | tft->print(leftScore); 105 | tft->setCursor(721, 35); 106 | tft->print("Player 2: "); 107 | tft->print(rightScore); 108 | } 109 | 110 | void drawMessage(const String &message) 111 | { 112 | // Clear the message area 113 | tft->fillRect(0, 0, messageAreaWidth, tft->height(), TFT_BLACK); 114 | 115 | // Set text properties and display the message 116 | tft->setFont(&Fun_Games40pt7b); 117 | tft->setTextColor(0xfec0); 118 | tft->setCursor(25, 150); 119 | tft->print(message); 120 | } -------------------------------------------------------------------------------- /examples/4x1Screens/tetris/tetris.ino: -------------------------------------------------------------------------------- 1 | // Screen Layout : 4 screens on a single row 2 | // See the tutorial : https://youtu.be/eCfeJh9Pyns 3 | // 4 | 5 | #include "virtualScreen.h" 6 | 7 | VirtualDisplay *tft; 8 | ScreenBuilder screens; 9 | 10 | void setup() 11 | { 12 | Serial.begin(115200); 13 | 14 | // Adjust this setup according to your actual screen layout 15 | screens.addRow({{16, 0}, {15, 0}, {6, 0}, {7, 0}}); 16 | 17 | tft = new VirtualDisplay(screens.width(), screens.height(), &screens); 18 | tft->begin(); 19 | 20 | playTetris(); 21 | } 22 | 23 | void loop() 24 | { 25 | } 26 | 27 | std::vector> updateGrid; 28 | 29 | // Define Tetromino shapes 30 | const int I[4][4] = { 31 | {0, 0, 0, 0}, 32 | {1, 1, 1, 1}, 33 | {0, 0, 0, 0}, 34 | {0, 0, 0, 0}}; 35 | 36 | const int O[4][4] = { 37 | {0, 0, 0, 0}, 38 | {0, 1, 1, 0}, 39 | {0, 1, 1, 0}, 40 | {0, 0, 0, 0}}; 41 | 42 | const int T[4][4] = { 43 | {0, 1, 0, 0}, 44 | {1, 1, 1, 0}, 45 | {0, 0, 0, 0}, 46 | {0, 0, 0, 0}}; 47 | 48 | const int S[4][4] = { 49 | {0, 1, 1, 0}, 50 | {1, 1, 0, 0}, 51 | {0, 0, 0, 0}, 52 | {0, 0, 0, 0}}; 53 | 54 | const int Z[4][4] = { 55 | {1, 1, 0, 0}, 56 | {0, 1, 1, 0}, 57 | {0, 0, 0, 0}, 58 | {0, 0, 0, 0}}; 59 | 60 | const int J[4][4] = { 61 | {1, 0, 0, 0}, 62 | {1, 1, 1, 0}, 63 | {0, 0, 0, 0}, 64 | {0, 0, 0, 0}}; 65 | 66 | const int L[4][4] = { 67 | {0, 0, 1, 0}, 68 | {1, 1, 1, 0}, 69 | {0, 0, 0, 0}, 70 | {0, 0, 0, 0}}; 71 | 72 | // Define colors for each tetromino shape 73 | const uint16_t tetrominoColors[7] = { 74 | TFT_RED, // Color for shape I 75 | TFT_GREEN, // Color for shape O 76 | TFT_BLUE, // Color for shape T 77 | TFT_YELLOW, // Color for shape S 78 | TFT_PURPLE, // Color for shape Z 79 | TFT_ORANGE, // Color for shape J 80 | TFT_CYAN // Color for shape L 81 | }; 82 | 83 | const int blockSize = 20; // Size of each Tetris block in pixels 84 | 85 | const int (*tetrominoes[7])[4] = {I, O, T, S, Z, J, L}; 86 | 87 | int tetrisWidth; // Width of the Tetris grid, set in setupTetris 88 | int tetrisHeight; // Height of the Tetris grid, set in setupTetris 89 | std::vector> grid; // Game grid 90 | 91 | struct Tetromino 92 | { 93 | int x, y; // Position 94 | int shape[4][4]; // Shape 95 | uint16_t color; // Color 96 | } currentTetromino; 97 | 98 | void playTetris() 99 | { 100 | setupTetris(); 101 | 102 | while (true) 103 | { 104 | clearTetrominoPosition(); 105 | 106 | // Attempt to move the tetromino down by incrementing its x position 107 | if (canPlace(currentTetromino.x + 1, currentTetromino.y, currentTetromino.shape)) 108 | { 109 | currentTetromino.x++; 110 | } 111 | else 112 | { 113 | // If the tetromino cannot move down, place it on the grid 114 | placeTetromino(); 115 | clearLines(); // Call the line-clearing function 116 | spawnTetromino(); // Spawn a new tetromino 117 | } 118 | 119 | placeTetromino(); 120 | drawGrid(); 121 | 122 | tft->output(); // Assuming this function outputs the virtual display to the actual display 123 | } 124 | } 125 | 126 | void clearLines() 127 | { 128 | for (int row = tetrisHeight - 1; row >= 0; row--) 129 | { 130 | bool rowFilled = true; 131 | 132 | // Check if the row is filled 133 | for (int col = 0; col < tetrisWidth; col++) 134 | { 135 | if (grid[row][col] == 0) 136 | { 137 | rowFilled = false; 138 | break; 139 | } 140 | } 141 | 142 | // Clear the row if it's filled 143 | if (rowFilled) 144 | { 145 | for (int y = row; y > 0; y--) 146 | { 147 | for (int x = 0; x < tetrisWidth; x++) 148 | { 149 | grid[y][x] = grid[y - 1][x]; 150 | } 151 | } 152 | 153 | // Set the top row to empty 154 | for (int x = 0; x < tetrisWidth; x++) 155 | { 156 | grid[0][x] = 0; 157 | } 158 | 159 | // Since we moved the rows down, we need to check the same row again 160 | row++; 161 | } 162 | } 163 | } 164 | 165 | // Initialize a new tetromino at the top of the grid 166 | void spawnTetromino() 167 | { 168 | int shapeIndex = esp_random() % 7; // Random index for shape 169 | memcpy(currentTetromino.shape, tetrominoes[shapeIndex], sizeof(currentTetromino.shape)); 170 | currentTetromino.x = 0; // Start from the left side (which is now the top) 171 | 172 | // Choose a random y position within the grid's width 173 | // Subtract 4 to ensure the entire tetromino shape fits within the grid 174 | currentTetromino.y = esp_random() % (tetrisHeight - 4); 175 | 176 | currentTetromino.color = tetrominoColors[shapeIndex]; 177 | } 178 | 179 | // Check if the tetromino can be placed at a position in the grid 180 | bool canPlace(int x, int y, int shape[4][4]) 181 | { 182 | for (int i = 0; i < 4; i++) 183 | { 184 | for (int j = 0; j < 4; j++) 185 | { 186 | if (shape[i][j]) 187 | { 188 | int newX = x + j; // newX represents vertical movement in the rotated grid 189 | int newY = y + i; // newY represents horizontal movement 190 | 191 | // Check for out-of-bounds or collision with existing blocks 192 | if (newX < 0 || newX >= tetrisWidth || newY < 0 || newY >= tetrisHeight || grid[newX][newY]) 193 | { 194 | return false; 195 | } 196 | } 197 | } 198 | } 199 | return true; 200 | } 201 | 202 | // Place the tetromino on the grid 203 | void placeTetromino() 204 | { 205 | for (int i = 0; i < 4; i++) 206 | { 207 | for (int j = 0; j < 4; j++) 208 | { 209 | if (currentTetromino.shape[i][j]) 210 | { 211 | int newX = currentTetromino.x + j; 212 | int newY = currentTetromino.y + i; 213 | 214 | if (newX >= 0 && newX < tetrisWidth && newY >= 0 && newY < tetrisHeight) 215 | { 216 | grid[newX][newY] = currentTetromino.color; 217 | updateGrid[newX][newY] = true; // Mark this cell for updating 218 | } 219 | } 220 | } 221 | } 222 | } 223 | 224 | void clearTetrominoPosition() 225 | { 226 | for (int i = 0; i < 4; i++) 227 | { 228 | for (int j = 0; j < 4; j++) 229 | { 230 | if (currentTetromino.shape[i][j]) 231 | { 232 | int newX = currentTetromino.x + j; 233 | int newY = currentTetromino.y + i; 234 | 235 | if (newX >= 0 && newX < tetrisWidth && newY >= 0 && newY < tetrisHeight) 236 | { 237 | grid[newX][newY] = 0; // Clear the cell 238 | updateGrid[newX][newY] = true; // Mark this cell for updating 239 | } 240 | } 241 | } 242 | } 243 | } 244 | 245 | void setupTetris() 246 | { 247 | tetrisWidth = tft->width() / blockSize; 248 | tetrisHeight = tft->height() / blockSize; 249 | grid = std::vector>(tetrisWidth, std::vector(tetrisHeight, 0)); 250 | updateGrid = std::vector>(tetrisWidth, std::vector(tetrisHeight, true)); // Initially, all cells need to be drawn 251 | 252 | spawnTetromino(); 253 | } 254 | 255 | // Modify drawGrid to only redraw cells that have changed 256 | void drawGrid() 257 | { 258 | for (int x = 0; x < tetrisWidth; x++) 259 | { 260 | for (int y = 0; y < tetrisHeight; y++) 261 | { 262 | if (updateGrid[x][y]) // Only update cells marked for redraw 263 | { 264 | int drawX = x * blockSize; 265 | int drawY = y * blockSize; 266 | uint16_t color = grid[x][y] ? grid[x][y] : TFT_BLACK; 267 | tft->fillRect(drawX, drawY, blockSize, blockSize, color); 268 | 269 | if (!grid[x][y]) // Optionally, redraw the grid lines for empty cells 270 | { 271 | tft->drawRect(drawX, drawY, blockSize, blockSize, 0x4a89); 272 | } 273 | 274 | updateGrid[x][y] = false; // Reset the update flag 275 | } 276 | } 277 | } 278 | } 279 | -------------------------------------------------------------------------------- /font_test.h: -------------------------------------------------------------------------------- 1 | #include "virtualScreen.h" 2 | #include "fonts/Starjedi32pt7b.h" 3 | #include "fonts/raidercrusader48pt7b.h" 4 | #include "fonts/Star_Trek_Enterprise_Future80pt7b.h" 5 | 6 | void printCenteredText(VirtualDisplay *tft, const String &text, const GFXfont *font, uint16_t color) 7 | { 8 | 9 | tft->setFont(font); 10 | tft->setTextColor(color); 11 | 12 | int16_t x1, y1; 13 | uint16_t w, h; 14 | tft->getTextBounds(text, 0, 0, &x1, &y1, &w, &h); // Calculate the bounds of the text 15 | 16 | int x = (tft->width() - w) / 2; // Calculate the x position to center the text 17 | int y = (tft->height() + h) / 2; // Center vertically 18 | 19 | tft->setCursor(x, y); 20 | tft->println(text); 21 | } 22 | 23 | void font_test(VirtualDisplay *tft) 24 | { 25 | tft->fillScreen(TFT_BLACK); 26 | tft->drawRect(10, 20, tft->width() - 50, tft->height() - 50, TFT_GREEN); 27 | tft->drawRect(12, 23, tft->width() - 48, tft->height() - 48, TFT_GREEN); 28 | tft->drawRoundRect(20, 50, tft->width() - 80, tft->height() - 100, 20, TFT_CYAN); 29 | printCenteredText(tft, "Star Wars Yoda Jedi", &Starjedi32pt7b, 0x00ff0c); 30 | tft->output(); 31 | delay(5000); 32 | tft->fillScreen(TFT_BLACK); 33 | printCenteredText(tft, "We are Crusaders!", &raidercrusader48pt7b, 0x17bb); 34 | tft->output(); 35 | delay(5000); 36 | tft->fillScreen(TFT_BLACK); 37 | printCenteredText(tft, "Star Trek Kirk", &Star_Trek_Enterprise_Future80pt7b, 0x3728); 38 | tft->output(); 39 | } -------------------------------------------------------------------------------- /fonts/BebasNeue_Regular13pt7b.h: -------------------------------------------------------------------------------- 1 | const uint8_t BebasNeue_Regular13pt7bBitmaps[] PROGMEM = { 2 | 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xB6, 0x07, 0xFC, 0xEF, 0xDB, 0xB6, 0x6C, 3 | 0xC9, 0x80, 0x19, 0x86, 0x61, 0x98, 0x66, 0x7F, 0xDF, 0xF3, 0xB8, 0xCC, 4 | 0x33, 0x0C, 0xC7, 0xF9, 0xFE, 0xFF, 0x8C, 0xC7, 0x71, 0xDC, 0x67, 0x19, 5 | 0x80, 0x18, 0x18, 0x7E, 0xFF, 0xE7, 0xE3, 0xE0, 0xF0, 0x78, 0x3C, 0x1E, 6 | 0x0F, 0x07, 0xE7, 0xE7, 0xE7, 0xFF, 0x7E, 0x18, 0x18, 0x70, 0x67, 0xC6, 7 | 0x36, 0x31, 0xB1, 0x8D, 0x98, 0x6C, 0xC3, 0x64, 0x1B, 0x60, 0xFB, 0x73, 8 | 0xB7, 0xC1, 0xB6, 0x09, 0x30, 0xC9, 0x86, 0x4C, 0x62, 0x63, 0x1B, 0x18, 9 | 0xF9, 0x83, 0x80, 0x3E, 0x3F, 0x3F, 0x9C, 0x0E, 0x07, 0x1B, 0x8C, 0xFF, 10 | 0x3F, 0xBF, 0xF8, 0xDC, 0x6E, 0x37, 0x1B, 0x9D, 0xFE, 0xFF, 0x3D, 0xC0, 11 | 0xFF, 0xEC, 0x80, 0x1B, 0xDF, 0xCE, 0x73, 0x9C, 0xE7, 0x39, 0xCE, 0x73, 12 | 0x9C, 0xE7, 0x3E, 0xF3, 0x80, 0x87, 0xBC, 0x73, 0x9C, 0xE7, 0x39, 0xCE, 13 | 0x73, 0x9C, 0xE7, 0x39, 0xFF, 0xEE, 0x00, 0x0E, 0x03, 0x04, 0x45, 0xD7, 14 | 0xFF, 0xC3, 0x81, 0xB0, 0xEE, 0x31, 0x80, 0x18, 0x0C, 0x06, 0x1F, 0xFF, 15 | 0xFF, 0xFC, 0x60, 0x30, 0x18, 0x00, 0xFF, 0xAD, 0x80, 0xFF, 0xFE, 0xFF, 16 | 0x80, 0x01, 0xC0, 0x60, 0x38, 0x0C, 0x07, 0x01, 0xC0, 0x60, 0x38, 0x0C, 17 | 0x03, 0x01, 0xC0, 0x60, 0x38, 0x0C, 0x03, 0x01, 0xC0, 0x60, 0x38, 0x00, 18 | 0x3C, 0x7F, 0xFF, 0xE7, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 19 | 0xE3, 0xE3, 0xE7, 0xFF, 0x7F, 0x3C, 0x0C, 0x7F, 0xFF, 0xFC, 0x71, 0xC7, 20 | 0x1C, 0x71, 0xC7, 0x1C, 0x71, 0xC7, 0x1C, 0x70, 0x3C, 0x7F, 0xFF, 0xE7, 21 | 0xE3, 0xE7, 0x07, 0x07, 0x0E, 0x1C, 0x3C, 0x78, 0x70, 0xE0, 0xE0, 0xFF, 22 | 0xFF, 0xFF, 0x3C, 0x7E, 0xFF, 0xE7, 0xE7, 0x07, 0x07, 0x1F, 0x1C, 0x1E, 23 | 0x07, 0x07, 0xC7, 0xC7, 0xE7, 0xFF, 0x7E, 0x3C, 0x07, 0x81, 0xE0, 0xF8, 24 | 0x3E, 0x0F, 0x87, 0xE1, 0xB8, 0xEE, 0x33, 0x9C, 0xE7, 0x39, 0x8E, 0xFF, 25 | 0xFF, 0xFF, 0xFC, 0x0E, 0x03, 0x80, 0xE0, 0xFF, 0xFF, 0xFF, 0xE0, 0xE0, 26 | 0xE4, 0xFF, 0xFF, 0xE7, 0xE7, 0x03, 0x03, 0xE3, 0xE3, 0xE7, 0xFF, 0x7F, 27 | 0x3C, 0x3C, 0x7F, 0xFF, 0xE3, 0xE3, 0xE0, 0xE4, 0xFF, 0xFF, 0xE7, 0xE3, 28 | 0xE3, 0xE3, 0xE3, 0xE3, 0xFF, 0x7F, 0x3E, 0xFF, 0xFF, 0xFF, 0x07, 0x07, 29 | 0x06, 0x0E, 0x0E, 0x0E, 0x1C, 0x1C, 0x1C, 0x18, 0x38, 0x38, 0x38, 0x70, 30 | 0x70, 0x3C, 0x7F, 0xFF, 0xE7, 0xE3, 0xE3, 0xE7, 0xFF, 0x7E, 0xFF, 0xE7, 31 | 0xE3, 0xE3, 0xE3, 0xE3, 0xFF, 0xFF, 0x3E, 0x3C, 0x7E, 0xFF, 0xE7, 0xE7, 32 | 0xE7, 0xE7, 0xE7, 0xE7, 0xFF, 0x7F, 0x27, 0x07, 0xC7, 0xE7, 0xFF, 0x7E, 33 | 0x3C, 0xFF, 0x80, 0x00, 0x03, 0xFE, 0xFF, 0x80, 0x00, 0x03, 0xFE, 0xB4, 34 | 0x03, 0x0F, 0x3C, 0xF0, 0xE0, 0x7C, 0x1F, 0x03, 0xFF, 0xFF, 0xFF, 0x00, 35 | 0xFF, 0xFF, 0xFF, 0xC0, 0xF0, 0x3E, 0x0F, 0x07, 0x3E, 0xF8, 0xC0, 0x3E, 36 | 0x3F, 0x9F, 0xCC, 0x7E, 0x3F, 0x1C, 0x0C, 0x0E, 0x0E, 0x07, 0x07, 0x03, 37 | 0x81, 0x80, 0x00, 0x00, 0x38, 0x1C, 0x0E, 0x00, 0x00, 0x40, 0x07, 0xF8, 38 | 0x1F, 0xFC, 0x3C, 0x1E, 0x38, 0x07, 0x71, 0x37, 0x67, 0xB3, 0xE7, 0xF3, 39 | 0xC6, 0x73, 0xCE, 0x73, 0xCE, 0x73, 0xCE, 0x73, 0xCE, 0x76, 0xCE, 0xFE, 40 | 0xCF, 0xFC, 0xE7, 0x78, 0xE0, 0x00, 0x70, 0x08, 0x3F, 0xF8, 0x1F, 0xF8, 41 | 0x07, 0xE0, 0x1E, 0x07, 0x81, 0xE0, 0x7C, 0x3F, 0x0F, 0xC3, 0xF0, 0xCC, 42 | 0x33, 0x0C, 0xE7, 0x39, 0xCE, 0x7F, 0x9F, 0xE6, 0x19, 0x87, 0x61, 0xF8, 43 | 0x70, 0xFE, 0x7F, 0xBF, 0xDC, 0xEE, 0x37, 0x1B, 0x9D, 0xFE, 0xFE, 0x7F, 44 | 0xB9, 0xDC, 0x7E, 0x3F, 0x1F, 0x8F, 0xFE, 0xFF, 0x7F, 0x00, 0x3C, 0x7E, 45 | 0xFF, 0xE7, 0xE7, 0xE7, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE7, 0xE7, 0xE7, 46 | 0xE7, 0xFF, 0x7E, 0x3C, 0xFE, 0x7F, 0xBF, 0xDC, 0x6E, 0x3F, 0x1F, 0x8F, 47 | 0xC7, 0xE3, 0xF1, 0xF8, 0xFC, 0x7E, 0x3F, 0x1F, 0x8D, 0xFE, 0xFF, 0x7F, 48 | 0x00, 0xFF, 0xFF, 0xFF, 0xE0, 0xE0, 0xE0, 0xE0, 0xFE, 0xFE, 0xFE, 0xE0, 49 | 0xE0, 0xE0, 0xE0, 0xE0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0E, 0x1C, 50 | 0x38, 0x7E, 0xFD, 0xFB, 0x87, 0x0E, 0x1C, 0x38, 0x70, 0xE1, 0xC0, 0x3C, 51 | 0x7E, 0xFF, 0xE7, 0xE3, 0xE3, 0xE0, 0xE0, 0xEF, 0xEF, 0xEF, 0xE3, 0xE3, 52 | 0xE3, 0xE7, 0xFF, 0x7E, 0x3C, 0xE3, 0xF1, 0xF8, 0xFC, 0x7E, 0x3F, 0x1F, 53 | 0x8F, 0xFF, 0xFF, 0xFF, 0xF8, 0xFC, 0x7E, 0x3F, 0x1F, 0x8F, 0xC7, 0xE3, 54 | 0xF1, 0xC0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0x1C, 0x71, 0xC7, 55 | 0x1C, 0x71, 0xC7, 0x1C, 0x71, 0xC7, 0x1C, 0x71, 0xFF, 0xFB, 0xC0, 0xE3, 56 | 0xF1, 0xB9, 0xDC, 0xCE, 0xE7, 0x73, 0xF1, 0xF8, 0xFC, 0x7F, 0x3F, 0x9D, 57 | 0xCE, 0x77, 0x3B, 0x9D, 0xC7, 0xE3, 0xF1, 0xC0, 0xE1, 0xC3, 0x87, 0x0E, 58 | 0x1C, 0x38, 0x70, 0xE1, 0xC3, 0x87, 0x0E, 0x1C, 0x38, 0x7F, 0xFF, 0xFC, 59 | 0xF0, 0xFF, 0x1F, 0xF1, 0xFF, 0x9F, 0xF9, 0xFD, 0x9F, 0xD9, 0xFD, 0x9F, 60 | 0xDB, 0x7D, 0xB7, 0xDB, 0x7C, 0xF7, 0xCF, 0x7C, 0xF7, 0xCE, 0x7C, 0xE7, 61 | 0xCE, 0x7C, 0xE7, 0xF3, 0xF9, 0xFC, 0xFE, 0x7F, 0xBF, 0xDF, 0xEF, 0xF7, 62 | 0xFF, 0xF7, 0xFB, 0xFD, 0xFE, 0x7F, 0x3F, 0x9F, 0xCF, 0xE3, 0xF1, 0xC0, 63 | 0x3C, 0x7F, 0xFF, 0xE7, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 64 | 0xE3, 0xE3, 0xE7, 0xFF, 0x7F, 0x3C, 0xFC, 0xFF, 0xFF, 0xE7, 0xE3, 0xE3, 65 | 0xE3, 0xE7, 0xFF, 0xFE, 0xF0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 66 | 0x3C, 0x3F, 0xBF, 0xDC, 0xEE, 0x37, 0x1B, 0x8D, 0xC6, 0xE3, 0x71, 0xB8, 67 | 0xDC, 0x6E, 0x37, 0x1B, 0x9D, 0xFE, 0x7F, 0x1F, 0xC0, 0xE0, 0x10, 0xFE, 68 | 0x7F, 0xBF, 0xDC, 0xEE, 0x37, 0x1B, 0x8D, 0xCE, 0xFE, 0x7F, 0x3F, 0xDC, 69 | 0xEE, 0x37, 0x1B, 0x8D, 0xC6, 0xE3, 0x71, 0x80, 0x3C, 0xFE, 0xFF, 0xC7, 70 | 0xC7, 0xE0, 0xE0, 0x70, 0x78, 0x3C, 0x1E, 0x0F, 0x07, 0xC7, 0xC7, 0xFF, 71 | 0xFE, 0x7C, 0xFF, 0xFF, 0xFF, 0xE3, 0x81, 0xC0, 0xE0, 0x70, 0x38, 0x1C, 72 | 0x0E, 0x07, 0x03, 0x81, 0xC0, 0xE0, 0x70, 0x38, 0x1C, 0x0E, 0x00, 0xE3, 73 | 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 74 | 0xE3, 0xE7, 0xFF, 0x7E, 0x3C, 0xE1, 0xB0, 0xD8, 0xEE, 0x77, 0x3B, 0x9D, 75 | 0xCC, 0xE6, 0x33, 0x19, 0x8F, 0xC7, 0xE3, 0xF1, 0xF0, 0xF8, 0x3C, 0x1E, 76 | 0x0F, 0x00, 0xE3, 0x9D, 0x8E, 0x76, 0x79, 0xD9, 0xE6, 0x67, 0x99, 0xDE, 77 | 0x67, 0x79, 0x9D, 0xE6, 0x76, 0xD9, 0xDB, 0x67, 0x6F, 0x8D, 0xBE, 0x3E, 78 | 0xF8, 0xF3, 0xC3, 0xCF, 0x0F, 0x3C, 0x3C, 0xF0, 0xF3, 0xC0, 0xF1, 0xDC, 79 | 0x67, 0x38, 0xCE, 0x3B, 0x0F, 0xC1, 0xF0, 0x78, 0x1E, 0x07, 0x81, 0xE0, 80 | 0x7C, 0x3F, 0x0C, 0xC7, 0x39, 0xCE, 0x61, 0xF8, 0x70, 0xE1, 0xDC, 0x67, 81 | 0x39, 0xCE, 0x33, 0x0E, 0xC3, 0xF0, 0x78, 0x1E, 0x07, 0x80, 0xC0, 0x30, 82 | 0x0C, 0x03, 0x00, 0xC0, 0x30, 0x0C, 0x03, 0x00, 0x7F, 0xBF, 0xDF, 0xE0, 83 | 0xE0, 0x70, 0x70, 0x38, 0x1C, 0x1C, 0x0E, 0x0E, 0x07, 0x03, 0x83, 0x81, 84 | 0xC1, 0xFF, 0xFF, 0xFF, 0xC0, 0xFF, 0xFF, 0xCE, 0x73, 0x9C, 0xE7, 0x39, 85 | 0xCE, 0x73, 0x9C, 0xE7, 0x3F, 0xFF, 0x80, 0xE0, 0x18, 0x07, 0x00, 0xC0, 86 | 0x30, 0x0E, 0x01, 0x80, 0x70, 0x0C, 0x03, 0x00, 0xE0, 0x18, 0x07, 0x00, 87 | 0xC0, 0x30, 0x0E, 0x01, 0x80, 0x70, 0xFF, 0xFE, 0x73, 0x9C, 0xE7, 0x39, 88 | 0xCE, 0x73, 0x9C, 0xE7, 0x39, 0xFF, 0xFF, 0x80, 0x0C, 0x07, 0x81, 0xE0, 89 | 0xEC, 0x33, 0x1C, 0x6E, 0x1C, 0xFF, 0xFF, 0xFF, 0xE3, 0x8E, 0x1E, 0x07, 90 | 0x81, 0xE0, 0x7C, 0x3F, 0x0F, 0xC3, 0xF0, 0xCC, 0x33, 0x0C, 0xE7, 0x39, 91 | 0xCE, 0x7F, 0x9F, 0xE6, 0x19, 0x87, 0x61, 0xF8, 0x70, 0xFE, 0x7F, 0xBF, 92 | 0xDC, 0xEE, 0x37, 0x1B, 0x9D, 0xFE, 0xFE, 0x7F, 0xB9, 0xDC, 0x7E, 0x3F, 93 | 0x1F, 0x8F, 0xFE, 0xFF, 0x7F, 0x00, 0x3C, 0x7E, 0xFF, 0xE7, 0xE7, 0xE7, 94 | 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE7, 0xE7, 0xE7, 0xE7, 0xFF, 0x7E, 0x3C, 95 | 0xFE, 0x7F, 0xBF, 0xDC, 0x6E, 0x3F, 0x1F, 0x8F, 0xC7, 0xE3, 0xF1, 0xF8, 96 | 0xFC, 0x7E, 0x3F, 0x1F, 0x8D, 0xFE, 0xFF, 0x7F, 0x00, 0xFF, 0xFF, 0xFF, 97 | 0xE0, 0xE0, 0xE0, 0xE0, 0xFE, 0xFE, 0xFE, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 98 | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0E, 0x1C, 0x38, 0x7E, 0xFD, 0xFB, 99 | 0x87, 0x0E, 0x1C, 0x38, 0x70, 0xE1, 0xC0, 0x3C, 0x7E, 0xFF, 0xE7, 0xE3, 100 | 0xE3, 0xE0, 0xE0, 0xEF, 0xEF, 0xEF, 0xE3, 0xE3, 0xE3, 0xE7, 0xFF, 0x7E, 101 | 0x3C, 0xE3, 0xF1, 0xF8, 0xFC, 0x7E, 0x3F, 0x1F, 0x8F, 0xFF, 0xFF, 0xFF, 102 | 0xF8, 0xFC, 0x7E, 0x3F, 0x1F, 0x8F, 0xC7, 0xE3, 0xF1, 0xC0, 0xFF, 0xFF, 103 | 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0x1C, 0x71, 0xC7, 0x1C, 0x71, 0xC7, 0x1C, 104 | 0x71, 0xC7, 0x1C, 0x71, 0xFF, 0xFB, 0xC0, 0xE3, 0xF1, 0xB9, 0xDC, 0xCE, 105 | 0xE7, 0x73, 0xF1, 0xF8, 0xFC, 0x7F, 0x3F, 0x9D, 0xCE, 0x77, 0x3B, 0x9D, 106 | 0xC7, 0xE3, 0xF1, 0xC0, 0xE1, 0xC3, 0x87, 0x0E, 0x1C, 0x38, 0x70, 0xE1, 107 | 0xC3, 0x87, 0x0E, 0x1C, 0x38, 0x7F, 0xFF, 0xFC, 0xF0, 0xFF, 0x1F, 0xF1, 108 | 0xFF, 0x9F, 0xF9, 0xFD, 0x9F, 0xD9, 0xFD, 0x9F, 0xDB, 0x7D, 0xB7, 0xDB, 109 | 0x7C, 0xF7, 0xCF, 0x7C, 0xF7, 0xCE, 0x7C, 0xE7, 0xCE, 0x7C, 0xE7, 0xF3, 110 | 0xF9, 0xFC, 0xFE, 0x7F, 0xBF, 0xDF, 0xEF, 0xF7, 0xFF, 0xF7, 0xFB, 0xFD, 111 | 0xFE, 0x7F, 0x3F, 0x9F, 0xCF, 0xE3, 0xF1, 0xC0, 0x3C, 0x7F, 0xFF, 0xE7, 112 | 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE7, 0xFF, 113 | 0x7F, 0x3C, 0xFC, 0xFF, 0xFF, 0xE7, 0xE3, 0xE3, 0xE3, 0xE7, 0xFF, 0xFE, 114 | 0xF0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0x3C, 0x3F, 0xBF, 0xDC, 115 | 0xEE, 0x37, 0x1B, 0x8D, 0xC6, 0xE3, 0x71, 0xB8, 0xDC, 0x6E, 0x37, 0x1B, 116 | 0x9D, 0xFE, 0x7F, 0x1F, 0xC0, 0xE0, 0x10, 0xFE, 0x7F, 0xBF, 0xDC, 0xEE, 117 | 0x37, 0x1B, 0x8D, 0xCE, 0xFE, 0x7F, 0x3F, 0xDC, 0xEE, 0x37, 0x1B, 0x8D, 118 | 0xC6, 0xE3, 0x71, 0x80, 0x3C, 0xFE, 0xFF, 0xC7, 0xC7, 0xE0, 0xE0, 0x70, 119 | 0x78, 0x3C, 0x1E, 0x0F, 0x07, 0xC7, 0xC7, 0xFF, 0xFE, 0x7C, 0xFF, 0xFF, 120 | 0xFF, 0xE3, 0x81, 0xC0, 0xE0, 0x70, 0x38, 0x1C, 0x0E, 0x07, 0x03, 0x81, 121 | 0xC0, 0xE0, 0x70, 0x38, 0x1C, 0x0E, 0x00, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 122 | 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE7, 0xFF, 0x7E, 123 | 0x3C, 0xE1, 0xB0, 0xD8, 0xEE, 0x77, 0x3B, 0x9D, 0xCC, 0xE6, 0x33, 0x19, 124 | 0x8F, 0xC7, 0xE3, 0xF1, 0xF0, 0xF8, 0x3C, 0x1E, 0x0F, 0x00, 0xE3, 0x9D, 125 | 0x8E, 0x76, 0x79, 0xD9, 0xE6, 0x67, 0x99, 0xDE, 0x67, 0x79, 0x9D, 0xE6, 126 | 0x76, 0xD9, 0xDB, 0x67, 0x6F, 0x8D, 0xBE, 0x3E, 0xF8, 0xF3, 0xC3, 0xCF, 127 | 0x0F, 0x3C, 0x3C, 0xF0, 0xF3, 0xC0, 0xF1, 0xDC, 0x67, 0x38, 0xCE, 0x3B, 128 | 0x0F, 0xC1, 0xF0, 0x78, 0x1E, 0x07, 0x81, 0xE0, 0x7C, 0x3F, 0x0C, 0xC7, 129 | 0x39, 0xCE, 0x61, 0xF8, 0x70, 0xE1, 0xDC, 0x67, 0x39, 0xCE, 0x33, 0x0E, 130 | 0xC3, 0xF0, 0x78, 0x1E, 0x07, 0x80, 0xC0, 0x30, 0x0C, 0x03, 0x00, 0xC0, 131 | 0x30, 0x0C, 0x03, 0x00, 0x7F, 0xBF, 0xDF, 0xE0, 0xE0, 0x70, 0x70, 0x38, 132 | 0x1C, 0x1C, 0x0E, 0x0E, 0x07, 0x03, 0x83, 0x81, 0xC1, 0xFF, 0xFF, 0xFF, 133 | 0xC0, 0x19, 0xDE, 0xE7, 0x39, 0xCE, 0x77, 0x39, 0xC7, 0x39, 0xCE, 0x73, 134 | 0x9E, 0xF3, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 135 | 0xE0, 0x87, 0x3C, 0xE7, 0x39, 0xCE, 0x71, 0xCE, 0x77, 0x39, 0xCE, 0x73, 136 | 0xBD, 0xEE, 0x00, 0x10, 0x9F, 0xFF, 0xF9, 0x1C }; 137 | 138 | const GFXglyph BebasNeue_Regular13pt7bGlyphs[] PROGMEM = { 139 | { 0, 1, 1, 4, 0, 0 }, // 0x20 ' ' 140 | { 1, 3, 18, 5, 1, -17 }, // 0x21 '!' 141 | { 8, 7, 6, 9, 1, -17 }, // 0x22 '"' 142 | { 14, 10, 18, 10, 0, -17 }, // 0x23 '#' 143 | { 37, 8, 20, 10, 1, -18 }, // 0x24 '$' 144 | { 57, 13, 18, 15, 1, -17 }, // 0x25 '%' 145 | { 87, 9, 18, 11, 1, -17 }, // 0x26 '&' 146 | { 108, 3, 6, 5, 1, -17 }, // 0x27 ''' 147 | { 111, 5, 21, 7, 1, -19 }, // 0x28 '(' 148 | { 125, 5, 21, 7, 1, -19 }, // 0x29 ')' 149 | { 139, 10, 9, 11, 0, -17 }, // 0x2A '*' 150 | { 151, 9, 9, 10, 1, -12 }, // 0x2B '+' 151 | { 162, 3, 6, 5, 1, -2 }, // 0x2C ',' 152 | { 165, 5, 3, 7, 1, -10 }, // 0x2D '-' 153 | { 167, 3, 3, 5, 1, -2 }, // 0x2E '.' 154 | { 169, 10, 18, 10, 0, -17 }, // 0x2F '/' 155 | { 192, 8, 18, 10, 1, -17 }, // 0x30 '0' 156 | { 210, 6, 18, 10, 2, -17 }, // 0x31 '1' 157 | { 224, 8, 18, 10, 1, -17 }, // 0x32 '2' 158 | { 242, 8, 18, 10, 1, -17 }, // 0x33 '3' 159 | { 260, 10, 18, 10, 0, -17 }, // 0x34 '4' 160 | { 283, 8, 18, 10, 1, -17 }, // 0x35 '5' 161 | { 301, 8, 18, 10, 1, -17 }, // 0x36 '6' 162 | { 319, 8, 18, 10, 1, -17 }, // 0x37 '7' 163 | { 337, 8, 18, 10, 1, -17 }, // 0x38 '8' 164 | { 355, 8, 18, 10, 1, -17 }, // 0x39 '9' 165 | { 373, 3, 13, 5, 1, -12 }, // 0x3A ':' 166 | { 378, 3, 16, 5, 1, -12 }, // 0x3B ';' 167 | { 384, 8, 8, 10, 1, -12 }, // 0x3C '<' 168 | { 392, 8, 7, 10, 1, -12 }, // 0x3D '=' 169 | { 399, 8, 8, 10, 1, -12 }, // 0x3E '>' 170 | { 407, 9, 18, 9, 0, -17 }, // 0x3F '?' 171 | { 428, 16, 21, 18, 1, -18 }, // 0x40 '@' 172 | { 470, 10, 18, 10, 0, -17 }, // 0x41 'A' 173 | { 493, 9, 18, 10, 1, -17 }, // 0x42 'B' 174 | { 514, 8, 18, 10, 1, -17 }, // 0x43 'C' 175 | { 532, 9, 18, 10, 1, -17 }, // 0x44 'D' 176 | { 553, 8, 18, 9, 1, -17 }, // 0x45 'E' 177 | { 571, 7, 18, 9, 1, -17 }, // 0x46 'F' 178 | { 587, 8, 18, 10, 1, -17 }, // 0x47 'G' 179 | { 605, 9, 18, 11, 1, -17 }, // 0x48 'H' 180 | { 626, 3, 18, 5, 1, -17 }, // 0x49 'I' 181 | { 633, 6, 18, 7, 0, -17 }, // 0x4A 'J' 182 | { 647, 9, 18, 11, 1, -17 }, // 0x4B 'K' 183 | { 668, 7, 18, 9, 1, -17 }, // 0x4C 'L' 184 | { 684, 12, 18, 14, 1, -17 }, // 0x4D 'M' 185 | { 711, 9, 18, 11, 1, -17 }, // 0x4E 'N' 186 | { 732, 8, 18, 10, 1, -17 }, // 0x4F 'O' 187 | { 750, 8, 18, 10, 1, -17 }, // 0x50 'P' 188 | { 768, 9, 20, 10, 1, -17 }, // 0x51 'Q' 189 | { 791, 9, 18, 10, 1, -17 }, // 0x52 'R' 190 | { 812, 8, 18, 9, 1, -17 }, // 0x53 'S' 191 | { 830, 9, 18, 9, 0, -17 }, // 0x54 'T' 192 | { 851, 8, 18, 10, 1, -17 }, // 0x55 'U' 193 | { 869, 9, 18, 10, 0, -17 }, // 0x56 'V' 194 | { 890, 14, 18, 14, 0, -17 }, // 0x57 'W' 195 | { 922, 10, 18, 10, 0, -17 }, // 0x58 'X' 196 | { 945, 10, 18, 10, 0, -17 }, // 0x59 'Y' 197 | { 968, 9, 18, 9, 0, -17 }, // 0x5A 'Z' 198 | { 989, 5, 21, 7, 1, -19 }, // 0x5B '[' 199 | { 1003, 10, 18, 10, 0, -17 }, // 0x5C '\' 200 | { 1026, 5, 21, 7, 1, -19 }, // 0x5D ']' 201 | { 1040, 10, 7, 10, 0, -17 }, // 0x5E '^' 202 | { 1049, 8, 3, 8, 0, 0 }, // 0x5F '_' 203 | { 1052, 5, 3, 13, 3, -21 }, // 0x60 '`' 204 | { 1054, 10, 18, 10, 0, -17 }, // 0x61 'a' 205 | { 1077, 9, 18, 10, 1, -17 }, // 0x62 'b' 206 | { 1098, 8, 18, 10, 1, -17 }, // 0x63 'c' 207 | { 1116, 9, 18, 10, 1, -17 }, // 0x64 'd' 208 | { 1137, 8, 18, 9, 1, -17 }, // 0x65 'e' 209 | { 1155, 7, 18, 9, 1, -17 }, // 0x66 'f' 210 | { 1171, 8, 18, 10, 1, -17 }, // 0x67 'g' 211 | { 1189, 9, 18, 11, 1, -17 }, // 0x68 'h' 212 | { 1210, 3, 18, 5, 1, -17 }, // 0x69 'i' 213 | { 1217, 6, 18, 7, 0, -17 }, // 0x6A 'j' 214 | { 1231, 9, 18, 11, 1, -17 }, // 0x6B 'k' 215 | { 1252, 7, 18, 9, 1, -17 }, // 0x6C 'l' 216 | { 1268, 12, 18, 14, 1, -17 }, // 0x6D 'm' 217 | { 1295, 9, 18, 11, 1, -17 }, // 0x6E 'n' 218 | { 1316, 8, 18, 10, 1, -17 }, // 0x6F 'o' 219 | { 1334, 8, 18, 10, 1, -17 }, // 0x70 'p' 220 | { 1352, 9, 20, 10, 1, -17 }, // 0x71 'q' 221 | { 1375, 9, 18, 10, 1, -17 }, // 0x72 'r' 222 | { 1396, 8, 18, 9, 1, -17 }, // 0x73 's' 223 | { 1414, 9, 18, 9, 0, -17 }, // 0x74 't' 224 | { 1435, 8, 18, 10, 1, -17 }, // 0x75 'u' 225 | { 1453, 9, 18, 10, 0, -17 }, // 0x76 'v' 226 | { 1474, 14, 18, 14, 0, -17 }, // 0x77 'w' 227 | { 1506, 10, 18, 10, 0, -17 }, // 0x78 'x' 228 | { 1529, 10, 18, 10, 0, -17 }, // 0x79 'y' 229 | { 1552, 9, 18, 9, 0, -17 }, // 0x7A 'z' 230 | { 1573, 5, 21, 7, 1, -19 }, // 0x7B '{' 231 | { 1587, 3, 25, 13, 5, -19 }, // 0x7C '|' 232 | { 1597, 5, 21, 7, 1, -19 }, // 0x7D '}' 233 | { 1611, 10, 4, 10, 0, -10 } }; // 0x7E '~' 234 | 235 | const GFXfont BebasNeue_Regular13pt7b PROGMEM = { 236 | (uint8_t *)BebasNeue_Regular13pt7bBitmaps, 237 | (GFXglyph *)BebasNeue_Regular13pt7bGlyphs, 238 | 0x20, 0x7E, 31 }; 239 | 240 | // Approx. 2288 bytes 241 | -------------------------------------------------------------------------------- /fonts/Fun_Games20pt7b.h: -------------------------------------------------------------------------------- 1 | const uint8_t Fun_Games20pt7bBitmaps[] PROGMEM = { 2 | 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xEF, 0x38, 3 | 0xC2, 0x10, 0x7F, 0xFF, 0xFF, 0xC0, 0xEF, 0xDF, 0xBF, 0x7E, 0xFD, 0xFB, 4 | 0x80, 0x01, 0x80, 0x80, 0x03, 0x83, 0xC0, 0x1E, 0x0E, 0x00, 0x70, 0x38, 5 | 0x01, 0xC0, 0xE0, 0x07, 0x03, 0x80, 0x1C, 0x1E, 0x1F, 0xFF, 0xFF, 0x7F, 6 | 0xFF, 0xFD, 0xFF, 0xFF, 0xF0, 0x38, 0x1C, 0x00, 0xE0, 0xF0, 0x03, 0x83, 7 | 0x80, 0x1E, 0x0E, 0x00, 0x78, 0x38, 0x01, 0xC0, 0xE0, 0x07, 0x03, 0x80, 8 | 0x1C, 0x1E, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0x38, 9 | 0x1C, 0x00, 0xE0, 0x70, 0x03, 0x83, 0xC0, 0x0E, 0x0E, 0x00, 0x78, 0x38, 10 | 0x01, 0xC0, 0xE0, 0x07, 0x03, 0x80, 0x00, 0x0F, 0x00, 0x00, 0x0F, 0x00, 11 | 0x00, 0x0F, 0x00, 0x00, 0x0F, 0x00, 0x01, 0xFF, 0xFE, 0x03, 0xFF, 0xFC, 12 | 0x07, 0xFF, 0xF8, 0x07, 0xFF, 0xF0, 0x0F, 0xFF, 0xF0, 0x0F, 0x80, 0x00, 13 | 0x1F, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x7F, 0xFF, 0xFF, 14 | 0x7F, 0xFF, 0xFF, 0x7F, 0xFF, 0xFF, 0x7F, 0xFF, 0xFF, 0x7F, 0xFF, 0xFF, 15 | 0x00, 0x00, 0x3F, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x7C, 16 | 0x00, 0x00, 0xF8, 0x0F, 0xFF, 0xF8, 0x1F, 0xFF, 0xF0, 0x3F, 0xFF, 0xF0, 17 | 0x3F, 0xFF, 0xE0, 0x7F, 0xFF, 0xC0, 0x80, 0x0F, 0x00, 0x00, 0x0F, 0x00, 18 | 0x00, 0x0F, 0x00, 0x00, 0x0F, 0x00, 0xFC, 0x1F, 0xF8, 0x3B, 0xF0, 0xF7, 19 | 0xE1, 0xEF, 0xC7, 0x9F, 0x8F, 0x00, 0x3C, 0x00, 0x78, 0x01, 0xE0, 0x03, 20 | 0xC0, 0x0F, 0x00, 0x1E, 0x00, 0x78, 0x00, 0xF0, 0x03, 0xC0, 0x07, 0x80, 21 | 0x1E, 0x00, 0x3C, 0x00, 0x7B, 0xF1, 0xE7, 0xE3, 0xCF, 0xCF, 0x1F, 0x9E, 22 | 0x3F, 0x78, 0x7E, 0xFF, 0xFF, 0xE3, 0xFF, 0xFF, 0x8F, 0xFF, 0xFE, 0x3F, 23 | 0xFF, 0xF8, 0xFF, 0xFF, 0xE3, 0xE0, 0x00, 0x0F, 0x80, 0x00, 0x3E, 0x00, 24 | 0x00, 0xF8, 0x00, 0x03, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 25 | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0x3E, 0x3E, 0x00, 0xF8, 0xF8, 26 | 0x03, 0xE3, 0xE0, 0x0F, 0x8F, 0xC0, 0x3E, 0x3F, 0xFF, 0xF8, 0x7F, 0xFF, 27 | 0xE0, 0xFF, 0xFF, 0x81, 0xFF, 0xFE, 0x01, 0xFF, 0xF8, 0xFF, 0xFF, 0xF8, 28 | 0x07, 0xFF, 0x0F, 0xFE, 0x3F, 0xFC, 0x7F, 0xF0, 0xFF, 0xE0, 0xFC, 0x00, 29 | 0xF8, 0x00, 0xF8, 0x00, 0xF8, 0x00, 0xF8, 0x00, 0xF8, 0x00, 0xF8, 0x00, 30 | 0xF8, 0x00, 0xF8, 0x00, 0xF8, 0x00, 0xF8, 0x00, 0xF8, 0x00, 0xF8, 0x00, 31 | 0xF8, 0x00, 0xF8, 0x00, 0xF8, 0x00, 0xF8, 0x00, 0xF8, 0x00, 0xF8, 0x00, 32 | 0xFC, 0x00, 0xFF, 0xE0, 0x7F, 0xF0, 0x3F, 0xFC, 0x0F, 0xFE, 0x07, 0xFF, 33 | 0xFF, 0xE0, 0x7F, 0xF0, 0x1F, 0xFC, 0x0F, 0xFE, 0x07, 0xFF, 0x00, 0x3F, 34 | 0x00, 0x1F, 0x00, 0x1F, 0x00, 0x1F, 0x00, 0x1F, 0x00, 0x1F, 0x00, 0x1F, 35 | 0x00, 0x1F, 0x00, 0x1F, 0x00, 0x1F, 0x00, 0x1F, 0x00, 0x1F, 0x00, 0x1F, 36 | 0x00, 0x1F, 0x00, 0x1F, 0x00, 0x1F, 0x00, 0x1F, 0x00, 0x1F, 0x00, 0x1F, 37 | 0x00, 0x3F, 0x07, 0xFF, 0x0F, 0xFE, 0x1F, 0xFC, 0x7F, 0xF0, 0xFF, 0xE0, 38 | 0x0C, 0x0B, 0x47, 0xF8, 0xFC, 0xFF, 0xFF, 0xF3, 0xF1, 0xFE, 0x2D, 0x03, 39 | 0x00, 0x00, 0xF8, 0x00, 0x07, 0xC0, 0x00, 0x3E, 0x00, 0x01, 0xF0, 0x00, 40 | 0x0F, 0x80, 0x00, 0x7C, 0x00, 0x03, 0xE0, 0x00, 0x1F, 0x00, 0xFF, 0xFF, 41 | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 42 | 0x7C, 0x00, 0x03, 0xE0, 0x00, 0x1F, 0x00, 0x00, 0xF8, 0x00, 0x07, 0xC0, 43 | 0x00, 0x3E, 0x00, 0x01, 0xF0, 0x00, 0x0F, 0x80, 0x00, 0xFF, 0xFF, 0xFF, 44 | 0xFB, 0xDC, 0xC4, 0x20, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 45 | 0x80, 0xFF, 0xFF, 0xFF, 0x80, 0x00, 0x18, 0x00, 0x70, 0x03, 0xC0, 0x0E, 46 | 0x00, 0x78, 0x01, 0xC0, 0x07, 0x00, 0x3C, 0x00, 0xE0, 0x07, 0x80, 0x1C, 47 | 0x00, 0xF0, 0x03, 0x80, 0x0E, 0x00, 0x78, 0x01, 0xC0, 0x0F, 0x00, 0x38, 48 | 0x01, 0xE0, 0x07, 0x00, 0x1C, 0x00, 0xF0, 0x03, 0x80, 0x1E, 0x00, 0x70, 49 | 0x01, 0xC0, 0x0F, 0x00, 0x38, 0x00, 0x60, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 50 | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0x00, 0x7F, 51 | 0xE0, 0x03, 0xFF, 0x00, 0x1F, 0xF8, 0x00, 0xFF, 0xC0, 0x07, 0xFE, 0x00, 52 | 0x3F, 0xF0, 0x01, 0xFF, 0x80, 0x0F, 0xFC, 0x00, 0x7F, 0xE0, 0x03, 0xFF, 53 | 0x00, 0x1F, 0xF8, 0x00, 0xFF, 0xC0, 0x07, 0xFE, 0x00, 0x3F, 0xFF, 0xFF, 54 | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 55 | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC1, 0xF0, 0x7C, 0x1F, 0x07, 0xC1, 0xF0, 56 | 0x7C, 0x1F, 0x07, 0xC1, 0xF0, 0x7C, 0x1F, 0x07, 0xC1, 0xF0, 0x7C, 0x1F, 57 | 0x07, 0xC1, 0xF0, 0x7C, 0x1F, 0x07, 0xC0, 0xF0, 0x1C, 0x03, 0x00, 0xC0, 58 | 0x10, 0xFF, 0xFF, 0x80, 0xFF, 0xFF, 0x80, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 59 | 0x00, 0xFF, 0xFE, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x7C, 60 | 0x00, 0x00, 0xFD, 0xFF, 0xFF, 0xFB, 0xFF, 0xFF, 0xF7, 0xFF, 0xFF, 0xEF, 61 | 0xFF, 0xFF, 0xDF, 0xFF, 0xFF, 0xBE, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x7C, 62 | 0x00, 0x00, 0xFC, 0x00, 0x00, 0xF8, 0x00, 0x01, 0xFF, 0xFF, 0x01, 0xFF, 63 | 0xFF, 0x01, 0xFF, 0xFF, 0x03, 0xFF, 0xFF, 0x03, 0xFF, 0xFF, 0xFF, 0xFF, 64 | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0x00, 0x07, 65 | 0xC0, 0x00, 0xF8, 0x00, 0x1F, 0x00, 0x03, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 66 | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC0, 0x00, 0xF8, 0x00, 0x1F, 67 | 0x00, 0x03, 0xE0, 0x00, 0x7C, 0x00, 0x1F, 0x87, 0xFF, 0xF1, 0xFF, 0xFC, 68 | 0x7F, 0xFF, 0x0F, 0xFF, 0xC3, 0xFF, 0xE0, 0xF8, 0x03, 0xFF, 0x00, 0x7F, 69 | 0xE0, 0x0F, 0xFC, 0x01, 0xFF, 0x80, 0x3F, 0xF0, 0x07, 0xFE, 0x00, 0xFF, 70 | 0xC0, 0x1F, 0xF8, 0x03, 0xFF, 0x00, 0x7F, 0xE0, 0x0F, 0xFC, 0x01, 0xFF, 71 | 0x80, 0x3F, 0xF0, 0x07, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 72 | 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0x01, 0xF0, 0x00, 0x3E, 0x00, 0x07, 0xC0, 73 | 0x00, 0xF8, 0x00, 0x1F, 0x00, 0x03, 0xE0, 0x00, 0x3C, 0x00, 0x03, 0x80, 74 | 0x00, 0x30, 0x00, 0x06, 0x00, 0x00, 0x40, 0x00, 0x08, 0x07, 0xFF, 0xFE, 75 | 0x1F, 0xFF, 0xF8, 0x7F, 0xFF, 0xE1, 0xFF, 0xFF, 0x83, 0xFF, 0xFE, 0x0F, 76 | 0xE0, 0x00, 0x3F, 0x80, 0x00, 0x7E, 0x00, 0x00, 0xFF, 0xFF, 0xFD, 0xFF, 77 | 0xFF, 0xFB, 0xFF, 0xFF, 0xF7, 0xFF, 0xFF, 0xEF, 0xFF, 0xFF, 0xC0, 0x00, 78 | 0x1F, 0x80, 0x00, 0x7F, 0x00, 0x00, 0xFC, 0x00, 0x03, 0xF0, 0x00, 0x07, 79 | 0xE0, 0x00, 0x0F, 0x80, 0x7F, 0xFF, 0x01, 0xFF, 0xFC, 0x07, 0xFF, 0xF8, 80 | 0x1F, 0xFF, 0xE0, 0x7F, 0xFF, 0xC0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xBF, 81 | 0xFF, 0xF9, 0xFF, 0xFF, 0x8F, 0xFF, 0xF8, 0x7C, 0x00, 0x03, 0xE0, 0x00, 82 | 0x1F, 0x00, 0x00, 0xF8, 0x00, 0x07, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 83 | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE0, 0x03, 0xFF, 0x00, 0x1F, 84 | 0xF8, 0x00, 0xFF, 0xC0, 0x07, 0xFE, 0x00, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 85 | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE7, 86 | 0xFF, 0xF8, 0x7F, 0xFF, 0x0F, 0xFF, 0xE0, 0xFF, 0xF8, 0x00, 0x1F, 0x00, 87 | 0x03, 0xE0, 0x00, 0x7C, 0x00, 0x1F, 0x00, 0x03, 0xE0, 0x00, 0x7C, 0x00, 88 | 0x1F, 0x80, 0x03, 0xE0, 0x00, 0x7C, 0x00, 0x0F, 0x80, 0x03, 0xE0, 0x00, 89 | 0x7C, 0x00, 0x0F, 0x80, 0x01, 0xF0, 0x00, 0x7C, 0x00, 0x0F, 0x80, 0x01, 90 | 0xF0, 0x00, 0x7E, 0x00, 0x0F, 0x80, 0x01, 0xF0, 0x00, 0x1E, 0x00, 0x03, 91 | 0x80, 0x00, 0x30, 0x00, 0x02, 0x00, 0x00, 0x40, 0x00, 0xFF, 0xFF, 0xFF, 92 | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0x00, 93 | 0x7F, 0xE0, 0x03, 0xFF, 0x00, 0x1F, 0xF8, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 94 | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE0, 0x03, 95 | 0xFF, 0x00, 0x1F, 0xF8, 0x00, 0xFF, 0xC0, 0x07, 0xFE, 0x00, 0x3F, 0xFF, 96 | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 97 | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 98 | 0xFF, 0xFC, 0x00, 0x7F, 0xE0, 0x03, 0xFF, 0x00, 0x1F, 0xF8, 0x00, 0xFF, 99 | 0xC0, 0x07, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 100 | 0xFF, 0xFF, 0xFF, 0xE0, 0x00, 0x1F, 0x00, 0x00, 0xF8, 0x00, 0x07, 0xC0, 101 | 0x00, 0x3E, 0x3F, 0xFF, 0xF1, 0xFF, 0xFF, 0x9F, 0xFF, 0xFD, 0xFF, 0xFF, 102 | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 103 | 0x00, 0xFF, 0xFF, 0xFF, 0x80, 0xFF, 0xFF, 0xFF, 0x80, 0x00, 0x00, 0x00, 104 | 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xDC, 0xC4, 0x20, 0x00, 0x08, 105 | 0x01, 0xC0, 0x3E, 0x03, 0xF0, 0x7F, 0x87, 0xF0, 0xFF, 0x1F, 0xE0, 0xFC, 106 | 0x07, 0xC0, 0x38, 0x01, 0xF0, 0x0F, 0xC0, 0x7F, 0x80, 0xFF, 0x01, 0xFC, 107 | 0x07, 0xF8, 0x0F, 0xC0, 0x1E, 0x00, 0x70, 0x00, 0x80, 0xFF, 0xFF, 0xFF, 108 | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0x00, 0x00, 0x3F, 109 | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 110 | 0x80, 0x07, 0x00, 0x3E, 0x01, 0xF8, 0x0F, 0xF0, 0x1F, 0xC0, 0x7F, 0x80, 111 | 0xFF, 0x01, 0xF8, 0x07, 0xC0, 0x0E, 0x01, 0xF0, 0x1F, 0x83, 0xFC, 0x7F, 112 | 0x87, 0xF0, 0xFF, 0x07, 0xE0, 0x3C, 0x01, 0xC0, 0x08, 0x00, 0x00, 0xFF, 113 | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0x00, 114 | 0x07, 0xC0, 0x00, 0xF8, 0x00, 0x1F, 0x00, 0x03, 0xE0, 0x3F, 0xFC, 0x07, 115 | 0xFF, 0x80, 0xFF, 0xF0, 0x1F, 0xFE, 0x03, 0xFF, 0xC0, 0x00, 0x00, 0x00, 116 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x1F, 117 | 0x00, 0x03, 0xE0, 0x00, 0x7C, 0x00, 0x0F, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 118 | 0xFF, 0xFF, 0xFF, 0xFE, 0x00, 0x07, 0xE0, 0x00, 0x7E, 0x3F, 0xC7, 0xE3, 119 | 0xFC, 0x7E, 0x30, 0xC7, 0xE3, 0x3C, 0x7E, 0x37, 0xC7, 0xE3, 0xEC, 0x7E, 120 | 0x3C, 0xC7, 0xE3, 0x8C, 0x7E, 0x38, 0xC7, 0xE3, 0x00, 0x7E, 0x20, 0x07, 121 | 0xE4, 0x00, 0x7E, 0x00, 0x07, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 122 | 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 123 | 0xFF, 0xFF, 0xFC, 0x00, 0x7F, 0xE0, 0x03, 0xFF, 0x03, 0x1F, 0xF8, 0x3C, 124 | 0xFF, 0xC1, 0xF7, 0xFE, 0x1F, 0xFF, 0xF1, 0xFD, 0xFF, 0x9F, 0xCF, 0xFD, 125 | 0xFC, 0x7F, 0xEF, 0xC3, 0xFF, 0xFC, 0x1F, 0xFF, 0xE0, 0xFF, 0xFE, 0x07, 126 | 0xFF, 0xE0, 0x3F, 0xFE, 0x01, 0xFF, 0xF0, 0x0F, 0xFF, 0x00, 0x7F, 0xF0, 127 | 0x03, 0xFF, 0x00, 0x1F, 0xF8, 0x00, 0x07, 0x80, 0x00, 0x38, 0x00, 0x01, 128 | 0x80, 0x00, 0x08, 0x00, 0x00, 0x40, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 129 | 0xFF, 0xBF, 0xFF, 0xFD, 0xFF, 0xFF, 0xCF, 0xFF, 0xFC, 0x7C, 0x03, 0xE3, 130 | 0xE0, 0x3E, 0x1F, 0x03, 0xE0, 0xF8, 0x7F, 0xFF, 0xC3, 0xFF, 0xFE, 0x1F, 131 | 0xFF, 0xF0, 0xFF, 0xFF, 0x87, 0xFF, 0xFC, 0x01, 0xFF, 0xE0, 0x0F, 0xDF, 132 | 0x00, 0xFC, 0xF8, 0x0F, 0xC7, 0xC0, 0xFE, 0x3E, 0x07, 0xE1, 0xF0, 0x7E, 133 | 0x0F, 0x87, 0xE0, 0x7C, 0x7F, 0x03, 0xE3, 0xF0, 0x1F, 0x3F, 0x00, 0x03, 134 | 0xF0, 0x00, 0x3F, 0x80, 0x01, 0xF8, 0x00, 0x1F, 0x80, 0x00, 0xF8, 0x00, 135 | 0x03, 0xC0, 0x00, 0x04, 0x00, 0x00, 0x07, 0xFF, 0xF1, 0xFF, 0xFE, 0x3F, 136 | 0xFF, 0xC7, 0xFF, 0xF8, 0xFF, 0xFF, 0x0F, 0xC0, 0x00, 0xF8, 0x00, 0x0F, 137 | 0x80, 0x00, 0xF8, 0x00, 0x0F, 0x80, 0x00, 0xF8, 0x00, 0x0F, 0x80, 0x00, 138 | 0xF8, 0x00, 0x0F, 0x80, 0x00, 0xF8, 0x00, 0x0F, 0x80, 0x3E, 0xF8, 0x03, 139 | 0xEF, 0x80, 0x3E, 0xF8, 0x03, 0xEF, 0xFF, 0xFE, 0xFF, 0xFF, 0xEF, 0xFF, 140 | 0xFE, 0xFF, 0xFF, 0xEF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 141 | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x07, 0xFE, 0x00, 0xFF, 0xC0, 142 | 0x1F, 0xF8, 0x03, 0xFF, 0x00, 0x7F, 0xE0, 0x0F, 0xFC, 0x01, 0xFF, 0x80, 143 | 0x3F, 0xF0, 0x07, 0xFE, 0x00, 0xFF, 0xC0, 0x1F, 0xF8, 0x03, 0xFF, 0x00, 144 | 0x7F, 0xE0, 0x1F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFD, 0xFF, 0xFF, 0x3F, 0xFF, 145 | 0xC7, 0xFF, 0xE0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 146 | 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 147 | 0xFC, 0xFF, 0xF0, 0xFF, 0xE0, 0xFF, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 148 | 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 149 | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 150 | 0xFF, 0xFF, 0xFE, 0x00, 0x0F, 0x80, 0x03, 0xE0, 0x00, 0xF8, 0x00, 0x3F, 151 | 0xFF, 0xFF, 0xFF, 0xF3, 0xFF, 0xF8, 0xFF, 0xF8, 0x3F, 0xFC, 0x0F, 0x80, 152 | 0x03, 0xE0, 0x00, 0xF8, 0x00, 0x3E, 0x00, 0x0F, 0x80, 0x03, 0xE0, 0x00, 153 | 0xF8, 0x00, 0x3E, 0x00, 0x0F, 0x80, 0x03, 0xE0, 0x00, 0x07, 0xFF, 0xF1, 154 | 0xFF, 0xFE, 0x3F, 0xFF, 0xC7, 0xFF, 0xF8, 0xFF, 0xFF, 0x0F, 0xC0, 0x00, 155 | 0xF8, 0x00, 0x0F, 0x80, 0x00, 0xF8, 0x1F, 0xFF, 0x83, 0xFF, 0xF8, 0x7F, 156 | 0xFF, 0x8F, 0xFF, 0xF9, 0xFF, 0xFF, 0xA0, 0x1F, 0xF8, 0x01, 0xFF, 0x80, 157 | 0x1F, 0xF8, 0x01, 0xFF, 0x80, 0x1F, 0xF8, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 158 | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x08, 159 | 0x00, 0x00, 0x40, 0x00, 0x06, 0x00, 0x00, 0x70, 0x00, 0x07, 0x80, 0x00, 160 | 0x7F, 0xE0, 0x03, 0xFF, 0x00, 0x1F, 0xF8, 0x00, 0xFF, 0xC0, 0x07, 0xFE, 161 | 0x00, 0x3F, 0xF0, 0x01, 0xFF, 0x80, 0x0F, 0xFC, 0x00, 0x7F, 0xE0, 0x03, 162 | 0xFF, 0x00, 0x1F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 163 | 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0x00, 0x7F, 0xE0, 0x03, 0xFF, 0x00, 0x1F, 164 | 0xF8, 0x00, 0xFF, 0xC0, 0x07, 0xFE, 0x00, 0x3F, 0xF0, 0x01, 0xFF, 0x80, 165 | 0x0F, 0xFC, 0x00, 0x7F, 0xE0, 0x00, 0x0F, 0x00, 0x00, 0x38, 0x00, 0x00, 166 | 0xC0, 0x00, 0x02, 0x00, 0x00, 0x10, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 167 | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFB, 168 | 0xDE, 0x71, 0x84, 0x20, 0x7F, 0xFE, 0x7F, 0xFC, 0x7F, 0xF8, 0x7F, 0xF0, 169 | 0x7F, 0xE0, 0x07, 0xC0, 0x0F, 0x80, 0x1F, 0x00, 0x3E, 0x00, 0x7C, 0x00, 170 | 0xF8, 0x01, 0xF0, 0x03, 0xF0, 0x07, 0xE0, 0x0F, 0xE0, 0x1F, 0xE0, 0x3F, 171 | 0xE0, 0x7F, 0xE0, 0xFF, 0xC1, 0xFF, 0x83, 0xFF, 0x07, 0xFE, 0x0F, 0xFC, 172 | 0xFF, 0xFF, 0xFF, 0xFF, 0xFB, 0xFF, 0xC7, 0xFC, 0x0F, 0xE0, 0x1E, 0x00, 173 | 0x30, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x07, 0x00, 0x00, 0x3E, 0x00, 174 | 0x00, 0xFC, 0xF8, 0x07, 0xE3, 0xE0, 0x3F, 0x8F, 0x81, 0xFC, 0x3E, 0x0F, 175 | 0xE0, 0xF8, 0x7F, 0x03, 0xE3, 0xF8, 0x0F, 0x9F, 0xC0, 0x3E, 0xFE, 0x00, 176 | 0xFF, 0xF0, 0x03, 0xFF, 0x80, 0x0F, 0xFC, 0x00, 0x3F, 0xF8, 0x00, 0xFF, 177 | 0xE0, 0x03, 0xFF, 0xC0, 0x0F, 0xFF, 0x80, 0x3F, 0x7F, 0x00, 0xF8, 0xFC, 178 | 0x03, 0xE1, 0xF8, 0x0F, 0x87, 0xF0, 0x3E, 0x0F, 0xC0, 0xF8, 0x1F, 0x83, 179 | 0xE0, 0x7F, 0x0F, 0x80, 0xFC, 0x3E, 0x01, 0xF8, 0xF8, 0x03, 0xF1, 0xE0, 180 | 0x0F, 0xC3, 0x80, 0x1F, 0x86, 0x00, 0x3F, 0x18, 0x00, 0xFC, 0x20, 0x01, 181 | 0xE0, 0x80, 0x02, 0x00, 0x80, 0x00, 0x38, 0x00, 0x0F, 0x80, 0x03, 0xE0, 182 | 0x00, 0xF8, 0x00, 0x3E, 0x00, 0x0F, 0x80, 0x03, 0xE0, 0x00, 0xF8, 0x00, 183 | 0x3E, 0x00, 0x0F, 0x80, 0x03, 0xE0, 0x00, 0xF8, 0x00, 0x3E, 0x00, 0x0F, 184 | 0x80, 0x03, 0xE0, 0x00, 0xF8, 0x00, 0x3E, 0x00, 0x0F, 0x80, 0x03, 0xE0, 185 | 0x00, 0xF8, 0x00, 0x3E, 0x00, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 186 | 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0x80, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x70, 187 | 0x00, 0x00, 0x7C, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x7F, 0xC0, 0x00, 0x7F, 188 | 0xE0, 0x00, 0x3F, 0xF8, 0x00, 0x3F, 0xFE, 0x00, 0x3F, 0xFF, 0x80, 0x3F, 189 | 0xFF, 0xC0, 0x1F, 0xFF, 0xF0, 0x1F, 0xFF, 0xFC, 0x1F, 0xFF, 0xFE, 0x1F, 190 | 0xFF, 0xFF, 0x8F, 0xFF, 0xF7, 0xEF, 0xDF, 0xFB, 0xFF, 0xEF, 0xFC, 0xFF, 191 | 0xE7, 0xFE, 0x3F, 0xE3, 0xFF, 0x0F, 0xE1, 0xFF, 0x87, 0xF0, 0xFF, 0xC1, 192 | 0xF0, 0x7F, 0xE0, 0x70, 0x3F, 0xF0, 0x10, 0x1F, 0xF8, 0x00, 0x0F, 0xFC, 193 | 0x00, 0x07, 0xFE, 0x00, 0x03, 0xE0, 0x80, 0x00, 0x10, 0x00, 0x03, 0x00, 194 | 0x00, 0x70, 0x01, 0xFF, 0x00, 0x3F, 0xF0, 0x07, 0xFE, 0x00, 0xFF, 0xE0, 195 | 0x1F, 0xFE, 0x03, 0xFF, 0xE0, 0x7F, 0xFE, 0x0F, 0xFF, 0xE1, 0xFF, 0xFE, 196 | 0x3F, 0xFF, 0xE7, 0xFE, 0xFE, 0xFF, 0xCF, 0xDF, 0xF8, 0xFF, 0xFF, 0x0F, 197 | 0xFF, 0xE1, 0xFF, 0xFC, 0x1F, 0xFF, 0x81, 0xFF, 0xF0, 0x1F, 0xFE, 0x01, 198 | 0xFF, 0xC0, 0x1F, 0xF8, 0x01, 0xFF, 0x00, 0x3F, 0xE0, 0x03, 0x80, 0x00, 199 | 0x30, 0x00, 0x02, 0x00, 0x00, 0x40, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 200 | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0x00, 0x7F, 0xE0, 0x03, 201 | 0xFF, 0x00, 0x1F, 0xF8, 0x00, 0xFF, 0xC0, 0x07, 0xFE, 0x00, 0x3F, 0xF0, 202 | 0x01, 0xFF, 0x80, 0x0F, 0xFC, 0x00, 0x7F, 0xE0, 0x03, 0xFF, 0x00, 0x1F, 203 | 0xF8, 0x00, 0xFF, 0xC0, 0x07, 0xFE, 0x00, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 204 | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 205 | 0xFF, 0xFF, 0xEF, 0xFF, 0xFF, 0xBF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFB, 0xE0, 206 | 0x03, 0xEF, 0x80, 0x1F, 0xBE, 0x00, 0x7C, 0xF8, 0x01, 0xF3, 0xE0, 0x07, 207 | 0xCF, 0xFF, 0xFF, 0x3F, 0xFF, 0xFC, 0xFF, 0xFF, 0xF3, 0xFF, 0xFF, 0x8F, 208 | 0xFF, 0xFE, 0x3E, 0x00, 0x00, 0xF8, 0x00, 0x03, 0xE0, 0x00, 0x0F, 0x80, 209 | 0x00, 0x3E, 0x00, 0x00, 0xF8, 0x00, 0x03, 0xE0, 0x00, 0x0F, 0x80, 0x00, 210 | 0x3E, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 211 | 0xFF, 0xFF, 0xFF, 0xF0, 0x07, 0xFE, 0x00, 0xFF, 0xC0, 0x1F, 0xF8, 0x03, 212 | 0xFF, 0x00, 0x7F, 0xE0, 0x0F, 0xFC, 0x01, 0xFF, 0x80, 0x3F, 0xF0, 0x07, 213 | 0xFE, 0x00, 0xFF, 0xC0, 0x1F, 0xF8, 0x03, 0xFF, 0x00, 0x7F, 0xF0, 0x0F, 214 | 0xFF, 0xFF, 0xF7, 0xFF, 0xFE, 0x7F, 0xFF, 0xC7, 0xFF, 0xF8, 0x3F, 0xFF, 215 | 0x03, 0xFC, 0x00, 0x3F, 0xC0, 0x03, 0xFC, 0x00, 0x1F, 0xE0, 0x01, 0xF8, 216 | 0x00, 0x1E, 0x00, 0x01, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xEF, 0xFF, 217 | 0xFF, 0xBF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFB, 0xE0, 0x03, 0xEF, 0x80, 0x1F, 218 | 0xBE, 0x00, 0x7C, 0xF8, 0x01, 0xF3, 0xE0, 0x07, 0xCF, 0xBF, 0xFF, 0x3E, 219 | 0x7F, 0xFC, 0xF8, 0xFF, 0xF3, 0xE3, 0xFF, 0x8F, 0x87, 0xFE, 0x3E, 0x1F, 220 | 0x00, 0xF8, 0x3E, 0x03, 0xE0, 0xFC, 0x0F, 0x81, 0xF0, 0x3E, 0x03, 0xE0, 221 | 0xF8, 0x0F, 0x83, 0xE0, 0x1F, 0x0F, 0x80, 0x7E, 0x3E, 0x00, 0xF8, 0x00, 222 | 0x03, 0xE0, 0x00, 0x07, 0x00, 0x00, 0x08, 0x00, 0x00, 0x40, 0x03, 0xFF, 223 | 0xFE, 0x0F, 0xFF, 0xF8, 0x1F, 0xFF, 0xE0, 0x7F, 0xFF, 0x81, 0xFF, 0xFE, 224 | 0x03, 0xF0, 0x00, 0x0F, 0xC0, 0x00, 0x1F, 0x00, 0x00, 0x7E, 0x00, 0x00, 225 | 0xFF, 0xFF, 0xFD, 0xFF, 0xFF, 0xFB, 0xFF, 0xFF, 0xF7, 0xFF, 0xFF, 0xEF, 226 | 0xFF, 0xFF, 0xC0, 0x00, 0x0F, 0x80, 0x00, 0x3F, 0x00, 0x00, 0x7C, 0x00, 227 | 0x01, 0xF8, 0x00, 0x07, 0xE0, 0xFF, 0xFF, 0x81, 0xFF, 0xFF, 0x07, 0xFF, 228 | 0xFC, 0x1F, 0xFF, 0xF8, 0x7F, 0xFF, 0xE0, 0x03, 0xFF, 0xFF, 0xE1, 0xFF, 229 | 0xFF, 0xF0, 0x7F, 0xFF, 0xFC, 0x1F, 0xFF, 0xFF, 0x0F, 0xFF, 0xFF, 0x80, 230 | 0x00, 0x3E, 0x00, 0x00, 0x07, 0xC0, 0x00, 0x00, 0xF8, 0x00, 0x00, 0x1F, 231 | 0x00, 0x00, 0x03, 0xE0, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x0F, 0x80, 0x00, 232 | 0x01, 0xF0, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x07, 0xC0, 0x00, 0x00, 0xF8, 233 | 0x00, 0x00, 0x1F, 0x00, 0x00, 0x03, 0xE0, 0x00, 0x00, 0x7C, 0x00, 0x00, 234 | 0x0F, 0x80, 0x00, 0x01, 0xF0, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x07, 0xC0, 235 | 0x00, 0x00, 0xF8, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x01, 0xE0, 0x00, 0x00, 236 | 0x1C, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x30, 0x00, 0x00, 0x02, 0x00, 237 | 0x00, 0xF8, 0x00, 0xFF, 0xC0, 0x07, 0xFE, 0x00, 0x3F, 0xF0, 0x01, 0xFF, 238 | 0x80, 0x0F, 0xFC, 0x00, 0x7F, 0xE0, 0x03, 0xFF, 0x00, 0x1F, 0xF8, 0x00, 239 | 0xFF, 0xC0, 0x07, 0xFE, 0x00, 0x3F, 0xF0, 0x01, 0xFF, 0x80, 0x0F, 0xFC, 240 | 0x00, 0x7F, 0xE0, 0x03, 0xFF, 0x00, 0x1F, 0xF8, 0x00, 0xFF, 0xC0, 0x07, 241 | 0xFE, 0x00, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 242 | 0xFF, 0xFF, 0xFF, 0xFF, 0xF8, 0x00, 0x1F, 0x80, 0x01, 0xF8, 0x00, 0x3F, 243 | 0x80, 0x07, 0xF8, 0x00, 0xFF, 0x80, 0x1F, 0xF8, 0x03, 0xFF, 0x80, 0x7F, 244 | 0xF8, 0x07, 0xEF, 0x80, 0xFC, 0xF8, 0x1F, 0x8F, 0x83, 0xF0, 0xF8, 0x7F, 245 | 0x0F, 0x8F, 0xE0, 0xF9, 0xFC, 0x0F, 0xBF, 0x80, 0xFB, 0xF0, 0x0F, 0xFE, 246 | 0x00, 0xFF, 0xC0, 0x0F, 0xFC, 0x00, 0xFF, 0x80, 0x0F, 0xF0, 0x00, 0xFE, 247 | 0x00, 0x0F, 0xC0, 0x00, 0xF8, 0x00, 0x0F, 0x00, 0x00, 0xF0, 0x00, 0x0E, 248 | 0x00, 0x00, 0xC0, 0x00, 0x08, 0x00, 0x00, 0x80, 0x00, 0x00, 0xF8, 0x00, 249 | 0x0F, 0xFC, 0x00, 0x07, 0xFE, 0x02, 0x03, 0xFF, 0x01, 0x81, 0xFF, 0x81, 250 | 0xC0, 0xFF, 0xC1, 0xF0, 0x7F, 0xE1, 0xFC, 0x3F, 0xF1, 0xFF, 0x1F, 0xF8, 251 | 0xFF, 0x8F, 0xFC, 0xFF, 0xE7, 0xFE, 0xFF, 0xFB, 0xFF, 0xFE, 0xFF, 0xFF, 252 | 0xFE, 0x3F, 0xFF, 0xFE, 0x0F, 0xFF, 0xFF, 0x07, 0xFF, 0xFF, 0x01, 0xFF, 253 | 0xFF, 0x00, 0x7F, 0xFF, 0x00, 0x1F, 0xFF, 0x80, 0x0F, 0xFF, 0x80, 0x03, 254 | 0xFF, 0x80, 0x00, 0xFF, 0x80, 0x00, 0x3F, 0xC0, 0x00, 0x1F, 0xC0, 0x00, 255 | 0x07, 0xC0, 0x00, 0x01, 0xC0, 0x00, 0x00, 0x60, 0x00, 0x00, 0x20, 0xFC, 256 | 0x00, 0x7F, 0x7E, 0x00, 0x7E, 0x3F, 0x00, 0xFC, 0x3F, 0x81, 0xFC, 0x1F, 257 | 0x83, 0xF8, 0x0F, 0xC3, 0xF0, 0x07, 0xE7, 0xE0, 0x07, 0xFF, 0xE0, 0x03, 258 | 0xFF, 0xC0, 0x01, 0xFF, 0x80, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 259 | 0x7E, 0x00, 0x00, 0xFF, 0x00, 0x01, 0xFF, 0x80, 0x03, 0xFF, 0xC0, 0x03, 260 | 0xFF, 0xC0, 0x07, 0xE7, 0xE0, 0x0F, 0xC3, 0xF0, 0x1F, 0xC3, 0xF8, 0x1F, 261 | 0x81, 0xF8, 0x3F, 0x00, 0xFC, 0x7E, 0x00, 0x7E, 0xFE, 0x00, 0x7F, 0xFE, 262 | 0x00, 0x7F, 0x7E, 0x00, 0x7E, 0x3F, 0x00, 0xFC, 0x1F, 0x81, 0xF8, 0x1F, 263 | 0xC3, 0xF8, 0x0F, 0xC3, 0xF0, 0x07, 0xE7, 0xE0, 0x03, 0xFF, 0xC0, 0x03, 264 | 0xFF, 0xC0, 0x01, 0xFF, 0x80, 0x00, 0xFF, 0x00, 0x00, 0x7E, 0x00, 0x00, 265 | 0x7E, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x7E, 0x00, 0x00, 266 | 0x7E, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x7E, 0x00, 0x00, 267 | 0x7E, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x7E, 0x00, 0x00, 268 | 0x7C, 0x00, 0x00, 0x78, 0x00, 0x00, 0x70, 0x00, 0x00, 0x40, 0x00, 0xFF, 269 | 0xFF, 0xDF, 0xFF, 0xFB, 0xFF, 0xFF, 0x7F, 0xFF, 0xEF, 0xFF, 0xFC, 0x00, 270 | 0x7F, 0x00, 0x0F, 0xC0, 0x03, 0xF8, 0x00, 0xFE, 0x00, 0x3F, 0x80, 0x07, 271 | 0xE0, 0x01, 0xFC, 0x00, 0x7F, 0x00, 0x1F, 0xC0, 0x03, 0xF0, 0x00, 0xFC, 272 | 0x00, 0x3F, 0x80, 0x0F, 0xE0, 0x01, 0xF8, 0x00, 0x7F, 0xFF, 0xFF, 0xFF, 273 | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xCF, 274 | 0xFE, 0x3F, 0xF0, 0xFF, 0x83, 0xE0, 0x0F, 0x80, 0x3E, 0x00, 0xF8, 0x03, 275 | 0xE0, 0x0F, 0x80, 0x3E, 0x00, 0xF8, 0x03, 0xE0, 0x0F, 0x80, 0x3E, 0x00, 276 | 0xF8, 0x03, 0xE0, 0x0F, 0x80, 0x3E, 0x00, 0xF8, 0x03, 0xE0, 0x0F, 0x80, 277 | 0x3E, 0x00, 0xF8, 0x03, 0xFE, 0x0F, 0xFC, 0x3F, 0xF8, 0xFF, 0xF3, 0xFF, 278 | 0xF0, 0x60, 0x03, 0x80, 0x0F, 0x00, 0x1C, 0x00, 0x70, 0x01, 0xE0, 0x03, 279 | 0x80, 0x0F, 0x00, 0x1C, 0x00, 0x70, 0x00, 0xE0, 0x03, 0x80, 0x0F, 0x00, 280 | 0x1C, 0x00, 0x78, 0x00, 0xE0, 0x03, 0x80, 0x0F, 0x00, 0x1C, 0x00, 0x78, 281 | 0x00, 0xE0, 0x03, 0xC0, 0x07, 0x00, 0x1C, 0x00, 0x78, 0x00, 0xE0, 0x03, 282 | 0xC0, 0x07, 0x00, 0x18, 0xFF, 0xFC, 0xFF, 0xF1, 0xFF, 0xC3, 0xFF, 0x07, 283 | 0xFC, 0x01, 0xF0, 0x07, 0xC0, 0x1F, 0x00, 0x7C, 0x01, 0xF0, 0x07, 0xC0, 284 | 0x1F, 0x00, 0x7C, 0x01, 0xF0, 0x07, 0xC0, 0x1F, 0x00, 0x7C, 0x01, 0xF0, 285 | 0x07, 0xC0, 0x1F, 0x00, 0x7C, 0x01, 0xF0, 0x07, 0xC0, 0x1F, 0x00, 0x7C, 286 | 0x1F, 0xF0, 0xFF, 0xC7, 0xFF, 0x3F, 0xFF, 0xFF, 0xF0, 0x01, 0xF8, 0x00, 287 | 0x3F, 0x80, 0x03, 0xFC, 0x00, 0x7F, 0xE0, 0x0F, 0x9E, 0x00, 0xF1, 0xF0, 288 | 0x1F, 0x0F, 0x01, 0xE0, 0xF8, 0x3E, 0x07, 0xC7, 0xC0, 0x3C, 0x78, 0x03, 289 | 0xEF, 0x80, 0x1E, 0xF0, 0x01, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 290 | 0xE0, 0xF1, 0xE3, 0x8F, 0x1C, 0x30, 0xC1, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 291 | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0x00, 0x7F, 0xE0, 292 | 0x03, 0xFF, 0x03, 0x1F, 0xF8, 0x3C, 0xFF, 0xC1, 0xF7, 0xFE, 0x1F, 0xFF, 293 | 0xF1, 0xFD, 0xFF, 0x9F, 0xCF, 0xFD, 0xFC, 0x7F, 0xEF, 0xC3, 0xFF, 0xFC, 294 | 0x1F, 0xFF, 0xE0, 0xFF, 0xFE, 0x07, 0xFF, 0xE0, 0x3F, 0xFE, 0x01, 0xFF, 295 | 0xF0, 0x0F, 0xFF, 0x00, 0x7F, 0xF0, 0x03, 0xFF, 0x00, 0x1F, 0xF8, 0x00, 296 | 0x07, 0x80, 0x00, 0x38, 0x00, 0x01, 0x80, 0x00, 0x08, 0x00, 0x00, 0x40, 297 | 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xBF, 0xFF, 0xFD, 0xFF, 0xFF, 298 | 0xCF, 0xFF, 0xFC, 0x7C, 0x03, 0xE3, 0xE0, 0x3E, 0x1F, 0x03, 0xE0, 0xF8, 299 | 0x7F, 0xFF, 0xC3, 0xFF, 0xFE, 0x1F, 0xFF, 0xF0, 0xFF, 0xFF, 0x87, 0xFF, 300 | 0xFC, 0x01, 0xFF, 0xE0, 0x0F, 0xDF, 0x00, 0xFC, 0xF8, 0x0F, 0xC7, 0xC0, 301 | 0xFE, 0x3E, 0x07, 0xE1, 0xF0, 0x7E, 0x0F, 0x87, 0xE0, 0x7C, 0x7F, 0x03, 302 | 0xE3, 0xF0, 0x1F, 0x3F, 0x00, 0x03, 0xF0, 0x00, 0x3F, 0x80, 0x01, 0xF8, 303 | 0x00, 0x1F, 0x80, 0x00, 0xF8, 0x00, 0x03, 0xC0, 0x00, 0x04, 0x00, 0x00, 304 | 0x07, 0xFF, 0xF1, 0xFF, 0xFE, 0x3F, 0xFF, 0xC7, 0xFF, 0xF8, 0xFF, 0xFF, 305 | 0x0F, 0xC0, 0x00, 0xF8, 0x00, 0x0F, 0x80, 0x00, 0xF8, 0x00, 0x0F, 0x80, 306 | 0x00, 0xF8, 0x00, 0x0F, 0x80, 0x00, 0xF8, 0x00, 0x0F, 0x80, 0x00, 0xF8, 307 | 0x00, 0x0F, 0x80, 0x3E, 0xF8, 0x03, 0xEF, 0x80, 0x3E, 0xF8, 0x03, 0xEF, 308 | 0xFF, 0xFE, 0xFF, 0xFF, 0xEF, 0xFF, 0xFE, 0xFF, 0xFF, 0xEF, 0xFF, 0xFE, 309 | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 310 | 0xF0, 0x07, 0xFE, 0x00, 0xFF, 0xC0, 0x1F, 0xF8, 0x03, 0xFF, 0x00, 0x7F, 311 | 0xE0, 0x0F, 0xFC, 0x01, 0xFF, 0x80, 0x3F, 0xF0, 0x07, 0xFE, 0x00, 0xFF, 312 | 0xC0, 0x1F, 0xF8, 0x03, 0xFF, 0x00, 0x7F, 0xE0, 0x1F, 0xFF, 0xFF, 0xFF, 313 | 0xFF, 0xFD, 0xFF, 0xFF, 0x3F, 0xFF, 0xC7, 0xFF, 0xE0, 0xFF, 0xFF, 0xFF, 314 | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 315 | 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFC, 0xFF, 0xF0, 0xFF, 0xE0, 0xFF, 316 | 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 317 | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 318 | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0x00, 0x0F, 0x80, 319 | 0x03, 0xE0, 0x00, 0xF8, 0x00, 0x3F, 0xFF, 0xFF, 0xFF, 0xF3, 0xFF, 0xF8, 320 | 0xFF, 0xF8, 0x3F, 0xFC, 0x0F, 0x80, 0x03, 0xE0, 0x00, 0xF8, 0x00, 0x3E, 321 | 0x00, 0x0F, 0x80, 0x03, 0xE0, 0x00, 0xF8, 0x00, 0x3E, 0x00, 0x0F, 0x80, 322 | 0x03, 0xE0, 0x00, 0x07, 0xFF, 0xF1, 0xFF, 0xFE, 0x3F, 0xFF, 0xC7, 0xFF, 323 | 0xF8, 0xFF, 0xFF, 0x0F, 0xC0, 0x00, 0xF8, 0x00, 0x0F, 0x80, 0x00, 0xF8, 324 | 0x1F, 0xFF, 0x83, 0xFF, 0xF8, 0x7F, 0xFF, 0x8F, 0xFF, 0xF9, 0xFF, 0xFF, 325 | 0xA0, 0x1F, 0xF8, 0x01, 0xFF, 0x80, 0x1F, 0xF8, 0x01, 0xFF, 0x80, 0x1F, 326 | 0xF8, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 327 | 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x08, 0x00, 0x00, 0x40, 0x00, 0x06, 0x00, 328 | 0x00, 0x70, 0x00, 0x07, 0x80, 0x00, 0x7F, 0xE0, 0x03, 0xFF, 0x00, 0x1F, 329 | 0xF8, 0x00, 0xFF, 0xC0, 0x07, 0xFE, 0x00, 0x3F, 0xF0, 0x01, 0xFF, 0x80, 330 | 0x0F, 0xFC, 0x00, 0x7F, 0xE0, 0x03, 0xFF, 0x00, 0x1F, 0xFF, 0xFF, 0xFF, 331 | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0x00, 332 | 0x7F, 0xE0, 0x03, 0xFF, 0x00, 0x1F, 0xF8, 0x00, 0xFF, 0xC0, 0x07, 0xFE, 333 | 0x00, 0x3F, 0xF0, 0x01, 0xFF, 0x80, 0x0F, 0xFC, 0x00, 0x7F, 0xE0, 0x00, 334 | 0x0F, 0x00, 0x00, 0x38, 0x00, 0x00, 0xC0, 0x00, 0x02, 0x00, 0x00, 0x10, 335 | 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 336 | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFB, 0xDE, 0x71, 0x84, 0x20, 0x7F, 0xFE, 337 | 0x7F, 0xFC, 0x7F, 0xF8, 0x7F, 0xF0, 0x7F, 0xE0, 0x07, 0xC0, 0x0F, 0x80, 338 | 0x1F, 0x00, 0x3E, 0x00, 0x7C, 0x00, 0xF8, 0x01, 0xF0, 0x03, 0xF0, 0x07, 339 | 0xE0, 0x0F, 0xE0, 0x1F, 0xE0, 0x3F, 0xE0, 0x7F, 0xE0, 0xFF, 0xC1, 0xFF, 340 | 0x83, 0xFF, 0x07, 0xFE, 0x0F, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFB, 0xFF, 341 | 0xC7, 0xFC, 0x0F, 0xE0, 0x1E, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x80, 342 | 0x00, 0x07, 0x00, 0x00, 0x3E, 0x00, 0x00, 0xFC, 0xF8, 0x07, 0xE3, 0xE0, 343 | 0x3F, 0x8F, 0x81, 0xFC, 0x3E, 0x0F, 0xE0, 0xF8, 0x7F, 0x03, 0xE3, 0xF8, 344 | 0x0F, 0x9F, 0xC0, 0x3E, 0xFE, 0x00, 0xFF, 0xF0, 0x03, 0xFF, 0x80, 0x0F, 345 | 0xFC, 0x00, 0x3F, 0xF8, 0x00, 0xFF, 0xE0, 0x03, 0xFF, 0xC0, 0x0F, 0xFF, 346 | 0x80, 0x3F, 0x7F, 0x00, 0xF8, 0xFC, 0x03, 0xE1, 0xF8, 0x0F, 0x87, 0xF0, 347 | 0x3E, 0x0F, 0xC0, 0xF8, 0x1F, 0x83, 0xE0, 0x7F, 0x0F, 0x80, 0xFC, 0x3E, 348 | 0x01, 0xF8, 0xF8, 0x03, 0xF1, 0xE0, 0x0F, 0xC3, 0x80, 0x1F, 0x86, 0x00, 349 | 0x3F, 0x18, 0x00, 0xFC, 0x20, 0x01, 0xE0, 0x80, 0x02, 0x00, 0x80, 0x00, 350 | 0x38, 0x00, 0x0F, 0x80, 0x03, 0xE0, 0x00, 0xF8, 0x00, 0x3E, 0x00, 0x0F, 351 | 0x80, 0x03, 0xE0, 0x00, 0xF8, 0x00, 0x3E, 0x00, 0x0F, 0x80, 0x03, 0xE0, 352 | 0x00, 0xF8, 0x00, 0x3E, 0x00, 0x0F, 0x80, 0x03, 0xE0, 0x00, 0xF8, 0x00, 353 | 0x3E, 0x00, 0x0F, 0x80, 0x03, 0xE0, 0x00, 0xF8, 0x00, 0x3E, 0x00, 0x0F, 354 | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0x80, 355 | 0x00, 0x00, 0xC0, 0x00, 0x00, 0x70, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x7F, 356 | 0x00, 0x00, 0x7F, 0xC0, 0x00, 0x7F, 0xE0, 0x00, 0x3F, 0xF8, 0x00, 0x3F, 357 | 0xFE, 0x00, 0x3F, 0xFF, 0x80, 0x3F, 0xFF, 0xC0, 0x1F, 0xFF, 0xF0, 0x1F, 358 | 0xFF, 0xFC, 0x1F, 0xFF, 0xFE, 0x1F, 0xFF, 0xFF, 0x8F, 0xFF, 0xF7, 0xEF, 359 | 0xDF, 0xFB, 0xFF, 0xEF, 0xFC, 0xFF, 0xE7, 0xFE, 0x3F, 0xE3, 0xFF, 0x0F, 360 | 0xE1, 0xFF, 0x87, 0xF0, 0xFF, 0xC1, 0xF0, 0x7F, 0xE0, 0x70, 0x3F, 0xF0, 361 | 0x10, 0x1F, 0xF8, 0x00, 0x0F, 0xFC, 0x00, 0x07, 0xFE, 0x00, 0x03, 0xE0, 362 | 0x80, 0x00, 0x10, 0x00, 0x03, 0x00, 0x00, 0x70, 0x01, 0xFF, 0x00, 0x3F, 363 | 0xF0, 0x07, 0xFE, 0x00, 0xFF, 0xE0, 0x1F, 0xFE, 0x03, 0xFF, 0xE0, 0x7F, 364 | 0xFE, 0x0F, 0xFF, 0xE1, 0xFF, 0xFE, 0x3F, 0xFF, 0xE7, 0xFE, 0xFE, 0xFF, 365 | 0xCF, 0xDF, 0xF8, 0xFF, 0xFF, 0x0F, 0xFF, 0xE1, 0xFF, 0xFC, 0x1F, 0xFF, 366 | 0x81, 0xFF, 0xF0, 0x1F, 0xFE, 0x01, 0xFF, 0xC0, 0x1F, 0xF8, 0x01, 0xFF, 367 | 0x00, 0x3F, 0xE0, 0x03, 0x80, 0x00, 0x30, 0x00, 0x02, 0x00, 0x00, 0x40, 368 | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 369 | 0xFF, 0xFC, 0x00, 0x7F, 0xE0, 0x03, 0xFF, 0x00, 0x1F, 0xF8, 0x00, 0xFF, 370 | 0xC0, 0x07, 0xFE, 0x00, 0x3F, 0xF0, 0x01, 0xFF, 0x80, 0x0F, 0xFC, 0x00, 371 | 0x7F, 0xE0, 0x03, 0xFF, 0x00, 0x1F, 0xF8, 0x00, 0xFF, 0xC0, 0x07, 0xFE, 372 | 0x00, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 373 | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xEF, 0xFF, 0xFF, 0xBF, 374 | 0xFF, 0xFE, 0xFF, 0xFF, 0xFB, 0xE0, 0x03, 0xEF, 0x80, 0x1F, 0xBE, 0x00, 375 | 0x7C, 0xF8, 0x01, 0xF3, 0xE0, 0x07, 0xCF, 0xFF, 0xFF, 0x3F, 0xFF, 0xFC, 376 | 0xFF, 0xFF, 0xF3, 0xFF, 0xFF, 0x8F, 0xFF, 0xFE, 0x3E, 0x00, 0x00, 0xF8, 377 | 0x00, 0x03, 0xE0, 0x00, 0x0F, 0x80, 0x00, 0x3E, 0x00, 0x00, 0xF8, 0x00, 378 | 0x03, 0xE0, 0x00, 0x0F, 0x80, 0x00, 0x3E, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 379 | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x07, 0xFE, 380 | 0x00, 0xFF, 0xC0, 0x1F, 0xF8, 0x03, 0xFF, 0x00, 0x7F, 0xE0, 0x0F, 0xFC, 381 | 0x01, 0xFF, 0x80, 0x3F, 0xF0, 0x07, 0xFE, 0x00, 0xFF, 0xC0, 0x1F, 0xF8, 382 | 0x03, 0xFF, 0x00, 0x7F, 0xF0, 0x0F, 0xFF, 0xFF, 0xF7, 0xFF, 0xFE, 0x7F, 383 | 0xFF, 0xC7, 0xFF, 0xF8, 0x3F, 0xFF, 0x03, 0xFC, 0x00, 0x3F, 0xC0, 0x03, 384 | 0xFC, 0x00, 0x1F, 0xE0, 0x01, 0xF8, 0x00, 0x1E, 0x00, 0x01, 0x80, 0xFF, 385 | 0xFF, 0xFF, 0xFF, 0xFF, 0xEF, 0xFF, 0xFF, 0xBF, 0xFF, 0xFE, 0xFF, 0xFF, 386 | 0xFB, 0xE0, 0x03, 0xEF, 0x80, 0x1F, 0xBE, 0x00, 0x7C, 0xF8, 0x01, 0xF3, 387 | 0xE0, 0x07, 0xCF, 0xBF, 0xFF, 0x3E, 0x7F, 0xFC, 0xF8, 0xFF, 0xF3, 0xE3, 388 | 0xFF, 0x8F, 0x87, 0xFE, 0x3E, 0x1F, 0x00, 0xF8, 0x3E, 0x03, 0xE0, 0xFC, 389 | 0x0F, 0x81, 0xF0, 0x3E, 0x03, 0xE0, 0xF8, 0x0F, 0x83, 0xE0, 0x1F, 0x0F, 390 | 0x80, 0x7E, 0x3E, 0x00, 0xF8, 0x00, 0x03, 0xE0, 0x00, 0x07, 0x00, 0x00, 391 | 0x08, 0x00, 0x00, 0x40, 0x03, 0xFF, 0xFE, 0x0F, 0xFF, 0xF8, 0x1F, 0xFF, 392 | 0xE0, 0x7F, 0xFF, 0x81, 0xFF, 0xFE, 0x03, 0xF0, 0x00, 0x0F, 0xC0, 0x00, 393 | 0x1F, 0x00, 0x00, 0x7E, 0x00, 0x00, 0xFF, 0xFF, 0xFD, 0xFF, 0xFF, 0xFB, 394 | 0xFF, 0xFF, 0xF7, 0xFF, 0xFF, 0xEF, 0xFF, 0xFF, 0xC0, 0x00, 0x0F, 0x80, 395 | 0x00, 0x3F, 0x00, 0x00, 0x7C, 0x00, 0x01, 0xF8, 0x00, 0x07, 0xE0, 0xFF, 396 | 0xFF, 0x81, 0xFF, 0xFF, 0x07, 0xFF, 0xFC, 0x1F, 0xFF, 0xF8, 0x7F, 0xFF, 397 | 0xE0, 0x03, 0xFF, 0xFF, 0xE1, 0xFF, 0xFF, 0xF0, 0x7F, 0xFF, 0xFC, 0x1F, 398 | 0xFF, 0xFF, 0x0F, 0xFF, 0xFF, 0x80, 0x00, 0x3E, 0x00, 0x00, 0x07, 0xC0, 399 | 0x00, 0x00, 0xF8, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x03, 0xE0, 0x00, 0x00, 400 | 0x7C, 0x00, 0x00, 0x0F, 0x80, 0x00, 0x01, 0xF0, 0x00, 0x00, 0x3E, 0x00, 401 | 0x00, 0x07, 0xC0, 0x00, 0x00, 0xF8, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x03, 402 | 0xE0, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x0F, 0x80, 0x00, 0x01, 0xF0, 0x00, 403 | 0x00, 0x3E, 0x00, 0x00, 0x07, 0xC0, 0x00, 0x00, 0xF8, 0x00, 0x00, 0x1F, 404 | 0x00, 0x00, 0x01, 0xE0, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x01, 0x80, 0x00, 405 | 0x00, 0x30, 0x00, 0x00, 0x02, 0x00, 0x00, 0xF8, 0x00, 0xFF, 0xC0, 0x07, 406 | 0xFE, 0x00, 0x3F, 0xF0, 0x01, 0xFF, 0x80, 0x0F, 0xFC, 0x00, 0x7F, 0xE0, 407 | 0x03, 0xFF, 0x00, 0x1F, 0xF8, 0x00, 0xFF, 0xC0, 0x07, 0xFE, 0x00, 0x3F, 408 | 0xF0, 0x01, 0xFF, 0x80, 0x0F, 0xFC, 0x00, 0x7F, 0xE0, 0x03, 0xFF, 0x00, 409 | 0x1F, 0xF8, 0x00, 0xFF, 0xC0, 0x07, 0xFE, 0x00, 0x3F, 0xFF, 0xFF, 0xFF, 410 | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF8, 0x00, 411 | 0x1F, 0x80, 0x01, 0xF8, 0x00, 0x3F, 0x80, 0x07, 0xF8, 0x00, 0xFF, 0x80, 412 | 0x1F, 0xF8, 0x03, 0xFF, 0x80, 0x7F, 0xF8, 0x07, 0xEF, 0x80, 0xFC, 0xF8, 413 | 0x1F, 0x8F, 0x83, 0xF0, 0xF8, 0x7F, 0x0F, 0x8F, 0xE0, 0xF9, 0xFC, 0x0F, 414 | 0xBF, 0x80, 0xFB, 0xF0, 0x0F, 0xFE, 0x00, 0xFF, 0xC0, 0x0F, 0xFC, 0x00, 415 | 0xFF, 0x80, 0x0F, 0xF0, 0x00, 0xFE, 0x00, 0x0F, 0xC0, 0x00, 0xF8, 0x00, 416 | 0x0F, 0x00, 0x00, 0xF0, 0x00, 0x0E, 0x00, 0x00, 0xC0, 0x00, 0x08, 0x00, 417 | 0x00, 0x80, 0x00, 0x00, 0xF8, 0x00, 0x0F, 0xFC, 0x00, 0x07, 0xFE, 0x02, 418 | 0x03, 0xFF, 0x01, 0x81, 0xFF, 0x81, 0xC0, 0xFF, 0xC1, 0xF0, 0x7F, 0xE1, 419 | 0xFC, 0x3F, 0xF1, 0xFF, 0x1F, 0xF8, 0xFF, 0x8F, 0xFC, 0xFF, 0xE7, 0xFE, 420 | 0xFF, 0xFB, 0xFF, 0xFE, 0xFF, 0xFF, 0xFE, 0x3F, 0xFF, 0xFE, 0x0F, 0xFF, 421 | 0xFF, 0x07, 0xFF, 0xFF, 0x01, 0xFF, 0xFF, 0x00, 0x7F, 0xFF, 0x00, 0x1F, 422 | 0xFF, 0x80, 0x0F, 0xFF, 0x80, 0x03, 0xFF, 0x80, 0x00, 0xFF, 0x80, 0x00, 423 | 0x3F, 0xC0, 0x00, 0x1F, 0xC0, 0x00, 0x07, 0xC0, 0x00, 0x01, 0xC0, 0x00, 424 | 0x00, 0x60, 0x00, 0x00, 0x20, 0xFC, 0x00, 0x7F, 0x7E, 0x00, 0x7E, 0x3F, 425 | 0x00, 0xFC, 0x3F, 0x81, 0xFC, 0x1F, 0x83, 0xF8, 0x0F, 0xC3, 0xF0, 0x07, 426 | 0xE7, 0xE0, 0x07, 0xFF, 0xE0, 0x03, 0xFF, 0xC0, 0x01, 0xFF, 0x80, 0x00, 427 | 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x7E, 0x00, 0x00, 0xFF, 0x00, 0x01, 428 | 0xFF, 0x80, 0x03, 0xFF, 0xC0, 0x03, 0xFF, 0xC0, 0x07, 0xE7, 0xE0, 0x0F, 429 | 0xC3, 0xF0, 0x1F, 0xC3, 0xF8, 0x1F, 0x81, 0xF8, 0x3F, 0x00, 0xFC, 0x7E, 430 | 0x00, 0x7E, 0xFE, 0x00, 0x7F, 0xFE, 0x00, 0x7F, 0x7E, 0x00, 0x7E, 0x3F, 431 | 0x00, 0xFC, 0x1F, 0x81, 0xF8, 0x1F, 0xC3, 0xF8, 0x0F, 0xC3, 0xF0, 0x07, 432 | 0xE7, 0xE0, 0x03, 0xFF, 0xC0, 0x03, 0xFF, 0xC0, 0x01, 0xFF, 0x80, 0x00, 433 | 0xFF, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x7E, 0x00, 0x00, 434 | 0x7E, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x7E, 0x00, 0x00, 435 | 0x7E, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x7E, 0x00, 0x00, 436 | 0x7E, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x78, 0x00, 0x00, 437 | 0x70, 0x00, 0x00, 0x40, 0x00, 0xFF, 0xFF, 0xDF, 0xFF, 0xFB, 0xFF, 0xFF, 438 | 0x7F, 0xFF, 0xEF, 0xFF, 0xFC, 0x00, 0x7F, 0x00, 0x0F, 0xC0, 0x03, 0xF8, 439 | 0x00, 0xFE, 0x00, 0x3F, 0x80, 0x07, 0xE0, 0x01, 0xFC, 0x00, 0x7F, 0x00, 440 | 0x1F, 0xC0, 0x03, 0xF0, 0x00, 0xFC, 0x00, 0x3F, 0x80, 0x0F, 0xE0, 0x01, 441 | 0xF8, 0x00, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 442 | 0xFF, 0xFF, 0x00, 0xFF, 0xE0, 0x7F, 0xF8, 0x1F, 0xFE, 0x07, 0xFF, 0x01, 443 | 0xFF, 0xC0, 0x3F, 0x00, 0x07, 0xC0, 0x00, 0xF8, 0x00, 0x1F, 0x00, 0x03, 444 | 0xE0, 0x00, 0x7C, 0x00, 0x0F, 0x80, 0x0F, 0xF0, 0x01, 0xFE, 0x00, 0x3F, 445 | 0xC0, 0x07, 0xF8, 0x00, 0xFF, 0x00, 0x03, 0xE0, 0x00, 0x7C, 0x00, 0x0F, 446 | 0x80, 0x01, 0xF0, 0x00, 0x3E, 0x00, 0x07, 0xC0, 0x00, 0xF8, 0x00, 0x1F, 447 | 0x80, 0x03, 0xFF, 0x80, 0x3F, 0xF8, 0x03, 0xFF, 0xC0, 0x1F, 0xFC, 0x01, 448 | 0xFF, 0xC0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0xFF, 449 | 0xE0, 0x0F, 0xFF, 0x00, 0xFF, 0xF0, 0x07, 0xFF, 0x00, 0x7F, 0xF0, 0x00, 450 | 0x7E, 0x00, 0x07, 0xC0, 0x00, 0xF8, 0x00, 0x1F, 0x00, 0x03, 0xE0, 0x00, 451 | 0x7C, 0x00, 0x0F, 0x80, 0x01, 0xFE, 0x00, 0x3F, 0xC0, 0x07, 0xF8, 0x00, 452 | 0xFF, 0x00, 0x1F, 0xE0, 0x03, 0xE0, 0x00, 0x7C, 0x00, 0x0F, 0x80, 0x01, 453 | 0xF0, 0x00, 0x3E, 0x00, 0x07, 0xC0, 0x00, 0xF8, 0x00, 0x3F, 0x00, 0xFF, 454 | 0xE0, 0x3F, 0xF8, 0x1F, 0xFE, 0x07, 0xFF, 0x01, 0xFF, 0xC0, 0x00, 0x3F, 455 | 0x00, 0x0F, 0xF8, 0x03, 0xFF, 0xC3, 0x30, 0xFF, 0xF4, 0x07, 0xFC, 0x00, 456 | 0x1F, 0x00 }; 457 | 458 | const GFXglyph Fun_Games20pt7bGlyphs[] PROGMEM = { 459 | { 0, 1, 1, 10, 0, 0 }, // 0x20 ' ' 460 | { 1, 5, 26, 9, 2, -25 }, // 0x21 '!' 461 | { 18, 7, 7, 11, 2, -23 }, // 0x22 '"' 462 | { 25, 22, 28, 25, 2, -25 }, // 0x23 '#' 463 | { 102, 24, 32, 27, 1, -27 }, // 0x24 '$' 464 | { 198, 15, 24, 18, 2, -23 }, // 0x25 '%' 465 | { 243, 22, 24, 25, 2, -23 }, // 0x26 '&' 466 | { 309, 3, 7, 6, 2, -23 }, // 0x27 ''' 467 | { 312, 16, 30, 19, 2, -23 }, // 0x28 '(' 468 | { 372, 16, 30, 20, 2, -23 }, // 0x29 ')' 469 | { 432, 10, 10, 13, 2, -24 }, // 0x2A '*' 470 | { 445, 21, 21, 23, 1, -23 }, // 0x2B '+' 471 | { 501, 5, 11, 9, 2, -4 }, // 0x2C ',' 472 | { 508, 13, 5, 17, 2, -12 }, // 0x2D '-' 473 | { 517, 5, 5, 9, 2, -4 }, // 0x2E '.' 474 | { 521, 14, 29, 18, 2, -27 }, // 0x2F '/' 475 | { 572, 21, 24, 25, 2, -23 }, // 0x30 '0' 476 | { 635, 10, 30, 14, 2, -23 }, // 0x31 '1' 477 | { 673, 23, 24, 27, 2, -23 }, // 0x32 '2' 478 | { 742, 19, 24, 23, 2, -23 }, // 0x33 '3' 479 | { 799, 19, 31, 23, 2, -23 }, // 0x34 '4' 480 | { 873, 23, 24, 27, 2, -23 }, // 0x35 '5' 481 | { 942, 21, 24, 25, 2, -23 }, // 0x36 '6' 482 | { 1005, 19, 30, 20, 0, -23 }, // 0x37 '7' 483 | { 1077, 21, 24, 25, 2, -23 }, // 0x38 '8' 484 | { 1140, 21, 24, 25, 2, -23 }, // 0x39 '9' 485 | { 1203, 5, 21, 9, 2, -20 }, // 0x3A ':' 486 | { 1217, 5, 27, 9, 2, -20 }, // 0x3B ';' 487 | { 1234, 13, 21, 16, 2, -23 }, // 0x3C '<' 488 | { 1269, 19, 11, 23, 2, -18 }, // 0x3D '=' 489 | { 1296, 13, 21, 16, 1, -23 }, // 0x3E '>' 490 | { 1331, 19, 24, 23, 2, -23 }, // 0x3F '?' 491 | { 1388, 20, 21, 24, 2, -23 }, // 0x40 '@' 492 | { 1441, 21, 30, 25, 2, -23 }, // 0x41 'A' 493 | { 1520, 21, 31, 25, 2, -23 }, // 0x42 'B' 494 | { 1602, 20, 24, 24, 2, -23 }, // 0x43 'C' 495 | { 1662, 19, 24, 23, 2, -23 }, // 0x44 'D' 496 | { 1719, 16, 24, 20, 2, -23 }, // 0x45 'E' 497 | { 1767, 18, 24, 22, 2, -23 }, // 0x46 'F' 498 | { 1821, 20, 24, 24, 2, -23 }, // 0x47 'G' 499 | { 1881, 21, 36, 25, 2, -29 }, // 0x48 'H' 500 | { 1976, 5, 31, 9, 2, -24 }, // 0x49 'I' 501 | { 1996, 15, 31, 18, 2, -23 }, // 0x4A 'J' 502 | { 2055, 22, 35, 23, 2, -27 }, // 0x4B 'K' 503 | { 2152, 18, 27, 22, 2, -26 }, // 0x4C 'L' 504 | { 2213, 25, 27, 29, 2, -26 }, // 0x4D 'M' 505 | { 2298, 19, 30, 23, 2, -26 }, // 0x4E 'N' 506 | { 2370, 21, 24, 25, 2, -23 }, // 0x4F 'O' 507 | { 2433, 22, 24, 25, 2, -23 }, // 0x50 'P' 508 | { 2499, 19, 31, 23, 2, -23 }, // 0x51 'Q' 509 | { 2573, 22, 28, 24, 2, -23 }, // 0x52 'R' 510 | { 2650, 23, 24, 27, 2, -23 }, // 0x53 'S' 511 | { 2719, 27, 30, 27, 0, -23 }, // 0x54 'T' 512 | { 2821, 21, 24, 25, 2, -23 }, // 0x55 'U' 513 | { 2884, 20, 31, 23, 2, -23 }, // 0x56 'V' 514 | { 2962, 25, 27, 29, 2, -23 }, // 0x57 'W' 515 | { 3047, 24, 24, 28, 2, -23 }, // 0x58 'X' 516 | { 3119, 24, 28, 28, 2, -23 }, // 0x59 'Y' 517 | { 3203, 19, 24, 22, 2, -23 }, // 0x5A 'Z' 518 | { 3260, 14, 30, 17, 2, -23 }, // 0x5B '[' 519 | { 3313, 14, 29, 18, 2, -27 }, // 0x5C '\' 520 | { 3364, 14, 30, 17, 1, -23 }, // 0x5D ']' 521 | { 3417, 20, 13, 24, 2, -23 }, // 0x5E '^' 522 | { 3450, 17, 3, 20, 2, 4 }, // 0x5F '_' 523 | { 3457, 6, 8, 9, 2, -29 }, // 0x60 '`' 524 | { 3463, 21, 30, 25, 2, -23 }, // 0x61 'a' 525 | { 3542, 21, 31, 25, 2, -23 }, // 0x62 'b' 526 | { 3624, 20, 24, 24, 2, -23 }, // 0x63 'c' 527 | { 3684, 19, 24, 23, 2, -23 }, // 0x64 'd' 528 | { 3741, 16, 24, 20, 2, -23 }, // 0x65 'e' 529 | { 3789, 18, 24, 22, 2, -23 }, // 0x66 'f' 530 | { 3843, 20, 24, 24, 2, -23 }, // 0x67 'g' 531 | { 3903, 21, 36, 25, 2, -29 }, // 0x68 'h' 532 | { 3998, 5, 31, 9, 2, -24 }, // 0x69 'i' 533 | { 4018, 15, 31, 18, 2, -23 }, // 0x6A 'j' 534 | { 4077, 22, 35, 23, 2, -27 }, // 0x6B 'k' 535 | { 4174, 18, 27, 22, 2, -26 }, // 0x6C 'l' 536 | { 4235, 25, 27, 29, 2, -26 }, // 0x6D 'm' 537 | { 4320, 19, 30, 23, 2, -26 }, // 0x6E 'n' 538 | { 4392, 21, 24, 25, 2, -23 }, // 0x6F 'o' 539 | { 4455, 22, 24, 25, 2, -23 }, // 0x70 'p' 540 | { 4521, 19, 31, 23, 2, -23 }, // 0x71 'q' 541 | { 4595, 22, 28, 24, 2, -23 }, // 0x72 'r' 542 | { 4672, 23, 24, 27, 2, -23 }, // 0x73 's' 543 | { 4741, 27, 30, 27, 0, -23 }, // 0x74 't' 544 | { 4843, 21, 24, 25, 2, -23 }, // 0x75 'u' 545 | { 4906, 20, 31, 23, 2, -23 }, // 0x76 'v' 546 | { 4984, 25, 27, 29, 2, -23 }, // 0x77 'w' 547 | { 5069, 24, 24, 28, 2, -23 }, // 0x78 'x' 548 | { 5141, 24, 28, 28, 2, -23 }, // 0x79 'y' 549 | { 5225, 19, 24, 22, 2, -23 }, // 0x7A 'z' 550 | { 5282, 19, 30, 23, 2, -23 }, // 0x7B '{' 551 | { 5354, 2, 34, 6, 2, -26 }, // 0x7C '|' 552 | { 5363, 19, 30, 23, 2, -23 }, // 0x7D '}' 553 | { 5435, 19, 6, 23, 2, -19 } }; // 0x7E '~' 554 | 555 | const GFXfont Fun_Games20pt7b PROGMEM = { 556 | (uint8_t *)Fun_Games20pt7bBitmaps, 557 | (GFXglyph *)Fun_Games20pt7bGlyphs, 558 | 0x20, 0x7E, 40 }; 559 | 560 | // Approx. 6122 bytes 561 | -------------------------------------------------------------------------------- /image_test.h: -------------------------------------------------------------------------------- 1 | #include "virtualScreen.h" 2 | #include "images/newyork_960x240.h" 3 | #include "images/highway_720x480.h" 4 | #include "images/night_earth_960x240.h" 5 | #include "images/bazar_960x240.h" 6 | #include "images/spacebattle_960x240.h" 7 | #include "images/console_960x240.h" 8 | 9 | // #define test_image bazar 10 | // #define test_width bazar_width 11 | // #define test_height bazar_height 12 | 13 | // #define test_image spacebattle 14 | // #define test_width spacebattle_width 15 | // #define test_height spacebattle_height 16 | 17 | // #define test_image console 18 | // #define test_width console_width 19 | // #define test_height console_height 20 | 21 | #define test_image highway 22 | #define test_width highway_width 23 | #define test_height highway_height 24 | 25 | void image_test(VirtualDisplay *tft) 26 | { 27 | tft->fillScreen(TFT_BLACK); 28 | tft->drawRGBBitmap(0, 0, (uint16_t *)test_image, test_width, test_height); 29 | tft->output(); 30 | } -------------------------------------------------------------------------------- /keywords.txt: -------------------------------------------------------------------------------- 1 | [Keywords] 2 | ####################################### 3 | # Datatypes (KEYWORD1) 4 | ####################################### 5 | boolean 6 | uint16_t 7 | int 8 | 9 | ####################################### 10 | # Methods and Functions (KEYWORD2) 11 | ####################################### 12 | begin KEYWORD2 13 | output KEYWORD2 14 | highlightArea KEYWORD2 15 | color565 KEYWORD2 16 | readRect KEYWORD2 -------------------------------------------------------------------------------- /library.properties: -------------------------------------------------------------------------------- 1 | name=VirtualScreen 2 | version=2.0.2 3 | author=The Last Outpost Workshop 4 | maintainer=The Last Outpost Workshop 5 | sentence=Automatically span GFX Adafruit graphics functions across multiple screens 6 | paragraph=Works with any 16 bit SPI Screen supported by TFT_eSPI on ESP32 7 | category=Display 8 | keywords=keywords.txt 9 | url=https://github.com/thelastoutpostworkshop/virtualScreen 10 | architectures=esp32 11 | depends=Adafruit GFX Library, TFT_eSPI -------------------------------------------------------------------------------- /oldino: -------------------------------------------------------------------------------- 1 | #include "virtualScreen.h" 2 | 3 | #include "gameoflife.h" 4 | #include "maze.h" 5 | #include "playPong.h" 6 | #include "tetris.h" 7 | #include "font_test.h" 8 | #include "image_test.h" 9 | 10 | VirtualDisplay *tft; 11 | 12 | 13 | void setup() 14 | { 15 | Serial.begin(115200); 16 | 17 | ScreenBuilder screens; 18 | 19 | // 4 sreens on one row 20 | screens.addRow({{16, 0}, {15, 0}, {6, 0}, {7, 0}}); 21 | 22 | // 6 screens 3 on each row 23 | // screens.addRow({{7, 2}, {6, 2}, {15, 2}}); 24 | // screens.addRow({{16, 0}, {11, 0}, {9, 0}}); 25 | 26 | tft = new VirtualDisplay(screens.width(), screens.height(), &screens); 27 | 28 | if (!tft->begin()) 29 | { 30 | Serial.println("Memory Allocation for virtual screen failed"); 31 | return; 32 | } 33 | 34 | // Demonstrations 35 | // 36 | 37 | // playPong(tft); 38 | gameOfLife(tft); 39 | // solveMaze(tft); 40 | // font_test(tft); 41 | // image_test(tft); 42 | // playTetris(tft); 43 | // runNostromoSimulation(tft); 44 | } 45 | 46 | void loop() 47 | { 48 | } 49 | -------------------------------------------------------------------------------- /src/virtualScreen.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #ifndef _VIRTUAL_SCREEN_ 6 | #define _VIRTUAL_SCREEN_ 7 | 8 | #define pixelSize 2 // Pixel Size in bytes 9 | 10 | TFT_eSPI physicalDisplayTFT = TFT_eSPI(); 11 | 12 | typedef struct 13 | { 14 | int cs; 15 | int rotation; 16 | } ScreenRow; 17 | 18 | typedef struct 19 | { 20 | int row; 21 | int column; 22 | int cs; 23 | int rotation; 24 | bool dirty; 25 | } Screen; 26 | 27 | class ScreenBuilder 28 | { 29 | std::vector screens; 30 | int totalRows = 0; 31 | int maxColumns = 0; 32 | int virtualScreenWidth = 0; 33 | int virtualScreenHeight = 0; 34 | 35 | public: 36 | ScreenBuilder &addRow(std::initializer_list screenRows) 37 | { 38 | int columnCount = screenRows.size(); 39 | maxColumns = std::max(maxColumns, columnCount); 40 | int column = 0; 41 | for (const auto &screenRow : screenRows) 42 | { 43 | screens.push_back({totalRows, column, screenRow.cs, screenRow.rotation}); 44 | ++column; 45 | } 46 | ++totalRows; 47 | 48 | // Update virtual screen dimensions 49 | virtualScreenWidth = physicalDisplayTFT.width() * maxColumns; 50 | virtualScreenHeight = physicalDisplayTFT.height() * totalRows; 51 | 52 | return *this; 53 | } 54 | 55 | std::vector &getScreens() 56 | { 57 | return screens; 58 | } 59 | 60 | Screen *getScreen(int x, int y) 61 | { 62 | // Calculate which row and column the x, y coordinates fall into 63 | int column = x / physicalDisplayTFT.width(); 64 | int row = y / physicalDisplayTFT.height(); 65 | 66 | // Iterate through the screens to find the matching one 67 | for (auto &screen : screens) 68 | { 69 | if (screen.row == row && screen.column == column) 70 | { 71 | return &screen; // Return the address of the screen 72 | } 73 | } 74 | 75 | // If no matching screen is found, return a null pointer 76 | return nullptr; 77 | } 78 | 79 | int width() const 80 | { 81 | return virtualScreenWidth; 82 | } 83 | 84 | int height() const 85 | { 86 | return virtualScreenHeight; 87 | } 88 | }; 89 | 90 | class VirtualDisplay : public Adafruit_GFX 91 | { 92 | private: 93 | uint16_t *canvas; 94 | size_t canvasSize; 95 | size_t displayBufferSize; 96 | uint16_t *displayBuffer; 97 | int16_t _width; 98 | int16_t _height; 99 | bool _ready = false; 100 | ScreenBuilder *screenBuilder; 101 | 102 | inline bool checkReady() const 103 | { 104 | return _ready; 105 | } 106 | 107 | void clearDisplayBuffer() 108 | { 109 | memset(canvas, 0, displayBufferSize); 110 | } 111 | 112 | uint16_t *getScreenImage(const Screen &screen) 113 | { 114 | // Calculate the starting position of the screen in the buffer 115 | uint32_t position = (screen.row * physicalDisplayTFT.height() * screenBuilder->width()) + (screen.column * physicalDisplayTFT.width()); 116 | 117 | uint16_t *startPos = canvas + position; 118 | 119 | // Copy the screen image from the buffer 120 | for (int y = 0; y < physicalDisplayTFT.height(); ++y) 121 | { 122 | for (int x = 0; x < physicalDisplayTFT.width(); ++x) 123 | { 124 | displayBuffer[y * physicalDisplayTFT.width() + x] = startPos[y * screenBuilder->width() + x]; 125 | } 126 | } 127 | 128 | return displayBuffer; 129 | } 130 | 131 | void clearDirtyFlag() 132 | { 133 | auto &screens = screenBuilder->getScreens(); 134 | 135 | for (auto &screen : screens) 136 | { 137 | screen.dirty = false; 138 | } 139 | } 140 | void initPhysicalScreens() 141 | { 142 | physicalDisplayTFT.begin(); 143 | physicalDisplayTFT.setSwapBytes(true); 144 | const auto &screens = screenBuilder->getScreens(); 145 | 146 | for (const auto &screen : screens) 147 | { 148 | pinMode(screen.cs, OUTPUT); 149 | digitalWrite(screen.cs, HIGH); 150 | } 151 | clearDirtyFlag(); 152 | } 153 | 154 | // Method to adjust color brightness 155 | uint16_t adjustBrightness(uint16_t color, float intensity) 156 | { 157 | // Decompose the color into its RGB components 158 | uint8_t r = (color >> 11) & 0x1F; 159 | uint8_t g = (color >> 5) & 0x3F; 160 | uint8_t b = color & 0x1F; 161 | 162 | // Increase brightness according to the specified intensity, ensuring no overflow 163 | r = std::min(31.0f, r * (1.0f + intensity)); 164 | g = std::min(63.0f, g * (1.0f + intensity)); 165 | b = std::min(31.0f, b * (1.0f + intensity)); 166 | 167 | // Recompose the color 168 | return (r << 11) | (g << 5) | b; 169 | } 170 | 171 | public: 172 | VirtualDisplay(int16_t w, int16_t h, ScreenBuilder *builder) : Adafruit_GFX(w, h) 173 | { 174 | _width = w; 175 | _height = h; 176 | canvasSize = w * h * pixelSize; 177 | if ((canvas = (uint16_t *)malloc(canvasSize))) 178 | { 179 | memset(canvas, 0, canvasSize); 180 | } 181 | displayBufferSize = physicalDisplayTFT.width() * physicalDisplayTFT.height() * pixelSize; 182 | if ((displayBuffer = (uint16_t *)malloc(displayBufferSize))) 183 | { 184 | clearDisplayBuffer(); 185 | } 186 | _ready = canvas && displayBuffer; 187 | if (!_ready) 188 | { 189 | Serial.println(">>> Not enough memory for virtual screen"); 190 | Serial.println(">>> Enable PSRAM in your board configuration if supported"); 191 | } 192 | screenBuilder = builder; 193 | } 194 | 195 | bool begin() 196 | { 197 | if (_ready) 198 | { 199 | initPhysicalScreens(); 200 | Serial.printf("Virtual Screen Width=%d\n", _width); 201 | Serial.printf("Virtual Screen Height=%d\n", _height); 202 | } 203 | return _ready; 204 | } 205 | 206 | void output() 207 | { 208 | if (!checkReady()) 209 | return; 210 | 211 | const auto &screens = screenBuilder->getScreens(); 212 | 213 | for (const auto &screen : screens) 214 | { 215 | 216 | uint16_t *screenImage = getScreenImage(screen); 217 | if (screen.dirty) 218 | { 219 | digitalWrite(screen.cs, LOW); 220 | physicalDisplayTFT.setRotation(screen.rotation); 221 | physicalDisplayTFT.pushImage(0, 0, physicalDisplayTFT.width(), physicalDisplayTFT.height(), screenImage); 222 | digitalWrite(screen.cs, HIGH); 223 | } 224 | } 225 | clearDirtyFlag(); 226 | } 227 | 228 | // Method to highlight a specified area of the canvas with adjustable intensity 229 | void highlightArea(int16_t x, int16_t y, int16_t width, int16_t height, float intensity) 230 | { 231 | if (!checkReady()) 232 | return; 233 | 234 | for (int16_t row = y; row < y + height; ++row) 235 | { 236 | for (int16_t col = x; col < x + width; ++col) 237 | { 238 | if (col >= 0 && col < _width && row >= 0 && row < _height) 239 | { 240 | // Fetch the original color from the canvas 241 | uint16_t originalColor = canvas[row * _width + col]; 242 | 243 | // Adjust the color brightness based on the specified intensity 244 | uint16_t adjustedColor = adjustBrightness(originalColor, intensity); 245 | 246 | // Update the pixel on the canvas 247 | drawPixel(col, row, adjustedColor); 248 | } 249 | } 250 | } 251 | } 252 | 253 | // Method to highlight a circular area of the canvas with adjustable intensity 254 | void highlightArea(int16_t centerX, int16_t centerY, int16_t radius, float intensity) 255 | { 256 | if (!checkReady()) 257 | return; 258 | 259 | for (int16_t y = centerY - radius; y <= centerY + radius; ++y) 260 | { 261 | for (int16_t x = centerX - radius; x <= centerX + radius; ++x) 262 | { 263 | // Calculate distance from the center of the circle 264 | int16_t dx = x - centerX; 265 | int16_t dy = y - centerY; 266 | if (dx * dx + dy * dy <= radius * radius) 267 | { 268 | // The pixel is inside the circle 269 | if (x >= 0 && x < _width && y >= 0 && y < _height) 270 | { 271 | uint16_t originalColor = canvas[y * _width + x]; 272 | uint16_t highlightedColor = adjustBrightness(originalColor, intensity); 273 | drawPixel(x, y, highlightedColor); 274 | } 275 | } 276 | } 277 | } 278 | } 279 | 280 | ~VirtualDisplay() 281 | { 282 | if (canvas) 283 | { 284 | free(canvas); 285 | free(displayBuffer); 286 | } 287 | } 288 | 289 | uint16_t color565(uint8_t r, uint8_t g, uint8_t b) 290 | { 291 | return (uint16_t)((r & 0xF8) << 8) | ((g & 0xFC) << 3) | (b >> 3); 292 | } 293 | 294 | int16_t width() 295 | { 296 | return _width; 297 | } 298 | int16_t height() 299 | { 300 | return _height; 301 | } 302 | 303 | void pushImage(int16_t x, int16_t y, int16_t width, int16_t height, uint16_t *buffer) 304 | { 305 | if (!checkReady()) 306 | return; 307 | 308 | if (x < 0) 309 | { 310 | x = 0; 311 | } 312 | if (y < 0) 313 | { 314 | y = 0; 315 | } 316 | if (x + width > _width) 317 | { 318 | x = _width; 319 | } 320 | if (y + height > _height) 321 | { 322 | y = _height; 323 | } 324 | 325 | for (int16_t i = 0; i < height; i++) 326 | { 327 | for (int16_t j = 0; j < width; j++) 328 | { 329 | int bufferIndex = i * width + j; 330 | 331 | int canvasIndex = (y + i) * _width + (x + j); 332 | 333 | drawPixel(x + j, y + i, buffer[bufferIndex]); 334 | } 335 | } 336 | } 337 | 338 | void readRect(int16_t x, int16_t y, int16_t width, int16_t height, uint16_t *buffer) 339 | { 340 | if (!checkReady()) 341 | return; 342 | 343 | if (x < 0) 344 | { 345 | x = 0; 346 | } 347 | if (y < 0) 348 | { 349 | y = 0; 350 | } 351 | if (x + width > _width) 352 | { 353 | x = _width; 354 | } 355 | if (y + height > _height) 356 | { 357 | y = _height; 358 | } 359 | 360 | for (int16_t row = 0; row < height; ++row) 361 | { 362 | for (int16_t col = 0; col < width; ++col) 363 | { 364 | int canvasIndex = ((y + row) * _width) + (x + col); 365 | int bufferIndex = (row * width) + col; 366 | buffer[bufferIndex] = canvas[canvasIndex]; 367 | } 368 | } 369 | } 370 | void drawPixel(int16_t x, int16_t y, uint16_t color) override 371 | { 372 | if (!checkReady()) 373 | return; 374 | 375 | if ((x < 0) || (y < 0) || (x >= _width) || (y >= _height)) 376 | { 377 | return; 378 | } 379 | 380 | Screen *screen = screenBuilder->getScreen(x, y); 381 | 382 | if (screen) 383 | { 384 | screen->dirty = true; 385 | } 386 | 387 | canvas[y * _width + x] = color; 388 | } 389 | 390 | void startWrite(void) override 391 | { 392 | } 393 | 394 | void endWrite(void) override 395 | { 396 | } 397 | }; 398 | 399 | #endif 400 | -------------------------------------------------------------------------------- /virtualScreen.ino: -------------------------------------------------------------------------------- 1 | #include "src/virtualScreen.h" 2 | #include "images/spacedock_480x480.h" 3 | #include "images/spaceship_480x480.h" 4 | 5 | VirtualDisplay *tft; 6 | ScreenBuilder screens; 7 | 8 | void setup() 9 | { 10 | Serial.begin(115200); 11 | 12 | // Adjust this setup according to your actual screen configuration 13 | screens.addRow({{6, 0}, {7, 0}}); 14 | screens.addRow({{16, 2}, {15, 2}}); 15 | 16 | tft = new VirtualDisplay(screens.width(), screens.height(), &screens); 17 | tft->begin(); 18 | 19 | tft->fillScreen(TFT_BLACK); 20 | tft->drawRGBBitmap(0, 0, (uint16_t *)spaceship_480x480, spaceship_480x480_width, spaceship_480x480_height); 21 | tft->output(); 22 | delay(5000); 23 | tft->drawRGBBitmap(0, 0, (uint16_t *)spacedock_480x480, spacedock_480x480_width, spacedock_480x480_height); 24 | tft->output(); 25 | } 26 | 27 | void loop() 28 | { 29 | } 30 | 31 | --------------------------------------------------------------------------------