89 lines
2.2 KiB
C
Raw Normal View History

2026-04-04 12:36:25 +03:00
#include "vga.h"
2022-12-13 19:06:51 +03:00
#include "../lib/string.h"
2025-01-17 23:29:01 +04:00
#include "cpu/memlayout.h"
#include "port.h"
2022-11-14 00:23:42 +03:00
static char *const video_memory = (char *)(KERNBASE + 0xb8000);
2022-11-14 00:23:42 +03:00
enum colors16 : unsigned char {
2022-11-14 01:01:22 +03:00
black = 0,
blue,
green,
cyan,
red,
magenta,
brown,
light_gray,
dark_gray,
light_blue,
light_green,
light_cyan,
light_red,
light_magenta,
yellow,
white,
};
static unsigned char get_color(unsigned char fg, unsigned char bg) {
return (bg << 4) + fg;
}
2026-04-04 12:36:25 +03:00
unsigned vga_get_offset(unsigned col, unsigned row) {
return row * VGA_COLS + col;
2022-11-14 01:01:22 +03:00
}
unsigned vga_get_row_from_offset(unsigned offset) { return offset / VGA_COLS; }
2022-11-14 01:01:22 +03:00
2022-11-14 00:23:42 +03:00
void vga_set_cursor(unsigned offset) {
port_byte_out(VGA_CTRL_REGISTER, VGA_OFFSET_HIGH);
port_byte_out(VGA_DATA_REGISTER, (unsigned char)(offset >> 8));
2022-11-14 00:23:42 +03:00
port_byte_out(VGA_CTRL_REGISTER, VGA_OFFSET_LOW);
port_byte_out(VGA_DATA_REGISTER, (unsigned char)(offset & 0xff));
2022-11-14 00:23:42 +03:00
}
unsigned vga_get_cursor() {
port_byte_out(VGA_CTRL_REGISTER, VGA_OFFSET_HIGH);
unsigned offset = port_byte_in(VGA_DATA_REGISTER) << 8;
port_byte_out(VGA_CTRL_REGISTER, VGA_OFFSET_LOW);
offset += port_byte_in(VGA_DATA_REGISTER);
return offset;
}
void vga_set_char(unsigned offset, char c) {
video_memory[2 * offset] = c;
2022-11-14 01:01:22 +03:00
video_memory[2 * offset + 1] = get_color(light_gray, black);
2022-11-14 00:23:42 +03:00
}
void vga_clear_screen() {
2026-04-04 12:36:25 +03:00
for (unsigned i = 0; i < VGA_ROWS * VGA_COLS; ++i) {
2022-11-14 00:23:42 +03:00
vga_set_char(i, ' ');
}
vga_set_cursor(0);
}
2022-11-14 01:01:22 +03:00
static unsigned scroll() {
kmemmove(video_memory, video_memory + 2 * VGA_COLS,
2 * VGA_COLS * (VGA_ROWS - 1));
2026-04-04 12:36:25 +03:00
for (int col = 0; col < VGA_COLS; col++) {
vga_set_char(vga_get_offset(col, VGA_ROWS - 1), ' ');
2022-11-14 01:01:22 +03:00
}
2026-04-04 12:36:25 +03:00
return vga_get_offset(0, VGA_ROWS - 1);
2022-11-14 01:01:22 +03:00
}
void vga_print_string(const char *s) {
2022-11-14 01:01:22 +03:00
unsigned offset = vga_get_cursor();
2022-11-14 00:23:42 +03:00
while (*s != 0) {
2022-11-14 01:01:22 +03:00
if (*s == '\n') {
2026-04-04 12:36:25 +03:00
offset = vga_get_offset(0, vga_get_row_from_offset(offset) + 1);
2022-11-14 01:01:22 +03:00
} else {
vga_set_char(offset, *s);
offset++;
}
2022-11-14 00:23:42 +03:00
s++;
2026-04-04 12:36:25 +03:00
if (offset >= VGA_COLS * VGA_ROWS) {
2022-11-14 01:01:22 +03:00
offset = scroll();
}
2022-11-14 00:23:42 +03:00
}
vga_set_cursor(offset);
}