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