#include #include #include #include #include #include "term.h" #include "color.h" #include "cursor.h" uint16_t buffer[TERM_W * TERM_H * sizeof(uint16_t)]; uint16_t *front; uint8_t x, y; uint8_t color; const uint16_t blank = (uint16_t) 0 | VGA_BLACK << 12 | VGA_WHITE << 8; static void term_clear_line(int y) { if (y < 0 || y >= TERM_H) return; for (uint8_t x = 0; x < TERM_W; x++) { const size_t index = y * TERM_W + x; buffer[index] = blank; } } void term_init (void) { x = 0; y = 0; front = (uint16_t*) 0xb8000; term_setfg(VGA_WHITE); term_setbg(VGA_BLACK); term_clear(); } void term_setpos(uint8_t xp, uint8_t yp) { x = xp; y = yp; cursor_setpos(x, y); } void term_scroll (int lines) { int_disable(); y -= lines; if (!lines) return; if(lines >= TERM_H || lines <= -TERM_H) { term_clear(); } else if(lines > 0) { memmove(buffer, buffer + lines * TERM_W, 2 * (TERM_H - lines) * TERM_W); term_clear_line(TERM_H - lines); } else { memmove(buffer + lines * TERM_W, buffer + lines, (TERM_H + lines) * TERM_W); } int_enable(); } void term_setfg(enum VGAColor c) { color = (color & 0xF0) | c; } void term_setbg(enum VGAColor c) { color = (color & 0x0F) | c << 4; } void term_clear (void) { for (uint8_t y = 0; y < TERM_H; y++) term_clear_line(y); } uint32_t term_save(void) { uint32_t state = 0; state |= (uint32_t) x << 16; state |= (uint32_t) y << 8; state |= (uint32_t) color << 0; return state; } void term_load(uint32_t state) { x = (uint8_t) (state >> 16); y = (uint8_t) (state >> 8); color = (uint8_t) (state >> 0); cursor_setpos(x, y); } uint16_t term_save_col(void) { return color; } void term_load_col(uint16_t c) { color = c; } void putchar(int c) { switch (c) { case '\n': x = 0; y++; break; case '\t': x += 4; break; case '\v': case '\f': y++; break; case '\r': x = 0; break; default: { const size_t index = y * TERM_W + x; buffer[index] = c | (uint16_t) color << 8; x++; } } if (x >= TERM_W) { x = 0; y++; } if (y >= TERM_H) { term_scroll(y - (TERM_H - 1)); y = TERM_H - 1; } cursor_setpos(x, y); } bool term_newline(void) { return x == 0; } void term_flush(void) { int_disable(); memcpy(front, buffer, TERM_W * TERM_H * sizeof(uint16_t)); int_enable(); }