1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
|
#include <mercury/kernel/framebuffer.hpp>
#include <mercury/kernel/terminal.hpp>
namespace mercury::kernel::terminal {
uint8_t *termfont;
uint64_t termfont_len;
int width;
int height;
int cursor_x;
int cursor_y;
framebuffer::color bg_color;
framebuffer::color fg_color;
static uint8_t glyph_height;
void init_terminal() {
//TODO - verify that termfont fits inside termfont_len (i.e. that no other
// functions in this file will try to access memory outside termfont)
//TODO - check magic header to verify that this is actually a font and to
// see whether this is a psf1 font or a psf2 font.
//TODO - support psf2 fonts. currently psf1 is assumed.
//TODO - read unicode table if there is one. currently it is assumed that
// all 256 codepoints have glyphs, and that they appear in order.
glyph_height = termfont[3];
width = framebuffer::width / 8;
height = framebuffer::height / glyph_height;
cursor_x = 0;
cursor_y = 0;
bg_color = framebuffer::encode_color(0, 0, 0);
fg_color = framebuffer::encode_color(255, 255, 255);
}
static void cursor_down() {
if (++cursor_y == height) {
--cursor_y;
framebuffer::move_region(
0, glyph_height, width * 8, height * glyph_height, 0, 0);
framebuffer::fill_region(0, (height - 1) * glyph_height,
width * 8, height * glyph_height, bg_color);
}
}
static void cursor_right() {
if (++cursor_x == width) {
cursor_x = 0;
cursor_down();
}
}
void draw_char(char ch, int x, int y) {
const uint8_t *glyph = termfont + 4 + glyph_height * (unsigned)ch;
for (int i = 0; i < glyph_height; ++i)
for (int j = 0; j < 8; ++j)
framebuffer::set_pixel(x * 8 + j, y * glyph_height + i,
((glyph[i] << j) & 0x80) ? fg_color : bg_color);
}
void put_char(char ch) {
switch (ch) {
case '\n':
cursor_x = 0;
cursor_down();
break;
default:
draw_char(ch, cursor_x, cursor_y);
cursor_right();
break;
}
}
void put_string(const utility::string &str) {
for (size_t i = 0; i < str.count; ++i)
put_char(str.buffer[i]);
}
void put_string_sz(const char *str) {
for (size_t i = 0; str[i]; ++i)
put_char(str[i]);
}
void put_int_decimal(uint64_t n, bool with_commas) {
if (n == 0) {
put_char('0');
return;
}
uint64_t d = 1;
int i = 0;
while (d <= n / 10) {
d *= 10;
++i;
}
while (d) {
put_char('0' + ((n / d) % 10));
d /= 10;
if (with_commas && (i % 3 == 0) && (i != 0))
put_char(',');
--i;
}
}
}
|