diff options
-rw-r--r-- | Makefile | 2 | ||||
-rwxr-xr-x | make_cdrom.sh | 1 | ||||
-rw-r--r-- | src/lib/include/draw.h | 2 | ||||
-rw-r--r-- | src/lib/include/keyboard.h | 3 | ||||
-rw-r--r-- | src/lib/libkogata/draw.c | 8 | ||||
-rw-r--r-- | src/lib/libkogata/gip.c | 2 | ||||
-rw-r--r-- | src/sysbin/login/main.c | 132 | ||||
-rw-r--r-- | src/sysbin/terminal/Makefile | 12 | ||||
-rw-r--r-- | src/sysbin/terminal/main.c | 253 |
9 files changed, 296 insertions, 119 deletions
@@ -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 :*/ |