summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/LINKS.TODO4
-rw-r--r--src/Makefile10
-rw-r--r--src/console.c18
-rw-r--r--src/console.h6
-rw-r--r--src/kernel.c34
-rw-r--r--src/mouse.c6
-rw-r--r--src/vga.c262
-rw-r--r--src/vga.h68
-rw-r--r--src/vgatext.c262
-rw-r--r--src/vgatext.h68
10 files changed, 371 insertions, 367 deletions
diff --git a/doc/LINKS.TODO b/doc/LINKS.TODO
index 4a2f7b3..6c41e53 100644
--- a/doc/LINKS.TODO
+++ b/doc/LINKS.TODO
@@ -75,3 +75,7 @@ http://wiki.osdev.org/ATA_in_x86_RealMode_%28BIOS%29
C:
http://www.drdobbs.com/extending-c-for-object-oriented-programm/184402731
+
+VGA:
+http://www.inp.nsk.su./~bolkhov/files/fonts/univga/
+https://sourceforge.net/projects/bdf2c/
diff --git a/src/Makefile b/src/Makefile
index c7925bf..9688ebc 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -33,9 +33,9 @@ kernel.bin: kernel.elf
kernel.sym: kernel.elf
$(OBJCOPY) --only-keep-debug kernel.elf kernel.sym
-kernel.elf: kernel.o kernel_asm.o console.o vga.o serial.o port.o port_asm.o interrupts.o interrupts_asm.o driver.o pci.o keyboard.o mouse.o string.o stdlib.o stdio.o setjmp.o
+kernel.elf: kernel.o kernel_asm.o console.o vgatext.o serial.o port.o port_asm.o interrupts.o interrupts_asm.o driver.o pci.o keyboard.o mouse.o string.o stdlib.o stdio.o setjmp.o
$(LD) -o kernel.elf -N -n -Ttext 0x8400 --oformat elf32-i386 \
- kernel.o kernel_asm.o console.o vga.o serial.o \
+ kernel.o kernel_asm.o console.o vgatext.o serial.o \
port.o port_asm.o interrupts.o interrupts_asm.o \
driver.o pci.o \
keyboard.o mouse.o \
@@ -56,11 +56,11 @@ port.o: port.c port.h
port_asm.o: port.asm
$(NASM) port.asm $(NASMFLAGS) -o port_asm.o
-console.o: console.c console.h vga.h serial.h
+console.o: console.c console.h vgatext.h serial.h
$(CC) $(CFLAGS) -c -o console.o console.c
-vga.o: vga.c vga.h
- $(CC) $(CFLAGS) -c -o vga.o vga.c
+vgatext.o: vgatext.c vgatext.h
+ $(CC) $(CFLAGS) -c -o vgatext.o vgatext.c
serial.o: serial.c serial.h
$(CC) $(CFLAGS) -c -o serial.o serial.c
diff --git a/src/console.c b/src/console.c
index ef4c36f..6113823 100644
--- a/src/console.c
+++ b/src/console.c
@@ -7,13 +7,13 @@ void console_init( console_t *console )
{
memset( console, 0, sizeof( console_t ) );
- console->vga = NULL;
+ console->vga_text = NULL;
console->serial = NULL;
}
-void console_add_vga_output( console_t *console, vga_t *vga )
+void console_add_vga_text_output( console_t *console, vga_text_t *vga_text )
{
- console->vga = vga;
+ console->vga_text = vga_text;
}
void console_add_serial_output( console_t *console, serial_t *serial )
@@ -23,8 +23,8 @@ void console_add_serial_output( console_t *console, serial_t *serial )
void console_put_char( console_t *console, const char c )
{
- if( console->vga != NULL ) {
- vga_put_char( console->vga, c );
+ if( console->vga_text != NULL ) {
+ vga_text_put_char( console->vga_text, c );
}
if( console->serial != NULL ) {
@@ -34,8 +34,8 @@ void console_put_char( console_t *console, const char c )
void console_put_string( console_t *console, const char *s )
{
- if( console->vga != NULL ) {
- vga_put_string( console->vga, s );
+ if( console->vga_text != NULL ) {
+ vga_text_put_string( console->vga_text, s );
}
if( console->serial != NULL ) {
@@ -45,8 +45,8 @@ void console_put_string( console_t *console, const char *s )
void console_put_newline( console_t *console )
{
- if( console->vga != NULL ) {
- vga_put_newline( console->vga );
+ if( console->vga_text != NULL ) {
+ vga_text_put_newline( console->vga_text );
}
if( console->serial != NULL ) {
diff --git a/src/console.h b/src/console.h
index f8eccff..a1c55ac 100644
--- a/src/console.h
+++ b/src/console.h
@@ -1,16 +1,16 @@
#ifndef CONSOLE_H
#define CONSOLE_H
-#include "vga.h"
+#include "vgatext.h"
#include "serial.h"
typedef struct {
- vga_t *vga;
+ vga_text_t *vga_text;
serial_t *serial;
} console_t;
void console_init( console_t *console );
-void console_add_vga_output( console_t *console, vga_t *vga );
+void console_add_vga_text_output( console_t *console, vga_text_t *vga_text );
void console_add_serial_output( console_t *console, serial_t *serial );
void console_put_char( console_t *console, const char c );
void console_put_string( console_t *console, const char *s );
diff --git a/src/kernel.c b/src/kernel.c
index 3f873ef..3c520d6 100644
--- a/src/kernel.c
+++ b/src/kernel.c
@@ -2,7 +2,7 @@
#include <stdint.h>
#include <stdarg.h>
-#include "vga.h"
+#include "vgatext.h"
#include "serial.h"
#include "console.h"
#include "stdlib.h"
@@ -35,14 +35,14 @@ void kernel_main( void )
serial_t serial;
serial_init( &serial );
- vga_t vga;
- vga_init( &vga );
- vga_set_color( &vga, VGA_COLOR_LIGHT_GREY );
- vga_set_background_color( &vga, VGA_COLOR_BLACK );
+ vga_text_t vga_text;
+ vga_text_init( &vga_text );
+ vga_text_set_color( &vga_text, VGA_TEXT_COLOR_LIGHT_GREY );
+ vga_text_set_background_color( &vga_text, VGA_TEXT_COLOR_BLACK );
console_t console;
console_init( &console );
- console_add_vga_output( &console, &vga );
+ console_add_vga_text_output( &console, &vga_text );
console_add_serial_output( &console, &serial );
// initialize the early console of the kernel
@@ -68,14 +68,14 @@ void kernel_main( void )
// hard-wired drivers
keyboard_t keyboard;
- keyboard_init( &keyboard, &handle_keyboard_event, (void *)&vga );
+ keyboard_init( &keyboard, &handle_keyboard_event, (void *)&vga_text );
interrupt_handler_t keyboard_interrupt_handler;
interrupt_handler_init( &keyboard_interrupt_handler, IRQ_BASE + 0x01, &interrupt, keyboard_handle_interrupt, &keyboard );
interrupts_register_interrupt_handler( keyboard_interrupt_handler );
driver_manager_add_driver( &driver_manager, (driver_t *)&keyboard );
mouse_t mouse;
- mouse_init( &mouse, &handle_mouse_event, (void *)&vga );
+ mouse_init( &mouse, &handle_mouse_event, (void *)&vga_text );
interrupt_handler_t mouse_interrupt_handler;
interrupt_handler_init( &mouse_interrupt_handler, IRQ_BASE + 0x0C, &interrupt, mouse_handle_interrupt, &mouse );
interrupts_register_interrupt_handler( mouse_interrupt_handler );
@@ -136,9 +136,9 @@ static void handle_keyboard_event( keyboard_event_t *event, void *context )
{
static int pos = 0;
static char buf[80];
- vga_t *vga = (vga_t *)context;
+ vga_text_t *vga_text = (vga_text_t *)context;
- vga_hide_mouse_cursor( vga );
+ vga_text_hide_mouse_cursor( vga_text );
if( event->type == KEYBOARD_EVENT_TYPE_KEY_PRESSED ) {
if( event->key == KEYBOARD_KEY_ASCII ) {
@@ -177,26 +177,26 @@ static void handle_keyboard_event( keyboard_event_t *event, void *context )
static void handle_mouse_event( mouse_event_t *event, void *context )
{
- vga_t *vga = (vga_t *)context;
+ vga_text_t *vga_text = (vga_text_t *)context;
switch( event->type ) {
case MOUSE_EVENT_TYPE_BUTTON_UP:
- vga_hide_mouse_cursor( vga );
+ vga_text_hide_mouse_cursor( vga_text );
printf( "MOUSE UP %d AT X:%d, Y:%d\n", event->button, event->cursor_x,
event->cursor_y );
- vga_show_mouse_cursor( vga );
+ vga_text_show_mouse_cursor( vga_text );
break;
case MOUSE_EVENT_TYPE_BUTTON_DOWN:
- vga_hide_mouse_cursor( vga );
+ vga_text_hide_mouse_cursor( vga_text );
printf( "MOUSE DOWN %d AT X:%d, Y:%d\n", event->button, event->cursor_x,
event->cursor_y );
- vga_show_mouse_cursor( vga );
+ vga_text_show_mouse_cursor( vga_text );
break;
case MOUSE_EVENT_TYPE_MOVE:
- vga_move_mouse_cursor( vga, event->cursor_x, event->cursor_y );
- vga_show_mouse_cursor( vga );
+ vga_text_move_mouse_cursor( vga_text, event->cursor_x, event->cursor_y );
+ vga_text_show_mouse_cursor( vga_text );
break;
}
}
diff --git a/src/mouse.c b/src/mouse.c
index 0e1d736..46984eb 100644
--- a/src/mouse.c
+++ b/src/mouse.c
@@ -92,10 +92,10 @@ void mouse_init( mouse_t *mouse, mouse_event_handler_t handler, void *context )
// TODO: we should probe for wheel mouse and more than 3 packets
mouse->nof_packets = DEFAULT_NOF_PACKETS;
- vga_t *vga = (vga_t *)context;
+ vga_text_t *vga_text = (vga_text_t *)context;
- mouse->res_x = vga->res_x;
- mouse->res_y = vga->res_y;
+ mouse->res_x = vga_text->res_x;
+ mouse->res_y = vga_text->res_y;
mouse->cursor_x = mouse->res_x / 2;
mouse->cursor_y = mouse->res_y / 2;
mouse->handler = handler;
diff --git a/src/vga.c b/src/vga.c
deleted file mode 100644
index 1356d62..0000000
--- a/src/vga.c
+++ /dev/null
@@ -1,262 +0,0 @@
-#include "vga.h"
-
-#include <stdbool.h>
-
-#include "string.h"
-#include "stdlib.h"
-#include "kernel.h"
-
-static bool params_ok( vga_t *vga, const int x, const int y );
-static int calculate_offset( vga_t *vga, const int x, const int y );
-static uint8_t calculate_color_cell( vga_t *vga );
-static void scroll_screen( vga_t *vga );
-
-void vga_init( vga_t *vga )
-{
- memset( vga, 0, sizeof( vga_t ) );
-
- vga->res_x = VGA_DEFAULT_RES_X;
- vga->res_y = VGA_DEFAULT_RES_Y;
- vga->color = VGA_COLOR_DARK_GREY;
- vga->background_color = VGA_COLOR_BLACK;
- vga->show_mouse_cursor = false;
- vga->mouse_cursor_x = -1;
- vga->mouse_cursor_y = -1;
-
- // make sure we use the 0x3dx VGA ports, is done
- // in assembly in stage 2 too
- port8_init( &vga->crtc_misc_port, 0x3d2 );
- port8_write( &vga->crtc_misc_port, 1 );
-
- // set up VGA ports
- port8_init( &vga->crtc_index_port, 0x3d4 );
- port8_init( &vga->crtc_data_port, 0x3d5 );
-
- vga_set_cursor_from_hardware( vga );
-};
-
-void vga_clear_screen( vga_t *vga )
-{
- volatile uint8_t *VIDEO_MEMORY = (uint8_t *)0xb8000;
-
- for( int i = 0; i < 2 * ( vga->res_x * vga->res_y ); i += 2 ) {
- *(VIDEO_MEMORY+i) = ' ';
- *(VIDEO_MEMORY+i+1) = calculate_color_cell( vga );
- }
-
- vga_set_cursor( vga, 0, 0 );
-}
-
-void vga_set_cursor( vga_t *vga, const int x, const int y )
-{
- if( !params_ok( vga, x, y ) ) {
- kernel_panic( "Cursor parameters out of bounds: (%d, %d), resolution is only (%d, %d)",
- x, y, vga->res_x, vga->res_y );
- }
-
- vga->cursor_x = x;
- vga->cursor_y = y;
-
- // TODO: have a silent mode where we don't update the cursor
- vga_set_cursor_on_hardware( vga );
-}
-
-void vga_set_cursor_from_hardware( vga_t *vga )
-{
- uint16_t hw_cursor_pos;
-
- port8_write( &vga->crtc_index_port, 14 );
- uint8_t data = port8_read( &(vga->crtc_data_port ) );
- hw_cursor_pos = data << 8;
-
- port8_write( &vga->crtc_index_port, 15 );
- data = port8_read( &(vga->crtc_data_port ) );
-
- hw_cursor_pos |= data;
-
- vga->cursor_x = hw_cursor_pos % vga->res_x;
- vga->cursor_y = hw_cursor_pos / vga->res_x;
-
- // reset to sane values if we get funny values from the VGA card
- if( vga->cursor_x < 0 || vga->cursor_x > vga->res_x ||
- vga->cursor_y < 0 || vga->cursor_y > vga->res_y ) {
- vga->cursor_x = 0;
- vga->cursor_y = 0;
- }
-}
-
-void vga_set_cursor_on_hardware( vga_t *vga )
-{
- uint16_t hw_cursor_pos = vga->cursor_x + vga->cursor_y * vga->res_x;
-
- port8_write( &vga->crtc_index_port, 15 );
- port8_write( &vga->crtc_data_port, hw_cursor_pos & 0xff );
- port8_write( &vga->crtc_index_port, 14 );
- port8_write( &vga->crtc_data_port, hw_cursor_pos >> 8 );
-}
-
-int vga_get_cursor_x( vga_t *vga )
-{
- return vga->cursor_x;
-}
-
-int vga_get_cursor_y( vga_t *vga )
-{
- return vga->cursor_y;
-}
-
-void vga_set_color( vga_t *vga, const vga_color_t color )
-{
- vga->color = color;
-}
-
-void vga_set_background_color( vga_t *vga, const vga_color_t color )
-{
- vga->background_color = color;
-}
-
-static int calculate_offset( vga_t *vga, const int x, const int y )
-{
- int offset = ( vga->res_x * y + x ) * 2;
-
- return offset;
-}
-
-static void scroll_screen( vga_t *vga )
-{
- volatile uint8_t *VIDEO_MEMORY = (uint8_t *)0xb8000;
-
- memmove( (void *)VIDEO_MEMORY, (const void *)VIDEO_MEMORY + 2 * vga->res_x, 2 * ( vga->res_y - 1 ) * vga->res_x );
-
- for( int i = 2 * ( vga->res_x * ( vga->res_y - 1 ) ); i < 2 * ( vga->res_x * vga->res_y ); i += 2 ) {
- *(VIDEO_MEMORY+i) = ' ';
- *(VIDEO_MEMORY+i+1) = calculate_color_cell( vga );
- }
-
- vga->cursor_y = vga->res_y - 1;
-}
-
-static uint8_t calculate_color_cell( vga_t *vga )
-{
- uint8_t cell;
-
- cell = ( vga->background_color << 4 ) | vga->color;
-
- return cell;
-}
-
-static bool params_ok( vga_t *vga, const int x, const int y )
-{
- if( x > vga->res_x || y > vga->res_y ) return false;
-
- return true;
-}
-
-void vga_put_char_at( vga_t *vga, const int x, const int y, const char c )
-{
- vga_set_cursor( vga, x, y );
- vga_put_char( vga, c );
-}
-
-
-void vga_put_string_at( vga_t *vga, const int x, const int y, const char *s )
-{
- vga_set_cursor( vga, x, y );
- vga_put_string( vga, s );
-}
-
-void vga_put_char( vga_t *vga, const char c )
-{
- int offset = calculate_offset( vga, vga->cursor_x, vga->cursor_y );
-
- volatile uint8_t *VIDEO_MEMORY = (uint8_t *)0xb8000;
- *(VIDEO_MEMORY+offset) = (uint8_t)c;
- *(VIDEO_MEMORY+offset+1) = calculate_color_cell( vga );
-
- vga->cursor_x++;
- if( vga->cursor_x >= vga->res_x ) {
- vga->cursor_x = 0;
- vga->cursor_y++;
- if( vga->cursor_y >= vga->res_y ) {
- scroll_screen( vga );
- }
- }
-
- vga_set_cursor_on_hardware( vga );
-}
-
-void vga_put_string( vga_t *vga, const char *s )
-{
- for( size_t i = 0; i < strlen( s ); i++ ) {
- vga_put_char( vga, s[i] );
- }
-}
-
-void vga_put_newline( vga_t *vga )
-{
- vga->cursor_x = 0;
- vga->cursor_y++;
- if( vga->cursor_y >= vga->res_y ) {
- scroll_screen( vga );
- }
-
- vga_set_cursor_on_hardware( vga );
-}
-
-void vga_set_background_color_at( vga_t *vga, const int x, const int y, vga_color_t color )
-{
- int offset = calculate_offset( vga, x, y );
-
- volatile uint8_t *VIDEO_MEMORY = (uint8_t *)0xb8000;
- *(VIDEO_MEMORY+offset+1) = ( *(VIDEO_MEMORY+offset+1) & 0x0f ) | ( color << 4 );
-}
-
-vga_color_t vga_get_background_color_at( vga_t *vga, const int x, const int y )
-{
- int offset = calculate_offset( vga, x, y );
-
- volatile uint8_t *VIDEO_MEMORY = (uint8_t *)0xb8000;
- uint8_t cell = *(VIDEO_MEMORY+offset+1);
-
- return cell & 0xf0;
-}
-
-void vga_inverse_colors_at( vga_t *vga, const int x, const int y )
-{
- int offset = calculate_offset( vga, x, y );
-
- volatile uint8_t *VIDEO_MEMORY = (uint8_t *)0xb8000;
- *(VIDEO_MEMORY+offset+1) = ( ( *(VIDEO_MEMORY+offset+1) & 0x0f ) << 4 )
- | ( ( *(VIDEO_MEMORY+offset+1) & 0xf0 ) >> 4 );
-}
-
-void vga_show_mouse_cursor( vga_t *vga )
-{
- if( !vga->show_mouse_cursor ) {
- vga->show_mouse_cursor = true;
- vga_inverse_colors_at( vga, vga->mouse_cursor_x, vga->mouse_cursor_y );
- }
-}
-
-void vga_move_mouse_cursor( vga_t *vga, const int x, const int y )
-{
- if( vga->show_mouse_cursor ) {
- vga_inverse_colors_at( vga, vga->mouse_cursor_x, vga->mouse_cursor_y );
- }
-
- vga->mouse_cursor_x = x;
- vga->mouse_cursor_y = y;
-
- if( vga->show_mouse_cursor ) {
- vga_inverse_colors_at( vga, vga->mouse_cursor_x, vga->mouse_cursor_y );
- }
-}
-
-void vga_hide_mouse_cursor( vga_t *vga )
-{
- if( vga->show_mouse_cursor ) {
- vga_inverse_colors_at( vga, vga->mouse_cursor_x, vga->mouse_cursor_y );
- vga->show_mouse_cursor = false;
- }
-}
-
diff --git a/src/vga.h b/src/vga.h
deleted file mode 100644
index 695c228..0000000
--- a/src/vga.h
+++ /dev/null
@@ -1,68 +0,0 @@
-#ifndef VGA_H
-#define VGA_H
-
-#include <stdbool.h>
-
-#include "port.h"
-
-enum {
- VGA_DEFAULT_RES_X = 80,
- VGA_DEFAULT_RES_Y = 25
-};
-
-typedef enum {
- VGA_COLOR_BLACK = 0,
- VGA_COLOR_BLUE = 1,
- VGA_COLOR_GREEN = 2,
- VGA_COLOR_CYAN = 3,
- VGA_COLOR_RED = 4,
- VGA_COLOR_MAGENTA = 5,
- VGA_COLOR_BROWN = 6,
- VGA_COLOR_LIGHT_GREY = 7,
- VGA_COLOR_DARK_GREY = 8,
- VGA_COLOR_LIGHT_BLUE = 9,
- VGA_COLOR_LIGHT_GREEN = 10,
- VGA_COLOR_LIGHT_CYAN = 11,
- VGA_COLOR_LIGHT_RED = 12,
- VGA_COLOR_LIGHT_MAGENTA = 13,
- VGA_COLOR_LIGHT_BROWN = 14,
- VGA_COLOR_WHITE = 15
-} vga_color_t;
-
-typedef struct {
- int res_x; // resolution, default 80
- int res_y; // resolution, default 25
- int cursor_x; // current cursor position X
- int cursor_y; // current cursor position Y
- vga_color_t color;
- vga_color_t background_color;
- port8_t crtc_misc_port;
- port8_t crtc_index_port;
- port8_t crtc_data_port;
- bool show_mouse_cursor;
- int mouse_cursor_x;
- int mouse_cursor_y;
-} vga_t;
-
-void vga_init( vga_t *vga );
-void vga_clear_screen( vga_t *vga );
-void vga_set_cursor( vga_t *vga, const int x, const int y );
-void vga_set_cursor_from_hardware( vga_t *vga );
-void vga_set_cursor_on_hardware( vga_t *vga );
-int vga_get_cursor_x( vga_t *vga );
-int vga_get_cursor_y( vga_t *vga );
-void vga_set_color( vga_t *vga, const vga_color_t color );
-void vga_set_background_color( vga_t *vga, const vga_color_t color );
-void vga_put_char_at( vga_t *vga, const int x, const int y, const char c );
-void vga_put_string_at( vga_t *vga, const int x, const int y, const char *s );
-void vga_put_char( vga_t *vga, const char c );
-void vga_put_string( vga_t *vga, const char *s );
-void vga_put_newline( vga_t *vga );
-void vga_set_background_color_at( vga_t *vga, const int x, const int y, vga_color_t color );
-vga_color_t vga_get_background_color_at( vga_t *vga, const int x, const int y );
-void vga_inverse_colors_at( vga_t *vga, const int x, const int y );
-void vga_show_mouse_cursor( vga_t *vga );
-void vga_move_mouse_cursor( vga_t *vga, const int x, const int y );
-void vga_hide_mouse_cursor( vga_t *vga );
-
-#endif /* VGA_H */
diff --git a/src/vgatext.c b/src/vgatext.c
new file mode 100644
index 0000000..cbee587
--- /dev/null
+++ b/src/vgatext.c
@@ -0,0 +1,262 @@
+#include "vgatext.h"
+
+#include <stdbool.h>
+
+#include "string.h"
+#include "stdlib.h"
+#include "kernel.h"
+
+static bool params_ok( vga_text_t *vga_text, const int x, const int y );
+static int calculate_offset( vga_text_t *vga_text, const int x, const int y );
+static uint8_t calculate_color_cell( vga_text_t *vga_text );
+static void scroll_screen( vga_text_t *vga_text );
+
+void vga_text_init( vga_text_t *vga_text )
+{
+ memset( vga_text, 0, sizeof( vga_text_t ) );
+
+ vga_text->res_x = VGA_TEXT_DEFAULT_RES_X;
+ vga_text->res_y = VGA_TEXT_DEFAULT_RES_Y;
+ vga_text->color = VGA_TEXT_COLOR_DARK_GREY;
+ vga_text->background_color = VGA_TEXT_COLOR_BLACK;
+ vga_text->show_mouse_cursor = false;
+ vga_text->mouse_cursor_x = -1;
+ vga_text->mouse_cursor_y = -1;
+
+ // make sure we use the 0x3dx VGA_TEXT ports, is done
+ // in assembly in stage 2 too
+ port8_init( &vga_text->crtc_misc_port, 0x3d2 );
+ port8_write( &vga_text->crtc_misc_port, 1 );
+
+ // set up VGA_TEXT ports
+ port8_init( &vga_text->crtc_index_port, 0x3d4 );
+ port8_init( &vga_text->crtc_data_port, 0x3d5 );
+
+ vga_text_set_cursor_from_hardware( vga_text );
+};
+
+void vga_text_clear_screen( vga_text_t *vga_text )
+{
+ volatile uint8_t *VIDEO_MEMORY = (uint8_t *)0xb8000;
+
+ for( int i = 0; i < 2 * ( vga_text->res_x * vga_text->res_y ); i += 2 ) {
+ *(VIDEO_MEMORY+i) = ' ';
+ *(VIDEO_MEMORY+i+1) = calculate_color_cell( vga_text );
+ }
+
+ vga_text_set_cursor( vga_text, 0, 0 );
+}
+
+void vga_text_set_cursor( vga_text_t *vga_text, const int x, const int y )
+{
+ if( !params_ok( vga_text, x, y ) ) {
+ kernel_panic( "Cursor parameters out of bounds: (%d, %d), resolution is only (%d, %d)",
+ x, y, vga_text->res_x, vga_text->res_y );
+ }
+
+ vga_text->cursor_x = x;
+ vga_text->cursor_y = y;
+
+ // TODO: have a silent mode where we don't update the cursor
+ vga_text_set_cursor_on_hardware( vga_text );
+}
+
+void vga_text_set_cursor_from_hardware( vga_text_t *vga_text )
+{
+ uint16_t hw_cursor_pos;
+
+ port8_write( &vga_text->crtc_index_port, 14 );
+ uint8_t data = port8_read( &(vga_text->crtc_data_port ) );
+ hw_cursor_pos = data << 8;
+
+ port8_write( &vga_text->crtc_index_port, 15 );
+ data = port8_read( &(vga_text->crtc_data_port ) );
+
+ hw_cursor_pos |= data;
+
+ vga_text->cursor_x = hw_cursor_pos % vga_text->res_x;
+ vga_text->cursor_y = hw_cursor_pos / vga_text->res_x;
+
+ // reset to sane values if we get funny values from the VGA_TEXT card
+ if( vga_text->cursor_x < 0 || vga_text->cursor_x > vga_text->res_x ||
+ vga_text->cursor_y < 0 || vga_text->cursor_y > vga_text->res_y ) {
+ vga_text->cursor_x = 0;
+ vga_text->cursor_y = 0;
+ }
+}
+
+void vga_text_set_cursor_on_hardware( vga_text_t *vga_text )
+{
+ uint16_t hw_cursor_pos = vga_text->cursor_x + vga_text->cursor_y * vga_text->res_x;
+
+ port8_write( &vga_text->crtc_index_port, 15 );
+ port8_write( &vga_text->crtc_data_port, hw_cursor_pos & 0xff );
+ port8_write( &vga_text->crtc_index_port, 14 );
+ port8_write( &vga_text->crtc_data_port, hw_cursor_pos >> 8 );
+}
+
+int vga_text_get_cursor_x( vga_text_t *vga_text )
+{
+ return vga_text->cursor_x;
+}
+
+int vga_text_get_cursor_y( vga_text_t *vga_text )
+{
+ return vga_text->cursor_y;
+}
+
+void vga_text_set_color( vga_text_t *vga_text, const vga_text_color_t color )
+{
+ vga_text->color = color;
+}
+
+void vga_text_set_background_color( vga_text_t *vga_text, const vga_text_color_t color )
+{
+ vga_text->background_color = color;
+}
+
+static int calculate_offset( vga_text_t *vga_text, const int x, const int y )
+{
+ int offset = ( vga_text->res_x * y + x ) * 2;
+
+ return offset;
+}
+
+static void scroll_screen( vga_text_t *vga_text )
+{
+ volatile uint8_t *VIDEO_MEMORY = (uint8_t *)0xb8000;
+
+ memmove( (void *)VIDEO_MEMORY, (const void *)VIDEO_MEMORY + 2 * vga_text->res_x, 2 * ( vga_text->res_y - 1 ) * vga_text->res_x );
+
+ for( int i = 2 * ( vga_text->res_x * ( vga_text->res_y - 1 ) ); i < 2 * ( vga_text->res_x * vga_text->res_y ); i += 2 ) {
+ *(VIDEO_MEMORY+i) = ' ';
+ *(VIDEO_MEMORY+i+1) = calculate_color_cell( vga_text );
+ }
+
+ vga_text->cursor_y = vga_text->res_y - 1;
+}
+
+static uint8_t calculate_color_cell( vga_text_t *vga_text )
+{
+ uint8_t cell;
+
+ cell = ( vga_text->background_color << 4 ) | vga_text->color;
+
+ return cell;
+}
+
+static bool params_ok( vga_text_t *vga_text, const int x, const int y )
+{
+ if( x > vga_text->res_x || y > vga_text->res_y ) return false;
+
+ return true;
+}
+
+void vga_text_put_char_at( vga_text_t *vga_text, const int x, const int y, const char c )
+{
+ vga_text_set_cursor( vga_text, x, y );
+ vga_text_put_char( vga_text, c );
+}
+
+
+void vga_text_put_string_at( vga_text_t *vga_text, const int x, const int y, const char *s )
+{
+ vga_text_set_cursor( vga_text, x, y );
+ vga_text_put_string( vga_text, s );
+}
+
+void vga_text_put_char( vga_text_t *vga_text, const char c )
+{
+ int offset = calculate_offset( vga_text, vga_text->cursor_x, vga_text->cursor_y );
+
+ volatile uint8_t *VIDEO_MEMORY = (uint8_t *)0xb8000;
+ *(VIDEO_MEMORY+offset) = (uint8_t)c;
+ *(VIDEO_MEMORY+offset+1) = calculate_color_cell( vga_text );
+
+ vga_text->cursor_x++;
+ if( vga_text->cursor_x >= vga_text->res_x ) {
+ vga_text->cursor_x = 0;
+ vga_text->cursor_y++;
+ if( vga_text->cursor_y >= vga_text->res_y ) {
+ scroll_screen( vga_text );
+ }
+ }
+
+ vga_text_set_cursor_on_hardware( vga_text );
+}
+
+void vga_text_put_string( vga_text_t *vga_text, const char *s )
+{
+ for( size_t i = 0; i < strlen( s ); i++ ) {
+ vga_text_put_char( vga_text, s[i] );
+ }
+}
+
+void vga_text_put_newline( vga_text_t *vga_text )
+{
+ vga_text->cursor_x = 0;
+ vga_text->cursor_y++;
+ if( vga_text->cursor_y >= vga_text->res_y ) {
+ scroll_screen( vga_text );
+ }
+
+ vga_text_set_cursor_on_hardware( vga_text );
+}
+
+void vga_text_set_background_color_at( vga_text_t *vga_text, const int x, const int y, vga_text_color_t color )
+{
+ int offset = calculate_offset( vga_text, x, y );
+
+ volatile uint8_t *VIDEO_MEMORY = (uint8_t *)0xb8000;
+ *(VIDEO_MEMORY+offset+1) = ( *(VIDEO_MEMORY+offset+1) & 0x0f ) | ( color << 4 );
+}
+
+vga_text_color_t vga_text_get_background_color_at( vga_text_t *vga_text, const int x, const int y )
+{
+ int offset = calculate_offset( vga_text, x, y );
+
+ volatile uint8_t *VIDEO_MEMORY = (uint8_t *)0xb8000;
+ uint8_t cell = *(VIDEO_MEMORY+offset+1);
+
+ return cell & 0xf0;
+}
+
+void vga_text_inverse_colors_at( vga_text_t *vga_text, const int x, const int y )
+{
+ int offset = calculate_offset( vga_text, x, y );
+
+ volatile uint8_t *VIDEO_MEMORY = (uint8_t *)0xb8000;
+ *(VIDEO_MEMORY+offset+1) = ( ( *(VIDEO_MEMORY+offset+1) & 0x0f ) << 4 )
+ | ( ( *(VIDEO_MEMORY+offset+1) & 0xf0 ) >> 4 );
+}
+
+void vga_text_show_mouse_cursor( vga_text_t *vga_text )
+{
+ if( !vga_text->show_mouse_cursor ) {
+ vga_text->show_mouse_cursor = true;
+ vga_text_inverse_colors_at( vga_text, vga_text->mouse_cursor_x, vga_text->mouse_cursor_y );
+ }
+}
+
+void vga_text_move_mouse_cursor( vga_text_t *vga_text, const int x, const int y )
+{
+ if( vga_text->show_mouse_cursor ) {
+ vga_text_inverse_colors_at( vga_text, vga_text->mouse_cursor_x, vga_text->mouse_cursor_y );
+ }
+
+ vga_text->mouse_cursor_x = x;
+ vga_text->mouse_cursor_y = y;
+
+ if( vga_text->show_mouse_cursor ) {
+ vga_text_inverse_colors_at( vga_text, vga_text->mouse_cursor_x, vga_text->mouse_cursor_y );
+ }
+}
+
+void vga_text_hide_mouse_cursor( vga_text_t *vga_text )
+{
+ if( vga_text->show_mouse_cursor ) {
+ vga_text_inverse_colors_at( vga_text, vga_text->mouse_cursor_x, vga_text->mouse_cursor_y );
+ vga_text->show_mouse_cursor = false;
+ }
+}
+
diff --git a/src/vgatext.h b/src/vgatext.h
new file mode 100644
index 0000000..499e3d8
--- /dev/null
+++ b/src/vgatext.h
@@ -0,0 +1,68 @@
+#ifndef VGA_TEXT_H
+#define VGA_TEXT_H
+
+#include <stdbool.h>
+
+#include "port.h"
+
+enum {
+ VGA_TEXT_DEFAULT_RES_X = 80,
+ VGA_TEXT_DEFAULT_RES_Y = 25
+};
+
+typedef enum {
+ VGA_TEXT_COLOR_BLACK = 0,
+ VGA_TEXT_COLOR_BLUE = 1,
+ VGA_TEXT_COLOR_GREEN = 2,
+ VGA_TEXT_COLOR_CYAN = 3,
+ VGA_TEXT_COLOR_RED = 4,
+ VGA_TEXT_COLOR_MAGENTA = 5,
+ VGA_TEXT_COLOR_BROWN = 6,
+ VGA_TEXT_COLOR_LIGHT_GREY = 7,
+ VGA_TEXT_COLOR_DARK_GREY = 8,
+ VGA_TEXT_COLOR_LIGHT_BLUE = 9,
+ VGA_TEXT_COLOR_LIGHT_GREEN = 10,
+ VGA_TEXT_COLOR_LIGHT_CYAN = 11,
+ VGA_TEXT_COLOR_LIGHT_RED = 12,
+ VGA_TEXT_COLOR_LIGHT_MAGENTA = 13,
+ VGA_TEXT_COLOR_LIGHT_BROWN = 14,
+ VGA_TEXT_COLOR_WHITE = 15
+} vga_text_color_t;
+
+typedef struct {
+ int res_x; // resolution, default 80
+ int res_y; // resolution, default 25
+ int cursor_x; // current cursor position X
+ int cursor_y; // current cursor position Y
+ vga_text_color_t color;
+ vga_text_color_t background_color;
+ port8_t crtc_misc_port;
+ port8_t crtc_index_port;
+ port8_t crtc_data_port;
+ bool show_mouse_cursor;
+ int mouse_cursor_x;
+ int mouse_cursor_y;
+} vga_text_t;
+
+void vga_text_init( vga_text_t *vga_text );
+void vga_text_clear_screen( vga_text_t *vga_text );
+void vga_text_set_cursor( vga_text_t *vga_text, const int x, const int y );
+void vga_text_set_cursor_from_hardware( vga_text_t *vga_text );
+void vga_text_set_cursor_on_hardware( vga_text_t *vga_text );
+int vga_text_get_cursor_x( vga_text_t *vga_text );
+int vga_text_get_cursor_y( vga_text_t *vga_text );
+void vga_text_set_color( vga_text_t *vga_text, const vga_text_color_t color );
+void vga_text_set_background_color( vga_text_t *vga_text, const vga_text_color_t color );
+void vga_text_put_char_at( vga_text_t *vga_text, const int x, const int y, const char c );
+void vga_text_put_string_at( vga_text_t *vga_text, const int x, const int y, const char *s );
+void vga_text_put_char( vga_text_t *vga_text, const char c );
+void vga_text_put_string( vga_text_t *vga_text, const char *s );
+void vga_text_put_newline( vga_text_t *vga_text );
+void vga_text_set_background_color_at( vga_text_t *vga_text, const int x, const int y, vga_text_color_t color );
+vga_text_color_t vga_text_get_background_color_at( vga_text_t *vga_text, const int x, const int y );
+void vga_text_inverse_colors_at( vga_text_t *vga_text, const int x, const int y );
+void vga_text_show_mouse_cursor( vga_text_t *vga_text );
+void vga_text_move_mouse_cursor( vga_text_t *vga_text, const int x, const int y );
+void vga_text_hide_mouse_cursor( vga_text_t *vga_text );
+
+#endif /* VGA_TEXT_H */