2018-07-20 15:41:58 +02:00
|
|
|
#include "vga.h"
|
|
|
|
#include "io.h"
|
|
|
|
#include "klibc.h"
|
|
|
|
|
|
|
|
static uint vgaBgColor;
|
|
|
|
static uint vgaColor;
|
|
|
|
static int line, col;
|
|
|
|
|
2018-11-08 22:08:27 +01:00
|
|
|
int VGASetup(uint bgColor, uint color)
|
2018-07-20 15:41:58 +02:00
|
|
|
{
|
|
|
|
vgaBgColor = bgColor;
|
|
|
|
vgaColor = color;
|
|
|
|
clearScreen(bgColor);
|
|
|
|
line = 0;
|
|
|
|
col = 0;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void clearScreen(uint bgColor)
|
|
|
|
{
|
|
|
|
volatile short *vga = (short *)VGA_ADDR;
|
|
|
|
long int colorAttr = bgColor << 12;
|
|
|
|
for (int i = 0; i < VGA_WIDTH * VGA_HEIGHT; i++) {
|
|
|
|
vga[i] = colorAttr;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-11-16 19:56:38 +01:00
|
|
|
void clearScreenLine(uint bgColor, uint line)
|
|
|
|
{
|
|
|
|
volatile short *vga = (short *)VGA_ADDR;
|
|
|
|
long int colorAttr = bgColor << 12;
|
|
|
|
for (uint i = VGA_WIDTH * line; i < VGA_WIDTH * (line + 1); i++) {
|
|
|
|
vga[i] = colorAttr;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-07-20 15:41:58 +02:00
|
|
|
void printInt(int integer)
|
|
|
|
{
|
|
|
|
char num[sizeof(int) *
|
|
|
|
3]; // int max is 2^(sizeof(int)*8) which is (2^3)^(sizeof(int)*8/3) =
|
|
|
|
// 8^(sizeof(int)*8/3) ~ 10^(sizeof(int)*8/3)
|
|
|
|
int i = 0, k = 0;
|
|
|
|
if (integer < 0) {
|
|
|
|
printChar('-');
|
|
|
|
}
|
2018-11-14 18:03:11 +01:00
|
|
|
if (integer == 0) {
|
2018-11-13 14:31:39 +01:00
|
|
|
num[i++] = 0;
|
|
|
|
}
|
2018-07-20 15:41:58 +02:00
|
|
|
while (integer != 0) {
|
|
|
|
int digit = integer % 10;
|
|
|
|
num[i++] = (digit > 0) ? digit : -digit;
|
|
|
|
integer = integer / 10;
|
|
|
|
}
|
|
|
|
for (k = i - 1; k >= 0; k--) {
|
|
|
|
printChar(num[k] + '0');
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void printIntDetails(int integer, uint color, uint bgColor, int startX, int startY)
|
|
|
|
{
|
|
|
|
char num[sizeof(int) *
|
|
|
|
3]; // int max is 2^(sizeof(int)*8) which is (2^3)^(sizeof(int)*8/3) =
|
|
|
|
// 8^(sizeof(int)*8/3) ~ 10^(sizeof(int)*8/3)
|
|
|
|
int x = startX;
|
|
|
|
int i = 0, k = 0;
|
|
|
|
if (integer < 0) {
|
|
|
|
printCharDetails('-', color, bgColor, x++, startY);
|
|
|
|
}
|
2018-11-14 18:03:11 +01:00
|
|
|
if (integer == 0) {
|
2018-11-14 15:45:34 +01:00
|
|
|
num[i++] = 0;
|
|
|
|
}
|
2018-07-20 15:41:58 +02:00
|
|
|
while (integer != 0) {
|
|
|
|
int digit = integer % 10;
|
|
|
|
num[i++] = (digit > 0) ? digit : -digit;
|
|
|
|
integer = integer / 10;
|
|
|
|
}
|
|
|
|
for (k = i - 1; k >= 0; k--) {
|
|
|
|
printCharDetails(num[k] + '0', color, bgColor, x++, startY);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void printCharDetails(const char str, uint color, uint bgColor, int startX, int startY)
|
|
|
|
{
|
|
|
|
volatile short *vga = (short *)VGA_ADDR;
|
|
|
|
long int colorAttr = (bgColor << 4 | (color & 0x0f)) << 8;
|
|
|
|
vga[VGA_WIDTH * startY + startX] = colorAttr | str;
|
|
|
|
}
|
|
|
|
|
|
|
|
void vgaScrollUp(void)
|
|
|
|
{
|
|
|
|
long int colorAttr = vgaBgColor << 12;
|
|
|
|
volatile short *vga = (short *)VGA_ADDR;
|
2018-11-07 17:38:28 +01:00
|
|
|
for (int i = 1; i < VGA_HEIGHT - 1;
|
2018-07-20 15:41:58 +02:00
|
|
|
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 - 2) * VGA_WIDTH + i] = colorAttr;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-08-06 22:28:45 +02:00
|
|
|
void vprintf(const char *format, va_list ap)
|
|
|
|
{
|
|
|
|
int i = 0;
|
|
|
|
while (format[i] != '\0') {
|
|
|
|
switch (format[i]) {
|
|
|
|
case '%':
|
|
|
|
switch (format[i + 1]) {
|
|
|
|
case 'i':
|
|
|
|
case 'd': {
|
|
|
|
int d = va_arg(ap, int);
|
|
|
|
printInt(d);
|
|
|
|
break;
|
|
|
|
}
|
2018-11-16 10:34:03 +01:00
|
|
|
case 'x': {
|
|
|
|
char val[sizeof(int) * 2];
|
|
|
|
int d = va_arg(ap, int);
|
|
|
|
itoa(d, val, 16);
|
|
|
|
printString(val);
|
|
|
|
break;
|
|
|
|
}
|
2018-08-06 22:28:45 +02:00
|
|
|
case 'c': {
|
|
|
|
int c = va_arg(ap, int);
|
|
|
|
printChar((char)c);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case 's': {
|
|
|
|
char *str = va_arg(ap, char *);
|
2018-11-14 18:03:11 +01:00
|
|
|
if (!str)
|
2018-08-06 22:28:45 +02:00
|
|
|
str = "[NULL STR]";
|
|
|
|
printString(str);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case '%':
|
|
|
|
printChar('%');
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
i++;
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
printChar(format[i]);
|
|
|
|
}
|
|
|
|
i++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-11-14 18:03:11 +01:00
|
|
|
void printf(const char *format, ...)
|
|
|
|
{
|
2018-08-06 22:28:45 +02:00
|
|
|
va_list ap;
|
|
|
|
va_start(ap, format);
|
|
|
|
vprintf(format, ap);
|
|
|
|
va_end(ap);
|
|
|
|
}
|
|
|
|
|
2018-07-20 15:41:58 +02:00
|
|
|
void printString(const char *str)
|
|
|
|
{
|
|
|
|
while (*str) {
|
|
|
|
printChar(*(str++));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void printChar(const char str)
|
|
|
|
{
|
|
|
|
if (str == '\n') {
|
|
|
|
line++;
|
|
|
|
col = 0;
|
|
|
|
if (line >= VGA_HEIGHT - 1) {
|
|
|
|
vgaScrollUp();
|
|
|
|
line--;
|
|
|
|
}
|
2018-11-14 18:03:11 +01:00
|
|
|
} else if (str == '\r') {
|
2018-07-20 15:41:58 +02:00
|
|
|
col = 0;
|
2018-11-14 18:03:11 +01:00
|
|
|
} else if (str == '\b') {
|
2018-07-20 15:41:58 +02:00
|
|
|
col--;
|
|
|
|
if (col < 0) {
|
|
|
|
col = VGA_WIDTH - 1;
|
|
|
|
line--;
|
|
|
|
}
|
|
|
|
printCharDetails(' ', vgaColor, vgaBgColor, col, line);
|
2018-11-14 18:03:11 +01:00
|
|
|
} else {
|
2018-07-20 15:41:58 +02:00
|
|
|
printCharDetails(str, vgaColor, vgaBgColor, col++, line);
|
|
|
|
if (col == VGA_WIDTH) {
|
|
|
|
col = 0;
|
|
|
|
line++;
|
|
|
|
}
|
|
|
|
if (line >= VGA_HEIGHT - 1) {
|
|
|
|
vgaScrollUp();
|
|
|
|
line--;
|
|
|
|
}
|
|
|
|
}
|
2018-11-15 13:29:05 +01:00
|
|
|
cursorMove(col, line);
|
2018-07-20 15:41:58 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void printStringDetails(const char *str, uint color, uint bgColor, int startX, int startY)
|
|
|
|
{
|
|
|
|
volatile short *vga = (short *)VGA_ADDR;
|
|
|
|
int i = 0;
|
|
|
|
long int colorAttr = (bgColor << 4 | (color & 0x0f)) << 8;
|
|
|
|
while (*str) {
|
|
|
|
vga[VGA_WIDTH * startY + startX + i] = colorAttr | *str;
|
|
|
|
str++;
|
|
|
|
i++;
|
|
|
|
}
|
|
|
|
}
|
2018-11-14 18:03:11 +01:00
|
|
|
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
|
|
|
void cursorMove(int x, int y)
|
|
|
|
{
|
2018-11-15 13:29:05 +01:00
|
|
|
volatile short *vga = (short *)VGA_ADDR;
|
|
|
|
long int colorAttr = (vgaBgColor << 4 | (vgaColor & 0x0f)) << 8;
|
2018-11-14 18:03:11 +01:00
|
|
|
uint16_t pos = y * VGA_WIDTH + x;
|
2018-11-15 13:29:05 +01:00
|
|
|
vga[pos] = colorAttr;
|
2018-11-14 18:03:11 +01:00
|
|
|
|
|
|
|
outb(0x3D4, 0x0F);
|
|
|
|
outb(0x3D5, (uint8_t)(pos & 0xFF));
|
|
|
|
outb(0x3D4, 0x0E);
|
|
|
|
outb(0x3D5, (uint8_t)((pos >> 8) & 0xFF));
|
|
|
|
}
|