Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
937abc1
Add union for console char type
ryuukumar Apr 26, 2026
2d24ff3
Merge remote-tracking branch 'origin/main' into gfx/console-revamp
ryuukumar May 13, 2026
d14ae4a
Merge remote-tracking branch 'origin/main' into gfx/console-revamp
ryuukumar May 15, 2026
de120ef
console -> oldconsole
ryuukumar May 15, 2026
0ef55c4
Format
ryuukumar May 15, 2026
bf5c5a4
Start implementing a console data structure
ryuukumar May 15, 2026
b36af70
Remove old console_char_t and stub out con.h
ryuukumar May 15, 2026
95ab0c1
Unstub some scroll functions
ryuukumar May 15, 2026
499ac30
Merge remote-tracking branch 'origin/main' into gfx/console-revamp
ryuukumar May 15, 2026
9b712f9
Adapt the console structure to deque
ryuukumar May 15, 2026
40240a4
Implement console_putchar and console_clearscrollback
ryuukumar May 15, 2026
dc6c784
Add console_parameters_t + write_to_gfx
ryuukumar May 15, 2026
c150b0b
Return 0
ryuukumar May 15, 2026
7be7f9d
Set dirty flag where appropriate
ryuukumar May 15, 2026
147e694
If index exceeds printable area, expand it
ryuukumar May 15, 2026
9be21c4
Enforce scrollback limit and always print on newest line
ryuukumar May 15, 2026
9392d0c
Add comments + handle \n
ryuukumar May 15, 2026
5c5858b
Implement console_delete
ryuukumar May 15, 2026
3891dfa
Bug fixes
ryuukumar May 15, 2026
4c9a7ae
Bugfixes + update comment to describe behavior accurately
ryuukumar May 15, 2026
fb71246
Update init_con
ryuukumar May 15, 2026
272f7e1
Substitute whatever possible
ryuukumar May 16, 2026
0f7a479
Create new update-related functions
ryuukumar May 16, 2026
a765a3e
Parse delete and \r
ryuukumar May 16, 2026
bf92109
Add ANSI character parsing
ryuukumar May 16, 2026
1616749
Actually init the buffer, and update the print_info call
ryuukumar May 16, 2026
9e7f021
Add some colors to cosh
ryuukumar May 16, 2026
9c9b959
Implement scrolling on the console
ryuukumar May 16, 2026
20d3a9f
Add buildin clear + fix issue where consecutive ansi sequences would …
ryuukumar May 16, 2026
23429f8
Light optimisations to clearing
ryuukumar May 16, 2026
adcdcd5
Delete the old console
ryuukumar May 16, 2026
f43016a
Handle tabs in the new console
ryuukumar May 16, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions kernel/include/kclib/stdio.h
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
#pragma once

#include <kernel/console.h>
#include <stdarg.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>

Expand Down
11 changes: 11 additions & 0 deletions kernel/include/kernel/con/ansi.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#pragma once

#include <kernel/con/con_ds.h>

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);
19 changes: 19 additions & 0 deletions kernel/include/kernel/con/con.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#pragma once

#include <stddef.h>
#include <stdint.h>
#include <utils/varray.h>

#define TAB_WIDTH 8

bool con_update_cache_set (void);
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);
63 changes: 63 additions & 0 deletions kernel/include/kernel/con/con_ds.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
#pragma once

#include <stddef.h>
#include <stdint.h>
#include <utils/deque.h>

#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)

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 {
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)) {
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, console_parameters_t* params);
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_clearscrollback (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);
19 changes: 0 additions & 19 deletions kernel/include/kernel/console.h

This file was deleted.

9 changes: 4 additions & 5 deletions kernel/src/kclib/stdio.c
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#include <kclib/stdio.h>
#include <kclib/string.h>
#include <kernel/console.h>
#include <kernel/con/con.h>
#include <kernel/serial.h>
#include <liballoc/liballoc.h>

Expand Down Expand Up @@ -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;
Expand Down
214 changes: 214 additions & 0 deletions kernel/src/kernel/con/ansi.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,214 @@
#include <kclib/string.h>
#include <kernel/con/ansi.h>
#include <kernel/con/con.h>
#include <kernel/con/con_ds.h>
#include <liballoc/liballoc.h>

#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;
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;
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));
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;
} 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));
con_update_upd (con_flag);
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);
}
Loading
Loading