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 479#ifdef FLANTERM_FB_ENABLE_MASKING 480static void plot_char_masked(struct flanterm_context *_ctx, struct flanterm_fb_char *old, struct flanterm_fb_char *c, size_t x, size_t y) { 481 struct flanterm_fb_context *ctx = (void *)_ctx; 482 483 if (x >= _ctx->cols || y >= _ctx->rows) { 484 return; 485 } 486 487 x = ctx->offset_x + x * ctx->glyph_width; 488 y = ctx->offset_y + y * ctx->glyph_height; 489 490#ifdef FLANTERM_FB_DISABLE_CANVAS 491 uint32_t default_bg = ctx->default_bg; 492#endif 493 494 bool *new_glyph = &ctx->font_bool[c->c * ctx->font_height * ctx->font_width]; 495 bool *old_glyph = &ctx->font_bool[old->c * ctx->font_height * ctx->font_width]; 496 for (size_t gy = 0; gy < ctx->glyph_height; gy++) { 497 uint8_t fy = gy / ctx->font_scale_y; 498 volatile uint32_t *fb_line = ctx->framebuffer + x + (y + gy) * (ctx->pitch / 4); 499#ifndef FLANTERM_FB_DISABLE_CANVAS 500 uint32_t *canvas_line = ctx->canvas + x + (y + gy) * ctx->width; 501#endif 502 for (size_t fx = 0; fx < ctx->font_width; fx++) { 503 bool old_draw = old_glyph[fy * ctx->font_width + fx]; 504 bool new_draw = new_glyph[fy * ctx->font_width + fx]; 505 if (old_draw == new_draw) 506 continue; 507 for (size_t i = 0; i < ctx->font_scale_x; i++) { 508 size_t gx = ctx->font_scale_x * fx + i; 509#ifndef FLANTERM_FB_DISABLE_CANVAS 510 uint32_t bg = c->bg == 0xffffffff ? canvas_line[gx] : c->bg; 511 uint32_t fg = c->fg == 0xffffffff ? canvas_line[gx] : c->fg; 512#else 513 uint32_t bg = c->bg == 0xffffffff ? default_bg : c->bg; 514 uint32_t fg = c->fg == 0xffffffff ? default_bg : c->fg; 515#endif 516 fb_line[gx] = new_draw ? fg : bg; 517 } 518 } 519 } 520} 521#endif 522 523static inline bool compare_char(struct flanterm_fb_char *a, struct flanterm_fb_char *b) { 524 return !(a->c != b->c || a->bg != b->bg || a->fg != b->fg); 525} 526 527static void push_to_queue(struct flanterm_context *_ctx, struct flanterm_fb_char *c, size_t x, size_t y) { 528 struct flanterm_fb_context *ctx = (void *)_ctx; 529 530 if (x >= _ctx->cols || y >= _ctx->rows) { 531 return; 532 } 533 534 size_t i = y * _ctx->cols + x; 535 536 struct flanterm_fb_queue_item *q = ctx->map[i]; 537 538 if (q == NULL) { 539 if (compare_char(&ctx->grid[i], c)) { 540 return; 541 } 542 q = &ctx->queue[ctx->queue_i++]; 543 q->x = x; 544 q->y = y; 545 ctx->map[i] = q; 546 } 547 548 q->c = *c; 549} 550 551static void flanterm_fb_revscroll(struct flanterm_context *_ctx) { 552 struct flanterm_fb_context *ctx = (void *)_ctx; 553 554 for (size_t i = (_ctx->scroll_bottom_margin - 1) * _ctx->cols - 1; 555 i >= _ctx->scroll_top_margin * _ctx->cols; i--) { 556 if (i == (size_t)-1) { 557 break; 558 } 559 struct flanterm_fb_char *c; 560 struct flanterm_fb_queue_item *q = ctx->map[i]; 561 if (q != NULL) { 562 c = &q->c; 563 } else { 564 c = &ctx->grid[i]; 565 } 566 push_to_queue(_ctx, c, (i + _ctx->cols) % _ctx->cols, (i + _ctx->cols) / _ctx->cols); 567 } 568 569 // Clear the first line of the screen. 570 struct flanterm_fb_char empty; 571 empty.c = ' '; 572 empty.fg = ctx->text_fg; 573 empty.bg = ctx->text_bg; 574 for (size_t i = 0; i < _ctx->cols; i++) { 575 push_to_queue(_ctx, &empty, i, _ctx->scroll_top_margin); 576 } 577} 578 579static void flanterm_fb_scroll(struct flanterm_context *_ctx) { 580 struct flanterm_fb_context *ctx = (void *)_ctx; 581 582 for (size_t i = (_ctx->scroll_top_margin + 1) * _ctx->cols; 583 i < _ctx->scroll_bottom_margin * _ctx->cols; i++) { 584 struct flanterm_fb_char *c; 585 struct flanterm_fb_queue_item *q = ctx->map[i]; 586 if (q != NULL) { 587 c = &q->c; 588 } else { 589 c = &ctx->grid[i]; 590 } 591 push_to_queue(_ctx, c, (i - _ctx->cols) % _ctx->cols, (i - _ctx->cols) / _ctx->cols); 592 } 593 594 // Clear the last line of the screen. 595 struct flanterm_fb_char empty; 596 empty.c = ' '; 597 empty.fg = ctx->text_fg; 598 empty.bg = ctx->text_bg; 599 for (size_t i = 0; i < _ctx->cols; i++) { 600 push_to_queue(_ctx, &empty, i, _ctx->scroll_bottom_margin - 1); 601 } 602} 603 604static void flanterm_fb_clear(struct flanterm_context *_ctx, bool move) { 605 struct flanterm_fb_context *ctx = (void *)_ctx; 606 607 struct flanterm_fb_char empty; 608 empty.c = ' '; 609 empty.fg = ctx->text_fg; 610 empty.bg = ctx->text_bg; 611 for (size_t i = 0; i < _ctx->rows * _ctx->cols; i++) { 612 push_to_queue(_ctx, &empty, i % _ctx->cols, i / _ctx->cols); 613 } 614 615 if (move) { 616 ctx->cursor_x = 0; 617 ctx->cursor_y = 0; 618 } 619} 620 621static void flanterm_fb_set_cursor_pos(struct flanterm_context *_ctx, size_t x, size_t y) { 622 struct flanterm_fb_context *ctx = (void *)_ctx; 623 624 if (x >= _ctx->cols) { 625 if ((int)x < 0) { 626 x = 0; 627 } else { 628 x = _ctx->cols - 1; 629 } 630 } 631 if (y >= _ctx->rows) { 632 if ((int)y < 0) { 633 y = 0; 634 } else { 635 y = _ctx->rows - 1; 636 } 637 } 638 ctx->cursor_x = x; 639 ctx->cursor_y = y; 640} 641 642static void flanterm_fb_get_cursor_pos(struct flanterm_context *_ctx, size_t *x, size_t *y) { 643 struct flanterm_fb_context *ctx = (void *)_ctx; 644 645 *x = ctx->cursor_x >= _ctx->cols ? _ctx->cols - 1 : ctx->cursor_x; 646 *y = ctx->cursor_y >= _ctx->rows ? _ctx->rows - 1 : ctx->cursor_y; 647} 648 649static 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) { 650 struct flanterm_fb_context *ctx = (void *)_ctx; 651 652 if (old_x >= _ctx->cols || old_y >= _ctx->rows 653 || new_x >= _ctx->cols || new_y >= _ctx->rows) { 654 return; 655 } 656 657 size_t i = old_x + old_y * _ctx->cols; 658 659 struct flanterm_fb_char *c; 660 struct flanterm_fb_queue_item *q = ctx->map[i]; 661 if (q != NULL) { 662 c = &q->c; 663 } else { 664 c = &ctx->grid[i]; 665 } 666 667 push_to_queue(_ctx, c, new_x, new_y); 668} 669 670static void flanterm_fb_set_text_fg(struct flanterm_context *_ctx, size_t fg) { 671 struct flanterm_fb_context *ctx = (void *)_ctx; 672 673 ctx->text_fg = ctx->ansi_colours[fg]; 674} 675 676static void flanterm_fb_set_text_bg(struct flanterm_context *_ctx, size_t bg) { 677 struct flanterm_fb_context *ctx = (void *)_ctx; 678 679 ctx->text_bg = ctx->ansi_colours[bg]; 680} 681 682static void flanterm_fb_set_text_fg_bright(struct flanterm_context *_ctx, size_t fg) { 683 struct flanterm_fb_context *ctx = (void *)_ctx; 684 685 ctx->text_fg = ctx->ansi_bright_colours[fg]; 686} 687 688static void flanterm_fb_set_text_bg_bright(struct flanterm_context *_ctx, size_t bg) { 689 struct flanterm_fb_context *ctx = (void *)_ctx; 690 691 ctx->text_bg = ctx->ansi_bright_colours[bg]; 692} 693 694static void flanterm_fb_set_text_fg_rgb(struct flanterm_context *_ctx, uint32_t fg) { 695 struct flanterm_fb_context *ctx = (void *)_ctx; 696 697 ctx->text_fg = convert_colour(_ctx, fg); 698} 699 700static void flanterm_fb_set_text_bg_rgb(struct flanterm_context *_ctx, uint32_t bg) { 701 struct flanterm_fb_context *ctx = (void *)_ctx; 702 703 ctx->text_bg = convert_colour(_ctx, bg); 704} 705 706static void flanterm_fb_set_text_fg_default(struct flanterm_context *_ctx) { 707 struct flanterm_fb_context *ctx = (void *)_ctx; 708 709 ctx->text_fg = ctx->default_fg; 710} 711 712static void flanterm_fb_set_text_bg_default(struct flanterm_context *_ctx) { 713 struct flanterm_fb_context *ctx = (void *)_ctx; 714 715 ctx->text_bg = 0xffffffff; 716} 717 718static void flanterm_fb_set_text_fg_default_bright(struct flanterm_context *_ctx) { 719 struct flanterm_fb_context *ctx = (void *)_ctx; 720 721 ctx->text_fg = ctx->default_fg_bright; 722} 723 724static void flanterm_fb_set_text_bg_default_bright(struct flanterm_context *_ctx) { 725 struct flanterm_fb_context *ctx = (void *)_ctx; 726 727 ctx->text_bg = ctx->default_bg_bright; 728} 729 730static void draw_cursor(struct flanterm_context *_ctx) { 731 struct flanterm_fb_context *ctx = (void *)_ctx; 732 733 if (ctx->cursor_x >= _ctx->cols || ctx->cursor_y >= _ctx->rows) { 734 return; 735 } 736 737 size_t i = ctx->cursor_x + ctx->cursor_y * _ctx->cols; 738 739 struct flanterm_fb_char c; 740 struct flanterm_fb_queue_item *q = ctx->map[i]; 741 if (q != NULL) { 742 c = q->c; 743 } else { 744 c = ctx->grid[i]; 745 } 746 uint32_t tmp = c.fg; 747 c.fg = c.bg; 748 c.bg = tmp; 749 plot_char(_ctx, &c, ctx->cursor_x, ctx->cursor_y); 750 if (q != NULL) { 751 ctx->grid[i] = q->c; 752 ctx->map[i] = NULL; 753 } 754} 755 756static void flanterm_fb_double_buffer_flush(struct flanterm_context *_ctx) { 757 struct flanterm_fb_context *ctx = (void *)_ctx; 758 759 if (_ctx->cursor_enabled) { 760 draw_cursor(_ctx); 761 } 762 763 for (size_t i = 0; i < ctx->queue_i; i++) { 764 struct flanterm_fb_queue_item *q = &ctx->queue[i]; 765 size_t offset = q->y * _ctx->cols + q->x; 766 if (ctx->map[offset] == NULL) { 767 continue; 768 } 769 #ifdef FLANTERM_FB_ENABLE_MASKING 770 struct flanterm_fb_char *old = &ctx->grid[offset]; 771 if (q->c.bg == old->bg && q->c.fg == old->fg) { 772 plot_char_masked(_ctx, old, &q->c, q->x, q->y); 773 } else { 774 plot_char(_ctx, &q->c, q->x, q->y); 775 } 776 #else 777 plot_char(_ctx, &q->c, q->x, q->y); 778 #endif 779 ctx->grid[offset] = q->c; 780 ctx->map[offset] = NULL; 781 } 782 783 if ((ctx->old_cursor_x != ctx->cursor_x || ctx->old_cursor_y != ctx->cursor_y) || _ctx->cursor_enabled == false) { 784 if (ctx->old_cursor_x < _ctx->cols && ctx->old_cursor_y < _ctx->rows) { 785 plot_char(_ctx, &ctx->grid[ctx->old_cursor_x + ctx->old_cursor_y * _ctx->cols], ctx->old_cursor_x, ctx->old_cursor_y); 786 } 787 } 788 789 ctx->old_cursor_x = ctx->cursor_x; 790 ctx->old_cursor_y = ctx->cursor_y; 791 792 ctx->queue_i = 0; 793} 794 795static void flanterm_fb_raw_putchar(struct flanterm_context *_ctx, uint8_t c) { 796 struct flanterm_fb_context *ctx = (void *)_ctx; 797 798 if (ctx->cursor_x >= _ctx->cols && (ctx->cursor_y < _ctx->scroll_bottom_margin - 1 || _ctx->scroll_enabled)) { 799 ctx->cursor_x = 0; 800 ctx->cursor_y++; 801 if (ctx->cursor_y == _ctx->scroll_bottom_margin) { 802 ctx->cursor_y--; 803 flanterm_fb_scroll(_ctx); 804 } 805 if (ctx->cursor_y >= _ctx->cols) { 806 ctx->cursor_y = _ctx->cols - 1; 807 } 808 } 809 810 struct flanterm_fb_char ch; 811 ch.c = c; 812 ch.fg = ctx->text_fg; 813 ch.bg = ctx->text_bg; 814 push_to_queue(_ctx, &ch, ctx->cursor_x++, ctx->cursor_y); 815} 816 817static void flanterm_fb_full_refresh(struct flanterm_context *_ctx) { 818 struct flanterm_fb_context *ctx = (void *)_ctx; 819 820#ifdef FLANTERM_FB_DISABLE_CANVAS 821 uint32_t default_bg = ctx->default_bg; 822#endif 823 824 for (size_t y = 0; y < ctx->height; y++) { 825 for (size_t x = 0; x < ctx->width; x++) { 826#ifndef FLANTERM_FB_DISABLE_CANVAS 827 ctx->framebuffer[y * (ctx->pitch / sizeof(uint32_t)) + x] = ctx->canvas[y * ctx->width + x]; 828#else 829 ctx->framebuffer[y * (ctx->pitch / sizeof(uint32_t)) + x] = default_bg; 830#endif 831 } 832 } 833 834 for (size_t i = 0; i < (size_t)_ctx->rows * _ctx->cols; i++) { 835 size_t x = i % _ctx->cols; 836 size_t y = i / _ctx->cols; 837 838 plot_char(_ctx, &ctx->grid[i], x, y); 839 } 840 841 if (_ctx->cursor_enabled) { 842 draw_cursor(_ctx); 843 } 844} 845 846static void flanterm_fb_deinit(struct flanterm_context *_ctx, void (*_free)(void *, size_t)) { 847 struct flanterm_fb_context *ctx = (void *)_ctx; 848 849 if (_free == NULL) { 850 return; 851 } 852 853 _free(ctx->font_bits, ctx->font_bits_size); 854 _free(ctx->font_bool, ctx->font_bool_size); 855 _free(ctx->grid, ctx->grid_size); 856 _free(ctx->queue, ctx->queue_size); 857 _free(ctx->map, ctx->map_size); 858 859#ifndef FLANTERM_FB_DISABLE_CANVAS 860 _free(ctx->canvas, ctx->canvas_size); 861#endif 862 863 _free(ctx, sizeof(struct flanterm_fb_context)); 864} 865 866struct flanterm_context *flanterm_fb_init( 867 void *(*_malloc)(size_t), 868 void (*_free)(void *, size_t), 869 uint32_t *framebuffer, size_t width, size_t height, size_t pitch, 870#ifdef FLANTERM_FB_SUPPORT_BPP 871 uint8_t red_mask_size, uint8_t red_mask_shift, 872 uint8_t green_mask_size, uint8_t green_mask_shift, 873 uint8_t blue_mask_size, uint8_t blue_mask_shift, 874#endif 875#ifndef FLANTERM_FB_DISABLE_CANVAS 876 uint32_t *canvas, 877#endif 878 uint32_t *ansi_colours, uint32_t *ansi_bright_colours, 879 uint32_t *default_bg, uint32_t *default_fg, 880 uint32_t *default_bg_bright, uint32_t *default_fg_bright, 881 void *font, size_t font_width, size_t font_height, size_t font_spacing, 882 size_t font_scale_x, size_t font_scale_y, 883 size_t margin 884) { 885#ifndef FLANTERM_FB_DISABLE_BUMP_ALLOC 886 size_t orig_bump_alloc_ptr = bump_alloc_ptr; 887#endif 888 889#ifdef FLANTERM_FB_SUPPORT_BPP 890 if (red_mask_size < 8 || red_mask_size != green_mask_size || red_mask_size != blue_mask_size) { 891 return NULL; 892 } 893#endif 894 895 if (_malloc == NULL) { 896#ifndef FLANTERM_FB_DISABLE_BUMP_ALLOC 897 _malloc = bump_alloc; 898#else 899 return NULL; 900#endif 901 } 902 903 struct flanterm_fb_context *ctx = NULL; 904 ctx = _malloc(sizeof(struct flanterm_fb_context)); 905 if (ctx == NULL) { 906 goto fail; 907 } 908 909 struct flanterm_context *_ctx = (void *)ctx; 910 memset(ctx, 0, sizeof(struct flanterm_fb_context)); 911 912#ifdef FLANTERM_FB_SUPPORT_BPP 913 ctx->red_mask_size = red_mask_size; 914 ctx->red_mask_shift = red_mask_shift + (red_mask_size - 8); 915 ctx->green_mask_size = green_mask_size; 916 ctx->green_mask_shift = green_mask_shift + (green_mask_size - 8); 917 ctx->blue_mask_size = blue_mask_size; 918 ctx->blue_mask_shift = blue_mask_shift + (blue_mask_size - 8); 919#endif 920 921 if (ansi_colours != NULL) { 922 for (size_t i = 0; i < 8; i++) { 923 ctx->ansi_colours[i] = convert_colour(_ctx, ansi_colours[i]); 924 } 925 } else { 926 ctx->ansi_colours[0] = convert_colour(_ctx, 0x00000000); // black 927 ctx->ansi_colours[1] = convert_colour(_ctx, 0x00aa0000); // red 928 ctx->ansi_colours[2] = convert_colour(_ctx, 0x0000aa00); // green 929 ctx->ansi_colours[3] = convert_colour(_ctx, 0x00aa5500); // brown 930 ctx->ansi_colours[4] = convert_colour(_ctx, 0x000000aa); // blue 931 ctx->ansi_colours[5] = convert_colour(_ctx, 0x00aa00aa); // magenta 932 ctx->ansi_colours[6] = convert_colour(_ctx, 0x0000aaaa); // cyan 933 ctx->ansi_colours[7] = convert_colour(_ctx, 0x00aaaaaa); // grey 934 } 935 936 if (ansi_bright_colours != NULL) { 937 for (size_t i = 0; i < 8; i++) { 938 ctx->ansi_bright_colours[i] = convert_colour(_ctx, ansi_bright_colours[i]); 939 } 940 } else { 941 ctx->ansi_bright_colours[0] = convert_colour(_ctx, 0x00555555); // black 942 ctx->ansi_bright_colours[1] = convert_colour(_ctx, 0x00ff5555); // red 943 ctx->ansi_bright_colours[2] = convert_colour(_ctx, 0x0055ff55); // green 944 ctx->ansi_bright_colours[3] = convert_colour(_ctx, 0x00ffff55); // brown 945 ctx->ansi_bright_colours[4] = convert_colour(_ctx, 0x005555ff); // blue 946 ctx->ansi_bright_colours[5] = convert_colour(_ctx, 0x00ff55ff); // magenta 947 ctx->ansi_bright_colours[6] = convert_colour(_ctx, 0x0055ffff); // cyan 948 ctx->ansi_bright_colours[7] = convert_colour(_ctx, 0x00ffffff); // grey 949 } 950 951 if (default_bg != NULL) { 952 ctx->default_bg = convert_colour(_ctx, *default_bg); 953 } else { 954 ctx->default_bg = 0x00000000; // background (black) 955 } 956 957 if (default_fg != NULL) { 958 ctx->default_fg = convert_colour(_ctx, *default_fg); 959 } else { 960 ctx->default_fg = convert_colour(_ctx, 0x00aaaaaa); // foreground (grey) 961 } 962 963 if (default_bg_bright != NULL) { 964 ctx->default_bg_bright = convert_colour(_ctx, *default_bg_bright); 965 } else { 966 ctx->default_bg_bright = convert_colour(_ctx, 0x00555555); // background (black) 967 } 968 969 if (default_fg_bright != NULL) { 970 ctx->default_fg_bright = convert_colour(_ctx, *default_fg_bright); 971 } else { 972 ctx->default_fg_bright = convert_colour(_ctx, 0x00ffffff); // foreground (grey) 973 } 974 975 ctx->text_fg = ctx->default_fg; 976 ctx->text_bg = 0xffffffff; 977 978 ctx->framebuffer = (void *)framebuffer; 979 ctx->width = width; 980 ctx->height = height; 981 ctx->pitch = pitch; 982 983#define FONT_BYTES ((font_width * font_height * FLANTERM_FB_FONT_GLYPHS) / 8) 984 985 if (font != NULL) { 986 ctx->font_width = font_width; 987 ctx->font_height = font_height; 988 ctx->font_bits_size = FONT_BYTES; 989 ctx->font_bits = _malloc(ctx->font_bits_size); 990 if (ctx->font_bits == NULL) { 991 goto fail; 992 } 993 memcpy(ctx->font_bits, font, ctx->font_bits_size); 994 } else { 995 ctx->font_width = font_width = 8; 996 ctx->font_height = font_height = 16; 997 ctx->font_bits_size = FONT_BYTES; 998 font_spacing = 1; 999 ctx->font_bits = _malloc(ctx->font_bits_size); 1000 if (ctx->font_bits == NULL) { 1001 goto fail; 1002 } 1003 memcpy(ctx->font_bits, builtin_font, ctx->font_bits_size); 1004 } 1005 1006#undef FONT_BYTES 1007 1008 ctx->font_width += font_spacing; 1009 1010 ctx->font_bool_size = FLANTERM_FB_FONT_GLYPHS * font_height * ctx->font_width * sizeof(bool); 1011 ctx->font_bool = _malloc(ctx->font_bool_size); 1012 if (ctx->font_bool == NULL) { 1013 goto fail; 1014 } 1015 1016 for (size_t i = 0; i < FLANTERM_FB_FONT_GLYPHS; i++) { 1017 uint8_t *glyph = &ctx->font_bits[i * font_height]; 1018 1019 for (size_t y = 0; y < font_height; y++) { 1020 // NOTE: the characters in VGA fonts are always one byte wide. 1021 // 9 dot wide fonts have 8 dots and one empty column, except 1022 // characters 0xC0-0xDF replicate column 9. 1023 for (size_t x = 0; x < 8; x++) { 1024 size_t offset = i * font_height * ctx->font_width + y * ctx->font_width + x; 1025 1026 if ((glyph[y] & (0x80 >> x))) { 1027 ctx->font_bool[offset] = true; 1028 } else { 1029 ctx->font_bool[offset] = false; 1030 } 1031 } 1032 // fill columns above 8 like VGA Line Graphics Mode does 1033 for (size_t x = 8; x < ctx->font_width; x++) { 1034 size_t offset = i * font_height * ctx->font_width + y * ctx->font_width + x; 1035 1036 if (i >= 0xc0 && i <= 0xdf) { 1037 ctx->font_bool[offset] = (glyph[y] & 1); 1038 } else { 1039 ctx->font_bool[offset] = false; 1040 } 1041 } 1042 } 1043 } 1044 1045 ctx->font_scale_x = font_scale_x; 1046 ctx->font_scale_y = font_scale_y; 1047 1048 ctx->glyph_width = ctx->font_width * font_scale_x; 1049 ctx->glyph_height = font_height * font_scale_y; 1050 1051 _ctx->cols = (ctx->width - margin * 2) / ctx->glyph_width; 1052 _ctx->rows = (ctx->height - margin * 2) / ctx->glyph_height; 1053 1054 ctx->offset_x = margin + ((ctx->width - margin * 2) % ctx->glyph_width) / 2; 1055 ctx->offset_y = margin + ((ctx->height - margin * 2) % ctx->glyph_height) / 2; 1056 1057 ctx->grid_size = _ctx->rows * _ctx->cols * sizeof(struct flanterm_fb_char); 1058 ctx->grid = _malloc(ctx->grid_size); 1059 if (ctx->grid == NULL) { 1060 goto fail; 1061 } 1062 for (size_t i = 0; i < _ctx->rows * _ctx->cols; i++) { 1063 ctx->grid[i].c = ' '; 1064 ctx->grid[i].fg = ctx->text_fg; 1065 ctx->grid[i].bg = ctx->text_bg; 1066 } 1067 1068 ctx->queue_size = _ctx->rows * _ctx->cols * sizeof(struct flanterm_fb_queue_item); 1069 ctx->queue = _malloc(ctx->queue_size); 1070 if (ctx->queue == NULL) { 1071 goto fail; 1072 } 1073 ctx->queue_i = 0; 1074 memset(ctx->queue, 0, ctx->queue_size); 1075 1076 ctx->map_size = _ctx->rows * _ctx->cols * sizeof(struct flanterm_fb_queue_item *); 1077 ctx->map = _malloc(ctx->map_size); 1078 if (ctx->map == NULL) { 1079 goto fail; 1080 } 1081 memset(ctx->map, 0, ctx->map_size); 1082 1083#ifndef FLANTERM_FB_DISABLE_CANVAS 1084 ctx->canvas_size = ctx->width * ctx->height * sizeof(uint32_t); 1085 ctx->canvas = _malloc(ctx->canvas_size); 1086 if (ctx->canvas == NULL) { 1087 goto fail; 1088 } 1089 if (canvas != NULL) { 1090 for (size_t i = 0; i < ctx->width * ctx->height; i++) { 1091 ctx->canvas[i] = convert_colour(_ctx, canvas[i]); 1092 } 1093 } else { 1094 for (size_t i = 0; i < ctx->width * ctx->height; i++) { 1095 ctx->canvas[i] = ctx->default_bg; 1096 } 1097 } 1098#endif 1099 1100 _ctx->raw_putchar = flanterm_fb_raw_putchar; 1101 _ctx->clear = flanterm_fb_clear; 1102 _ctx->set_cursor_pos = flanterm_fb_set_cursor_pos; 1103 _ctx->get_cursor_pos = flanterm_fb_get_cursor_pos; 1104 _ctx->set_text_fg = flanterm_fb_set_text_fg; 1105 _ctx->set_text_bg = flanterm_fb_set_text_bg; 1106 _ctx->set_text_fg_bright = flanterm_fb_set_text_fg_bright; 1107 _ctx->set_text_bg_bright = flanterm_fb_set_text_bg_bright; 1108 _ctx->set_text_fg_rgb = flanterm_fb_set_text_fg_rgb; 1109 _ctx->set_text_bg_rgb = flanterm_fb_set_text_bg_rgb; 1110 _ctx->set_text_fg_default = flanterm_fb_set_text_fg_default; 1111 _ctx->set_text_bg_default = flanterm_fb_set_text_bg_default; 1112 _ctx->set_text_fg_default_bright = flanterm_fb_set_text_fg_default_bright; 1113 _ctx->set_text_bg_default_bright = flanterm_fb_set_text_bg_default_bright; 1114 _ctx->move_character = flanterm_fb_move_character; 1115 _ctx->scroll = flanterm_fb_scroll; 1116 _ctx->revscroll = flanterm_fb_revscroll; 1117 _ctx->swap_palette = flanterm_fb_swap_palette; 1118 _ctx->save_state = flanterm_fb_save_state; 1119 _ctx->restore_state = flanterm_fb_restore_state; 1120 _ctx->double_buffer_flush = flanterm_fb_double_buffer_flush; 1121 _ctx->full_refresh = flanterm_fb_full_refresh; 1122 _ctx->deinit = flanterm_fb_deinit; 1123 1124 flanterm_context_reinit(_ctx); 1125 flanterm_fb_full_refresh(_ctx); 1126 1127 return _ctx; 1128 1129fail: 1130#ifndef FLANTERM_FB_DISABLE_BUMP_ALLOC 1131 if (_malloc == bump_alloc) { 1132 bump_alloc_ptr = orig_bump_alloc_ptr; 1133 return NULL; 1134 } 1135#endif 1136 1137 if (_free == NULL) { 1138 return NULL; 1139 } 1140 1141#ifndef FLANTERM_FB_DISABLE_CANVAS 1142 if (ctx->canvas != NULL) { 1143 _free(ctx->canvas, ctx->canvas_size); 1144 } 1145#endif 1146 if (ctx->map != NULL) { 1147 _free(ctx->map, ctx->map_size); 1148 } 1149 if (ctx->queue != NULL) { 1150 _free(ctx->queue, ctx->queue_size); 1151 } 1152 if (ctx->grid != NULL) { 1153 _free(ctx->grid, ctx->grid_size); 1154 } 1155 if (ctx->font_bool != NULL) { 1156 _free(ctx->font_bool, ctx->font_bool_size); 1157 } 1158 if (ctx->font_bits != NULL) { 1159 _free(ctx->font_bits, ctx->font_bits_size); 1160 } 1161 if (ctx != NULL) { 1162 _free(ctx, sizeof(struct flanterm_fb_context)); 1163 } 1164 1165 return NULL; 1166}