:: commit 3eb7d5f0ba3c81d79b9c011bdd5e7e61f4612a9a

mintsuki <mintsuki@protonmail.com> — 2020-09-02 05:16

parents: 2052d92b91

Implement logic for graphical terminal

diff --git a/limine.bin b/limine.bin
index 7b95fbce..e6bb1327 100644
Binary files a/limine.bin and b/limine.bin differ
diff --git a/src/drivers/vbe.c b/src/drivers/vbe.c
index deb7ff47..5fac9b83 100644
--- a/src/drivers/vbe.c
+++ b/src/drivers/vbe.c
@@ -1,10 +1,170 @@
 #include <stddef.h>
 #include <stdint.h>
+#include <stdbool.h>
 #include <drivers/vbe.h>
+#include <lib/memmap.h>
+#include <lib/libc.h>
 #include <lib/blib.h>
 #include <lib/real.h>
 #include <lib/print.h>
 
+#define VGA_FONT_WIDTH  8
+#define VGA_FONT_HEIGHT 16
+#define VGA_FONT_GLYPHS 256
+#define VGA_FONT_MAX    (VGA_FONT_HEIGHT * VGA_FONT_GLYPHS)
+
+static uint8_t *vga_font;
+
+static void vga_font_retrieve(void) {
+    struct rm_regs r = {0};
+
+    r.eax = 0x1130;
+    r.ebx = 0x06;
+    rm_int(0x10, &r, &r);
+
+    vga_font = ext_mem_balloc(VGA_FONT_MAX);
+
+    memcpy(vga_font, (void *)rm_desegment(r.es, r.ebp), VGA_FONT_MAX);
+}
+
+static uint32_t *vbe_framebuffer;
+static uint16_t  vbe_pitch;
+static uint16_t  vbe_width = 0;
+static uint16_t  vbe_height = 0;
+static uint16_t  vbe_bpp = 0;
+
+void vbe_plot_px(int x, int y, uint32_t hex) {
+    size_t fb_i = x + (vbe_pitch / sizeof(uint32_t)) * y;
+
+    vbe_framebuffer[fb_i] = hex;
+}
+
+void vbe_plot_char(struct vbe_char c, int x, int y) {
+    int orig_x = x;
+    uint8_t *glyph = &vga_font[c.c * VGA_FONT_HEIGHT];
+
+    for (int i = 0; i < VGA_FONT_HEIGHT; i++) {
+        for (int j = VGA_FONT_WIDTH - 1; j >= 0; j--)
+            vbe_plot_px(x++, y, (glyph[i] & (1 << j)) ? c.fg : c.bg);
+        y++;
+        x = orig_x;
+    }
+}
+
+static struct vbe_char *grid;
+
+static bool cursor_status = true;
+
+static int cursor_x;
+static int cursor_y;
+
+static uint32_t cursor_fg = 0x00000000;
+static uint32_t cursor_bg = 0x00ffffff;
+static uint32_t text_fg   = 0x00ffffff;
+static uint32_t text_bg   = 0x00000000;
+
+static int rows;
+static int cols;
+
+static void plot_char_grid(struct vbe_char c, int x, int y) {
+    vbe_plot_char(c, x * VGA_FONT_WIDTH, y * VGA_FONT_HEIGHT);
+    grid[x + y * cols] = c;
+}
+
+static void clear_cursor(void) {
+    if (cursor_status) {
+        vbe_plot_char(grid[cursor_x + cursor_y * cols],
+                  cursor_x * VGA_FONT_WIDTH, cursor_y * VGA_FONT_HEIGHT);
+    }
+}
+
+static void draw_cursor(void) {
+    struct vbe_char c = grid[cursor_x + cursor_y * cols];
+    c.fg = cursor_fg;
+    c.bg = cursor_bg;
+    if (cursor_status)
+        vbe_plot_char(c, cursor_x * VGA_FONT_WIDTH, cursor_y * VGA_FONT_HEIGHT);
+}
+
+void vbe_scroll(void) {
+    clear_cursor();
+
+    for (int i = cols; i < rows * cols; i++) {
+        plot_char_grid(grid[i], (i - cols) % cols, (i - cols) / cols);
+    }
+
+    // Clear the last line of the screen.
+    struct vbe_char empty;
+    empty.c  = ' ';
+    empty.fg = text_fg;
+    empty.bg = text_bg;
+    for (int i = rows * cols - cols; i < rows * cols; i++) {
+        plot_char_grid(empty, i % cols, i / cols);
+    }
+
+    draw_cursor();
+}
+
+void vbe_clear(void) {
+    clear_cursor();
+
+    struct vbe_char empty;
+    empty.c  = ' ';
+    empty.fg = text_fg;
+    empty.bg = text_bg;
+    for (int i = 0; i < rows * cols; i++) {
+        plot_char_grid(empty, i % cols, i / cols);
+    }
+
+    cursor_x = 0;
+    cursor_y = 0;
+
+    draw_cursor();
+}
+
+void vbe_enable_cursor(void) {
+    cursor_status = true;
+    draw_cursor();
+}
+
+void vbe_disable_cursor(void) {
+    clear_cursor();
+    cursor_status = false;
+}
+
+void vbe_set_cursor_pos(int x, int y) {
+    clear_cursor();
+    cursor_x = x;
+    cursor_y = y;
+    draw_cursor();
+}
+
+void vbe_get_cursor_pos(int *x, int *y) {
+    *x = cursor_x;
+    *y = cursor_y;
+}
+
+void vbe_set_text_attributes(uint32_t fg, uint32_t bg) {
+    text_fg = fg;
+    text_bg = bg;
+}
+
+void vbe_set_cursor_attributes(uint32_t fg, uint32_t bg) {
+    clear_cursor();
+    cursor_fg = fg;
+    cursor_bg = bg;
+    draw_cursor();
+}
+
+void vbe_tty_init(void) {
+    init_vbe(&vbe_framebuffer, &vbe_pitch, &vbe_width, &vbe_height, &vbe_bpp);
+    vga_font_retrieve();
+    cols = vbe_width / VGA_FONT_WIDTH;
+    rows = vbe_height / VGA_FONT_HEIGHT;
+    grid = ext_mem_balloc(rows * cols * sizeof(struct vbe_char));
+    vbe_clear();
+}
+
 struct vbe_info_struct {
     char     signature[4];
     uint8_t  version_min;
@@ -119,7 +279,7 @@ static struct resolution fallback_resolutions[] = {
     { 640,  480, 32 }
 };
 
-int init_vbe(uint64_t *framebuffer, uint16_t *pitch, uint16_t *target_width, uint16_t *target_height, uint16_t *target_bpp) {
+int init_vbe(uint32_t **framebuffer, uint16_t *pitch, uint16_t *target_width, uint16_t *target_height, uint16_t *target_bpp) {
     print("vbe: Initialising...\n");
 
     size_t current_fallback = 0;
@@ -166,7 +326,7 @@ retry:;
           && vbe_mode_info.res_y == *target_height
           && vbe_mode_info.bpp   == *target_bpp) {
             print("vbe: Found matching mode %x, attempting to set\n", vid_modes[i]);
-            *framebuffer = (uint64_t)vbe_mode_info.framebuffer;
+            *framebuffer = (uint32_t *)vbe_mode_info.framebuffer;
             *pitch       = (int)vbe_mode_info.pitch;
             print("vbe: Framebuffer address: %x\n", vbe_mode_info.framebuffer);
             set_vbe_mode(vid_modes[i]);
diff --git a/src/drivers/vbe.h b/src/drivers/vbe.h
index 180deb1a..af9fa30e 100644
--- a/src/drivers/vbe.h
+++ b/src/drivers/vbe.h
@@ -1,6 +1,14 @@
 #ifndef __DRIVERS__VBE_H__
 #define __DRIVERS__VBE_H__
 
-int init_vbe(uint64_t *framebuffer, uint16_t *pitch, uint16_t *target_width, uint16_t *target_height, uint16_t *target_bpp);
+#include <stdint.h>
+
+struct vbe_char {
+    char c;
+    uint32_t fg;
+    uint32_t bg;
+};
+
+int init_vbe(uint32_t **framebuffer, uint16_t *pitch, uint16_t *target_width, uint16_t *target_height, uint16_t *target_bpp);
 
 #endif
diff --git a/src/lib/memmap.c b/src/lib/memmap.c
index 1cd14e3d..321fea73 100644
--- a/src/lib/memmap.c
+++ b/src/lib/memmap.c
@@ -168,7 +168,7 @@ void init_memmap(void) {
 static size_t ext_mem_balloc_base = 0x100000;
 
 void *ext_mem_balloc(size_t count) {
-    ext_mem_balloc_aligned(count, 4);
+    return ext_mem_balloc_aligned(count, 4);
 }
 
 // TODO: this basically only works for the 1st extended memory entry in the
@@ -186,7 +186,7 @@ void *ext_mem_balloc_aligned(size_t count, size_t alignment) {
         if (base >= entry_base && base < entry_top &&
             top  >= entry_base && top  < entry_top) {
             ext_mem_balloc_base = base + count;
-            return (void *)base;
+            return (void *)(size_t)base;
         }
     }
 
diff --git a/src/protos/stivale.c b/src/protos/stivale.c
index 305191be..ebf10fce 100644
--- a/src/protos/stivale.c
+++ b/src/protos/stivale.c
@@ -225,11 +225,13 @@ void stivale_load(char *cmdline, int boot_drive) {
     stivale_struct.framebuffer_bpp    = stivale_hdr.framebuffer_bpp;
 
     if (stivale_hdr.flags & (1 << 0)) {
-        init_vbe(&stivale_struct.framebuffer_addr,
+        uint32_t *fb32;
+        init_vbe(&fb32,
                  &stivale_struct.framebuffer_pitch,
                  &stivale_struct.framebuffer_width,
                  &stivale_struct.framebuffer_height,
                  &stivale_struct.framebuffer_bpp);
+        stivale_struct.framebuffer_addr = (uint64_t)(size_t)fb32;
     } else {
         deinit_vga_textmode();
     }
diff --git a/src/protos/stivale2.c b/src/protos/stivale2.c
index 5f812872..b7a1fd46 100644
--- a/src/protos/stivale2.c
+++ b/src/protos/stivale2.c
@@ -374,11 +374,13 @@ void stivale2_load(char *cmdline, int boot_drive) {
         tag->framebuffer_height = hdrtag->framebuffer_height;
         tag->framebuffer_bpp    = hdrtag->framebuffer_bpp;
 
-        init_vbe(&tag->framebuffer_addr,
+        uint32_t *fb32;
+        init_vbe(&fb32,
                  &tag->framebuffer_pitch,
                  &tag->framebuffer_width,
                  &tag->framebuffer_height,
                  &tag->framebuffer_bpp);
+        tag->framebuffer_addr = (uint64_t)(size_t)fb32;
 
         append_tag(&stivale2_struct, (struct stivale2_tag *)tag);
     }
tab: 248 wrap: offon