diff --git a/kernel/arch/i386/tty.c b/kernel/arch/i386/tty.c index 2570945..a585906 100644 --- a/kernel/arch/i386/tty.c +++ b/kernel/arch/i386/tty.c @@ -6,6 +6,7 @@ #include #include "vga.h" +#include "../../kernel/asm_helper.h" // FIXME static const size_t VGA_WIDTH = 80; static const size_t VGA_HEIGHT = 25; @@ -38,14 +39,42 @@ void terminal_putentryat(unsigned char c, uint8_t color, size_t x, size_t y) { terminal_buffer[index] = vga_entry(c, color); } +// Updates the hardware cursor. +static void move_cursor() +{ + // The screen is 80 characters wide... + uint16_t cursorLocation = terminal_row * 80 + terminal_column; + outb(0x3D4, 14); // Tell the VGA board we are setting the high cursor byte. + outb(0x3D5, cursorLocation >> 8); // Send the high cursor byte. + outb(0x3D4, 15); // Tell the VGA board we are setting the low cursor byte. + outb(0x3D5, cursorLocation); // Send the low cursor byte. +} + void terminal_scroll(int line) { - int loop; - int c; - - for(loop = line * (VGA_WIDTH * 2) + 0xB8000; loop < VGA_WIDTH * 2; loop++) { - c = loop; - //*(loop - (VGA_WIDTH * 2)) = c; - } + // Get a space character with the default colour attributes. + int attributeByte = (0 /*black*/ << 4) | (15 /*white*/ & 0x0F); + uint16_t blank = 0x20 /* space */ | (attributeByte << 8); + + // Row 25 is the end, this means we need to scroll up + if(terminal_row >= 25) + { + // Move the current text chunk that makes up the screen + // back in the buffer by a line + int i; + for (i = 0*80; i < 24*80; i++) + { + terminal_buffer[i] = terminal_buffer[i+80]; + } + + // The last line should now be blank. Do this by writing + // 80 spaces to it. + for (i = 24*80; i < 25*80; i++) + { + terminal_buffer[i] = blank; + } + // The cursor should now be on the last line. + terminal_row = 24; + } } @@ -65,18 +94,19 @@ void terminal_putchar(char c) { if (++terminal_column == VGA_WIDTH) { terminal_column = 0; if (++terminal_row == VGA_HEIGHT) { - for(int line = 1; line <= VGA_HEIGHT - 1; line++) - { - terminal_scroll(line); - } - terminal_delete_last_line(); - terminal_row = VGA_HEIGHT - 1; + for(int line = 1; line <= VGA_HEIGHT - 1; line++) { + terminal_scroll(line); + } + terminal_delete_last_line(); + terminal_row = VGA_HEIGHT - 1; } } } else { terminal_row += 1; terminal_column = 0; } + terminal_scroll(terminal_row); + move_cursor(); } void terminal_write(const char* data, size_t size) {