//------------------------------------------------------------------- // cgademo.cpp // // This program demonstrates early IBM-PC graphics programming // with 32KB of installed video memory (real address 0xB8000), // supporting either 2-colors or 4-colors using "packed-pixel" // memory organization, using two separate 16KB display pages. // (Supported by VGA/SVGA devices for backward compatibility.) // // programmer: ALLAN CRUSE // written on: 07 SEP 2003 //------------------------------------------------------------------- #include // for printf(), perror() #include // for open() #include // for exit() #include // for close() #include // for mman() typedef unsigned char u8; u8 *vram = (u8*)0x000B8000; int hres, vres; void (*set_pixel)( int x, int y, int color ); void set_pixel_1( int x, int y, int color ) { int posn = 0x2000*(y % 2) + 80*(y / 2) + (x / 8); int mask = 0x80 >> (x % 8); u8 temp = vram[ posn ]; color &= 1; color <<= 7; color >>= (x % 8); temp &= ~mask; temp |= color; vram[ posn ] = temp; } void set_pixel_2( int x, int y, int color ) { int posn = 0x2000*(y % 2) + 80*(y / 2) + ((2 * x) / 8); int mask = 0xC0 >> ((2 * x) % 8); u8 temp = vram[ posn ]; color &= 3; color <<= 6; color >>= ((2 * x) % 8); temp &= ~mask; temp |= color; vram[ posn ] = temp; } void map_vram( int base, int size ); int main( int argc, char **argv ) { int base = (int)vram; int size = (32 << 10); map_vram( base, size ); int minx, midx, maxx, miny, midy, maxy; int x, y, color, radius_squared; //--------------------------------------------- // Demonstrate CGA color graphics (VGA mode 5) //--------------------------------------------- system( "clear ; mode3 5 " ); // 320x200, 4-colors hres = 320, vres = 200, set_pixel = set_pixel_2; // draw screen border color = 3; // white minx = 0, maxx = hres-1; miny = 0, maxy = vres-1; x = y = 0; do { set_pixel( x, y, color ); ++x; } while ( x < maxx ); do { set_pixel( x, y, color ); ++y; } while ( y < maxy ); do { set_pixel( x, y, color ); --x; } while ( x > minx ); do { set_pixel( x, y, color ); --y; } while ( y > miny ); getchar(); // fill circle (unrescaled) midx = hres/2; midy = vres/2; radius_squared = 60*60; for (y = 4; y <= maxy-4; y++) for (x = 4; x <= maxx-4; x++) { int dx = x - midx; int dy = y - midy; int dist_squared = dx*dx + dy*dy; color = ( dist_squared < radius_squared ) ? 1 : 2; set_pixel( x, y, color ); } getchar(); // fill circle (adjusted) radius_squared *= 30; for (y = 4; y <= maxy-4; y++) for (x = 4; x <= maxx-4; x++) { int dx = (x - midx)*5; int dy = (y - midy)*6; int dist_squared = dx*dx + dy*dy; color = ( dist_squared < radius_squared ) ? 1 : 2; set_pixel( x, y, color ); } getchar(); //-------------------------------------------------- // Demonstrate CGA monochrome graphics (VGA mode 6) //-------------------------------------------------- system( "clear ; mode3 6 " ); // 640x200, 2-colors hres = 640, vres = 200, set_pixel = set_pixel_1; // draw screen border minx = 0, maxx = hres-1; miny = 0, maxy = vres-1; x = y = 0; color = 1; // white do { set_pixel( x, y, color ); ++x; } while ( x < maxx ); do { set_pixel( x, y, color ); ++y; } while ( y < maxy ); do { set_pixel( x, y, color ); --x; } while ( x > minx ); do { set_pixel( x, y, color ); --y; } while ( y > miny ); getchar(); // fill circle (unrescaled) midx = hres/2; midy = vres/2; radius_squared = 60*60; for (y = 4; y <= maxy-4; y++) for (x = 4; x <= maxx-4; x++) { int dx = x - midx; int dy = y - midy; int dist_squared = dx*dx + dy*dy; color = ( dist_squared < radius_squared ) ? 1 : 0; set_pixel( x, y, color ); } getchar(); // fill circle (adjusted) radius_squared *= 60; for (y = 4; y <= maxy-4; y++) for (x = 4; x <= maxx-4; x++) { int dx = (x - midx)*5; int dy = (y - midy)*12; int dist_squared = dx*dx + dy*dy; color = ( dist_squared < radius_squared ) ? 1 : 0; set_pixel( x, y, color ); } getchar(); system( " mode3 3 " ); // standard 80x25 text mode } void map_vram( int base, int size ) { int fd = open( "/dev/mem", O_RDWR ); if ( fd < 0 ) { perror( "/dev/mem" ); exit(1); } int prot = PROT_READ | PROT_WRITE; int flag = MAP_FIXED | MAP_SHARED; void *mm = (void*)base; if ( mmap( mm, size, prot, flag, fd, base ) == MAP_FAILED ) { perror( "mmap" ); exit(1); } close( fd ); }