--- /dev/null
+#include <stddef.h>
+#include <stdint.h>
+
+#include "tty.h"
+
+#include "kernel.h"
+#include "interrupt.h"
+#include "ioport.h"
+
+#include "string.h"
+
+#include <mem.h>
+
+#define make_color(fg, bg) (fg | bg << 4)
+#define make_vga(ch, color) ((uint16_t)(ch & 0xff | color << 8))
+
+#define VGA_WIDTH 80
+#define VGA_HEIGHT 25
+
+static struct virtual_console {
+ int row, column;
+ uint8_t color;
+
+} con;
+
+struct terminal terminal = { 0 };
+
+static void clear() {
+ int i;
+ uint16_t blank = make_vga(' ', terminal.color);
+ for (i=0; i < VGA_WIDTH * VGA_HEIGHT; i++) {
+ terminal.vmem[i] = blank;
+ }
+}
+
+static void scroll(int lines) {
+ uint16_t *base, *offset;
+ uint16_t blank;
+ int i;
+
+ base = terminal.vmem;
+ offset = base + VGA_WIDTH * lines;
+ memmove(base, offset, (VGA_WIDTH * VGA_HEIGHT - lines) * 2);
+
+ offset = base + (VGA_WIDTH * VGA_HEIGHT - lines);
+ blank = make_vga(' ', terminal.color);
+ for (i=0; i < VGA_WIDTH * lines; i++) {
+ offset[i] = blank;
+ }
+}
+
+static void putentryat(int c, uint8_t color, size_t x, size_t y) {
+ size_t index = y * VGA_WIDTH + x;
+ terminal.vmem[index] = make_vga(c, color);
+}
+
+static void putchar(int c) {
+ if (terminal.escape) {
+ switch(c) {
+
+ }
+
+ return;
+ }
+
+ switch (c) {
+ case '\n':
+ terminal.column = 0;
+ if (++terminal.row == VGA_HEIGHT) {
+ terminal.row = VGA_HEIGHT-1;
+ scroll(1);
+ }
+ break;
+ case '\r':
+ terminal.column = 0;
+ break;
+ default:
+ putentryat(c, terminal.color, terminal.column, terminal.row);
+ terminal.column++;
+ break;
+ }
+
+ if (terminal.column == VGA_WIDTH) {
+ terminal.column = 0;
+ if (++terminal.row == VGA_HEIGHT) {
+ terminal.row = VGA_HEIGHT-1;
+ scroll(1);
+ }
+ }
+}
+
+static void setcursor(int row, int col) {
+ uint16_t position = (row*VGA_WIDTH) + col;
+
+ /* cursor low port to vga index register */
+ outport8(0x3D4, 0x0F);
+ outport8(0x3D5, (unsigned char)(position&0xFF));
+ /* cursor high port to vga index register */
+ outport8(0x3D4, 0x0E);
+ outport8(0x3D5, (unsigned char )((position>>8)&0xFF));
+}
+
+static void updcursor() {
+ setcursor(terminal.row, terminal.column);
+}
+
+static void writestring(const char *data) {
+ size_t i = 0;
+
+ while (data[i]) {
+ putchar(data[i++]);
+ }
+ updcursor();
+}
+
+void terminal_initialize() {
+ terminal.putchar = putchar;
+ terminal.clear = clear;
+ terminal.scroll = scroll;
+ terminal.writestring = writestring;
+ terminal.vc = &con;
+ terminal.vmem = (uint16_t *) (0xb8000 + _asm_physmap);
+ terminal.update_cursor = updcursor;
+
+ terminal.row = 0;
+ terminal.column = 0;
+ updcursor();
+
+ terminal.color = make_color(VGA_LIGHT_GREY, VGA_BLACK);
+
+ clear();
+}