#include #include #include // --- VGA Hardware Constants --- static const size_t VGA_WIDTH = 80; static const size_t VGA_HEIGHT = 25; uint16_t* vga_buffer = (uint16_t*) 0xB8000; // System State size_t terminal_row = 0; size_t terminal_col = 0; uint8_t terminal_color = 7; // Light grey on black // --- Low Level I/O --- static inline void outb(uint16_t port, uint8_t val) { asm volatile ( "outb %0, %1" : : "a"(val), "Nd"(port) ); } static inline uint8_t inb(uint16_t port) { uint8_t ret; asm volatile ( "inb %1, %0" : "=a"(ret) : "Nd"(port) ); return ret; } // --- Hardware Cursor Logic --- void update_cursor(int x, int y) { uint16_t pos = y * VGA_WIDTH + x; outb(0x3D4, 0x0F); outb(0x3D5, (uint8_t) (pos & 0xFF)); outb(0x3D4, 0x0E); outb(0x3D5, (uint8_t) ((pos >> 8) & 0xFF)); } // --- String & Memory Utilities --- int strlen(const char* str) { int len = 0; while (str[len]) len++; return len; } int strcmp(const char* s1, const char* s2) { while (*s1 && (*s1 == *s2)) { s1++; s2++; } return *(unsigned char*)s1 - *(unsigned char*)s2; } char* itoa(int value, char* str, int base) { char *rc, *ptr, *low; if (base < 2 || base > 36) return str; rc = ptr = str; if (value < 0 && base == 10) *ptr++ = '-'; low = ptr; int v = (value < 0) ? -value : value; do { *ptr++ = "0123456789abcdefghijklmnopqrstuvwxyz"[v % base]; v /= base; } while (v); *ptr-- = '\0'; while (low < ptr) { char tmp = *low; *low++ = *ptr; *ptr-- = tmp; } return rc; } // --- Terminal Output --- void putchar(char c) { if (c == '\n') { terminal_col = 0; terminal_row++; } else if (c == '\b') { // Backspace logic is handled in scanf, // but putchar supports it for generic use if (terminal_col > 0) terminal_col--; } else { const size_t index = terminal_row * VGA_WIDTH + terminal_col; vga_buffer[index] = (uint16_t) c | (uint16_t) terminal_color << 8; if (++terminal_col == VGA_WIDTH) { terminal_col = 0; terminal_row++; } } if (terminal_row >= VGA_HEIGHT) { // Simple scroll: just reset to top for now terminal_row = 0; } update_cursor(terminal_col, terminal_row); } void printf(const char* format, ...) { va_list args; va_start(args, format); for (int i = 0; format[i] != '\0'; i++) { if (format[i] == '%') { i++; if (format[i] == 's') { char* s = va_arg(args, char*); while (*s) putchar(*s++); } else if (format[i] == 'd') { char buf[32]; itoa(va_arg(args, int), buf, 10); for (int j = 0; buf[j]; j++) putchar(buf[j]); } else if (format[i] == 'c') { putchar((char)va_arg(args, int)); } } else { putchar(format[i]); } } va_end(args); } // --- Keyboard Input --- char getchar() { static unsigned char map[128] = { 0, 27, '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-', '=', '\b', '\t', 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', '[', ']', '\n', 0, 'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', '\'', '`', 0, '\\', 'z', 'x', 'c', 'v', 'b', 'n', 'm', ',', '.', '/', 0, '*', 0, ' ' }; while (1) { if (inb(0x64) & 0x01) { uint8_t scancode = inb(0x60); // Ignore key-release events (scancode + 128) and non-mapped keys (Alt/Shift) if (scancode < 128 && map[scancode] != 0) { return map[scancode]; } } } } void scanf(char* buffer) { int i = 0; while (1) { char c = getchar(); if (c == '\n') { buffer[i] = '\0'; putchar('\n'); break; } else if (c == '\b') { if (i > 0) { i--; if (terminal_col > 0) { terminal_col--; } else if (terminal_row > 0) { terminal_row--; terminal_col = VGA_WIDTH - 1; } // Clear the character visually vga_buffer[terminal_row * VGA_WIDTH + terminal_col] = (uint16_t)' ' | (uint16_t)terminal_color << 8; update_cursor(terminal_col, terminal_row); } } else { buffer[i++] = c; putchar(c); } } } // --- Kernel Entry --- void kernel_main(void) { // Clear Screen for (size_t i = 0; i < VGA_WIDTH * VGA_HEIGHT; i++) { vga_buffer[i] = (uint16_t)' ' | (uint16_t)7 << 8; } update_cursor(0, 0); printf("BUGS (Buggy Unverified Greatish Script) v1.1\n"); printf("Hardware Cursor: ENABLED\n"); printf("Filtering Alt/Tab symbols: ENABLED\n\n"); while (1) { printf("BUGS> "); char input[64]; scanf(input); if (strcmp(input, "help") == 0) { printf("Available commands: help, clear, hello\n"); } else if (strcmp(input, "clear") == 0) { for (size_t i = 0; i < VGA_WIDTH * VGA_HEIGHT; i++) vga_buffer[i] = (uint16_t)' ' | (uint16_t)7 << 8; terminal_row = 0; terminal_col = 0; update_cursor(0,0); } else if (strcmp(input, "hello") == 0) { printf("Greetings from the kernel!\n"); } else if (strlen(input) > 0) { printf("Unknown command: %s\n", input); } } }