#include #include #include #include #include size_t terminal_row; size_t terminal_column; uint8_t terminal_color; uint16_t* terminal_buffer; void terminal_initialize(void) { terminal_initializec(0x00); terminal_update_cursor(); } 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) { if (1) { terminal_scroll(); terminal_row = VGA_HEIGHT - 1; } else { terminal_clear(); terminal_row = 0; } } terminal_update_cursor(); return; } else if (uc == '\t') { terminal_column += 4; if (terminal_column >= VGA_WIDTH) { terminal_putchar('\n'); } terminal_update_cursor(); return; } else if (uc == '\b') { if (terminal_column == 0) { if (terminal_row > 0) { terminal_row--; terminal_column = VGA_WIDTH - 1; } else { terminal_update_cursor(); /* For good measure */ return; } } else { terminal_column--; } terminal_putentryat(' ', terminal_color, terminal_column, terminal_row); terminal_update_cursor(); 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_update_cursor(); } 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) { memmove( terminal_buffer, terminal_buffer + VGA_WIDTH, sizeof(uint16_t) * VGA_WIDTH * (VGA_HEIGHT/* + 1*/) ); terminal_row = VGA_HEIGHT - 1; for (int32_t k = 0; k < (int32_t)VGA_WIDTH; k++) { terminal_putentryat((unsigned char)' ', terminal_getcolor(), (size_t)terminal_row, (size_t)k); } } 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'; } void terminal_set_cursor(uint16_t row, uint16_t column) { if (row < VGA_HEIGHT && column < VGA_WIDTH) { terminal_row = (size_t) row; terminal_column = (size_t) column; } terminal_update_cursor(); } void terminal_update_cursor(void) { uint16_t pos = terminal_row * VGA_WIDTH + terminal_column; outb(0x3D4, 0x0F); outb(0x3D5, (uint8_t) (pos & 0xFF)); outb(0x3D4, 0x0E); outb(0x3D5, (uint8_t) ((pos >> 8) & 0xFF)); }