//------------------------------------------------------------------- // vgadraw.cpp // // This program draws an animation to SiS video display memory. // Assumes the 'sischip.c' and 'mysis.c' modules are installed. // // programmer: Kai Long // written on: 10 MAY 2003 //------------------------------------------------------------------- #include // for printf(), perror() #include // for open() #include // for exit() #include // for read(), write(), close() #include // for mmap(), munmap() #include // for memset() #define VRES 1024 #define HRES 1280 #define PEL_SIZE 4 #define N_PELS (HRES*VRES) #define FB_BYTES (N_PELS*PEL_SIZE) #define sisname "/proc/sischip" #define vramname "/dev/vram" int delay = 400000; void clear_screen(long* start) { memset( start, 0, FB_BYTES); } void draw_border( long *vram, int indent, long color ) { int r = indent; int k = indent; do { vram[ r*HRES + k ] = color; k += 1; } while( k < HRES-1-indent ); do { vram[ r*HRES + k ] = color; r += 1; } while( r < VRES-1-indent ); do { vram[ r*HRES + k ] = color; k -= 1; } while( k > indent ); do { vram[ r*HRES + k ] = color; r -= 1; } while( r > indent ); } long* backup_screen(long* start) { long* back_buf = (long*)malloc(FB_BYTES); memcpy(back_buf, start, FB_BYTES); return back_buf; } void restore_screen(long* vram_start, long* back_buf) { memcpy(vram_start, back_buf, FB_BYTES); free(back_buf); } int main( int argc, char **argv ) { // open /proc/sischip for reading and writing start_address_offset int sis = open( sisname, O_RDWR ); if ( sis < 0 ) { perror( sisname ); exit(1); } // get the current offset for display frame buffer unsigned long start_address_offset; int nbytes = read( sis, &start_address_offset, 4 ); // open /dev/vram to map it later int fd = open( vramname, O_RDWR ); if ( fd < 0 ) { perror( vramname ); exit(1); } // get the vram size int filesize = lseek( fd, 0, SEEK_END ); // map /dev/vram for direct drawing int prot = PROT_READ | PROT_WRITE; int flags = MAP_SHARED; int offset = 0; long *vram = (long*)mmap( 0, filesize, prot, flags, fd, offset ); if ( vram < 0 ) { perror( "mmap" ); exit(1); } // backup the original screen--> not necessary // long* orig_screen = backup_screen(vram); // put our own drawing buffer 2 screen after the current one offset = HRES*VRES*PEL_SIZE*2; //<---- this matters start_address_offset += offset; // make sure it's not exceeding the real vram size start_address_offset %= filesize; // clear our own screen long* my_vram = vram + start_address_offset; clear_screen(my_vram); // set start address of frame buffer to our own position write( sis, &start_address_offset, 4 ); // to draw the animation for (int i = 0; i < VRES/2; i++) { draw_border( my_vram, i, (i*10)<<8 ); for (int j = 0; j < delay; j++); } getchar(); // <--- added by Allan Cruse on 5/10/2003 // restore the original screen--> not necessary // restore_screen(vram, orig_screen); // set start address offset back to original one start_address_offset -= offset; write( sis, &start_address_offset, 4 ); // wrap up the mapped video frame buffer and file descriptor munmap( vram, filesize ); close(fd); close(sis); }