162 lines
3.4 KiB
C++
162 lines
3.4 KiB
C++
|
#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;
|
||
|
}
|
||
|
|
||
|
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;
|
||
|
}
|
||
|
}
|