feat(drivers): add VGA text-mode driver with scrolling and cursor
This commit is contained in:
1 parent
39f8c5fc48
commit
7b52e9d3f9
2 files changed
+124
No files matched your search
@@ -0,0 +1,31 @@
|
||||
#ifndef FROSTBYTE_VGA_H
|
||||
#define FROSTBYTE_VGA_H
|
||||
|
||||
#include "types.h"
|
||||
|
||||
typedef enum {
|
||||
vgaBlack = 0,
|
||||
vgaBlue = 1,
|
||||
vgaGreen = 2,
|
||||
vgaCyan = 3,
|
||||
vgaRed = 4,
|
||||
vgaMagenta = 5,
|
||||
vgaBrown = 6,
|
||||
vgaLightGrey = 7,
|
||||
vgaDarkGrey = 8,
|
||||
vgaLightBlue = 9,
|
||||
vgaLightGreen = 10,
|
||||
vgaLightCyan = 11,
|
||||
vgaLightRed = 12,
|
||||
vgaPink = 13,
|
||||
vgaYellow = 14,
|
||||
vgaWhite = 15
|
||||
} VgaColor;
|
||||
|
||||
void vgaInit(void);
|
||||
void vgaClear(void);
|
||||
void vgaPutChar(char c);
|
||||
void vgaWriteString(const char* str);
|
||||
void vgaSetColor(VgaColor foreground, VgaColor background);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,93 @@
|
||||
#include "vga.h"
|
||||
#include "ports.h"
|
||||
|
||||
#define vgaWidth 80
|
||||
#define vgaHeight 25
|
||||
#define vgaBuffer 0xB8000
|
||||
|
||||
static volatile uint16* const screen = (volatile uint16*)vgaBuffer;
|
||||
static uint32 cursorRow;
|
||||
static uint32 cursorColumn;
|
||||
static uint8 currentColor;
|
||||
|
||||
static uint16 makeCell(char c, uint8 color)
|
||||
{
|
||||
return (uint16)c | ((uint16)color << 8);
|
||||
}
|
||||
|
||||
static void updateHardwareCursor(void)
|
||||
{
|
||||
uint16 position = (uint16)(cursorRow * vgaWidth + cursorColumn);
|
||||
outb(0x3D4, 0x0F);
|
||||
outb(0x3D5, (uint8)(position & 0xFF));
|
||||
outb(0x3D4, 0x0E);
|
||||
outb(0x3D5, (uint8)((position >> 8) & 0xFF));
|
||||
}
|
||||
|
||||
void vgaSetColor(VgaColor foreground, VgaColor background)
|
||||
{
|
||||
currentColor = (uint8)foreground | (uint8)(background << 4);
|
||||
}
|
||||
|
||||
void vgaClear(void)
|
||||
{
|
||||
for (uint32 y = 0; y < vgaHeight; y++) {
|
||||
for (uint32 x = 0; x < vgaWidth; x++)
|
||||
screen[y * vgaWidth + x] = makeCell(' ', currentColor);
|
||||
}
|
||||
cursorRow = 0;
|
||||
cursorColumn = 0;
|
||||
updateHardwareCursor();
|
||||
}
|
||||
|
||||
void vgaInit(void)
|
||||
{
|
||||
currentColor = (uint8)vgaLightGrey | (uint8)(vgaBlack << 4);
|
||||
vgaClear();
|
||||
}
|
||||
|
||||
static void scroll(void)
|
||||
{
|
||||
for (uint32 y = 1; y < vgaHeight; y++) {
|
||||
for (uint32 x = 0; x < vgaWidth; x++)
|
||||
screen[(y - 1) * vgaWidth + x] = screen[y * vgaWidth + x];
|
||||
}
|
||||
for (uint32 x = 0; x < vgaWidth; x++)
|
||||
screen[(vgaHeight - 1) * vgaWidth + x] = makeCell(' ', currentColor);
|
||||
cursorRow = vgaHeight - 1;
|
||||
}
|
||||
|
||||
void vgaPutChar(char c)
|
||||
{
|
||||
if (c == '\n') {
|
||||
cursorColumn = 0;
|
||||
cursorRow++;
|
||||
} else if (c == '\r') {
|
||||
cursorColumn = 0;
|
||||
} else if (c == '\b') {
|
||||
if (cursorColumn > 0) {
|
||||
cursorColumn--;
|
||||
screen[cursorRow * vgaWidth + cursorColumn] = makeCell(' ', currentColor);
|
||||
}
|
||||
} else if (c == '\t') {
|
||||
cursorColumn = (cursorColumn + 4) & ~3u;
|
||||
} else {
|
||||
screen[cursorRow * vgaWidth + cursorColumn] = makeCell(c, currentColor);
|
||||
cursorColumn++;
|
||||
}
|
||||
|
||||
if (cursorColumn >= vgaWidth) {
|
||||
cursorColumn = 0;
|
||||
cursorRow++;
|
||||
}
|
||||
if (cursorRow >= vgaHeight)
|
||||
scroll();
|
||||
|
||||
updateHardwareCursor();
|
||||
}
|
||||
|
||||
void vgaWriteString(const char* str)
|
||||
{
|
||||
while (*str)
|
||||
vgaPutChar(*str++);
|
||||
}
|
||||
Reference in new issue
Block a user