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