#include "vga.h" #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"); 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 (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); }