:: limine / common / lib / gterm.c 48.8 KB raw

1
#include <stdint.h>
2
#include <stddef.h>
3
#include <lib/gterm.h>
4
#include <lib/misc.h>
5
#include <lib/libc.h>
6
#include <lib/config.h>
7
#include <lib/print.h>
8
#include <lib/uri.h>
9
#include <lib/fb.h>
10
#include <lib/image.h>
11
#include <lib/rand.h>
12
#include <mm/pmm.h>
13
#include <flanterm.h>
14
#include <flanterm_backends/fb.h>
15
#include <lib/term.h>
16
#include <sys/cpu.h>
17
18
// Builtin font originally taken from:
19
// https://github.com/viler-int10h/vga-text-mode-fonts/raw/master/FONTS/PC-OTHER/TOSH-SAT.F16
20
static const uint8_t builtin_font[] = {
21
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
22
  0x00, 0x3c, 0x42, 0x81, 0x81, 0xa5, 0xa5, 0x81, 0x81, 0xa5, 0x99, 0x81, 0x42, 0x3c, 0x00, 0x00,
23
  0x00, 0x3c, 0x7e, 0xff, 0xff, 0xdb, 0xdb, 0xff, 0xff, 0xdb, 0xe7, 0xff, 0x7e, 0x3c, 0x00, 0x00,
24
  0x00, 0x00, 0x00, 0x6c, 0xfe, 0xfe, 0xfe, 0x7c, 0x7c, 0x38, 0x38, 0x10, 0x10, 0x00, 0x00, 0x00,
25
  0x00, 0x10, 0x10, 0x38, 0x38, 0x7c, 0x7c, 0xfe, 0x7c, 0x7c, 0x38, 0x38, 0x10, 0x10, 0x00, 0x00,
26
  0x00, 0x00, 0x00, 0x18, 0x3c, 0x3c, 0xdb, 0xff, 0xff, 0xdb, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00,
27
  0x00, 0x00, 0x00, 0x18, 0x3c, 0x7e, 0xff, 0xff, 0xff, 0x66, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00,
28
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x78, 0x78, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
29
  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe7, 0xc3, 0xc3, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
30
  0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0xcc, 0x84, 0x84, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00,
31
  0xff, 0xff, 0xff, 0xff, 0xff, 0xc3, 0x99, 0xbd, 0xbd, 0x99, 0xc3, 0xff, 0xff, 0xff, 0xff, 0xff,
32
  0x00, 0x00, 0x00, 0x1e, 0x0e, 0x1e, 0x32, 0x78, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00,
33
  0x00, 0x00, 0x00, 0x78, 0xcc, 0xcc, 0xcc, 0x78, 0x30, 0xfc, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00,
34
  0x00, 0x00, 0x10, 0x18, 0x1c, 0x1e, 0x16, 0x12, 0x10, 0x10, 0x70, 0xf0, 0xe0, 0x00, 0x00, 0x00,
35
  0x00, 0x30, 0x38, 0x2c, 0x26, 0x32, 0x3a, 0x2e, 0x26, 0x22, 0x62, 0xe2, 0xc6, 0x0e, 0x0c, 0x00,
36
  0x00, 0x00, 0x00, 0x18, 0x18, 0xdb, 0x3c, 0xe7, 0x3c, 0xdb, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
37
  0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xfc, 0xf8, 0xf0, 0xe0, 0xc0, 0x80, 0x00, 0x00,
38
  0x00, 0x02, 0x06, 0x0e, 0x1e, 0x3e, 0x7e, 0xfe, 0x7e, 0x3e, 0x1e, 0x0e, 0x06, 0x02, 0x00, 0x00,
39
  0x00, 0x00, 0x30, 0x78, 0xfc, 0x30, 0x30, 0x30, 0x30, 0x30, 0xfc, 0x78, 0x30, 0x00, 0x00, 0x00,
40
  0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x00, 0xcc, 0xcc, 0x00, 0x00, 0x00,
41
  0x00, 0x00, 0x7f, 0xdb, 0xdb, 0xdb, 0xdb, 0x7b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x00, 0x00, 0x00,
42
  0x00, 0x00, 0x7c, 0xc6, 0x60, 0x38, 0x6c, 0xc6, 0xc6, 0x6c, 0x38, 0x0c, 0xc6, 0x7c, 0x00, 0x00,
43
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xfe, 0xfe, 0x00, 0x00, 0x00,
44
  0x00, 0x00, 0x30, 0x78, 0xfc, 0x30, 0x30, 0x30, 0x30, 0x30, 0xfc, 0x78, 0x30, 0xfc, 0x00, 0x00,
45
  0x00, 0x00, 0x30, 0x78, 0xfc, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x00, 0x00, 0x00,
46
  0x00, 0x00, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0xfc, 0x78, 0x30, 0x00, 0x00, 0x00,
47
  0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x0c, 0xfe, 0xfe, 0x0c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00,
48
  0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x60, 0xfe, 0xfe, 0x60, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00,
49
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00,
50
  0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x66, 0xff, 0xff, 0x66, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00,
51
  0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x38, 0x38, 0x7c, 0x7c, 0xfe, 0xfe, 0x00, 0x00, 0x00, 0x00,
52
  0x00, 0x00, 0x00, 0x00, 0xfe, 0xfe, 0x7c, 0x7c, 0x38, 0x38, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00,
53
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
54
  0x00, 0x00, 0x30, 0x78, 0x78, 0x78, 0x78, 0x30, 0x30, 0x30, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00,
55
  0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
56
  0x00, 0x00, 0x6c, 0x6c, 0x6c, 0xfe, 0x6c, 0x6c, 0x6c, 0xfe, 0x6c, 0x6c, 0x6c, 0x00, 0x00, 0x00,
57
  0x00, 0x18, 0x18, 0x7c, 0xc6, 0xc0, 0xc0, 0x7c, 0x06, 0x06, 0xc6, 0x7c, 0x18, 0x18, 0x00, 0x00,
58
  0x00, 0x00, 0xc6, 0xc6, 0x0c, 0x0c, 0x18, 0x38, 0x30, 0x60, 0x60, 0xc6, 0xc6, 0x00, 0x00, 0x00,
59
  0x00, 0x00, 0x38, 0x6c, 0x6c, 0x38, 0x30, 0x76, 0xde, 0xcc, 0xcc, 0xde, 0x76, 0x00, 0x00, 0x00,
60
  0x00, 0x00, 0x18, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
61
  0x00, 0x00, 0x18, 0x30, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x30, 0x18, 0x00, 0x00, 0x00,
62
  0x00, 0x00, 0x60, 0x30, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x30, 0x60, 0x00, 0x00, 0x00,
63
  0x00, 0x00, 0x00, 0x00, 0x00, 0x6c, 0x38, 0xfe, 0x38, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
64
  0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7e, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
65
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x30, 0x00, 0x00,
66
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
67
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00,
68
  0x00, 0x00, 0x06, 0x06, 0x0c, 0x0c, 0x18, 0x38, 0x30, 0x60, 0x60, 0xc0, 0xc0, 0x00, 0x00, 0x00,
69
  0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xd6, 0xd6, 0xd6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00,
70
  0x00, 0x00, 0x18, 0x38, 0x78, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x7e, 0x00, 0x00, 0x00,
71
  0x00, 0x00, 0x7c, 0xc6, 0x06, 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0xc0, 0xfe, 0x00, 0x00, 0x00,
72
  0x00, 0x00, 0x7c, 0xc6, 0x06, 0x06, 0x3c, 0x06, 0x06, 0x06, 0x06, 0xc6, 0x7c, 0x00, 0x00, 0x00,
73
  0x00, 0x00, 0x04, 0x0c, 0x1c, 0x3c, 0x6c, 0xcc, 0xfe, 0x0c, 0x0c, 0x0c, 0x0c, 0x00, 0x00, 0x00,
74
  0x00, 0x00, 0xfe, 0xc0, 0xc0, 0xc0, 0xfc, 0x06, 0x06, 0x06, 0x06, 0xc6, 0x7c, 0x00, 0x00, 0x00,
75
  0x00, 0x00, 0x3c, 0x60, 0xc0, 0xc0, 0xfc, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00,
76
  0x00, 0x00, 0xfe, 0xc6, 0x06, 0x06, 0x0c, 0x18, 0x30, 0x30, 0x30, 0x30, 0x30, 0x00, 0x00, 0x00,
77
  0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00,
78
  0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x06, 0x06, 0x0c, 0x78, 0x00, 0x00, 0x00,
79
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00,
80
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x18, 0x18, 0x30, 0x00, 0x00,
81
  0x00, 0x00, 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0x60, 0x30, 0x18, 0x0c, 0x06, 0x00, 0x00, 0x00,
82
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
83
  0x00, 0x00, 0xc0, 0x60, 0x30, 0x18, 0x0c, 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0x00, 0x00, 0x00,
84
  0x00, 0x00, 0x7c, 0xc6, 0xc6, 0x06, 0x0c, 0x18, 0x30, 0x30, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00,
85
  0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xde, 0xde, 0xde, 0xde, 0xc0, 0xc0, 0x7e, 0x00, 0x00, 0x00,
86
  0x00, 0x00, 0x38, 0x6c, 0xc6, 0xc6, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00,
87
  0x00, 0x00, 0xfc, 0xc6, 0xc6, 0xc6, 0xfc, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xfc, 0x00, 0x00, 0x00,
88
  0x00, 0x00, 0x7c, 0xc6, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00,
89
  0x00, 0x00, 0xf8, 0xcc, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xcc, 0xf8, 0x00, 0x00, 0x00,
90
  0x00, 0x00, 0xfe, 0xc0, 0xc0, 0xc0, 0xfc, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xfe, 0x00, 0x00, 0x00,
91
  0x00, 0x00, 0xfe, 0xc0, 0xc0, 0xc0, 0xfc, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00,
92
  0x00, 0x00, 0x7c, 0xc6, 0xc0, 0xc0, 0xc0, 0xde, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, 0x00, 0x00, 0x00,
93
  0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00,
94
  0x00, 0x00, 0xfc, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0xfc, 0x00, 0x00, 0x00,
95
  0x00, 0x00, 0x1e, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00,
96
  0x00, 0x00, 0xc6, 0xc6, 0xcc, 0xd8, 0xf0, 0xe0, 0xf0, 0xd8, 0xcc, 0xc6, 0xc6, 0x00, 0x00, 0x00,
97
  0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xfe, 0x00, 0x00, 0x00,
98
  0x00, 0x00, 0xc6, 0xc6, 0xee, 0xfe, 0xd6, 0xd6, 0xd6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00,
99
  0x00, 0x00, 0xc6, 0xc6, 0xe6, 0xe6, 0xf6, 0xde, 0xce, 0xce, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00,
100
  0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00,
101
  0x00, 0x00, 0xfc, 0xc6, 0xc6, 0xc6, 0xc6, 0xfc, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00,
102
  0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xf6, 0xda, 0x6c, 0x06, 0x00, 0x00,
103
  0x00, 0x00, 0xfc, 0xc6, 0xc6, 0xc6, 0xc6, 0xfc, 0xd8, 0xcc, 0xcc, 0xc6, 0xc6, 0x00, 0x00, 0x00,
104
  0x00, 0x00, 0x7c, 0xc6, 0xc0, 0x60, 0x30, 0x18, 0x0c, 0x06, 0x06, 0xc6, 0x7c, 0x00, 0x00, 0x00,
105
  0x00, 0x00, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00,
106
  0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00,
107
  0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x6c, 0x38, 0x10, 0x00, 0x00, 0x00,
108
  0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xd6, 0xd6, 0xd6, 0xd6, 0xfe, 0x6c, 0x6c, 0x00, 0x00, 0x00,
109
  0x00, 0x00, 0xc6, 0xc6, 0xc6, 0x6c, 0x38, 0x38, 0x38, 0x6c, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00,
110
  0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x30, 0x30, 0x30, 0x30, 0x30, 0x00, 0x00, 0x00,
111
  0x00, 0x00, 0xfe, 0x06, 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0xc0, 0xc0, 0xfe, 0x00, 0x00, 0x00,
112
  0x00, 0x00, 0x78, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x78, 0x00, 0x00, 0x00,
113
  0x00, 0x00, 0xc0, 0xc0, 0x60, 0x60, 0x30, 0x38, 0x18, 0x0c, 0x0c, 0x06, 0x06, 0x00, 0x00, 0x00,
114
  0x00, 0x00, 0x78, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x78, 0x00, 0x00, 0x00,
115
  0x00, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
116
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00,
117
  0x00, 0x00, 0x18, 0x18, 0x18, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
118
  0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x06, 0x06, 0x7e, 0xc6, 0xc6, 0xc6, 0x7e, 0x00, 0x00, 0x00,
119
  0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xdc, 0xe6, 0xc6, 0xc6, 0xc6, 0xc6, 0xe6, 0xdc, 0x00, 0x00, 0x00,
120
  0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc0, 0xc0, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00,
121
  0x00, 0x00, 0x06, 0x06, 0x06, 0x76, 0xce, 0xc6, 0xc6, 0xc6, 0xc6, 0xce, 0x76, 0x00, 0x00, 0x00,
122
  0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xfe, 0xc0, 0xc0, 0xc0, 0x7e, 0x00, 0x00, 0x00,
123
  0x00, 0x00, 0x1c, 0x36, 0x30, 0x30, 0xfc, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x00, 0x00, 0x00,
124
  0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xce, 0xc6, 0xc6, 0xc6, 0xce, 0x76, 0x06, 0xc6, 0x7c, 0x00,
125
  0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xdc, 0xe6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00,
126
  0x00, 0x00, 0x18, 0x00, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00,
127
  0x00, 0x00, 0x06, 0x00, 0x00, 0x1e, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0xc6, 0xc6, 0x7c, 0x00,
128
  0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc6, 0xcc, 0xd8, 0xf0, 0xf0, 0xd8, 0xcc, 0xc6, 0x00, 0x00, 0x00,
129
  0x00, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00,
130
  0x00, 0x00, 0x00, 0x00, 0x00, 0xec, 0xfe, 0xd6, 0xd6, 0xd6, 0xd6, 0xc6, 0xc6, 0x00, 0x00, 0x00,
131
  0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0xe6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00,
132
  0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00,
133
  0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0xe6, 0xc6, 0xc6, 0xc6, 0xe6, 0xdc, 0xc0, 0xc0, 0xc0, 0x00,
134
  0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xce, 0xc6, 0xc6, 0xc6, 0xce, 0x76, 0x06, 0x06, 0x06, 0x00,
135
  0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0xe6, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00,
136
  0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc0, 0x70, 0x1c, 0x06, 0xc6, 0x7c, 0x00, 0x00, 0x00,
137
  0x00, 0x00, 0x30, 0x30, 0x30, 0xfe, 0x30, 0x30, 0x30, 0x30, 0x30, 0x36, 0x1c, 0x00, 0x00, 0x00,
138
  0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00,
139
  0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x6c, 0x38, 0x10, 0x00, 0x00, 0x00,
140
  0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xd6, 0xd6, 0xd6, 0xd6, 0xfe, 0x6c, 0x00, 0x00, 0x00,
141
  0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0x6c, 0x38, 0x38, 0x6c, 0xc6, 0xc6, 0x00, 0x00, 0x00,
142
  0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xce, 0x76, 0x06, 0xc6, 0x7c, 0x00,
143
  0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0xfe, 0x00, 0x00, 0x00,
144
  0x00, 0x00, 0x1c, 0x30, 0x30, 0x30, 0x30, 0xe0, 0x30, 0x30, 0x30, 0x30, 0x1c, 0x00, 0x00, 0x00,
145
  0x00, 0x00, 0x30, 0x30, 0x30, 0x30, 0x30, 0x00, 0x30, 0x30, 0x30, 0x30, 0x30, 0x00, 0x00, 0x00,
146
  0x00, 0x00, 0xe0, 0x30, 0x30, 0x30, 0x30, 0x1c, 0x30, 0x30, 0x30, 0x30, 0xe0, 0x00, 0x00, 0x00,
147
  0x00, 0x00, 0x00, 0x76, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
148
  0x00, 0x00, 0x00, 0x10, 0x10, 0x38, 0x38, 0x6c, 0x6c, 0xc6, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00,
149
  0x00, 0x00, 0x3c, 0x66, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x66, 0x3c, 0x18, 0xcc, 0x78, 0x00,
150
  0x00, 0x00, 0x6c, 0x6c, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00,
151
  0x00, 0x0c, 0x18, 0x30, 0x00, 0x7c, 0xc6, 0xc6, 0xfe, 0xc0, 0xc0, 0xc0, 0x7e, 0x00, 0x00, 0x00,
152
  0x00, 0x10, 0x38, 0x6c, 0x00, 0x7c, 0x06, 0x06, 0x7e, 0xc6, 0xc6, 0xc6, 0x7e, 0x00, 0x00, 0x00,
153
  0x00, 0x00, 0x6c, 0x6c, 0x00, 0x7c, 0x06, 0x06, 0x7e, 0xc6, 0xc6, 0xc6, 0x7e, 0x00, 0x00, 0x00,
154
  0x00, 0x60, 0x30, 0x18, 0x00, 0x7c, 0x06, 0x06, 0x7e, 0xc6, 0xc6, 0xc6, 0x7e, 0x00, 0x00, 0x00,
155
  0x00, 0x38, 0x6c, 0x38, 0x00, 0x7c, 0x06, 0x06, 0x7e, 0xc6, 0xc6, 0xc6, 0x7e, 0x00, 0x00, 0x00,
156
  0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc0, 0xc0, 0xc0, 0xc0, 0xc6, 0x7c, 0x18, 0x0c, 0x38,
157
  0x00, 0x10, 0x38, 0x6c, 0x00, 0x7c, 0xc6, 0xc6, 0xfe, 0xc0, 0xc0, 0xc0, 0x7e, 0x00, 0x00, 0x00,
158
  0x00, 0x00, 0x6c, 0x6c, 0x00, 0x7c, 0xc6, 0xc6, 0xfe, 0xc0, 0xc0, 0xc0, 0x7e, 0x00, 0x00, 0x00,
159
  0x00, 0x60, 0x30, 0x18, 0x00, 0x7c, 0xc6, 0xc6, 0xfe, 0xc0, 0xc0, 0xc0, 0x7e, 0x00, 0x00, 0x00,
160
  0x00, 0x00, 0x6c, 0x6c, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00,
161
  0x00, 0x10, 0x38, 0x6c, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00,
162
  0x00, 0x60, 0x30, 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00,
163
  0xc6, 0xc6, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00,
164
  0x38, 0x6c, 0x38, 0x00, 0x38, 0x6c, 0xc6, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00,
165
  0x18, 0x30, 0x60, 0x00, 0xfe, 0xc0, 0xc0, 0xfc, 0xc0, 0xc0, 0xc0, 0xc0, 0xfe, 0x00, 0x00, 0x00,
166
  0x00, 0x00, 0x00, 0x00, 0x00, 0xec, 0x36, 0x36, 0x76, 0xde, 0xd8, 0xd8, 0x6e, 0x00, 0x00, 0x00,
167
  0x00, 0x00, 0x1e, 0x3c, 0x6c, 0xcc, 0xcc, 0xfe, 0xcc, 0xcc, 0xcc, 0xcc, 0xce, 0x00, 0x00, 0x00,
168
  0x00, 0x10, 0x38, 0x6c, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00,
169
  0x00, 0x00, 0x6c, 0x6c, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00,
170
  0x00, 0x60, 0x30, 0x18, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00,
171
  0x00, 0x10, 0x38, 0x6c, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00,
172
  0x00, 0x60, 0x30, 0x18, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00,
173
  0x00, 0x00, 0x6c, 0x6c, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xce, 0x76, 0x06, 0xc6, 0x7c, 0x00,
174
  0x6c, 0x6c, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00,
175
  0x6c, 0x6c, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00,
176
  0x00, 0x00, 0x00, 0x30, 0x30, 0x78, 0xcc, 0xc0, 0xc0, 0xcc, 0x78, 0x30, 0x30, 0x00, 0x00, 0x00,
177
  0x00, 0x00, 0x38, 0x6c, 0x60, 0x60, 0x60, 0xf8, 0x60, 0x60, 0x60, 0xe6, 0xfc, 0x00, 0x00, 0x00,
178
  0x00, 0x00, 0xcc, 0xcc, 0xcc, 0x78, 0x30, 0xfc, 0x30, 0xfc, 0x30, 0x30, 0x30, 0x00, 0x00, 0x00,
179
  0x00, 0x00, 0xf8, 0xcc, 0xcc, 0xf8, 0xc4, 0xcc, 0xde, 0xcc, 0xcc, 0xcc, 0xc6, 0x00, 0x00, 0x00,
180
  0x00, 0x00, 0x0e, 0x1b, 0x18, 0x18, 0x18, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0xd8, 0x70, 0x00,
181
  0x00, 0x0c, 0x18, 0x30, 0x00, 0x7c, 0x06, 0x06, 0x7e, 0xc6, 0xc6, 0xc6, 0x7e, 0x00, 0x00, 0x00,
182
  0x00, 0x0c, 0x18, 0x30, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00,
183
  0x00, 0x0c, 0x18, 0x30, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00,
184
  0x00, 0x0c, 0x18, 0x30, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00,
185
  0x00, 0x76, 0xdc, 0x00, 0x00, 0xdc, 0xe6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00,
186
  0x76, 0xdc, 0x00, 0xc6, 0xc6, 0xe6, 0xf6, 0xfe, 0xde, 0xce, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00,
187
  0x00, 0x78, 0xd8, 0xd8, 0x6c, 0x00, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
188
  0x00, 0x38, 0x6c, 0x6c, 0x38, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
189
  0x00, 0x00, 0x18, 0x18, 0x00, 0x18, 0x18, 0x30, 0x60, 0xc0, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00,
190
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00,
191
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00,
192
  0x00, 0x00, 0xc0, 0xc2, 0xc6, 0xcc, 0xd8, 0x30, 0x60, 0xdc, 0x86, 0x0c, 0x18, 0x3e, 0x00, 0x00,
193
  0x00, 0x00, 0xc0, 0xc2, 0xc6, 0xcc, 0xd8, 0x30, 0x66, 0xce, 0x9e, 0x3e, 0x06, 0x06, 0x00, 0x00,
194
  0x00, 0x00, 0x30, 0x30, 0x00, 0x30, 0x30, 0x30, 0x78, 0x78, 0x78, 0x78, 0x30, 0x00, 0x00, 0x00,
195
  0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x6c, 0xd8, 0x6c, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
196
  0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x6c, 0x36, 0x6c, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
197
  0x22, 0x88, 0x22, 0x88, 0x22, 0x88, 0x22, 0x88, 0x22, 0x88, 0x22, 0x88, 0x22, 0x88, 0x22, 0x88,
198
  0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa,
199
  0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77,
200
  0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
201
  0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
202
  0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0xf8, 0x18, 0x18, 0xf8, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18,
203
  0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xf6, 0xf6, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
204
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xfe, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
205
  0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xf8, 0x18, 0x18, 0xf8, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18,
206
  0x36, 0x36, 0x36, 0x36, 0x36, 0xf6, 0xf6, 0x06, 0x06, 0xf6, 0xf6, 0x36, 0x36, 0x36, 0x36, 0x36,
207
  0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
208
  0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xfe, 0x06, 0x06, 0xf6, 0xf6, 0x36, 0x36, 0x36, 0x36, 0x36,
209
  0x36, 0x36, 0x36, 0x36, 0x36, 0xf6, 0xf6, 0x06, 0x06, 0xfe, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00,
210
  0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xfe, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
211
  0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0xf8, 0x18, 0x18, 0xf8, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00,
212
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
213
  0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
214
  0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
215
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
216
  0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x1f, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
217
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
218
  0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
219
  0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x1f, 0x18, 0x18, 0x1f, 0x1f, 0x18, 0x18, 0x18, 0x18, 0x18,
220
  0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x37, 0x37, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
221
  0x36, 0x36, 0x36, 0x36, 0x36, 0x37, 0x37, 0x30, 0x30, 0x3f, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00,
222
  0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x3f, 0x30, 0x30, 0x37, 0x37, 0x36, 0x36, 0x36, 0x36, 0x36,
223
  0x36, 0x36, 0x36, 0x36, 0x36, 0xf7, 0xf7, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
224
  0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xf7, 0xf7, 0x36, 0x36, 0x36, 0x36, 0x36,
225
  0x36, 0x36, 0x36, 0x36, 0x36, 0x37, 0x37, 0x30, 0x30, 0x37, 0x37, 0x36, 0x36, 0x36, 0x36, 0x36,
226
  0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
227
  0x36, 0x36, 0x36, 0x36, 0x36, 0xf7, 0xf7, 0x00, 0x00, 0xf7, 0xf7, 0x36, 0x36, 0x36, 0x36, 0x36,
228
  0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
229
  0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
230
  0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18,
231
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
232
  0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x3f, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
233
  0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x1f, 0x18, 0x18, 0x1f, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00,
234
  0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x1f, 0x18, 0x18, 0x1f, 0x1f, 0x18, 0x18, 0x18, 0x18, 0x18,
235
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x3f, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
236
  0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xff, 0xff, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
237
  0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0xff, 0x18, 0x18, 0xff, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18,
238
  0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
239
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x1f, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
240
  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
241
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
242
  0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0,
243
  0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f,
244
  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
245
  0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xd6, 0xdc, 0xc8, 0xc8, 0xdc, 0xd6, 0x76, 0x00, 0x00, 0x00,
246
  0x00, 0x00, 0x78, 0xcc, 0xcc, 0xcc, 0xd8, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xd8, 0xc0, 0xc0, 0x00,
247
  0x00, 0x00, 0xfe, 0xc6, 0xc6, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00,
248
  0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0xfe, 0x24, 0x24, 0x24, 0x24, 0x66, 0xc6, 0x00, 0x00, 0x00,
249
  0x00, 0x00, 0xfe, 0xfe, 0xc2, 0x60, 0x30, 0x18, 0x30, 0x60, 0xc2, 0xfe, 0xfe, 0x00, 0x00, 0x00,
250
  0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0xc8, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00,
251
  0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x76, 0x6c, 0x60, 0xc0, 0x00,
252
  0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0xfc, 0x98, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00,
253
  0x00, 0x00, 0xfc, 0x30, 0x30, 0x78, 0xcc, 0xcc, 0xcc, 0x78, 0x30, 0x30, 0xfc, 0x00, 0x00, 0x00,
254
  0x00, 0x00, 0x38, 0x6c, 0xc6, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x6c, 0x38, 0x00, 0x00, 0x00,
255
  0x00, 0x00, 0x38, 0x6c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x6c, 0x6c, 0x6c, 0xee, 0x00, 0x00, 0x00,
256
  0x00, 0x00, 0x78, 0xcc, 0x60, 0x30, 0x78, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00,
257
  0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xbb, 0x99, 0x99, 0xdd, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x00,
258
  0x00, 0x00, 0x02, 0x06, 0x3c, 0x6c, 0xce, 0xd6, 0xd6, 0xe6, 0x6c, 0x78, 0xc0, 0x80, 0x00, 0x00,
259
  0x00, 0x00, 0x1e, 0x30, 0x60, 0xc0, 0xc0, 0xfe, 0xc0, 0xc0, 0x60, 0x30, 0x1e, 0x00, 0x00, 0x00,
260
  0x00, 0x00, 0x38, 0x6c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00,
261
  0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0xfe, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00,
262
  0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0xfc, 0x30, 0x30, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x00,
263
  0x00, 0x00, 0x00, 0x00, 0x60, 0x30, 0x18, 0x0c, 0x18, 0x30, 0x60, 0x00, 0xfc, 0x00, 0x00, 0x00,
264
  0x00, 0x00, 0x00, 0x00, 0x18, 0x30, 0x60, 0xc0, 0x60, 0x30, 0x18, 0x00, 0xfc, 0x00, 0x00, 0x00,
265
  0x00, 0x00, 0x1c, 0x36, 0x36, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
266
  0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xd8, 0xd8, 0x70, 0x00, 0x00, 0x00,
267
  0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0x00, 0xfc, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00,
268
  0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, 0x00, 0x76, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
269
  0x00, 0x78, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
270
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
271
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
272
  0x00, 0x0f, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0xcc, 0x6c, 0x3c, 0x1c, 0x0c, 0x00, 0x00,
273
  0x00, 0xd8, 0xec, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
274
  0x00, 0x38, 0x6c, 0x0c, 0x18, 0x30, 0x60, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
275
  0x00, 0x00, 0x00, 0x00, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00,
276
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
277
};
278
279
#define FONT_MAX 16384
280
281
static struct image *background;
282
283
static size_t margin = 64;
284
static size_t margin_gradient = 4;
285
286
static uint32_t default_bg, default_fg;
287
static uint32_t default_bg_bright, default_fg_bright;
288
289
static size_t bg_canvas_size;
290
static uint32_t *bg_canvas;
291
292
#define A(rgb) (uint8_t)(rgb >> 24)
293
#define R(rgb) (uint8_t)(rgb >> 16)
294
#define G(rgb) (uint8_t)(rgb >> 8)
295
#define B(rgb) (uint8_t)(rgb)
296
#define ARGB(a, r, g, b) (((a) << 24) | (((r) & 0xFF) << 16) | (((g) & 0xFF) << 8) | ((b) & 0xFF))
297
298
static inline uint32_t colour_blend(uint32_t fg, uint32_t bg) {
299
    unsigned alpha = 255 - A(fg);
300
    unsigned inv_alpha = A(fg) + 1;
301
302
    uint8_t r = (uint8_t)((alpha * R(fg) + inv_alpha * R(bg)) / 256);
303
    uint8_t g = (uint8_t)((alpha * G(fg) + inv_alpha * G(bg)) / 256);
304
    uint8_t b = (uint8_t)((alpha * B(fg) + inv_alpha * B(bg)) / 256);
305
306
    return ARGB(0, r, g, b);
307
}
308
309
static uint32_t blend_gradient_from_box(struct fb_info *fb, size_t x, size_t y, uint32_t bg_px, uint32_t hex) {
310
    size_t distance, x_distance, y_distance;
311
    size_t gradient_stop_x = fb->framebuffer_width - margin;
312
    size_t gradient_stop_y = fb->framebuffer_height - margin;
313
314
    if (x < margin)
315
        x_distance = margin - x;
316
    else
317
        x_distance = x - gradient_stop_x;
318
319
    if (y < margin)
320
        y_distance = margin - y;
321
    else
322
        y_distance = y - gradient_stop_y;
323
324
    if (x >= margin && x < gradient_stop_x) {
325
        distance = y_distance;
326
    } else if (y >= margin && y < gradient_stop_y) {
327
        distance = x_distance;
328
    } else {
329
        distance = sqrt((uint64_t)x_distance * (uint64_t)x_distance
330
                      + (uint64_t)y_distance * (uint64_t)y_distance);
331
    }
332
333
    if (distance > margin_gradient)
334
        return bg_px;
335
336
    uint8_t gradient_step = (0xff - A(hex)) / margin_gradient;
337
    uint8_t new_alpha     = A(hex) + gradient_step * distance;
338
339
    return colour_blend((hex & 0xffffff) | (new_alpha << 24), bg_px);
340
}
341
342
typedef size_t fixedp6; // the last 6 bits are the fixed point part
343
static size_t fixedp6_to_int(fixedp6 value) { return value / 64; }
344
static fixedp6 int_to_fixedp6(size_t value) { return value * 64; }
345
346
// Draw rect at coordinates, copying from the image to the fb and canvas, applying fn on every pixel
347
__attribute__((always_inline)) static inline void genloop(struct fb_info *fb, size_t xstart, size_t xend, size_t ystart, size_t yend, uint32_t (*blend)(struct fb_info *fb, size_t x, size_t y, uint32_t orig)) {
348
    uint8_t *img = background->img;
349
    const size_t img_width = background->img_width, img_height = background->img_height, img_pitch = background->pitch, colsize = background->bpp / 8;
350
351
    if (xstart > xend) {
352
        size_t tmp = xstart;
353
        xstart = xend;
354
        xend = tmp;
355
    }
356
    if (ystart > yend) {
357
        size_t tmp = ystart;
358
        ystart = yend;
359
        yend = tmp;
360
    }
361
362
    switch (background->type) {
363
    case IMAGE_TILED:
364
        for (size_t y = ystart; y < yend; y++) {
365
            size_t image_y = y % img_height, image_x = xstart % img_width;
366
            const size_t off = img_pitch * image_y;
367
            size_t canvas_off = fb->framebuffer_width * y;
368
            for (size_t x = xstart; x < xend; x++) {
369
                uint32_t img_pixel = *(uint32_t*)(img + image_x * colsize + off);
370
                uint32_t i = blend(fb, x, y, img_pixel);
371
                bg_canvas[canvas_off + x] = i;
372
                if (++image_x == img_width) image_x = 0; // image_x = x % img_width, but modulo is too expensive
373
            }
374
        }
375
        break;
376
377
    case IMAGE_CENTERED:
378
        for (size_t y = ystart; y < yend; y++) {
379
            int64_t image_y = (int64_t)y - background->y_displacement;
380
            size_t canvas_off = fb->framebuffer_width * y;
381
            if (image_y < 0 || (uint64_t)image_y >= background->y_size) { /* external part */
382
                for (size_t x = xstart; x < xend; x++) {
383
                    uint32_t i = blend(fb, x, y, background->back_colour);
384
                    bg_canvas[canvas_off + x] = i;
385
                }
386
            }
387
            else { /* internal part */
388
                const size_t off = img_pitch * (size_t)image_y;
389
                for (size_t x = xstart; x < xend; x++) {
390
                    uint32_t pixel;
391
                    int64_t image_x = (int64_t)x - background->x_displacement;
392
                    if (image_x < 0 || (uint64_t)image_x >= background->x_size) {
393
                        pixel = background->back_colour;
394
                    } else {
395
                        pixel = *(uint32_t*)(img + (size_t)image_x * colsize + off);
396
                    }
397
                    uint32_t i = blend(fb, x, y, pixel);
398
                    bg_canvas[canvas_off + x] = i;
399
                }
400
            }
401
        }
402
        break;
403
    // For every pixel, ratio = img_width / gterm_width, img_x = x * ratio, x = (xstart + i)
404
    // hence x = xstart * ratio + i * ratio
405
    // so you can set x = xstart * ratio, and increment by ratio at each iteration
406
    case IMAGE_STRETCHED:
407
        for (size_t y = ystart; y < yend; y++) {
408
            size_t img_y = (y * img_height) / fb->framebuffer_height; // calculate Y with full precision
409
            size_t off = img_pitch * img_y;
410
            size_t canvas_off = fb->framebuffer_width * y;
411
412
            size_t ratio = int_to_fixedp6(img_width) / fb->framebuffer_width;
413
            fixedp6 img_x = ratio * xstart;
414
            for (size_t x = xstart; x < xend; x++) {
415
                uint32_t img_pixel = *(uint32_t*)(img + fixedp6_to_int(img_x) * colsize + off);
416
                uint32_t i = blend(fb, x, y, img_pixel);
417
                bg_canvas[canvas_off + x] = i;
418
                img_x += ratio;
419
            }
420
        }
421
        break;
422
    }
423
}
424
425
static uint32_t blend_external(struct fb_info *fb, size_t x, size_t y, uint32_t orig) { (void)fb; (void)x; (void)y; return orig; }
426
static uint32_t blend_internal(struct fb_info *fb, size_t x, size_t y, uint32_t orig) { (void)fb; (void)x; (void)y; return colour_blend(default_bg, orig); }
427
static uint32_t blend_margin(struct fb_info *fb, size_t x, size_t y, uint32_t orig) { return blend_gradient_from_box(fb, x, y, orig, default_bg); }
428
429
static void loop_external(struct fb_info *fb, size_t xstart, size_t xend, size_t ystart, size_t yend) { genloop(fb, xstart, xend, ystart, yend, blend_external); }
430
static void loop_margin(struct fb_info *fb, size_t xstart, size_t xend, size_t ystart, size_t yend) { genloop(fb, xstart, xend, ystart, yend, blend_margin); }
431
static void loop_internal(struct fb_info *fb, size_t xstart, size_t xend, size_t ystart, size_t yend) { genloop(fb, xstart, xend, ystart, yend, blend_internal); }
432
433
static void generate_canvas(struct fb_info *fb) {
434
    if (background) {
435
        // Free previous canvas if it exists
436
        if (bg_canvas != NULL) {
437
            pmm_free(bg_canvas, bg_canvas_size);
438
        }
439
        bg_canvas_size = CHECKED_MUL(fb->framebuffer_width, fb->framebuffer_height,
440
            panic(false, "gterm: canvas size overflow"));
441
        bg_canvas_size = CHECKED_MUL(bg_canvas_size, sizeof(uint32_t),
442
            panic(false, "gterm: canvas size overflow"));
443
        bg_canvas = ext_mem_alloc(bg_canvas_size);
444
445
        // Clamp margin to half the framebuffer dimensions to prevent underflow
446
        size_t max_margin = fb->framebuffer_width / 2;
447
        if (fb->framebuffer_height / 2 < max_margin) {
448
            max_margin = fb->framebuffer_height / 2;
449
        }
450
        size_t effective_margin = margin > max_margin ? max_margin : margin;
451
        size_t effective_margin_gradient = margin_gradient > effective_margin ? effective_margin : margin_gradient;
452
453
        int64_t margin_no_gradient = (int64_t)effective_margin - effective_margin_gradient;
454
455
        if (margin_no_gradient < 0) {
456
            margin_no_gradient = 0;
457
        }
458
459
        size_t scan_stop_x = fb->framebuffer_width - margin_no_gradient;
460
        size_t scan_stop_y = fb->framebuffer_height - margin_no_gradient;
461
462
        loop_external(fb, 0, fb->framebuffer_width, 0, margin_no_gradient);
463
        loop_external(fb, 0, fb->framebuffer_width, scan_stop_y, fb->framebuffer_height);
464
        loop_external(fb, 0, margin_no_gradient, margin_no_gradient, scan_stop_y);
465
        loop_external(fb, scan_stop_x, fb->framebuffer_width, margin_no_gradient, scan_stop_y);
466
467
        size_t gradient_stop_x = fb->framebuffer_width - effective_margin;
468
        size_t gradient_stop_y = fb->framebuffer_height - effective_margin;
469
470
        if (effective_margin_gradient) {
471
            loop_margin(fb, margin_no_gradient, scan_stop_x, margin_no_gradient, effective_margin);
472
            loop_margin(fb, margin_no_gradient, scan_stop_x, gradient_stop_y, scan_stop_y);
473
            loop_margin(fb, margin_no_gradient, effective_margin, effective_margin, gradient_stop_y);
474
            loop_margin(fb, gradient_stop_x, scan_stop_x, effective_margin, gradient_stop_y);
475
        }
476
477
        loop_internal(fb, effective_margin, gradient_stop_x, effective_margin, gradient_stop_y);
478
    } else {
479
        bg_canvas = NULL;
480
        bg_canvas_size = 0;
481
    }
482
}
483
484
485
static void parse_palette(const char *str, uint32_t *colours) {
486
    const char *first = str;
487
    for (size_t i = 0; i < 8; i++) {
488
        const char *last;
489
        uint32_t col = strtoui(first, &last, 16);
490
        if (first == last)
491
            break;
492
        colours[i] = col & 0xffffff;
493
        if (*last == 0)
494
            break;
495
        first = last + 1;
496
    }
497
}
498
499
struct gterm_config {
500
    int fb_rotation;
501
    uint32_t ansi_colours[8];
502
    uint32_t ansi_bright_colours[8];
503
    char *theme_background;
504
    uint8_t *font;
505
    size_t font_width;
506
    size_t font_height;
507
    size_t font_size;
508
    size_t font_spacing;
509
    size_t font_scale_x;
510
    size_t font_scale_y;
511
    bool font_scale_is_default;
512
};
513
514
static void gterm_parse_config(char *config, struct gterm_config *cfg) {
515
    cfg->fb_rotation = FLANTERM_FB_ROTATE_0;
516
    char *rotation_str = config_get_value(config, 0, "INTERFACE_ROTATION");
517
    if (rotation_str != NULL) {
518
        int rotation_val = strtoui(rotation_str, NULL, 10);
519
        switch (rotation_val) {
520
            case 90: cfg->fb_rotation = FLANTERM_FB_ROTATE_90; break;
521
            case 180: cfg->fb_rotation = FLANTERM_FB_ROTATE_180; break;
522
            case 270: cfg->fb_rotation = FLANTERM_FB_ROTATE_270; break;
523
        }
524
    }
525
526
    cfg->ansi_colours[0] = 0x00000000;
527
    cfg->ansi_colours[1] = 0x00aa0000;
528
    cfg->ansi_colours[2] = 0x0000aa00;
529
    cfg->ansi_colours[3] = 0x00aa5500;
530
    cfg->ansi_colours[4] = 0x000000aa;
531
    cfg->ansi_colours[5] = 0x00aa00aa;
532
    cfg->ansi_colours[6] = 0x0000aaaa;
533
    cfg->ansi_colours[7] = 0x00aaaaaa;
534
535
    char *colours = config_get_value(config, 0, "TERM_PALETTE");
536
    if (colours != NULL) {
537
        parse_palette(colours, cfg->ansi_colours);
538
    }
539
540
    cfg->ansi_bright_colours[0] = 0x00555555;
541
    cfg->ansi_bright_colours[1] = 0x00ff5555;
542
    cfg->ansi_bright_colours[2] = 0x0055ff55;
543
    cfg->ansi_bright_colours[3] = 0x00ffff55;
544
    cfg->ansi_bright_colours[4] = 0x005555ff;
545
    cfg->ansi_bright_colours[5] = 0x00ff55ff;
546
    cfg->ansi_bright_colours[6] = 0x0055ffff;
547
    cfg->ansi_bright_colours[7] = 0x00ffffff;
548
549
    char *bright_colours = config_get_value(config, 0, "TERM_PALETTE_BRIGHT");
550
    if (bright_colours != NULL) {
551
        parse_palette(bright_colours, cfg->ansi_bright_colours);
552
    }
553
554
    default_bg = 0x00000000;
555
    default_fg = 0x00aaaaaa;
556
    default_bg_bright = 0x00555555;
557
    default_fg_bright = 0x00ffffff;
558
559
    cfg->theme_background = config_get_value(config, 0, "TERM_BACKGROUND");
560
    if (cfg->theme_background != NULL) {
561
        default_bg = strtoui(cfg->theme_background, NULL, 16);
562
    }
563
564
    char *theme_foreground = config_get_value(config, 0, "TERM_FOREGROUND");
565
    if (theme_foreground != NULL) {
566
        default_fg = strtoui(theme_foreground, NULL, 16) & 0xffffff;
567
    }
568
569
    char *theme_background_bright = config_get_value(config, 0, "TERM_BACKGROUND_BRIGHT");
570
    if (theme_background_bright != NULL) {
571
        default_bg_bright = strtoui(theme_background_bright, NULL, 16);
572
    }
573
574
    char *theme_foreground_bright = config_get_value(config, 0, "TERM_FOREGROUND_BRIGHT");
575
    if (theme_foreground_bright != NULL) {
576
        default_fg_bright = strtoui(theme_foreground_bright, NULL, 16);
577
    }
578
579
    size_t wallpaper_count = 0;
580
    while (config_get_value(config, wallpaper_count, "WALLPAPER") != NULL)
581
        wallpaper_count++;
582
583
    background = NULL;
584
    if (wallpaper_count > 0) {
585
        char *background_path = config_get_value(config, rand32() % wallpaper_count, "WALLPAPER");
586
        if (background_path != NULL) {
587
            if (secure_boot_active && strchr(background_path, '#') == NULL) {
588
                print("Wallpaper skipped: Secure Boot is active and no hash is associated.\n");
589
            } else {
590
                struct file_handle *bg_file;
591
                if ((bg_file = uri_open(background_path, MEMMAP_BOOTLOADER_RECLAIMABLE, false
592
#if defined (__i386__)
593
                    , NULL, NULL
594
#endif
595
                )) != NULL) {
596
                    background = image_open(bg_file);
597
                    fclose(bg_file);
598
                }
599
            }
600
        }
601
    }
602
603
    margin = 64;
604
    margin_gradient = 4;
605
606
    if (background == NULL) {
607
        margin = 0;
608
        margin_gradient = 0;
609
    } else {
610
        if (cfg->theme_background == NULL) {
611
            default_bg = 0x80000000;
612
        }
613
    }
614
615
    char *theme_margin = config_get_value(config, 0, "TERM_MARGIN");
616
    if (theme_margin != NULL) {
617
        margin = strtoui(theme_margin, NULL, 10);
618
    }
619
620
    char *theme_margin_gradient = config_get_value(config, 0, "TERM_MARGIN_GRADIENT");
621
    if (theme_margin_gradient != NULL) {
622
        margin_gradient = strtoui(theme_margin_gradient, NULL, 10);
623
    }
624
625
    if (margin_gradient > margin) {
626
        margin_gradient = margin;
627
    }
628
629
    cfg->font_width = 8;
630
    cfg->font_height = 16;
631
    cfg->font_size = (cfg->font_width * cfg->font_height * FLANTERM_FB_FONT_GLYPHS) / 8;
632
633
    cfg->font = ext_mem_alloc(FONT_MAX);
634
    memcpy(cfg->font, builtin_font, 4096);
635
636
    size_t tmp_font_width, tmp_font_height;
637
638
    char *menu_font_size = config_get_value(config, 0, "TERM_FONT_SIZE");
639
    if (menu_font_size != NULL) {
640
        if (!parse_resolution(&tmp_font_width, &tmp_font_height, NULL, menu_font_size)) {
641
            print("Could not parse TERM_FONT_SIZE. Using default font.\n");
642
            goto config_no_load_font;
643
        }
644
645
        if (tmp_font_width != 8) {
646
            print("Font width must be 8, got %u. Using default font.\n", tmp_font_width);
647
            goto config_no_load_font;
648
        }
649
650
        size_t tmp_font_size = CHECKED_MUL(tmp_font_width, tmp_font_height,
651
            goto config_no_load_font);
652
        tmp_font_size = CHECKED_MUL(tmp_font_size, FLANTERM_FB_FONT_GLYPHS,
653
            goto config_no_load_font) / 8;
654
655
        if (tmp_font_size > FONT_MAX) {
656
            print("Font would be too large (%U bytes, %u bytes allowed). Not loading.\n", (uint64_t)tmp_font_size, FONT_MAX);
657
            goto config_no_load_font;
658
        }
659
660
        cfg->font_size = tmp_font_size;
661
    }
662
663
    char *menu_font = config_get_value(config, 0, "TERM_FONT");
664
    if (menu_font != NULL) {
665
        if (secure_boot_active && strchr(menu_font, '#') == NULL) {
666
            print("Font skipped: Secure Boot is active and no hash is associated.\n");
667
            goto config_no_load_font;
668
        }
669
        struct file_handle *f;
670
        if ((f = uri_open(menu_font, MEMMAP_BOOTLOADER_RECLAIMABLE, false
671
#if defined (__i386__)
672
            , NULL, NULL
673
#endif
674
        )) == NULL) {
675
            print("menu: Could not open font file.\n");
676
        } else {
677
            if (cfg->font_size > f->size) {
678
                print("Font size too large for provided font file. Not loading.\n");
679
                fclose(f);
680
                goto config_no_load_font;
681
            }
682
            fread(f, cfg->font, 0, cfg->font_size);
683
            if (menu_font_size != NULL) {
684
                cfg->font_width = tmp_font_width;
685
                cfg->font_height = tmp_font_height;
686
            }
687
            fclose(f);
688
        }
689
    }
690
691
config_no_load_font:;
692
    cfg->font_spacing = 1;
693
    char *font_spacing_str = config_get_value(config, 0, "TERM_FONT_SPACING");
694
    if (font_spacing_str != NULL) {
695
        cfg->font_spacing = strtoui(font_spacing_str, NULL, 10);
696
    }
697
698
    cfg->font_scale_x = 1;
699
    cfg->font_scale_y = 1;
700
    cfg->font_scale_is_default = true;
701
702
    char *menu_font_scale = config_get_value(config, 0, "TERM_FONT_SCALE");
703
    if (menu_font_scale != NULL) {
704
        parse_resolution(&cfg->font_scale_x, &cfg->font_scale_y, NULL, menu_font_scale);
705
        if (cfg->font_scale_x == 0 || cfg->font_scale_y == 0
706
         || cfg->font_scale_x > 8 || cfg->font_scale_y > 8) {
707
            cfg->font_scale_x = 1;
708
            cfg->font_scale_y = 1;
709
        } else {
710
            cfg->font_scale_is_default = false;
711
        }
712
    }
713
}
714
715
static void gterm_fb_setup(struct fb_info *fb, char *config,
716
                           struct gterm_config *cfg,
717
                           size_t *out_scale_x, size_t *out_scale_y) {
718
    if (cfg->fb_rotation == FLANTERM_FB_ROTATE_90 || cfg->fb_rotation == FLANTERM_FB_ROTATE_270) {
719
        uint64_t tmp = fb->framebuffer_width;
720
        fb->framebuffer_width = fb->framebuffer_height;
721
        fb->framebuffer_height = tmp;
722
    }
723
724
    if (background != NULL) {
725
        char *background_layout = config_get_value(config, 0, "WALLPAPER_STYLE");
726
        if (background_layout != NULL && strcmp(background_layout, "centered") == 0) {
727
            char *background_colour = config_get_value(config, 0, "BACKDROP");
728
            if (background_colour == NULL)
729
                background_colour = "0";
730
            uint32_t bg_col = strtoui(background_colour, NULL, 16);
731
            image_make_centered(background, fb->framebuffer_width, fb->framebuffer_height, bg_col);
732
        } else if (background_layout != NULL && strcmp(background_layout, "tiled") == 0) {
733
        } else {
734
            image_make_stretched(background, fb->framebuffer_width, fb->framebuffer_height);
735
        }
736
    }
737
738
    generate_canvas(fb);
739
740
    *out_scale_x = cfg->font_scale_x;
741
    *out_scale_y = cfg->font_scale_y;
742
    if (cfg->font_scale_is_default) {
743
        *out_scale_x = 1;
744
        *out_scale_y = 1;
745
        if (fb->framebuffer_width >= (1920 + 1920 / 3) && fb->framebuffer_height >= (1080 + 1080 / 3)) {
746
            *out_scale_x = 2;
747
            *out_scale_y = 2;
748
        }
749
        if (fb->framebuffer_width >= (3840 + 3840 / 3) && fb->framebuffer_height >= (2160 + 2160 / 3)) {
750
            *out_scale_x = 4;
751
            *out_scale_y = 4;
752
        }
753
    }
754
755
    if (cfg->fb_rotation == FLANTERM_FB_ROTATE_90 || cfg->fb_rotation == FLANTERM_FB_ROTATE_270) {
756
        uint64_t tmp = fb->framebuffer_width;
757
        fb->framebuffer_width = fb->framebuffer_height;
758
        fb->framebuffer_height = tmp;
759
    }
760
}
761
762
bool gterm_init(struct fb_info **_fbs, size_t *_fbs_count,
763
                char *config, size_t width, size_t height) {
764
    static struct fb_info *fbs;
765
    static size_t fbs_count;
766
767
    static bool prev_valid = false;
768
    static char *prev_config;
769
    static size_t prev_width, prev_height;
770
771
    if (prev_valid && config == prev_config && width == prev_width && height == prev_height) {
772
        if (_fbs != NULL) {
773
            *_fbs = fbs;
774
        }
775
        if (_fbs_count != NULL) {
776
            *_fbs_count = fbs_count;
777
        }
778
        reset_term();
779
        return true;
780
    }
781
782
    prev_valid = false;
783
784
    if (quiet) {
785
        term_notready();
786
        return false;
787
    }
788
789
#if defined (UEFI)
790
    if (serial || COM_OUTPUT) {
791
        term_fallback();
792
        return true;
793
    }
794
#endif
795
796
    term_notready();
797
798
    // We force bpp to 32
799
    fb_init(&fbs, &fbs_count, width, height, 32, true, true);
800
801
    if (_fbs != NULL) {
802
        *_fbs = fbs;
803
    }
804
    if (_fbs_count != NULL) {
805
        *_fbs_count = fbs_count;
806
    }
807
808
    if (fbs_count == 0) {
809
        return false;
810
    }
811
812
    struct gterm_config cfg;
813
    gterm_parse_config(config, &cfg);
814
815
    terms_i = 0;
816
    terms = ext_mem_alloc_counted(fbs_count, sizeof(void *));
817
818
    for (size_t i = 0; i < fbs_count; i++) {
819
        struct fb_info *fb = &fbs[i];
820
821
        if (fb->framebuffer_bpp != 32) {
822
            continue;
823
        }
824
825
        size_t font_scale_x, font_scale_y;
826
        gterm_fb_setup(fb, config, &cfg, &font_scale_x, &font_scale_y);
827
828
        terms[terms_i] = flanterm_fb_init(ext_mem_alloc_size_t,
829
                            pmm_free_size_t,
830
                            (void *)(uintptr_t)fb->framebuffer_addr,
831
                            fb->framebuffer_width, fb->framebuffer_height, fb->framebuffer_pitch,
832
                            fb->red_mask_size, fb->red_mask_shift,
833
                            fb->green_mask_size, fb->green_mask_shift,
834
                            fb->blue_mask_size, fb->blue_mask_shift,
835
                            bg_canvas,
836
                            cfg.ansi_colours, cfg.ansi_bright_colours,
837
                            &default_bg, &default_fg,
838
                            &default_bg_bright, &default_fg_bright,
839
                            cfg.font, cfg.font_width, cfg.font_height, cfg.font_spacing,
840
                            font_scale_x, font_scale_y,
841
                            margin, cfg.fb_rotation);
842
843
        if (terms[terms_i] != NULL) {
844
            terms_i++;
845
        }
846
847
        if (bg_canvas != NULL) {
848
            pmm_free(bg_canvas, bg_canvas_size);
849
            bg_canvas = NULL;
850
        }
851
    }
852
853
    pmm_free(cfg.font, FONT_MAX);
854
855
    if (background != NULL) {
856
        image_close(background);
857
        background = NULL;
858
    }
859
860
    if (terms_i == 0) {
861
        pmm_free(terms, fbs_count * sizeof(void *));
862
        return false;
863
    }
864
865
    for (size_t i = 0; i < terms_i; i++) {
866
        struct flanterm_context *term = terms[i];
867
868
        if (serial) {
869
            term->cols = term->cols > 80 ? 80 : term->cols;
870
            term->rows = term->rows > 24 ? 24 : term->rows;
871
        }
872
    }
873
874
    size_t min_cols = (size_t)-1;
875
    size_t min_rows = (size_t)-1;
876
877
    for (size_t i = 0; i < terms_i; i++) {
878
        struct flanterm_context *term = terms[i];
879
880
        if (term->cols < min_cols) {
881
            min_cols = term->cols;
882
        }
883
884
        if (term->rows < min_rows) {
885
            min_rows = term->rows;
886
        }
887
    }
888
889
    for (size_t i = 0; i < terms_i; i++) {
890
        struct flanterm_context *term = terms[i];
891
892
        term->cols = min_cols;
893
        term->rows = min_rows;
894
895
        flanterm_context_reinit(term);
896
        flanterm_fb_set_flush_callback(term, (void *)fb_flush);
897
    }
898
899
    term_backend = GTERM;
900
901
    prev_config = config;
902
    prev_height = height;
903
    prev_width = width;
904
    prev_valid = true;
905
906
    return true;
907
}
908
909
size_t gterm_prepare_flanterm_params(struct fb_info *fbs, size_t fbs_count,
910
                                     struct flanterm_params *out, size_t out_max) {
911
    struct gterm_config cfg;
912
    gterm_parse_config(NULL, &cfg);
913
914
    uint32_t configured_default_bg = default_bg;
915
916
    size_t count = 0;
917
918
    for (size_t i = 0; i < fbs_count && count < out_max; i++) {
919
        struct fb_info *fb = &fbs[i];
920
921
        if (fb->framebuffer_bpp != 32) {
922
            continue;
923
        }
924
925
        size_t font_scale_x, font_scale_y;
926
        gterm_fb_setup(fb, NULL, &cfg, &font_scale_x, &font_scale_y);
927
928
        struct flanterm_params *p = &out[count];
929
930
        p->canvas = bg_canvas;
931
        p->canvas_size = bg_canvas_size;
932
        bg_canvas = NULL;
933
934
        memcpy(p->ansi_colours, cfg.ansi_colours, sizeof(cfg.ansi_colours));
935
        memcpy(p->ansi_bright_colours, cfg.ansi_bright_colours, sizeof(cfg.ansi_bright_colours));
936
        p->default_bg = configured_default_bg;
937
        p->default_fg = default_fg;
938
        p->default_bg_bright = default_bg_bright;
939
        p->default_fg_bright = default_fg_bright;
940
941
        p->font = cfg.font;
942
        p->font_width = cfg.font_width;
943
        p->font_height = cfg.font_height;
944
        p->font_spacing = cfg.font_spacing;
945
        p->font_scale_x = font_scale_x;
946
        p->font_scale_y = font_scale_y;
947
        p->margin = margin;
948
        p->rotation = cfg.fb_rotation;
949
950
        count++;
951
    }
952
953
    if (background != NULL) {
954
        image_close(background);
955
        background = NULL;
956
    }
957
958
    return count;
959
}
tab: 248 wrap: offon