#include #include #include static size_t terminal_row; static size_t terminal_column; static uint8_t terminal_color; static uint16_t* terminal_buffer; void terminal_initialize(void) { terminal_initializec(0x00); } void terminal_initializec(uint8_t color) { terminal_row = 0; terminal_column = 0; if (color == 0x00) { terminal_color = vga_entry_color(VGA_COLOR_LIGHT_GREY, VGA_COLOR_BLACK); } else { terminal_color = color; } terminal_buffer = VGA_MEMORY; for (size_t y = 0; y < VGA_HEIGHT; y++) { for (size_t x = 0; x < VGA_WIDTH; x++) { const size_t index = y * VGA_WIDTH + x; terminal_buffer[index] = vga_entry(' ', terminal_color); } } } void terminal_setcolor(uint8_t color) { terminal_color = color; } uint8_t terminal_getcolor(void) { return terminal_color; } void terminal_putentryat(unsigned char c, uint8_t color, size_t x, size_t y) { const size_t index = y * VGA_WIDTH + x; terminal_buffer[index] = vga_entry(c, color); } void terminal_putchar(const char c) { unsigned char uc = c; if (uc == '\n') { terminal_column = 0; if (++terminal_row == VGA_HEIGHT) { terminal_scroll(); terminal_row = VGA_HEIGHT - 1; } return; } else if (uc == '\t') { terminal_column += 4; if (terminal_column >= VGA_WIDTH) { terminal_putchar('\n'); } return; } else if (uc == '\b') { if (terminal_column == 0) { terminal_row -= 1; if (terminal_row == (size_t)-1) { terminal_row = 0; } terminal_column = VGA_WIDTH; terminal_putentryat(' ', terminal_getcolor(), (size_t)terminal_column, (size_t)terminal_row); } else { terminal_putentryat(' ', terminal_getcolor(), (size_t)--terminal_column, (size_t)terminal_row); } return; } terminal_putentryat(uc, terminal_color, terminal_column, terminal_row); if (++terminal_column == VGA_WIDTH) { terminal_column = 0; if (++terminal_row == VGA_HEIGHT) { terminal_scroll(); terminal_row = VGA_HEIGHT - 1; } } } void terminal_write(const char* data, size_t size) { for (size_t i = 0; i < size; i++) { terminal_putchar(data[i]); } } void terminal_writestring(const char* data) { terminal_write(data, strlen(data)); } void terminal_debug_writestring(const char* data) { terminal_writestring("[ DEBUG ] "); terminal_writestring(data); } void terminal_writeline(const char* data) { terminal_column = 0; terminal_writestring(data); } void terminal_writechar_r(const char ch) { unsigned char uch = ch; for (size_t i = 0; i < VGA_WIDTH; i++) { terminal_putchar(uch); } } void terminal_clear(void) { terminal_clearl(-1); } void terminal_clearl(size_t num_lines) { if (num_lines == (size_t)-1) { terminal_initializec(terminal_getcolor()); } else { /* XXX note to self: VGA_HEIGHT is 25, and VGA_WIDTH is 80 XXX */ /* static size_t terminal_row; static size_t terminal_column; */ terminal_row = VGA_HEIGHT; terminal_column = 0; while (terminal_row < num_lines) { for (int32_t k = 0; k < (int32_t)VGA_WIDTH; k++) { terminal_putentryat((unsigned char)' ', terminal_getcolor(), (size_t)terminal_row, (size_t)k); } terminal_row -= 1; } } } void terminal_scroll(void) { for (size_t y = 1; y < VGA_HEIGHT; y++) { for (size_t x = 0; x < VGA_WIDTH; x++) { const size_t src_index = y * VGA_WIDTH + x; const size_t dst_index = (y - 1) * VGA_WIDTH + x; terminal_buffer[dst_index] = terminal_buffer[src_index]; } } for (size_t x = 0; x < VGA_WIDTH; x++) { const size_t index = (VGA_HEIGHT - 1) * VGA_WIDTH + x; terminal_buffer[index] = (terminal_color << 8) | ' '; } } unsigned char terminal_get_shifted(unsigned char uc) { unsigned char lowerc[] = { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '\0' }; unsigned char upperc[] = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '\0' }; unsigned char nums[] = { '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '\0' }; unsigned char nsyms[] = { '!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '\0' }; unsigned char syms1[] = { ',', '.', '/', ';', '\'', '[', ']', '`', '-', '=', '\\', '\0' }; unsigned char syms2[] = { '<', '>', '?', ':', '\"', '{', '}', '~', '_', '+', '|', '\0' }; for (int32_t i = 0; i < (int32_t)(strlen((char*)lowerc)); ++i) { if (uc == lowerc[i]) { return upperc[i]; } else if (uc == upperc[i]) { return lowerc[i]; } } for (int32_t i = 0; i < (int32_t)(strlen((char*)nums)); ++i) { if (uc == nums[i]) { return nsyms[i]; } else if (uc == nsyms[i]) { return nums[i]; } } for (int32_t i = 0; i < (int32_t)(strlen((char*)syms1)); ++i) { if (uc == syms1[i]) { return syms2[i]; } else if (uc == syms2[i]) { return syms1[i]; } } return '\0'; }