/* 
 *
 *    This application has been modified from its original version,
 *    by Timothy A. Graupmann. For any questions or comments send
 *    email to tgraupmann@yahoo.com.
 *
 *    Example program for the Allegro library, by Shawn Hargreaves.
 *
 *    This program originally demonstrated...
 *
 *    This program demonstrates how to write directly to video memory.
 *    It implements a simple fire effect, first by calling getpixel() and
 *    putpixel(), then by accessing video memory directly a byte at a
 *    time, and finally using block memory copy operations.
 */


#include <stdlib.h>
#include <stdio.h>

#ifdef DJGPP
#include <sys/farptr.h>
#include <sys/segments.h>
#include <sys/movedata.h>
#endif

#include "allegro.h"


/* The fire is formed from several 'hotspots' which are moved randomly
 * across the bottom of the screen.
 */
#define FIRE_HOTSPOTS   75

int hotspot[FIRE_HOTSPOTS]; 
static int thotspot[FIRE_HOTSPOTS];



/* This function updates the bottom line of the screen with a pattern
 * of varying intensities which are then moved upwards and faded out
 * by the code in main().
 */
void draw_bottom_line_of_fire()
{
   int c, c2;
   unsigned char temp[320];

   /* zero the buffer */
   for (c=0; c<SCREEN_W; c++)
      temp[c] = 0;

   for (c=0; c<FIRE_HOTSPOTS; c++) { 
      /* display the hotspots */
      for (c2=hotspot[c]-20; c2<hotspot[c]+20; c2++)
	 if ((c2 >= 0) && (c2 < SCREEN_W))
	    temp[c2] = MIN(temp[c2] + 20-ABS(hotspot[c]-c2), 192);

      /* move the hotspots */
      hotspot[c] += thotspot[c];
      if (hotspot[c] < 0)
	 hotspot[c] += SCREEN_W;
      else
	 if (hotspot[c] >= SCREEN_W)
	    hotspot[c] -= SCREEN_W;
   }

   /* display the buffer */
   for (c=0; c<SCREEN_W; c++)
      putpixel(screen, c, SCREEN_H-1, temp[c]);
}



int main()
{
   for(int index=0; index<FIRE_HOTSPOTS; index++)
      thotspot[index]=rand()%3-1;
   PALLETE pal1;
   int c;
   int x, y;
   unsigned long address;
   unsigned char temp[320];

   allegro_init();
   install_keyboard(); 
   set_gfx_mode(GFX_VGA, 320, 200, 0, 0);

   for (c=0; c<FIRE_HOTSPOTS; c++)
      hotspot[c] = random() % SCREEN_W;

   /* fill our pallete with a gradually altering sequence of colors */
   for (c=0; c<64; c++) {
      pal1[c].r = c;
      pal1[c].g = 0;
      pal1[c].b = 0;
   }
   for (c=64; c<128; c++) {
      pal1[c].r = 63;
      pal1[c].g = c-64;
      pal1[c].b = 0;
   }
   for (c=128; c<192; c++) {
      pal1[c].r = 63;
      pal1[c].g = 63;
      pal1[c].b = c-192;
   }
   for (c=192; c<256; c++) {
      pal1[c].r = 63;
      pal1[c].g = 63;
      pal1[c].b = 63;
   }

   /* it's even faster if we transfer the data in big blocks */
   while (!keypressed()) {
      set_pallete(pal1);
      draw_bottom_line_of_fire();

      for (y=SCREEN_H-2; y>50; y--) {
	 /* get an address for reading line y+1 */
	 address = bmp_read_line(screen, y+1);

	 /* read the line */
	 movedata(screen->seg, address, _my_ds(), (unsigned)temp, SCREEN_W);

	 /* adjust it */
	 for (x=0; x<SCREEN_W; x++)
	    if (temp[x] > 0)
	       temp[x]--;

	 /* get an address for writing line y */
	 address = bmp_write_line(screen, y);

	 /* write the line */
	 movedata(_my_ds(), (unsigned)temp, screen->seg, address, SCREEN_W);
      }

      for (y=0; y<51; y++) {
	 /* get an address for reading line y+1 */
	 address = bmp_read_line(screen, y+1);

	 /* read the line */
	 movedata(screen->seg, address, _my_ds(), (unsigned)temp, SCREEN_W);

	 /* adjust it */
	 for (x=0; x<SCREEN_W; x++)
	    if (temp[x] > 0)
	       temp[x]--;

	 /* get an address for writing line y */
	 address = bmp_write_line(screen, y);

	 /* write the line */
	 movedata(_my_ds(), (unsigned)temp, screen->seg, address, SCREEN_W);
      }

   }

   return 0;
}
