//------------------------------------------------------------------- // drawtext.cpp // // This program shows how a graphics application can draw text, // based on a character glyph-table stored in the VGA firmware. // // compile using: g++ drawtext.cpp lrmi.o -o drawtext // // programmer: ALLAN CRUSE // written on: 14 SEP 2003 //------------------------------------------------------------------- extern "C" int LRMI_init( void ), LRMI_int( int, struct LRMI_regs * ); #include "lrmi.h" // for LRMI_init(), LRMI_int() #include // for printf(), perror() #include // for open() #include // for exit() #include // for close() #include // for mman() #include // for iopl() #define VRAM_BASE_ADDRESS 0x000A0000 #define VGA_WINDOW_LENGTH (64 << 10) unsigned char glyph[ 256][ 16 ]; unsigned char *vram = (unsigned char*)VRAM_BASE_ADDRESS; int display_mode = 19, hres = 320, vres = 200; void draw_character( int x, int y, int ascii, int color ) { unsigned char *dstn = &vram[ y*hres + x ]; for (int i = 0; i < 14; i++) { int bits = glyph[ ascii ][ i ]; for (int j = 0; j < 8; j++) if ( bits & ( 0x80 >> j ) ) dstn[ j ] = color; dstn += hres; } } void map_system_memory( int base, int size ) { int prot = PROT_READ | PROT_WRITE; int flag = MAP_FIXED | MAP_SHARED; void *mm = (void*)base; int fd = open( "/dev/mem", O_RDWR ); if ( fd < 0 ) { perror( "/dev/mem" ); exit(1); } if ( mmap( mm, size, prot, flag, fd, base ) == MAP_FAILED ) { perror( "mmap" ); exit(1); } close( fd ); } int main( int argc, char **argv ) { if ( iopl( 3 ) ) { perror( "iopl" ); exit(1); } if ( !LRMI_init() ) { perror( "LRMI_init" ); exit(1); } // find and copy the ROM character-table to our 'glyph' array struct LRMI_regs reg = {0}; reg.eax = 0x1130; // get font information reg.ebx = 0x0200; // address of 8x14 font LRMI_int( 0x10, ® ); // BIOS service routine int font_base = ( reg.es << 4 ) + ( reg.ebp & 0xFFFF ); int vrom_base = font_base & ~0xFFF; int vrom_size = 0x1000; // 256*32 map_system_memory( vrom_base, vrom_size ); int i, j; unsigned char *font = (unsigned char*)font_base; for (i = 0; i < 256; i++) for (j = 0; j < 14; j++) glyph[ i ][ j ] = *font++; printf( "\033[H\033[J\nfont_base: %08X \n\n", font_base ); getchar(); // map the video memory and enter graphics mode int vram_base = VRAM_BASE_ADDRESS; int vram_size = VGA_WINDOW_LENGTH; map_system_memory( vram_base, vram_size ); reg.eax = display_mode; LRMI_int( 0x10, ® ); // draw a screen border int minx = 0, maxx = hres-1, miny = 0, maxy = vres-1; int x = 0, y = 0, color = 15; do { vram[ y*hres + x ] = color; ++x; } while ( x < maxx ); do { vram[ y*hres + x ] = color; ++y; } while ( y < maxy ); do { vram[ y*hres + x ] = color; --x; } while ( x > minx ); do { vram[ y*hres + x ] = color; --y; } while ( y > miny ); getchar(); // fill the screen area with a colored pattern color = 9; for (y = 1; y < vres-1; y++) for (x = 1; x < hres-1; x++) if (( x % 2 )&&( y % 2 )) vram[ y*hres + x ] = color; getchar(); // draw some text on the patterned background char message[] = "Hello, world!"; int len = sizeof( message ) - 1; int wide = 8*len, high = 14; x = ( hres - wide )/2; y = ( vres - high )/2; color = 14; for (i = 0; i < len; i++) { draw_character( x, y, message[i], color ); x += 8; } getchar(); // restore text mode reg.eax = 0x0003; LRMI_int( 0x10, ® ); }