//------------------------------------------------------------------- // bresdemo.cpp // // This program uses Bresenham's Algorithm to draw some lines. // // compile using: $ g++ bresdemo.cpp int86.cpp -o bresdemo // // programmer: ALLAN CRUSE // written on: 29 SEP 2003 // revised on: 30 SEP 2005 -- replaced svgalib with 'int86()' //------------------------------------------------------------------- #include // for printf(), perror() #include // for open() #include // for exit() #include // for lseek() #include // for mman() #include "int86.h" // for init8086(), int86() unsigned char *vram = (unsigned char*)0xA0000000; int vesa_mode = 0x4101, hres = 640, vres = 480; struct vm86plus_struct vm; void exchange( int &x1, int &y1, int &x2, int &y2 ) { int temp; temp = x1; x1 = x2; x2 = temp; temp = y1; y1 = y2; y2 = temp; } void octant_odd( int x1, int y1, int x2, int y2, int color ) { // make sure x1 <= x2 if ( x1 > x2 ) exchange( x1, y1, x2, y2 ); int xinc = ( x2 > x1 ) ? 1 : -1; int yinc = ( y2 > y1 ) ? 1 : -1; int dx = (x2-x1)*xinc; int dy = (y2-y1)*yinc; int errorterm = -dx; for (int x = x1, y = y1; x <= x2; x++) { vram[ y*hres + x ] = color; errorterm += (dy+dy); if ( errorterm >= 0 ) { y += yinc; errorterm -= (dx+dx); } } } void octant_even( int x1, int y1, int x2, int y2, int color ) { // make sure y1 <= y2 if ( y1 > y2 ) exchange( x1, y1, x2, y2 ); int xinc = ( x2 > x1 ) ? 1 : -1; int yinc = ( y2 > y1 ) ? 1 : -1; int dx = (x2-x1)*xinc; int dy = (y2-y1)*yinc; int errorterm = -dy; for (int x = x1, y = y1; y <= y2; y++) { vram[ y*hres + x ] = color; errorterm += (dx+dx); if ( errorterm >= 0 ) { x += xinc; errorterm -= (dy+dy); } } } void draw_line( int x1, int y1, int x2, int y2, int color ) { int deltax = ( x1 < x2 ) ? x2-x1 : x1-x2; int deltay = ( y1 < y2 ) ? y2-y1 : y1-y2; if ( deltax > deltay ) octant_odd( x1, y1, x2, y2, color ); else octant_even( x1, y1, x2, y2, color ); } void draw_segments( int x, int y, int xcent, int ycent, int color ) { int minx = 0, miny = 0, maxx = hres-1, maxy = vres-1; int xlo, xhi, v, h; xlo = xcent-x, xhi = xcent+x; if ( xlo < minx ) xlo = minx; if ( xhi > maxx ) xhi = maxx; if ( ( v = ycent-y ) >= miny ) for (h = xlo; h <= xhi; h++) vram[ v*hres + h ] = color; if ( ( v = ycent+y ) <= maxy ) for (h = xlo; h <= xhi; h++) vram[ v*hres + h ] = color; xlo = xcent-y, xhi = xcent+y; if ( xlo < minx ) xlo = minx; if ( xhi > maxx ) xhi = maxx; if ( ( v = ycent-x ) >= miny ) for (h = xlo; h <= xhi; h++) vram[ v*hres + h ] = color; if ( ( v = ycent+x ) <= maxy ) for (h = xlo; h <= xhi; h++) vram[ v*hres + h ] = color; } void fill_circle( int x, int y, int radius, int color ) { int xcent = x, ycent = y, esum = 3 - 2*radius; y = radius, x = 0; while ( x <= y ) { draw_segments( x, y, xcent, ycent, color ); if ( esum < 0 ) { esum += 4*x + 6; ++x; } else { esum += 4*(x - y) + 10; y -= 1; ++x; } } } void draw_rectangle( int x, int y, int h, int v, int color ) { int minx = x, miny = y, maxx = x+h-1, maxy = y+v-1; 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 ); } int main( int argc, char **argv ) { // map display memory into application's address-space int fd = open( "/dev/vram", O_RDWR ); if ( fd < 0 ) { perror( "/dev/vram" ); exit(1); } int size = lseek( fd, 0, SEEK_END ); int prot = PROT_READ | PROT_WRITE; int flag = MAP_FIXED | MAP_SHARED; if ( mmap( (void*)vram, size, prot, flag, fd, 0 ) == MAP_FAILED ) { perror( "mmap" ); exit(1); } // enter graphics mode init8086(); // setup 8086 environment vm.regs.eax = 0x4F02; // VESA Set Display Mode vm.regs.ebx = vesa_mode; // specify mode id-number int86( 0x10, vm ); // invoke BIOS service // draw screen border int color = 15; draw_rectangle( 0, 0, hres, vres, color ); getchar(); // draw circular disk as background int midx = hres/2, midy = vres/2, radius = vres/4; color = 5; fill_circle( midx, midy, radius, color ); getchar(); // draw the first line-pair (yellow) color = 14; draw_line( 100, 100, hres-100, vres-100, color ); getchar(); draw_line( hres-100, 100, 100, vres-100, color ); getchar(); // draw the second line-pair (cyan) color = 11; draw_line( 300, 100, hres-300, vres-100, color ); getchar(); draw_line( hres-300, 100, 300, vres-100, color ); getchar(); // leave graphics mode vm.regs.eax = 0x0003; // VGA Set Display Mode 3 int86( 0x10, vm ); // invoke BIOS service }