diff options
author | dzwdz | 2022-08-02 15:20:31 +0200 |
---|---|---|
committer | dzwdz | 2022-08-02 15:20:31 +0200 |
commit | b4447c1c7bc8639774df6bd74428977908bff61e (patch) | |
tree | e2b28678b5d3c4c481432b3ff790e80b63434d34 /src/user/app/vterm | |
parent | 31b0a15671977a0157a57b7efffd9b1f1acafa3b (diff) |
user/vterm: split into separate files
Diffstat (limited to 'src/user/app/vterm')
-rw-r--r-- | src/user/app/vterm/draw.c | 44 | ||||
-rw-r--r-- | src/user/app/vterm/font.c | 52 | ||||
-rw-r--r-- | src/user/app/vterm/vterm.c | 130 | ||||
-rw-r--r-- | src/user/app/vterm/vterm.h | 42 |
4 files changed, 152 insertions, 116 deletions
diff --git a/src/user/app/vterm/draw.c b/src/user/app/vterm/draw.c new file mode 100644 index 0000000..44d3ffe --- /dev/null +++ b/src/user/app/vterm/draw.c @@ -0,0 +1,44 @@ +#include "vterm.h" +#include <camellia/syscalls.h> +#include <string.h> + +struct framebuf fb; +handle_t fb_fd; +struct rect dirty; + + +void dirty_mark(uint32_t x, uint32_t y) { + if (dirty.x1 > x) dirty.x1 = x; + if (dirty.x2 < x) dirty.x2 = x; + if (dirty.y1 > y) dirty.y1 = y; + if (dirty.y2 < y) dirty.y2 = y; +} + +void flush(void) { + size_t low, high; + if (~dirty.x1 == 0) return; + + // still not optimal, copies 80 characters instead of 1 + low = fb.pitch * ( dirty.y1 * font.h) + 4 * ( dirty.x1 * font.w); + high = fb.pitch * ((dirty.y2+1) * font.h) + 4 * ((dirty.x2+1) * font.w) + 3; + + if (~dirty.y2 == 0) high = fb.len; + if (high > fb.len) high = fb.len; + + while (low < high) + low += _syscall_write(fb_fd, fb.b + low, high - low, low, 0); + + dirty.x1 = ~0; dirty.y1 = ~0; + dirty.x2 = 0; dirty.y2 = 0; +} + +void scroll(void) { + // TODO memmove. this is UD + size_t row_len = fb.pitch * font.h; + memcpy(fb.b, fb.b + row_len, fb.len - row_len); + memset(fb.b + fb.len - row_len, 0, row_len); + cursor.y--; + + dirty.x1 = 0; dirty.y1 = 0; + dirty.x2 = ~0; dirty.y2 = ~0; +} diff --git a/src/user/app/vterm/font.c b/src/user/app/vterm/font.c new file mode 100644 index 0000000..d9a4e3c --- /dev/null +++ b/src/user/app/vterm/font.c @@ -0,0 +1,52 @@ +#include "vterm.h" +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +struct psf font; +void *font_data; + +void font_load(const char *path) { + FILE *f = fopen(path, "r"); + if (!f) { + eprintf("couldn't open font \"%s\"", path); + 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 font_blit(uint32_t glyph, int x, int y) { + if (glyph >= font.glyph_amt) glyph = 0; + + dirty_mark(x, y); + + 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.b[fb.pitch * (y * font.h + j) + 4 * (x * font.w + i)]) = byte * 0xB0B0B0; + } + } +} diff --git a/src/user/app/vterm/vterm.c b/src/user/app/vterm/vterm.c index 4309900..0468477 100644 --- a/src/user/app/vterm/vterm.c +++ b/src/user/app/vterm/vterm.c @@ -1,143 +1,41 @@ +#include "vterm.h" #include <camellia/syscalls.h> #include <stdbool.h> -#include <stdio.h> #include <stdlib.h> -#include <string.h> -#include <unistd.h> -#define eprintf(fmt, ...) fprintf(stderr, "vterm: "fmt"\n" __VA_OPT__(,) __VA_ARGS__) +struct point cursor = {0}; -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) { +void in_char(char c) { switch (c) { case '\n': cursor.x = 0; cursor.y++; break; case '\b': - if (--cursor.x < 0) cursor.x = 0; + if (cursor.x > 0) cursor.x--; break; default: font_blit(c, cursor.x, cursor.y); cursor.x++; } - if (cursor.x * font.w >= fb_width) { + 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; + while (cursor.y * font.h >= fb.height) scroll(); } 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(); + // TODO don't hardcode size + fb.len = 640 * 480 * 4; + fb.width = 640; + fb.height = 480; + fb.pitch = 640 * 4; + fb.b = malloc(fb.len); + + font_load("/init/font.psf"); static char buf[512]; struct fs_wait_response res; diff --git a/src/user/app/vterm/vterm.h b/src/user/app/vterm/vterm.h new file mode 100644 index 0000000..5e09105 --- /dev/null +++ b/src/user/app/vterm/vterm.h @@ -0,0 +1,42 @@ +#pragma once +#include <camellia/types.h> +#include <stdint.h> +#include <stdio.h> + +#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)); +extern struct psf font; +extern void *font_data; +void font_load(const char *path); +void font_blit(uint32_t glyph, int x, int y); + + +struct framebuf { + size_t len, width, height, pitch; + char *b; +}; +extern struct framebuf fb; +extern handle_t fb_fd; + +struct rect { + uint32_t x1, y1, x2, y2; +}; +extern struct rect dirty; +void dirty_mark(uint32_t x, uint32_t y); +void flush(void); +void scroll(void); + +struct point {uint32_t x, y;}; +extern struct point cursor; +void in_char(char c); |