#include "vga.h" #include #include "string.h" #include "stdlib.h" static bool params_ok( vga_t *vga, const int x, const int y ); static int calculate_offset( vga_t *vga ); 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; // 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 ) { // TODO: PANIC? OUT OF BOUND ACCESS if( !params_ok( vga, x, y ) ) return; 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 ) { int offset = ( vga->res_x * vga->cursor_y + vga->cursor_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 ); 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_hex( vga_t *vga, const uint32_t v ) { char buf[9]; vga_put_string( vga, "0x" ); itoa( v, (char *)buf, 16 ); vga_put_string( vga, (const char *)buf ); } 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 ); }