orion/src/vga.c

97 lines
2.4 KiB
C

/*
From OSDev Wiki:
IMPORTANT NOTE: the VGA text mode (as well as the BIOS) is deprecated
on newer machines, and UEFI only supports pixel buffers. For forward
compatibility you might want to start with that. Ask GRUB to set up a
framebuffer using appropriate Multiboot flags or call VESA VBE yourself. Unlike
VGA text mode, a framebuffer has pixels, so you have to draw each glyph
yourself.
*/
#include <vga.h>
#include <string.h>
size_t terminal_row;
size_t terminal_column;
uint8_t terminal_color;
uint16_t* terminal_buffer;
static inline uint8_t vga_entry_color(enum vga_color fg, enum vga_color bg) {
return fg | bg << 4;
}
static inline uint16_t vga_entry(unsigned char uc, int color) {
return (uint16_t) uc | (uint16_t) color << 8;
}
void terminal_initialize(void) {
terminal_row = 0;
terminal_column = 0;
terminal_color = vga_entry_color(VGA_COLOR_LIGHT_GREY, VGA_COLOR_BLACK);
terminal_buffer = (uint16_t*) 0xB8000;
for (size_t y = 0; y < VGA_HEIGHT; y++) {
for (size_t x = 0; x < VGA_WIDTH; x++) {
const size_t index = y * VGA_WIDTH + x;
terminal_buffer[index] = vga_entry(' ', terminal_color);
}
}
}
void terminal_setcolor(uint8_t color) {
terminal_color = color;
}
void terminal_putentryat(char c, uint8_t color, size_t x, size_t y) {
const size_t index = y * VGA_WIDTH + x;
terminal_buffer[index] = vga_entry(c, color);
}
void terminal_scroll() {
if (terminal_row >= 25) {
int i;
for (i = 0; i < 24*80; i++)
terminal_buffer[i] = terminal_buffer[i+80];
for (i = 24*80; i < 25*80; i++)
terminal_buffer[i] = ' ';
terminal_row = 24;
}
}
void terminal_delete_last_line() {
int x, *ptr;
for(x = 0; x < VGA_WIDTH * 2; x++) {
ptr = (int*)0xB8000 + (VGA_WIDTH * 2) * (VGA_HEIGHT - 1) + x;
*ptr = 0;
}
}
void terminal_putchar(char c) {
terminal_putentryat(c, terminal_color, terminal_column, terminal_row);
if (c != '\n') {
if (++terminal_column == VGA_WIDTH) {
terminal_column = 0;
if (++terminal_row == VGA_HEIGHT) {
for(int line = 1; line <= VGA_HEIGHT - 1; line++)
terminal_scroll(line);
terminal_delete_last_line();
terminal_row = VGA_HEIGHT - 1;
}
}
} else {
terminal_row += 1;
terminal_column = 0;
}
terminal_scroll();
}
void terminal_write(const char* data, size_t size) {
for (size_t i = 0; i < size; i++)
terminal_putchar(data[i]);
}
void terminal_writestring(const char* data) {
terminal_write(data, strlen(data));
}