Luna/kernel/src/video/TextConsole.cpp

172 lines
3.5 KiB
C++
Raw Normal View History

2022-11-20 16:55:22 +00:00
#include "video/TextConsole.h"
#include "boot/bootboot.h"
#include "video/Framebuffer.h"
#include <Format.h>
#include <String.h>
extern BOOTBOOT bootboot;
#include "video/BuiltinFont.h"
static constexpr u32 BLACK = 0xff000000;
static constexpr u32 WHITE = 0xffffffff;
static u32 g_background_color = BLACK;
static u32 g_foreground_color = WHITE;
static constexpr u32 FONT_HEIGHT = 16;
static constexpr u32 FONT_WIDTH = 8;
static u32 g_x_position = 0;
static u32 g_y_position = 0;
static void putchar_at(char c, u32 x, u32 y)
{
u8* glyph = &font[c * 16];
for (u32 i = 0; i < FONT_HEIGHT; i++)
{
for (u32 j = 0; j < FONT_WIDTH; j++)
{
volatile u8 mask = *glyph;
if (mask & (0b10000000 >> j)) Framebuffer::pixel(x + j, y + i, g_foreground_color);
else
Framebuffer::pixel(x + j, y + i, g_background_color);
}
glyph++;
}
}
static void erase_current_line()
{
Framebuffer::rect(0, g_y_position, Framebuffer::width(), FONT_HEIGHT, BLACK);
}
static void scroll()
{
memcpy(Framebuffer::ptr(), Framebuffer::ptr() + (Framebuffer::scanline() * FONT_HEIGHT),
Framebuffer::size() - (Framebuffer::scanline() * FONT_HEIGHT));
g_y_position -= FONT_HEIGHT;
erase_current_line();
}
static bool should_scroll()
{
return (g_y_position + FONT_HEIGHT) >= Framebuffer::height();
}
static void next_line()
{
g_x_position = 0;
g_y_position += FONT_HEIGHT;
}
static void next_char()
{
g_x_position += FONT_WIDTH;
}
static void prev_char()
{
g_x_position -= FONT_WIDTH;
}
static void erase_current_char()
{
Framebuffer::rect(g_x_position, g_y_position, FONT_WIDTH, FONT_HEIGHT, BLACK);
}
static bool at_end_of_screen()
{
return (g_x_position + FONT_WIDTH) > Framebuffer::width();
}
namespace TextConsole
{
void putchar(char c)
{
switch (c)
{
case '\n': {
next_line();
if (should_scroll()) scroll();
break;
}
case '\r': g_x_position = 0; break;
case '\b':
if (g_x_position != 0)
{
prev_char();
erase_current_char();
}
break;
default: {
putchar_at(c, g_x_position, g_y_position);
next_char();
if (at_end_of_screen())
{
next_line();
if (should_scroll()) scroll();
}
break;
}
}
}
void set_foreground(u32 color)
{
g_foreground_color = color;
}
void set_background(u32 color)
{
g_background_color = color;
}
2022-11-30 12:29:28 +00:00
u32 foreground()
{
return g_foreground_color;
}
u32 background()
{
return g_background_color;
}
2022-11-20 16:55:22 +00:00
void move_to(u32 x, u32 y)
{
g_x_position = x;
g_y_position = y;
}
void clear()
{
move_to(0, 0);
Framebuffer::rect(0, 0, Framebuffer::width(), Framebuffer::height(), BLACK);
}
void print(const char* str)
{
while (*str) putchar(*str++);
}
void println(const char* str)
{
print(str);
putchar('\n');
}
Result<usize> printf(const char* format, ...)
{
va_list ap;
va_start(ap, format);
auto rc = cstyle_format(
format,
[](char c, void*) -> Result<void> {
putchar(c);
return {};
},
nullptr, ap);
va_end(ap);
return rc;
}
}