From 247fb5a8476aa66fdc6d4f042b0a743fe7c3ab2b Mon Sep 17 00:00:00 2001 From: aqua Date: Tue, 1 Nov 2022 17:43:33 +0200 Subject: Add uppercase scancodes Make text mode screen scroll --- devices/vga.c | 112 +++++++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 104 insertions(+), 8 deletions(-) (limited to 'devices/vga.c') diff --git a/devices/vga.c b/devices/vga.c index 983e630..908bd5e 100644 --- a/devices/vga.c +++ b/devices/vga.c @@ -1,35 +1,131 @@ #include "vga.h" -#include #include +#include struct __attribute__((packed)) VGAEntry { unsigned char text; uint8_t foreground : 4; uint8_t background : 4; }; +_Static_assert(sizeof(struct VGAEntry) == 2, "sizeof VGAEntry"); -_Static_assert(sizeof(struct VGAEntry) == 2); - -const size_t width = 80; -const size_t height = 25; +const int width = 80; +const int height = 25; struct VGAEntry *buffer; +int col = 0; +int row = 0; void vga_init() { buffer = (struct VGAEntry *)0xc03ff000; + // vga_enable_cursor(0, 15); vga_clear(VGA_COLOR_LIGHT_BLUE, VGA_COLOR_LIGHT_GREY); } void vga_clear(enum vga_color foreground, enum vga_color background) { - for (size_t y = 0; y < height; ++y) - for (size_t x = 0; x < width; ++x) { - const size_t index = y * width + x; + for (int y = 0; y < height; ++y) + for (int x = 0; x < width; ++x) { + const int index = y * width + x; buffer[index].text = ' '; buffer[index].foreground = foreground; buffer[index].background = background; } + col = row = 0; + // vga_update_cursor(); +} + +void +vga_putc(char a) +{ + switch (a) { + case '\n': + col = 0; + ++row; + break; + case '\r': + col = 0; + break; + case '\b': + --col; + if (col < 0) col = 0; + break; + default: + buffer[row * width + col].text = a; + ++col; + } + + if (col == width) { + col = 0; + ++row; + } + + if (row == height) { + // scroll up + for (int y = 1; y < height; ++y) + for (int x = 0; x < width; ++x) { + const int prev = (y - 1) * width + x; + const int curr = y * width + x; + buffer[prev] = buffer[curr]; + } + // blank out last row + for (int i = (height - 1) * width; i < height * width; ++i) buffer[i].text = ' '; + --row; + } +} + +void +vga_puts(const char *string, int len) +{ + + if (len == -1) + while (*string != '\0') { + vga_putc(*string); + ++string; + } + + else + for (int i = 0; i < len; ++i) { vga_putc(string[i]); } +} + +// Cursor +const uint16_t cga_idx_port = 0x3d4; +const uint16_t cga_dat_port = 0x3d5; + +const uint8_t cursor_start = 0xa; +const uint8_t cursor_end = 0xb; +const uint8_t cursor_addr_h = 0xe; +const uint8_t cursor_addr_l = 0xf; +const uint8_t cursor_hide = 0x20; + +void +vga_enable_cursor(unsigned char start, unsigned char end) +{ + outb(cga_idx_port, cursor_start); + outb(cga_dat_port, (inb(cga_dat_port) & 0xc0) | start); + + outb(cga_idx_port, cursor_end); + outb(cga_dat_port, (inb(cga_dat_port) & 0xe0) | end); +} + +void +vga_disable_cursor() +{ + outb(cga_idx_port, cursor_start); + outb(cga_dat_port, cursor_hide); +} + +void +vga_update_cursor() +{ + const uint16_t pos = row * width + col; + + outb(cga_idx_port, cursor_addr_l); + outb(cga_dat_port, pos & 0xff); + + outb(cga_idx_port, cursor_addr_h); + outb(cga_dat_port, (pos >> 8) & 0xff); } -- cgit v1.2.1