From e493d18d1c2aa1cad224692638fe1e046310b494 Mon Sep 17 00:00:00 2001 From: Farhan Tariq Date: Wed, 13 Aug 2025 18:10:27 +0500 Subject: [PATCH] Add console text coloring support (ANSI escape codes) #3 Signed-off-by: Farhan Tariq --- src/include/colors.h | 24 +++++++++- src/kernel.c | 109 +++++++++++++++++++++++++++++++------------ 2 files changed, 101 insertions(+), 32 deletions(-) diff --git a/src/include/colors.h b/src/include/colors.h index 9520eba..096ef0b 100644 --- a/src/include/colors.h +++ b/src/include/colors.h @@ -1 +1,23 @@ -#define WHITE_ON_BLACK 0x0F +// Foreground colors +#define VGA_BLACK 0x00 +#define VGA_BLUE 0x01 +#define VGA_GREEN 0x02 +#define VGA_CYAN 0x03 +#define VGA_RED 0x04 +#define VGA_MAGENTA 0x05 +#define VGA_BROWN 0x06 +#define VGA_LIGHT_GREY 0x07 +#define VGA_DARK_GREY 0x08 +#define VGA_LIGHT_BLUE 0x09 +#define VGA_LIGHT_GREEN 0x0A +#define VGA_LIGHT_CYAN 0x0B +#define VGA_LIGHT_RED 0x0C +#define VGA_LIGHT_MAGENTA 0x0D +#define VGA_YELLOW 0x0E +#define VGA_WHITE 0x0F + +// Macro to combine background + foreground +#define VGA_COLOR(bg, fg) (((bg) << 4) | (fg)) + +// Default +#define WHITE_ON_BLACK VGA_COLOR(VGA_BLACK, VGA_WHITE) diff --git a/src/kernel.c b/src/kernel.c index 5765cef..1a4e35a 100644 --- a/src/kernel.c +++ b/src/kernel.c @@ -18,7 +18,7 @@ uint16_t input_pos = 0; void k_clear(void) { char *vidmem = VIDEO_MEMORY; - for(uint16_t i = 0; i < 80*25; i++) { + for(uint16_t i = 0; i < WIDTH * HEIGHT; i++) { vidmem[i*2] = ' '; vidmem[i*2+1] = WHITE_ON_BLACK; } @@ -31,14 +31,14 @@ void k_putc(char c, uint8_t color) { char *vidmem = VIDEO_MEMORY; if(c == '\n') { - cursor_pos = (cursor_pos / 80 + 1) * 80; + cursor_pos = (cursor_pos / WIDTH + 1) * WIDTH; } else { vidmem[cursor_pos*2] = c; vidmem[cursor_pos*2+1] = color; cursor_pos++; } - if(cursor_pos >= 80*25) { + if(cursor_pos >= WIDTH * HEIGHT) { k_clear(); } update_cursor(); @@ -50,15 +50,53 @@ void k_print(const char *str) { void k_printf(const char* fmt, ...) { uint32_t* args = (uint32_t*)&fmt + 1; - + uint8_t color = WHITE_ON_BLACK; // active color + while (*fmt) { - if (*fmt == '%') { + // ANSI escape sequence handling + if (*fmt == '\x1b' && fmt[1] == '[') { + fmt += 2; // skip ESC[ + + int code = 0; + while (*fmt >= '0' && *fmt <= '9') { + code = code * 10 + (*fmt - '0'); + fmt++; + } + + if (*fmt == 'm') { + fmt++; // skip 'm' + + // Reset + if (code == 0) { + color = WHITE_ON_BLACK; + } + // Foreground colors + else if (code >= 30 && code <= 37) { + uint8_t fg; + switch (code) { + case 30: fg = VGA_BLACK; break; + case 31: fg = VGA_RED; break; + case 32: fg = VGA_GREEN; break; + case 33: fg = VGA_YELLOW; break; + case 34: fg = VGA_BLUE; break; + case 35: fg = VGA_MAGENTA; break; + case 36: fg = VGA_CYAN; break; + case 37: fg = VGA_WHITE; break; + default: fg = VGA_WHITE; break; + } + color = (color & 0xF0) | fg; + } + continue; // skip normal printing for escape sequences + } + } + // printf-like parsing + else if (*fmt == '%') { fmt++; switch (*fmt) { case 's': { char* s = *(char**)args; args++; - k_print(s); + while (*s) k_putc(*s++, color); break; } case 'd': { @@ -82,23 +120,23 @@ void k_printf(const char* fmt, ...) { } if (is_neg) *--p = '-'; } - k_print(p); + while (*p) k_putc(*p++, color); break; } case 'c': { char c = *(char*)args; args++; - k_putc(c, WHITE_ON_BLACK); + k_putc(c, color); break; } case '%': { - k_putc('%', WHITE_ON_BLACK); + k_putc('%', color); break; } } fmt++; } else { - k_putc(*fmt++, WHITE_ON_BLACK); + k_putc(*fmt++, color); } } } @@ -109,38 +147,47 @@ void sysinfo() { k_printf("OS Version: OpenDOS %s\n", version); } - void k_init(void) { - init_keyboard(); - ata_init(); - - if (fat12_mount(&fs, 0) != 0) { - k_printf("FAT12 mount failed!\n"); - return; - } - - // beep - speaker_beep(600); - delay_ms(5000); - speaker_off(); + init_keyboard(); + ata_init(); + + if (fat12_mount(&fs, 0) != 0) { + k_printf("FAT12 mount failed!\n"); + return; + } + + speaker_beep(600); + delay_ms(5000); + speaker_off(); } void k_main(void) { k_init(); - fat12_file_t files[32]; - fat12_file_t dir; - if (fat12_find(&fs, "OPENDOS", &dir) == 0 && dir.is_dir) { // fix fat12 driver please - int count = fat12_list_dir(&fs, dir.cluster, files, 32); - for (int i = 0; i < count; i++) { - k_printf("%s (%u bytes)\n", files[i].name, files[i].size); - } - } + fat12_file_t files[32]; + fat12_file_t dir; + if (fat12_find(&fs, "OPENDOS", &dir) == 0 && dir.is_dir) { + int count = fat12_list_dir(&fs, dir.cluster, files, 32); + for (int i = 0; i < count; i++) { + k_printf("%s (%u bytes)\n", files[i].name, files[i].size); + } + } k_clear(); k_printf("OpenDOS Kernel %s\n", version); sysinfo(); ata_print_devices(); + + k_printf("ANSI Color Test:"); + k_printf("\x1b[30mBlack \x1b[0m\n"); + k_printf("\x1b[31mRed \x1b[0m\n"); + k_printf("\x1b[32mGreen \x1b[0m\n"); + k_printf("\x1b[33mYellow \x1b[0m\n"); + k_printf("\x1b[34mBlue \x1b[0m\n"); + k_printf("\x1b[35mMagenta \x1b[0m\n"); + k_printf("\x1b[36mCyan \x1b[0m\n"); + k_printf("\x1b[37mWhite \x1b[0m\n"); + k_print("Type 'help' for commands\n> "); while(1) {