From 288db801e1c13617d8426031ceafd1cec65fe0b1 Mon Sep 17 00:00:00 2001 From: xiaoyi1212 Date: Mon, 2 Sep 2024 16:02:08 +0800 Subject: [PATCH] =?UTF-8?q?=E5=9F=BA=E7=A1=80vt1000=E6=A1=86=E6=9E=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/include/tty.h | 40 ++++- src/kernel/kernel.c | 1 - src/kernel/task.c | 1 + src/kernel/tty.c | 353 +++++++++++++++++++++++++++++++++++++++++++- src/util/printf.c | 21 +++ 5 files changed, 404 insertions(+), 12 deletions(-) diff --git a/src/include/tty.h b/src/include/tty.h index f688263..93f7687 100644 --- a/src/include/tty.h +++ b/src/include/tty.h @@ -6,15 +6,47 @@ typedef void (*key_lis) (uint8_t); +typedef enum { + MODE_A = 'A', + MODE_B = 'B', + MODE_C = 'C', + MODE_D = 'D', + MODE_E = 'E', + MODE_F = 'F', + MODE_G = 'G', + MODE_H = 'H', + MODE_f = 'f', + MODE_J = 'J', + MODE_K = 'K', + MODE_S = 'S', + MODE_T = 'T', + MODE_m = 'm' +} vt100_mode_t; + typedef struct tty{ - uint32_t *frame_buffer; // 图形缓冲区映射 - uint32_t width; - uint32_t height; - bool is_default_frame; // 是否为根缓冲区 + void (*print)(struct tty *res,const char *string); + void (*putchar)(struct tty *res,int c); + void (*MoveCursor)(struct tty *res,int x, int y); + void (*clear)(struct tty *res); + void (*gotoxy)(struct tty *res, int x, int y); + void (*screen_ne)(struct tty *res); + + bool is_using; // 是否可以接受输入 struct FIFO8 *fifo; // 键盘输出缓冲区 key_lis keyboard_press; // 键盘按下 key_lis keyboard_release; // 键盘松开 + int xsize, ysize; + int x, y; + uint8_t color; + + /* vt100 */ + int vt100; // 是否检测到标志 + char buffer[81]; // 缓冲区 + int buf_p; // 缓冲区指针 + int done; // 这个东西读取完毕没有? + vt100_mode_t mode; // 控制模式 + int color_saved; // 保存的颜色 }tty_t; #include "task.h" diff --git a/src/kernel/kernel.c b/src/kernel/kernel.c index bdf5f70..8a6d9e9 100644 --- a/src/kernel/kernel.c +++ b/src/kernel/kernel.c @@ -73,7 +73,6 @@ int check_task(int *pid){ } int check_task_usershell(int *pid){ - while (1) asm("hlt"); struct task_struct *shell = found_task_pid(*pid); while (1){ if(shell->state == TASK_DEATH){ diff --git a/src/kernel/task.c b/src/kernel/task.c index af01e76..a5c0bb1 100644 --- a/src/kernel/task.c +++ b/src/kernel/task.c @@ -403,6 +403,7 @@ void init_sched() { current->mem_size = 0; current->next = current; current->isUser = 0; + init_default_tty(current); extern header_t *head; extern header_t *tail; diff --git a/src/kernel/tty.c b/src/kernel/tty.c index 7d579fa..1777941 100644 --- a/src/kernel/tty.c +++ b/src/kernel/tty.c @@ -1,27 +1,366 @@ #include "../include/tty.h" #include "../include/task.h" +#include "../include/graphics.h" +#include "../include/printf.h" extern uint32_t *screen; extern uint32_t width, height; +static char eos[] = {'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'f', 'J', 'K', 'S', 'T', 'm'}; +// vt100控制字符中可能的结束符号 + +static inline int t_is_eos(char ch) { + for (int i = 0; i < sizeof(eos); i++) { + if (ch == eos[i]) return 1; + } + return 0; +} + +static inline long atol(char* s) { + bool neg = *s == '-'; + if (neg || *s == '+') s++; + long n = 0; + for (; isdigit(*s); s++) + n = n * 10 + (*s - '0'); + return neg ? -n : n; +} + +static void tty_gotoxy(struct tty *res, int x, int y) { + if (res->x == x && res->y == y) return; + if (x >= 0 && y >= 0) { + int x2 = x; + int y2 = y; + if (x <= res->xsize - 1 && y <= res->ysize - 1) { + res->MoveCursor(res, x, y); + return; + } + if (x <= res->xsize - 1) { + for (int i = 0; i < y - res->ysize + 1; i++) { + res->screen_ne(res); + } + res->MoveCursor(res, x, res->ysize - 1); + return; + } + if (x > res->xsize - 1) { + y2 += x / res->xsize - 1; + x2 = x % res->xsize; + if (y2 <= res->ysize - 1) + tty_gotoxy(res, x2, y2 + 1); + else + tty_gotoxy(res, x2, y2); + } + } else { + if (x < 0) { + x += res->xsize; + y--; + tty_gotoxy(res, x, y); + } + if (y < 0) { return; } + } +} + +static int parse_vt100(struct tty *res, char *string) { + switch (res->mode) { + case MODE_A: { + char dig_string[81] = {0}; + for (int i = 2, j = 0; string[i]; i++) { + if (t_is_eos(string[i])) break; + if (!isdigit(string[i])) return 0; + dig_string[j++] = string[i]; + } + int delta = atol(dig_string); + if (!delta) delta = 1; + res->gotoxy(res, res->x, res->y - delta); + return 1; + } + case MODE_B: { + char dig_string[81] = {0}; + for (int i = 2, j = 0; string[i]; i++) { + if (t_is_eos(string[i])) break; + if (!isdigit(string[i])) return 0; + dig_string[j++] = string[i]; + } + int delta = atol(dig_string); + if (!delta) delta = 1; + res->gotoxy(res, res->x, res->y + delta); + return 1; + } + case MODE_C: { + char dig_string[81] = {0}; + for (int i = 2, j = 0; string[i]; i++) { + if (t_is_eos(string[i])) break; + if (!isdigit(string[i])) return 0; + dig_string[j++] = string[i]; + } + int delta = atol(dig_string); + if (!delta) delta = 1; + res->gotoxy(res, res->x + delta, res->y); + return 1; + } + case MODE_D: { + char dig_string[81] = {0}; + for (int i = 2, j = 0; string[i]; i++) { + if (t_is_eos(string[i])) break; + if (!isdigit(string[i])) return 0; + dig_string[j++] = string[i]; + } + int delta = atol(dig_string); + if (!delta) delta = 1; + res->gotoxy(res, res->x - delta, res->y); + return 1; + } + case MODE_E: { + char dig_string[81] = {0}; + for (int i = 2, j = 0; string[i]; i++) { + if (t_is_eos(string[i])) break; + if (!isdigit(string[i])) return 0; + dig_string[j++] = string[i]; + } + int delta = atol(dig_string); + if (!delta) delta = 1; + res->gotoxy(res, 0, res->y + delta); + return 1; + } + case MODE_F: { + char dig_string[81] = {0}; + for (int i = 2, j = 0; string[i]; i++) { + if (t_is_eos(string[i])) break; + if (!isdigit(string[i])) return 0; + dig_string[j++] = string[i]; + } + int delta = atol(dig_string); + if (!delta) delta = 1; + res->gotoxy(res, 0, res->y - delta); + return 1; + } + case MODE_G: { + char dig_string[81] = {0}; + for (int i = 2, j = 0; string[i]; i++) { + if (t_is_eos(string[i])) break; + if (!isdigit(string[i])) return 0; + dig_string[j++] = string[i]; + } + int delta = atol(dig_string); + if (!delta) delta = 1; + res->gotoxy(res, delta - 1, res->y); // 可能是这样的 + return 1; + } + case MODE_H: { + int k = 0; + char dig_string[2][81]; + memset(dig_string, 0, sizeof(dig_string)); // 全部设置为0 + for (int i = 2, j = 0; string[i]; i++) { + if (t_is_eos(string[i])) break; + if (!isdigit(string[i])) { + if (string[i] == ';') { // 分号 + k++; + j = 0; + continue; + } + return 0; + } + dig_string[k][j++] = string[i]; + } + if (k > 1) return 0; + + int delta[2] = {0}; + for (int i = 0; i <= k; i++) { + delta[i] = atol(dig_string[i]); + } + if (k == 0 && delta[0] != 0) return 0; + switch (k) { + case 0: res->gotoxy(res, 0, 0); break; + case 1: res->gotoxy(res, delta[0], delta[1]); break; + default: return 0; + } + return 1; + } + case MODE_J: { + char dig_string[81] = {0}; + for (int i = 2, j = 0; string[i]; i++) { + if (t_is_eos(string[i])) break; + if (!isdigit(string[i])) return 0; + dig_string[j++] = string[i]; + } + int delta = atol(dig_string); + int old_x = res->x, old_y = res->y; + switch (delta) { + case 0: { + int flag = 0; + for (int i = old_y * res->xsize + old_x; i < res->xsize * res->ysize; i++) { + flag = 1; + res->putchar(res, ' '); + } + if (flag) res->gotoxy(res, old_x, old_y); + break; + } + case 1: + res->gotoxy(res, 0, 0); + for (int i = 0; i < old_y * res->xsize + old_x; i++) { + res->putchar(res, ' '); + } + break; + case 2: res->clear(res); break; + default: return 0; + } + return 1; + } + case MODE_K: { + char dig_string[81] = {0}; + for (int i = 2, j = 0; string[i]; i++) { + if (t_is_eos(string[i])) break; + if (!isdigit(string[i])) return 0; + dig_string[j++] = string[i]; + } + int delta = atol(dig_string); + int old_x = res->x, old_y = res->y; + switch (delta) { + case 0: { + int flag = 0; + for (int i = old_y * res->xsize + old_x; i < (old_y + 1) * res->ysize; i++) { + flag = 1; + res->putchar(res, ' '); + } + if (flag) res->gotoxy(res, old_x, old_y); + break; + } + case 1: + res->gotoxy(res, 0, res->y); + for (int i = old_y * res->xsize; i < old_y * res->xsize + old_x; i++) { + res->putchar(res, ' '); + } + break; + case 2: + res->gotoxy(res, 0, res->y); + for (int i = old_y * res->xsize; i < (old_y + 1) * res->xsize; i++) { + res->putchar(res, ' '); + } + res->gotoxy(res, old_x, old_y); + break; + default: return 0; + } + return 1; + } + case MODE_S: return 0; // unsupported + case MODE_T: { + char dig_string[81] = {0}; + for (int i = 2, j = 0; string[i]; i++) { + if (t_is_eos(string[i])) break; + if (!isdigit(string[i])) return 0; + dig_string[j++] = string[i]; + } + int delta = atol(dig_string); + if (delta) return 0; + res->screen_ne(res); + return 1; + } + case MODE_m: { + // klogd("MODE_m"); + int k = 0; + char dig_string[2][81]; + memset(dig_string, 0, sizeof(dig_string)); // 全部设置为0 + for (int i = 2, j = 0; string[i]; i++) { + if (t_is_eos(string[i])) break; + if (!isdigit(string[i])) { + if (string[i] == ';') { // 分号 + k++; + j = 0; + continue; + } + return 0; + } + dig_string[k][j++] = string[i]; + } + if (k > 1) { + return 0; + } + + int delta[2] = {0}; + // klogd("start for %d", k); + for (int i = 0; i <= k; i++) { + delta[i] = atol(dig_string[i]); + } + if (delta[0] == 0 && k == 0) { + int sel_color = res->color_saved != -1 ? res->color_saved : res->color; + res->color = sel_color; + res->color_saved = -1; + return 1; + } else if (delta[0] == 1 && k == 0) { // unsupported + return 0; + } + // klogd("switch k"); + static const uint8_t color_map[8] = {0, 4, 2, 6, 1, 5, 3, 7}; + switch (k) { + case 0: { + if (delta[0] >= 30 && delta[0] <= 37) { // foreground color + if (res->color_saved == -1) res->color_saved = res->color; + res->color &= 0xf0; + res->color |= color_map[delta[0] - 30]; + return 1; + } else if (delta[0] >= 40 && delta[0] <= 47) { + if (res->color_saved == -1) res->color_saved = res->color; + res->color &= 0x0f; + res->color |= color_map[delta[0] - 40] << 4; + return 1; + } else { + return 0; + } + } + case 1: { + if (delta[0] != 1) { + return 0; + } + if (delta[1] >= 30 && delta[1] <= 37) { // foreground color + if (res->color_saved == -1) { res->color_saved = res->color; } + res->color &= 0xf0; + res->color |= color_map[delta[1] - 30] + 8; + return 1; + } else if (delta[1] >= 40 && delta[1] <= 47) { + if (res->color_saved == -1) res->color_saved = res->color; + res->color &= 0x0f; + res->color |= (color_map[delta[1] - 40] + 8) << 4; + return 1; + } else { + return 0; + } + } + default: return 0; + } + } + default: break; + } + return 0; +} + +void tty_print(struct tty *res,const char *string){ + vbe_writestring(string); +} +void tty_putchar(struct tty *res,int c){ + vbe_putchar(c); +} +void tty_MoveCursor(struct tty *res,int x, int y){ + +} +void tty_clear(struct tty *res){ + vbe_clear(); +} + void init_default_tty(struct task_struct *task){ task->tty->fifo = kmalloc(sizeof(struct FIFO8)); char* buffer = kmalloc(256); - task->tty->frame_buffer = screen; - task->tty->width = width; - task->tty->height = height; - task->tty->is_default_frame = true; task->tty->is_using = true; + task->tty->print = tty_print; + task->tty->clear = tty_clear; + task->tty->putchar = tty_putchar; + task->tty->gotoxy = tty_gotoxy; fifo8_init(task->tty->fifo,256,buffer); } void free_tty(struct task_struct *task){ - if(!task->tty->is_default_frame){ - kfree(task->tty->frame_buffer); - } kfree(task->tty->fifo->buf); kfree(task->tty->fifo); kfree(task->tty); } + diff --git a/src/util/printf.c b/src/util/printf.c index 4dcb96f..67dbc83 100644 --- a/src/util/printf.c +++ b/src/util/printf.c @@ -2,6 +2,7 @@ #include "../include/common.h" #include "../include/graphics.h" #include "../include/serial.h" +#include "../include/tty.h" static int skip_atoi(const char **s) { int i = 0; @@ -305,18 +306,38 @@ void printf(const char *formet, ...) { } void screen_clear(){ + struct task_struct *task = get_current(); + if(task != NULL){ + task->tty->clear(task->tty); + return; + } + if(vbe_status){ vbe_clear(); } else vga_clear(); } void putchar(char c){ + struct task_struct *task = get_current(); + if(task != NULL){ + task->tty->putchar(task->tty,c); + return; + } + if(vbe_status){ vbe_putchar(c); } else vga_putchar(c); } void print(char *message) { + struct task_struct *task = get_current(); + if(task != NULL){ + task->tty->print(task->tty,message); + return; + } + + logk(message); + if(vbe_status){ vbe_writestring(message); } else vga_writestring(message);