//---------------------------------------------------------------------------
// Fonts functions
//---------------------------------------------------------------------------

#include <sys\types.h>
#include <libetc.h>
#include <libgte.h>
#include <libgpu.h>
#include <rand.h>
#include <libcd.h>
#include <memory.h>
#include "..\include\compile.h"
#include "..\include\db.h"
#include "..\include\alocvram.h"
#include "..\include\readfile.h"

#ifndef __point
   #define __point
   typedef struct
   {
      int x;
      int y;
   } point;
#endif

#include "..\include\fonts.h"

int           FNTxstart, FNTystart;
int           FNTalign = 0;
DoubleBuffer  *FNTdbu;
int           FNTtextclr = 0;
int           FNTvrammemhandle = -1;
int           FNTTPX, FNTTPY;
int           FNTClutY[3] = {-1,-1,-1};

//-------------------------------------
// Loads a font and initalize it
//-------------------------------------
int SetFont (int FontNbr, u_long memptr)
{
   int i;
   TIM_IMAGE timimg;
   char *FileNames [4] = {"\\SPRITES\\LE1FONT1.TIM",
                          "\\SPRITES\\LE1FONT2.TIM",
                          "\\SPRITES\\LE2FONT1.TIM",
                          "\\SPRITES\\LE2FONT2.TIM"};

   //----------------------------------
   if (FNTvrammemhandle != -1)          // If there was vram & clut allocated
   {                                    //  previously, free it first
      FreeVram (FNTvrammemhandle);      //
      FNTvrammemhandle = -1;            //
   }                                    //
   if (FNTClutY[0] != -1)               //
   {                                    //
      FreeClut (FNTClutY[0]);           //
      FNTClutY[0] = -1;                 //
   }                                    //
   if (FNTClutY[1] != -1)               //
   {                                    //
      FreeClut (FNTClutY[1]);           //
      FNTClutY[1] = -1;                 //
   }                                    //
   if (FNTClutY[2] != -1)               //
   {                                    //
      FreeClut (FNTClutY[2]);           //
      FNTClutY[2] = -1;                 //
   }                                    //

   //--- Reads the second palette -----
   if (ReadFont (FileNames[FontNbr + 1], memptr) == 0)
   {
      while (1)
      {
         return (-1);
         FntPrint ("Unable to load font.\n");
         FntFlush (-1);
      }
   }

   if (OpenTIM ((u_long *)memptr))
      while (1)
      {
         return (-1);
         FntPrint ("Unable to load font.\n");
         FntFlush (-1);
      }

   if (!ReadTIM (&timimg))
      while (1)
      {
         return (-1);
         FntPrint ("Unable to load font.\n");
         FntFlush (-1);
      }

   if ((FNTClutY[1] = AllocClut ()) == -1)
      return (-1);

   RECT shit = {0,FNTClutY[1] + 480, 256,1};

   u_short *martini = (u_short *)timimg.caddr;
   for (i = 0; i < 256; i++)            // The clut can be translucent
   {
      if (martini[i] & ~32768)
         martini[i] |= 32768;
   }

   if (timimg.crect)
      LoadImage (&shit, timimg.caddr);
   DrawSync (0);

   //---- Reads the font & palette ----
   if (ReadFont (FileNames[FontNbr], memptr) == 0)
   {
      while (1)
      {
         return (-1);
         FntPrint ("Unable to load font.\n");
         FntFlush (-1);
      }
   }

   if (OpenTIM ((u_long *)memptr))
      while (1)
      {
         return (-1);
         FntPrint ("Unable to load font.\n");
         FntFlush (-1);
      }

   if (!ReadTIM (&timimg))
      while (1)
      {
         return (-1);
         FntPrint ("Unable to load font.\n");
         FntFlush (-1);
      }

   point po = FixAllocVram (timimg.prect->x, timimg.prect->y,
                              timimg.prect->w, timimg.prect->h,
                              &FNTvrammemhandle);
   FNTTPX = timimg.prect->x;
   FNTTPY = timimg.prect->y;

   if ((FNTClutY[0] = AllocClut ()) == -1)
      return (-1);

   RECT shit2 = {0,FNTClutY[0] + 480, 256,1};

   martini = (u_short *)timimg.caddr;

   for (i = 0; i < 256; i++)            // The clut can be translucent
   {
      if (martini[i] & ~32768)
         martini[i] |= 32768;
   }

   if (timimg.crect)
      LoadImage (&shit2, timimg.caddr);

   if (timimg.prect)
      LoadImage (timimg.prect, timimg.paddr);

   //----- Read the score sprites -----
   if (ReadFont ("\\SPRITES\\SCORESPR.TIM", memptr) == 0)
   {
      while (1)
      {
         return (-1);
         FntPrint ("Unable to load font.\n");
         FntFlush (-1);
      }
   }

   if (OpenTIM ((u_long *)memptr))
      while (1)
      {
         return (-1);
         FntPrint ("Unable to load font.\n");
         FntFlush (-1);
      }

   if (!ReadTIM (&timimg))
      while (1)
      {
         return (-1);
         FntPrint ("Unable to load font.\n");
         FntFlush (-1);
      }

   if ((FNTClutY[2] = AllocClut ()) == -1)
      return (-1);

   RECT shit3 = {0,FNTClutY[2] + 480, 256,1};
   LoadImage (&shit3, timimg.caddr);

   RECT shit4 = {FNTTPX + (54 / 2),FNTTPY + 184,
                 timimg.prect->w,timimg.prect->h};
   if (timimg.prect)
      LoadImage (&shit4, timimg.paddr);

   return (0);
}

//-------------------------------------
// Reads a file
//-------------------------------------
int ReadFont (char filename[], u_long memptr)
{
   int filelength;
   char *memloc;

   if (OpenFile (filename) == -1)
      return (0);

   if ((filelength = FileSize ()) == 0)
   {
      CloseFile ();
      return (0);
   }

   if (ReadFile ((char *)memptr, filelength) != filelength)
   {
      CloseFile ();
      return (0);
   }

   if (CloseFile () == -1)
      return (0);

   return ((int)filelength);
}

//-------------------------------------
// Returns the length of a string, in
// pixel.
//-------------------------------------
// Note: Will treat '\n' as string end
//-------------------------------------
int StringLength (char string[])
{
   int length = 0;
   int i, j;
   char Font_W = 8;
   char Font_H = 16;

   j = 0;
   while ((string[j] != 0) && (string[j] != 10))
   {
      i = string[j];

      if ((i >= 33) && (i < 128))
      {
         length += 1 + Font_W;
      }
      else if (i == 32)
         length += 9;

      j++;
   }

   return (length);
}

//-------------------------------------
// Set the font to be semi-transpa-
// rent (1) or  not (0).
//-------------------------------------
void SetFontTransparency (int trans)
{

}

//-------------------------------------
// Align text on left
//-------------------------------------
void FontLeftOn (int coorx, int coory)
{
   FNTxstart = coorx;
   FNTystart = coory;
   FNTalign = 0;
}

//-------------------------------------
// Align text on left
//-------------------------------------
void FontLeftOn (point p)
{
   FNTxstart = p.x;
   FNTystart = p.y;
   FNTalign = 0;
}

//-------------------------------------
// Align text on right
//-------------------------------------
void FontRightOn (int coorx, int coory)
{
   FNTxstart = coorx;
   FNTystart = coory;
   FNTalign = 1;
}

//-------------------------------------
// Align text on right
//-------------------------------------
void FontRightOn (point p)
{
   FNTxstart = p.x;
   FNTystart = p.y;
   FNTalign = 1;
}

//-------------------------------------
// Center text
//-------------------------------------
void FontCenterOn (int coorx, int coory)
{
   FNTxstart = coorx;
   FNTystart = coory;
   FNTalign = 2;
}

//-------------------------------------
// Center text
//-------------------------------------
void FontCenterOn (point p)
{
   FNTxstart = p.x;
   FNTystart = p.y;
   FNTalign = 2;
}

//-------------------------------------
// Write text vertically
//-------------------------------------
void FontVerticalOn (int coorx, int coory)
{
   FNTxstart = coorx;
   FNTystart = coory;
   FNTalign = 3;
}

//-------------------------------------
// Write text vertically
//-------------------------------------
void FontVerticalOn (point p)
{
   FNTxstart = p.x;
   FNTystart = p.y;
   FNTalign = 3;
}

//-------------------------------------
// Set the default double buffer class
// to use
//-------------------------------------
void SetFontDB (DoubleBuffer *db)
{
   FNTdbu = db;
}

//-------------------------------------
// Write a string in the buffer
//-------------------------------------
void Print (char string[])
{
   int i, j;
   int x, y;
   SPRT *polygon;
   DR_MODE *drmode;
   char Font_W = 8;
   char Font_H = 16;
   char Font_U[] = {0,72,0,0,0,0,48,104,80,88,0,0,40,112,32,96,0,8,16,24,32,
                    40,48,56,64,72,56,0,0,0,0,64,0,80,88,96,104,112,120,128,
                    136,144,152,160,168,176,184,192,200,208,216,224,232,240,
                    248,0,8,16,24,0,96,0,0,0,0,80,88,96,104,112,120,128,136,
                    144,152,160,168,176,184,192,200,208,216,224,232,240,248,
                    0,8,16,24,0,0,0};
   char Font_V[] = {0,16,0,0,0,0,16,16,16,16,0,0,16,16,16,16,0,0,0,0,0,0,0,0,
                    0,0,16,0,0,0,0,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
                    0,0,0,16,16,16,16,0,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
                    0,0,0,0,0,0,0,0,16,16,16,16,0,0,0};

   y = FNTystart;

   if (FNTalign != 3)              // Non-vertical shit
   {
      j = 0;
      while (string[j] != 0)
      {
         if (FNTalign == 0)                           // Left-aligned
            x = FNTxstart;
         else if (FNTalign == 1)                      // Right-aligned
            x = FNTxstart - StringLength (&string[j]);
         else if (FNTalign == 2)                      // Centered
            x = FNTxstart - (StringLength (&string[j]) >> 1);
         
         while ((string[j] != 0) && (string[j] != '\n'))
         {
            i = string[j];

            if ((i >= 33) && (i < 128))
            {
               i -= 32;
               polygon = FNTdbu->Get_Spr ();
               SetSprt (polygon);
               setXY0 (polygon, x, y);
               polygon->w = Font_W;
               polygon->h = Font_H;
               polygon->clut = GetClut (0,FNTClutY[FNTtextclr & 1] + 480);
               setUV0 (polygon, Font_U[i], Font_V[i]);
               if (FNTtextclr & 2)
                  SetSemiTrans (polygon, 1);
               else
                  SetSemiTrans (polygon, 0);
               FNTdbu->Add_Spr (polygon, 16);

               x += 1 + Font_W;
            }
            else if (i == 32)
               x += 9;
            else if (i == '\n')
            {
               y += 16;
               x = FNTxstart;
            }

            j++;
         }

         drmode = FNTdbu->Get_DrMode ();
         RECT tww = {FNTTPX,FNTTPY, 256,256};
         SetDrawMode (drmode, 0, 0, GetTPage (1, 0, FNTTPX,FNTTPY), &tww);
         FNTdbu->Add_DrMode (drmode, 16);

         if (string[j] == '\n')
            j++;
         y += 16;
      }

      FNTystart = y;
   }
   else
   {
      j = 0;

      while (string[j] != 0)
      {
         y = FNTystart;

         while ((string[j] != 0) && (string[j] != '\n'))
         {
            i = string[j];
           
            if ((i >= 33) && (i < 128))
            {
               i -= 32;
               x = FNTxstart - (Font_W >> 1);

               polygon = FNTdbu->Get_Spr ();
               SetSprt (polygon);
               setXY0 (polygon, x, y);
               polygon->w = Font_W;
               polygon->h = Font_H;
               polygon->clut = GetClut (0,FNTClutY[FNTtextclr & 1] + 480);
               setUV0 (polygon, Font_U[i], Font_V[i]);
               if (FNTtextclr & 2)
                  SetSemiTrans (polygon, 1);
               else
                  SetSemiTrans (polygon, 0);
               FNTdbu->Add_Spr (polygon, 16);

               y += 1 + Font_H;
            }
            else if (i == 32)
               y += 13;
            else if (i == '\n')
            {
               y = FNTystart;
               FNTxstart += 12;
            }

            j++;
         }

         drmode = FNTdbu->Get_DrMode ();
         RECT tww = {FNTTPX,FNTTPY, 256,256};
         SetDrawMode (drmode, 0, 0, GetTPage (1, 0, FNTTPX,FNTTPY), &tww);
         FNTdbu->Add_DrMode (drmode, 16);

         if (string[j] == '\n')
            j++;
         x += 12;
         FNTxstart = x;
      }

      FNTxstart = x;
   }
}

//-------------------------------------
// Set the text's color
//-------------------------------------
// Color = 0: fade blue
//         1: fade yellow
//         2: translucent fade blue
//         3: translucent fade yellow
//-------------------------------------
void SetFontColor (int color)
{
   FNTtextclr = color;
}

//-------------------------------------
// Return the # of both cluts
//-------------------------------------
void GetFontClutNumber (int *clut1, int *clut2, int *clut3)
{
   *clut1 = FNTClutY[0];
   *clut2 = FNTClutY[1];
   *clut3 = FNTClutY[2];
}

//-------------------------------------
// Return the coordinate in VRAM where
// textures are
//-------------------------------------
void GetFontTextureCoor (int *coorx, int *coory)
{
   *coorx = FNTTPX;
   *coory = FNTTPY;
}

//-------------------------------------
// Converts an int to a string
//-------------------------------------
void itoa (int number, char str[])
{
   int i = 1000000000, j = 0, k = 0;

   if (number < 0)
   {
      str[k] = '-';
      k++;
      number = -number;
   }

   while (i != 0)
   {
      if (number / i)
      {
         j = 1;
         str[k] = 48 + (number / i);
         k++;
         number -= (number / i) * i;
      }
      else
      {
         if ((j) || (i == 1))
         {
            str[k] = '0';
            k++;
         }
      }

      i = i / 10;
   }

   str[k] = 0;
}
