CoolPotOS/driver/vga.c

133 lines
3.5 KiB
C

#include "../include/vga.h"
#include "../include/common.h"
#include "../include/io.h"
size_t terminal_row;
size_t terminal_column;
uint8_t terminal_color;
uint16_t *terminal_buffer;
static uint16_t cursor_x = 0, cursor_y = 0; // 光标位置
static inline uint8_t vga_entry_color(enum vga_color fg, enum vga_color bg) {
return fg | bg << 4;
}
uint16_t vga_entry(unsigned char uc, uint8_t color) {
return (uint16_t) uc | (uint16_t) color << 8;
}
static void scroll() {
uint8_t attributeByte = (0 << 4) | (15 & 0x0F);
uint16_t blank = 0x20 | (attributeByte << 8);
if (cursor_y >= 25) {
int i;
for (i = 0 * 80; i < 24 * 80; i++) terminal_buffer[i] = terminal_buffer[i + 80];
for (i = 24 * 80; i < 25 * 80; i++) terminal_buffer[i] = blank;
cursor_y = 24;
}
}
void vga_install(void) {
terminal_row = 0;
terminal_column = 0;
terminal_color = vga_entry_color(VGA_COLOR_DARK_GREY, VGA_COLOR_BLACK);
terminal_buffer = (uint16_t *) 0xB8000;
//terminal_buffer = (uint16_t*) 0xA0000;
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 vga_clear() {
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);
}
}
cursor_x = 0;
cursor_y = 0;
move_cursor();
}
void move_cursor() {
uint16_t cursorLocation = cursor_y * 80 + cursor_x;
outb(0x3D4, 14);
outb(0x3D5, cursorLocation >> 8);
outb(0x3D4, 15);
outb(0x3D5, cursorLocation);
}
void vga_setcolor(uint8_t color) {
terminal_color = color;
}
void vga_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 vga_putchar(char c) {
uint8_t backColor = 0, foreColor = 15;
uint8_t attributeByte = (backColor << 4) | (foreColor & 0x07); // 黑底白字
uint16_t attribute = attributeByte << 8;
uint16_t *location;
if (c == 0x08 && cursor_x) {
cursor_x--;
location = terminal_buffer + (cursor_y * 80 + cursor_x);
*location = ' ' | attribute;
} else if (c == 0x09) {
location = terminal_buffer + (cursor_y * 80 + cursor_x);
*location = ' ' | attribute;
cursor_x = (cursor_x + 8) & ~(8 - 1);
} else if (c == '\r') {
cursor_x = 0;
} else if (c == '\n') {
cursor_x = 0; // 光标回首
cursor_y++; // 下一行
} else if (c >= ' ' && c <= '~') {
location = terminal_buffer + (cursor_y * 80 + cursor_x);
*location = c | attribute;
cursor_x++;
}
if (cursor_x >= 80) {
cursor_x = 0;
cursor_y++;
}
scroll();
move_cursor();
}
void vga_write_dec(uint32_t dec) {
int upper = dec / 10, rest = dec % 10;
if (upper) vga_write_dec(upper);
vga_putchar(rest + '0');
}
void vga_write(const char *data, size_t size) {
for (size_t i = 0; i < size; i++)
vga_putchar(data[i]);
}
void vga_writestring(const char *data) {
vga_write(data, strlen(data));
}
void printf(const char *formet, ...) {
int len;
va_list ap;
va_start(ap, formet);
char *buf[1024] = {0};
len = vsprintf(buf, formet, ap);
vga_writestring(buf);
va_end(ap);
}