//------------------------------------------------------------------------- //fi_fire.c - fire tutorial source //By Calvrak of Fusion Industries //alexz@fusionindustries.com - http://www.fusionindustries.com //You are free to modify this code and experiment with it. // //I'd be interested in any feedback or if this tutorial was of any // use to you. // //-Calvrak //June 7, 1998 // //This code was written and compiled under Microsoft Visual C v1.0 //It was tested under Borland C v3.0 and will compile under it if all the // _outp and _inp functions are changed to outp and inp. // //June 11, 1999 //*Code cleaned up. It's better, but not as good as I'd like. // //------------------------------------------------------------------------- #include #include #include #include #include // P R O T O T Y P E S ------------------------------------------------------ void fire(void); void Setpal(int col,unsigned char r,unsigned char g,unsigned char b); void Create_Fire_Pal(void); void Wait_For_Retrace(void); // G L O B A L S ------------------------------------------------------------ unsigned char far *video_buffer = (char far *)0xA0000000L; unsigned char far *double_buffer = NULL; //--------------------------------------------------------------------------- void main() { printf("Fire by Calvrak of Fusion Industries\n"); printf("http://fusion.techcore.com\n"); printf("\n\nPress any key to start the inferno!\n"); getch(); double_buffer = (unsigned char far *)_fmalloc(32000); //set video mode to VGA 320x200x256 _asm { mov ax, 13h int 10h } fire(); _ffree(double_buffer); //set video mode back to text mode _asm { mov ax, 03h int 10h } } //--------------------------------------------------------------------------- void fire(void) { int x,y; //screen coords int avg; //average color int offset; //so we don't have to keep calc'ing 320*y+x all the time unsigned char color; //fire color //clear the double buffer _fmemset((unsigned char far *)double_buffer,0,64000); Create_Fire_Pal(); while(!kbhit()) { ////////////// S E E D //////////////////////// for(x=0; x<320; x++) { // bottom row(320*199+x) is white double_buffer[63680+x] = 255; } for(y=197; y<200; y++) { for(x=0; x<320; x+=8) { color = (char)rand()%256; // get a random color offset = (y<<6) + (y<<8) + x; // calculate the offset if(color>128) color = 255; // all or nothing; if(color<127) color = 0; // white or black // this just makes fatter fire -- horizontal 8-pixel // wide seed colors. Try changing this to just 4-pixel // wide seeds and see what happens. double_buffer[offset ] = color; double_buffer[offset+1] = color; double_buffer[offset+2] = color; double_buffer[offset+3] = color; double_buffer[offset+4] = color; double_buffer[offset+5] = color; double_buffer[offset+6] = color; double_buffer[offset+7] = color; } } ////////// E N D S E E D ///////////////////// //////////////////// B L U R /////////////////////////// for(y=199; y>0; y--) { avg = 0; offset = (y<<6) + (y<<8); // 320 * y -- (calculate the next row) for(x=0; x<319; x++) { offset += 1; // equivalent to 320 * y + x + 1 avg = double_buffer[offset-320];//1 [x-320] (1) avg += double_buffer[offset-1]; //2 [x-1][x][x+1] (2,3,4) avg += double_buffer[offset]; //3 avg += double_buffer[offset+1]; //4 avg = avg>>2; if(avg>1) avg -= 1; // make it fade faster // this also allows pixels with the // value of 1 to go to zero and // "extinguish". Try removing this line // to see what happens. // move "blurred" pixel up by one line double_buffer[offset - 320] = avg; } } ///////////////////////END BLUR///////////////////// Wait_For_Retrace(); // Don't want flicker ;) // copy everything except the seed rows to the video buffer (screen) _fmemcpy((char far *)video_buffer, (char far *)double_buffer, 62720); // 62720 == 64000-4*320 for the seed rows } } //--------------------------------------------------------------------------- void Setpal(int col,unsigned char r,unsigned char g,unsigned char b) { _outp(0x03C8,col);// 0x03C8 is write permission, col is the color number _outp(0x03C9,r); _outp(0x03C9,g); _outp(0x03C9,b); } //--------------------------------------------------------------------------- void Create_Fire_Pal() { unsigned char i = 0; for (i=0; i<64; i++) { Setpal( i, i, 0, 0); // black to max red Setpal( i+64, 63, i, 0); // max red to max yellow Setpal(i+128, 63, 63, 0); // max yellow Setpal(i+192, 63, 63-i, 0); // max yellow to red; we just do the } // opposite of the color eqn above } //--------------------------------------------------------------------------- void Wait_For_Retrace(void) { while(_inp(0x3DA) & 0x08); // do nothing, retracing while(!(_inp(0x3DA) & 0x08));// wait for start of retrace }