/*
 *    SPEED - by Shawn Hargreaves, 1999
 *
 *    Main program body, setup code, action pump, etc.
 */

#include <allegro.h>

#include "speed.h"



/* are we cheating? */
int cheat = FALSE; 



/* how many points did we get? */
int score; 



/* timer for controlling game speed */
static volatile int counter;

static void inc_counter()
{
   counter++;
}

END_OF_STATIC_FUNCTION(inc_counter);



/* the main game function */
static int play_game()
{ 
   BITMAP *bmp = create_bitmap(SCREEN_W, SCREEN_H);

   int gameover = 0;
   int cyclenum = 0;

   /* init */
   score = 0;

   init_view();
   init_player();
   init_badguys();
   init_bullets();
   init_explode();
   init_message();

   LOCK_VARIABLE(counter);
   LOCK_FUNCTION(inc_counter);

   counter = 0;

   #define TIMER_SPEED  BPS_TO_TIMER(30*(cyclenum+2))

   install_int_ex(inc_counter, TIMER_SPEED);

   while (!gameover) {

      /* move everyone */
      while (counter > 0) {
	 update_view();
	 update_bullets();
	 update_explode();
	 update_message();

	 if (update_badguys()) {
	    if (advance_view()) {
	       cyclenum++;
	       install_int_ex(inc_counter, TIMER_SPEED);
	    }

	    advance_player();
	 }

	 gameover = update_player();

	 counter--;
      }

      /* draw everyone */
      draw_view(bmp);
   }

   /* cleanup */
   shutdown_view();
   shutdown_player();
   shutdown_badguys();
   shutdown_bullets();
   shutdown_explode();
   shutdown_message();

   destroy_bitmap(bmp);

   return (gameover > 0);
}



/* for generating the 8 bit additive color lookup table */
static void add_blender8(PALETTE pal, int x, int y, RGB *rgb)
{
   int r, g, b;

   r = (int)pal[x].r + (int)pal[y].r;
   g = (int)pal[x].g + (int)pal[y].g;
   b = (int)pal[x].b + (int)pal[y].b;

   rgb->r = MIN(r, 63);
   rgb->g = MIN(g, 63);
   rgb->b = MIN(b, 63);
}



/* 15 bit additive color blender */
static unsigned long add_blender15(unsigned long x, unsigned long y, unsigned long n)
{
   int r = getr15(x) + getr15(y);
   int g = getg15(x) + getg15(y);
   int b = getb15(x) + getb15(y);

   r = MIN(r, 255);
   g = MIN(g, 255);
   b = MIN(b, 255);

   return makecol15(r, g, b);
}



/* 16 bit additive color blender */
static unsigned long add_blender16(unsigned long x, unsigned long y, unsigned long n)
{
   int r = getr16(x) + getr16(y);
   int g = getg16(x) + getg16(y);
   int b = getb16(x) + getb16(y);

   r = MIN(r, 255);
   g = MIN(g, 255);
   b = MIN(b, 255);

   return makecol16(r, g, b);
}



/* 24 bit additive color blender */
static unsigned long add_blender24(unsigned long x, unsigned long y, unsigned long n)
{
   int r = getr24(x) + getr24(y);
   int g = getg24(x) + getg24(y);
   int b = getb24(x) + getb24(y);

   r = MIN(r, 255);
   g = MIN(g, 255);
   b = MIN(b, 255);

   return makecol24(r, g, b);
}



/* display a commandline usage message */
static void usage()
{
   allegro_message(
      "\n"
      "SPEED - by Shawn Hargreaves, 1999\n"
      "\n"
      "Usage: speed w h bpp [options]\n"
      "\n"
      "The w and h values set your desired screen resolution\n"
      "(available modes will depend on your hardware)\n"
      "\n"
      "The bpp value sets the color depth: 8, 15, 16, 24, or 32\n"
      "It runs _much_ faster in 8 bit mode\n"
      "\n"
      "Available options:\n"
      "\n"
      "\t-cheat makes you invulnerable\n"
      "\t-www invokes the built-in web browser\n"
      "\n"
      "Example usage:\n"
      "\n"
      "\tspeed 640 480 8\n"
   );
}



/* the main program body */
int main(int argc, char *argv[])
{
   int w=0, h=0, bpp=0;
   int www = FALSE;
   PALETTE pal;
   int i, n;

   allegro_init();

   /* parse the commandline */
   for (i=1; i<argc; i++) {
      if (stricmp(argv[i], "-cheat") == 0) {
	 cheat = TRUE;
      }
      else if (stricmp(argv[i], "-www") == 0) {
	 www = TRUE;
      }
      else {
	 n = atoi(argv[i]);

	 if (!n) {
	    usage();
	    return 1;
	 }

	 if (!w) {
	    w = n;
	 }
	 else if (!h) {
	    h = n;
	 }
	 else if (!bpp) {
	    bpp = n;
	 }
	 else {
	    usage();
	    return 1;
	 }
      }
   }

   /* it's a real shame that I had to take this out! */
   if (www) {
      allegro_message(
	 "\n"
	 "Unfortunately the built-in web browser feature had to be removed.\n"
	 "\n"
	 "I did get it more or less working as of Saturday evening (forms and\n"
	 "Java were unsupported, but tables and images were mostly rendering ok),\n"
	 "but the US Department of Justice felt that this was an unacceptable\n"
	 "monopolistic attempt to tie in web browsing functionality to an\n"
	 "unrelated product, so they threatened me with being sniped at from\n"
	 "the top of tall buildings by guys with high powered rifles unless I\n"
	 "agreed to disable this code.\n"
	 "\n"
	 "We apologise for any inconvenience that this may cause you.\n"
      );

      return 1;
   }

   if ((!w) || (!h) || (!bpp)) {
      usage();
      return 1;
   }

   /* set the screen mode */
   set_color_depth(bpp);

   if (set_gfx_mode(GFX_AUTODETECT, w, h, 0, 0) != 0) {
      allegro_message("Error setting %dx%d %d bpp display mode:\n%s\n",
		      w, h, bpp, allegro_error);
      return 1;
   }

   /* set up everything else */
   install_timer();
   install_keyboard();
   install_joystick(JOY_TYPE_AUTODETECT);

   /* additive color is cool */
   if (bpp == 8) {
      generate_332_palette(pal);

      pal[0].r = 0;
      pal[0].g = 0;
      pal[0].b = 0;

      set_palette(pal);

      rgb_map = malloc(sizeof(RGB_MAP));
      create_rgb_table(rgb_map, pal, NULL);

      color_map = malloc(sizeof(COLOR_MAP));
      create_color_table(color_map, pal, add_blender8, NULL);
   }
   else {
      set_blender_mode(add_blender15, add_blender16, add_blender24, 0, 0, 0, 0);
   }

   text_mode(-1);

   /* the main program body */
   while (title_screen()) {
      if (play_game())
	 show_results();
   }

   /* time to go away now */
   goodbye();

   if (rgb_map) {
      free(rgb_map);
      rgb_map = NULL;
   }

   if (color_map) {
      free(color_map);
      color_map = NULL;
   }

   return 0;
}

END_OF_MAIN();
