167 lines
3.8 KiB
C
167 lines
3.8 KiB
C
#include "vga.h"
|
|
#include "io.h"
|
|
#include "irq.h"
|
|
#include "klibc.h"
|
|
|
|
static uint vgaBgColor;
|
|
static uint vgaColor;
|
|
static int line, col;
|
|
|
|
static volatile short *vga = (short *)VGA_ADDR;
|
|
static void clearScreen(uint bgColor);
|
|
static void cursorMove(int x, int y);
|
|
static void cursorEnable(uint8_t cursor_start, uint8_t cursor_end);
|
|
static void printCharDetails(char str, uint color, uint bgColor, int startX, int startY);
|
|
|
|
int VGASetup(uint bgColor, uint color)
|
|
{
|
|
vgaBgColor = bgColor;
|
|
vgaColor = color;
|
|
line = 0;
|
|
col = 0;
|
|
clearScreen(bgColor);
|
|
cursorEnable(14, 15);
|
|
return 0;
|
|
}
|
|
|
|
static void clearScreen(uint bgColor)
|
|
{
|
|
uint32_t flags;
|
|
long int colorAttr = bgColor << 12;
|
|
|
|
disable_IRQs(flags);
|
|
for (int i = 0; i < VGA_WIDTH * VGA_HEIGHT; i++) {
|
|
vga[i] = colorAttr;
|
|
}
|
|
restore_IRQs(flags);
|
|
}
|
|
|
|
void VGAclearLine(uint bgColor, uint line)
|
|
{
|
|
uint32_t flags;
|
|
long int colorAttr = bgColor << 12;
|
|
|
|
if (line >= VGA_HEIGHT)
|
|
return;
|
|
|
|
disable_IRQs(flags);
|
|
for (uint i = VGA_WIDTH * line; i < VGA_WIDTH * (line + 1); i++) {
|
|
vga[i] = colorAttr;
|
|
}
|
|
restore_IRQs(flags);
|
|
}
|
|
|
|
void VGAPrintf(uint color, uint bgColor, int startX, int startY, const char *format, ...)
|
|
{
|
|
int flags;
|
|
char tmp[VGA_WIDTH];
|
|
int idx = 0;
|
|
|
|
disable_IRQs(flags);
|
|
|
|
va_list ap;
|
|
va_start(ap, format);
|
|
|
|
int ret = vsnprintf(tmp, sizeof(tmp), format, ap);
|
|
while (ret > 0 && tmp[idx]) {
|
|
printCharDetails(tmp[idx++], color, bgColor, startX++, startY);
|
|
}
|
|
va_end(ap);
|
|
|
|
restore_IRQs(flags);
|
|
}
|
|
|
|
static void printCharDetails(const char str, uint color, uint bgColor, int startX, int startY)
|
|
{
|
|
int pos = VGA_WIDTH * startY + startX;
|
|
|
|
if (pos > VGA_WIDTH * VGA_HEIGHT || pos < 0)
|
|
return;
|
|
|
|
long int colorAttr = (bgColor << 4 | (color & 0x0f)) << 8;
|
|
vga[pos] = colorAttr | str;
|
|
}
|
|
|
|
void VGAScrollUp(void)
|
|
{
|
|
long int colorAttr = vgaBgColor << 12;
|
|
int flags;
|
|
|
|
disable_IRQs(flags);
|
|
for (int i = 1; i < VGA_HEIGHT - VGA_STATUS_LINE_HEIGHT;
|
|
i++) { // last line is status line. Do not scroll it
|
|
memcpy((void *)&vga[VGA_WIDTH * (i - 1)], (void *)&vga[VGA_WIDTH * i],
|
|
VGA_WIDTH * sizeof(short));
|
|
}
|
|
for (int i = 0; i < VGA_WIDTH; i++) {
|
|
vga[(VGA_HEIGHT - 1 - VGA_STATUS_LINE_HEIGHT) * VGA_WIDTH + i] = colorAttr;
|
|
}
|
|
restore_IRQs(flags);
|
|
}
|
|
|
|
void VGAPutc(const char str)
|
|
{
|
|
int flags;
|
|
|
|
disable_IRQs(flags);
|
|
if (str == '\n') {
|
|
line++;
|
|
col = 0;
|
|
if (line >= VGA_HEIGHT - VGA_STATUS_LINE_HEIGHT) {
|
|
VGAScrollUp();
|
|
line--;
|
|
}
|
|
} else if (str == '\r') {
|
|
col = 0;
|
|
} else if (str == '\b') {
|
|
col--;
|
|
if (col < 0) {
|
|
col = VGA_WIDTH - 1;
|
|
line--;
|
|
if (line < 0)
|
|
line = 0;
|
|
}
|
|
printCharDetails(' ', vgaColor, vgaBgColor, col, line);
|
|
} else {
|
|
printCharDetails(str, vgaColor, vgaBgColor, col++, line);
|
|
if (col == VGA_WIDTH) {
|
|
col = 0;
|
|
line++;
|
|
}
|
|
if (line >= VGA_HEIGHT - VGA_STATUS_LINE_HEIGHT) {
|
|
VGAScrollUp();
|
|
line--;
|
|
}
|
|
}
|
|
|
|
cursorMove(col, line);
|
|
restore_IRQs(flags);
|
|
}
|
|
|
|
static void cursorEnable(uint8_t cursor_start, uint8_t cursor_end)
|
|
{
|
|
outb(0x3D4, 0x0A);
|
|
outb(0x3D5, (inb(0x3D5) & 0xC0) | cursor_start);
|
|
|
|
outb(0x3D4, 0x0B);
|
|
outb(0x3D5, (inb(0x3D5) & 0xE0) | cursor_end);
|
|
}
|
|
|
|
void cursorDisable(void)
|
|
{
|
|
outb(0x3D4, 0x0A);
|
|
outb(0x3D5, 0x20);
|
|
}
|
|
|
|
static void cursorMove(int x, int y)
|
|
{
|
|
long int colorAttr = (vgaBgColor << 4 | (vgaColor & 0x0f)) << 8;
|
|
uint16_t pos = y * VGA_WIDTH + x;
|
|
vga[pos] = colorAttr;
|
|
|
|
outb(0x3D4, 0x0F);
|
|
outb(0x3D5, (uint8_t)(pos & 0xFF));
|
|
outb(0x3D4, 0x0E);
|
|
outb(0x3D5, (uint8_t)((pos >> 8) & 0xFF));
|
|
}
|