aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlex Auvolat <alex@adnab.me>2015-03-13 14:46:15 +0100
committerAlex Auvolat <alex@adnab.me>2015-03-13 14:46:53 +0100
commit243e6d72928d1fc4cf20366eab9007980b945458 (patch)
treeb4b2a22d4ef4cbb33c8c17f904f82cde73093ea6
parentfb5efb630ab93893f8bb3036acbb591591a03032 (diff)
downloadkogata-243e6d72928d1fc4cf20366eab9007980b945458.tar.gz
kogata-243e6d72928d1fc4cf20366eab9007980b945458.zip
Begin implement terminal
-rw-r--r--Makefile2
-rwxr-xr-xmake_cdrom.sh1
-rw-r--r--src/lib/include/draw.h2
-rw-r--r--src/lib/include/keyboard.h3
-rw-r--r--src/lib/libkogata/draw.c8
-rw-r--r--src/lib/libkogata/gip.c2
-rw-r--r--src/sysbin/login/main.c132
-rw-r--r--src/sysbin/terminal/Makefile12
-rw-r--r--src/sysbin/terminal/main.c253
9 files changed, 296 insertions, 119 deletions
diff --git a/Makefile b/Makefile
index 6e472d0..7e026bb 100644
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,6 @@
DIRS = src/common/libkogata src/common/libc src/common/libalgo \
src/kernel src/lib/libkogata \
- src/sysbin/init src/sysbin/giosrv src/sysbin/login \
+ src/sysbin/init src/sysbin/giosrv src/sysbin/login src/sysbin/terminal \
res/fonts res/keymaps
all:
diff --git a/make_cdrom.sh b/make_cdrom.sh
index 1e32b32..d42a33c 100755
--- a/make_cdrom.sh
+++ b/make_cdrom.sh
@@ -15,6 +15,7 @@ cp src/sysbin/init/init.bin cdrom/boot; strip cdrom/boot/init.bin
mkdir -p cdrom/sys/bin
cp src/sysbin/giosrv/giosrv.bin cdrom/sys/bin
cp src/sysbin/login/login.bin cdrom/sys/bin
+cp src/sysbin/terminal/terminal.bin cdrom/sys/bin
for BIN in cdrom/sys/bin/*.bin; do strip $BIN; done
mkdir -p cdrom/sys/fonts
diff --git a/src/lib/include/draw.h b/src/lib/include/draw.h
index 893c5a3..5296b92 100644
--- a/src/lib/include/draw.h
+++ b/src/lib/include/draw.h
@@ -48,6 +48,8 @@ void g_fillcircle(fb_t *fb, int cx, int cy, int r, color_t c);
void g_blit(fb_t *dst, int x, int y, fb_t *src);
void g_blit_region(fb_t *dst, int x, int y, fb_t *src, fb_region_t reg);
+void g_scroll_up(fb_t *fb, int l);
+
// ---- Text manipulation
font_t *g_load_font(const char* fontname);
diff --git a/src/lib/include/keyboard.h b/src/lib/include/keyboard.h
index 2842936..0d5a97a 100644
--- a/src/lib/include/keyboard.h
+++ b/src/lib/include/keyboard.h
@@ -1,7 +1,8 @@
#pragma once
-#include <proto/keymap_file.h>
+#include <proto/keyboard.h>
+#include <proto/keymap_file.h>
#define KBD_CHAR 0x01
#define KBD_ALT 0x02
diff --git a/src/lib/libkogata/draw.c b/src/lib/libkogata/draw.c
index b9ef9bc..0536c03 100644
--- a/src/lib/libkogata/draw.c
+++ b/src/lib/libkogata/draw.c
@@ -208,6 +208,14 @@ void g_blit_region(fb_t *dst, int x, int y, fb_t *src, fb_region_t reg) {
}
}
+void g_scroll_up(fb_t *dst, int l) {
+ for (unsigned y = 0; y < dst->geom.height - l; y++) {
+ memcpy(dst->data + y * dst->geom.pitch,
+ dst->data + (y + l) * dst->geom.pitch,
+ dst->geom.pitch);
+ }
+}
+
// ---- Text manipulation
#define FONT_ASCII_BITMAP 1
diff --git a/src/lib/libkogata/gip.c b/src/lib/libkogata/gip.c
index 852cc05..cdfeb71 100644
--- a/src/lib/libkogata/gip.c
+++ b/src/lib/libkogata/gip.c
@@ -137,7 +137,7 @@ void giph_msg_header(mainloop_fd_t *fd) {
ASSERT(fd == &h->mainloop_item);
int code = h->msg_buf.code;
- dbg_printf("Got GIP header, code %d\n", code);
+ /*dbg_printf("Got GIP header, code %d\n", code);*/
noarg_gip_callback_t use_cb = 0;
if (code == GIPC_RESET) {
diff --git a/src/sysbin/login/main.c b/src/sysbin/login/main.c
index 3c02a4b..5d8840b 100644
--- a/src/sysbin/login/main.c
+++ b/src/sysbin/login/main.c
@@ -3,132 +3,32 @@
#include <user_region.h>
#include <debug.h>
-#include <gip.h>
-#include <draw.h>
-#include <keyboard.h>
-
-typedef struct {
- fb_info_t mode;
- fd_t fd;
- fb_t *fb;
-
- uint32_t sv_features, cl_features;
-} loginc_t;
-
-void c_buffer_info(gip_handler_t *s, gip_msg_header *p, gip_buffer_info_msg *m);
-void c_key_down(gip_handler_t *s, gip_msg_header *p);
-void c_key_up(gip_handler_t *s, gip_msg_header *p);
-void c_unknown_msg(gip_handler_t *s, gip_msg_header *p);
-void c_fd_error(gip_handler_t *s);
-
-void c_async_initiate(gip_handler_t *s, gip_msg_header *p, void* msgdata, void* hdata);
-
-gip_handler_callbacks_t loginc_cb = {
- .reset = 0,
- .initiate = 0,
- .ok = 0,
- .failure = 0,
- .enable_features = 0,
- .disable_features = 0,
- .query_mode = 0,
- .set_mode = 0,
- .buffer_info = c_buffer_info,
- .mode_info = 0,
- .buffer_damage = 0,
- .key_down = c_key_down,
- .key_up = c_key_up,
- .unknown_msg = c_unknown_msg,
- .fd_error = c_fd_error,
-};
-
-keyboard_t *kb;
+#include <syscall.h>
int main(int argc, char **argv) {
dbg_print("[login] Starting up.\n");
- kb = init_keyboard();
-
- loginc_t loginc;
- memset(&loginc, 0, sizeof(loginc));
-
- gip_handler_t *h = new_gip_handler(&loginc_cb, &loginc);
- ASSERT(h != 0);
-
- h->mainloop_item.fd = 1;
- mainloop_add_fd(&h->mainloop_item);
-
- gip_msg_header reset_msg = { .code = GIPC_RESET, .arg = 0 };
- gip_cmd(h, &reset_msg, 0, c_async_initiate, 0);
-
- mainloop_run();
-
- return 0;
-}
-
-void c_buffer_info(gip_handler_t *s, gip_msg_header *p, gip_buffer_info_msg *m) {
- dbg_printf("[login] Got buffer info msg\n");
-
- loginc_t *c = (loginc_t*)s->data;
-
- if (c->fb != 0) {
- g_delete_fb(c->fb);
- c->fb = 0;
- }
- if (c->fd != 0) {
- close(c->fd);
- c->fd = 0;
+ // just launch a terminal
+ pid_t term_pid = new_proc();
+ if (term_pid == 0) {
+ PANIC("[login] Could not launch terminal");
}
- c->fd = use_token(&m->tok);
- if (c->fd != 0) {
- memcpy(&c->mode, &m->geom, sizeof(fb_info_t));
-
- dbg_printf("[login] Got buffer on FD %d, %dx%dx%d\n",
- c->fd, c->mode.width, c->mode.height, c->mode.bpp);
-
- c->fb = g_fb_from_file(c->fd, &m->geom);
- if (c->fb != 0) {
- color_t black = g_color_rgb(c->fb, 0, 0, 0);
- color_t grey = g_color_rgb(c->fb, 128, 128, 128);
- g_fillrect(c->fb, 0, 0, m->geom.width, m->geom.height, black);
- g_fillrect(c->fb, 50, 50, 50, 50, grey);
+ bool ok;
- font_t *f = g_load_font("default");
- if (f != 0) {
- g_write(c->fb, 50, 100, "Hello, world!", f, grey);
- g_free_font(f);
- } else {
- dbg_printf("Could not load font 'default'\n");
- }
- } else {
- dbg_printf("Could not open framebuffer file %d\n", c->fd);
- }
+ ok = bind_fs(term_pid, "root", "root")
+ && bind_fs(term_pid, "sys", "sys")
+ && bind_fs(term_pid, "config", "config")
+ && bind_fd(term_pid, 1, 1);
+ if (!ok) PANIC("[login] Could not bind to terminal process.");
- }
-}
+ ok = proc_exec(term_pid, "sys:/bin/terminal.bin");
+ if (!ok) PANIC("[login] Could not run terminal.bin");
-void c_key_down(gip_handler_t *s, gip_msg_header *p) {
- keyboard_press(kb, p->arg);
-}
+ proc_status_t s;
+ proc_wait(term_pid, true, &s);
-void c_key_up(gip_handler_t *s, gip_msg_header *p) {
- key_t k = keyboard_release(kb, p->arg);
- if (k.chr) dbg_printf("%c", k.chr);
-}
-
-void c_unknown_msg(gip_handler_t *s, gip_msg_header *p) {
- // TODO
-}
-
-void c_fd_error(gip_handler_t *s) {
- // TODO
-}
-
-void c_async_initiate(gip_handler_t *s, gip_msg_header *p, void* msgdata, void* hdata) {
- loginc_t *c = (loginc_t*)s->data;
- c->sv_features = p->arg;
-
- dbg_printf("[login] Got initiate reply to reset request (features 0x%p).\n", c->sv_features);
+ return 0;
}
/* vim: set ts=4 sw=4 tw=0 noet :*/
diff --git a/src/sysbin/terminal/Makefile b/src/sysbin/terminal/Makefile
new file mode 100644
index 0000000..cdbf2fe
--- /dev/null
+++ b/src/sysbin/terminal/Makefile
@@ -0,0 +1,12 @@
+
+OBJ = main.o
+
+LIB = ../../lib/libkogata/libkogata.lib
+
+CFLAGS = -I ./include -I ../../common/include -I ../../lib/include
+
+LDFLAGS = -T ../linker.ld -Xlinker -Map=terminal.map
+
+OUT = terminal.bin
+
+include ../../rules.make
diff --git a/src/sysbin/terminal/main.c b/src/sysbin/terminal/main.c
new file mode 100644
index 0000000..9ba7afe
--- /dev/null
+++ b/src/sysbin/terminal/main.c
@@ -0,0 +1,253 @@
+#include <string.h>
+#include <malloc.h>
+#include <user_region.h>
+#include <debug.h>
+
+#include <gip.h>
+#include <draw.h>
+#include <keyboard.h>
+
+typedef char tchar_t;
+
+typedef struct {
+ fb_info_t mode;
+ fd_t fd;
+ fb_t *fb;
+
+ uint32_t sv_features, cl_features;
+
+ font_t *font;
+ int cw, ch; // size of a character
+ color_t fg, bg;
+
+ keyboard_t *kb;
+
+ int w, h;
+ tchar_t* scr_chars;
+ int csrl, csrc;
+ bool csr_visible;
+
+} term_t;
+
+void c_buffer_info(gip_handler_t *s, gip_msg_header *p, gip_buffer_info_msg *m);
+void c_key_down(gip_handler_t *s, gip_msg_header *p);
+void c_key_up(gip_handler_t *s, gip_msg_header *p);
+void c_unknown_msg(gip_handler_t *s, gip_msg_header *p);
+void c_fd_error(gip_handler_t *s);
+
+void c_async_initiate(gip_handler_t *s, gip_msg_header *p, void* msgdata, void* hdata);
+
+gip_handler_callbacks_t term_gip_cb = {
+ .reset = 0,
+ .initiate = 0,
+ .ok = 0,
+ .failure = 0,
+ .enable_features = 0,
+ .disable_features = 0,
+ .query_mode = 0,
+ .set_mode = 0,
+ .buffer_info = c_buffer_info,
+ .mode_info = 0,
+ .buffer_damage = 0,
+ .key_down = c_key_down,
+ .key_up = c_key_up,
+ .unknown_msg = c_unknown_msg,
+ .fd_error = c_fd_error,
+};
+
+
+int main(int argc, char **argv) {
+ dbg_print("[terminal] Starting up.\n");
+
+ term_t term;
+ memset(&term, 0, sizeof(term));
+
+ term.kb = init_keyboard();
+ ASSERT(term.kb != 0);
+
+ term.font = g_load_font("default");
+ ASSERT(term.font != 0);
+ term.cw = g_text_width(term.font, "#");
+ term.ch = g_text_height(term.font, "#");
+
+ gip_handler_t *h = new_gip_handler(&term_gip_cb, &term);
+ ASSERT(h != 0);
+
+ h->mainloop_item.fd = 1;
+ mainloop_add_fd(&h->mainloop_item);
+
+ gip_msg_header reset_msg = { .code = GIPC_RESET, .arg = 0 };
+ gip_cmd(h, &reset_msg, 0, c_async_initiate, 0);
+
+ mainloop_run();
+
+ return 0;
+}
+
+// Terminal features
+
+void term_draw_c(term_t *t, int l, int c) {
+ color_t bg = t->bg;
+ if (l == t->csrl && c == t->csrc) bg = g_color_rgb(t->fb, 0, 100, 0);
+
+ char ss[2];
+ ss[0] = t->scr_chars[l * t->w + c];
+ ss[1] = 0;
+
+ g_fillrect(t->fb, c * t->cw, l * t->ch, t->cw, t->ch, bg);
+ g_write(t->fb, c * t->cw, l * t->ch, ss, t->font, t->fg);
+}
+
+void term_move_cursor(term_t *t, int l, int c) {
+ int l0 = t->csrl, c0 = t->csrc;
+ t->csrl = l;
+ t->csrc = c;
+ term_draw_c(t, l0, c0);
+ term_draw_c(t, l, c);
+}
+
+void term_clear_screen(term_t *t) {
+ t->csr_visible = true;
+
+ for (int i = 0; i < t->w * t->h; i++) t->scr_chars[i] = ' ';
+
+ g_fillrect(t->fb, 0, 0, t->mode.width, t->mode.height, t->bg);
+
+ term_move_cursor(t, 0, 0);
+}
+
+void term_scroll1(term_t *t) {
+ for (int i = 0; i < t->w * (t->h - 1); i++)
+ t->scr_chars[i] = t->scr_chars[i + t->w];
+ for (int i = 0; i < t->w; i++) {
+ t->scr_chars[i + (t->h - 1) * t->w] = ' ';
+ }
+ t->csrl--;
+
+ g_scroll_up(t->fb, t->ch);
+ g_fillrect(t->fb, 0, t->ch * (t->h - 1), t->cw * t->w, t->ch, t->bg);
+}
+
+void term_putc(term_t *t, int c) {
+ int nl = t->csrl, nc = t->csrc;
+ if (c == '\n') {
+ nl++; nc = 0;
+ } else if (c == '\b') {
+ if (nc > 0) {
+ nc--;
+ t->scr_chars[nl * t->w + nc] = ' ';
+ }
+ } else if (c == '\t') {
+ while (nc % 4 != 0) nc++;
+ } else if (c >= ' ' && c < 128) {
+ t->scr_chars[nl * t->w + nc] = c;
+ nc++;
+ }
+ if (nc >= t->w) {
+ nc = 0;
+ nl++;
+ }
+ if (nl >= t->h) {
+ term_scroll1(t);
+ nl--;
+ }
+ term_move_cursor(t, nl, nc);
+}
+
+void term_puts(term_t *t, char* s) {
+ while ((*s) != 0) {
+ term_putc(t, *s);
+ s++;
+ }
+}
+
+// GIP client connection
+
+void c_buffer_info(gip_handler_t *s, gip_msg_header *p, gip_buffer_info_msg *m) {
+ dbg_printf("[terminal] Got buffer info msg\n");
+
+ term_t *c = (term_t*)s->data;
+
+ if (c->fb != 0) {
+ g_delete_fb(c->fb);
+ c->fb = 0;
+ }
+ if (c->fd != 0) {
+ close(c->fd);
+ c->fd = 0;
+ }
+
+ c->fd = use_token(&m->tok);
+ if (c->fd != 0) {
+ memcpy(&c->mode, &m->geom, sizeof(fb_info_t));
+
+ dbg_printf("[terminal] Got buffer on FD %d, %dx%dx%d\n",
+ c->fd, c->mode.width, c->mode.height, c->mode.bpp);
+
+ if (c->scr_chars != 0) {
+ free(c->scr_chars);
+ c->scr_chars = 0;
+ }
+ c->w = c->mode.width / c->cw;
+ c->h = c->mode.height / c->ch;
+ c->scr_chars = (tchar_t*)malloc(c->w * c->h * sizeof(tchar_t));
+ ASSERT(c->scr_chars != 0);
+
+ c->fb = g_fb_from_file(c->fd, &m->geom);
+ if (c->fb != 0) {
+ c->bg = g_color_rgb(c->fb, 0, 0, 0);
+ c->fg = g_color_rgb(c->fb, 200, 200, 200);
+ term_clear_screen(c);
+ } else {
+ dbg_printf("[terminal] Could not open framebuffer file %d\n", c->fd);
+ }
+
+ }
+}
+
+void c_key_down(gip_handler_t *s, gip_msg_header *p) {
+ term_t *c = (term_t*)s->data;
+
+ key_t k = keyboard_press(c->kb, p->arg);
+
+ if (k.flags & KBD_CHAR)
+ dbg_printf("D %x %c\n", k.flags, k.key);
+ else
+ dbg_printf("D %x %d\n", k.flags, k.key);
+}
+
+void c_key_up(gip_handler_t *s, gip_msg_header *p) {
+ term_t *c = (term_t*)s->data;
+
+ key_t k = keyboard_release(c->kb, p->arg);
+
+ if (k.flags & KBD_CHAR)
+ dbg_printf("U %x %c\n", k.flags, k.key);
+ else
+ dbg_printf("U %x %d\n", k.flags, k.key);
+
+ if (k.flags & KBD_CHAR) {
+ term_putc(c, k.chr);
+ } else {
+ if (k.key == KBD_CODE_RETURN) term_putc(c, '\n');
+ if (k.key == KBD_CODE_TAB) term_putc(c, '\t');
+ if (k.key == KBD_CODE_BKSP) term_putc(c, '\b');
+ }
+}
+
+void c_unknown_msg(gip_handler_t *s, gip_msg_header *p) {
+ // TODO
+}
+
+void c_fd_error(gip_handler_t *s) {
+ // TODO
+}
+
+void c_async_initiate(gip_handler_t *s, gip_msg_header *p, void* msgdata, void* hdata) {
+ term_t *c = (term_t*)s->data;
+ c->sv_features = p->arg;
+
+ dbg_printf("[temrinal] Got initiate reply to reset request (features 0x%p).\n", c->sv_features);
+}
+
+/* vim: set ts=4 sw=4 tw=0 noet :*/