FIREKIT v1.0 by John W. Ractliff 70253.3237@compuserve.com jratclif@inlink.com 32bit DOS4GW application. Will run in Microsoft Windowss 32 bit mode. Source code in ANSI C and Turbo Assembler The enclosed software was written by John W. Ratcliff on May 27, 1996. As of this date I am releasing this software into the public domain. I am releasing this software into the public domain, hopefully, to make a point. I would like to demonstrate how to write source code that is useful to other people. I was looking at some of the various flame algorithms and source code examples and in each case they were such hard coded demos nobody could actually get them integrated into an application. Please take a look at the source code enclosed, including the very simple and easy to understand prototypes in FLAMES.H. The first thing you probably want to do is to just run the program. You must print out a copy of the following keyboard definitions so you will be able to operate the software. ===== KEYBOARD CONTROLS FOR THE FLAME PROGRAM ===== 0-9 = Control the base amount of fuel being fed into the system. + = Increase the value for the flame feeder. - = Decrease the value for the flame feeder. ] = Increase the quantity of fuel in the flame feeder. [ = Decrease the quantity of fuel of the flame feeder. A = Set the flame consumption rate to zero. B = Set the flame consumption rate to 1 C = Set the flame consumption rate to 2 D = Set the flame consumption rate to 3 F = Toggle the filter method from 4x to 8x and back. y = Lowercase y, increase vertical screen size. Y = Uppercase Y, decrease vertical screen size. x = Lowercase x, increase horizontal screen size. X = Uppercase X, decrease horizontal screen size. P = Toggle the background picture mode on and off. ESC = Exit the program. ============ What are these files? ================= D.BAT This is a batch file to invoke the Watcom debugger. FLAME.C The C source to the FIREKIT application. FLAME.EXE The 32 bit DOS4GW FIREKIT application. FLAME.LNK A Microsoft make compatible link file. FLAME.MAK A Microsoft make compatible make file. FLAME.OBJ The Watcom 32 bit object file for FLAME.C FLAME.TXT This documentation file. FLAMES.ASM The assembly language source code for the flame algorithm and support routines. Written in Turbo Assembler IDEAL mode. Will run directly under Microsoft windows 95. FLAMES.H The C language prototype file for FLAMES.ASM FLAMES.OBJ The assembly language object module for FLAMES.ASM IMAGE.PAK A sample image to demonstrate merging the flame routines into an existing application. IMAGE.PAL The palette file that goes with IMAGE.PAK M.BAT A batch file which invokes the Microsoft make utility. ==== What is FIREKIT? =============== FIREKIT is an assembly language routine which generates a series of images which simulates fire. Through the use of a single data structure the application programmer can effect almost every single variable in the flame routine providing a wide array of visual effects. The FIREKIT application program, FLAME.EXE, allows you to manipulate all of these variables in real time with the keyboard. ==== How does it work? =============== The flame algorithm is simply a little image filter. It will average 4 or 8 pixels at a time. The variable "fire8" in the FLAMESPEC structure controls whether to use 4 or 8 pixels in the average. Set it to 1 if you want it to average 8 pixels, or zero if you want it to average 4. Averaging 4 pixels is faster and has a different visual look and feel than 8. When the program takes the average it will also subtract off a value from it, which causes the flame to dissapate. You control the rate of dissapation of the flame by modifying the variable "fheight" in the FLAMESPEC structure. Typically this value is set to 1, so that it takes one less than the average at each frame. You can set it to zero which causes an interesting looking visual effect. When you set this value to 2, or 3, or more, the flames will not be able to get very tall before they fall out to zero. The flame algorithm uses two frame buffers which are flip/flopped each time. At every iteration the output frame is equal to the averaged pixels of the previous frame. These two buffers are denoted in the FLAMESPEC structure as "flame1" and "flame2". To make the flame effect work we have to feed "fire" into the bottom of the buffers. At each iteration randomly modulated values are placed at the bottom of the frame. You control the strength of the fire base by setting the variable "fuelbase" in the FLAMESPEC structure. Values between 0 and about 100 are valid. After the fuelbase has been added the algorithm then processes the fuel feeder. In this case a random number of fuel points are added into the stream. The number of random fuel points is controlled by the "andmask" value in the FLAMESPEC structure. If the and mask is, for example, set to 7, then up to 7 random fuel feeder points are placed into the stream. Without these random fuel feeder points the flames would be very boring and static. The strength of these fuel feeder point is controlled by the value "fuel" in the data structure. That's all there is to it. At each iteration the next frame is equal to an average of pixels from the previous frame, less the fuel depletion rate. Then fuel is added at the base of the image and random fuel feeder points are thrown into the mix. ==== How to use the FLAMESPEC data structure. ============== The flame algorith is controlled by a single data structure called FLAMESPEC. With this data structure there is nothing keeping you from creating many different active flame buffers going all at the same time. You could allocate buffers for 5 or 6 different sized flames with different control variables and just keep calling the same routines. Here's how the FLAMESPEC data structure is defined. typedef struct { long width; // width of flame buffer. long height; // height of flame buffer. long fsize; // number of bytes total in flame buffer (width*height) long andmask; // andmask indicates how much extra fuel to throw in. char *flame1; // frame 1 of flame buffer. char *flame2; // frame 2 of flame buffer. long *jitter; // 512 dword jitter table, used to throw random fuel in. long seed; // current random number seed. long fheight; // controls rate of flame consumption, from 0 to about 4 long fuel; // the controls the strength of the fuel feeder. long fuelbase; // this is the base fuel strength. long fire8; // true if doing 8 pixel average for flames. long ScreenX; // destination Screen X for flamecopy. long ScreenY; // destination Screen Y for flamecopy char ctrans[256]; //the color palette translation table if used. } FLAMESPEC; In the main application program FLAME.C contains a routine which will allocate and initialize a FLAMESPEC data structure. The routines provided to setup and manage FLAMESPEC data structures are written in C, and are as follows: // This routine will initialize a framspec structure of the width and // height specified. It will allocate the memory for the frame buffers // and the jitter table (precomputed randomized offset values for the // fuel dump stage). If this routine returns a zero then it was unable // to allocate enough memory for the buffers. If it returns one then // the flamespec buffer is ready to go. int CreateFlame(FLAMESPEC *f,long wid,long hit); // This routine frees up the memory allocated by a CreateFlame call. void DestroyFlame(FLAMESPEC *f); // This is a routine which loads a background image and color palette // which is used to demonstrate merging the flame output into an existing // application. char * LoadPicture(char *fname,char *imagepal); // This routine will build a color translate table which translates colors // from the flame palette into the application's own color palette. The // translation table is "ctrans" inside the FLAMESPEC structure. void FlameColorMatch(FLAMESPEC *f,unsigned char *imagepal,unsigned char *fpal); ===== What do the assembly language routines do? ================== // These are DOS only functions! They handle support for going directly // to the Mode 13 320x200 VGA screen. Under Windows you should use directdraw // WinG or something else to update your blits. void cdecl FlameStart(void); // turn 320x200 graphics mode on and set palette (DOS only) // For the moment this routine is set to NOT copy the *LAST 3 SCANLINES* of // the flame buffer. That's because the last 3 scanlines contain the fuel // feeder area, which can often just look like random noise until it filters // up into the flame region. void cdecl FlameCopy(FLAMESPEC *f); // copy the flame to the Mode13 VGA screen. void cdecl FlameStop(void); // turn 320x200 graphics mode off (DOS only) void cdecl FlameZeroScreen(void); //erase screen. void cdecl FlameImage(char *image); // copy vga screen image. void cdecl FlameDAC(char *pal); // set vga color palette. void cdecl FlamePal(char *fpal); // set flame palette, and retrieve settings. // This routine has self-modified code in it! Under Windows this will // cause a protection fault unless you change the read/write access to // this section of memory! There is no way *not* to use self-modified // code for this routine if the program is to support variable width // flame buffers, which it does. void cdecl FlameFrame(FLAMESPEC *f); // Copies the flame from FLAMESPEC into the destination "image", but // translates the flame colors into the application color palette and // handles a translucency for flames that are near zero. void cdecl FlameCopyTranslate(FLAMESPEC *f,char *image); // Returns which entry in the 8 bit RGB color palette "pal" is closest // to the 8 bit red/green/blue value passed. long cdecl FlameClosestColor(char *pal,long red,long green,long blue);