summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/user/app/vterm/draw.c44
-rw-r--r--src/user/app/vterm/font.c52
-rw-r--r--src/user/app/vterm/vterm.c130
-rw-r--r--src/user/app/vterm/vterm.h42
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);