From 937abc1f034c1a92a599b731df09aa3fd5f7f48e Mon Sep 17 00:00:00 2001 From: ryuukumar Date: Sun, 26 Apr 2026 09:21:47 +0530 Subject: [PATCH 01/29] Add union for console char type --- kernel/include/kernel/console.h | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/kernel/include/kernel/console.h b/kernel/include/kernel/console.h index 8e38c8ae..d264219f 100644 --- a/kernel/include/kernel/console.h +++ b/kernel/include/kernel/console.h @@ -6,6 +6,17 @@ #define TAB_WIDTH 8 +typedef union { + uint32_t raw; + struct __attribute__((packed)) { + uint8_t dirty : 1; + unsigned char character : 7; + uint8_t red; + uint8_t green; + uint8_t blue; + }; +} console_char_t; + void set_update_on_putch (bool); bool get_update_on_putch (void); void set_idx (size_t); From de120ef74a891d8334b7a18191d9e5937eaba625 Mon Sep 17 00:00:00 2001 From: ryuukumar Date: Fri, 15 May 2026 14:46:47 +0530 Subject: [PATCH 02/29] console -> oldconsole --- kernel/include/kclib/stdio.h | 2 +- kernel/include/kernel/{console.h => oldconsole.h} | 0 kernel/src/kclib/stdio.c | 2 +- kernel/src/kernel/entry.c | 2 +- kernel/src/kernel/fs/chardev/chardev.c | 2 +- kernel/src/kernel/{console.c => oldconsole.c} | 2 +- 6 files changed, 5 insertions(+), 5 deletions(-) rename kernel/include/kernel/{console.h => oldconsole.h} (100%) rename kernel/src/kernel/{console.c => oldconsole.c} (98%) diff --git a/kernel/include/kclib/stdio.h b/kernel/include/kclib/stdio.h index 8811d8f9..1f2fc495 100644 --- a/kernel/include/kclib/stdio.h +++ b/kernel/include/kclib/stdio.h @@ -1,6 +1,6 @@ #pragma once -#include +#include #include #include #include diff --git a/kernel/include/kernel/console.h b/kernel/include/kernel/oldconsole.h similarity index 100% rename from kernel/include/kernel/console.h rename to kernel/include/kernel/oldconsole.h diff --git a/kernel/src/kclib/stdio.c b/kernel/src/kclib/stdio.c index 5f0468f6..fda8b6e8 100644 --- a/kernel/src/kclib/stdio.c +++ b/kernel/src/kclib/stdio.c @@ -1,6 +1,6 @@ #include #include -#include +#include #include #include diff --git a/kernel/src/kernel/entry.c b/kernel/src/kernel/entry.c index 7fcf9fef..0a9b9643 100644 --- a/kernel/src/kernel/entry.c +++ b/kernel/src/kernel/entry.c @@ -1,7 +1,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/kernel/src/kernel/fs/chardev/chardev.c b/kernel/src/kernel/fs/chardev/chardev.c index 32db773b..a9027915 100644 --- a/kernel/src/kernel/fs/chardev/chardev.c +++ b/kernel/src/kernel/fs/chardev/chardev.c @@ -1,7 +1,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/kernel/src/kernel/console.c b/kernel/src/kernel/oldconsole.c similarity index 98% rename from kernel/src/kernel/console.c rename to kernel/src/kernel/oldconsole.c index f8ebebe3..fa8ecd1b 100644 --- a/kernel/src/kernel/console.c +++ b/kernel/src/kernel/oldconsole.c @@ -1,6 +1,6 @@ #include #include -#include +#include #include #include #include From 0ef55c443320e6b9db4aedf05a9e096c6dc36f37 Mon Sep 17 00:00:00 2001 From: ryuukumar Date: Fri, 15 May 2026 17:26:42 +0530 Subject: [PATCH 03/29] Format --- kernel/src/kernel/entry.c | 2 +- kernel/src/kernel/fs/chardev/chardev.c | 2 +- kernel/src/kernel/oldconsole.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/kernel/src/kernel/entry.c b/kernel/src/kernel/entry.c index 0a9b9643..b8b86dd6 100644 --- a/kernel/src/kernel/entry.c +++ b/kernel/src/kernel/entry.c @@ -1,7 +1,6 @@ #include #include #include -#include #include #include #include @@ -17,6 +16,7 @@ #include #include #include +#include #include #include #include diff --git a/kernel/src/kernel/fs/chardev/chardev.c b/kernel/src/kernel/fs/chardev/chardev.c index a9027915..ae22d796 100644 --- a/kernel/src/kernel/fs/chardev/chardev.c +++ b/kernel/src/kernel/fs/chardev/chardev.c @@ -1,11 +1,11 @@ #include #include #include -#include #include #include #include #include +#include #include #include diff --git a/kernel/src/kernel/oldconsole.c b/kernel/src/kernel/oldconsole.c index fa8ecd1b..b331dc54 100644 --- a/kernel/src/kernel/oldconsole.c +++ b/kernel/src/kernel/oldconsole.c @@ -1,8 +1,8 @@ #include #include -#include #include #include +#include #include #include From bf5c5a4580d32bc558290263bba9cd2c21b21c0a Mon Sep 17 00:00:00 2001 From: ryuukumar Date: Fri, 15 May 2026 17:26:55 +0530 Subject: [PATCH 04/29] Start implementing a console data structure --- kernel/include/kernel/con/con_ds.h | 51 +++++++++++++++++++ kernel/src/kernel/con/con_ds.c | 80 ++++++++++++++++++++++++++++++ 2 files changed, 131 insertions(+) create mode 100644 kernel/include/kernel/con/con_ds.h create mode 100644 kernel/src/kernel/con/con_ds.c diff --git a/kernel/include/kernel/con/con_ds.h b/kernel/include/kernel/con/con_ds.h new file mode 100644 index 00000000..96783d13 --- /dev/null +++ b/kernel/include/kernel/con/con_ds.h @@ -0,0 +1,51 @@ +#pragma once + +#include +#include +#include + +#define CON_IDX_X(idx) (idx & 0xFFFFFFFF) +#define CON_IDX_Y(idx) ((idx & (0xFFFFFFFF << 32)) >> 32) + +typedef uint64_t idx_t; + +typedef struct __attribute__ ((packed)) { + uint8_t red; + uint8_t green; + uint8_t blue; +} console_color_t; + +typedef struct __attribute__ ((packed)) { + unsigned char character; + console_color_t color; +} console_char_t; + +typedef struct __attribute__ ((packed)) { + console_char_t* chars; + size_t width; + uint8_t dirty; +} console_line_t; + +typedef struct __attribute__ ((packed)) { + varray* lines; + size_t count_lines; + size_t con_width, con_height; + idx_t idx; + console_color_t current_color; + size_t currline_offset_from_bottom; +} console_t; + +int console_create (console_t** console, size_t width, size_t height); +int console_delete (console_t** console); + +int console_putchar (console_t** console, unsigned char c); +int console_setcolor (console_t** console, uint8_t red, uint8_t green, uint8_t blue); +int console_goto (console_t** console, uint32_t x, uint32_t y); + +int console_scrollup (console_t** console, size_t howmuch); +int console_scrolldown (console_t** console, size_t howmuch); +int console_setbottomoffset (console_t** console, size_t howmuch); +int console_clearscrollback (console_t** console); + +idx_t console_getidx (console_t** console); +console_color_t console_getcolor (console_t** console); diff --git a/kernel/src/kernel/con/con_ds.c b/kernel/src/kernel/con/con_ds.c new file mode 100644 index 00000000..0a6280af --- /dev/null +++ b/kernel/src/kernel/con/con_ds.c @@ -0,0 +1,80 @@ +#include "utils/varray.h" +#include +#include +#include +#include + +int console_create (console_t** console, size_t width, size_t height) { + if (!console) return -EINVAL; + + console_t* new_console = kmalloc (sizeof (console)); + if (!new_console) return -ENOMEM; + + kmemset (new_console, 0, sizeof (console)); + new_console->lines = varray_create (width); + if (!new_console->lines) return -ENOMEM; + + new_console->con_width = width; + new_console->con_height = height; + + new_console->current_color.red = 0xFF; + new_console->current_color.green = 0xFF; + new_console->current_color.blue = 0xFF; + + new_console->currline_offset_from_bottom = height - 1; + + *console = new_console; + return 0; +} + +int console_delete (console_t** console) { + if (!console || !(*console)) return -EINVAL; + return -ENOSYS; +} + +int console_putchar (console_t** console, unsigned char c) { + (void)c; + if (!console || !(*console)) return -EINVAL; + return -ENOSYS; +} + +int console_setcolor (console_t** console, uint8_t red, uint8_t green, uint8_t blue) { + if (!console || !(*console)) return -EINVAL; + (*console)->current_color.red = red; + (*console)->current_color.red = green; + (*console)->current_color.red = blue; + return 0; +} + +int console_goto (console_t** console, uint32_t x, uint32_t y) { + if (!console || !(*console)) return -EINVAL; + (*console)->idx = ((uint64_t)x << 32) || (uint64_t)y; + return 0; +} + +int console_scrollup (console_t** console, size_t howmuch) { + (void)howmuch; + if (!console || !(*console)) return -EINVAL; + return -ENOSYS; +} + +int console_scrolldown (console_t** console, size_t howmuch) { + (void)howmuch; + if (!console || !(*console)) return -EINVAL; + return -ENOSYS; +} + +int console_setbottomoffset (console_t** console, size_t howmuch) { + if (!console || !(*console)) return -EINVAL; + (*console)->currline_offset_from_bottom = howmuch; + return 0; +} + +int console_clearscrollback (console_t** console) { + if (!console || !(*console)) return -EINVAL; + return -ENOSYS; +} + +idx_t console_getidx (console_t** console) { return (*console)->idx; } + +console_color_t console_getcolor (console_t** console) { return (*console)->current_color; } From b36af7001b3c5bcb40d857e1801c5a033bd6d72e Mon Sep 17 00:00:00 2001 From: ryuukumar Date: Fri, 15 May 2026 17:28:01 +0530 Subject: [PATCH 05/29] Remove old console_char_t and stub out con.h --- kernel/include/kernel/con/con.h | 17 +++++++++++++++++ kernel/include/kernel/oldconsole.h | 11 ----------- kernel/src/kernel/con/con.c | 11 +++++++++++ 3 files changed, 28 insertions(+), 11 deletions(-) create mode 100644 kernel/include/kernel/con/con.h create mode 100644 kernel/src/kernel/con/con.c diff --git a/kernel/include/kernel/con/con.h b/kernel/include/kernel/con/con.h new file mode 100644 index 00000000..3db88f2d --- /dev/null +++ b/kernel/include/kernel/con/con.h @@ -0,0 +1,17 @@ +#pragma once + +#include +#include +#include + +#ifdef TAB_WIDTH +#undef TAB_WIDTH +#endif + +typedef struct { + size_t lpad, rpad, tpad, bpad; +} pad_t; + +int add_char (unsigned char c); +void init_con (size_t screen_width, size_t screen_height, pad_t* con_padding, size_t char_spacing, + size_t line_padding, size_t font_multiplier); diff --git a/kernel/include/kernel/oldconsole.h b/kernel/include/kernel/oldconsole.h index d264219f..8e38c8ae 100644 --- a/kernel/include/kernel/oldconsole.h +++ b/kernel/include/kernel/oldconsole.h @@ -6,17 +6,6 @@ #define TAB_WIDTH 8 -typedef union { - uint32_t raw; - struct __attribute__((packed)) { - uint8_t dirty : 1; - unsigned char character : 7; - uint8_t red; - uint8_t green; - uint8_t blue; - }; -} console_char_t; - void set_update_on_putch (bool); bool get_update_on_putch (void); void set_idx (size_t); diff --git a/kernel/src/kernel/con/con.c b/kernel/src/kernel/con/con.c new file mode 100644 index 00000000..b75b92fc --- /dev/null +++ b/kernel/src/kernel/con/con.c @@ -0,0 +1,11 @@ +#include +#include + +static console_t* console = nullptr; + +int add_char (unsigned char c) {} + +void init_con (size_t screen_width, size_t screen_height, pad_t* con_padding, size_t char_spacing, + size_t line_padding, size_t font_multiplier) { + +}; From 95ab0c1c0443bcdbdfcc123a39c620080b52cd2e Mon Sep 17 00:00:00 2001 From: ryuukumar Date: Fri, 15 May 2026 21:04:52 +0530 Subject: [PATCH 06/29] Unstub some scroll functions --- kernel/include/kernel/con/con_ds.h | 2 +- kernel/src/kernel/con/con_ds.c | 20 ++++++++++++++------ 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/kernel/include/kernel/con/con_ds.h b/kernel/include/kernel/con/con_ds.h index 96783d13..d18b8348 100644 --- a/kernel/include/kernel/con/con_ds.h +++ b/kernel/include/kernel/con/con_ds.h @@ -5,7 +5,7 @@ #include #define CON_IDX_X(idx) (idx & 0xFFFFFFFF) -#define CON_IDX_Y(idx) ((idx & (0xFFFFFFFF << 32)) >> 32) +#define CON_IDX_Y(idx) ((idx & (0xFFFFFFFFull << 32)) >> 32) typedef uint64_t idx_t; diff --git a/kernel/src/kernel/con/con_ds.c b/kernel/src/kernel/con/con_ds.c index 0a6280af..9e22a5a2 100644 --- a/kernel/src/kernel/con/con_ds.c +++ b/kernel/src/kernel/con/con_ds.c @@ -4,6 +4,8 @@ #include #include +#define CON_SCROLLBACK_LIMIT 10000 + int console_create (console_t** console, size_t width, size_t height) { if (!console) return -EINVAL; @@ -11,7 +13,7 @@ int console_create (console_t** console, size_t width, size_t height) { if (!new_console) return -ENOMEM; kmemset (new_console, 0, sizeof (console)); - new_console->lines = varray_create (width); + new_console->lines = varray_create (height); if (!new_console->lines) return -ENOMEM; new_console->con_width = width; @@ -32,8 +34,14 @@ int console_delete (console_t** console) { return -ENOSYS; } +static console_char_t* console_resolve_chidx (console_t** console, idx_t idx) { + size_t lines_idx = varray_size((*console)->lines)-1 - (*console)->currline_offset_from_bottom + CON_IDX_Y(idx); + size_t char_idx = CON_IDX_X(idx); + + return nullptr; +} + int console_putchar (console_t** console, unsigned char c) { - (void)c; if (!console || !(*console)) return -EINVAL; return -ENOSYS; } @@ -53,15 +61,15 @@ int console_goto (console_t** console, uint32_t x, uint32_t y) { } int console_scrollup (console_t** console, size_t howmuch) { - (void)howmuch; if (!console || !(*console)) return -EINVAL; - return -ENOSYS; + (*console)->currline_offset_from_bottom -= howmuch; + return 0; } int console_scrolldown (console_t** console, size_t howmuch) { - (void)howmuch; if (!console || !(*console)) return -EINVAL; - return -ENOSYS; + (*console)->currline_offset_from_bottom += howmuch; + return 0; } int console_setbottomoffset (console_t** console, size_t howmuch) { From 9b712f9edf011e71e499ea073610fd8776c60436 Mon Sep 17 00:00:00 2001 From: ryuukumar Date: Fri, 15 May 2026 22:45:14 +0530 Subject: [PATCH 07/29] Adapt the console structure to deque --- kernel/include/kernel/con/con_ds.h | 15 +++--- kernel/src/kernel/con/con_ds.c | 86 +++++++++++++++++++++--------- 2 files changed, 68 insertions(+), 33 deletions(-) diff --git a/kernel/include/kernel/con/con_ds.h b/kernel/include/kernel/con/con_ds.h index d18b8348..1f810141 100644 --- a/kernel/include/kernel/con/con_ds.h +++ b/kernel/include/kernel/con/con_ds.h @@ -2,7 +2,7 @@ #include #include -#include +#include #define CON_IDX_X(idx) (idx & 0xFFFFFFFF) #define CON_IDX_Y(idx) ((idx & (0xFFFFFFFFull << 32)) >> 32) @@ -27,12 +27,12 @@ typedef struct __attribute__ ((packed)) { } console_line_t; typedef struct __attribute__ ((packed)) { - varray* lines; - size_t count_lines; - size_t con_width, con_height; - idx_t idx; - console_color_t current_color; - size_t currline_offset_from_bottom; + size_t width, height; + console_line_t** display; + deque* scrollback; + deque* scrollfront; + idx_t idx; + console_color_t current_color; } console_t; int console_create (console_t** console, size_t width, size_t height); @@ -44,7 +44,6 @@ int console_goto (console_t** console, uint32_t x, uint32_t y); int console_scrollup (console_t** console, size_t howmuch); int console_scrolldown (console_t** console, size_t howmuch); -int console_setbottomoffset (console_t** console, size_t howmuch); int console_clearscrollback (console_t** console); idx_t console_getidx (console_t** console); diff --git a/kernel/src/kernel/con/con_ds.c b/kernel/src/kernel/con/con_ds.c index 9e22a5a2..4464a710 100644 --- a/kernel/src/kernel/con/con_ds.c +++ b/kernel/src/kernel/con/con_ds.c @@ -1,31 +1,47 @@ -#include "utils/varray.h" +#include "utils/deque.h" #include #include #include #include +#include #define CON_SCROLLBACK_LIMIT 10000 int console_create (console_t** console, size_t width, size_t height) { if (!console) return -EINVAL; - console_t* new_console = kmalloc (sizeof (console)); + console_t* new_console = kmalloc (sizeof (console_t)); if (!new_console) return -ENOMEM; - kmemset (new_console, 0, sizeof (console)); - new_console->lines = varray_create (height); - if (!new_console->lines) return -ENOMEM; + kmemset (new_console, 0, sizeof (console_t)); - new_console->con_width = width; - new_console->con_height = height; + new_console->scrollback = deque_create (0); + new_console->scrollfront = deque_create (0); + if (!new_console->scrollback || !new_console->scrollfront) return -ENOMEM; + + new_console->display = kmalloc (height * sizeof (console_line_t*)); + if (!new_console->display) return -ENOMEM; + + for (size_t i = 0; i < height; i++) { + new_console->display[i] = kmalloc (sizeof (console_line_t)); + if (!new_console->display[i]) return -ENOMEM; + + new_console->display[i]->chars = kmalloc (width * sizeof (console_char_t)); + if (!new_console->display[i]->chars) return -ENOMEM; + + new_console->display[i]->dirty = 0; + new_console->display[i]->width = width; + } new_console->current_color.red = 0xFF; new_console->current_color.green = 0xFF; new_console->current_color.blue = 0xFF; - new_console->currline_offset_from_bottom = height - 1; + new_console->height = height; + new_console->width = width; *console = new_console; + return 0; } @@ -34,13 +50,6 @@ int console_delete (console_t** console) { return -ENOSYS; } -static console_char_t* console_resolve_chidx (console_t** console, idx_t idx) { - size_t lines_idx = varray_size((*console)->lines)-1 - (*console)->currline_offset_from_bottom + CON_IDX_Y(idx); - size_t char_idx = CON_IDX_X(idx); - - return nullptr; -} - int console_putchar (console_t** console, unsigned char c) { if (!console || !(*console)) return -EINVAL; return -ENOSYS; @@ -49,32 +58,59 @@ int console_putchar (console_t** console, unsigned char c) { int console_setcolor (console_t** console, uint8_t red, uint8_t green, uint8_t blue) { if (!console || !(*console)) return -EINVAL; (*console)->current_color.red = red; - (*console)->current_color.red = green; - (*console)->current_color.red = blue; + (*console)->current_color.green = green; + (*console)->current_color.blue = blue; return 0; } int console_goto (console_t** console, uint32_t x, uint32_t y) { if (!console || !(*console)) return -EINVAL; - (*console)->idx = ((uint64_t)x << 32) || (uint64_t)y; + (*console)->idx = ((uint64_t)y << 32) | (uint64_t)x; return 0; } int console_scrollup (console_t** console, size_t howmuch) { if (!console || !(*console)) return -EINVAL; - (*console)->currline_offset_from_bottom -= howmuch; + + for (size_t i = 0; i < howmuch; i++) { + console_line_t* popped = nullptr; + int error = deque_pop_front ((*console)->scrollback, (deque_elem*)&popped); + if (error == -INTERNAL_EEMPQ) + break; + else if (error != 0) + return error; + + error = deque_push_front ((*console)->scrollfront, + (deque_elem)(*console)->display[(*console)->height - 1]); + if (error) return error; + + for (size_t j = (*console)->height - 1; j > 0; j--) + (*console)->display[j] = (*console)->display[j - 1]; + (*console)->display[0] = popped; + } + return 0; } int console_scrolldown (console_t** console, size_t howmuch) { if (!console || !(*console)) return -EINVAL; - (*console)->currline_offset_from_bottom += howmuch; - return 0; -} -int console_setbottomoffset (console_t** console, size_t howmuch) { - if (!console || !(*console)) return -EINVAL; - (*console)->currline_offset_from_bottom = howmuch; + for (size_t i = 0; i < howmuch; i++) { + console_line_t* popped = nullptr; + int error = deque_pop_front ((*console)->scrollfront, (deque_elem*)&popped); + if (error == -INTERNAL_EEMPQ) + break; + else if (error != 0) + return error; + + error = deque_push_front ((*console)->scrollback, (deque_elem)(*console)->display[0]); + if (error) return error; + + for (size_t j = 0; j < (*console)->height - 1; j++) + (*console)->display[j] = (*console)->display[j + 1]; + (*console)->display[(*console)->height - 1] = popped; + } + return 0; } From 40240a41db13ae7a4bb6c348dd4ff4046a699e60 Mon Sep 17 00:00:00 2001 From: ryuukumar Date: Fri, 15 May 2026 23:16:22 +0530 Subject: [PATCH 08/29] Implement console_putchar and console_clearscrollback --- kernel/src/kernel/con/con_ds.c | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/kernel/src/kernel/con/con_ds.c b/kernel/src/kernel/con/con_ds.c index 4464a710..ab6a13bd 100644 --- a/kernel/src/kernel/con/con_ds.c +++ b/kernel/src/kernel/con/con_ds.c @@ -52,7 +52,12 @@ int console_delete (console_t** console) { int console_putchar (console_t** console, unsigned char c) { if (!console || !(*console)) return -EINVAL; - return -ENOSYS; + + console_char_t* target = &(*console)->display[CON_IDX_Y((*console)->idx)]->chars[CON_IDX_X((*console)->idx)]; + target->character = c; + target->color = (*console)->current_color; + + return 0; } int console_setcolor (console_t** console, uint8_t red, uint8_t green, uint8_t blue) { @@ -116,7 +121,19 @@ int console_scrolldown (console_t** console, size_t howmuch) { int console_clearscrollback (console_t** console) { if (!console || !(*console)) return -EINVAL; - return -ENOSYS; + + console_line_t* popped = nullptr; + do { + int error = deque_pop_front ((*console)->scrollback, (deque_elem*)&popped); + if (error == -INTERNAL_EEMPQ) + break; + else if (error != 0) + return error; + kfree(popped->chars); + kfree(popped); + } while (1); + + return 0; } idx_t console_getidx (console_t** console) { return (*console)->idx; } From dc6c7843e5731ba013c1a3c349a60534120dcdac Mon Sep 17 00:00:00 2001 From: ryuukumar Date: Fri, 15 May 2026 23:32:26 +0530 Subject: [PATCH 09/29] Add console_parameters_t + write_to_gfx --- kernel/include/kernel/con/con_ds.h | 29 +++++++++++------ kernel/src/kernel/con/con_ds.c | 51 ++++++++++++++++++++---------- 2 files changed, 54 insertions(+), 26 deletions(-) diff --git a/kernel/include/kernel/con/con_ds.h b/kernel/include/kernel/con/con_ds.h index 1f810141..8c85b563 100644 --- a/kernel/include/kernel/con/con_ds.h +++ b/kernel/include/kernel/con/con_ds.h @@ -4,8 +4,9 @@ #include #include -#define CON_IDX_X(idx) (idx & 0xFFFFFFFF) -#define CON_IDX_Y(idx) ((idx & (0xFFFFFFFFull << 32)) >> 32) +#define CON_IDX_X(idx) (idx & 0xFFFFFFFF) +#define CON_IDX_Y(idx) ((idx & (0xFFFFFFFFull << 32)) >> 32) +#define CON_COL_RGB(color) ((color.red << 16) & (color.green << 8) & color.blue) typedef uint64_t idx_t; @@ -26,16 +27,24 @@ typedef struct __attribute__ ((packed)) { uint8_t dirty; } console_line_t; +typedef struct { + size_t glyph_height, glyph_width; + size_t line_spacing, char_spacing; + size_t xpad, ypad; + size_t width, height; + size_t font_size; +} console_parameters_t; + typedef struct __attribute__ ((packed)) { - size_t width, height; - console_line_t** display; - deque* scrollback; - deque* scrollfront; - idx_t idx; - console_color_t current_color; + console_line_t** display; + deque* scrollback; + deque* scrollfront; + idx_t idx; + console_color_t current_color; + console_parameters_t params; } console_t; -int console_create (console_t** console, size_t width, size_t height); +int console_create (console_t** console, console_parameters_t* params); int console_delete (console_t** console); int console_putchar (console_t** console, unsigned char c); @@ -48,3 +57,5 @@ int console_clearscrollback (console_t** console); idx_t console_getidx (console_t** console); console_color_t console_getcolor (console_t** console); + +int write_to_gfx (console_t** console); diff --git a/kernel/src/kernel/con/con_ds.c b/kernel/src/kernel/con/con_ds.c index ab6a13bd..e8d0548e 100644 --- a/kernel/src/kernel/con/con_ds.c +++ b/kernel/src/kernel/con/con_ds.c @@ -1,14 +1,15 @@ -#include "utils/deque.h" #include #include #include +#include +#include #include #include #define CON_SCROLLBACK_LIMIT 10000 -int console_create (console_t** console, size_t width, size_t height) { - if (!console) return -EINVAL; +int console_create (console_t** console, console_parameters_t* params) { + if (!console || !params) return -EINVAL; console_t* new_console = kmalloc (sizeof (console_t)); if (!new_console) return -ENOMEM; @@ -19,26 +20,24 @@ int console_create (console_t** console, size_t width, size_t height) { new_console->scrollfront = deque_create (0); if (!new_console->scrollback || !new_console->scrollfront) return -ENOMEM; - new_console->display = kmalloc (height * sizeof (console_line_t*)); + new_console->display = kmalloc (params->height * sizeof (console_line_t*)); if (!new_console->display) return -ENOMEM; - for (size_t i = 0; i < height; i++) { + for (size_t i = 0; i < params->height; i++) { new_console->display[i] = kmalloc (sizeof (console_line_t)); if (!new_console->display[i]) return -ENOMEM; - new_console->display[i]->chars = kmalloc (width * sizeof (console_char_t)); + new_console->display[i]->chars = kmalloc (params->width * sizeof (console_char_t)); if (!new_console->display[i]->chars) return -ENOMEM; new_console->display[i]->dirty = 0; - new_console->display[i]->width = width; + new_console->display[i]->width = params->width; } new_console->current_color.red = 0xFF; new_console->current_color.green = 0xFF; new_console->current_color.blue = 0xFF; - - new_console->height = height; - new_console->width = width; + new_console->params = *params; *console = new_console; @@ -53,7 +52,8 @@ int console_delete (console_t** console) { int console_putchar (console_t** console, unsigned char c) { if (!console || !(*console)) return -EINVAL; - console_char_t* target = &(*console)->display[CON_IDX_Y((*console)->idx)]->chars[CON_IDX_X((*console)->idx)]; + console_char_t* target = + &(*console)->display[CON_IDX_Y ((*console)->idx)]->chars[CON_IDX_X ((*console)->idx)]; target->character = c; target->color = (*console)->current_color; @@ -86,10 +86,10 @@ int console_scrollup (console_t** console, size_t howmuch) { return error; error = deque_push_front ((*console)->scrollfront, - (deque_elem)(*console)->display[(*console)->height - 1]); + (deque_elem)(*console)->display[(*console)->params.height - 1]); if (error) return error; - for (size_t j = (*console)->height - 1; j > 0; j--) + for (size_t j = (*console)->params.height - 1; j > 0; j--) (*console)->display[j] = (*console)->display[j - 1]; (*console)->display[0] = popped; } @@ -111,9 +111,9 @@ int console_scrolldown (console_t** console, size_t howmuch) { error = deque_push_front ((*console)->scrollback, (deque_elem)(*console)->display[0]); if (error) return error; - for (size_t j = 0; j < (*console)->height - 1; j++) + for (size_t j = 0; j < (*console)->params.height - 1; j++) (*console)->display[j] = (*console)->display[j + 1]; - (*console)->display[(*console)->height - 1] = popped; + (*console)->display[(*console)->params.height - 1] = popped; } return 0; @@ -129,8 +129,8 @@ int console_clearscrollback (console_t** console) { break; else if (error != 0) return error; - kfree(popped->chars); - kfree(popped); + kfree (popped->chars); + kfree (popped); } while (1); return 0; @@ -139,3 +139,20 @@ int console_clearscrollback (console_t** console) { idx_t console_getidx (console_t** console) { return (*console)->idx; } console_color_t console_getcolor (console_t** console) { return (*console)->current_color; } + +int write_to_gfx (console_t** console) { + if (!console || !(*console)) return -EINVAL; + + console_parameters_t* params = &(*console)->params; + for (size_t i = 0; i < params->height; i++) { + if (!(*console)->display[i]->dirty) continue; + console_char_t* target = (*console)->display[i]->chars; + + for (size_t j = 0; j < params->width; j++) { + renderGlyph (glyph (target[j].character), 8, 5, + params->xpad + (params->font_size * j * (5 + params->char_spacing)), + params->ypad + (params->font_size * i * (8 + params->line_spacing)), + params->font_size, CON_COL_RGB (target[j].color)); + } + } +} From c150b0b362a04e84e018a6abb51a85faa1de3775 Mon Sep 17 00:00:00 2001 From: ryuukumar Date: Fri, 15 May 2026 23:33:04 +0530 Subject: [PATCH 10/29] Return 0 --- kernel/src/kernel/con/con_ds.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/kernel/src/kernel/con/con_ds.c b/kernel/src/kernel/con/con_ds.c index e8d0548e..9a49ae08 100644 --- a/kernel/src/kernel/con/con_ds.c +++ b/kernel/src/kernel/con/con_ds.c @@ -155,4 +155,6 @@ int write_to_gfx (console_t** console) { params->font_size, CON_COL_RGB (target[j].color)); } } + + return 0; } From 7be7f9d7971903e8d8b87533d8590343d4567c00 Mon Sep 17 00:00:00 2001 From: ryuukumar Date: Fri, 15 May 2026 23:36:08 +0530 Subject: [PATCH 11/29] Set dirty flag where appropriate --- kernel/src/kernel/con/con_ds.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/kernel/src/kernel/con/con_ds.c b/kernel/src/kernel/con/con_ds.c index 9a49ae08..bb21b495 100644 --- a/kernel/src/kernel/con/con_ds.c +++ b/kernel/src/kernel/con/con_ds.c @@ -56,6 +56,7 @@ int console_putchar (console_t** console, unsigned char c) { &(*console)->display[CON_IDX_Y ((*console)->idx)]->chars[CON_IDX_X ((*console)->idx)]; target->character = c; target->color = (*console)->current_color; + (*console)->display[CON_IDX_Y ((*console)->idx)]->dirty = 1; return 0; } @@ -89,9 +90,13 @@ int console_scrollup (console_t** console, size_t howmuch) { (deque_elem)(*console)->display[(*console)->params.height - 1]); if (error) return error; - for (size_t j = (*console)->params.height - 1; j > 0; j--) + for (size_t j = (*console)->params.height - 1; j > 0; j--) { (*console)->display[j] = (*console)->display[j - 1]; + (*console)->display[j]->dirty = 1; + } + (*console)->display[0] = popped; + (*console)->display[0]->dirty = 1; } return 0; @@ -111,9 +116,13 @@ int console_scrolldown (console_t** console, size_t howmuch) { error = deque_push_front ((*console)->scrollback, (deque_elem)(*console)->display[0]); if (error) return error; - for (size_t j = 0; j < (*console)->params.height - 1; j++) + for (size_t j = 0; j < (*console)->params.height - 1; j++) { (*console)->display[j] = (*console)->display[j + 1]; + (*console)->display[j]->dirty = 1; + } + (*console)->display[(*console)->params.height - 1] = popped; + (*console)->display[(*console)->params.height - 1]->dirty = 1; } return 0; @@ -154,6 +163,8 @@ int write_to_gfx (console_t** console) { params->ypad + (params->font_size * i * (8 + params->line_spacing)), params->font_size, CON_COL_RGB (target[j].color)); } + + (*console)->display[i]->dirty = 0; } return 0; From 147e694ee0a27aebf6a1c25c5de88ead99154ea6 Mon Sep 17 00:00:00 2001 From: ryuukumar Date: Fri, 15 May 2026 23:47:25 +0530 Subject: [PATCH 12/29] If index exceeds printable area, expand it --- kernel/src/kernel/con/con_ds.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/kernel/src/kernel/con/con_ds.c b/kernel/src/kernel/con/con_ds.c index bb21b495..164fb255 100644 --- a/kernel/src/kernel/con/con_ds.c +++ b/kernel/src/kernel/con/con_ds.c @@ -5,6 +5,7 @@ #include #include #include +#include #define CON_SCROLLBACK_LIMIT 10000 @@ -58,6 +59,23 @@ int console_putchar (console_t** console, unsigned char c) { target->color = (*console)->current_color; (*console)->display[CON_IDX_Y ((*console)->idx)]->dirty = 1; + (*console)->idx++; + if ((*console)->idx > (*console)->params.width * (*console)->params.height) { + console_line_t* new_line = kmalloc (sizeof (console_line_t)); + if (!new_line) return -ENOMEM; + + new_line->chars = kmalloc ((*console)->params.width * sizeof (console_char_t)); + if (!new_line->chars) return -ENOMEM; + + new_line->dirty = 0; + new_line->width = (*console)->params.width; + + int error = deque_push_front ((*console)->scrollfront, (deque_elem)new_line); + if (error) return error; + + console_scrolldown (console, 1); + } + return 0; } From 9be21c4abd8e924b516b5b651c5ce54378c7a695 Mon Sep 17 00:00:00 2001 From: ryuukumar Date: Fri, 15 May 2026 23:52:51 +0530 Subject: [PATCH 13/29] Enforce scrollback limit and always print on newest line --- kernel/src/kernel/con/con_ds.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/kernel/src/kernel/con/con_ds.c b/kernel/src/kernel/con/con_ds.c index 164fb255..9f406dc2 100644 --- a/kernel/src/kernel/con/con_ds.c +++ b/kernel/src/kernel/con/con_ds.c @@ -53,6 +53,9 @@ int console_delete (console_t** console) { int console_putchar (console_t** console, unsigned char c) { if (!console || !(*console)) return -EINVAL; + // clear the scrollfront so we are always printing on the newest line + console_scrolldown (console, deque_size ((*console)->scrollfront)); + console_char_t* target = &(*console)->display[CON_IDX_Y ((*console)->idx)]->chars[CON_IDX_X ((*console)->idx)]; target->character = c; @@ -60,7 +63,7 @@ int console_putchar (console_t** console, unsigned char c) { (*console)->display[CON_IDX_Y ((*console)->idx)]->dirty = 1; (*console)->idx++; - if ((*console)->idx > (*console)->params.width * (*console)->params.height) { + if ((*console)->idx > (*console)->params.width * (*console)->params.height) { console_line_t* new_line = kmalloc (sizeof (console_line_t)); if (!new_line) return -ENOMEM; @@ -74,6 +77,16 @@ int console_putchar (console_t** console, unsigned char c) { if (error) return error; console_scrolldown (console, 1); + (*console)->idx -= (*console)->params.width; + } + + while (deque_size ((*console)->scrollback) > CON_SCROLLBACK_LIMIT) { + deque_elem* buf = nullptr; + int error = deque_pop_back ((*console)->scrollback, buf); + if (error == -INTERNAL_EEMPQ) + break; + else if (error != 0) + return error; } return 0; From 9392d0cc9ad607e6ba2fdf8ba086af4b02c86ace Mon Sep 17 00:00:00 2001 From: ryuukumar Date: Sat, 16 May 2026 00:12:27 +0530 Subject: [PATCH 14/29] Add comments + handle \n --- kernel/src/kernel/con/con_ds.c | 100 +++++++++++++++++++++++++++++++-- 1 file changed, 94 insertions(+), 6 deletions(-) diff --git a/kernel/src/kernel/con/con_ds.c b/kernel/src/kernel/con/con_ds.c index 9f406dc2..c1a02674 100644 --- a/kernel/src/kernel/con/con_ds.c +++ b/kernel/src/kernel/con/con_ds.c @@ -9,6 +9,12 @@ #define CON_SCROLLBACK_LIMIT 10000 +/*! + * Allocate and initialise a new console object. + * @param console pointer to console_t* which will hold the reference to created console + * @param params initialisation parameters for the console + * @return 0 if successful, else -EINVAL or -ENOMEM + */ int console_create (console_t** console, console_parameters_t* params) { if (!console || !params) return -EINVAL; @@ -45,24 +51,50 @@ int console_create (console_t** console, console_parameters_t* params) { return 0; } +/*! + * Deallocate an existing console object. + * @param console pointer to console_t* which holds the reference to console + * @return 0 if successful, else -EINVAL + */ int console_delete (console_t** console) { if (!console || !(*console)) return -EINVAL; return -ENOSYS; } +/*! + * Write a character at the current cursor position. Increments idx to the sequentially next value. + * + * In the case that character \n is supplied, no update is made to actual console charaters, instead + * idx is directly set to width * height + 1, potentially falling through to the following case. + * This is the canonical way of adding new lines to the console. + * + * In the case that after incrementing, the condition idx >= width * height holds true, a new line + * is added at the bottom and the console is scrolled to accomodate. In the case that after addition + * of a new line, the scrollback exceeds CON_SCROLLBACK_LIMIT, the oldest line is freed. + * + * This function does not call write_to_gfx. + * + * @param console pointer to console_t* which holds the reference to console + * @param c character to put at index + * @return 0 if successful, else -EINVAL, -ENOMEM or other errors + */ int console_putchar (console_t** console, unsigned char c) { if (!console || !(*console)) return -EINVAL; // clear the scrollfront so we are always printing on the newest line console_scrolldown (console, deque_size ((*console)->scrollfront)); - console_char_t* target = - &(*console)->display[CON_IDX_Y ((*console)->idx)]->chars[CON_IDX_X ((*console)->idx)]; - target->character = c; - target->color = (*console)->current_color; - (*console)->display[CON_IDX_Y ((*console)->idx)]->dirty = 1; + if (c == '\n') { + (*console)->idx = (*console)->params.width * ((*console)->params.height + 1); + } else { + console_char_t* target = + &(*console)->display[CON_IDX_Y ((*console)->idx)]->chars[CON_IDX_X ((*console)->idx)]; + target->character = c; + target->color = (*console)->current_color; + (*console)->display[CON_IDX_Y ((*console)->idx)]->dirty = 1; + (*console)->idx++; + } - (*console)->idx++; if ((*console)->idx > (*console)->params.width * (*console)->params.height) { console_line_t* new_line = kmalloc (sizeof (console_line_t)); if (!new_line) return -ENOMEM; @@ -92,6 +124,14 @@ int console_putchar (console_t** console, unsigned char c) { return 0; } +/*! + * Set the color that will be used by putchar for following characters. + * @param console pointer to console_t* which holds the reference to console + * @param red 8-bit value for red channel + * @param green 8-bit value for green channel + * @param blue 8-but value for blue channel + * @return 0 if successful, else -EINVAL + */ int console_setcolor (console_t** console, uint8_t red, uint8_t green, uint8_t blue) { if (!console || !(*console)) return -EINVAL; (*console)->current_color.red = red; @@ -100,12 +140,29 @@ int console_setcolor (console_t** console, uint8_t red, uint8_t green, uint8_t b return 0; } +/*! + * Move the cursor to another position. + * @param console pointer to console_t* which holds the reference to console + * @param x x-index to seek (left-right) + * @param y y-index to seek (top-down) + * @return 0 if successful, else -EINVAL + */ int console_goto (console_t** console, uint32_t x, uint32_t y) { if (!console || !(*console)) return -EINVAL; (*console)->idx = ((uint64_t)y << 32) | (uint64_t)x; return 0; } +/*! + * Scroll the whole console to reveal a line from the scrollback deque. + * + * If there are fewer lines in the scrollback than requested by the howmuch parameter, no new lines + * will be created and scrolling will terminate once the scrollback deque is empty. + * + * @param console pointer to console_t* which holds the reference to console + * @param howmuch how many lines to scroll + * @return 0 if successful, else -EINVAL or other errors + */ int console_scrollup (console_t** console, size_t howmuch) { if (!console || !(*console)) return -EINVAL; @@ -133,6 +190,16 @@ int console_scrollup (console_t** console, size_t howmuch) { return 0; } +/*! + * Scroll the whole console to reveal a line from the scrollfront deque. + * + * If there are fewer lines in the scrollfront than requested by the howmuch parameter, no new lines + * will be created and scrolling will terminate once the scrollfront deque is empty. + * + * @param console pointer to console_t* which holds the reference to console + * @param howmuch how many lines to scroll + * @return 0 if successful, else -EINVAL or other errors + */ int console_scrolldown (console_t** console, size_t howmuch) { if (!console || !(*console)) return -EINVAL; @@ -159,6 +226,11 @@ int console_scrolldown (console_t** console, size_t howmuch) { return 0; } +/*! + * Free the scrollback deque. + * @param console pointer to console_t* which holds the reference to console + * @return 0 if successful, else -EINVAL or other errors + */ int console_clearscrollback (console_t** console) { if (!console || !(*console)) return -EINVAL; @@ -176,10 +248,26 @@ int console_clearscrollback (console_t** console) { return 0; } +/*! + * Get the position of the cursor. Behavior undefined if console parameter is invalid + * @param console pointer to console_t* which holds the reference to console + * @return index + */ idx_t console_getidx (console_t** console) { return (*console)->idx; } +/*! + * Get the color that will be used when printing the following characters. Behavior undefined if + * console parameter is invalid + * @param console pointer to console_t* which holds the reference to console + * @return color + */ console_color_t console_getcolor (console_t** console) { return (*console)->current_color; } +/*! + * Update the screenbuffer to match the contents of the console structure's internal display. + * @param console pointer to console_t* which holds the reference to console + * @return 0 if successful, else -EINVAL + */ int write_to_gfx (console_t** console) { if (!console || !(*console)) return -EINVAL; From 5c5858b94c03652ce3a92ddfedb5ebffd4266648 Mon Sep 17 00:00:00 2001 From: ryuukumar Date: Sat, 16 May 2026 00:16:52 +0530 Subject: [PATCH 15/29] Implement console_delete --- kernel/src/kernel/con/con_ds.c | 32 +++++++++++++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/kernel/src/kernel/con/con_ds.c b/kernel/src/kernel/con/con_ds.c index c1a02674..d13fb435 100644 --- a/kernel/src/kernel/con/con_ds.c +++ b/kernel/src/kernel/con/con_ds.c @@ -58,7 +58,37 @@ int console_create (console_t** console, console_parameters_t* params) { */ int console_delete (console_t** console) { if (!console || !(*console)) return -EINVAL; - return -ENOSYS; + + while (deque_size ((*console)->scrollback)) { + console_line_t* popped = nullptr; + int error = deque_pop_front ((*console)->scrollback, (deque_elem*)&popped); + if (error) break; + + kfree (popped->chars); + kfree (popped); + } + + while (deque_size ((*console)->scrollfront)) { + console_line_t* popped = nullptr; + int error = deque_pop_front ((*console)->scrollfront, (deque_elem*)&popped); + if (error) break; + + kfree (popped->chars); + kfree (popped); + } + + deque_destroy ((*console)->scrollback); + deque_destroy ((*console)->scrollfront); + + for (size_t i = 0; i < (*console)->params.height; i++) { + kfree ((*console)->display[i]->chars); + kfree ((*console)->display[i]); + } + + kfree ((*console)->display); + kfree (*console); + + return 0; } /*! From 3891dfa6d752dd1a86d0b0cd268a0684c9f66f39 Mon Sep 17 00:00:00 2001 From: ryuukumar Date: Sat, 16 May 2026 00:33:26 +0530 Subject: [PATCH 16/29] Bug fixes --- kernel/include/kernel/con/con_ds.h | 3 ++- kernel/src/kernel/con/con_ds.c | 31 +++++++++++++++++++++++------- 2 files changed, 26 insertions(+), 8 deletions(-) diff --git a/kernel/include/kernel/con/con_ds.h b/kernel/include/kernel/con/con_ds.h index 8c85b563..2cb1a74a 100644 --- a/kernel/include/kernel/con/con_ds.h +++ b/kernel/include/kernel/con/con_ds.h @@ -4,9 +4,10 @@ #include #include +#define CON_IDX_GEN(x, y) (((uint64_t)(y) << 32) | (x)) #define CON_IDX_X(idx) (idx & 0xFFFFFFFF) #define CON_IDX_Y(idx) ((idx & (0xFFFFFFFFull << 32)) >> 32) -#define CON_COL_RGB(color) ((color.red << 16) & (color.green << 8) & color.blue) +#define CON_COL_RGB(color) ((color.red << 16) | (color.green << 8) | color.blue) typedef uint64_t idx_t; diff --git a/kernel/src/kernel/con/con_ds.c b/kernel/src/kernel/con/con_ds.c index d13fb435..876bcca1 100644 --- a/kernel/src/kernel/con/con_ds.c +++ b/kernel/src/kernel/con/con_ds.c @@ -9,6 +9,17 @@ #define CON_SCROLLBACK_LIMIT 10000 +/*! + * Increment idx_t index. + * @param idx index to be incremented + * @param width width of the console + * @return incremented idx_t index + */ +static inline idx_t increment_idx (idx_t idx, size_t width) { + return CON_IDX_GEN (CON_IDX_X (idx) == width - 1 ? 0 : CON_IDX_X (idx) + 1, + CON_IDX_Y (idx) + (CON_IDX_X (idx) == width - 1)); +} + /*! * Allocate and initialise a new console object. * @param console pointer to console_t* which will hold the reference to created console @@ -36,6 +47,7 @@ int console_create (console_t** console, console_parameters_t* params) { new_console->display[i]->chars = kmalloc (params->width * sizeof (console_char_t)); if (!new_console->display[i]->chars) return -ENOMEM; + kmemset (new_console->display[i]->chars, 0, params->width * sizeof (console_char_t)); new_console->display[i]->dirty = 0; new_console->display[i]->width = params->width; @@ -87,6 +99,7 @@ int console_delete (console_t** console) { kfree ((*console)->display); kfree (*console); + *console = nullptr; return 0; } @@ -115,17 +128,17 @@ int console_putchar (console_t** console, unsigned char c) { console_scrolldown (console, deque_size ((*console)->scrollfront)); if (c == '\n') { - (*console)->idx = (*console)->params.width * ((*console)->params.height + 1); + (*console)->idx = CON_IDX_GEN (0, (*console)->params.height + 1); } else { console_char_t* target = &(*console)->display[CON_IDX_Y ((*console)->idx)]->chars[CON_IDX_X ((*console)->idx)]; target->character = c; target->color = (*console)->current_color; (*console)->display[CON_IDX_Y ((*console)->idx)]->dirty = 1; - (*console)->idx++; + (*console)->idx = increment_idx ((*console)->idx, (*console)->params.width); } - if ((*console)->idx > (*console)->params.width * (*console)->params.height) { + while (CON_IDX_Y ((*console)->idx) >= (*console)->params.height) { console_line_t* new_line = kmalloc (sizeof (console_line_t)); if (!new_line) return -ENOMEM; @@ -139,16 +152,20 @@ int console_putchar (console_t** console, unsigned char c) { if (error) return error; console_scrolldown (console, 1); - (*console)->idx -= (*console)->params.width; + (*console)->idx = + CON_IDX_GEN (CON_IDX_X ((*console)->idx), CON_IDX_Y ((*console)->idx) - 1); } while (deque_size ((*console)->scrollback) > CON_SCROLLBACK_LIMIT) { - deque_elem* buf = nullptr; - int error = deque_pop_back ((*console)->scrollback, buf); + console_line_t* buf = nullptr; + int error = deque_pop_back ((*console)->scrollback, (deque_elem*)&buf); if (error == -INTERNAL_EEMPQ) break; else if (error != 0) return error; + + kfree (buf->chars); + kfree (buf); } return 0; @@ -179,7 +196,7 @@ int console_setcolor (console_t** console, uint8_t red, uint8_t green, uint8_t b */ int console_goto (console_t** console, uint32_t x, uint32_t y) { if (!console || !(*console)) return -EINVAL; - (*console)->idx = ((uint64_t)y << 32) | (uint64_t)x; + (*console)->idx = CON_IDX_GEN (x, y); return 0; } From 4c9a7aed1c35d3a96cbfc63bf5c0160cba657250 Mon Sep 17 00:00:00 2001 From: ryuukumar Date: Sat, 16 May 2026 00:41:14 +0530 Subject: [PATCH 17/29] Bugfixes + update comment to describe behavior accurately --- kernel/src/kernel/con/con_ds.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/kernel/src/kernel/con/con_ds.c b/kernel/src/kernel/con/con_ds.c index 876bcca1..b6bf4939 100644 --- a/kernel/src/kernel/con/con_ds.c +++ b/kernel/src/kernel/con/con_ds.c @@ -108,12 +108,13 @@ int console_delete (console_t** console) { * Write a character at the current cursor position. Increments idx to the sequentially next value. * * In the case that character \n is supplied, no update is made to actual console charaters, instead - * idx is directly set to width * height + 1, potentially falling through to the following case. - * This is the canonical way of adding new lines to the console. + * idx is directly set to (0, height), potentially falling through to the following case. This is + * the canonical way of adding new lines to the console. * - * In the case that after incrementing, the condition idx >= width * height holds true, a new line - * is added at the bottom and the console is scrolled to accomodate. In the case that after addition - * of a new line, the scrollback exceeds CON_SCROLLBACK_LIMIT, the oldest line is freed. + * In the case that after incrementing, the condition idx.y >= height holds true, new lines are + * added at the bottom and the console is scrolled to accomodate until the condition is no longer + * true. In the case that after addition of a new line, the scrollback exceeds CON_SCROLLBACK_LIMIT, + * the oldest line is freed until the condition is no longer true. * * This function does not call write_to_gfx. * @@ -128,7 +129,7 @@ int console_putchar (console_t** console, unsigned char c) { console_scrolldown (console, deque_size ((*console)->scrollfront)); if (c == '\n') { - (*console)->idx = CON_IDX_GEN (0, (*console)->params.height + 1); + (*console)->idx = CON_IDX_GEN (0, (*console)->params.height); } else { console_char_t* target = &(*console)->display[CON_IDX_Y ((*console)->idx)]->chars[CON_IDX_X ((*console)->idx)]; @@ -144,6 +145,7 @@ int console_putchar (console_t** console, unsigned char c) { new_line->chars = kmalloc ((*console)->params.width * sizeof (console_char_t)); if (!new_line->chars) return -ENOMEM; + kmemset (new_line->chars, 0, (*console)->params.width * sizeof (console_char_t)); new_line->dirty = 0; new_line->width = (*console)->params.width; From fb71246ac3ce72e36b5a844fe50cbdc48c10c486 Mon Sep 17 00:00:00 2001 From: ryuukumar Date: Sat, 16 May 2026 00:48:36 +0530 Subject: [PATCH 18/29] Update init_con --- kernel/include/kernel/con/con.h | 8 ++------ kernel/src/kernel/con/con.c | 14 ++++++++++++-- 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/kernel/include/kernel/con/con.h b/kernel/include/kernel/con/con.h index 3db88f2d..3bd57411 100644 --- a/kernel/include/kernel/con/con.h +++ b/kernel/include/kernel/con/con.h @@ -8,10 +8,6 @@ #undef TAB_WIDTH #endif -typedef struct { - size_t lpad, rpad, tpad, bpad; -} pad_t; - int add_char (unsigned char c); -void init_con (size_t screen_width, size_t screen_height, pad_t* con_padding, size_t char_spacing, - size_t line_padding, size_t font_multiplier); +void init_con (size_t screen_width, size_t screen_height, size_t x_padding, size_t y_padding, + size_t char_spacing, size_t line_padding, size_t font_multiplier); diff --git a/kernel/src/kernel/con/con.c b/kernel/src/kernel/con/con.c index b75b92fc..e85843ce 100644 --- a/kernel/src/kernel/con/con.c +++ b/kernel/src/kernel/con/con.c @@ -5,7 +5,17 @@ static console_t* console = nullptr; int add_char (unsigned char c) {} -void init_con (size_t screen_width, size_t screen_height, pad_t* con_padding, size_t char_spacing, - size_t line_padding, size_t font_multiplier) { +void init_con (size_t screen_width, size_t screen_height, size_t x_padding, size_t y_padding, + size_t char_spacing, size_t line_padding, size_t font_multiplier) { + console_parameters_t params = {.glyph_height = 8, + .glyph_width = 5, + .line_spacing = line_padding, + .char_spacing = char_spacing, + .xpad = x_padding, + .ypad = y_padding, + .width = screen_width, + .height = screen_height, + .font_size = font_multiplier}; + console_create(&console, ¶ms); }; From 272f7e150cb187b6dd3860c6df1de07ab578ab4c Mon Sep 17 00:00:00 2001 From: ryuukumar Date: Sat, 16 May 2026 10:35:03 +0530 Subject: [PATCH 19/29] Substitute whatever possible --- kernel/include/kclib/stdio.h | 2 -- kernel/src/kclib/stdio.c | 9 ++++----- kernel/src/kernel/con/con.c | 27 +++++++++++++++----------- kernel/src/kernel/con/con_ds.c | 2 +- kernel/src/kernel/entry.c | 16 +++++++-------- kernel/src/kernel/fs/chardev/chardev.c | 20 +++++++++---------- 6 files changed, 39 insertions(+), 37 deletions(-) diff --git a/kernel/include/kclib/stdio.h b/kernel/include/kclib/stdio.h index 1f2fc495..102d0029 100644 --- a/kernel/include/kclib/stdio.h +++ b/kernel/include/kclib/stdio.h @@ -1,8 +1,6 @@ #pragma once -#include #include -#include #include #include diff --git a/kernel/src/kclib/stdio.c b/kernel/src/kclib/stdio.c index fda8b6e8..b5f7012b 100644 --- a/kernel/src/kclib/stdio.c +++ b/kernel/src/kclib/stdio.c @@ -1,6 +1,6 @@ #include #include -#include +#include #include #include @@ -164,10 +164,9 @@ static void kvsprintf (char* buf, const char* fmt, va_list* list) { buf[kvsprintf_idx] = '\0'; } -static void kvprintf (const char* fmt, va_list* list) { - kv_core_printf (fmt, list, putchar); - update (); -} +static void kvprintf_putc (unsigned char c) { add_char (c); } + +static void kvprintf (const char* fmt, va_list* list) { kv_core_printf (fmt, list, kvprintf_putc); } void ksprintf (char* buf, const char* fmt, ...) { va_list ap; diff --git a/kernel/src/kernel/con/con.c b/kernel/src/kernel/con/con.c index e85843ce..8a4eb407 100644 --- a/kernel/src/kernel/con/con.c +++ b/kernel/src/kernel/con/con.c @@ -3,19 +3,24 @@ static console_t* console = nullptr; -int add_char (unsigned char c) {} +int add_char (unsigned char c) { + int error = console_putchar (&console, c); + write_to_gfx (&console); + return error; +} void init_con (size_t screen_width, size_t screen_height, size_t x_padding, size_t y_padding, size_t char_spacing, size_t line_padding, size_t font_multiplier) { - console_parameters_t params = {.glyph_height = 8, - .glyph_width = 5, - .line_spacing = line_padding, - .char_spacing = char_spacing, - .xpad = x_padding, - .ypad = y_padding, - .width = screen_width, - .height = screen_height, - .font_size = font_multiplier}; + console_parameters_t params = { + .glyph_height = 8, + .glyph_width = 5, + .line_spacing = line_padding, + .char_spacing = char_spacing, + .xpad = x_padding, + .ypad = y_padding, + .width = (screen_width - 2 * x_padding) / ((5 + char_spacing) * font_multiplier), + .height = (screen_height - 2 * y_padding) / ((8 + line_padding) * font_multiplier), + .font_size = font_multiplier}; - console_create(&console, ¶ms); + console_create (&console, ¶ms); }; diff --git a/kernel/src/kernel/con/con_ds.c b/kernel/src/kernel/con/con_ds.c index b6bf4939..d79de508 100644 --- a/kernel/src/kernel/con/con_ds.c +++ b/kernel/src/kernel/con/con_ds.c @@ -129,7 +129,7 @@ int console_putchar (console_t** console, unsigned char c) { console_scrolldown (console, deque_size ((*console)->scrollfront)); if (c == '\n') { - (*console)->idx = CON_IDX_GEN (0, (*console)->params.height); + (*console)->idx = CON_IDX_GEN (0, CON_IDX_Y ((*console)->idx) + 1); } else { console_char_t* target = &(*console)->display[CON_IDX_Y ((*console)->idx)]->chars[CON_IDX_X ((*console)->idx)]; diff --git a/kernel/src/kernel/entry.c b/kernel/src/kernel/entry.c index b8b86dd6..6e0d5051 100644 --- a/kernel/src/kernel/entry.c +++ b/kernel/src/kernel/entry.c @@ -1,6 +1,7 @@ #include #include #include +#include #include #include #include @@ -16,7 +17,6 @@ #include #include #include -#include #include #include #include @@ -56,25 +56,25 @@ static void hcf (void) { } static void print_info (void) { - drawBorder (20); - set_color (0x44eeaa); + // drawBorder (20); + // set_color (0x44eeaa); kprintf ("COS 0.0%d", 7); - set_color (0xddeecc); + // set_color (0xddeecc); kprintf ("\n\nHello, World!\n\n"); - set_color (0x88aaee); + // set_color (0x88aaee); kprintf ("System info:\n"); if (bootinfo_req.response != nullptr) { - set_color (0x888888); + // set_color (0x888888); kprintf ("Bootloader: %s %s", bootinfo_req.response->name, bootinfo_req.response->version); } else kprintf ("\nDid not receive bootloader info from bootloader.\n"); if (boottime_req.response != nullptr) { - set_color (0x888888); + // set_color (0x888888); kprintf ("\nSystem booted at time %ld.\n", boottime_req.response->boot_time); } else kprintf ("\nDid not receive boot time from Limine.\n"); @@ -82,7 +82,7 @@ static void print_info (void) { __attribute__ ((noreturn)) void _start_stage2 (void) { init_graphics (framebuffer); - init_console (framebuffer->width, framebuffer->height, 40, 40, 1, 1, 2); + init_con (framebuffer->width, framebuffer->height, 40, 40, 1, 1, 2); init_kb (); init_acpi (rsdp); diff --git a/kernel/src/kernel/fs/chardev/chardev.c b/kernel/src/kernel/fs/chardev/chardev.c index ae22d796..4b8b89d9 100644 --- a/kernel/src/kernel/fs/chardev/chardev.c +++ b/kernel/src/kernel/fs/chardev/chardev.c @@ -1,11 +1,11 @@ #include #include #include +#include #include #include #include #include -#include #include #include @@ -13,14 +13,14 @@ inode* tty1_ptr = nullptr; static int stdout_write (inode* node, file* f, void* buf, size_t len) { (void)node, (void)f; // args not used - bool stdio_buf = get_update_on_putch (); - set_update_on_putch (false); + // bool stdio_buf = get_update_on_putch (); + // set_update_on_putch (false); for (size_t i = 0; i < len; i++) - putchar (((char*)buf)[i]); + add_char (((char*)buf)[i]); - update (); - set_update_on_putch (stdio_buf); + // update (); + // set_update_on_putch (stdio_buf); return len; } @@ -45,8 +45,8 @@ static int stdin_read (inode* node, file* f, void* buffer, size_t size) { if (i > 0) { i -= 2; bytes_read--; - putchar ('\x7F'); - update (); + add_char ('\x7F'); + // update (); } else { i--; } @@ -55,8 +55,8 @@ static int stdin_read (inode* node, file* f, void* buffer, size_t size) { } else if (c < 0x80) { cbuffer[i] = c; bytes_read++; - putchar (c); - update (); + add_char (c); + // update (); if (c == '\n') break; } else { i--; From 0f7a479a821b54f3ac225544083b19d1c1d9ae86 Mon Sep 17 00:00:00 2001 From: ryuukumar Date: Sat, 16 May 2026 10:41:35 +0530 Subject: [PATCH 20/29] Create new update-related functions --- kernel/include/kernel/con/con.h | 5 +++++ kernel/src/kernel/con/con.c | 19 ++++++++++++++++++- kernel/src/kernel/fs/chardev/chardev.c | 11 +++++------ 3 files changed, 28 insertions(+), 7 deletions(-) diff --git a/kernel/include/kernel/con/con.h b/kernel/include/kernel/con/con.h index 3bd57411..2ae58000 100644 --- a/kernel/include/kernel/con/con.h +++ b/kernel/include/kernel/con/con.h @@ -8,6 +8,11 @@ #undef TAB_WIDTH #endif +bool con_update_cache_set (void); +bool con_update_cache_clear (void); +void con_update_upd (bool cached); +int con_update (void); + int add_char (unsigned char c); void init_con (size_t screen_width, size_t screen_height, size_t x_padding, size_t y_padding, size_t char_spacing, size_t line_padding, size_t font_multiplier); diff --git a/kernel/src/kernel/con/con.c b/kernel/src/kernel/con/con.c index 8a4eb407..122b1051 100644 --- a/kernel/src/kernel/con/con.c +++ b/kernel/src/kernel/con/con.c @@ -2,10 +2,27 @@ #include static console_t* console = nullptr; +static bool update_flag = true; + +bool con_update_cache_set (void) { + bool cached = update_flag; + update_flag = true; + return cached; +} + +bool con_update_cache_clear (void) { + bool cached = update_flag; + update_flag = false; + return cached; +} + +void con_update_upd (bool cached) { update_flag = cached; } + +int con_update (void) { return write_to_gfx (&console); } int add_char (unsigned char c) { int error = console_putchar (&console, c); - write_to_gfx (&console); + if (update_flag) write_to_gfx (&console); return error; } diff --git a/kernel/src/kernel/fs/chardev/chardev.c b/kernel/src/kernel/fs/chardev/chardev.c index 4b8b89d9..51095364 100644 --- a/kernel/src/kernel/fs/chardev/chardev.c +++ b/kernel/src/kernel/fs/chardev/chardev.c @@ -13,14 +13,13 @@ inode* tty1_ptr = nullptr; static int stdout_write (inode* node, file* f, void* buf, size_t len) { (void)node, (void)f; // args not used - // bool stdio_buf = get_update_on_putch (); - // set_update_on_putch (false); + bool stdio_buf = con_update_cache_clear (); for (size_t i = 0; i < len; i++) add_char (((char*)buf)[i]); - // update (); - // set_update_on_putch (stdio_buf); + con_update (); + con_update_upd (stdio_buf); return len; } @@ -37,6 +36,7 @@ static int stdin_read (inode* node, file* f, void* buffer, size_t size) { (void)node, (void)f; // args not used char* cbuffer = (char*)buffer; size_t bytes_read = 0; + bool stdio_buf = con_update_cache_set (); for (size_t i = 0; i < size; i++) { unsigned char c = 255; while ((c = pop_next_char ()) == 255) @@ -46,7 +46,6 @@ static int stdin_read (inode* node, file* f, void* buffer, size_t size) { i -= 2; bytes_read--; add_char ('\x7F'); - // update (); } else { i--; } @@ -56,12 +55,12 @@ static int stdin_read (inode* node, file* f, void* buffer, size_t size) { cbuffer[i] = c; bytes_read++; add_char (c); - // update (); if (c == '\n') break; } else { i--; } } + con_update_upd (stdio_buf); return (int)bytes_read; } From a765a3e6b1ba29f619870e9f48420403161eddec Mon Sep 17 00:00:00 2001 From: ryuukumar Date: Sat, 16 May 2026 10:58:08 +0530 Subject: [PATCH 21/29] Parse delete and \r --- kernel/include/kernel/con/con_ds.h | 5 +++-- kernel/src/kernel/con/con.c | 26 +++++++++++++++++++++++++- kernel/src/kernel/con/con_ds.c | 7 +++++++ 3 files changed, 35 insertions(+), 3 deletions(-) diff --git a/kernel/include/kernel/con/con_ds.h b/kernel/include/kernel/con/con_ds.h index 2cb1a74a..68746305 100644 --- a/kernel/include/kernel/con/con_ds.h +++ b/kernel/include/kernel/con/con_ds.h @@ -56,7 +56,8 @@ int console_scrollup (console_t** console, size_t howmuch); int console_scrolldown (console_t** console, size_t howmuch); int console_clearscrollback (console_t** console); -idx_t console_getidx (console_t** console); -console_color_t console_getcolor (console_t** console); +idx_t console_getidx (console_t** console); +console_color_t console_getcolor (console_t** console); +console_parameters_t console_getparams (console_t** console); int write_to_gfx (console_t** console); diff --git a/kernel/src/kernel/con/con.c b/kernel/src/kernel/con/con.c index 122b1051..bdfe2ac4 100644 --- a/kernel/src/kernel/con/con.c +++ b/kernel/src/kernel/con/con.c @@ -1,9 +1,13 @@ +#include "kernel/memmgt.h" #include #include static console_t* console = nullptr; static bool update_flag = true; +static bool in_esc = false; +static bool in_csi = false; + bool con_update_cache_set (void) { bool cached = update_flag; update_flag = true; @@ -21,7 +25,27 @@ void con_update_upd (bool cached) { update_flag = cached; } int con_update (void) { return write_to_gfx (&console); } int add_char (unsigned char c) { - int error = console_putchar (&console, c); + int error = 0; + console_parameters_t params = console_getparams (&console); + if (c == '\x7F') { + idx_t idx = console_getidx (&console); + if (CON_IDX_X (idx) == 0) + idx = CON_IDX_GEN (params.width - 1, CON_IDX_Y (idx) - 1); + else + idx = CON_IDX_GEN (CON_IDX_X (idx) - 1, CON_IDX_Y (idx)); + + console_goto (&console, CON_IDX_X (idx), CON_IDX_Y (idx)); + error = console_putchar (&console, 0); + console_goto (&console, CON_IDX_X (idx), CON_IDX_Y (idx)); + } else if (c == '\r') { + idx_t idx = console_getidx (&console); + console_goto (&console, 0, CON_IDX_Y (idx)); + } else if (c == '\033') { + in_esc = true; + } else { + error = console_putchar (&console, c); + } + if (update_flag) write_to_gfx (&console); return error; } diff --git a/kernel/src/kernel/con/con_ds.c b/kernel/src/kernel/con/con_ds.c index d79de508..0453d795 100644 --- a/kernel/src/kernel/con/con_ds.c +++ b/kernel/src/kernel/con/con_ds.c @@ -312,6 +312,13 @@ idx_t console_getidx (console_t** console) { return (*console)->idx; } */ console_color_t console_getcolor (console_t** console) { return (*console)->current_color; } +/*! + * Get the parameters of the console. Behavior undefined if console parameter is invalid + * @param console pointer to console_t* which holds the reference to console + * @return parameters + */ +console_parameters_t console_getparams (console_t** console) { return (*console)->params; } + /*! * Update the screenbuffer to match the contents of the console structure's internal display. * @param console pointer to console_t* which holds the reference to console From bf92109286bf12710bb571e53bf9aa9a1b5e5793 Mon Sep 17 00:00:00 2001 From: ryuukumar Date: Sat, 16 May 2026 11:30:29 +0530 Subject: [PATCH 22/29] Add ANSI character parsing --- kernel/include/kernel/con/ansi.h | 11 ++ kernel/src/kernel/con/ansi.c | 201 +++++++++++++++++++++++++++++++ kernel/src/kernel/con/con.c | 14 ++- 3 files changed, 224 insertions(+), 2 deletions(-) create mode 100644 kernel/include/kernel/con/ansi.h create mode 100644 kernel/src/kernel/con/ansi.c diff --git a/kernel/include/kernel/con/ansi.h b/kernel/include/kernel/con/ansi.h new file mode 100644 index 00000000..68d06a20 --- /dev/null +++ b/kernel/include/kernel/con/ansi.h @@ -0,0 +1,11 @@ +#pragma once + +#include + +typedef enum { ANSI_INCOMPLETE, ANSI_INVALID, ANSI_VALID } ansi_status_t; + +ansi_status_t add_to_ansi_parser_buf (unsigned char c); + +const char* get_ansi_buffer (void); +void clear_ansi_buffer (void); +void init_ansi_buffer (console_t** console); diff --git a/kernel/src/kernel/con/ansi.c b/kernel/src/kernel/con/ansi.c new file mode 100644 index 00000000..a69f098d --- /dev/null +++ b/kernel/src/kernel/con/ansi.c @@ -0,0 +1,201 @@ +#include +#include +#include +#include + +#define ANSI_BUFFER_SIZE 100 +#define ANSI_VALID_CMDS "ABCDEFGHJKSTm" +#define ANSI_MAX_PARAMS 8 + +static char* ansi_buffer = nullptr; +static size_t ansi_idx = 0; +static console_t** ansi_console = nullptr; + +static ansi_status_t try_parse_ansi (void) { + size_t idx = 0; + if (ansi_buffer[idx] != '[') return ANSI_INVALID; + idx++; + + int64_t params[ANSI_MAX_PARAMS]; + int param_count = 0; + params[0] = -1; + + while (1) { + if (ansi_buffer[idx] >= '0' && ansi_buffer[idx] <= '9') { + if (params[param_count] == -1) params[param_count] = 0; + params[param_count] = params[param_count] * 10 + (ansi_buffer[idx] - '0'); + idx++; + } else if (ansi_buffer[idx] == ';') { + if (++param_count >= ANSI_MAX_PARAMS) return ANSI_INVALID; + params[param_count] = -1; + idx++; + } else { + break; + } + } + + char cmd = ansi_buffer[idx]; + if (cmd == '\0') return ANSI_INCOMPLETE; + if (!kstrchr (ANSI_VALID_CMDS, cmd)) return ANSI_INVALID; + + int64_t a = (params[0] == -1) ? 1 : params[0]; + idx_t cur = console_getidx (ansi_console); + int64_t new_x, new_y; + + console_parameters_t p = console_getparams (ansi_console); + + switch (cmd) { + case 'A': /* Cursor Up */ + new_y = (int64_t)CON_IDX_Y (cur) - a; + if (new_y < 0) new_y = 0; + console_goto (ansi_console, CON_IDX_X (cur), (uint32_t)new_y); + break; + + case 'B': /* Cursor Down */ + new_y = (int64_t)CON_IDX_Y (cur) + a; + if (new_y >= (int64_t)p.height) new_y = (int64_t)p.height - 1; + console_goto (ansi_console, CON_IDX_X (cur), (uint32_t)new_y); + break; + + case 'C': /* Cursor Forward */ + new_x = (int64_t)CON_IDX_X (cur) + a; + if (new_x >= (int64_t)p.width) new_x = (int64_t)p.width - 1; + console_goto (ansi_console, (uint32_t)new_x, CON_IDX_Y (cur)); + break; + + case 'D': /* Cursor Back */ + new_x = (int64_t)CON_IDX_X (cur) - a; + if (new_x < 0) new_x = 0; + console_goto (ansi_console, (uint32_t)new_x, CON_IDX_Y (cur)); + break; + + case 'E': /* Cursor Next Line */ + new_y = (int64_t)CON_IDX_Y (cur) + a; + if (new_y >= (int64_t)p.height) new_y = (int64_t)p.height - 1; + console_goto (ansi_console, 0, (uint32_t)new_y); + break; + + case 'F': /* Cursor Previous Line */ + new_y = (int64_t)CON_IDX_Y (cur) - a; + if (new_y < 0) new_y = 0; + console_goto (ansi_console, 0, (uint32_t)new_y); + break; + + case 'G': /* Cursor Horizontal Absolute (1-based column) */ + new_x = a - 1; + if (new_x < 0) new_x = 0; + if (new_x >= (int64_t)p.width) new_x = (int64_t)p.width - 1; + console_goto (ansi_console, (uint32_t)new_x, CON_IDX_Y (cur)); + break; + + case 'H': { /* Cursor Position: ESC[row;col H (1-based, default 1;1) */ + int64_t row = (params[0] == -1 ? 1 : params[0]) - 1; + int64_t col = (param_count >= 1 && params[1] != -1 ? params[1] : 1) - 1; + if (row < 0) row = 0; + if (col < 0) col = 0; + if (row >= (int64_t)p.height) row = (int64_t)p.height - 1; + if (col >= (int64_t)p.width) col = (int64_t)p.width - 1; + console_goto (ansi_console, (uint32_t)col, (uint32_t)row); + break; + } + + case 'J': { /* Erase in Display (default 0) */ + int64_t mode = (params[0] == -1) ? 0 : params[0]; + int64_t sx = CON_IDX_X (cur), sy = CON_IDX_Y (cur); + int64_t ex = (int64_t)p.width - 1, ey = (int64_t)p.height - 1; + if (mode == 1) { + sx = 0; + sy = 0; + ex = CON_IDX_X (cur); + ey = CON_IDX_Y (cur); + } else if (mode == 2) { + sx = 0; + sy = 0; + } + /* mode == 0: from cursor to end of screen (sx/sy already set) */ + for (int64_t y = sy; y <= ey; y++) { + int64_t lx = (y == sy) ? sx : 0; + int64_t rx = (y == ey) ? ex : (int64_t)p.width - 1; + for (int64_t x = lx; x <= rx; x++) { + console_goto (ansi_console, (uint32_t)x, (uint32_t)y); + console_putchar (ansi_console, 0); + } + } + console_goto (ansi_console, CON_IDX_X (cur), CON_IDX_Y (cur)); + break; + } + + case 'K': { /* Erase in Line (default 0) */ + int64_t mode = (params[0] == -1) ? 0 : params[0]; + int64_t lx, rx; + if (mode == 0) { + lx = CON_IDX_X (cur); + rx = (int64_t)p.width - 1; + } else if (mode == 1) { + lx = 0; + rx = CON_IDX_X (cur); + } else { + lx = 0; + rx = (int64_t)p.width - 1; + } + for (int64_t x = lx; x <= rx; x++) { + console_goto (ansi_console, (uint32_t)x, CON_IDX_Y (cur)); + console_putchar (ansi_console, 0); + } + console_goto (ansi_console, CON_IDX_X (cur), CON_IDX_Y (cur)); + break; + } + + case 'S': /* Scroll Up */ + console_scrollup (ansi_console, (size_t)a); + break; + + case 'T': /* Scroll Down */ + console_scrolldown (ansi_console, (size_t)a); + break; + + case 'm': /* SGR */ + if (params[0] == -1 || params[0] == 0) { + console_setcolor (ansi_console, 0xFF, 0xFF, 0xFF); + } else if (params[0] == 38 && param_count >= 4 && params[1] == 2) { + uint8_t r = (uint8_t)(params[2] < 0 ? 0 : params[2] > 255 ? 255 : params[2]); + uint8_t g = (uint8_t)(params[3] < 0 ? 0 : params[3] > 255 ? 255 : params[3]); + uint8_t b = (uint8_t)(params[4] < 0 ? 0 : params[4] > 255 ? 255 : params[4]); + console_setcolor (ansi_console, r, g, b); + } else if (params[0] >= 30 && params[0] <= 37) { + static const uint8_t ansi_cols[8][3] = { + {0, 0, 0}, /* 30 black */ + {170, 0, 0}, /* 31 red */ + {0, 170, 0}, /* 32 green */ + {170, 170, 0}, /* 33 yellow */ + {0, 0, 170}, /* 34 blue */ + {170, 0, 170}, /* 35 magenta */ + {0, 170, 170}, /* 36 cyan */ + {170, 170, 170}, /* 37 white */ + }; + int ci = (int)(params[0] - 30); + console_setcolor (ansi_console, ansi_cols[ci][0], ansi_cols[ci][1], ansi_cols[ci][2]); + } + break; + } + + clear_ansi_buffer (); + return ANSI_VALID; +} + +ansi_status_t add_to_ansi_parser_buf (unsigned char c) { + ansi_buffer[ansi_idx++] = c; + return try_parse_ansi (); +} + +const char* get_ansi_buffer (void) { return (const char*)ansi_buffer; } + +void clear_ansi_buffer (void) { + kmemset (ansi_buffer, 0, ANSI_BUFFER_SIZE); + ansi_idx = 0; +} + +void init_ansi_buffer (console_t** console) { + ansi_console = console; + ansi_buffer = kmalloc (ANSI_BUFFER_SIZE); +} \ No newline at end of file diff --git a/kernel/src/kernel/con/con.c b/kernel/src/kernel/con/con.c index bdfe2ac4..fad2bb9a 100644 --- a/kernel/src/kernel/con/con.c +++ b/kernel/src/kernel/con/con.c @@ -1,4 +1,4 @@ -#include "kernel/memmgt.h" +#include #include #include @@ -27,7 +27,17 @@ int con_update (void) { return write_to_gfx (&console); } int add_char (unsigned char c) { int error = 0; console_parameters_t params = console_getparams (&console); - if (c == '\x7F') { + if (in_esc) { + ansi_status_t status = add_to_ansi_parser_buf (c); + if (status == ANSI_INVALID) { + const char* buf = get_ansi_buffer (); + for (size_t i = 0; buf[i]; i++) + console_putchar (&console, (unsigned char)buf[i]); + clear_ansi_buffer (); + in_esc = false; + in_csi = false; + } + } else if (c == '\x7F') { idx_t idx = console_getidx (&console); if (CON_IDX_X (idx) == 0) idx = CON_IDX_GEN (params.width - 1, CON_IDX_Y (idx) - 1); From 161674976d1a07278073f0ab0f4ba80b21a9c7f2 Mon Sep 17 00:00:00 2001 From: ryuukumar Date: Sat, 16 May 2026 11:38:26 +0530 Subject: [PATCH 23/29] Actually init the buffer, and update the print_info call --- kernel/src/kernel/con/con.c | 1 + kernel/src/kernel/entry.c | 23 ++++++++--------------- 2 files changed, 9 insertions(+), 15 deletions(-) diff --git a/kernel/src/kernel/con/con.c b/kernel/src/kernel/con/con.c index fad2bb9a..5ec6f598 100644 --- a/kernel/src/kernel/con/con.c +++ b/kernel/src/kernel/con/con.c @@ -73,5 +73,6 @@ void init_con (size_t screen_width, size_t screen_height, size_t x_padding, size .height = (screen_height - 2 * y_padding) / ((8 + line_padding) * font_multiplier), .font_size = font_multiplier}; + init_ansi_buffer (&console); console_create (&console, ¶ms); }; diff --git a/kernel/src/kernel/entry.c b/kernel/src/kernel/entry.c index 6e0d5051..44eff6c2 100644 --- a/kernel/src/kernel/entry.c +++ b/kernel/src/kernel/entry.c @@ -56,33 +56,26 @@ static void hcf (void) { } static void print_info (void) { - // drawBorder (20); - // set_color (0x44eeaa); + kprintf ("\033[38;2;68;238;170mCOS 0.0%d", 7); + kprintf ("\033[38;2;221;238;204m\n\nHello, World!\n\n"); + kprintf ("\033[38;2;136;170;238mSystem info:\n"); - kprintf ("COS 0.0%d", 7); - - // set_color (0xddeecc); - - kprintf ("\n\nHello, World!\n\n"); - - // set_color (0x88aaee); - kprintf ("System info:\n"); if (bootinfo_req.response != nullptr) { - // set_color (0x888888); - kprintf ("Bootloader: %s %s", bootinfo_req.response->name, bootinfo_req.response->version); + kprintf ("\033[38;2;200;200;200mBootloader: %s %s", bootinfo_req.response->name, + bootinfo_req.response->version); } else kprintf ("\nDid not receive bootloader info from bootloader.\n"); if (boottime_req.response != nullptr) { - // set_color (0x888888); - kprintf ("\nSystem booted at time %ld.\n", boottime_req.response->boot_time); + kprintf ("\n\033[38;2;200;200;200mSystem booted at time %ld.\n", + boottime_req.response->boot_time); } else kprintf ("\nDid not receive boot time from Limine.\n"); } __attribute__ ((noreturn)) void _start_stage2 (void) { init_graphics (framebuffer); - init_con (framebuffer->width, framebuffer->height, 40, 40, 1, 1, 2); + init_con (framebuffer->width, framebuffer->height, 20, 20, 1, 1, 2); init_kb (); init_acpi (rsdp); From 9e7f0213ab168d913fa45109d0a83f38ac4aa5f7 Mon Sep 17 00:00:00 2001 From: ryuukumar Date: Sat, 16 May 2026 11:42:18 +0530 Subject: [PATCH 24/29] Add some colors to cosh --- user/cosh/src/repl_main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/user/cosh/src/repl_main.c b/user/cosh/src/repl_main.c index 7188e4ff..ec626b29 100644 --- a/user/cosh/src/repl_main.c +++ b/user/cosh/src/repl_main.c @@ -122,14 +122,14 @@ int repl_loop (void) { if (!pathbuf || !cmdbuf) return -1; getcwd (pathbuf, 100); - printf ("root@cos %s > ", pathbuf); + printf ("\033[37mroot@cos \033[36m%s\033[37m > ", pathbuf); if (fgets (cmdbuf, 1000, stdin) == nullptr) return -1; cmdbuf[strcspn (cmdbuf, "\n")] = '\0'; if (cmdbuf[0] == '\0') return 0; last_exit = run_line (cmdbuf); - if (last_exit != 0) printf ("exited with non-zero status: %i\n", last_exit); + if (last_exit != 0) printf ("\033[31mexited with non-zero status: %i\n", last_exit); return 0; } From 9c9b959405d22749d4bef16fbc1af9d44ca3b937 Mon Sep 17 00:00:00 2001 From: ryuukumar Date: Sat, 16 May 2026 12:01:43 +0530 Subject: [PATCH 25/29] Implement scrolling on the console Scrolling is done with PgUp + PgDown --- kernel/include/kernel/con/con.h | 3 +++ kernel/src/kernel/con/con.c | 10 ++++++++++ kernel/src/kernel/hw/keyboard.c | 7 ++++++- 3 files changed, 19 insertions(+), 1 deletion(-) diff --git a/kernel/include/kernel/con/con.h b/kernel/include/kernel/con/con.h index 2ae58000..3c85e4aa 100644 --- a/kernel/include/kernel/con/con.h +++ b/kernel/include/kernel/con/con.h @@ -13,6 +13,9 @@ bool con_update_cache_clear (void); void con_update_upd (bool cached); int con_update (void); +void con_scrollup (size_t howmuch); +void con_scrolldown (size_t howmuch); + int add_char (unsigned char c); void init_con (size_t screen_width, size_t screen_height, size_t x_padding, size_t y_padding, size_t char_spacing, size_t line_padding, size_t font_multiplier); diff --git a/kernel/src/kernel/con/con.c b/kernel/src/kernel/con/con.c index 5ec6f598..2c9f789f 100644 --- a/kernel/src/kernel/con/con.c +++ b/kernel/src/kernel/con/con.c @@ -24,6 +24,16 @@ void con_update_upd (bool cached) { update_flag = cached; } int con_update (void) { return write_to_gfx (&console); } +void con_scrollup (size_t howmuch) { + console_scrollup (&console, howmuch); + write_to_gfx (&console); +} + +void con_scrolldown (size_t howmuch) { + console_scrolldown (&console, howmuch); + write_to_gfx (&console); +} + int add_char (unsigned char c) { int error = 0; console_parameters_t params = console_getparams (&console); diff --git a/kernel/src/kernel/hw/keyboard.c b/kernel/src/kernel/hw/keyboard.c index 67d45369..df4b28c3 100644 --- a/kernel/src/kernel/hw/keyboard.c +++ b/kernel/src/kernel/hw/keyboard.c @@ -1,4 +1,5 @@ #include +#include #include #include #include @@ -60,7 +61,11 @@ static void kb_handler (registers_t* registers) { if (kb_read_status_register ().out_buffer_full) { unsigned char scancode = inb (kb_ps2_data_port); unsigned char processed = map_keypress (kb_statemachine, scancode); - if (processed != 0) { + if (processed == kb_action_pgup) { + con_scrollup (3); + } else if (processed == kb_action_pgdn) { + con_scrolldown (3); + } else if (processed != 0) { push_charqueue (kb_keypress_charqueue, processed); if (kb_tty_handler) kb_tty_handler (processed); } From 20d3a9f3e8d49f6338e5d61accc84b7039005775 Mon Sep 17 00:00:00 2001 From: ryuukumar Date: Sat, 16 May 2026 12:13:33 +0530 Subject: [PATCH 26/29] Add buildin clear + fix issue where consecutive ansi sequences would not be parsed --- kernel/src/kernel/con/con.c | 4 ++-- user/cosh/include/builtin.h | 1 + user/cosh/src/builtin/clear.c | 11 +++++++++++ user/cosh/src/builtin/dispatch_builtin.c | 2 ++ 4 files changed, 16 insertions(+), 2 deletions(-) create mode 100644 user/cosh/src/builtin/clear.c diff --git a/kernel/src/kernel/con/con.c b/kernel/src/kernel/con/con.c index 2c9f789f..ef118729 100644 --- a/kernel/src/kernel/con/con.c +++ b/kernel/src/kernel/con/con.c @@ -6,7 +6,6 @@ static console_t* console = nullptr; static bool update_flag = true; static bool in_esc = false; -static bool in_csi = false; bool con_update_cache_set (void) { bool cached = update_flag; @@ -45,7 +44,8 @@ int add_char (unsigned char c) { console_putchar (&console, (unsigned char)buf[i]); clear_ansi_buffer (); in_esc = false; - in_csi = false; + } else if (status == ANSI_VALID) { + in_esc = false; } } else if (c == '\x7F') { idx_t idx = console_getidx (&console); diff --git a/user/cosh/include/builtin.h b/user/cosh/include/builtin.h index aa3e17c1..11f90a73 100644 --- a/user/cosh/include/builtin.h +++ b/user/cosh/include/builtin.h @@ -5,6 +5,7 @@ int dispatch_builtin (size_t argc, char** argv); int builtin_chdir (int argc, char** argv); +int builtin_clear (int argc, char** argv); int builtin_echo (int argc, char** argv); int builtin_eval (int argc, char** argv); int builtin_exit (int argc, char** argv); diff --git a/user/cosh/src/builtin/clear.c b/user/cosh/src/builtin/clear.c new file mode 100644 index 00000000..93a0cc82 --- /dev/null +++ b/user/cosh/src/builtin/clear.c @@ -0,0 +1,11 @@ +#include +#include + +int builtin_clear (int argc, char** argv) { + (void)argc; + (void)argv; + for (int i = 0; i < 60; i++) + putchar ('\n'); + printf ("\033[1;1H"); + return 0; +} diff --git a/user/cosh/src/builtin/dispatch_builtin.c b/user/cosh/src/builtin/dispatch_builtin.c index 2c5b2f57..2395998a 100644 --- a/user/cosh/src/builtin/dispatch_builtin.c +++ b/user/cosh/src/builtin/dispatch_builtin.c @@ -33,6 +33,8 @@ int dispatch_builtin (size_t argc, char** argv) { return builtin_source (argc, argv); else if (strcmp (argv[0], "test") == 0 || strcmp (argv[0], "[") == 0) return builtin_test (argc, argv); + else if (strcmp (argv[0], "clear") == 0) + return builtin_clear (argc, argv); return -1; } From 23429f810ac564b51fd7024a02489304cda33a97 Mon Sep 17 00:00:00 2001 From: ryuukumar Date: Sat, 16 May 2026 12:34:00 +0530 Subject: [PATCH 27/29] Light optimisations to clearing --- kernel/src/kernel/con/ansi.c | 13 +++++++++++++ user/cosh/src/builtin/clear.c | 7 ++----- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/kernel/src/kernel/con/ansi.c b/kernel/src/kernel/con/ansi.c index a69f098d..38ad1e4d 100644 --- a/kernel/src/kernel/con/ansi.c +++ b/kernel/src/kernel/con/ansi.c @@ -1,5 +1,6 @@ #include #include +#include #include #include @@ -103,6 +104,14 @@ static ansi_status_t try_parse_ansi (void) { int64_t mode = (params[0] == -1) ? 0 : params[0]; int64_t sx = CON_IDX_X (cur), sy = CON_IDX_Y (cur); int64_t ex = (int64_t)p.width - 1, ey = (int64_t)p.height - 1; + bool con_flag = con_update_cache_clear (); + + if (mode == 3) { + console_clearscrollback (ansi_console); + con_update_upd (con_flag); + break; + } + if (mode == 1) { sx = 0; sy = 0; @@ -122,12 +131,15 @@ static ansi_status_t try_parse_ansi (void) { } } console_goto (ansi_console, CON_IDX_X (cur), CON_IDX_Y (cur)); + con_update_upd (con_flag); break; } case 'K': { /* Erase in Line (default 0) */ int64_t mode = (params[0] == -1) ? 0 : params[0]; int64_t lx, rx; + bool con_flag = con_update_cache_clear (); + if (mode == 0) { lx = CON_IDX_X (cur); rx = (int64_t)p.width - 1; @@ -143,6 +155,7 @@ static ansi_status_t try_parse_ansi (void) { console_putchar (ansi_console, 0); } console_goto (ansi_console, CON_IDX_X (cur), CON_IDX_Y (cur)); + con_update_upd (con_flag); break; } diff --git a/user/cosh/src/builtin/clear.c b/user/cosh/src/builtin/clear.c index 93a0cc82..c4995243 100644 --- a/user/cosh/src/builtin/clear.c +++ b/user/cosh/src/builtin/clear.c @@ -2,10 +2,7 @@ #include int builtin_clear (int argc, char** argv) { - (void)argc; - (void)argv; - for (int i = 0; i < 60; i++) - putchar ('\n'); - printf ("\033[1;1H"); + (void)argc, (void)argv; + printf ("\033[2J\033[3J\033[H"); return 0; } From adcdcd5f311486a3b013732ac1a529872571c1b6 Mon Sep 17 00:00:00 2001 From: ryuukumar Date: Sat, 16 May 2026 12:35:58 +0530 Subject: [PATCH 28/29] Delete the old console --- kernel/include/kernel/oldconsole.h | 19 ---- kernel/src/kernel/oldconsole.c | 152 ----------------------------- 2 files changed, 171 deletions(-) delete mode 100644 kernel/include/kernel/oldconsole.h delete mode 100644 kernel/src/kernel/oldconsole.c diff --git a/kernel/include/kernel/oldconsole.h b/kernel/include/kernel/oldconsole.h deleted file mode 100644 index 8e38c8ae..00000000 --- a/kernel/include/kernel/oldconsole.h +++ /dev/null @@ -1,19 +0,0 @@ -#pragma once - -#include -#include -#include - -#define TAB_WIDTH 8 - -void set_update_on_putch (bool); -bool get_update_on_putch (void); -void set_idx (size_t); -size_t get_idx (void); - -void init_console (size_t, size_t, size_t, size_t, size_t, size_t, size_t); -void set_color (uint32_t); -void update (void); - -void putchar (unsigned char); -void putstr (const char*, size_t); diff --git a/kernel/src/kernel/oldconsole.c b/kernel/src/kernel/oldconsole.c deleted file mode 100644 index b331dc54..00000000 --- a/kernel/src/kernel/oldconsole.c +++ /dev/null @@ -1,152 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include - -#define CONSOLE_HEIGHT 80 -#define CONSOLE_WIDTH 140 - -bool PUTCH_UPDATE = false; - -unsigned char bufferstr[CONSOLE_HEIGHT * CONSOLE_WIDTH] = { - 0}; // TODO: replace this with malloc when implemented -uint32_t colorbufferstr[CONSOLE_HEIGHT * CONSOLE_WIDTH] = { - 0xffffff}; // TODO: replace this with malloc when implemented -unsigned char* buffer = bufferstr; -uint32_t* colorbuffer = colorbufferstr; -size_t x, y, xs, ys, xsp, ysp, xc, yc, fs; -size_t idx = 0; - -uint32_t color = 0xeeeeee; - -/*! -Set PUTCH_UPDATE - -@param set value to set to -*/ -void set_update_on_putch (bool set) { PUTCH_UPDATE = set; } - -/*! -Get PUTCH_UPDATE - -@return PUTCH_UPDATE -*/ -bool get_update_on_putch () { return PUTCH_UPDATE; } - -/*! -Set idx - -@param set value to set to -*/ -void set_idx (size_t set) { idx = set; } - -/*! -Get idx - -@return idx -*/ -size_t get_idx () { return idx; } - -/*! -Initialise the console with the default (classic) font - -@param x_screen screen width -@param y_screen screen height -@param x_pad padding around sides -@param y_pad padding around top and bottom -@param x_spc spacing between characters -@param y_spc spacing between lines -@param font_size font size -*/ -void init_console (size_t x_screen, size_t y_screen, size_t x_pad, size_t y_pad, size_t x_spc, - size_t y_spc, size_t font_size) { - x = x_screen - 2 * x_pad; - y = y_screen - 2 * y_pad; - - xc = (x / ((5 + x_spc) * font_size) > CONSOLE_WIDTH) ? CONSOLE_WIDTH - : x / ((5 + x_spc) * font_size); - yc = (y / ((8 + y_spc) * font_size) > CONSOLE_HEIGHT) ? CONSOLE_HEIGHT - : y / ((8 + y_spc) * font_size); - - xsp = x_spc; - ysp = y_spc; - - xs = x_pad; - ys = y_pad; - - fs = font_size; - - kmemset (buffer, 32, xc * yc); -} - -/*! -Set the screen color. - -@param c RGB color -*/ -void set_color (uint32_t c) { color = c; } - -/*! -Update the display. -*/ -void update () { - for (size_t pos = 0; pos < xc * yc; pos++) { - size_t i = pos / xc; - size_t j = pos % xc; - renderGlyph (glyph (buffer[pos]), 8, 5, xs + (fs * j * (5 + xsp)), - ys + (fs * i * (8 + ysp)), fs, colorbuffer[pos]); - } -} - -/*! -Register a character to the screen buffer. - -@param rc character to register -@param index position to print it on -*/ -static void registerChar (unsigned char rc, int index) { - buffer[index] = rc; - colorbuffer[index] = color; -} - -/*! -Print a single character to the screen. - -@param rc character to print -*/ -void putchar (unsigned char rc) { - switch (rc) { - case '\n': - idx = ((idx / xc) + 1) * xc; - if (idx >= xc * yc) idx -= xc * yc; - return; - case '\r': - idx -= idx % xc; - return; - case '\b': - idx--; - return; - case '\x7F': - idx--; - registerChar (0, idx); - return; - } - registerChar (rc, idx); - idx++; - if (PUTCH_UPDATE) update (); -} - -/*! -Print a string to the screen. - -@param str string to print -@param len length of string -*/ -void putstr (const char* str, size_t len) { - for (size_t i = 0; i < len; i++) - putchar (str[i]); - update (); -} From f43016a6b80c3d43b22e89081e73c9d5ecfb5ce7 Mon Sep 17 00:00:00 2001 From: ryuukumar Date: Sat, 16 May 2026 12:42:32 +0530 Subject: [PATCH 29/29] Handle tabs in the new console --- kernel/include/kernel/con/con.h | 4 +--- kernel/src/kernel/con/con.c | 10 ++++++++++ 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/kernel/include/kernel/con/con.h b/kernel/include/kernel/con/con.h index 3c85e4aa..d9e98e60 100644 --- a/kernel/include/kernel/con/con.h +++ b/kernel/include/kernel/con/con.h @@ -4,9 +4,7 @@ #include #include -#ifdef TAB_WIDTH -#undef TAB_WIDTH -#endif +#define TAB_WIDTH 8 bool con_update_cache_set (void); bool con_update_cache_clear (void); diff --git a/kernel/src/kernel/con/con.c b/kernel/src/kernel/con/con.c index ef118729..22ff2e3b 100644 --- a/kernel/src/kernel/con/con.c +++ b/kernel/src/kernel/con/con.c @@ -60,6 +60,16 @@ int add_char (unsigned char c) { } else if (c == '\r') { idx_t idx = console_getidx (&console); console_goto (&console, 0, CON_IDX_Y (idx)); + } else if (c == '\t') { + idx_t idx = console_getidx (&console); + size_t x_next_tabstop = TAB_WIDTH * ((CON_IDX_X (idx) + TAB_WIDTH - 1) / TAB_WIDTH); + if (x_next_tabstop >= params.width) + if (CON_IDX_Y (idx) + 1 == params.height) + console_putchar (&console, '\n'); + else + console_goto (&console, 0, CON_IDX_Y (idx) + 1); + else + console_goto (&console, x_next_tabstop, CON_IDX_Y (idx)); } else if (c == '\033') { in_esc = true; } else {