From 642b5fb0007b64c77d186fcb018d571152ee1d47 Mon Sep 17 00:00:00 2001 From: dzwdz Date: Mon, 14 Aug 2023 18:51:07 +0200 Subject: reorganization: first steps --- src/cmd/vterm/draw.c | 17 ++++++++++++ src/cmd/vterm/font.c | 76 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/cmd/vterm/vterm.c | 72 ++++++++++++++++++++++++++++++++++++++++++++++++ src/cmd/vterm/vterm.h | 39 ++++++++++++++++++++++++++ 4 files changed, 204 insertions(+) create mode 100644 src/cmd/vterm/draw.c create mode 100644 src/cmd/vterm/font.c create mode 100644 src/cmd/vterm/vterm.c create mode 100644 src/cmd/vterm/vterm.h (limited to 'src/cmd/vterm') diff --git a/src/cmd/vterm/draw.c b/src/cmd/vterm/draw.c new file mode 100644 index 0000000..ee36a0f --- /dev/null +++ b/src/cmd/vterm/draw.c @@ -0,0 +1,17 @@ +#include "vterm.h" +#include +#include +#include + +struct framebuf fb; +struct rect dirty; + +void scroll(void) { + size_t row_len = fb.pitch * font.h; + memmove(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/cmd/vterm/font.c b/src/cmd/vterm/font.c new file mode 100644 index 0000000..777b094 --- /dev/null +++ b/src/cmd/vterm/font.c @@ -0,0 +1,76 @@ +#include "vterm.h" +#include +#include +#include +#include + +struct psf2 font; +void *font_data; + +void font_load(const char *path) { + FILE *f = fopen(path, "r"); + if (!f) { + err(1, "couldn't open font \"%s\"", path); + } + + void *buf; + long buflen; + + fseek(f, 0, SEEK_END); + buflen = ftell(f); + if (buflen < 0) { + errx(1, "can't get the size of \"%s\"", path); + } + + buf = malloc(buflen); + if (!buf) { + err(1, "out of memory"); + } + + fseek(f, 0, SEEK_SET); + fread(buf, 1, buflen, f); + if (ferror(f)) { + err(1, "error reading font"); + } + fclose(f); + + if (!memcmp(buf, "\x72\xb5\x4a\x86", 4)) { + memcpy(&font, buf, sizeof font); + font_data = buf + font.glyph_offset; + } else if (!memcmp(buf, "\x36\x04", 2)) { + struct psf1 *hdr = buf; + font = (struct psf2){ + .glyph_amt = 256, + .glyph_size = hdr->h, + .h = hdr->h, + .w = 8, + }; + font_data = buf + 4; + } else { + errx(1, "invalid psf header"); + } +} + +void font_blit(uint32_t glyph, int x, int y) { + if (glyph >= font.glyph_amt) glyph = 0; + if (x < 0 || (x+1) * font.w >= fb.width || + y < 0 || (y+1) * font.h >= fb.height) + { + return; + } + + dirty_mark(&dirty, x * font.w, y * font.h); + dirty_mark(&dirty, (x+1) * font.w - 1, (y+1) * font.h - 1); + + 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; + } + } + return; +} diff --git a/src/cmd/vterm/vterm.c b/src/cmd/vterm/vterm.c new file mode 100644 index 0000000..f365f6b --- /dev/null +++ b/src/cmd/vterm/vterm.c @@ -0,0 +1,72 @@ +#include "vterm.h" +#include +#include +#include +#include +#include +#include +#include + +struct point cursor = {0}; + +void in_char(char c) { + switch (c) { + case '\n': + cursor.x = 0; + cursor.y++; + break; + case '\b': + if (cursor.x > 0) cursor.x--; + break; + case '\t': + /* rounds down to nearest multiple of 8 and adds 8 + = adding 1 and rounding up to the nearest multiple of 8 */ + cursor.x = (cursor.x & ~7) + 8; + 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 + 1) * font.h >= fb.height) scroll(); +} + +int main(void) { + if (fb_setup(&fb, "/kdev/video/") < 0) { + eprintf("fb_setup error"); + return 1; + } + font_load("/init/usr/share/fonts/spleen/spleen-8x16.psfu"); + + static char buf[512]; + struct ufs_request res; + while (!c0_fs_wait(buf, sizeof buf, &res)) { + switch (res.op) { + case VFSOP_OPEN: + // TODO check path + c0_fs_respond(NULL, 0, 0); + break; + + case VFSOP_WRITE: + if (res.flags) { + c0_fs_respond(NULL, -1, 0); + } else { + for (size_t i = 0; i < res.len; i++) + in_char(buf[i]); + dirty_flush(&dirty, &fb); + c0_fs_respond(NULL, res.len, 0); + } + break; + + default: + c0_fs_respond(NULL, -1, 0); + break; + } + } + + return 1; +} diff --git a/src/cmd/vterm/vterm.h b/src/cmd/vterm/vterm.h new file mode 100644 index 0000000..026e71a --- /dev/null +++ b/src/cmd/vterm/vterm.h @@ -0,0 +1,39 @@ +#pragma once +#include +#include +#include +#include + +#define eprintf(fmt, ...) fprintf(stderr, "vterm: "fmt"\n" __VA_OPT__(,) __VA_ARGS__) + + +struct psf1 { + uint16_t magic; + uint8_t mode; + uint8_t h; +} __attribute__((packed)); +struct psf2 { + 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 psf2 font; +extern void *font_data; +void font_load(const char *path); +void font_blit(uint32_t glyph, int x, int y); + +extern struct framebuf fb; + +extern struct rect dirty; +void vdirty_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); -- cgit v1.2.3