ROADMAP: закрыт 1 пункт

This commit is contained in:
msh356 2026-07-02 20:35:20 +03:00
parent 8e6f9cb31a
commit 7136ac3155
3 changed files with 59 additions and 5 deletions

View file

@ -12,7 +12,7 @@
- [x] UART отладка
- [x] Драйвер таймера
- [x] Драйвер клавиатуры
- [ ] Нормальный драйвер VGA (скролл итд)
- [x] Нормальный драйвер VGA (скролл итд)
- [ ] Нормальный драйвер клавиатуры (Caps Lock, Shift, Numpad итд)
- [ ] Драйвер PC Speaker
- [ ] Screen buffers (как tty в Linux)

View file

@ -1,4 +1,6 @@
#include "vga.h"
#include "../kernel/io.h"
#include <stdint.h>
#define VGA_WIDTH 80
#define VGA_HEIGHT 25
@ -9,6 +11,34 @@ 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;
@ -17,6 +47,7 @@ void vga_init(void) {
video_mem[i * 2] = ' ';
video_mem[i * 2 + 1] = current_color;
}
vga_update_cursor(0,0);
}
void vga_set_color(char fg, char bg) {
@ -24,11 +55,26 @@ void vga_set_color(char fg, char bg) {
}
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 {
} else if (c >= ' ') { // Печатаем только видимые символы
int index = (cursor_y * VGA_WIDTH + cursor_x) * 2;
video_mem[index] = c;
video_mem[index + 1] = current_color;
@ -41,10 +87,12 @@ void vga_putchar(char c) {
cursor_y++;
}
// Если экран кончился — просто сбрасываем наверх (примитивный скролл)
// Если экран кончился — скроллим вверх, пока курсор не встанет на последнюю строку
if (cursor_y >= VGA_HEIGHT) {
vga_init();
vga_scroll();
cursor_y = VGA_HEIGHT - 1;
}
vga_update_cursor(cursor_x, cursor_y);
}
void vga_print(const char *str) {
@ -54,6 +102,9 @@ void vga_print(const char *str) {
}
void vga_println(const char *str) {
vga_print(str);
for (int i = 0; str[i] != '\0'; i++) {
vga_putchar(str[i]);
}
vga_putchar('\n');
}

View file

@ -25,4 +25,7 @@ void vga_print(const char *str);
// Вывод строки с автоматическим переносом на новую линию
void vga_println(const char *str);
// Обновление курсора
void vga_update_cursor(int x, int y);
#endif