summaryrefslogtreecommitdiff
path: root/kernel/terminal.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/terminal.cpp')
-rw-r--r--kernel/terminal.cpp106
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;
+ }
+
+ }
+
+}