90 lines
2.2 KiB
C
90 lines
2.2 KiB
C
#include "vga.h"
|
|
#include "port.h"
|
|
#include "../lib/string.h"
|
|
#include "cpu/memlayout.h"
|
|
|
|
static char* const video_memory = (char*) (KERNBASE + 0xb8000);
|
|
|
|
enum colors16 : unsigned char {
|
|
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;
|
|
}
|
|
|
|
unsigned vga_get_offset(unsigned col, unsigned row) {
|
|
return row * VGA_COLS + col;
|
|
}
|
|
|
|
unsigned vga_get_row_from_offset(unsigned offset) {
|
|
return offset / VGA_COLS;
|
|
}
|
|
|
|
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));
|
|
port_byte_out(VGA_CTRL_REGISTER, VGA_OFFSET_LOW);
|
|
port_byte_out(VGA_DATA_REGISTER, (unsigned char) (offset & 0xff));
|
|
}
|
|
|
|
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;
|
|
video_memory[2 * offset + 1] = get_color(light_gray, black);
|
|
}
|
|
|
|
void vga_clear_screen() {
|
|
for (unsigned i = 0; i < VGA_ROWS * VGA_COLS; ++i) {
|
|
vga_set_char(i, ' ');
|
|
}
|
|
vga_set_cursor(0);
|
|
}
|
|
|
|
static unsigned scroll() {
|
|
kmemmove(video_memory, video_memory + 2 * VGA_COLS, 2 * VGA_COLS * (VGA_ROWS-1));
|
|
for (int col = 0; col < VGA_COLS; col++) {
|
|
vga_set_char(vga_get_offset(col, VGA_ROWS - 1), ' ');
|
|
}
|
|
return vga_get_offset(0, VGA_ROWS - 1);
|
|
}
|
|
|
|
void vga_print_string(const char* s) {
|
|
unsigned offset = vga_get_cursor();
|
|
while (*s != 0) {
|
|
if (*s == '\n') {
|
|
offset = vga_get_offset(0, vga_get_row_from_offset(offset) + 1);
|
|
} else {
|
|
vga_set_char(offset, *s);
|
|
offset++;
|
|
}
|
|
s++;
|
|
if (offset >= VGA_COLS * VGA_ROWS) {
|
|
offset = scroll();
|
|
}
|
|
}
|
|
vga_set_cursor(offset);
|
|
}
|