#include "vga.h" #include "../kernel/io.h" #include #define VGA_WIDTH 80 #define VGA_HEIGHT 25 #define VGA_ADDRESS 0xB8000 static volatile char *video_mem = (volatile char*)VGA_ADDRESS; static int cursor_x = 0; static int cursor_y = 0; static char current_color = 0x07; // По умолчанию серый на черном // Локальная функция для сдвига экрана вверх на одну строку static void vga_scroll(void) { // Копируем строки с 1-й по 24-ю на место строк с 0-й по 23-ю // Каждая строка занимает VGA_WIDTH * 2 байт (символ + атрибут) for (int i = 0; i < (VGA_HEIGHT - 1) * VGA_WIDTH * 2; i++) { video_mem[i] = video_mem[i + VGA_WIDTH * 2]; } // Очищаем самую нижнюю строку (заполняем пробелами с текущим цветом) int last_row_start = (VGA_HEIGHT - 1) * VGA_WIDTH * 2; for (int i = 0; i < VGA_WIDTH; i++) { video_mem[last_row_start + i * 2] = ' '; video_mem[last_row_start + i * 2 + 1] = current_color; } } void vga_update_cursor(int x, int y) { // Вычисляем плоский индекс в видеопамяти uint16_t pos = y * VGA_WIDTH + x; // Передаем контроллеру VGA младший байт позиции (регистр 15) outb(0x3D4, 0x0F); outb(0x3D5, (uint8_t)(pos & 0xFF)); // Передаем старший байт позиции (регистр 14) outb(0x3D4, 0x0E); outb(0x3D5, (uint8_t)((pos >> 8) & 0xFF)); } void vga_init(void) { cursor_x = 0; cursor_y = 0; // Заполняем весь экран пробелами for (int i = 0; i < VGA_WIDTH * VGA_HEIGHT; i++) { video_mem[i * 2] = ' '; video_mem[i * 2 + 1] = current_color; } vga_update_cursor(0,0); } void vga_set_color(char fg, char bg) { current_color = (bg << 4) | (fg & 0x0F); } void vga_putchar(char c) { // Обработка бэкспейса (стирание символа) if (c == '\b') { if (cursor_x > 0) { cursor_x--; } else if (cursor_y > 0) { cursor_y--; cursor_x = VGA_WIDTH - 1; } int index = (cursor_y * VGA_WIDTH + cursor_x) * 2; video_mem[index] = ' '; video_mem[index + 1] = current_color; vga_update_cursor(cursor_x, cursor_y); return; // Выходим, чтобы не двигать курсор вперед } // Обработка переноса строки if (c == '\n') { cursor_x = 0; cursor_y++; } else if (c >= ' ') { // Печатаем только видимые символы int index = (cursor_y * VGA_WIDTH + cursor_x) * 2; video_mem[index] = c; video_mem[index + 1] = current_color; cursor_x++; } // Если вышли за правый край — перенос if (cursor_x >= VGA_WIDTH) { cursor_x = 0; cursor_y++; } // Если экран кончился — скроллим вверх, пока курсор не встанет на последнюю строку if (cursor_y >= VGA_HEIGHT) { vga_scroll(); cursor_y = VGA_HEIGHT - 1; } vga_update_cursor(cursor_x, cursor_y); } void vga_print(const char *str) { for (int i = 0; str[i] != '\0'; i++) { vga_putchar(str[i]); } } void vga_println(const char *str) { for (int i = 0; str[i] != '\0'; i++) { vga_putchar(str[i]); } vga_putchar('\n'); }