diff options
Diffstat (limited to 'lib/virtterm.c')
| -rw-r--r-- | lib/virtterm.c | 131 |
1 files changed, 131 insertions, 0 deletions
diff --git a/lib/virtterm.c b/lib/virtterm.c new file mode 100644 index 0000000..de43c51 --- /dev/null +++ b/lib/virtterm.c @@ -0,0 +1,131 @@ +#include "virtterm.h" +#include "boot/cmdline.h" +#include "boot/initrd.h" +#include "hal/obj.h" +#include "init.h" +#include "jove.h" +#include "hal/framebuffer.h" +#include "lib/printf.h" +#include "lib/psf.h" +#include "lib/string.h" + +struct psf1_header *s_font = NULL; + +struct virtterm s_init_vtty = { 0 }; + +static void +vt_blit(struct virtterm *vtty, jove_owned_obj_t *fb, const uint8_t *glyph) +{ + uint32_t buffer[s_font->char_height << 3]; + size_t cursor_x = vtty->cursor_col * 9; + size_t cursor_y = vtty->cursor_row * s_font->char_height; + + for(size_t y = 0; y < s_font->char_height; y++) { + uint8_t mask = 1 << 7; + for(size_t x = 0; x < 8; x++) { + buffer[x + (y << 3)] = glyph[y] & mask ? vtty->cursor_fg : vtty->cursor_bg; + mask >>=1; + } + } + fb_blit(fb, buffer, cursor_x, cursor_y, 8, s_font->char_height); + vtty->cursor_col++; +} + +static void +vt_putc(struct virtterm *vtty, jove_owned_obj_t *fb, char c) +{ + const uint8_t *glyph = &s_font->bitmap[(size_t)c * s_font->char_height]; + + switch(c) { + case '\n': + vtty->cursor_col = 0; + vtty->cursor_row++; + break; + default: + vt_blit(vtty, fb, glyph); + break; + } + + if(vtty->cursor_col >= vtty->width) { + vtty->cursor_col = 0; + vtty->cursor_row++; + } + if(vtty->cursor_row >= vtty->height) { + vtty->cursor_row = 0; + } +} + +int +vt_write(jove_owned_obj_t *obj, const char *s, size_t n) +{ + if(obj_gettype(obj) != JOVE_OBJ_VIRTTERM) { + reterr(EBADOBJ); + } + + struct virtterm *vtty = obj_deref(obj); + jove_owned_obj_t *fb_obj = obj_take(objdir_getlocal(_rootdir_obj, vtty->fb_obj)); + if(obj_gettype(fb_obj) != JOVE_OBJ_FRAMEBUFFER) { + obj_release(fb_obj); + reterr(EBADOBJ); + } + + for(size_t i = 0; i < n; i++) { + vt_putc(vtty, fb_obj, s[i]); + } + + obj_release(fb_obj); + return 0; +} + +void +vt_init() +{ + const char *font_path = cmdline_getarg("font"); + if(font_path == NULL) { + kprintf("Kernel commandline is missing 'font' argument. VTT is disabled."); + return; + } + + jove_owned_obj_t *initrd_obj = obj_take(objdir_getlocal(_rootdir_obj, ROOTDIR_INITRD_I)); + if(obj_gettype(initrd_obj) != JOVE_OBJ_OBJDIR) { + kprintf("Initrd is not present. VTT is disabled.\n"); + obj_release(initrd_obj); + return; + } + + jove_owned_obj_t *file_obj; + size_t file_i = 0; + while((file_obj = obj_take(objdir_getlocal(initrd_obj, file_i++)))) { + const char *filename = NULL; + if(initrd_file_name(file_obj, &filename) != 0) { + break; + } + if(strncmp(font_path, filename, strlen(font_path)) == 0) { + initrd_file_data(file_obj, (uintptr_t*)&s_font); + break; + } + obj_release(file_obj); + } + obj_release(file_obj); + obj_release(initrd_obj); + + if(s_font == NULL) { + kprintf("Could not find file %s in initrd. VTT is disabled.\n", font_path); + return; + } + s_init_vtty.fb_obj = ROOTDIR_FRAMEBUFFER_I; + s_init_vtty.cursor_fg = 0x00FFFFFF; + + + { + jove_owned_obj_t *fb_obj = obj_take(objdir_getlocal(_rootdir_obj, ROOTDIR_FRAMEBUFFER_I)); + s_init_vtty.width = fb_width(fb_obj) / 9; + s_init_vtty.height = fb_height(fb_obj) / s_font->char_height; + obj_release(fb_obj); + + jove_owned_obj_t *vt_obj = obj_take(objdir_getlocal(_rootdir_obj, ROOTDIR_VIRTTERM_I)); + obj_settype(vt_obj, JOVE_OBJ_VIRTTERM); + obj_setvalue(vt_obj, (uintmax_t)&s_init_vtty); + obj_release(vt_obj); + } +} |
