From 48dc5e985731c5204be098ff9a79314d4058d805 Mon Sep 17 00:00:00 2001 From: Leonmmcoset Date: Sat, 11 Apr 2026 16:46:10 +0800 Subject: [PATCH] Stage 18 --- clks/drivers/video/framebuffer.c | 40 +++++++++++++++ clks/include/clks/framebuffer.h | 1 + clks/kernel/kmain.c | 4 +- clks/kernel/tty.c | 75 ++++++++++++++++++++++++++- clks/kernel/userland.c | 10 ++-- ramdisk/system/tty.psf | Bin 4597 -> 4100 bytes scripts/gen-tty-psf.ps1 | 84 +++++++++++++++++++++++++++++++ 7 files changed, 208 insertions(+), 6 deletions(-) create mode 100644 scripts/gen-tty-psf.ps1 diff --git a/clks/drivers/video/framebuffer.c b/clks/drivers/video/framebuffer.c index 25f792d..2a60b4d 100644 --- a/clks/drivers/video/framebuffer.c +++ b/clks/drivers/video/framebuffer.c @@ -1,4 +1,5 @@ #include +#include #include #include "psf_font.h" @@ -103,6 +104,45 @@ void clks_fb_clear(u32 rgb) { } } +void clks_fb_scroll_up(u32 pixel_rows, u32 fill_rgb) { + usize row_bytes; + usize move_bytes; + u32 y; + u32 x; + + if (clks_fb.ready == CLKS_FALSE) { + return; + } + + if (clks_fb.info.bpp != 32) { + return; + } + + if (pixel_rows == 0U) { + return; + } + + if (pixel_rows >= clks_fb.info.height) { + clks_fb_clear(fill_rgb); + return; + } + + row_bytes = (usize)clks_fb.info.pitch; + move_bytes = (usize)(clks_fb.info.height - pixel_rows) * row_bytes; + + clks_memmove( + (void *)clks_fb.address, + (const void *)(clks_fb.address + ((usize)pixel_rows * row_bytes)), + move_bytes + ); + + for (y = clks_fb.info.height - pixel_rows; y < clks_fb.info.height; y++) { + for (x = 0U; x < clks_fb.info.width; x++) { + clks_fb_put_pixel(x, y, fill_rgb); + } + } +} + void clks_fb_draw_char(u32 x, u32 y, char ch, u32 fg_rgb, u32 bg_rgb) { const u8 *glyph; u32 row; diff --git a/clks/include/clks/framebuffer.h b/clks/include/clks/framebuffer.h index 18d4c73..b7bea95 100644 --- a/clks/include/clks/framebuffer.h +++ b/clks/include/clks/framebuffer.h @@ -15,6 +15,7 @@ void clks_fb_init(const struct limine_framebuffer *fb); clks_bool clks_fb_ready(void); struct clks_framebuffer_info clks_fb_info(void); void clks_fb_clear(u32 rgb); +void clks_fb_scroll_up(u32 pixel_rows, u32 fill_rgb); void clks_fb_draw_char(u32 x, u32 y, char ch, u32 fg_rgb, u32 bg_rgb); clks_bool clks_fb_load_psf_font(const void *blob, u64 blob_size); u32 clks_fb_cell_width(void); diff --git a/clks/kernel/kmain.c b/clks/kernel/kmain.c index 69f9381..73b78ae 100644 --- a/clks/kernel/kmain.c +++ b/clks/kernel/kmain.c @@ -95,7 +95,7 @@ void clks_kernel_main(void) { clks_tty_init(); } - clks_log(CLKS_LOG_INFO, "BOOT", "CLEONOS STAGE16 START"); + clks_log(CLKS_LOG_INFO, "BOOT", "CLEONOS STAGE18 START"); if (boot_fb == CLKS_NULL) { clks_log(CLKS_LOG_WARN, "VIDEO", "NO FRAMEBUFFER FROM LIMINE"); @@ -218,10 +218,12 @@ void clks_kernel_main(void) { clks_log_hex(CLKS_LOG_INFO, "SYSCALL", "TICKS", syscall_ticks); clks_shell_init(); + clks_log(CLKS_LOG_INFO, "SHELL", "KERNEL SHELL ACTIVE"); clks_log_hex(CLKS_LOG_INFO, "TTY", "COUNT", (u64)clks_tty_count()); clks_log_hex(CLKS_LOG_INFO, "TTY", "ACTIVE", (u64)clks_tty_active()); clks_log(CLKS_LOG_INFO, "TTY", "VIRTUAL TTY0 READY"); + clks_log(CLKS_LOG_INFO, "TTY", "CURSOR ENABLED"); clks_log(CLKS_LOG_DEBUG, "KERNEL", "IDLE LOOP ENTER"); clks_cpu_halt_forever(); diff --git a/clks/kernel/tty.c b/clks/kernel/tty.c index f5c97e8..7459e2d 100644 --- a/clks/kernel/tty.c +++ b/clks/kernel/tty.c @@ -20,6 +20,7 @@ static u32 clks_tty_active_index = 0; static u32 clks_tty_cell_width = 8U; static u32 clks_tty_cell_height = 8U; static clks_bool clks_tty_is_ready = CLKS_FALSE; +static clks_bool clks_tty_cursor_visible = CLKS_FALSE; static void clks_tty_fill_row(u32 tty_index, u32 row, char ch) { u32 col; @@ -29,8 +30,57 @@ static void clks_tty_fill_row(u32 tty_index, u32 row, char ch) { } } +static void clks_tty_draw_cell_with_colors(u32 row, u32 col, char ch, u32 fg, u32 bg) { + clks_fb_draw_char(col * clks_tty_cell_width, row * clks_tty_cell_height, ch, fg, bg); +} + static void clks_tty_draw_cell(u32 row, u32 col, char ch) { - clks_fb_draw_char(col * clks_tty_cell_width, row * clks_tty_cell_height, ch, CLKS_TTY_FG, CLKS_TTY_BG); + clks_tty_draw_cell_with_colors(row, col, ch, CLKS_TTY_FG, CLKS_TTY_BG); +} + +static void clks_tty_hide_cursor(void) { + u32 row; + u32 col; + + if (clks_tty_is_ready == CLKS_FALSE || clks_tty_cursor_visible == CLKS_FALSE) { + return; + } + + row = clks_tty_cursor_row[clks_tty_active_index]; + col = clks_tty_cursor_col[clks_tty_active_index]; + + if (row < clks_tty_rows && col < clks_tty_cols) { + clks_tty_draw_cell(row, col, clks_tty_cells[clks_tty_active_index][row][col]); + } + + clks_tty_cursor_visible = CLKS_FALSE; +} + +static void clks_tty_draw_cursor(void) { + u32 row; + u32 col; + + if (clks_tty_is_ready == CLKS_FALSE) { + return; + } + + row = clks_tty_cursor_row[clks_tty_active_index]; + col = clks_tty_cursor_col[clks_tty_active_index]; + + if (row >= clks_tty_rows || col >= clks_tty_cols) { + clks_tty_cursor_visible = CLKS_FALSE; + return; + } + + clks_tty_draw_cell_with_colors( + row, + col, + clks_tty_cells[clks_tty_active_index][row][col], + CLKS_TTY_BG, + CLKS_TTY_FG + ); + + clks_tty_cursor_visible = CLKS_TRUE; } static void clks_tty_redraw_active(void) { @@ -38,12 +88,15 @@ static void clks_tty_redraw_active(void) { u32 col; clks_fb_clear(CLKS_TTY_BG); + clks_tty_cursor_visible = CLKS_FALSE; for (row = 0; row < clks_tty_rows; row++) { for (col = 0; col < clks_tty_cols; col++) { clks_tty_draw_cell(row, col, clks_tty_cells[clks_tty_active_index][row][col]); } } + + clks_tty_draw_cursor(); } static void clks_tty_scroll_up(u32 tty_index) { @@ -60,7 +113,13 @@ static void clks_tty_scroll_up(u32 tty_index) { clks_tty_fill_row(tty_index, clks_tty_rows - 1, ' '); if (tty_index == clks_tty_active_index) { - clks_tty_redraw_active(); + u32 col; + + clks_fb_scroll_up(clks_tty_cell_height, CLKS_TTY_BG); + + for (col = 0U; col < clks_tty_cols; col++) { + clks_tty_draw_cell(clks_tty_rows - 1U, col, clks_tty_cells[tty_index][clks_tty_rows - 1U][col]); + } } } @@ -121,6 +180,7 @@ void clks_tty_init(void) { clks_tty_active_index = 0; clks_tty_is_ready = CLKS_TRUE; + clks_tty_cursor_visible = CLKS_FALSE; clks_tty_redraw_active(); } @@ -133,12 +193,15 @@ void clks_tty_write_char(char ch) { return; } + clks_tty_hide_cursor(); + tty_index = clks_tty_active_index; row = clks_tty_cursor_row[tty_index]; col = clks_tty_cursor_col[tty_index]; if (ch == '\r') { clks_tty_cursor_col[tty_index] = 0; + clks_tty_draw_cursor(); return; } @@ -151,11 +214,13 @@ void clks_tty_write_char(char ch) { clks_tty_cursor_row[tty_index] = clks_tty_rows - 1; } + clks_tty_draw_cursor(); return; } if (ch == '\b') { if (col == 0U && row == 0U) { + clks_tty_draw_cursor(); return; } @@ -169,6 +234,7 @@ void clks_tty_write_char(char ch) { clks_tty_put_visible(tty_index, row, col, ' '); clks_tty_cursor_row[tty_index] = row; clks_tty_cursor_col[tty_index] = col; + clks_tty_draw_cursor(); return; } @@ -192,6 +258,8 @@ void clks_tty_write_char(char ch) { clks_tty_cursor_row[tty_index] = clks_tty_rows - 1; } } + + clks_tty_draw_cursor(); } void clks_tty_write(const char *text) { @@ -216,13 +284,16 @@ void clks_tty_switch(u32 tty_index) { return; } + clks_tty_hide_cursor(); clks_tty_active_index = tty_index; + clks_tty_cursor_visible = CLKS_FALSE; clks_tty_redraw_active(); } u32 clks_tty_active(void) { return clks_tty_active_index; } + u32 clks_tty_count(void) { return CLKS_TTY_COUNT; } diff --git a/clks/kernel/userland.c b/clks/kernel/userland.c index 6f2a9fb..6697079 100644 --- a/clks/kernel/userland.c +++ b/clks/kernel/userland.c @@ -9,6 +9,7 @@ static clks_bool clks_user_shell_ready = CLKS_FALSE; static clks_bool clks_user_shell_exec_requested_flag = CLKS_FALSE; +static clks_bool clks_user_shell_exec_enabled = CLKS_FALSE; static u64 clks_user_launch_attempt_count = 0ULL; static u64 clks_user_launch_success_count = 0ULL; static u64 clks_user_launch_fail_count = 0ULL; @@ -82,6 +83,7 @@ clks_bool clks_userland_init(void) { clks_user_shell_ready = CLKS_FALSE; clks_user_shell_exec_requested_flag = CLKS_FALSE; + clks_user_shell_exec_enabled = CLKS_FALSE; clks_user_launch_attempt_count = 0ULL; clks_user_launch_success_count = 0ULL; clks_user_launch_fail_count = 0ULL; @@ -103,12 +105,14 @@ clks_bool clks_userland_init(void) { return CLKS_FALSE; } - (void)clks_userland_request_shell_exec(); + clks_log(CLKS_LOG_INFO, "USER", "USER SHELL EXEC DISABLED (KERNEL SHELL MODE)"); return CLKS_TRUE; } void clks_userland_tick(u64 tick) { - if (clks_user_shell_ready == CLKS_FALSE || clks_user_shell_exec_requested_flag == CLKS_TRUE) { + if (clks_user_shell_exec_enabled == CLKS_FALSE || + clks_user_shell_ready == CLKS_FALSE || + clks_user_shell_exec_requested_flag == CLKS_TRUE) { return; } @@ -138,4 +142,4 @@ u64 clks_userland_launch_success(void) { u64 clks_userland_launch_failures(void) { return clks_user_launch_fail_count; -} +} \ No newline at end of file diff --git a/ramdisk/system/tty.psf b/ramdisk/system/tty.psf index 0a78e480d7c623ac96da0e29db7dee4bd1cac790..f59610e4a64dc9a85efa19b5c19fbb6bd001d3e6 100644 GIT binary patch literal 4100 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