diff options
Diffstat (limited to 'kernel/terminal.cpp')
-rw-r--r-- | kernel/terminal.cpp | 106 |
1 files changed, 106 insertions, 0 deletions
diff --git a/kernel/terminal.cpp b/kernel/terminal.cpp new file mode 100644 index 0000000..f017cad --- /dev/null +++ b/kernel/terminal.cpp @@ -0,0 +1,106 @@ +#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_sz(const char *str) { + for (int 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; + } + + } + +} |