ROADMAP: закрыт 1 пункт
This commit is contained in:
parent
8e6f9cb31a
commit
7136ac3155
3 changed files with 59 additions and 5 deletions
|
|
@ -12,7 +12,7 @@
|
||||||
- [x] UART отладка
|
- [x] UART отладка
|
||||||
- [x] Драйвер таймера
|
- [x] Драйвер таймера
|
||||||
- [x] Драйвер клавиатуры
|
- [x] Драйвер клавиатуры
|
||||||
- [ ] Нормальный драйвер VGA (скролл итд)
|
- [x] Нормальный драйвер VGA (скролл итд)
|
||||||
- [ ] Нормальный драйвер клавиатуры (Caps Lock, Shift, Numpad итд)
|
- [ ] Нормальный драйвер клавиатуры (Caps Lock, Shift, Numpad итд)
|
||||||
- [ ] Драйвер PC Speaker
|
- [ ] Драйвер PC Speaker
|
||||||
- [ ] Screen buffers (как tty в Linux)
|
- [ ] Screen buffers (как tty в Linux)
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,6 @@
|
||||||
#include "vga.h"
|
#include "vga.h"
|
||||||
|
#include "../kernel/io.h"
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
#define VGA_WIDTH 80
|
#define VGA_WIDTH 80
|
||||||
#define VGA_HEIGHT 25
|
#define VGA_HEIGHT 25
|
||||||
|
|
@ -9,6 +11,34 @@ static int cursor_x = 0;
|
||||||
static int cursor_y = 0;
|
static int cursor_y = 0;
|
||||||
static char current_color = 0x07; // По умолчанию серый на черном
|
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) {
|
void vga_init(void) {
|
||||||
cursor_x = 0;
|
cursor_x = 0;
|
||||||
cursor_y = 0;
|
cursor_y = 0;
|
||||||
|
|
@ -17,6 +47,7 @@ void vga_init(void) {
|
||||||
video_mem[i * 2] = ' ';
|
video_mem[i * 2] = ' ';
|
||||||
video_mem[i * 2 + 1] = current_color;
|
video_mem[i * 2 + 1] = current_color;
|
||||||
}
|
}
|
||||||
|
vga_update_cursor(0,0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void vga_set_color(char fg, char bg) {
|
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) {
|
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') {
|
if (c == '\n') {
|
||||||
cursor_x = 0;
|
cursor_x = 0;
|
||||||
cursor_y++;
|
cursor_y++;
|
||||||
} else {
|
} else if (c >= ' ') { // Печатаем только видимые символы
|
||||||
int index = (cursor_y * VGA_WIDTH + cursor_x) * 2;
|
int index = (cursor_y * VGA_WIDTH + cursor_x) * 2;
|
||||||
video_mem[index] = c;
|
video_mem[index] = c;
|
||||||
video_mem[index + 1] = current_color;
|
video_mem[index + 1] = current_color;
|
||||||
|
|
@ -41,10 +87,12 @@ void vga_putchar(char c) {
|
||||||
cursor_y++;
|
cursor_y++;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Если экран кончился — просто сбрасываем наверх (примитивный скролл)
|
// Если экран кончился — скроллим вверх, пока курсор не встанет на последнюю строку
|
||||||
if (cursor_y >= VGA_HEIGHT) {
|
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) {
|
void vga_print(const char *str) {
|
||||||
|
|
@ -54,6 +102,9 @@ void vga_print(const char *str) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void vga_println(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');
|
vga_putchar('\n');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -25,4 +25,7 @@ void vga_print(const char *str);
|
||||||
// Вывод строки с автоматическим переносом на новую линию
|
// Вывод строки с автоматическим переносом на новую линию
|
||||||
void vga_println(const char *str);
|
void vga_println(const char *str);
|
||||||
|
|
||||||
|
// Обновление курсора
|
||||||
|
void vga_update_cursor(int x, int y);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue