From f3e6838b44a5b37ce7664db5b8662e3d02e5f539 Mon Sep 17 00:00:00 2001 From: Freya Murphy Date: Thu, 17 Apr 2025 00:51:46 -0400 Subject: font rending in framebuffer yay!! --- kernel/term.c | 169 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 169 insertions(+) create mode 100644 kernel/term.c (limited to 'kernel/term.c') diff --git a/kernel/term.c b/kernel/term.c new file mode 100644 index 0000000..e40e0fe --- /dev/null +++ b/kernel/term.c @@ -0,0 +1,169 @@ +#include "lib/kio.h" +#include +#include +#include +#include +#include +#include +#include + +// draw function +static void (*draw_char)(char c, uint16_t x, uint16_t y) = vga_draw_char; + +// terminal data +static char buffer[TERM_MAX_WIDTH * TERM_MAX_HEIGHT]; +static uint16_t buffer_line = UINT16_MAX; +static uint16_t width = VGA_WIDTH; +static uint16_t height = VGA_HEIGHT; +static uint16_t x = 0; +static uint16_t y = 0; + +#define BUFY(y) ((buffer_line + (y)) % TERM_MAX_HEIGHT) +#define BUFIDX(x,y) ((x) + (BUFY(y) * TERM_MAX_WIDTH)) + +static void buffer_check(void) +{ + if (buffer_line == UINT16_MAX) { + buffer_line = 0; + memset(buffer, 0, sizeof(buffer)); + } +} + +static inline bool printable(char c) +{ + switch (c) { + case '\0': + case '\n': + case '\t': + case '\v': + case '\f': + case '\r': + return false; + default: + return true; + } +} + +static inline void term_move_cur(char c) +{ + if (c == '\0') + return; + + switch (c) { + case '\n': + x = 0; + y++; + break; + case '\t': + x += 4; + break; + case '\v': + case '\f': + y++; + break; + case '\r': + x = 0; + break; + default: + x++; + } + + if (x >= width) { + x = 0; + y++; + } + if (y >= height) { + term_scroll(y - (height - 1)); + y = height - 1; + } +} + +uint16_t term_width(void) +{ + return width; +} + +uint16_t term_height(void) +{ + return height; +} + +void term_out(char c) +{ + term_out_at(c, x, y); + term_move_cur(c); +} + +void term_out_at(char c, uint16_t x, uint16_t y) +{ + buffer_check(); + + if (!printable(c)) + return; + + buffer[BUFIDX(x, y)] = c; + draw_char(c, x, y); +} + +void term_out_str(const char *str) +{ + char c; + while (c = *(str++), c) { + term_out_at(c, x, y); + term_move_cur(c); + } +} + +void term_out_str_at(const char *str, uint16_t x, uint16_t y) +{ + char c; + while (c = *(str++), c) + term_out_at(c, x, y); +} + +void term_clear(void) +{ + for (uint16_t y = 0; y < height; y++) + term_clear_line(y); +} + +void term_clear_line(uint16_t line) +{ + buffer_check(); + + if (line > height) + return; + + for (uint16_t x = 0; x < width; x++) { + buffer[BUFIDX(x, line)] = 0; + draw_char(0, x, line); + } +} + +void term_redraw(void) +{ + buffer_check(); + + for (uint16_t j = 0; j < height; j++) { + for (uint16_t i = 0; i < width; i++) { + char c = buffer[BUFIDX(i, j)]; + draw_char(c, i, j); + } + } +} + +void term_scroll(uint16_t lines) +{ + if (!lines) + return; + buffer_line += lines; + term_redraw(); +} + +void term_switch_handler(uint16_t w, uint16_t h, void (*fn)(char c, uint16_t x, uint16_t y)) +{ + draw_char = fn; + width = w % TERM_MAX_WIDTH; + height = h % TERM_MAX_HEIGHT; + term_redraw(); +} -- cgit v1.2.3-freya