#include "vga.h" #include "io.h" #include "irq.h" #include "klibc.h" static uint vgaBgColor; static uint vgaColor; static int line, col; static volatile short *vga = (short *)VGA_ADDR; static void clearScreen(uint bgColor); int VGASetup(uint bgColor, uint color) { vgaBgColor = bgColor; vgaColor = color; line = 0; col = 0; clearScreen(bgColor); return 0; } static void clearScreen(uint bgColor) { uint32_t flags; long int colorAttr = bgColor << 12; disable_IRQs(flags); for (int i = 0; i < VGA_WIDTH * VGA_HEIGHT; i++) { vga[i] = colorAttr; } restore_IRQs(flags); } void clearScreenLine(uint bgColor, uint line) { uint32_t flags; long int colorAttr = bgColor << 12; if (line >= VGA_HEIGHT) return; disable_IRQs(flags); for (uint i = VGA_WIDTH * line; i < VGA_WIDTH * (line + 1); i++) { vga[i] = colorAttr; } restore_IRQs(flags); } void VGAprintf(uint color, uint bgColor, int startX, int startY, const char *format, ...) { int flags; char tmp[VGA_WIDTH]; int idx = 0; disable_IRQs(flags); va_list ap; va_start(ap, format); int ret = vsnprintf(tmp, sizeof(tmp), format, ap); while (ret > 0 && tmp[idx]) { printCharDetails(tmp[idx++], color, bgColor, startX++, startY); } va_end(ap); restore_IRQs(flags); } void printCharDetails(const char str, uint color, uint bgColor, int startX, int startY) { long int colorAttr = (bgColor << 4 | (color & 0x0f)) << 8; vga[VGA_WIDTH * startY + startX] = colorAttr | str; } void vgaScrollUp(void) { long int colorAttr = vgaBgColor << 12; int flags; disable_IRQs(flags); for (int i = 1; i < VGA_HEIGHT - 1; i++) { // last line is status line. Do not scroll it memcpy((void *)&vga[VGA_WIDTH * (i - 1)], (void *)&vga[VGA_WIDTH * i], VGA_WIDTH * sizeof(short)); } for (int i = 0; i < VGA_WIDTH; i++) { vga[(VGA_HEIGHT - 2) * VGA_WIDTH + i] = colorAttr; } restore_IRQs(flags); } void VGAputc(const char str) { int flags; disable_IRQs(flags); if (str == '\n') { line++; col = 0; if (line >= VGA_HEIGHT - 1) { vgaScrollUp(); line--; } } else if (str == '\r') { col = 0; } else if (str == '\b') { col--; if (col < 0) { col = VGA_WIDTH - 1; line--; } printCharDetails(' ', vgaColor, vgaBgColor, col, line); } else { printCharDetails(str, vgaColor, vgaBgColor, col++, line); if (col == VGA_WIDTH) { col = 0; line++; } if (line >= VGA_HEIGHT - 1) { vgaScrollUp(); line--; } } cursorMove(col, line); restore_IRQs(flags); } void cursorEnable(uint8_t cursor_start, uint8_t cursor_end) { outb(0x3D4, 0x0A); outb(0x3D5, (inb(0x3D5) & 0xC0) | cursor_start); outb(0x3D4, 0x0B); outb(0x3D5, (inb(0x3D5) & 0xE0) | cursor_end); } void cursorDisable(void) { outb(0x3D4, 0x0A); outb(0x3D5, 0x20); } void cursorMove(int x, int y) { long int colorAttr = (vgaBgColor << 4 | (vgaColor & 0x0f)) << 8; uint16_t pos = y * VGA_WIDTH + x; vga[pos] = colorAttr; outb(0x3D4, 0x0F); outb(0x3D5, (uint8_t)(pos & 0xFF)); outb(0x3D4, 0x0E); outb(0x3D5, (uint8_t)((pos >> 8) & 0xFF)); }