Fast and reasonably complete (framebuffer) terminal emulator (Zig fork)
1/* Copyright (C) 2022-2024 mintsuki and contributors. 2 * 3 * Redistribution and use in source and binary forms, with or without 4 * modification, are permitted provided that the following conditions are met: 5 * 6 * 1. Redistributions of source code must retain the above copyright notice, 7 * this list of conditions and the following disclaimer. 8 * 9 * 2. Redistributions in binary form must reproduce the above copyright notice, 10 * this list of conditions and the following disclaimer in the documentation 11 * and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 14 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 16 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 17 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 19 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 23 * POSSIBILITY OF SUCH DAMAGE. 24 */ 25 26#include <stdint.h> 27#include <stddef.h> 28 29#include "../flanterm.h" 30#include "fb.h" 31 32void *memset(void *, int, size_t); 33void *memcpy(void *, const void *, size_t); 34 35#ifndef FLANTERM_FB_DISABLE_BUMP_ALLOC 36 37#ifndef FLANTERM_FB_BUMP_ALLOC_POOL_SIZE 38#define FLANTERM_FB_BUMP_ALLOC_POOL_SIZE (64*1024*1024) 39#endif 40 41static uint8_t bump_alloc_pool[FLANTERM_FB_BUMP_ALLOC_POOL_SIZE]; 42static size_t bump_alloc_ptr = 0; 43 44static void *bump_alloc(size_t s) { 45 size_t next_ptr = bump_alloc_ptr + s; 46 if (next_ptr > FLANTERM_FB_BUMP_ALLOC_POOL_SIZE) { 47 return NULL; 48 } 49 void *ret = &bump_alloc_pool[bump_alloc_ptr]; 50 bump_alloc_ptr = next_ptr; 51 return ret; 52} 53 54#endif 55 56// Builtin font originally taken from: 57// https://github.com/viler-int10h/vga-text-mode-fonts/raw/master/FONTS/PC-OTHER/TOSH-SAT.F16 58static const uint8_t builtin_font[] = { 59 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 60 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x81, 0x81, 0xa5, 0xa5, 0x81, 61 0x81, 0xa5, 0x99, 0x81, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x3c, 0x7e, 0xff, 62 0xff, 0xdb, 0xdb, 0xff, 0xff, 0xdb, 0xe7, 0xff, 0x7e, 0x3c, 0x00, 0x00, 63 0x00, 0x00, 0x00, 0x6c, 0xfe, 0xfe, 0xfe, 0x7c, 0x7c, 0x38, 0x38, 0x10, 64 0x10, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x38, 0x38, 0x7c, 0x7c, 0xfe, 65 0x7c, 0x7c, 0x38, 0x38, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 66 0x3c, 0x3c, 0xdb, 0xff, 0xff, 0xdb, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 67 0x00, 0x00, 0x00, 0x18, 0x3c, 0x7e, 0xff, 0xff, 0xff, 0x66, 0x18, 0x18, 68 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x78, 69 0x78, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 70 0xff, 0xff, 0xe7, 0xc3, 0xc3, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 71 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0xcc, 0x84, 0x84, 0xcc, 0x78, 0x00, 72 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc3, 0x99, 0xbd, 73 0xbd, 0x99, 0xc3, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x1e, 74 0x0e, 0x1e, 0x32, 0x78, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00, 75 0x00, 0x00, 0x00, 0x78, 0xcc, 0xcc, 0xcc, 0x78, 0x30, 0xfc, 0x30, 0x30, 76 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x18, 0x1c, 0x1e, 0x16, 0x12, 77 0x10, 0x10, 0x70, 0xf0, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x30, 0x38, 0x2c, 78 0x26, 0x32, 0x3a, 0x2e, 0x26, 0x22, 0x62, 0xe2, 0xc6, 0x0e, 0x0c, 0x00, 79 0x00, 0x00, 0x00, 0x18, 0x18, 0xdb, 0x3c, 0xe7, 0x3c, 0xdb, 0x18, 0x18, 80 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xc0, 0xe0, 0xf8, 0xfe, 81 0xf8, 0xe0, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 82 0x06, 0x0e, 0x3e, 0xfe, 0x3e, 0x0e, 0x06, 0x02, 0x00, 0x00, 0x00, 0x00, 83 0x00, 0x00, 0x30, 0x78, 0xfc, 0x30, 0x30, 0x30, 0x30, 0x30, 0xfc, 0x78, 84 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 85 0xcc, 0xcc, 0x00, 0xcc, 0xcc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xdb, 86 0xdb, 0xdb, 0xdb, 0x7b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x00, 0x00, 0x00, 87 0x00, 0x00, 0x7c, 0xc6, 0x60, 0x38, 0x6c, 0xc6, 0xc6, 0x6c, 0x38, 0x0c, 88 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 89 0x00, 0x00, 0xfe, 0xfe, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x78, 90 0xfc, 0x30, 0x30, 0x30, 0x30, 0x30, 0xfc, 0x78, 0x30, 0xfc, 0x00, 0x00, 91 0x00, 0x00, 0x30, 0x78, 0xfc, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 92 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 93 0x30, 0x30, 0xfc, 0x78, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 94 0x00, 0x18, 0x0c, 0xfe, 0xfe, 0x0c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 95 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x60, 0xfe, 0xfe, 0x60, 0x30, 0x00, 96 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 97 0xc0, 0xc0, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 98 0x00, 0x24, 0x66, 0xff, 0xff, 0x66, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 99 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x38, 0x38, 0x7c, 0x7c, 0xfe, 0xfe, 100 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xfe, 0x7c, 0x7c, 101 0x38, 0x38, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 102 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 103 0x00, 0x00, 0x30, 0x78, 0x78, 0x78, 0x78, 0x30, 0x30, 0x30, 0x00, 0x30, 104 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x00, 105 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6c, 0x6c, 106 0x6c, 0xfe, 0x6c, 0x6c, 0x6c, 0xfe, 0x6c, 0x6c, 0x6c, 0x00, 0x00, 0x00, 107 0x00, 0x18, 0x18, 0x7c, 0xc6, 0xc0, 0xc0, 0x7c, 0x06, 0x06, 0xc6, 0x7c, 108 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0x0c, 0x0c, 0x18, 0x38, 109 0x30, 0x60, 0x60, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6c, 110 0x6c, 0x38, 0x30, 0x76, 0xde, 0xcc, 0xcc, 0xde, 0x76, 0x00, 0x00, 0x00, 111 0x00, 0x00, 0x18, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 112 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x30, 0x60, 0x60, 0x60, 0x60, 113 0x60, 0x60, 0x60, 0x30, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x30, 114 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x30, 0x60, 0x00, 0x00, 0x00, 115 0x00, 0x00, 0x00, 0x00, 0x00, 0x6c, 0x38, 0xfe, 0x38, 0x6c, 0x00, 0x00, 116 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7e, 117 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 118 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x30, 0x00, 0x00, 119 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 120 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 121 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x06, 122 0x0c, 0x0c, 0x18, 0x38, 0x30, 0x60, 0x60, 0xc0, 0xc0, 0x00, 0x00, 0x00, 123 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xd6, 0xd6, 0xd6, 0xc6, 0xc6, 0xc6, 124 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x38, 0x78, 0x18, 0x18, 0x18, 125 0x18, 0x18, 0x18, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 126 0x06, 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0xc0, 0xfe, 0x00, 0x00, 0x00, 127 0x00, 0x00, 0x7c, 0xc6, 0x06, 0x06, 0x3c, 0x06, 0x06, 0x06, 0x06, 0xc6, 128 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x0c, 0x1c, 0x3c, 0x6c, 0xcc, 129 0xfe, 0x0c, 0x0c, 0x0c, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc0, 130 0xc0, 0xc0, 0xfc, 0x06, 0x06, 0x06, 0x06, 0xc6, 0x7c, 0x00, 0x00, 0x00, 131 0x00, 0x00, 0x3c, 0x60, 0xc0, 0xc0, 0xfc, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 132 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc6, 0x06, 0x06, 0x0c, 0x18, 133 0x30, 0x30, 0x30, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 134 0xc6, 0xc6, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 135 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x06, 0x06, 0x0c, 136 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 137 0x18, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 138 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x18, 0x18, 0x30, 0x00, 0x00, 139 0x00, 0x00, 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0x60, 0x30, 0x18, 0x0c, 140 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 141 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x60, 142 0x30, 0x18, 0x0c, 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0x00, 0x00, 0x00, 143 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0x06, 0x0c, 0x18, 0x30, 0x30, 0x00, 0x30, 144 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xde, 0xde, 145 0xde, 0xde, 0xc0, 0xc0, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6c, 146 0xc6, 0xc6, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 147 0x00, 0x00, 0xfc, 0xc6, 0xc6, 0xc6, 0xfc, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 148 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc0, 0xc0, 0xc0, 0xc0, 149 0xc0, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xcc, 150 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xcc, 0xf8, 0x00, 0x00, 0x00, 151 0x00, 0x00, 0xfe, 0xc0, 0xc0, 0xc0, 0xfc, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 152 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc0, 0xc0, 0xc0, 0xfc, 0xc0, 153 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 154 0xc0, 0xc0, 0xc0, 0xde, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, 0x00, 0x00, 0x00, 155 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 156 0xc6, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x30, 0x30, 0x30, 0x30, 0x30, 157 0x30, 0x30, 0x30, 0x30, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x0c, 158 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 159 0x00, 0x00, 0xc6, 0xc6, 0xcc, 0xd8, 0xf0, 0xe0, 0xf0, 0xd8, 0xcc, 0xc6, 160 0xc6, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 161 0xc0, 0xc0, 0xc0, 0xc0, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 162 0xee, 0xfe, 0xd6, 0xd6, 0xd6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 163 0x00, 0x00, 0xc6, 0xc6, 0xe6, 0xe6, 0xf6, 0xde, 0xce, 0xce, 0xc6, 0xc6, 164 0xc6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 165 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xc6, 166 0xc6, 0xc6, 0xc6, 0xfc, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 167 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xf6, 0xda, 168 0x6c, 0x06, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xc6, 0xc6, 0xc6, 0xc6, 0xfc, 169 0xd8, 0xcc, 0xcc, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 170 0xc0, 0x60, 0x30, 0x18, 0x0c, 0x06, 0x06, 0xc6, 0x7c, 0x00, 0x00, 0x00, 171 0x00, 0x00, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 172 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 173 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 174 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x6c, 0x38, 0x10, 0x00, 0x00, 0x00, 175 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xd6, 0xd6, 0xd6, 0xd6, 0xfe, 0x6c, 176 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0x6c, 0x38, 0x38, 177 0x38, 0x6c, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, 0x00, 0xcc, 0xcc, 178 0xcc, 0xcc, 0xcc, 0x78, 0x30, 0x30, 0x30, 0x30, 0x30, 0x00, 0x00, 0x00, 179 0x00, 0x00, 0xfe, 0x06, 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0xc0, 0xc0, 180 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x60, 0x60, 0x60, 0x60, 0x60, 181 0x60, 0x60, 0x60, 0x60, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 182 0x60, 0x60, 0x30, 0x38, 0x18, 0x0c, 0x0c, 0x06, 0x06, 0x00, 0x00, 0x00, 183 0x00, 0x00, 0x78, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 184 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0x00, 0x00, 185 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 186 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 187 0x00, 0x00, 0x18, 0x18, 0x18, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 188 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x06, 0x06, 189 0x7e, 0xc6, 0xc6, 0xc6, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 190 0xc0, 0xdc, 0xe6, 0xc6, 0xc6, 0xc6, 0xc6, 0xe6, 0xdc, 0x00, 0x00, 0x00, 191 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc0, 0xc0, 0xc0, 0xc0, 0xc6, 192 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x06, 0x06, 0x76, 0xce, 0xc6, 193 0xc6, 0xc6, 0xc6, 0xce, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 194 0x00, 0x7c, 0xc6, 0xc6, 0xfe, 0xc0, 0xc0, 0xc0, 0x7e, 0x00, 0x00, 0x00, 195 0x00, 0x00, 0x1c, 0x36, 0x30, 0x30, 0xfc, 0x30, 0x30, 0x30, 0x30, 0x30, 196 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xce, 0xc6, 197 0xc6, 0xc6, 0xce, 0x76, 0x06, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0xc0, 0xc0, 198 0xc0, 0xdc, 0xe6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 199 0x00, 0x00, 0x18, 0x00, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 200 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x1e, 0x06, 0x06, 201 0x06, 0x06, 0x06, 0x06, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0xc0, 0xc0, 202 0xc0, 0xc6, 0xcc, 0xd8, 0xf0, 0xf0, 0xd8, 0xcc, 0xc6, 0x00, 0x00, 0x00, 203 0x00, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 204 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xec, 0xfe, 0xd6, 205 0xd6, 0xd6, 0xd6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 206 0x00, 0xdc, 0xe6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 207 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 208 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0xe6, 0xc6, 209 0xc6, 0xc6, 0xe6, 0xdc, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 210 0x00, 0x76, 0xce, 0xc6, 0xc6, 0xc6, 0xce, 0x76, 0x06, 0x06, 0x06, 0x00, 211 0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0xe6, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 212 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc0, 213 0x70, 0x1c, 0x06, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 214 0x30, 0xfe, 0x30, 0x30, 0x30, 0x30, 0x30, 0x36, 0x1c, 0x00, 0x00, 0x00, 215 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 216 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xc6, 217 0xc6, 0xc6, 0x6c, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 218 0x00, 0xc6, 0xc6, 0xd6, 0xd6, 0xd6, 0xd6, 0xfe, 0x6c, 0x00, 0x00, 0x00, 219 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0x6c, 0x38, 0x38, 0x6c, 0xc6, 220 0xc6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xc6, 221 0xc6, 0xc6, 0xce, 0x76, 0x06, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 222 0x00, 0xfe, 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0xfe, 0x00, 0x00, 0x00, 223 0x00, 0x00, 0x1c, 0x30, 0x30, 0x30, 0x30, 0xe0, 0x30, 0x30, 0x30, 0x30, 224 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0x30, 0x30, 0x30, 0x00, 225 0x30, 0x30, 0x30, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x30, 226 0x30, 0x30, 0x30, 0x1c, 0x30, 0x30, 0x30, 0x30, 0xe0, 0x00, 0x00, 0x00, 227 0x00, 0x00, 0x00, 0x76, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 228 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x38, 0x38, 0x6c, 229 0x6c, 0xc6, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 230 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x66, 0x3c, 0x18, 0xcc, 0x78, 0x00, 231 0x00, 0x00, 0x6c, 0x6c, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 232 0x7c, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x18, 0x30, 0x00, 0x7c, 0xc6, 0xc6, 233 0xfe, 0xc0, 0xc0, 0xc0, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6c, 234 0x00, 0x7c, 0x06, 0x06, 0x7e, 0xc6, 0xc6, 0xc6, 0x7e, 0x00, 0x00, 0x00, 235 0x00, 0x00, 0x6c, 0x6c, 0x00, 0x7c, 0x06, 0x06, 0x7e, 0xc6, 0xc6, 0xc6, 236 0x7e, 0x00, 0x00, 0x00, 0x00, 0x60, 0x30, 0x18, 0x00, 0x7c, 0x06, 0x06, 237 0x7e, 0xc6, 0xc6, 0xc6, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6c, 0x38, 238 0x00, 0x7c, 0x06, 0x06, 0x7e, 0xc6, 0xc6, 0xc6, 0x7e, 0x00, 0x00, 0x00, 239 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc0, 0xc0, 0xc0, 0xc0, 0xc6, 240 0x7c, 0x18, 0x0c, 0x38, 0x00, 0x10, 0x38, 0x6c, 0x00, 0x7c, 0xc6, 0xc6, 241 0xfe, 0xc0, 0xc0, 0xc0, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6c, 0x6c, 242 0x00, 0x7c, 0xc6, 0xc6, 0xfe, 0xc0, 0xc0, 0xc0, 0x7e, 0x00, 0x00, 0x00, 243 0x00, 0x60, 0x30, 0x18, 0x00, 0x7c, 0xc6, 0xc6, 0xfe, 0xc0, 0xc0, 0xc0, 244 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6c, 0x6c, 0x00, 0x38, 0x18, 0x18, 245 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6c, 246 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 247 0x00, 0x60, 0x30, 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 248 0x3c, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xc6, 249 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x38, 0x6c, 0x38, 0x00, 250 0x38, 0x6c, 0xc6, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 251 0x18, 0x30, 0x60, 0x00, 0xfe, 0xc0, 0xc0, 0xfc, 0xc0, 0xc0, 0xc0, 0xc0, 252 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xec, 0x36, 0x36, 253 0x76, 0xde, 0xd8, 0xd8, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x3c, 254 0x6c, 0xcc, 0xcc, 0xfe, 0xcc, 0xcc, 0xcc, 0xcc, 0xce, 0x00, 0x00, 0x00, 255 0x00, 0x10, 0x38, 0x6c, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 256 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6c, 0x6c, 0x00, 0x7c, 0xc6, 0xc6, 257 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x60, 0x30, 0x18, 258 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 259 0x00, 0x10, 0x38, 0x6c, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 260 0x7c, 0x00, 0x00, 0x00, 0x00, 0x60, 0x30, 0x18, 0x00, 0xc6, 0xc6, 0xc6, 261 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6c, 0x6c, 262 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xce, 0x76, 0x06, 0xc6, 0x7c, 0x00, 263 0x6c, 0x6c, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 264 0x7c, 0x00, 0x00, 0x00, 0x6c, 0x6c, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 265 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 266 0x30, 0x78, 0xcc, 0xc0, 0xc0, 0xcc, 0x78, 0x30, 0x30, 0x00, 0x00, 0x00, 267 0x00, 0x00, 0x38, 0x6c, 0x60, 0x60, 0x60, 0xf8, 0x60, 0x60, 0x60, 0xe6, 268 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0x78, 0x30, 0xfc, 269 0x30, 0xfc, 0x30, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xcc, 270 0xcc, 0xf8, 0xc4, 0xcc, 0xde, 0xcc, 0xcc, 0xcc, 0xc6, 0x00, 0x00, 0x00, 271 0x00, 0x00, 0x0e, 0x1b, 0x18, 0x18, 0x18, 0x7e, 0x18, 0x18, 0x18, 0x18, 272 0x18, 0xd8, 0x70, 0x00, 0x00, 0x0c, 0x18, 0x30, 0x00, 0x7c, 0x06, 0x06, 273 0x7e, 0xc6, 0xc6, 0xc6, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x18, 0x30, 274 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 275 0x00, 0x0c, 0x18, 0x30, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 276 0x7c, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x18, 0x30, 0x00, 0xc6, 0xc6, 0xc6, 277 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, 0x00, 278 0x00, 0xdc, 0xe6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 279 0x76, 0xdc, 0x00, 0xc6, 0xc6, 0xe6, 0xf6, 0xfe, 0xde, 0xce, 0xc6, 0xc6, 280 0xc6, 0x00, 0x00, 0x00, 0x00, 0x78, 0xd8, 0xd8, 0x6c, 0x00, 0xfc, 0x00, 281 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6c, 0x6c, 282 0x38, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 283 0x00, 0x00, 0x18, 0x18, 0x00, 0x18, 0x18, 0x30, 0x60, 0xc0, 0xc6, 0xc6, 284 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 285 0xfe, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 286 0x00, 0x00, 0x00, 0x00, 0xfe, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00, 287 0x00, 0x00, 0xc0, 0xc2, 0xc6, 0xcc, 0xd8, 0x30, 0x60, 0xdc, 0x86, 0x0c, 288 0x18, 0x3e, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc2, 0xc6, 0xcc, 0xd8, 0x30, 289 0x66, 0xce, 0x9e, 0x3e, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 290 0x00, 0x30, 0x30, 0x30, 0x78, 0x78, 0x78, 0x78, 0x30, 0x00, 0x00, 0x00, 291 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x6c, 0xd8, 0x6c, 0x36, 0x00, 0x00, 292 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x6c, 0x36, 293 0x6c, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0x88, 0x22, 0x88, 294 0x22, 0x88, 0x22, 0x88, 0x22, 0x88, 0x22, 0x88, 0x22, 0x88, 0x22, 0x88, 295 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 296 0x55, 0xaa, 0x55, 0xaa, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 297 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0x18, 0x18, 0x18, 0x18, 298 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 299 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0xf8, 0x18, 0x18, 0x18, 300 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0xf8, 0x18, 301 0x18, 0xf8, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x36, 0x36, 0x36, 0x36, 302 0x36, 0x36, 0x36, 0xf6, 0xf6, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 303 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xfe, 0x36, 0x36, 0x36, 304 0x36, 0x36, 0x36, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xf8, 0x18, 305 0x18, 0xf8, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x36, 0x36, 0x36, 0x36, 306 0x36, 0xf6, 0xf6, 0x06, 0x06, 0xf6, 0xf6, 0x36, 0x36, 0x36, 0x36, 0x36, 307 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 308 0x36, 0x36, 0x36, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xfe, 0x06, 309 0x06, 0xf6, 0xf6, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 310 0x36, 0xf6, 0xf6, 0x06, 0x06, 0xfe, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 311 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xfe, 0xfe, 0x00, 0x00, 0x00, 312 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0xf8, 0x18, 313 0x18, 0xf8, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 314 0x00, 0x00, 0x00, 0xf8, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 315 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x1f, 0x00, 0x00, 0x00, 316 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 317 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 318 0x00, 0x00, 0x00, 0xff, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 319 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x1f, 0x18, 0x18, 0x18, 320 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 321 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 322 0x18, 0x18, 0x18, 0xff, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 323 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x1f, 0x18, 0x18, 0x1f, 0x1f, 0x18, 324 0x18, 0x18, 0x18, 0x18, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x37, 325 0x37, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 326 0x36, 0x37, 0x37, 0x30, 0x30, 0x3f, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 327 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x3f, 0x30, 0x30, 0x37, 0x37, 0x36, 328 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xf7, 0xf7, 0x00, 329 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 330 0x00, 0xff, 0xff, 0x00, 0x00, 0xf7, 0xf7, 0x36, 0x36, 0x36, 0x36, 0x36, 331 0x36, 0x36, 0x36, 0x36, 0x36, 0x37, 0x37, 0x30, 0x30, 0x37, 0x37, 0x36, 332 0x36, 0x36, 0x36, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 333 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x36, 0x36, 0x36, 334 0x36, 0xf7, 0xf7, 0x00, 0x00, 0xf7, 0xf7, 0x36, 0x36, 0x36, 0x36, 0x36, 335 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 336 0x00, 0x00, 0x00, 0x00, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xff, 337 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 338 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 339 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x36, 0x36, 0x36, 340 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x3f, 341 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 342 0x18, 0x1f, 0x1f, 0x18, 0x18, 0x1f, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 343 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x1f, 0x18, 0x18, 0x1f, 0x1f, 0x18, 344 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 345 0x3f, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 346 0x36, 0x36, 0x36, 0xff, 0xff, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 347 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0xff, 0x18, 0x18, 0xff, 0xff, 0x18, 348 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 349 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 350 0x00, 0x00, 0x00, 0x1f, 0x1f, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 351 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 352 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 353 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0xf0, 0xf0, 0xf0, 354 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 355 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 356 0x0f, 0x0f, 0x0f, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 357 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 358 0x00, 0x76, 0xd6, 0xdc, 0xc8, 0xc8, 0xdc, 0xd6, 0x76, 0x00, 0x00, 0x00, 359 0x00, 0x00, 0x78, 0xcc, 0xcc, 0xcc, 0xd8, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 360 0xd8, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0xfe, 0xc6, 0xc6, 0xc0, 0xc0, 0xc0, 361 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 362 0x00, 0x7e, 0xfe, 0x24, 0x24, 0x24, 0x24, 0x66, 0xc6, 0x00, 0x00, 0x00, 363 0x00, 0x00, 0xfe, 0xfe, 0xc2, 0x60, 0x30, 0x18, 0x30, 0x60, 0xc2, 0xfe, 364 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0xc8, 0xcc, 365 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 366 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x76, 0x6c, 0x60, 0xc0, 0x00, 367 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0xfc, 0x98, 0x18, 0x18, 0x18, 0x18, 368 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x30, 0x30, 0x78, 0xcc, 0xcc, 369 0xcc, 0x78, 0x30, 0x30, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6c, 370 0xc6, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x6c, 0x38, 0x00, 0x00, 0x00, 371 0x00, 0x00, 0x38, 0x6c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x6c, 0x6c, 0x6c, 372 0xee, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0xcc, 0x60, 0x30, 0x78, 0xcc, 373 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 374 0x00, 0x76, 0xbb, 0x99, 0x99, 0xdd, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x00, 375 0x00, 0x00, 0x02, 0x06, 0x3c, 0x6c, 0xce, 0xd6, 0xd6, 0xe6, 0x6c, 0x78, 376 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x30, 0x60, 0xc0, 0xc0, 0xfe, 377 0xc0, 0xc0, 0x60, 0x30, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6c, 378 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 379 0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0xfe, 0x00, 0x00, 0xfe, 0x00, 380 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0xfc, 381 0x30, 0x30, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 382 0x60, 0x30, 0x18, 0x0c, 0x18, 0x30, 0x60, 0x00, 0xfc, 0x00, 0x00, 0x00, 383 0x00, 0x00, 0x00, 0x00, 0x18, 0x30, 0x60, 0xc0, 0x60, 0x30, 0x18, 0x00, 384 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x36, 0x36, 0x30, 0x30, 0x30, 385 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x18, 0x18, 0x18, 0x18, 386 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xd8, 0xd8, 0x70, 0x00, 0x00, 0x00, 387 0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0x00, 0xfc, 0x00, 0x30, 0x30, 0x00, 388 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, 0x00, 389 0x76, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0xcc, 0xcc, 390 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 391 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 392 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 393 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x0c, 0x0c, 394 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0xcc, 0x6c, 0x3c, 0x1c, 0x0c, 0x00, 0x00, 395 0x00, 0xd8, 0xec, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x00, 0x00, 0x00, 0x00, 396 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6c, 0x0c, 0x18, 0x30, 0x60, 0x7c, 397 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 398 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 399 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 400 0x00, 0x00, 0x00, 0x00 401}; 402 403#ifdef FLANTERM_FB_SUPPORT_BPP 404static inline __attribute__((always_inline)) uint32_t convert_colour(struct flanterm_context *_ctx, uint32_t colour) { 405 struct flanterm_fb_context *ctx = (void *)_ctx; 406 uint32_t r = (colour >> 16) & 0xff; 407 uint32_t g = (colour >> 8) & 0xff; 408 uint32_t b = colour & 0xff; 409 return (r << ctx->red_mask_shift) | (g << ctx->green_mask_shift) | (b << ctx->blue_mask_shift); 410} 411#else 412#define convert_colour(CTX, COLOUR) (COLOUR) 413#endif 414 415static void flanterm_fb_save_state(struct flanterm_context *_ctx) { 416 struct flanterm_fb_context *ctx = (void *)_ctx; 417 ctx->saved_state_text_fg = ctx->text_fg; 418 ctx->saved_state_text_bg = ctx->text_bg; 419 ctx->saved_state_cursor_x = ctx->cursor_x; 420 ctx->saved_state_cursor_y = ctx->cursor_y; 421} 422 423static void flanterm_fb_restore_state(struct flanterm_context *_ctx) { 424 struct flanterm_fb_context *ctx = (void *)_ctx; 425 ctx->text_fg = ctx->saved_state_text_fg; 426 ctx->text_bg = ctx->saved_state_text_bg; 427 ctx->cursor_x = ctx->saved_state_cursor_x; 428 ctx->cursor_y = ctx->saved_state_cursor_y; 429} 430 431static void flanterm_fb_swap_palette(struct flanterm_context *_ctx) { 432 struct flanterm_fb_context *ctx = (void *)_ctx; 433 uint32_t tmp = ctx->text_bg; 434 ctx->text_bg = ctx->text_fg; 435 ctx->text_fg = tmp; 436} 437 438static void plot_char(struct flanterm_context *_ctx, struct flanterm_fb_char *c, size_t x, size_t y) { 439 struct flanterm_fb_context *ctx = (void *)_ctx; 440 441 if (x >= _ctx->cols || y >= _ctx->rows) { 442 return; 443 } 444 445#ifdef FLANTERM_FB_DISABLE_CANVAS 446 uint32_t default_bg = ctx->default_bg; 447#endif 448 449 x = ctx->offset_x + x * ctx->glyph_width; 450 y = ctx->offset_y + y * ctx->glyph_height; 451 452 bool *glyph = &ctx->font_bool[c->c * ctx->font_height * ctx->font_width]; 453 // naming: fx,fy for font coordinates, gx,gy for glyph coordinates 454 for (size_t gy = 0; gy < ctx->glyph_height; gy++) { 455 uint8_t fy = gy / ctx->font_scale_y; 456 volatile uint32_t *fb_line = ctx->framebuffer + x + (y + gy) * (ctx->pitch / 4); 457 458#ifndef FLANTERM_FB_DISABLE_CANVAS 459 uint32_t *canvas_line = ctx->canvas + x + (y + gy) * ctx->width; 460#endif 461 462 for (size_t fx = 0; fx < ctx->font_width; fx++) { 463 bool draw = glyph[fy * ctx->font_width + fx]; 464 for (size_t i = 0; i < ctx->font_scale_x; i++) { 465 size_t gx = ctx->font_scale_x * fx + i; 466#ifndef FLANTERM_FB_DISABLE_CANVAS 467 uint32_t bg = c->bg == 0xffffffff ? canvas_line[gx] : c->bg; 468 uint32_t fg = c->fg == 0xffffffff ? canvas_line[gx] : c->fg; 469#else 470 uint32_t bg = c->bg == 0xffffffff ? default_bg : c->bg; 471 uint32_t fg = c->fg == 0xffffffff ? default_bg : c->fg; 472#endif 473 fb_line[gx] = draw ? fg : bg; 474 } 475 } 476 } 477} 478 479static void plot_char_fast(struct flanterm_context *_ctx, struct flanterm_fb_char *old, struct flanterm_fb_char *c, size_t x, size_t y) { 480 struct flanterm_fb_context *ctx = (void *)_ctx; 481 482 if (x >= _ctx->cols || y >= _ctx->rows) { 483 return; 484 } 485 486 x = ctx->offset_x + x * ctx->glyph_width; 487 y = ctx->offset_y + y * ctx->glyph_height; 488 489#ifdef FLANTERM_FB_DISABLE_CANVAS 490 uint32_t default_bg = ctx->default_bg; 491#endif 492 493 bool *new_glyph = &ctx->font_bool[c->c * ctx->font_height * ctx->font_width]; 494 bool *old_glyph = &ctx->font_bool[old->c * ctx->font_height * ctx->font_width]; 495 for (size_t gy = 0; gy < ctx->glyph_height; gy++) { 496 uint8_t fy = gy / ctx->font_scale_y; 497 volatile uint32_t *fb_line = ctx->framebuffer + x + (y + gy) * (ctx->pitch / 4); 498#ifndef FLANTERM_FB_DISABLE_CANVAS 499 uint32_t *canvas_line = ctx->canvas + x + (y + gy) * ctx->width; 500#endif 501 for (size_t fx = 0; fx < ctx->font_width; fx++) { 502 bool old_draw = old_glyph[fy * ctx->font_width + fx]; 503 bool new_draw = new_glyph[fy * ctx->font_width + fx]; 504 if (old_draw == new_draw) 505 continue; 506 for (size_t i = 0; i < ctx->font_scale_x; i++) { 507 size_t gx = ctx->font_scale_x * fx + i; 508#ifndef FLANTERM_FB_DISABLE_CANVAS 509 uint32_t bg = c->bg == 0xffffffff ? canvas_line[gx] : c->bg; 510 uint32_t fg = c->fg == 0xffffffff ? canvas_line[gx] : c->fg; 511#else 512 uint32_t bg = c->bg == 0xffffffff ? default_bg : c->bg; 513 uint32_t fg = c->fg == 0xffffffff ? default_bg : c->fg; 514#endif 515 fb_line[gx] = new_draw ? fg : bg; 516 } 517 } 518 } 519} 520 521static inline bool compare_char(struct flanterm_fb_char *a, struct flanterm_fb_char *b) { 522 return !(a->c != b->c || a->bg != b->bg || a->fg != b->fg); 523} 524 525static void push_to_queue(struct flanterm_context *_ctx, struct flanterm_fb_char *c, size_t x, size_t y) { 526 struct flanterm_fb_context *ctx = (void *)_ctx; 527 528 if (x >= _ctx->cols || y >= _ctx->rows) { 529 return; 530 } 531 532 size_t i = y * _ctx->cols + x; 533 534 struct flanterm_fb_queue_item *q = ctx->map[i]; 535 536 if (q == NULL) { 537 if (compare_char(&ctx->grid[i], c)) { 538 return; 539 } 540 q = &ctx->queue[ctx->queue_i++]; 541 q->x = x; 542 q->y = y; 543 ctx->map[i] = q; 544 } 545 546 q->c = *c; 547} 548 549static void flanterm_fb_revscroll(struct flanterm_context *_ctx) { 550 struct flanterm_fb_context *ctx = (void *)_ctx; 551 552 for (size_t i = (_ctx->scroll_bottom_margin - 1) * _ctx->cols - 1; 553 i >= _ctx->scroll_top_margin * _ctx->cols; i--) { 554 if (i == (size_t)-1) { 555 break; 556 } 557 struct flanterm_fb_char *c; 558 struct flanterm_fb_queue_item *q = ctx->map[i]; 559 if (q != NULL) { 560 c = &q->c; 561 } else { 562 c = &ctx->grid[i]; 563 } 564 push_to_queue(_ctx, c, (i + _ctx->cols) % _ctx->cols, (i + _ctx->cols) / _ctx->cols); 565 } 566 567 // Clear the first line of the screen. 568 struct flanterm_fb_char empty; 569 empty.c = ' '; 570 empty.fg = ctx->text_fg; 571 empty.bg = ctx->text_bg; 572 for (size_t i = 0; i < _ctx->cols; i++) { 573 push_to_queue(_ctx, &empty, i, _ctx->scroll_top_margin); 574 } 575} 576 577static void flanterm_fb_scroll(struct flanterm_context *_ctx) { 578 struct flanterm_fb_context *ctx = (void *)_ctx; 579 580 for (size_t i = (_ctx->scroll_top_margin + 1) * _ctx->cols; 581 i < _ctx->scroll_bottom_margin * _ctx->cols; i++) { 582 struct flanterm_fb_char *c; 583 struct flanterm_fb_queue_item *q = ctx->map[i]; 584 if (q != NULL) { 585 c = &q->c; 586 } else { 587 c = &ctx->grid[i]; 588 } 589 push_to_queue(_ctx, c, (i - _ctx->cols) % _ctx->cols, (i - _ctx->cols) / _ctx->cols); 590 } 591 592 // Clear the last line of the screen. 593 struct flanterm_fb_char empty; 594 empty.c = ' '; 595 empty.fg = ctx->text_fg; 596 empty.bg = ctx->text_bg; 597 for (size_t i = 0; i < _ctx->cols; i++) { 598 push_to_queue(_ctx, &empty, i, _ctx->scroll_bottom_margin - 1); 599 } 600} 601 602static void flanterm_fb_clear(struct flanterm_context *_ctx, bool move) { 603 struct flanterm_fb_context *ctx = (void *)_ctx; 604 605 struct flanterm_fb_char empty; 606 empty.c = ' '; 607 empty.fg = ctx->text_fg; 608 empty.bg = ctx->text_bg; 609 for (size_t i = 0; i < _ctx->rows * _ctx->cols; i++) { 610 push_to_queue(_ctx, &empty, i % _ctx->cols, i / _ctx->cols); 611 } 612 613 if (move) { 614 ctx->cursor_x = 0; 615 ctx->cursor_y = 0; 616 } 617} 618 619static void flanterm_fb_set_cursor_pos(struct flanterm_context *_ctx, size_t x, size_t y) { 620 struct flanterm_fb_context *ctx = (void *)_ctx; 621 622 if (x >= _ctx->cols) { 623 if ((int)x < 0) { 624 x = 0; 625 } else { 626 x = _ctx->cols - 1; 627 } 628 } 629 if (y >= _ctx->rows) { 630 if ((int)y < 0) { 631 y = 0; 632 } else { 633 y = _ctx->rows - 1; 634 } 635 } 636 ctx->cursor_x = x; 637 ctx->cursor_y = y; 638} 639 640static void flanterm_fb_get_cursor_pos(struct flanterm_context *_ctx, size_t *x, size_t *y) { 641 struct flanterm_fb_context *ctx = (void *)_ctx; 642 643 *x = ctx->cursor_x >= _ctx->cols ? _ctx->cols - 1 : ctx->cursor_x; 644 *y = ctx->cursor_y >= _ctx->rows ? _ctx->rows - 1 : ctx->cursor_y; 645} 646 647static void flanterm_fb_move_character(struct flanterm_context *_ctx, size_t new_x, size_t new_y, size_t old_x, size_t old_y) { 648 struct flanterm_fb_context *ctx = (void *)_ctx; 649 650 if (old_x >= _ctx->cols || old_y >= _ctx->rows 651 || new_x >= _ctx->cols || new_y >= _ctx->rows) { 652 return; 653 } 654 655 size_t i = old_x + old_y * _ctx->cols; 656 657 struct flanterm_fb_char *c; 658 struct flanterm_fb_queue_item *q = ctx->map[i]; 659 if (q != NULL) { 660 c = &q->c; 661 } else { 662 c = &ctx->grid[i]; 663 } 664 665 push_to_queue(_ctx, c, new_x, new_y); 666} 667 668static void flanterm_fb_set_text_fg(struct flanterm_context *_ctx, size_t fg) { 669 struct flanterm_fb_context *ctx = (void *)_ctx; 670 671 ctx->text_fg = ctx->ansi_colours[fg]; 672} 673 674static void flanterm_fb_set_text_bg(struct flanterm_context *_ctx, size_t bg) { 675 struct flanterm_fb_context *ctx = (void *)_ctx; 676 677 ctx->text_bg = ctx->ansi_colours[bg]; 678} 679 680static void flanterm_fb_set_text_fg_bright(struct flanterm_context *_ctx, size_t fg) { 681 struct flanterm_fb_context *ctx = (void *)_ctx; 682 683 ctx->text_fg = ctx->ansi_bright_colours[fg]; 684} 685 686static void flanterm_fb_set_text_bg_bright(struct flanterm_context *_ctx, size_t bg) { 687 struct flanterm_fb_context *ctx = (void *)_ctx; 688 689 ctx->text_bg = ctx->ansi_bright_colours[bg]; 690} 691 692static void flanterm_fb_set_text_fg_rgb(struct flanterm_context *_ctx, uint32_t fg) { 693 struct flanterm_fb_context *ctx = (void *)_ctx; 694 695 ctx->text_fg = convert_colour(_ctx, fg); 696} 697 698static void flanterm_fb_set_text_bg_rgb(struct flanterm_context *_ctx, uint32_t bg) { 699 struct flanterm_fb_context *ctx = (void *)_ctx; 700 701 ctx->text_bg = convert_colour(_ctx, bg); 702} 703 704static void flanterm_fb_set_text_fg_default(struct flanterm_context *_ctx) { 705 struct flanterm_fb_context *ctx = (void *)_ctx; 706 707 ctx->text_fg = ctx->default_fg; 708} 709 710static void flanterm_fb_set_text_bg_default(struct flanterm_context *_ctx) { 711 struct flanterm_fb_context *ctx = (void *)_ctx; 712 713 ctx->text_bg = 0xffffffff; 714} 715 716static void flanterm_fb_set_text_fg_default_bright(struct flanterm_context *_ctx) { 717 struct flanterm_fb_context *ctx = (void *)_ctx; 718 719 ctx->text_fg = ctx->default_fg_bright; 720} 721 722static void flanterm_fb_set_text_bg_default_bright(struct flanterm_context *_ctx) { 723 struct flanterm_fb_context *ctx = (void *)_ctx; 724 725 ctx->text_bg = ctx->default_bg_bright; 726} 727 728static void draw_cursor(struct flanterm_context *_ctx) { 729 struct flanterm_fb_context *ctx = (void *)_ctx; 730 731 if (ctx->cursor_x >= _ctx->cols || ctx->cursor_y >= _ctx->rows) { 732 return; 733 } 734 735 size_t i = ctx->cursor_x + ctx->cursor_y * _ctx->cols; 736 737 struct flanterm_fb_char c; 738 struct flanterm_fb_queue_item *q = ctx->map[i]; 739 if (q != NULL) { 740 c = q->c; 741 } else { 742 c = ctx->grid[i]; 743 } 744 uint32_t tmp = c.fg; 745 c.fg = c.bg; 746 c.bg = tmp; 747 plot_char(_ctx, &c, ctx->cursor_x, ctx->cursor_y); 748 if (q != NULL) { 749 ctx->grid[i] = q->c; 750 ctx->map[i] = NULL; 751 } 752} 753 754static void flanterm_fb_double_buffer_flush(struct flanterm_context *_ctx) { 755 struct flanterm_fb_context *ctx = (void *)_ctx; 756 757 if (_ctx->cursor_enabled) { 758 draw_cursor(_ctx); 759 } 760 761 for (size_t i = 0; i < ctx->queue_i; i++) { 762 struct flanterm_fb_queue_item *q = &ctx->queue[i]; 763 size_t offset = q->y * _ctx->cols + q->x; 764 if (ctx->map[offset] == NULL) { 765 continue; 766 } 767 struct flanterm_fb_char *old = &ctx->grid[offset]; 768 if (q->c.bg == old->bg && q->c.fg == old->fg) { 769 plot_char_fast(_ctx, old, &q->c, q->x, q->y); 770 } else { 771 plot_char(_ctx, &q->c, q->x, q->y); 772 } 773 ctx->grid[offset] = q->c; 774 ctx->map[offset] = NULL; 775 } 776 777 if ((ctx->old_cursor_x != ctx->cursor_x || ctx->old_cursor_y != ctx->cursor_y) || _ctx->cursor_enabled == false) { 778 if (ctx->old_cursor_x < _ctx->cols && ctx->old_cursor_y < _ctx->rows) { 779 plot_char(_ctx, &ctx->grid[ctx->old_cursor_x + ctx->old_cursor_y * _ctx->cols], ctx->old_cursor_x, ctx->old_cursor_y); 780 } 781 } 782 783 ctx->old_cursor_x = ctx->cursor_x; 784 ctx->old_cursor_y = ctx->cursor_y; 785 786 ctx->queue_i = 0; 787} 788 789static void flanterm_fb_raw_putchar(struct flanterm_context *_ctx, uint8_t c) { 790 struct flanterm_fb_context *ctx = (void *)_ctx; 791 792 if (ctx->cursor_x >= _ctx->cols && (ctx->cursor_y < _ctx->scroll_bottom_margin - 1 || _ctx->scroll_enabled)) { 793 ctx->cursor_x = 0; 794 ctx->cursor_y++; 795 if (ctx->cursor_y == _ctx->scroll_bottom_margin) { 796 ctx->cursor_y--; 797 flanterm_fb_scroll(_ctx); 798 } 799 if (ctx->cursor_y >= _ctx->cols) { 800 ctx->cursor_y = _ctx->cols - 1; 801 } 802 } 803 804 struct flanterm_fb_char ch; 805 ch.c = c; 806 ch.fg = ctx->text_fg; 807 ch.bg = ctx->text_bg; 808 push_to_queue(_ctx, &ch, ctx->cursor_x++, ctx->cursor_y); 809} 810 811static void flanterm_fb_full_refresh(struct flanterm_context *_ctx) { 812 struct flanterm_fb_context *ctx = (void *)_ctx; 813 814#ifdef FLANTERM_FB_DISABLE_CANVAS 815 uint32_t default_bg = ctx->default_bg; 816#endif 817 818 for (size_t y = 0; y < ctx->height; y++) { 819 for (size_t x = 0; x < ctx->width; x++) { 820#ifndef FLANTERM_FB_DISABLE_CANVAS 821 ctx->framebuffer[y * (ctx->pitch / sizeof(uint32_t)) + x] = ctx->canvas[y * ctx->width + x]; 822#else 823 ctx->framebuffer[y * (ctx->pitch / sizeof(uint32_t)) + x] = default_bg; 824#endif 825 } 826 } 827 828 for (size_t i = 0; i < (size_t)_ctx->rows * _ctx->cols; i++) { 829 size_t x = i % _ctx->cols; 830 size_t y = i / _ctx->cols; 831 832 plot_char(_ctx, &ctx->grid[i], x, y); 833 } 834 835 if (_ctx->cursor_enabled) { 836 draw_cursor(_ctx); 837 } 838} 839 840static void flanterm_fb_deinit(struct flanterm_context *_ctx, void (*_free)(void *, size_t)) { 841 struct flanterm_fb_context *ctx = (void *)_ctx; 842 843 if (_free == NULL) { 844 return; 845 } 846 847 _free(ctx->font_bits, ctx->font_bits_size); 848 _free(ctx->font_bool, ctx->font_bool_size); 849 _free(ctx->grid, ctx->grid_size); 850 _free(ctx->queue, ctx->queue_size); 851 _free(ctx->map, ctx->map_size); 852 853#ifndef FLANTERM_FB_DISABLE_CANVAS 854 _free(ctx->canvas, ctx->canvas_size); 855#endif 856 857 _free(ctx, sizeof(struct flanterm_fb_context)); 858} 859 860struct flanterm_context *flanterm_fb_init( 861 void *(*_malloc)(size_t), 862 void (*_free)(void *, size_t), 863 uint32_t *framebuffer, size_t width, size_t height, size_t pitch, 864#ifdef FLANTERM_FB_SUPPORT_BPP 865 uint8_t red_mask_size, uint8_t red_mask_shift, 866 uint8_t green_mask_size, uint8_t green_mask_shift, 867 uint8_t blue_mask_size, uint8_t blue_mask_shift, 868#endif 869#ifndef FLANTERM_FB_DISABLE_CANVAS 870 uint32_t *canvas, 871#endif 872 uint32_t *ansi_colours, uint32_t *ansi_bright_colours, 873 uint32_t *default_bg, uint32_t *default_fg, 874 uint32_t *default_bg_bright, uint32_t *default_fg_bright, 875 void *font, size_t font_width, size_t font_height, size_t font_spacing, 876 size_t font_scale_x, size_t font_scale_y, 877 size_t margin 878) { 879#ifndef FLANTERM_FB_DISABLE_BUMP_ALLOC 880 size_t orig_bump_alloc_ptr = bump_alloc_ptr; 881#endif 882 883#ifdef FLANTERM_FB_SUPPORT_BPP 884 if (red_mask_size < 8 || red_mask_size != green_mask_size || red_mask_size != blue_mask_size) { 885 return NULL; 886 } 887#endif 888 889 if (_malloc == NULL) { 890#ifndef FLANTERM_FB_DISABLE_BUMP_ALLOC 891 _malloc = bump_alloc; 892#else 893 return NULL; 894#endif 895 } 896 897 struct flanterm_fb_context *ctx = NULL; 898 ctx = _malloc(sizeof(struct flanterm_fb_context)); 899 if (ctx == NULL) { 900 goto fail; 901 } 902 903 struct flanterm_context *_ctx = (void *)ctx; 904 memset(ctx, 0, sizeof(struct flanterm_fb_context)); 905 906#ifdef FLANTERM_FB_SUPPORT_BPP 907 ctx->red_mask_size = red_mask_size; 908 ctx->red_mask_shift = red_mask_shift + (red_mask_size - 8); 909 ctx->green_mask_size = green_mask_size; 910 ctx->green_mask_shift = green_mask_shift + (green_mask_size - 8); 911 ctx->blue_mask_size = blue_mask_size; 912 ctx->blue_mask_shift = blue_mask_shift + (blue_mask_size - 8); 913#endif 914 915 if (ansi_colours != NULL) { 916 for (size_t i = 0; i < 8; i++) { 917 ctx->ansi_colours[i] = convert_colour(_ctx, ansi_colours[i]); 918 } 919 } else { 920 ctx->ansi_colours[0] = convert_colour(_ctx, 0x00000000); // black 921 ctx->ansi_colours[1] = convert_colour(_ctx, 0x00aa0000); // red 922 ctx->ansi_colours[2] = convert_colour(_ctx, 0x0000aa00); // green 923 ctx->ansi_colours[3] = convert_colour(_ctx, 0x00aa5500); // brown 924 ctx->ansi_colours[4] = convert_colour(_ctx, 0x000000aa); // blue 925 ctx->ansi_colours[5] = convert_colour(_ctx, 0x00aa00aa); // magenta 926 ctx->ansi_colours[6] = convert_colour(_ctx, 0x0000aaaa); // cyan 927 ctx->ansi_colours[7] = convert_colour(_ctx, 0x00aaaaaa); // grey 928 } 929 930 if (ansi_bright_colours != NULL) { 931 for (size_t i = 0; i < 8; i++) { 932 ctx->ansi_bright_colours[i] = convert_colour(_ctx, ansi_bright_colours[i]); 933 } 934 } else { 935 ctx->ansi_bright_colours[0] = convert_colour(_ctx, 0x00555555); // black 936 ctx->ansi_bright_colours[1] = convert_colour(_ctx, 0x00ff5555); // red 937 ctx->ansi_bright_colours[2] = convert_colour(_ctx, 0x0055ff55); // green 938 ctx->ansi_bright_colours[3] = convert_colour(_ctx, 0x00ffff55); // brown 939 ctx->ansi_bright_colours[4] = convert_colour(_ctx, 0x005555ff); // blue 940 ctx->ansi_bright_colours[5] = convert_colour(_ctx, 0x00ff55ff); // magenta 941 ctx->ansi_bright_colours[6] = convert_colour(_ctx, 0x0055ffff); // cyan 942 ctx->ansi_bright_colours[7] = convert_colour(_ctx, 0x00ffffff); // grey 943 } 944 945 if (default_bg != NULL) { 946 ctx->default_bg = convert_colour(_ctx, *default_bg); 947 } else { 948 ctx->default_bg = 0x00000000; // background (black) 949 } 950 951 if (default_fg != NULL) { 952 ctx->default_fg = convert_colour(_ctx, *default_fg); 953 } else { 954 ctx->default_fg = convert_colour(_ctx, 0x00aaaaaa); // foreground (grey) 955 } 956 957 if (default_bg_bright != NULL) { 958 ctx->default_bg_bright = convert_colour(_ctx, *default_bg_bright); 959 } else { 960 ctx->default_bg_bright = convert_colour(_ctx, 0x00555555); // background (black) 961 } 962 963 if (default_fg_bright != NULL) { 964 ctx->default_fg_bright = convert_colour(_ctx, *default_fg_bright); 965 } else { 966 ctx->default_fg_bright = convert_colour(_ctx, 0x00ffffff); // foreground (grey) 967 } 968 969 ctx->text_fg = ctx->default_fg; 970 ctx->text_bg = 0xffffffff; 971 972 ctx->framebuffer = (void *)framebuffer; 973 ctx->width = width; 974 ctx->height = height; 975 ctx->pitch = pitch; 976 977#define FONT_BYTES ((font_width * font_height * FLANTERM_FB_FONT_GLYPHS) / 8) 978 979 if (font != NULL) { 980 ctx->font_width = font_width; 981 ctx->font_height = font_height; 982 ctx->font_bits_size = FONT_BYTES; 983 ctx->font_bits = _malloc(ctx->font_bits_size); 984 if (ctx->font_bits == NULL) { 985 goto fail; 986 } 987 memcpy(ctx->font_bits, font, ctx->font_bits_size); 988 } else { 989 ctx->font_width = font_width = 8; 990 ctx->font_height = font_height = 16; 991 ctx->font_bits_size = FONT_BYTES; 992 font_spacing = 1; 993 ctx->font_bits = _malloc(ctx->font_bits_size); 994 if (ctx->font_bits == NULL) { 995 goto fail; 996 } 997 memcpy(ctx->font_bits, builtin_font, ctx->font_bits_size); 998 } 999 1000#undef FONT_BYTES 1001 1002 ctx->font_width += font_spacing; 1003 1004 ctx->font_bool_size = FLANTERM_FB_FONT_GLYPHS * font_height * ctx->font_width * sizeof(bool); 1005 ctx->font_bool = _malloc(ctx->font_bool_size); 1006 if (ctx->font_bool == NULL) { 1007 goto fail; 1008 } 1009 1010 for (size_t i = 0; i < FLANTERM_FB_FONT_GLYPHS; i++) { 1011 uint8_t *glyph = &ctx->font_bits[i * font_height]; 1012 1013 for (size_t y = 0; y < font_height; y++) { 1014 // NOTE: the characters in VGA fonts are always one byte wide. 1015 // 9 dot wide fonts have 8 dots and one empty column, except 1016 // characters 0xC0-0xDF replicate column 9. 1017 for (size_t x = 0; x < 8; x++) { 1018 size_t offset = i * font_height * ctx->font_width + y * ctx->font_width + x; 1019 1020 if ((glyph[y] & (0x80 >> x))) { 1021 ctx->font_bool[offset] = true; 1022 } else { 1023 ctx->font_bool[offset] = false; 1024 } 1025 } 1026 // fill columns above 8 like VGA Line Graphics Mode does 1027 for (size_t x = 8; x < ctx->font_width; x++) { 1028 size_t offset = i * font_height * ctx->font_width + y * ctx->font_width + x; 1029 1030 if (i >= 0xc0 && i <= 0xdf) { 1031 ctx->font_bool[offset] = (glyph[y] & 1); 1032 } else { 1033 ctx->font_bool[offset] = false; 1034 } 1035 } 1036 } 1037 } 1038 1039 ctx->font_scale_x = font_scale_x; 1040 ctx->font_scale_y = font_scale_y; 1041 1042 ctx->glyph_width = ctx->font_width * font_scale_x; 1043 ctx->glyph_height = font_height * font_scale_y; 1044 1045 _ctx->cols = (ctx->width - margin * 2) / ctx->glyph_width; 1046 _ctx->rows = (ctx->height - margin * 2) / ctx->glyph_height; 1047 1048 ctx->offset_x = margin + ((ctx->width - margin * 2) % ctx->glyph_width) / 2; 1049 ctx->offset_y = margin + ((ctx->height - margin * 2) % ctx->glyph_height) / 2; 1050 1051 ctx->grid_size = _ctx->rows * _ctx->cols * sizeof(struct flanterm_fb_char); 1052 ctx->grid = _malloc(ctx->grid_size); 1053 if (ctx->grid == NULL) { 1054 goto fail; 1055 } 1056 for (size_t i = 0; i < _ctx->rows * _ctx->cols; i++) { 1057 ctx->grid[i].c = ' '; 1058 ctx->grid[i].fg = ctx->text_fg; 1059 ctx->grid[i].bg = ctx->text_bg; 1060 } 1061 1062 ctx->queue_size = _ctx->rows * _ctx->cols * sizeof(struct flanterm_fb_queue_item); 1063 ctx->queue = _malloc(ctx->queue_size); 1064 if (ctx->queue == NULL) { 1065 goto fail; 1066 } 1067 ctx->queue_i = 0; 1068 memset(ctx->queue, 0, ctx->queue_size); 1069 1070 ctx->map_size = _ctx->rows * _ctx->cols * sizeof(struct flanterm_fb_queue_item *); 1071 ctx->map = _malloc(ctx->map_size); 1072 if (ctx->map == NULL) { 1073 goto fail; 1074 } 1075 memset(ctx->map, 0, ctx->map_size); 1076 1077#ifndef FLANTERM_FB_DISABLE_CANVAS 1078 ctx->canvas_size = ctx->width * ctx->height * sizeof(uint32_t); 1079 ctx->canvas = _malloc(ctx->canvas_size); 1080 if (ctx->canvas == NULL) { 1081 goto fail; 1082 } 1083 if (canvas != NULL) { 1084 for (size_t i = 0; i < ctx->width * ctx->height; i++) { 1085 ctx->canvas[i] = convert_colour(_ctx, canvas[i]); 1086 } 1087 } else { 1088 for (size_t i = 0; i < ctx->width * ctx->height; i++) { 1089 ctx->canvas[i] = ctx->default_bg; 1090 } 1091 } 1092#endif 1093 1094 _ctx->raw_putchar = flanterm_fb_raw_putchar; 1095 _ctx->clear = flanterm_fb_clear; 1096 _ctx->set_cursor_pos = flanterm_fb_set_cursor_pos; 1097 _ctx->get_cursor_pos = flanterm_fb_get_cursor_pos; 1098 _ctx->set_text_fg = flanterm_fb_set_text_fg; 1099 _ctx->set_text_bg = flanterm_fb_set_text_bg; 1100 _ctx->set_text_fg_bright = flanterm_fb_set_text_fg_bright; 1101 _ctx->set_text_bg_bright = flanterm_fb_set_text_bg_bright; 1102 _ctx->set_text_fg_rgb = flanterm_fb_set_text_fg_rgb; 1103 _ctx->set_text_bg_rgb = flanterm_fb_set_text_bg_rgb; 1104 _ctx->set_text_fg_default = flanterm_fb_set_text_fg_default; 1105 _ctx->set_text_bg_default = flanterm_fb_set_text_bg_default; 1106 _ctx->set_text_fg_default_bright = flanterm_fb_set_text_fg_default_bright; 1107 _ctx->set_text_bg_default_bright = flanterm_fb_set_text_bg_default_bright; 1108 _ctx->move_character = flanterm_fb_move_character; 1109 _ctx->scroll = flanterm_fb_scroll; 1110 _ctx->revscroll = flanterm_fb_revscroll; 1111 _ctx->swap_palette = flanterm_fb_swap_palette; 1112 _ctx->save_state = flanterm_fb_save_state; 1113 _ctx->restore_state = flanterm_fb_restore_state; 1114 _ctx->double_buffer_flush = flanterm_fb_double_buffer_flush; 1115 _ctx->full_refresh = flanterm_fb_full_refresh; 1116 _ctx->deinit = flanterm_fb_deinit; 1117 1118 flanterm_context_reinit(_ctx); 1119 flanterm_fb_full_refresh(_ctx); 1120 1121 return _ctx; 1122 1123fail: 1124#ifndef FLANTERM_FB_DISABLE_BUMP_ALLOC 1125 if (_malloc == bump_alloc) { 1126 bump_alloc_ptr = orig_bump_alloc_ptr; 1127 return NULL; 1128 } 1129#endif 1130 1131 if (_free == NULL) { 1132 return NULL; 1133 } 1134 1135#ifndef FLANTERM_FB_DISABLE_CANVAS 1136 if (ctx->canvas != NULL) { 1137 _free(ctx->canvas, ctx->canvas_size); 1138 } 1139#endif 1140 if (ctx->map != NULL) { 1141 _free(ctx->map, ctx->map_size); 1142 } 1143 if (ctx->queue != NULL) { 1144 _free(ctx->queue, ctx->queue_size); 1145 } 1146 if (ctx->grid != NULL) { 1147 _free(ctx->grid, ctx->grid_size); 1148 } 1149 if (ctx->font_bool != NULL) { 1150 _free(ctx->font_bool, ctx->font_bool_size); 1151 } 1152 if (ctx->font_bits != NULL) { 1153 _free(ctx->font_bits, ctx->font_bits_size); 1154 } 1155 if (ctx != NULL) { 1156 _free(ctx, sizeof(struct flanterm_fb_context)); 1157 } 1158 1159 return NULL; 1160}