scroll kinda works but keyboard is random
This commit is contained in:
@@ -26,68 +26,20 @@ uint8_t* glyphs = _binary_zap_light16_psf_start + sizeof(PSF1_Header);
|
||||
// Character cursor
|
||||
typedef struct
|
||||
{
|
||||
unsigned int x;
|
||||
unsigned int y;
|
||||
size_t x;
|
||||
size_t y;
|
||||
} Cursor;
|
||||
|
||||
Cursor cursor = {0};
|
||||
static Cursor cursor = {0, 0};
|
||||
|
||||
unsigned char* fb;
|
||||
|
||||
struct limine_framebuffer* framebuffer;
|
||||
static uint8_t* fb;
|
||||
static struct limine_framebuffer* framebuffer;
|
||||
|
||||
uint8_t lines_length[MAX_LINES];
|
||||
|
||||
int term_init()
|
||||
static inline size_t term_max_cols(void)
|
||||
{
|
||||
// Get framebuffer address from Limine struct
|
||||
|
||||
if (boot_ctx.fb)
|
||||
{
|
||||
fb = boot_ctx.fb->address;
|
||||
framebuffer = boot_ctx.fb;
|
||||
DEBUG("terminal initialized, fb=0x%p (width=%u height=%u pitch=%u bpp=%u)", fb, framebuffer->width, framebuffer->height, framebuffer->pitch, framebuffer->bpp);
|
||||
return 0;
|
||||
}
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
// These are marked "static" because we don't wanna expose them all around
|
||||
// AKA they should just be seen here (kind of like private functions in cpp)
|
||||
static void putpixel(int x, int y, int color)
|
||||
{
|
||||
// Depth isn't part of limine_framebuffer attributes so it will be 4
|
||||
unsigned pos = x*4 + y*framebuffer->pitch;
|
||||
fb[pos] = color & 255; // blue channel
|
||||
fb[pos+1] = (color >> 8) & 255; // green
|
||||
fb[pos+2] = (color >> 16) & 255; // blue
|
||||
}
|
||||
|
||||
static void draw_char(char c, int px, int py, int fg, int bg)
|
||||
{
|
||||
uint8_t* glyph = glyphs + ((unsigned char)c * FONT_HEIGHT);
|
||||
|
||||
for (size_t y=0; y<FONT_HEIGHT; y++)
|
||||
{
|
||||
uint8_t row = glyph[y];
|
||||
for (size_t x=0; x<8; x++)
|
||||
{
|
||||
int color = (row & (0x80 >> x)) ? fg : bg;
|
||||
putpixel(px+x, py+y, color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void erase_char(int px, int py)
|
||||
{
|
||||
for (size_t y=0; y<FONT_HEIGHT; y++)
|
||||
{
|
||||
for (size_t x=0; x<8; x++)
|
||||
{
|
||||
// Black
|
||||
putpixel(px+x, py+y, 0);
|
||||
}
|
||||
}
|
||||
return framebuffer->width / FONT_WIDTH;
|
||||
}
|
||||
|
||||
static inline size_t term_max_lines(void)
|
||||
@@ -95,6 +47,69 @@ static inline size_t term_max_lines(void)
|
||||
return framebuffer->height / FONT_HEIGHT;
|
||||
}
|
||||
|
||||
int term_init()
|
||||
{
|
||||
// Get framebuffer address from Limine struct
|
||||
|
||||
if (!boot_ctx.fb)
|
||||
{
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
framebuffer = boot_ctx.fb;
|
||||
fb = (uint8_t*)framebuffer->address;
|
||||
|
||||
memset(lines_length, 0, sizeof(lines_length));
|
||||
|
||||
DEBUG("terminal initialized, fb=0x%p (width=%u height=%u pitch=%u bpp=%u)", fb, framebuffer->width, framebuffer->height, framebuffer->pitch, framebuffer->bpp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// These are marked "static" because we don't wanna expose them all around
|
||||
// AKA they should just be seen here (kind of like private functions in cpp)
|
||||
static inline void putpixel(size_t x, size_t y, uint32_t color)
|
||||
{
|
||||
// Guard so we don't write past fb boundaries
|
||||
if (x >= framebuffer->width || y >= framebuffer->height) return;
|
||||
// Depth isn't part of limine_framebuffer attributes so it will be 4
|
||||
size_t pos = x*4 + y*framebuffer->pitch;
|
||||
fb[pos] = color & 255; // blue channel
|
||||
fb[pos+1] = (color >> 8) & 255; // green
|
||||
fb[pos+2] = (color >> 16) & 255; // blue
|
||||
}
|
||||
|
||||
static void draw_char(char c, size_t px, size_t py, uint32_t fg, uint32_t bg)
|
||||
{
|
||||
// So we cannot write past fb
|
||||
if (px+FONT_WIDTH > framebuffer->width || py+FONT_HEIGHT > framebuffer->height) return;
|
||||
|
||||
uint8_t* glyph = glyphs + ((unsigned char)c * FONT_HEIGHT);
|
||||
|
||||
for (size_t y=0; y<FONT_HEIGHT; y++)
|
||||
{
|
||||
uint8_t row = glyph[y];
|
||||
for (size_t x=0; x<FONT_WIDTH; x++)
|
||||
{
|
||||
uint32_t color = (row & (0x80 >> x)) ? fg : bg;
|
||||
putpixel(px+x, py+y, color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void erase_char(size_t px, size_t py)
|
||||
{
|
||||
if (px+FONT_WIDTH > framebuffer->width || py+FONT_HEIGHT > framebuffer->height) return;
|
||||
|
||||
for (size_t y=0; y<FONT_HEIGHT; y++)
|
||||
{
|
||||
for (size_t x=0; x<FONT_HEIGHT; x++)
|
||||
{
|
||||
// Black
|
||||
putpixel(px+x, py+y, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void term_scroll()
|
||||
{
|
||||
const size_t row_height = FONT_HEIGHT;
|
||||
@@ -121,71 +136,63 @@ void term_scroll()
|
||||
}
|
||||
|
||||
lines_length[max_lines - 1] = 0;
|
||||
|
||||
if (cursor.y > 0)
|
||||
{
|
||||
cursor.y--;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void putchar(char c)
|
||||
{
|
||||
if ((c == '\n') && ((cursor.y+1)*FONT_HEIGHT >= framebuffer->height))
|
||||
{
|
||||
term_scroll();
|
||||
return;
|
||||
}
|
||||
const size_t max_cols = term_max_cols();
|
||||
const size_t max_lines = term_max_lines();
|
||||
|
||||
if (c == '\n')
|
||||
{
|
||||
if (c == '\n') {
|
||||
lines_length[cursor.y] = cursor.x;
|
||||
cursor.x = 0;
|
||||
cursor.y++;
|
||||
|
||||
if (cursor.y + 1 >= max_lines)
|
||||
{
|
||||
term_scroll();
|
||||
}
|
||||
else
|
||||
{
|
||||
cursor.y++;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: Improperly handled.
|
||||
// When we're on an empty line it should get to the upper line's last character
|
||||
// NOT just the last position possible; we would need to track the last line's character amount for that
|
||||
if (c == '\b')
|
||||
if (c == '\b')
|
||||
{
|
||||
if (cursor.x == 0 && cursor.y == 0)
|
||||
if (cursor.x > 0)
|
||||
{
|
||||
cursor.x--;
|
||||
}
|
||||
else if (cursor.y > 0)
|
||||
{
|
||||
cursor.y--;
|
||||
cursor.x = lines_length[cursor.y];
|
||||
}
|
||||
else
|
||||
{
|
||||
// Top-left corner
|
||||
return;
|
||||
}
|
||||
|
||||
if (cursor.x == 0)
|
||||
{
|
||||
cursor.y--;
|
||||
// cursor.x = (framebuffer->width / FONT_WIDTH) -1; // here
|
||||
cursor.x = lines_length[cursor.y];
|
||||
}
|
||||
else {
|
||||
cursor.x--;
|
||||
}
|
||||
|
||||
int px = cursor.x * FONT_WIDTH;
|
||||
int py = cursor.y * FONT_HEIGHT;
|
||||
erase_char(px, py);
|
||||
erase_char(cursor.x * FONT_WIDTH, cursor.y * FONT_HEIGHT);
|
||||
return;
|
||||
}
|
||||
|
||||
if ((cursor.x+1)*FONT_WIDTH >= framebuffer->width)
|
||||
if (cursor.x >= max_cols)
|
||||
{
|
||||
cursor.x = 0;
|
||||
cursor.y++;
|
||||
if (cursor.y + 1 >= max_lines)
|
||||
{
|
||||
term_scroll();
|
||||
}
|
||||
else
|
||||
{
|
||||
cursor.y++;
|
||||
}
|
||||
}
|
||||
|
||||
if ((cursor.y+1)*FONT_HEIGHT >= framebuffer->height)
|
||||
{
|
||||
term_scroll();
|
||||
}
|
||||
|
||||
int px = cursor.x * FONT_WIDTH;
|
||||
int py = cursor.y * FONT_HEIGHT;
|
||||
draw_char(c, px, py, WHITE, BLACK);
|
||||
draw_char(c, cursor.x * FONT_WIDTH, cursor.y * FONT_HEIGHT, WHITE, BLACK);
|
||||
cursor.x++;
|
||||
}
|
||||
|
||||
@@ -198,7 +205,7 @@ void _putchar(char character)
|
||||
// Debug-printing
|
||||
void kputs(const char* str)
|
||||
{
|
||||
unsigned int i=0;
|
||||
size_t i=0;
|
||||
while (str[i] != 0)
|
||||
{
|
||||
putchar(str[i]);
|
||||
|
||||
Reference in New Issue
Block a user