From 31b0a15671977a0157a57b7efffd9b1f1acafa3b Mon Sep 17 00:00:00 2001 From: dzwdz Date: Tue, 2 Aug 2022 14:07:21 +0200 Subject: user: separate ansiterm/vterm out into its own binary --- src/user/app/init/driver/ansiterm.c | 170 ------------------------------------ src/user/app/init/driver/driver.h | 1 - src/user/app/init/init.c | 5 +- src/user/app/vterm/vterm.c | 169 +++++++++++++++++++++++++++++++++++ 4 files changed, 173 insertions(+), 172 deletions(-) delete mode 100644 src/user/app/init/driver/ansiterm.c create mode 100644 src/user/app/vterm/vterm.c (limited to 'src/user') diff --git a/src/user/app/init/driver/ansiterm.c b/src/user/app/init/driver/ansiterm.c deleted file mode 100644 index b59d0b8..0000000 --- a/src/user/app/init/driver/ansiterm.c +++ /dev/null @@ -1,170 +0,0 @@ -#include "driver.h" -#include -#include -#include -#include -#include -#include - -#define eprintf(fmt, ...) fprintf(stderr, "ansiterm: "fmt"\n" __VA_OPT__(,) __VA_ARGS__) - -struct psf { - uint32_t magic; - uint32_t version; - uint32_t glyph_offset; - uint32_t flags; - uint32_t glyph_amt; - uint32_t glyph_size; - uint32_t h; - uint32_t w; -} __attribute__((packed)); - -static handle_t fb_fd; - -static struct {int x, y;} cursor = {0}; - -static size_t dirty_low = ~0, dirty_high = 0; - -// TODO don't hardcode size -static const size_t fb_len = 640 * 480 * 4; -static const size_t fb_width = 640; -static const size_t fb_height = 480; -static const size_t fb_pitch = 640 * 4; -static char *fb; - -static struct psf font; -static void *font_data; - - -static void flush(void) { - if (dirty_high == 0) return; - - if (dirty_high > fb_len) // shouldn't happen - dirty_high = fb_len; - - // still not optimal, copies 80 characters instead of 1 - while (dirty_low < dirty_high) - dirty_low += _syscall_write(fb_fd, fb + dirty_low, dirty_high - dirty_low, dirty_low, 0); - - dirty_low = ~0; - dirty_high = 0; -} - -static void scroll(void) { - // TODO memmove. this is UD - size_t row_len = fb_pitch * font.h; - memcpy(fb, fb + row_len, fb_len - row_len); - memset(fb + fb_len - row_len, 0, row_len); - cursor.y--; - dirty_low = 0; dirty_high = ~0; -} - -static void font_blit(size_t glyph, int x, int y) { - if (glyph >= font.glyph_amt) glyph = 0; - - size_t low = fb_pitch * ( y * font.h) + 4 * ( x * font.w); - size_t high = fb_pitch * ((y+1) * font.h) + 4 * ((x+1) * font.w) + 3; - if (dirty_low > low) - dirty_low = low; - if (dirty_high < high) - dirty_high = high; - - char *bitmap = font_data + font.glyph_size * glyph; - for (size_t i = 0; i < font.w; i++) { - for (size_t j = 0; j < font.h; j++) { - size_t idx = j * font.w + i; - char byte = bitmap[idx / 8]; - byte >>= (7-(idx&7)); - byte &= 1; - *((uint32_t*)&fb[fb_pitch * (y * font.h + j) + 4 * (x * font.w + i)]) = byte * 0xB0B0B0; - } - } -} - -static void in_char(char c) { - switch (c) { - case '\n': - cursor.x = 0; - cursor.y++; - break; - case '\b': - if (--cursor.x < 0) cursor.x = 0; - break; - default: - font_blit(c, cursor.x, cursor.y); - cursor.x++; - } - - if (cursor.x * font.w >= fb_width) { - cursor.x = 0; - cursor.y++; - } - while (cursor.y * font.h >= fb_height) scroll(); -} - -static void font_load(void) { - FILE *f = fopen("/init/font.psf", "r"); - if (!f) { - eprintf("couldn't open font file"); - exit(1); - } - - const size_t cap = 8 * 1024; // TODO get file size - void *buf = malloc(cap); - if (!buf) { - eprintf("out of memory"); - exit(1); - } - fread(buf, 1, cap, f); - if (ferror(f)) { - eprintf("error reading file"); - exit(1); - } - fclose(f); - - if (memcmp(buf, "\x72\xb5\x4a\x86", 4)) { - eprintf("invalid psf header"); - exit(1); - } - memcpy(&font, buf, sizeof font); - font_data = buf + font.glyph_offset; -} - -void ansiterm_drv(void) { - fb = malloc(fb_len); - fb_fd = _syscall_open("/kdev/video/b", 13, 0); - - font_load(); - - cursor.x = 0; - cursor.y = 0; - flush(); - - static char buf[512]; - struct fs_wait_response res; - while (!_syscall_fs_wait(buf, sizeof buf, &res)) { - switch (res.op) { - case VFSOP_OPEN: - // TODO check path - _syscall_fs_respond(NULL, 0, 0); - break; - - case VFSOP_WRITE: - if (res.flags) { - _syscall_fs_respond(NULL, -1, 0); - } else { - for (size_t i = 0; i < res.len; i++) - in_char(buf[i]); - flush(); - _syscall_fs_respond(NULL, res.len, 0); - } - break; - - default: - _syscall_fs_respond(NULL, -1, 0); - break; - } - } - - exit(1); -} diff --git a/src/user/app/init/driver/driver.h b/src/user/app/init/driver/driver.h index d6e7343..c99955a 100644 --- a/src/user/app/init/driver/driver.h +++ b/src/user/app/init/driver/driver.h @@ -1,6 +1,5 @@ #pragma once -void ansiterm_drv(void); void ps2_drv(void); void tmpfs_drv(void); diff --git a/src/user/app/init/init.c b/src/user/app/init/init.c index 4e2a668..9e7ab7b 100644 --- a/src/user/app/init/init.c +++ b/src/user/app/init/init.c @@ -31,8 +31,11 @@ int main(void) { MOUNT_AT("/tmp/") { tmpfs_drv(); } MOUNT_AT("/keyboard") { ps2_drv(); } - MOUNT_AT("/vtty") { ansiterm_drv(); } MOUNT_AT("/bin/") { fs_passthru("/init/bin"); } + MOUNT_AT("/vtty") { + const char *argv[] = {"/bin/vterm", NULL}; + execv(argv[0], (void*)argv); + } if (fork()) { /* used to trigger a kernel bug diff --git a/src/user/app/vterm/vterm.c b/src/user/app/vterm/vterm.c new file mode 100644 index 0000000..4309900 --- /dev/null +++ b/src/user/app/vterm/vterm.c @@ -0,0 +1,169 @@ +#include +#include +#include +#include +#include +#include + +#define eprintf(fmt, ...) fprintf(stderr, "vterm: "fmt"\n" __VA_OPT__(,) __VA_ARGS__) + +struct psf { + uint32_t magic; + uint32_t version; + uint32_t glyph_offset; + uint32_t flags; + uint32_t glyph_amt; + uint32_t glyph_size; + uint32_t h; + uint32_t w; +} __attribute__((packed)); + +static handle_t fb_fd; + +static struct {int x, y;} cursor = {0}; + +static size_t dirty_low = ~0, dirty_high = 0; + +// TODO don't hardcode size +static const size_t fb_len = 640 * 480 * 4; +static const size_t fb_width = 640; +static const size_t fb_height = 480; +static const size_t fb_pitch = 640 * 4; +static char *fb; + +static struct psf font; +static void *font_data; + + +static void flush(void) { + if (dirty_high == 0) return; + + if (dirty_high > fb_len) // shouldn't happen + dirty_high = fb_len; + + // still not optimal, copies 80 characters instead of 1 + while (dirty_low < dirty_high) + dirty_low += _syscall_write(fb_fd, fb + dirty_low, dirty_high - dirty_low, dirty_low, 0); + + dirty_low = ~0; + dirty_high = 0; +} + +static void scroll(void) { + // TODO memmove. this is UD + size_t row_len = fb_pitch * font.h; + memcpy(fb, fb + row_len, fb_len - row_len); + memset(fb + fb_len - row_len, 0, row_len); + cursor.y--; + dirty_low = 0; dirty_high = ~0; +} + +static void font_blit(size_t glyph, int x, int y) { + if (glyph >= font.glyph_amt) glyph = 0; + + size_t low = fb_pitch * ( y * font.h) + 4 * ( x * font.w); + size_t high = fb_pitch * ((y+1) * font.h) + 4 * ((x+1) * font.w) + 3; + if (dirty_low > low) + dirty_low = low; + if (dirty_high < high) + dirty_high = high; + + char *bitmap = font_data + font.glyph_size * glyph; + for (size_t i = 0; i < font.w; i++) { + for (size_t j = 0; j < font.h; j++) { + size_t idx = j * font.w + i; + char byte = bitmap[idx / 8]; + byte >>= (7-(idx&7)); + byte &= 1; + *((uint32_t*)&fb[fb_pitch * (y * font.h + j) + 4 * (x * font.w + i)]) = byte * 0xB0B0B0; + } + } +} + +static void in_char(char c) { + switch (c) { + case '\n': + cursor.x = 0; + cursor.y++; + break; + case '\b': + if (--cursor.x < 0) cursor.x = 0; + break; + default: + font_blit(c, cursor.x, cursor.y); + cursor.x++; + } + + if (cursor.x * font.w >= fb_width) { + cursor.x = 0; + cursor.y++; + } + while (cursor.y * font.h >= fb_height) scroll(); +} + +static void font_load(void) { + FILE *f = fopen("/init/font.psf", "r"); + if (!f) { + eprintf("couldn't open font file"); + exit(1); + } + + const size_t cap = 8 * 1024; // TODO get file size + void *buf = malloc(cap); + if (!buf) { + eprintf("out of memory"); + exit(1); + } + fread(buf, 1, cap, f); + if (ferror(f)) { + eprintf("error reading file"); + exit(1); + } + fclose(f); + + if (memcmp(buf, "\x72\xb5\x4a\x86", 4)) { + eprintf("invalid psf header"); + exit(1); + } + memcpy(&font, buf, sizeof font); + font_data = buf + font.glyph_offset; +} + +int main(void) { + fb = malloc(fb_len); + fb_fd = _syscall_open("/kdev/video/b", 13, 0); + + font_load(); + + cursor.x = 0; + cursor.y = 0; + flush(); + + static char buf[512]; + struct fs_wait_response res; + while (!_syscall_fs_wait(buf, sizeof buf, &res)) { + switch (res.op) { + case VFSOP_OPEN: + // TODO check path + _syscall_fs_respond(NULL, 0, 0); + break; + + case VFSOP_WRITE: + if (res.flags) { + _syscall_fs_respond(NULL, -1, 0); + } else { + for (size_t i = 0; i < res.len; i++) + in_char(buf[i]); + flush(); + _syscall_fs_respond(NULL, res.len, 0); + } + break; + + default: + _syscall_fs_respond(NULL, -1, 0); + break; + } + } + + return 1; +} -- cgit v1.2.3