#if defined(WIN32)
#include <direct.h>
#include <io.h>
#endif /* WIN32 */
 
#include "FIL_CPA.h"
 
#define D_FIL_StructureDefine
 
#include "ErmFil.h"
 
#include "FIL_Pub.h"
#include "FIL_Priv.h"
 
#include "FIL_Tga.h"
 
#include "MMG.h"
 
/**************************************************************************/
/*
EXTERN CPA_EXPORT void FIL_fn_vTGASaveInFile(char *p_szFileName, unsigned char ucNumberOfBytesInSource, FIL_tdstBitmapData *_p_stSource )
{
}
*/
/**************************************************************************/
FILE *FIL_fn_hTGAOpenFile( char *_p_szPath, char *_p_szFileName, FIL_tdstTga *_p_stTga )
{
    /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
    FILE                *p_stFile;
    char                szCompleteName[_MAX_PATH];
    unsigned char       ucBpp, ucDesc, ucCode;
    /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
 
    if ( *_p_szPath != 0)
	    sprintf(szCompleteName, "%s\\%s", _p_szPath, _p_szFileName);
    else
	    sprintf(szCompleteName,"%s", _p_szFileName);
 
    if ( (p_stFile = fopen(szCompleteName,"rb")) !=NULL)
    {
        fread(&_p_stTga->stFileHeader,sizeof(struct FIL_tdstTgaFileHeader_),1,p_stFile);
        ucBpp  = _p_stTga->stFileHeader.stImageSpecification.ucPixelSize;
        ucDesc = _p_stTga->stFileHeader.stImageSpecification.ucDescriptorByte;
        ucCode = _p_stTga->stFileHeader.ucImageTypeCode; 
 
        if (    
            ( ucBpp != 24 || ucDesc != 0 ) && ( ucBpp != 32 || ( ucDesc != 0 && ucDesc != 8) ) && ( ucBpp!=8 || ( ucDesc != 0 && ucDesc != 8) )
            ||( ucCode !=1 &&ucCode!=2 && ucCode != 3 && ucCode != 10)
           )
        {
            M_FILInformationErrorWithMessage(E_uwFILBadTgaFormat, szCompleteName);
            fclose( p_stFile );
            p_stFile = NULL;
        }
    }
 
    return p_stFile;
 
}
 
/**************************************************************************/
void FIL_fn_vTGALoadInformationFromFile(char *p_szPath,char *p_szFileName, struct FIL_tdstGF_	*_p_stHeader )
{
    /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
    FILE						*p_stFile;
    struct FIL_tdstTga_			stTga;
	struct FIL_tdstFileHeader_	*p_stFileHeader = &(_p_stHeader -> stFileHeader);
    /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
 
    p_stFile = FIL_fn_hTGAOpenFile( p_szPath, p_szFileName, &stTga );
    if (p_stFile == NULL)
    {
        p_stFileHeader->ucBpcInPalette = 0;
        p_stFileHeader->ucBpp          = 0;
        p_stFileHeader->ulWidth        = 0;
        p_stFileHeader->ulHeight       = 0;
        return;
    }
 
    p_stFileHeader->ulWidth        = (unsigned long)stTga.stFileHeader.stImageSpecification.uwWidth;
    p_stFileHeader->ulHeight       = (unsigned long)stTga.stFileHeader.stImageSpecification.uwHeight;
    p_stFileHeader->ucBpp          = (unsigned char)(stTga.stFileHeader.stImageSpecification.ucPixelSize/8);
    p_stFileHeader->ucBpcInPalette = (unsigned char)(stTga.stFileHeader.stColorMapSpecification.ucEntrySize/8);
            /*
            if (stTga.stFileHeader.ucImageTypeCode==1)  //*** No compression in palette ***
            {
                //VL
                //*p_ucNumberOfBytesInDest = (unsigned char)(stTga.stFileHeader.stColorMapSpecification.ucEntrySize/8);
                *p_ucNumberOfBytesInDest = (unsigned char)(stTga.stFileHeader.stImageSpecification.ucPixelSize/8);
                *p_ucPaletteDepth = (unsigned char)(stTga.stFileHeader.stColorMapSpecification.ucEntrySize/8);
                //EVL
            }
            else if (stTga.stFileHeader.ucImageTypeCode==3)  //*** No compression 8 bits (gray levels) ***
                *p_ucNumberOfBytesInDest = 3;
            else
                *p_ucNumberOfBytesInDest = (unsigned char)(stTga.stFileHeader.stImageSpecification.ucPixelSize/8);
                */
    fclose(p_stFile);
}
 
/**************************************************************************/
#ifndef RETAIL
void FIL_fn_vTGALoadFromFileWithInvertPicture(char *p_szPath,char *p_szFileName, FIL_tdstGF	*_p_stHeader )
{
    FIL_fn_vTGALoadFromFileWithoutInvertPicture(p_szPath, p_szFileName, _p_stHeader );
    if ( _p_stHeader->p_ucBitMap != NULL )
        FIL_fn_vTGAInvert( _p_stHeader );
}
#endif /*RETAIL*/
 
/**************************************************************************/
void FIL_fn_vTGALoadFromFileWithoutInvertPicture(char *p_szPath, char *p_szFileName, FIL_tdstGF	*_p_stHeader)
{
    FILE						*p_stFile;
    struct FIL_tdstTga_			stTga;
    unsigned long				i,j;
    unsigned char				ucCount; 
    unsigned char				ucColorTable[4]; /**** RGBA ****/
    unsigned long				ulBitmapSize;
	struct FIL_tdstFileHeader_	*p_stFileHeader = &(_p_stHeader -> stFileHeader);
 
    
    stTga.p_ucBitMap = NULL;
    stTga.ucColorMapData = NULL;
    memset( _p_stHeader, 0, sizeof( FIL_tdstGF ) );
 
    p_stFile = FIL_fn_hTGAOpenFile( p_szPath, p_szFileName, &stTga );
    if (p_stFile == NULL)
        return;
    p_stFileHeader->ulWidth            = (unsigned long)stTga.stFileHeader.stImageSpecification.uwWidth;
    p_stFileHeader->ulHeight           = (unsigned long)stTga.stFileHeader.stImageSpecification.uwHeight;
    p_stFileHeader->ucBpp              = (unsigned char)(stTga.stFileHeader.stImageSpecification.ucPixelSize/8);
    p_stFileHeader->ucBpcInPalette     = (unsigned char)(stTga.stFileHeader.stColorMapSpecification.ucEntrySize/8);
    p_stFileHeader->uwNbColorInPalette = stTga.stFileHeader.stColorMapSpecification.uwLength;
 
    ulBitmapSize = p_stFileHeader->ulWidth * p_stFileHeader->ulHeight * p_stFileHeader->ucBpp;
	
    if (stTga.stFileHeader.ucImageTypeCode==1)  /**** No compression in palette ****/
    {
        if ( p_stFileHeader->ucBpp != 1 || p_stFileHeader->ucBpcInPalette != 3)
        {
            char szCompleteName[MAX_PATH];
            sprintf( szCompleteName, "%s\\%s", p_szPath, p_szFileName );
            M_FILInformationErrorWithMessage( E_uwFILBadTgaFormat, szCompleteName);
        }
        else
        {
		    MMG_fn_vAddMemoryInfo (MMG_C_lTypeFile , MMG_C_lSubTypeTgaFile , NULL);
		    stTga.p_ucBitMap = (unsigned char *) TMP_M_p_Malloc (max(ulBitmapSize, p_stFileHeader->uwNbColorInPalette * sizeof(RGBQUAD)) );
 
		    fseek(p_stFile, sizeof(struct FIL_tdstTgaFileHeader_) + stTga.stFileHeader.ucNumberOfCharInIdentField, SEEK_SET);
 
	        MMG_fn_vAddMemoryInfo (MMG_C_lTypeFile , MMG_C_lSubTypeTgaFile , NULL);
            stTga.ucColorMapData = (unsigned char *) TMP_M_p_Malloc ( p_stFileHeader->uwNbColorInPalette * sizeof(RGBQUAD) );
		    /*fread( stTga.ucColorMapData, p_stFileHeader->ucBpcInPalette, p_stFileHeader->uwNbColorInPalette, p_stFile);*/
            /* We first put the colormap in the bitmap field, then we convert it into the colormap field */
		    fread( stTga.p_ucBitMap, p_stFileHeader->ucBpcInPalette, p_stFileHeader->uwNbColorInPalette, p_stFile);
            for (i=0 ; i<p_stFileHeader->uwNbColorInPalette ; i++)
            {
                stTga.ucColorMapData[i*sizeof(RGBQUAD)+0] = stTga.p_ucBitMap[i*p_stFileHeader->ucBpcInPalette + 0];
                stTga.ucColorMapData[i*sizeof(RGBQUAD)+1] = stTga.p_ucBitMap[i*p_stFileHeader->ucBpcInPalette + 1];
                stTga.ucColorMapData[i*sizeof(RGBQUAD)+2] = stTga.p_ucBitMap[i*p_stFileHeader->ucBpcInPalette + 2];
                stTga.ucColorMapData[i*sizeof(RGBQUAD)+3] = 0xff;
            }
            /* Then we read the bitmap */
		    fread( stTga.p_ucBitMap, 1, ulBitmapSize, p_stFile);
            /*TMP_M_Free(stTga.ucColorMapData);*/
        }
    }
    else if (stTga.stFileHeader.ucImageTypeCode == 2)  /**** No compression 24 or 32 bits ****/
    {
	    MMG_fn_vAddMemoryInfo (MMG_C_lTypeFile , MMG_C_lSubTypeTgaFile , NULL);
        stTga.p_ucBitMap = (unsigned char *) TMP_M_p_Malloc( ulBitmapSize );
        fseek(p_stFile, sizeof(struct FIL_tdstTgaFileHeader_) + stTga.stFileHeader.ucNumberOfCharInIdentField + stTga.stFileHeader.stColorMapSpecification.uwLength, SEEK_SET);
        fread(stTga.p_ucBitMap, 1, ulBitmapSize, p_stFile);
    }
    else if (stTga.stFileHeader.ucImageTypeCode == 3)  /**** No compression 8 bits (gray levels) ****/
    {
        p_stFileHeader->ucBpp = 3;
	    MMG_fn_vAddMemoryInfo (MMG_C_lTypeFile , MMG_C_lSubTypeTgaFile , NULL);
        stTga.p_ucBitMap = (unsigned char *) TMP_M_p_Malloc( ulBitmapSize );
        fseek(p_stFile, sizeof(struct FIL_tdstTgaFileHeader_) + stTga.stFileHeader.ucNumberOfCharInIdentField + stTga.stFileHeader.stColorMapSpecification.uwLength, SEEK_SET);
        for(i=0;i < p_stFileHeader->ulWidth * p_stFileHeader->ulHeight ; i++)
        {
            fread(&ucCount,sizeof(unsigned char),1,p_stFile);
            memset(stTga.p_ucBitMap + i * p_stFileHeader->ucBpp , ucCount, p_stFileHeader->ucBpp);
        }
 
   }
   else if (stTga.stFileHeader.ucImageTypeCode==10) /**** RLE compression 24 or 32 bits ****/
   {
	    MMG_fn_vAddMemoryInfo (MMG_C_lTypeFile , MMG_C_lSubTypeTgaFile , NULL);
        stTga.p_ucBitMap = (unsigned char *)TMP_M_p_Malloc( ulBitmapSize );
        fseek(p_stFile, sizeof(struct FIL_tdstTgaFileHeader_) +stTga.stFileHeader.ucNumberOfCharInIdentField +stTga.stFileHeader.stColorMapSpecification.uwLength, SEEK_SET);
        for(i=0;i < p_stFileHeader->ulWidth * p_stFileHeader->ulHeight ;)
        {
            fread(&ucCount,sizeof(unsigned char),1,p_stFile);
            if (ucCount&0x80) /**** RLE package ****/
            {
                ucCount = (unsigned char)((ucCount&0x7f)+1);
                fread(ucColorTable,sizeof(unsigned char), p_stFileHeader->ucBpp, p_stFile);
                for (j=0;j<(unsigned long)ucCount;j++)
                {
                    memcpy(stTga.p_ucBitMap+i * p_stFileHeader->ucBpp, ucColorTable, p_stFileHeader->ucBpp );
                    i++;
                }
            }
            else /**** Raw package ****/
            {
                ucCount = (unsigned char)((ucCount&0x7f)+1);
                for (j=0;j<(unsigned long)ucCount;j++)
                {
                    fread(ucColorTable,sizeof(unsigned char),p_stFileHeader->ucBpp,p_stFile);
                    memcpy(stTga.p_ucBitMap+i*p_stFileHeader->ucBpp,ucColorTable,p_stFileHeader->ucBpp);
                    i++;
                }
            }
        }
   }
  fclose(p_stFile);
  _p_stHeader->p_ucBitMap = stTga.p_ucBitMap;
  _p_stHeader->p_ucPalette = stTga.ucColorMapData;
}
 
/**************************************************************************/
void FIL_fn_vTGALoadInformationFromConcatFile(FIL_tdxHandleToConcatFile hConcatFile,char *p_szPath,char *p_szFileName, struct FIL_tdstGF_	*_p_stHeader)
{
    FIL_fn_vTGALoadInformationFromFile(p_szPath,p_szFileName, _p_stHeader );
}
 
/**************************************************************************/
void FIL_fn_vTGALoadFromConcatFileWithInvertPicture(FIL_tdxHandleToConcatFile hConcatFile,char *p_szPath,char *p_szFileName, struct FIL_tdstGF_	*_p_stHeader )
{
    FIL_fn_vTGALoadFromConcatFileWithoutInvertPicture(hConcatFile, p_szPath, p_szFileName, _p_stHeader);
    if ( _p_stHeader->p_ucBitMap != NULL)
        FIL_fn_vTGAInvert( _p_stHeader );
}
 
/**************************************************************************/
void FIL_fn_vTGALoadFromConcatFileWithoutInvertPicture(FIL_tdxHandleToConcatFile hConcatFile,char *p_szPath,char *p_szFileName,struct FIL_tdstGF_ *_p_stHeader )
{
    FIL_fn_vTGALoadFromFileWithoutInvertPicture(p_szPath,p_szFileName,_p_stHeader);
}
 
/**************************************************************************/
void FIL_fn_vTGAFree( unsigned char **pp_ucMemory )
{
    if (*pp_ucMemory!=NULL)
        TMP_M_Free(*pp_ucMemory);
 
    *pp_ucMemory = NULL;
}
 
/**************************************************************************/
void FIL_fn_vTGAInvert( struct FIL_tdstGF_ *_p_stHeader )
{
    unsigned char				*p_ucOneLine,*p_ucBlockStart;
    unsigned long				y, ulLineSize;
	struct FIL_tdstFileHeader_	*p_stFileHeader = &(_p_stHeader -> stFileHeader);
 
    MMG_fn_vAddMemoryInfo (MMG_C_lTypeFile , MMG_C_lSubTypeTgaFile , NULL);
    ulLineSize = p_stFileHeader->ulWidth * p_stFileHeader->ucBpp;
    p_ucOneLine = (unsigned char *) TMP_M_p_Malloc ( ulLineSize );
 
    p_ucBlockStart = _p_stHeader->p_ucBitMap;
 /* GuS : palette is now stored into the filed ucColorMapData
    if(p_stFileHeader->ucBpp == 1)
    {
	    p_ucBlockStart += 256 * sizeof(RGBQUAD);
    }
 */
    for (y=0; y < p_stFileHeader->ulHeight / 2 ; y++)
    {
        memcpy( p_ucOneLine                                                  , p_ucBlockStart + y * ulLineSize                            , ulLineSize);
        memcpy( p_ucBlockStart + y * ulLineSize                              , p_ucBlockStart+(p_stFileHeader->ulHeight - 1 - y) * ulLineSize, ulLineSize);
        memcpy( p_ucBlockStart + (p_stFileHeader->ulHeight - 1 - y) * ulLineSize, p_ucOneLine                                                , ulLineSize);
    }
 
    TMP_M_Free(p_ucOneLine);
}
/**************************************************************************/
