diff options
Diffstat (limited to 'src/vga.c')
-rw-r--r-- | src/vga.c | 112 |
1 files changed, 112 insertions, 0 deletions
diff --git a/src/vga.c b/src/vga.c new file mode 100644 index 0000000..150af9b --- /dev/null +++ b/src/vga.c @@ -0,0 +1,112 @@ +#include <nrvn.h> +#include <vga.h> + +static size_t vga_x, vga_y; +static uint8_t vga_color; +static uint16_t *vga_buffer; + +void vga_init(void) { + vga_x = vga_y = 0; + vga_set_color(VGA_LIGHT_MAGENTA, VGA_BLACK); + vga_buffer = (uint16_t *)0xB8000; + for (size_t y = 0; y < VGA_HEIGHT; y++) + for (size_t x = 0; x < VGA_WIDTH; x++) + vga_buffer[y * VGA_WIDTH + x] = ' ' | (vga_color << 8); +} + +void vga_scroll() { + if (vga_y < VGA_HEIGHT) + return; + + for (size_t y = 0; y < VGA_HEIGHT - 1; y++) { + for (size_t x = 0; x < VGA_WIDTH; x++) { + const size_t from = (y + 1) * VGA_WIDTH + x; + const size_t to = y * VGA_WIDTH + x; + vga_buffer[to] = vga_buffer[from]; + } + } + vga_y = VGA_HEIGHT - 1; + for (size_t x = 0; x < VGA_HEIGHT; x++) { + vga_buffer[vga_y * VGA_WIDTH + x] = ' ' | (vga_color << 8); + } +} + +void vga_update_cursor(void) { + size_t index = vga_y * VGA_WIDTH + vga_x; + + outb(0x3D4, 14); + outb(0x3D5, index >> 8); + outb(0x3D4, 15); + outb(0x3D5, index); +} + +void vga_putn(const size_t number) { + char digits[32] = { 0 }; + size_t num = number, count = 0; + do { + digits[count] = (num % 10) + '0'; + count++; + } while ((num /= 10) > 0); + + do { + vga_putc(digits[count]); + } while (count-- > 0); +} + +void vga_putx(const size_t hex) { + char digits[32] = { 0 }; + size_t num = hex, count = 0; + do { + digits[count] = "0123456789abcdef"[num % 16]; + count++; + } while ((num /= 16) > 0); + + vga_puts("0x"); + do { + vga_putc(digits[count]); + } while (count-- > 0); +} + +void vga_putc(const char c) { + switch (c) { + case '\n': + vga_x = 0; + vga_y++; + break; + case '\b': + if (vga_x > 0) + vga_x--; + break; + case '\r': + vga_x = 0; + break; + case '\t': + break; + default: + // Any character greater than and including a space, is a printable character + if (c >= ' ') + vga_buffer[vga_y * VGA_WIDTH + vga_x++] = (uint16_t) c | ((uint16_t) vga_color << 8); + } + + if (vga_x >= VGA_WIDTH) { + vga_x = 0; + vga_y++; + } + + vga_scroll(); + vga_update_cursor(); +} + +void vga_puts(const char *s) { + while (*s) + vga_putc(*s++); +} + +void vga_putsn(const char *s, const size_t len) { + for (size_t i = 0; i < len; i++) + vga_putc(s[i]); +} + +void vga_set_color(const uint8_t fg, const uint8_t bg) { + vga_color = fg | bg << 4; +} |