#include <stdio.h>
#include <stdlib.h>

#include "allegro.h"

PALLETE my_pallete;
BITMAP *scr_buffer;

#define RGB(r,g,b) ((((b)>>1)<<10)+(((g)>>1)<<5)+((r)>>1))

// switches
int swSurpressScan;
int swBinaryMode;
int sw2by2;
int sw7colour;
int swPalette;

void DisplayHelp(char * Error)
{
   printf("PCX2GBA v1.0 by Ivan Mackintosh 10 Apr 2001\n\n");

   if (Error != NULL)
   {
      printf("*** Error: %s\n\n", Error);
   }
   printf("Usage: pcx2gba <infile.pcx> <outputfile> [switches]\n\n");
   printf("The input file should be a 256 colour Version 5 PCX file\n");
   printf("Switches:\n");
   printf("-2\tOptimise output for 2x2 tiles\n");
}



void GrabChar(char * Buffer, int offsetx, int offsety)
{
   int x, y, count;

   count = 0;

   for (y = 0; y < 8; y ++)
   {
      for (x = 0; x < 8; x ++)
      {
         Buffer[count] = getpixel(scr_buffer, offsetx + x, offsety + y);
         count++;
      }
   }
}


int ConvertPalette(int PalNum)
{
   return RGB(my_pallete[PalNum].r, my_pallete[PalNum].g, my_pallete[PalNum].b);
}



int main(int argc, char* argv[])
{
   int x2, y2, x, y, ox, oy, NumChars, chars, i;
   int Multiples;
   long GBATSCount, count;
   unsigned char * GBATileSet = NULL;
   FILE * fout = NULL;

   sw2by2 = 0;

   if (argc < 3)
   {
      DisplayHelp(NULL);
      return -1;
   }

   // read switches
   for (i = 3; i < argc; i ++)
   {
      if (argv[i][0] != '-')
      {
         DisplayHelp("Invalid Switch");
         return -1;
      }

      switch(argv[i][1])
      {
      case '2':
         sw2by2 = 1;
         break;

      default:
         DisplayHelp("Invalid Switch");
         return -1;
      }
   }

   allegro_init();              /* Initialise all Allegro stuff       */

   scr_buffer = load_pcx (argv[1],my_pallete);
   if (scr_buffer == NULL)
   {
      printf("Error: %s: file not found\n", argv[1]);
      allegro_exit();
      return -1;
   }

   // ensure that the image is divisible by 8
   Multiples=sw2by2?16:8;
   if (scr_buffer->w % Multiples != 0)
   {
      printf("Error: %s: width (%d) is not a multiple of %d pixels\n",
             argv[1], scr_buffer->w, Multiples);
      destroy_bitmap(scr_buffer);
      allegro_exit();
      return -1;
   }

   if (scr_buffer->h % Multiples != 0)
   {
      printf("Error: %s: height (%d) is not a multiple of %d pixels\n",
             argv[1], scr_buffer->h, Multiples);
      destroy_bitmap(scr_buffer);
      allegro_exit();
      return -1;
   }

   NumChars = (scr_buffer->w/8)*(scr_buffer->h/8);
   GBATileSet = malloc(NumChars * 64);

   GBATSCount = 0;

   if (!sw2by2)
   {
      for (oy = 0; oy < scr_buffer->h; oy+=8)
      {
         for (ox = 0; ox < scr_buffer->w; ox+=8)
         {
            GrabChar(&GBATileSet[GBATSCount], ox, oy);

            GBATSCount+=64; // size of a char
         }
      }
   }
   else
   {
      // optimise for 2by2 chars
      for (oy = 0; oy < scr_buffer->h; oy+=16)
      {
         for (ox = 0; ox < scr_buffer->w; ox+=16)
         {
            for (y2 = 0; y2 < 2; y2++)
            {
               for (x2 = 0; x2 < 2; x2++)
               {
                  GrabChar(&GBATileSet[GBATSCount], x2*8+ox, y2*8+oy);

                  GBATSCount+=64; // size of a char
               }
            }
         }
      }
   }

   fout = fopen(argv[2], "w");
   if (fout == NULL)
   {
      printf("Error: %s: Can't open output file", argv[2]);
      free(GBATileSet);
      destroy_bitmap(scr_buffer);
      allegro_exit();
      return 1;
   }

   count = 0;
   fprintf(fout, "/* GBA Tile data and Palette information optimised for Mode 0,\n"
                 " * 1x256 colour palette mode.\n"
                 " * Output from PCX2GBA\n"
                 " */\n\n");
   
   fprintf(fout, "const u8 TileData[] = {\n");

   // output an empty char
   fprintf(fout, "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n");
   fprintf(fout, "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n");
   fprintf(fout, "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n");
   fprintf(fout, "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n");
   
   for (chars = 0; chars < NumChars; chars++)
   {
      for (y = 0; y < 4; y ++)
      {
         fprintf(fout, "\t");
         for (x = 0; x < 16; x ++)
         {
            unsigned int value;

            value = GBATileSet[count];
            count ++;
            if (chars == NumChars - 1 && y == 3 && x == 15)
               fprintf(fout, "%d", value);
            else
               fprintf(fout, "%d,", value);
         }
         fprintf(fout, "\n");
      }
   }
   fprintf(fout, "};\n\n");

   fprintf(fout, "#define NUM_TILES (%d)\n\n", NumChars + 1);
   
   fprintf(fout, "const u16 TilePalette[] = {\n");
   for (x = 0; x < 16; x ++)
   {
      fprintf(fout, "\t");
      for (y = 0; y < 16; y ++)
      {
         unsigned int value;
         value = ConvertPalette((x*16)+y);
         if ((x * 16) + y < 255)
            fprintf(fout, "%d,", value);
         else
            fprintf(fout, "%d", value);
      }
      fprintf(fout, "\n");
   }
   fprintf(fout, "};\n");

   fclose(fout);

   free(GBATileSet);

   /* Destroys bitmap buffer */
   destroy_bitmap(scr_buffer);
   /* Shuts down Allegro     */
   allegro_exit();
   /* Exit program           */
   return 0;
}
