/*
 =======================================================================================
  Name        : Tex.c
  Author      : GLIGLOU
  Description : texture function
 =======================================================================================
 */
 
#define MTH_LOW
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
 
#include "gli_st.h"
#include "GLI_Defn.h"
#include "light_st.h"
#include "PvObj_st.h"
#include "texture.h"
#include "TEX.h"
#include "load.h"
 
#include "TMP.h"
#include "VIG.h"
 
#include "FIL.h"
#include "SNA.h"
 
#include "acp_opfi.h"
#include "texture.h"
#include "DLLInter.h"
#include "DLLCaps.h"
#include "TexName.h"
#include "TexArray.h"
#include "TexCompress.h"
#include "TexBench.h"
#include "MatBench.h"
#include "GliTExt.h"
#include "acp_driver.h"
 
/*
 =======================================================================================
    Macro
 =======================================================================================
 */
 
/*
 * Error
 */
#define TEX_M_ERROR(B)\
{\
   Erm_M_UpdateLastError(GEO, C_ucErmDefaultChannel, E_uwGEOCanNotloadBitmap , C_lErmNoDebugData , C_ucErmOpenInfoWindow, C_ucAllowStopForDebug, B);\
}\
 
/*
 =======================================================================================
    Globals
 =======================================================================================
 */
 
/*
 * memory
 */
unsigned long               GLI_gsCurrentMemoryChannel;
long                        g_lTextureMode = TEX_C_AGP;
 
/*
 * array of texture name
 */
extern long                   gs_lNumberOfTextureToCreate;
 
/*
 * to convert texture
 */
void *                      GLI_gs_p_ConvertBufferMipMapping;
long                        GLI_gs_lConvertBufferMipMappingSizeInBytes;
 
/*
 * bigfile with textures
 */
FIL_tdxHandleToConcatFile   GLI_g_hConcatTexturesFile = NULL;
 
/*
 =======================================================================================
    Prototype
 =======================================================================================
 */
void GLI_vDownLoadTexture(BOOL);

#ifdef __cplusplus
extern "C" 
{
#endif
 
/*
 =======================================================================================
    Texture memory mode / video memory mode
 =======================================================================================
 */
 
/*
 ----------------------------------------------------------------------------------------
  Description   : set video memory mode
 ----------------------------------------------------------------------------------------
 */
void GLI_vSetTextureMode(char *sMode)
{
  if( stricmp(sMode, "Vram") == 0)          g_lTextureMode = TEX_C_VRAM;
  else if( stricmp(sMode, "Vram+") == 0)    g_lTextureMode = TEX_C_VRAMAGP;
  else if( stricmp(sMode, "Vram4") == 0)    g_lTextureMode = TEX_C_VRAM4;
  else if( stricmp(sMode, "Vram8") == 0)    g_lTextureMode = TEX_C_VRAM8;
  else if( stricmp(sMode, "Agp") == 0)      g_lTextureMode = TEX_C_AGP;
  else if( stricmp(sMode, "Agp4") == 0)     g_lTextureMode = TEX_C_AGP4;
  else if( stricmp(sMode, "Agp8") == 0)     g_lTextureMode = TEX_C_AGP8;
  else                                      g_lTextureMode = TEX_C_AGP;
}
 
/*
 ----------------------------------------------------------------------------------------
  Description   : retrieve video memory mode
 ----------------------------------------------------------------------------------------
 */
long GLI_lGetTextureMode()
{
  return g_lTextureMode;
}
 
/*
 ----------------------------------------------------------------------------------------
  Description   : set current memory channel for texture
 ----------------------------------------------------------------------------------------
 */
void GLI_TEX_vSignalCurrentMemoryChannel(unsigned char ucCurrentChannel)
{
    GLI_gsCurrentMemoryChannel = (long)ucCurrentChannel;
}
 
/*
 ----------------------------------------------------------------------------------------
  Description   : unallocate all the textures allocated in this channel.
 ----------------------------------------------------------------------------------------
 */
void GLI_TEX_vKillMemoryChannel(unsigned char ucCurrentChannel)
{
    GLI_vUnloadTexture();
    GLI_fn_vUnallocTextureInChannel( ucCurrentChannel );
    /*GLI_vDownLoadTexture(TRUE); */
}
 
/*
 =======================================================================================
    Assert texture 
 =======================================================================================
 */
 
/*
 ----------------------------------------------------------------------------------------
  Description   : return the power of 2 of n
 ----------------------------------------------------------------------------------------
 */
long GLI_lGetLog2n(long ln)
{
    if (ln > 8192)  return (13);
    if (ln > 4096)  return (12);
    if (ln > 2048)  return (11);
    if (ln > 1024)  return (10);
    if (ln > 512)   return (9); 
    if (ln > 256)   return (8);
    if (ln > 128)   return (7);
    if (ln > 64)    return (6);
    if (ln > 32)    return (5);
    if (ln > 16)    return (4);
    if (ln >  8)    return (3);
    if (ln >  4)    return (2);
    if (ln >  2)    return (1);
    return (0);
}
 
/*
 ----------------------------------------------------------------------------------------
  Description   : return 1 if number is a power of 2
 ----------------------------------------------------------------------------------------
 */
long GLI_lIsPowerOf2(long ln)
{
    if (
            (ln == 128)  || (ln == 64)   || (ln == 32)   || (ln == 16)   || (ln == 8)    || (ln == 4) || (ln == 2) || (ln == 1) ||
            (ln == 8192) || (ln == 4096) || (ln == 2048) || (ln == 1024) || (ln == 512)  || (ln == 256) 
       ) 
        return 1;
    
    return 0;
}
 
/*
 ----------------------------------------------------------------------------------------
  Description   : check texture size (two dimension have to be power of 2)
 ----------------------------------------------------------------------------------------
 */
void GLI_vAssertTexture( GLI_tdstTexture *p_stTexture )
{
    if ( GLI_lIsPowerOf2(p_stTexture->lHeight) && ( (p_stTexture->lHeight == p_stTexture->lWidth) || GLI_lIsPowerOf2(p_stTexture->lWidth) ) )
        return;
 
    TEX_M_ERROR( p_stTexture->a255_cFileName );
}
 
/*
 ----------------------------------------------------------------------------------------
  Description   : init texture reading
 ----------------------------------------------------------------------------------------
 */
void GLI_vIniTextRead()
{
    GLI_fn_vUnallocAllTextures();
    gs_lNumberOfTextureToCreate = 0;
};
 
/*
 ----------------------------------------------------------------------------------------
  Description   : Open big file for textures
 ----------------------------------------------------------------------------------------
 */
void GLI_fn_vOpenBigFileTextures(char *p_szFileName)
{
    /* Multi-install Open file */
    ACP_M_OPENFILE(FIL_fn_vOpenConcatFile,GLI_g_hConcatTexturesFile,NULL,p_szFileName,(p_szFileName));
}
 
/*
 ----------------------------------------------------------------------------------------
  Description   : close big file for textures
 ----------------------------------------------------------------------------------------
 */
void GLI_fn_vCloseBigFileTextures(void)
{
    FIL_fn_vCloseConcatFile(&GLI_g_hConcatTexturesFile);
}
 
/*
 ----------------------------------------------------------------------------------------
  Description   : Create a texture (alloc and init)
 ----------------------------------------------------------------------------------------
 */
void GLI_xCreateTexture ( GLI_tdstTexture **h_stTexture )
{
    MMG_fn_vAddMemoryInfo (MMG_C_lTypeGLI , MMG_C_lSubTypeTexture , NULL);
    GEO_M_CPAMalloc(*h_stTexture,GLI_tdstTexture *,sizeof(GLI_tdstTexture),E_uwGEONotEnoughtMemory );
    memset(*h_stTexture,0,sizeof(GLI_tdstTexture));
    TEX_vSetTextureQualityLevel( (*h_stTexture) , (char)TEX_C_QNORMAL);
}
 
/*
 =======================================================================================
 =======================================================================================
    Tranform Bitmap
 =======================================================================================
 =======================================================================================
 */
 
/*
 ----------------------------------------------------------------------------------------
  Description   : Will detect frontier between chromakey and non-chromakey colors, for 
    filtering the black-border visible when bi-linear filtering is enable.
 ----------------------------------------------------------------------------------------
 */
void GLI_vComputeNZFiltering( GLI_tdstTexture *p_stTexture , void *GLI_gs_p_ConvertBuffer)
{
    long            ADDY ,SUBY ,ADDX ,SUBX ;
    unsigned long   lBitmapCounter,lBitmapCounter2,p_vConvertBufferCount , lLocalColor;
    unsigned long   lChromakeyColor = p_stTexture -> lChromakeyColorRGBA & 0x00ffffff; /* 0x00f8f8f8 */
  
    p_vConvertBufferCount = (long)GLI_gs_p_ConvertBuffer ;
  
    if ((p_stTexture -> lWidth == 1) && (p_stTexture -> lHeight == 1))
        return; 
  
    for (lBitmapCounter2 = 0;lBitmapCounter2 < (unsigned long) (p_stTexture -> lHeight * p_stTexture -> lWidth);lBitmapCounter2 += p_stTexture -> lWidth)
        for (lBitmapCounter = 0;lBitmapCounter < (p_stTexture -> lWidth);lBitmapCounter ++)
        {
            if ((*(((unsigned long *)p_vConvertBufferCount)+ lBitmapCounter + lBitmapCounter2)& 0x00ffffff) == lChromakeyColor) /* 0x00f8f8f8 */
                *(((unsigned long *)p_vConvertBufferCount)+lBitmapCounter + lBitmapCounter2) &= 0xffffff;
            else  
                *(((unsigned long *)p_vConvertBufferCount)+lBitmapCounter + lBitmapCounter2)  |= 0xff000000;
        }
    
    for (lBitmapCounter2 = 0;lBitmapCounter2 < (unsigned long) (p_stTexture -> lHeight * p_stTexture -> lWidth);lBitmapCounter2 += p_stTexture -> lWidth)
        for (lBitmapCounter = 0;lBitmapCounter < ((p_stTexture -> lWidth));lBitmapCounter ++)
        {
            ADDY = p_stTexture -> lWidth;
            SUBY = -(signed long)p_stTexture -> lWidth;
            ADDX = 1;
            SUBX = -1;
            if (lBitmapCounter2 == 0) 
                SUBY = ADDY;
            if (lBitmapCounter2 == (unsigned long) ((p_stTexture -> lHeight-1) * p_stTexture -> lWidth)) 
                ADDY = SUBY ;
            if (lBitmapCounter == 0) 
                SUBX = ADDX;
            if (lBitmapCounter == (unsigned long) ((p_stTexture -> lWidth - 1))) 
                ADDX = SUBX;
        
            lLocalColor = 0;
 
            if ((*(((unsigned long *)p_vConvertBufferCount) + lBitmapCounter + lBitmapCounter2)& 0xFF000000) == 0) 
            {
                if ((*(((unsigned long *)p_vConvertBufferCount)+ADDX + lBitmapCounter + lBitmapCounter2)& 0xFF000000) != 0)
                    lLocalColor = ((*(((unsigned long *)p_vConvertBufferCount) +ADDX  + lBitmapCounter + lBitmapCounter2) & 0xfefefefe) >> 1) + ((lLocalColor & 0xfefefefe) >> 1);
                if ((*(((unsigned long *)p_vConvertBufferCount)+SUBX  + lBitmapCounter + lBitmapCounter2)& 0xFF000000) != 0)
                    lLocalColor = ((*(((unsigned long *)p_vConvertBufferCount) +SUBX + lBitmapCounter + lBitmapCounter2) & 0xfefefefe) >> 1) + ((lLocalColor & 0xfefefefe) >> 1);
                if ((*(((unsigned long *)p_vConvertBufferCount)+ADDY + lBitmapCounter + lBitmapCounter2)& 0xFF000000) != 0)
                    lLocalColor = ((*(((unsigned long *)p_vConvertBufferCount) +ADDY  + lBitmapCounter + lBitmapCounter2) & 0xfefefefe) >> 1) + ((lLocalColor & 0xfefefefe) >> 1);
                if ((*(((unsigned long *)p_vConvertBufferCount)+ADDX+ADDY + lBitmapCounter + lBitmapCounter2)& 0xFF000000) != 0)
                    lLocalColor = ((*(((unsigned long *)p_vConvertBufferCount)+ADDX +ADDY  + lBitmapCounter + lBitmapCounter2) & 0xfefefefe) >> 1) + ((lLocalColor & 0xfefefefe) >> 1);
                if ((*(((unsigned long *)p_vConvertBufferCount)+SUBX  +ADDY + lBitmapCounter + lBitmapCounter2)& 0xFF000000) != 0)
                    lLocalColor = ((*(((unsigned long *)p_vConvertBufferCount)+SUBX  +ADDY  + lBitmapCounter + lBitmapCounter2) & 0xfefefefe) >> 1) + ((lLocalColor & 0xfefefefe) >> 1);
                if ((*(((unsigned long *)p_vConvertBufferCount)+SUBY + lBitmapCounter + lBitmapCounter2)& 0xFF000000) != 0)
                    lLocalColor = ((*(((unsigned long *)p_vConvertBufferCount)+SUBY  + lBitmapCounter + lBitmapCounter2) & 0xfefefefe) >> 1) + ((lLocalColor & 0xfefefefe) >> 1);
                if ((*(((unsigned long *)p_vConvertBufferCount)+ADDX+SUBY + lBitmapCounter + lBitmapCounter2)& 0xFF000000) != 0)
                    lLocalColor = ((*(((unsigned long *)p_vConvertBufferCount)+ADDX+SUBY  + lBitmapCounter + lBitmapCounter2) & 0xfefefefe) >> 1) + ((lLocalColor & 0xfefefefe) >> 1);
                if ((*(((unsigned long *)p_vConvertBufferCount)+SUBX+SUBY + lBitmapCounter + lBitmapCounter2)& 0xFF000000) != 0)
                    lLocalColor = ((*(((unsigned long *)p_vConvertBufferCount)+SUBX+SUBY  + lBitmapCounter + lBitmapCounter2) & 0xfefefefe) >> 1) + ((lLocalColor & 0xfefefefe) >> 1);
                lLocalColor &= 0xffffff;
                *(((unsigned long *)p_vConvertBufferCount)+lBitmapCounter + lBitmapCounter2) = lLocalColor ;
            }
        }
}
 
/*
 ----------------------------------------------------------------------------------------
  Description   : smooth chromakey border. And set alpha channel.
 ----------------------------------------------------------------------------------------
 */
void GLI_fn_vFilterNZForAlphaTest( void *_p_vBuffer, long _lWidth, long _lHeight, unsigned long _ulChromakey )
{
    long            ADDY ,SUBY ,ADDX ,SUBX ;
    unsigned long   lBitmapCounter,lBitmapCounter2 ,lLocalColor;
    unsigned long   ulSize;
    unsigned long   *p_ulBuffer, *p_ulEndBuffer;
    float           fRed, fBlue, fGreen;
    char            ucNbColor;
 
    if ( (_lWidth == 1) && ( _lHeight == 1) )
        return; 
  
    p_ulBuffer = (unsigned long *) _p_vBuffer;
    p_ulEndBuffer = p_ulBuffer + (_lWidth * _lHeight );
    _ulChromakey &= 0xFfFfFf; /* 0xf8f8f8 */
 
    for ( ; p_ulBuffer < p_ulEndBuffer; p_ulBuffer++) /* Set the chromakeys to alpha=0, otherwise alpha=1 */
    {
        if ( (*p_ulBuffer & 0xFfFfFf) == _ulChromakey )/* 0xf8f8f8 */
            *p_ulBuffer &= 0xFFFFFF;
        else
            *p_ulBuffer |= 0xFF000000;
    }
  
    p_ulBuffer = (unsigned long *) _p_vBuffer;
    ulSize = (unsigned long) _lWidth * _lHeight;
 
    for (lBitmapCounter2 = 0;lBitmapCounter2 < ulSize ;lBitmapCounter2 += _lWidth) /* For each line */
    {
        SUBY = ((lBitmapCounter2 == 0) ? 1 : -1) * _lWidth;
        ADDY = ( (lBitmapCounter2 == (unsigned long) ((_lHeight - 1) * _lWidth)) ? -1 : 1 ) * _lWidth;
        
        for (lBitmapCounter = 0;lBitmapCounter < (unsigned long) _lWidth;lBitmapCounter ++) /* For each pixel in the line */
        {
            ADDX = ( lBitmapCounter == (unsigned long) ( _lWidth - 1) ) ? -1 : 1;
            SUBX = ( lBitmapCounter == 0) ? 1 : -1;
        
            lLocalColor = 0;
 
            p_ulEndBuffer = p_ulBuffer + lBitmapCounter + lBitmapCounter2;
 
            if ((*p_ulEndBuffer & 0xFF000000) == 0) 
            {
                fRed = fBlue = fGreen = 0.0f;
                
                if ((*( p_ulEndBuffer + ADDX ) & 0xFF000000) != 0)
                {
                    fRed   += ( (float) ( (*( p_ulEndBuffer + ADDX ) & 0xFF0000) >> 16 ) ) / 9.f;
                    fGreen += ( (float) ( (*( p_ulEndBuffer + ADDX ) & 0x00FF00) >>  8 ) ) / 9.f;
                    fBlue  += ( (float) ( (*( p_ulEndBuffer + ADDX ) & 0x0000FF)       ) ) / 9.f;
                }
                if ((*(p_ulEndBuffer + SUBX)& 0xFF000000) != 0)
                {
                    fRed   += ( (float) ( (*( p_ulEndBuffer + SUBX ) & 0xFF0000) >> 16 ) ) / 9.f;
                    fGreen += ( (float) ( (*( p_ulEndBuffer + SUBX ) & 0x00FF00) >>  8 ) ) / 9.f;
                    fBlue  += ( (float) ( (*( p_ulEndBuffer + SUBX ) & 0x0000FF)       ) ) / 9.f;
                }
                if ((*(p_ulEndBuffer + ADDY )& 0xFF000000) != 0)
                {
                    fRed   += ( (float) ( (*( p_ulEndBuffer + ADDY ) & 0xFF0000) >> 16 ) ) / 9.f;
                    fGreen += ( (float) ( (*( p_ulEndBuffer + ADDY ) & 0x00FF00) >>  8 ) ) / 9.f;
                    fBlue  += ( (float) ( (*( p_ulEndBuffer + ADDY ) & 0x0000FF)       ) ) / 9.f;
                }
                if ((*(p_ulEndBuffer + ADDX + ADDY)& 0xFF000000) != 0)
                {
                    fRed   += ( (float) ( (*( p_ulEndBuffer + ADDY + ADDX ) & 0xFF0000) >> 16 ) ) / 9.f;
                    fGreen += ( (float) ( (*( p_ulEndBuffer + ADDY + ADDX ) & 0x00FF00) >>  8 ) ) / 9.f;
                    fBlue  += ( (float) ( (*( p_ulEndBuffer + ADDY + ADDX ) & 0x0000FF)       ) ) / 9.f;
                }
                if ((*(p_ulEndBuffer+ SUBX  +ADDY )& 0xFF000000) != 0)
                {
                    fRed   += ( (float) ( (*( p_ulEndBuffer + ADDY + SUBX ) & 0xFF0000) >> 16 ) ) / 9.f;
                    fGreen += ( (float) ( (*( p_ulEndBuffer + ADDY + SUBX ) & 0x00FF00) >>  8 ) ) / 9.f;
                    fBlue  += ( (float) ( (*( p_ulEndBuffer + ADDY + SUBX ) & 0x0000FF)       ) ) / 9.f;
                }
                if ((*(p_ulEndBuffer + SUBY )& 0xFF000000) != 0)
                {
                    fRed   += ( (float) ( (*( p_ulEndBuffer + SUBY ) & 0xFF0000) >> 16 ) ) / 9.f;
                    fGreen += ( (float) ( (*( p_ulEndBuffer + SUBY ) & 0x00FF00) >>  8 ) ) / 9.f;
                    fBlue  += ( (float) ( (*( p_ulEndBuffer + SUBY ) & 0x0000FF)       ) ) / 9.f;
                }
                if ((*(p_ulEndBuffer + ADDX + SUBY )& 0xFF000000) != 0)
                {
                    fRed   += ( (float) ( (*( p_ulEndBuffer + SUBY + ADDX ) & 0xFF0000) >> 16 ) ) / 9.f;
                    fGreen += ( (float) ( (*( p_ulEndBuffer + SUBY + ADDX ) & 0x00FF00) >>  8 ) ) / 9.f;
                    fBlue  += ( (float) ( (*( p_ulEndBuffer + SUBY + ADDX ) & 0x0000FF)       ) ) / 9.f;
                }
                if ((*(p_ulEndBuffer + SUBX + SUBY )& 0xFF000000) != 0)
                {
                    fRed   += ( (float) ( (*( p_ulEndBuffer + SUBY + SUBX ) & 0xFF0000) >> 16 ) ) / 9.f;
                    fGreen += ( (float) ( (*( p_ulEndBuffer + SUBY + SUBX ) & 0x00FF00) >>  8 ) ) / 9.f;
                    fBlue  += ( (float) ( (*( p_ulEndBuffer + SUBY + SUBX ) & 0x0000FF)       ) ) / 9.f;
                }
 
 
                lLocalColor  = (unsigned long) (fRed) << 16;
                lLocalColor |= (unsigned long) (fGreen) << 8;
                lLocalColor |= (unsigned long) (fBlue);
                /*if ( ucNbColor < 5 )*/
                lLocalColor &= 0x00FFFFFF;
 
                *p_ulEndBuffer = lLocalColor ;
            }
            else
            {
                ucNbColor = 0;
                if ((*( p_ulEndBuffer + ADDX ) & 0xFF000000) == 0)
                    ucNbColor++;
                if ((*(p_ulEndBuffer + SUBX)& 0xFF000000) == 0)
                    ucNbColor++;
                if ((*(p_ulEndBuffer + ADDY )& 0xFF000000) == 0)
                    ucNbColor++;
                if ((*(p_ulEndBuffer + ADDX + ADDY)& 0xFF000000) == 0)
                    ucNbColor++;
                if ((*(p_ulEndBuffer+ SUBX  +ADDY )& 0xFF000000) == 0)
                    ucNbColor++;
                if ((*(p_ulEndBuffer + SUBY )& 0xFF000000) == 0)
                    ucNbColor++;
                if ((*(p_ulEndBuffer + ADDX + SUBY )& 0xFF000000) == 0)
                    ucNbColor++;
                if ((*(p_ulEndBuffer + SUBX + SUBY )& 0xFF000000) == 0)
                    ucNbColor++;
 
                if (ucNbColor >= 7)
                    *p_ulEndBuffer &= 0xFFFFFF;
            }
        }
    }
}
 
 
/*
 ----------------------------------------------------------------------------------------
  Description   : compute alpha value for NZ texture
 ----------------------------------------------------------------------------------------
 */
void GLI_vComputeAlphaForNZTexture( GLI_tdstTexture *_p_stTexture, unsigned long *_p_ulTexel )
{
    /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
    unsigned long   ulChromakeyColor = _p_stTexture->lChromakeyColorRGBA & 0x00f8f8f8;
    unsigned long   *_p_ulLast;
    /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
 
    if ((_p_stTexture->lWidth == 1) && (_p_stTexture->lHeight == 1))
        return; 
  
    _p_ulLast = _p_ulTexel + (_p_stTexture->lWidth * _p_stTexture->lHeight);
    for ( ; _p_ulTexel < _p_ulLast; _p_ulTexel++ )
    {
        if ( (*_p_ulTexel & 0x00F8F8F8) == ulChromakeyColor )
            *_p_ulTexel &= 0xFFFFFF;
        else
            *_p_ulTexel |= 0xFF000000;
    }
}
 
/*
 =======================================================================================
    Function to divide a bitmap surface by 2 
 =======================================================================================
 */
 
/*
 ----------------------------------------------------------------------------------------
  Description   : divide 32b bitmap width by 2
 ----------------------------------------------------------------------------------------
 */
void GLI_vDivideBitmapBy2InX( unsigned long *p_SourceFF,unsigned long *p_DestFF,long lHSurfSouce, long lWSurfSouce )
{
    /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
    long            lWDest,lHDest;
    unsigned long   *p_Source,*p_Dest, *p_stLast;
    /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
 
    lWDest = lWSurfSouce >> 1;
    lHDest = lHSurfSouce;
 
    if (lWDest <=1) 
        return;
  
    p_Source = p_SourceFF;
    p_Dest   = p_DestFF;
    p_stLast = p_Dest + lWDest * lHDest;
      
    for ( ; p_Dest < p_stLast; p_Dest++, p_Source+=2)
        *p_Dest = ((*p_Source & 0xfefefefe) >> 1) + ((*(p_Source+1) & 0xfefefefe) >> 1);
}
 
/*
 ----------------------------------------------------------------------------------------
  Description   : divide 32b bitmap height by 2
 ----------------------------------------------------------------------------------------
 */
void GLI_vDivideBitmapBy2InY(unsigned long *p_SourceFF,unsigned long *p_DestFF,long lHSurfSouce, long lWSurfSouce)
{
    /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
    long            lWDest,lHDest,lXCounter,lYCounter;
    unsigned long   *p_Source,*p_Dest;
    /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
 
    lWDest = lWSurfSouce ;
    lHDest = lHSurfSouce  >>1;
 
    if (lHDest <=1 ) 
        return;
    
    p_Source = p_SourceFF;
    p_Dest   = p_DestFF;
 
    for (lYCounter = 0; lYCounter < lHDest ; lYCounter++, p_Source+=lWSurfSouce)
        for (lXCounter = 0; lXCounter < lWDest ; lXCounter++ , p_Dest++ , p_Source+=1)
            *p_Dest = ((*p_Source & 0xfefefefe) >> 1) + ((*(p_Source+lWSurfSouce) & 0xfefefefe) >> 1) ;
}
 
/*
 ----------------------------------------------------------------------------------------
  Description   : divide 32b bitmap width by 2 (do not take care of zero pixels )
 ----------------------------------------------------------------------------------------
 */
/* Begin G.CLEMENT 29/07/1999 : NZ can be non-black */
void GLI_vDivideBitmapBy2InXNonZero(unsigned long *p_SourceFF,unsigned long *p_DestFF,long lHSurfSouce, long lWSurfSouce, unsigned long ulChromaKey)
{
    /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
    long            lWDest;
    unsigned long   *p_ulLast, Psource1,Psource2;
    /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
 
    lWDest = lWSurfSouce >>1;
 
    if (lWDest <=1) 
        return;
  
    p_ulLast = p_DestFF + lWDest * lHSurfSouce;
      
    /*for ( ; p_DestFF < p_ulLast; p_DestFF++, p_SourceFF+=2)
    {
        Psource1 = ((*p_SourceFF & 0xfefefefe) );
        Psource2 = ((*(p_SourceFF+1) & 0xfefefefe) );
        if ((Psource1 & 0x00f8f8f8) != 0)
        {
            if ((Psource2 & 0x00f8f8f8) != 0)
                *p_DestFF = (Psource1 >> 1) + (Psource2 >> 1);
            else
                *p_DestFF = Psource1;
        } 
        else
            *p_DestFF = Psource2;
    }*/
    for ( ; p_DestFF < p_ulLast; p_DestFF++, p_SourceFF+=2)
    {
        Psource1 = *p_SourceFF;
        Psource2 = *(p_SourceFF+1);
        if ((Psource1 ^ ulChromaKey) & 0x00ffffff) /* 0x00f8f8f8 */
        {
            if ((Psource2 ^ ulChromaKey) & 0x00ffffff) /* 0x00f8f8f8 */
                *p_DestFF = ((Psource1 & 0xfefefefe) >> 1) + ((Psource2 & 0xfefefefe) >> 1);
            else
                *p_DestFF = Psource1;
        } 
        else
            *p_DestFF = Psource2;
    }
}
/* End G.CLEMENT 29/07/1999 */
 
/*
 ----------------------------------------------------------------------------------------
  Description   : divide 32b bitmap Height by 2 (do not take care of zero pixels )
 ----------------------------------------------------------------------------------------
 */
/* Begin G.CLEMENT 29/07/1999 : NZ can be non-black */
void GLI_vDivideBitmapBy2InYNonZero(unsigned long *p_SourceFF,unsigned long *p_DestFF,long lHSurfSouce, long lWSurfSouce, unsigned long ulChromaKey)
{
    /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
    long            lWDest,lHDest,lXCoounter,lYCoounter;
    unsigned long *p_Source,*p_Dest ,Psource1,Psource2;
    /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
 
    lWDest = lWSurfSouce ;
    lHDest  = lHSurfSouce  >>1;
 
    if (lHDest <=1) 
        return;
  
    p_Source  = p_SourceFF;
    p_Dest    = p_DestFF;
 
    /*for (lYCoounter = 0; lYCoounter < lHDest ; lYCoounter++, p_Source+=lWSurfSouce)
        for (lXCoounter = 0; lXCoounter < lWDest ; lXCoounter++ , p_Dest++ , p_Source+=1)
        {
            Psource1 = *p_Source & 0xfefefefe;
            Psource2 = *(p_Source+lWSurfSouce) & 0xfefefefe;
            if ((Psource1 & 0x00f8f8f8) != 0)
            {
                if ((Psource2 & 0x00f8f8f8) != 0)
                    *p_Dest = (Psource1 >> 1) + (Psource2 >> 1);
                else
                    *p_Dest = Psource1;
            } 
            else
                *p_Dest = Psource2;
        }*/
    for (lYCoounter = 0; lYCoounter < lHDest ; lYCoounter++, p_Source+=lWSurfSouce)
        for (lXCoounter = 0; lXCoounter < lWDest ; lXCoounter++ , p_Dest++ , p_Source+=1)
        {
            Psource1 = *p_Source;
            Psource2 = *(p_Source+lWSurfSouce);
			if ((Psource1 ^ ulChromaKey) & 0x00ffffff) /* 0x00f8f8f8 */
			{
				if ((Psource2 ^ ulChromaKey) & 0x00ffffff) /* 0x00f8f8f8 */
					*p_Dest = ((Psource1 & 0xfefefefe) >> 1) + ((Psource2 & 0xfefefefe) >> 1);
				else
					*p_Dest = Psource1;
			} 
			else
				*p_Dest = Psource2;
        }
}
/* End G.CLEMENT 29/07/1999 */
 
/*
 ----------------------------------------------------------------------------------------
  Description   : divide 32b bitmap (width and height) by 2
  !!! Lenght & Width are inverted !!!
 ----------------------------------------------------------------------------------------
 */
void GLI_vDivideBitmapSurfaceBy2 (unsigned long *p_SourceFF,unsigned long *p_DestFF,long lWidthSurfSouce, long lLenghtSurfSouce)
/* !!! Lenght & Width are inverted !!! */
{
    GLI_vDivideBitmapBy2InX(p_SourceFF,p_DestFF,lWidthSurfSouce, lLenghtSurfSouce);
    GLI_vDivideBitmapBy2InY(p_SourceFF,p_DestFF,lWidthSurfSouce >> 1, lLenghtSurfSouce);
}
 
/*
 ----------------------------------------------------------------------------------------
  Description   : divide 32b bitmap (width and height) by 2 (do not take care of zero pixels )
  !!! Lenght & Width are inverted !!!
 ----------------------------------------------------------------------------------------
 */
 /* Begin G.CLEMENT 29/07/1999 : added chromakey */
void GLI_vDivideBitmapSurfaceBy2NonZero (unsigned long *p_SourceFF,unsigned long *p_DestFF,long lWidthSurfSouce, long lLenghtSurfSouce, unsigned long ulChromaKey)
{
    GLI_vDivideBitmapBy2InXNonZero(p_SourceFF,p_DestFF,lWidthSurfSouce, lLenghtSurfSouce, ulChromaKey);
    GLI_vDivideBitmapBy2InYNonZero(p_SourceFF,p_DestFF,lWidthSurfSouce >> 1, lLenghtSurfSouce, ulChromaKey);
}
 /* End G.CLEMENT 29/07/1999 */
/*
 ----------------------------------------------------------------------------------------
  Description   : divide 8b paletized  bitmap (width and height) by 2
                    algorithm to have best result
 ----------------------------------------------------------------------------------------
 */
 
#ifdef DREAMCAST
#pragma inline(GLI_fn_vRGB2YIQ)
#endif
 
INLINE
void GLI_fn_vRGB2YIQ( unsigned char *_p_ulRGB, float *_p_fYIQ )
{
    *_p_fYIQ++  = (float) (0.299 * *(_p_ulRGB + 2) + 0.587 * *(_p_ulRGB + 1) + 0.114 * *_p_ulRGB);
	*_p_fYIQ++  = (float) (0.596 * *(_p_ulRGB + 2) - 0.274 * *(_p_ulRGB + 1) - 0.322 * *_p_ulRGB);
	*_p_fYIQ    = (float) (0.211 * *(_p_ulRGB + 2) - 0.522 * *(_p_ulRGB + 1) + 0.311 * *_p_ulRGB);
}
 
/*
static inline GLI_fn_vYIQ2RGB( float *_p_fYIQ, unsigned char *_p_ulRGB )
{
    *_p_ulRGB++ = 1.00 * *_p_fYIQ + 0.956 * *(_p_fYIQ + 1) +0.623 * *(_p_fYIQ + 2);
    *_p_ulRGB++ = 1.00 * *_p_fYIQ - 0.272 * *(_p_fYIQ + 1) -0.648 * *(_p_fYIQ + 2);
    *_p_ulRGB   = 1.00 * *_p_fYIQ - 1.105 * *(_p_fYIQ + 1) +0.705 * *(_p_fYIQ + 2);
}
*/
 
void GLI_vDivideBitmapSurfaceBy2Palette(unsigned char *_p_ucBitMap,unsigned long *_p_ulPalette,long _lWidth, long _lHeight )
{
    /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
    long            lIndex, lBestIndex;
    float           a_fYIQPalette[ 256 ][ 3 ];
    float           a_fYIQSum[3];
    float           *p_fYIQ, *p_fYIQLast;
    unsigned char   *p_ucSrc1, *p_ucSrc2, *p_ucDest, *p_ucEndLine, *p_ucSrcLast;
    float           fDiff, fDiffLocal, fBestDiff;
    /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
 
    /*
     * compute palette in YIQ
     */
    p_ucSrc1    = (unsigned char *) _p_ulPalette;
    p_ucSrcLast = p_ucSrc1 + 1024;
    p_fYIQ      = (float *) a_fYIQPalette;
    p_fYIQLast  = p_fYIQ + 256 * 3;
    for ( ; p_ucSrc1 < p_ucSrcLast; p_ucSrc1 += 4, p_fYIQ += 3 )
        GLI_fn_vRGB2YIQ( p_ucSrc1, p_fYIQ);
 
    p_ucSrc1    = _p_ucBitMap;             /* for even line*/
    p_ucSrc2    = _p_ucBitMap + _lWidth;   /* for odd line*/
    p_ucDest    = _p_ucBitMap;
    p_ucSrcLast = _p_ucBitMap + _lWidth * _lHeight;
 
    for ( ; p_ucSrc1 < p_ucSrcLast; p_ucSrc1 += _lWidth, p_ucSrc2 += _lWidth )
    {
        p_ucEndLine = p_ucSrc1 + _lWidth;
        for (  ; p_ucSrc1 < p_ucEndLine; )
        {
            a_fYIQSum[0] = a_fYIQPalette[ *p_ucSrc1 ][0]; 
            a_fYIQSum[1] = a_fYIQPalette[ *p_ucSrc1 ][1]; 
            a_fYIQSum[2] = a_fYIQPalette[ *p_ucSrc1++ ][2]; 
            a_fYIQSum[0] += a_fYIQPalette[ *p_ucSrc1 ][0]; 
            a_fYIQSum[1] += a_fYIQPalette[ *p_ucSrc1 ][1]; 
            a_fYIQSum[2] += a_fYIQPalette[ *p_ucSrc1++ ][2]; 
            a_fYIQSum[0] += a_fYIQPalette[ *p_ucSrc2 ][0]; 
            a_fYIQSum[1] += a_fYIQPalette[ *p_ucSrc2 ][1]; 
            a_fYIQSum[2] += a_fYIQPalette[ *p_ucSrc2++ ][2]; 
            a_fYIQSum[0] = (float) ((a_fYIQSum[0] + a_fYIQPalette[ *p_ucSrc2 ][0]) / 4.); 
            a_fYIQSum[1] = (float) ((a_fYIQSum[1] + a_fYIQPalette[ *p_ucSrc2 ][1]) / 4.); 
            a_fYIQSum[2] = (float) ((a_fYIQSum[2] + a_fYIQPalette[ *p_ucSrc2++ ][2]) /4.); 
 
            /*
             *  Search better color in palette that fit with average value
             */ 
            fBestDiff = 10000.f;
            for ( lIndex = 0, p_fYIQ = (float *) a_fYIQPalette; p_fYIQ < p_fYIQLast; lIndex++ )
            {
                fDiffLocal = a_fYIQSum[0] - *p_fYIQ++;
                fDiff = fDiffLocal * fDiffLocal;
                fDiffLocal = a_fYIQSum[1] - *p_fYIQ++;
                fDiff += fDiffLocal * fDiffLocal;
                fDiffLocal = a_fYIQSum[2] - *p_fYIQ++;
                fDiff += fDiffLocal * fDiffLocal;
 
                if (fDiff < fBestDiff)
                {
                    lBestIndex = lIndex;
                    fBestDiff = fDiff;
                }
            }
 
            *p_ucDest++ = (unsigned char) lBestIndex;
        }
    }
}
 
/*
 =======================================================================================
    Mirror textures
 =======================================================================================
 */
 
 
/*
 ----------------------------------------------------------------------------------------
  Description   : mirrored a texture by X       
 
                       _lWidth
                         <->
                      ^ |--x   |    mirror  |--xx--| 
             _lHeight | |-x-   |    ------> |-x--x-|
                      v |--x   |            |--xx--|
 
 ----------------------------------------------------------------------------------------
 */
void TEX_vMirrorX( unsigned long *_p_ulBitmap, long _lWidth, long _lHeight )
{
	/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
	unsigned long *p_ulLastEndLine, *p_ulEndLine, *p_ulStopLine;
	unsigned long *p_ulDestLineMirror, *p_ulDestLine;
	/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
 
	p_ulLastEndLine = _p_ulBitmap;
	p_ulEndLine = _p_ulBitmap + _lWidth * _lHeight - 1;
	p_ulDestLine = _p_ulBitmap + (_lWidth * 2 * _lHeight ) - _lWidth - 1;
	
	while (p_ulEndLine > p_ulLastEndLine )
	{
		p_ulStopLine = p_ulEndLine - _lWidth;
		p_ulDestLineMirror = p_ulDestLine + 1;
 
		while (p_ulEndLine > p_ulStopLine )
		{
			*p_ulDestLineMirror++ = *p_ulEndLine;
			*p_ulDestLine-- = *p_ulEndLine--;
		}
		
		p_ulEndLine = p_ulStopLine;
		p_ulDestLine -= _lWidth;
	}
}
 
/*
 ----------------------------------------------------------------------------------------
  Description   : mirrored a texture by Y,  apply an inversion before
  
                         _lWidth
                         <-->
                      ^ |-XXX|              |    |          |--XX|
             _lHeight v |--XX|  inversion   |    |  mirror  |-XXX|
                        |    |  ----------> |-XXX|  ------> |-XXX|
                        |    |              |--XX|          |--XX|
 
 ----------------------------------------------------------------------------------------
 */
void TEX_vMirrorY_WithInversion( unsigned long *_p_ulBitmap, long _lWidth, long _lHeight )
{
	/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
	unsigned long *p_ulStartCopy, *p_ulDestLine, *p_ulStartLine, *p_ulEndLine, *p_ulCurrent;
	/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
 
	p_ulStartLine = _p_ulBitmap;
	p_ulDestLine = p_ulEndLine = p_ulStartLine + _lWidth * _lHeight;
	while (p_ulStartLine < p_ulEndLine )
		*p_ulDestLine++ = *p_ulStartLine++;
 
	p_ulStartCopy = _p_ulBitmap + _lWidth * _lHeight;
 
	p_ulDestLine = _p_ulBitmap;
	p_ulEndLine = _p_ulBitmap + (_lWidth * _lHeight * 2);
	p_ulStartLine = p_ulEndLine - _lWidth;
	while (p_ulStartLine >= p_ulStartCopy )
	{
		p_ulCurrent = p_ulStartLine;
		while (p_ulCurrent < p_ulEndLine)
		{
			*p_ulDestLine++ = *p_ulCurrent++;
		}
 
		p_ulEndLine = p_ulStartLine;
		p_ulStartLine -= _lWidth;
	}
}
 
/*
 ----------------------------------------------------------------------------------------
  Description   : mirrored a texture by Y 
 
                         _lWidth
                         <-->
                      ^ |--XX|          |--XX|
             _lHeight v |-XXX|  mirror  |-XXX|
                        |    |  ------> |-XXX|
                        |    |          |--XX|
 
 ----------------------------------------------------------------------------------------
 */
void TEX_vMirrorY( unsigned long *_p_ulBitmap, long _lWidth, long _lHeight )
{
	/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
	unsigned long *p_ulDestLine, *p_ulStartLine, *p_ulEndLine, *p_ulCurrent;
	/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
 
	p_ulDestLine = _p_ulBitmap + _lWidth * _lHeight ;
	p_ulEndLine = _p_ulBitmap + (_lWidth * _lHeight );
	p_ulStartLine = p_ulEndLine - _lWidth;
 
	while (p_ulStartLine >= _p_ulBitmap )
	{
		p_ulCurrent = p_ulStartLine;
		while (p_ulCurrent < p_ulEndLine)
		{
			*p_ulDestLine++ = *p_ulCurrent++;
		}
 
		p_ulEndLine = p_ulStartLine;
		p_ulStartLine -= _lWidth;
	}
}
 
 
/*
 =======================================================================================
    Loading textures
 =======================================================================================
 */
 
/*
 ----------------------------------------------------------------------------------------
  Description   : special function to find texture in some other directories
                used only in not final version
 ----------------------------------------------------------------------------------------
 */
#if !defined (_FINAL)
char GLI_cLoadTextureInOtherDirectories( char *szTGAName, char *szGFName, FIL_tdstGF *_p_stHeader, BOOL _bJustInfo )
{
    /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
    static char				szTexturePath[_MAX_PATH];
    static ACP_tdxBool		bSecondDirectory = FALSE;
    static char				szTexturePath1[_MAX_PATH];
    static ACP_tdxBool		bThirdDirectory = FALSE;
	static char				cFirst = 1;
    char                    *subpath;
    /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
 
	if  (cFirst)
	{
		cFirst = 0;
		if ( *gsz_Version != 0 )
		{
			bSecondDirectory = TRUE;
			strcpy(szTexturePath, gsz_Version);
            if ( (subpath = strchr(GLI_fn_szGetPathOfTexture(), '\\')) != NULL)
			    strcat(szTexturePath, subpath );
		
			if ( *gsz_Version1 != 0)
			{
				bThirdDirectory = TRUE;
				strcpy(szTexturePath1, gsz_Version1);
                if ( subpath != NULL)
				    strcat(szTexturePath1, subpath );
			}
		}  
 
	}
 
    if ( _bJustInfo )
    {
        if ( bSecondDirectory )
		    FIL_fn_vGFLoadInformationFromConcatFile( GLI_g_hConcatTexturesFile, szTexturePath, szGFName, _p_stHeader );
        if ( _p_stHeader->stFileHeader.ucBpp != 0)
            return 1;
 
		if ( bThirdDirectory )
			FIL_fn_vGFLoadInformationFromConcatFile( GLI_g_hConcatTexturesFile, szTexturePath1, szGFName, _p_stHeader );
        if ( _p_stHeader->stFileHeader.ucBpp != 0)
            return 1;
    }
    else
    {
        if (bSecondDirectory) 
 		    FIL_fn_vLoadGFFromConcatFileWithoutInvertPicture( GLI_g_hConcatTexturesFile, szTexturePath, szGFName, _p_stHeader );
        if (_p_stHeader->stFileHeader.ucBpp != 0)
            return 1;
 
	    if ( bThirdDirectory ) 
 		    FIL_fn_vLoadGFFromConcatFileWithoutInvertPicture(GLI_g_hConcatTexturesFile,szTexturePath1,szGFName, _p_stHeader );
        if (_p_stHeader->stFileHeader.ucBpp != 0)
            return 1;
	}
	
 
#if defined(_DEBUG)
    if ( _bJustInfo )
    {
        FIL_fn_vTGALoadInformationFromConcatFile(GLI_g_hConcatTexturesFile,GLI_fn_szGetPathOfTexture(),szTGAName, _p_stHeader );
        if ( _p_stHeader->stFileHeader.ucBpp != 0 )
            return 0;
        
        if (bSecondDirectory)
	        FIL_fn_vTGALoadInformationFromConcatFile(GLI_g_hConcatTexturesFile,szTexturePath,szTGAName, _p_stHeader );
        if ( _p_stHeader->stFileHeader.ucBpp != 0 )
            return 0;
 
	    if (bThirdDirectory) 
		    FIL_fn_vTGALoadInformationFromConcatFile(GLI_g_hConcatTexturesFile,szTexturePath1,szTGAName, _p_stHeader);
    }
    else
    {
	    FIL_fn_vTGALoadFromConcatFileWithoutInvertPicture(GLI_g_hConcatTexturesFile,GLI_fn_szGetPathOfTexture(),szTGAName,_p_stHeader );
        if (_p_stHeader->stFileHeader.ucBpp != 0)
            return 0;
	    
        if (bSecondDirectory)
            FIL_fn_vTGALoadFromConcatFileWithoutInvertPicture(GLI_g_hConcatTexturesFile,szTexturePath,szTGAName,_p_stHeader );
        if (_p_stHeader->stFileHeader.ucBpp != 0)
            return 0;
 
	    if ( bThirdDirectory )
		    FIL_fn_vTGALoadFromConcatFileWithoutInvertPicture(GLI_g_hConcatTexturesFile,szTexturePath1,szTGAName,_p_stHeader );
    }
 
    if ( _p_stHeader->stFileHeader.ucBpp == 0 )
    {
            FILE *p_stFile;
 
            if ((p_stFile=fopen("EngTex.log","at"))!=NULL)
            {
                fprintf(p_stFile,"Can not load : %s\n",szTGAName);
                fclose(p_stFile);
            }
    }
	return 0;
 
#endif /* _DEBUG */
}
#endif
 
/*
 ----------------------------------------------------------------------------------------
  Description   : Load TGA texture
 ----------------------------------------------------------------------------------------
 */
 
void GLI_xLoadTextureTGA(GLI_tdstTexture *p_stTexture, char *d_ucFileName , long *p_TexelField)
{
    /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
    long                lBad32Detector;
    unsigned long       lColumnConvertCounter;
    unsigned long       *p_lTexturePtr, *p_lLastTexturePtr;
    unsigned char       *p_ucSource;
    char                szCompleteName[_MAX_PATH];
    FIL_tdstGF			stHeader;
    /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
    
    strcpy(szCompleteName,d_ucFileName);
    strcpy(strrchr(szCompleteName,'.'),".gf");
    FIL_fn_vLoadGFFromConcatFileWithoutInvertPicture(GLI_g_hConcatTexturesFile,GLI_fn_szGetPathOfTexture(),szCompleteName, &stHeader ); 
    
#if !defined (_FINAL)
    if (stHeader.p_ucBitMap == NULL)
    {
        GLI_cLoadTextureInOtherDirectories( d_ucFileName, szCompleteName, &stHeader, FALSE );
    }
#endif  /* _FINAL */
    
    if (stHeader.stFileHeader.ucBpp == 0)
    {
        p_stTexture = NULL;
        return;
    }
    
    stHeader.stFileHeader.ucBpp *= 8;
    p_stTexture->lRealWidth = p_stTexture->lWidth  = (unsigned short) stHeader.stFileHeader.ulWidth;
    p_stTexture->lRealHeight= p_stTexture->lHeight = (unsigned short) stHeader.stFileHeader.ulHeight;
    
    if (stHeader.stFileHeader.ucBpp == 32)
    {
        p_stTexture->lTextureCaps |= GLI_C_lAlphaTexture; 
        lBad32Detector = 0xFFFFFFFF;
        p_lTexturePtr = (long *) p_TexelField ;
        
        for (lColumnConvertCounter = 0; lColumnConvertCounter < (unsigned long) (p_stTexture->lWidth * p_stTexture->lHeight) ; lColumnConvertCounter ++)
        {
            p_lTexturePtr[lColumnConvertCounter] =  (long) stHeader.p_ucBitMap[lColumnConvertCounter*4+2] | (((long) stHeader.p_ucBitMap[lColumnConvertCounter*4+1])<<8) | (((long) stHeader.p_ucBitMap[lColumnConvertCounter*4+0])<<16) | (((long) stHeader.p_ucBitMap[lColumnConvertCounter*4+3])<<24);
            lBad32Detector &= p_lTexturePtr[lColumnConvertCounter];
        }
        if ((lBad32Detector & 0xF0000000) == 0xf0000000) 
            p_stTexture->lTextureCaps &= 0xffffffff - GLI_C_lAlphaTexture;
        
        if ( (p_stTexture->lTextureCaps & GLI_C_lAlphaTexture) && ( p_stTexture->lTextureCaps & GLI_C_lAddTransparencyTexture) )
            p_stTexture->lTextureCaps &= 0xffffffff - GLI_C_lAddTransparencyTexture;
    }
    else if (stHeader.stFileHeader.ucBpp == 24)
    {
        p_lTexturePtr       = (long * )p_TexelField;
        p_lLastTexturePtr   = p_lTexturePtr + p_stTexture->lWidth * p_stTexture->lHeight;
        p_ucSource          = stHeader.p_ucBitMap;

        for ( ; p_lTexturePtr < p_lLastTexturePtr ;p_lTexturePtr++)
        {
            *p_lTexturePtr = (long) *(p_ucSource + 2) | (((long) *(p_ucSource + 1))<<8) | (((long) *p_ucSource)<<16);
            p_ucSource += 3;
        }
    }
    else if (stHeader.stFileHeader.ucBpp == 8)
    {   
        if (GLI_g_stCaps.ulTextureCaps & GLICAPS_TEX_C_ulSupport8P)
        {
            unsigned char   *p_ucColorTable;
            unsigned char   *p_ucLast;
            
            p_lTexturePtr = (long * )p_TexelField;
            p_stTexture->p_vColorTable = stHeader.p_ucPalette;
            /* Copy loaded palette to temp texture palette*/
            /* p_stTexture->p_vColorTable = TMP_M_p_Malloc(256*sizeof(RGBQUAD)); 
            memcpy(p_stTexture->p_vColorTable,stHeader.p_ucBitMap,256*sizeof(RGBQUAD)); */
            p_ucColorTable  = ((unsigned char *) p_stTexture->p_vColorTable + 3);
            p_ucLast        = p_ucColorTable + 256*sizeof(RGBQUAD);
            for ( ; p_ucColorTable < p_ucLast; p_ucColorTable += 4 )
            {
                *p_ucColorTable = 0xFF;
            }
            /* Copy loaded bitmap to TexelField*/
            memcpy(p_lTexturePtr,stHeader.p_ucBitMap/*+256*sizeof(RGBQUAD)*/,p_stTexture->lHeight*p_stTexture->lWidth*stHeader.stFileHeader.ucBpp/8);
        }
        else
        {
            /* driver doesn't support 8 bit paletized texture, transform it*/
            unsigned char   *p_cPtr;
            unsigned long	*p_lColorTable = p_stTexture->p_vColorTable;
            unsigned char	ucSave;
      
            p_lTexturePtr = (long * )p_TexelField;

#ifdef USE_DIRECTX   
             p_stTexture->p_vColorTable = stHeader.p_ucPalette;
	     p_lColorTable = p_stTexture->p_vColorTable;
#endif 
            /* p_lColorTable=TMP_M_p_Malloc(256*4);*/
            
            /* Copy loaded palette to temp texture palette*/
            /*memcpy(p_lColorTable,stHeader.p_ucBitMap,(256*4));*/
            for (lColumnConvertCounter = 0; lColumnConvertCounter < 256; lColumnConvertCounter++)
            {
                ucSave = *((unsigned char *) &p_lColorTable[lColumnConvertCounter]);
                *(((unsigned char *) &p_lColorTable[lColumnConvertCounter]) + 0) = *(((unsigned char *) &p_lColorTable[lColumnConvertCounter]) + 2);
                *(((unsigned char *) &p_lColorTable[lColumnConvertCounter]) + 2) = ucSave;
            }
            
            p_cPtr = (char *)stHeader.p_ucBitMap;
            for (lColumnConvertCounter = 0;lColumnConvertCounter < (unsigned long) (p_stTexture -> lWidth * p_stTexture -> lHeight) ;lColumnConvertCounter ++, p_cPtr ++)
                p_lTexturePtr[lColumnConvertCounter] = p_lColorTable[ *p_cPtr ];
            
            //TMP_M_Free(p_lColorTable);
        }
    }
    else
        TEX_M_ERROR(d_ucFileName);

    FIL_fn_vTGAFree(&stHeader.p_ucBitMap);
}
 
 
/*
 ----------------------------------------------------------------------------------------
  Description   : Load header of TGA file
 ----------------------------------------------------------------------------------------
 */
long TEX_fnl_LoadHeaderTextureTGA(GLI_tdstTexture *_pst_Texture, char *d_ucFileName, long  lTextureCaps, long  lTextureQuality)
{
    /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
	FIL_tdstGF				stHeader;
    char                    szCompleteName[_MAX_PATH];
    /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
 
    _pst_Texture->lTextureCaps = lTextureCaps;
    
	strcpy(szCompleteName,d_ucFileName);
    strcpy(strrchr(szCompleteName,'.'),".gf");
    FIL_fn_vGFLoadInformationFromConcatFile(GLI_g_hConcatTexturesFile,GLI_fn_szGetPathOfTexture(),szCompleteName, &stHeader );
 
#if !defined (_FINAL)
    if (stHeader.stFileHeader.ucBpp == 0)
        GLI_cLoadTextureInOtherDirectories( d_ucFileName, szCompleteName, &stHeader, TRUE );

    if ( stHeader.stFileHeader.ucBpp == 0 )
    {
        FILE *p_stFile;
 
        if ((p_stFile=fopen("EngTex.log","at"))!=NULL)
        {
            fprintf(p_stFile,"Missing : %s\n",d_ucFileName);
            fclose(p_stFile);
        }
    }

#endif
 
    if (stHeader.stFileHeader.ucBpp == 0)
        return 0;
    
    _pst_Texture->lRealWidth  = _pst_Texture->lWidth     = (unsigned short) stHeader.stFileHeader.ulWidth;
    _pst_Texture->lRealHeight = _pst_Texture->lHeight    = (unsigned short) stHeader.stFileHeader.ulHeight;
    
    strcpy( _pst_Texture->a255_cFileName, d_ucFileName);
    
    GLI_vAssertTexture( _pst_Texture );
 
    if ( (stHeader.stFileHeader.ucBpp == 1) && (GLI_g_stCaps.ulTextureCaps & GLICAPS_TEX_C_ulSupport8P) )
        _pst_Texture->lTextureCaps |= GLI_C_lPaletteTexture;
    if (stHeader.stFileHeader.ucBpp == 4) 
        _pst_Texture->lTextureCaps |= GLI_C_lAlphaTexture;
}
 
 
/*
 =======================================================================================
    BMP Files 
 =======================================================================================
 */
 
/*
 ----------------------------------------------------------------------------------------
  Description   : Load Header of BMP file
 ----------------------------------------------------------------------------------------
 */
long TEX_fnl_LoadHeaderTextureBMP( GLI_tdstTexture *_pst_Texture, char *d_ucFileName, long  lTextureCaps, long  lTextureQuality)
{
    /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
    char                ucBBP;
    char                szCompleteName[_MAX_PATH];
    unsigned long       ulWidth, ulHeight;
    FIL_tdstGF          stHeader;
    /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
 
    strcpy(szCompleteName,d_ucFileName);
    strcpy(strrchr(szCompleteName,'.'),".gf");
 
    FIL_fn_vGFLoadInformationFromConcatFile(GLI_g_hConcatTexturesFile,GLI_fn_szGetPathOfTexture(),szCompleteName,&stHeader );
    ucBBP = stHeader.stFileHeader.ucBpp;
    ulWidth = stHeader.stFileHeader.ulWidth;
    ulHeight = stHeader.stFileHeader.ulHeight;
 
 
#if defined(_DEBUG)
    if (ucBBP ==0 )
        FIL_fn_vLoadBMPInformationFromConcatFile(GLI_g_hConcatTexturesFile,GLI_fn_szGetPathOfTexture(),d_ucFileName,&ucBBP,&ulWidth,&ulHeight );

    if ( ucBBP == 0 )
    {
        FILE *p_stFile;
 
        if ((p_stFile=fopen("EngTex.log","at"))!=NULL)
        {
            fprintf(p_stFile,"Missing : %s\n",d_ucFileName);
            fclose(p_stFile);
        }
    }
#endif /* _DEBUG */
 
    if (ucBBP ==0 )
        return 0;

    strcpy( _pst_Texture->a255_cFileName, d_ucFileName);

    _pst_Texture->lRealWidth  = _pst_Texture->lWidth  = (unsigned short) ulWidth;
    _pst_Texture->lRealHeight = _pst_Texture->lHeight = (unsigned short) ulHeight;
 
    GLI_vAssertTexture( _pst_Texture );
 
    _pst_Texture->lTextureCaps = lTextureCaps;
    if (ucBBP == 4) 
        _pst_Texture->lTextureCaps |= GLI_C_lAlphaTexture;
    if (ucBBP == 1) 
        _pst_Texture->lTextureCaps |= GLI_C_lPaletteTexture;

    return 1;
}
 
/*
 ----------------------------------------------------------------------------------------
  Description   : Load BMP file
 ----------------------------------------------------------------------------------------
 */
void GLI_xLoadTextureBMP(GLI_tdstTexture *p_stTexture, char *d_ucFileName , long *p_TexelField)
{
    /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
    char                ucBBP;
    unsigned long       ulWidth, ulHeight;
    long                lBad32Detector;
    unsigned long       lColumnConvertCounter;
    unsigned long       *p_lTexturePtr;
    unsigned char       *pDEF_ucReadBuffer=NULL;
    char                szCompleteName[_MAX_PATH];
	FIL_tdstGF			stHeader;
    /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
  
    strcpy(szCompleteName,d_ucFileName);
    strcpy(strrchr(szCompleteName,'.'),".gf");
	
	FIL_fn_vLoadGFFromConcatFileWithoutInvertPicture(GLI_g_hConcatTexturesFile,GLI_fn_szGetPathOfTexture(),szCompleteName,&stHeader );
    ucBBP = stHeader.stFileHeader.ucBpp;
    ulWidth = stHeader.stFileHeader.ulWidth;
    ulHeight = stHeader.stFileHeader.ulHeight;
    pDEF_ucReadBuffer = stHeader.p_ucBitMap;
 
#if defined(_DEBUG)
	 if (pDEF_ucReadBuffer == NULL)
        FIL_fn_vLoadBMPFromConcatFileWithoutInvertPicture(GLI_g_hConcatTexturesFile,GLI_fn_szGetPathOfTexture(),d_ucFileName,&pDEF_ucReadBuffer,&ucBBP,&ulWidth,&ulHeight);
#endif /* _DEBUG */
 
    if (pDEF_ucReadBuffer!=NULL)
    {
        ucBBP*=8;
        p_stTexture->lRealWidth  = p_stTexture->lWidth  = (unsigned short) ulWidth;
        p_stTexture->lRealHeight = p_stTexture->lHeight = (unsigned short) ulHeight;
 
        if (ucBBP == 32)
        {
            p_stTexture -> lTextureCaps |= GLI_C_lAlphaTexture; 
            lBad32Detector = 0xFFFFFFFF;
            p_lTexturePtr = (long * )p_TexelField ;
            for (lColumnConvertCounter = 0; lColumnConvertCounter < (unsigned long) (p_stTexture -> lWidth * p_stTexture -> lHeight) ; lColumnConvertCounter ++)
            {
                p_lTexturePtr[lColumnConvertCounter] = 
                                (long) pDEF_ucReadBuffer[lColumnConvertCounter*4+2] |
                                (((long) pDEF_ucReadBuffer[lColumnConvertCounter*4+1])<<8) |
                                (((long) pDEF_ucReadBuffer[lColumnConvertCounter*4+0])<<16) |
                                (((long) pDEF_ucReadBuffer[lColumnConvertCounter*4+3])<<24);
                lBad32Detector &= p_lTexturePtr[lColumnConvertCounter];
            }
            if ((lBad32Detector & 0xF0000000) == 0xf0000000) 
                p_stTexture -> lTextureCaps &= 0xffffffff - GLI_C_lAlphaTexture; 
        }
        else if (ucBBP == 24)
        {
            p_lTexturePtr = (long * )p_TexelField;
            for (lColumnConvertCounter = 0;lColumnConvertCounter < (unsigned long) (p_stTexture -> lWidth * p_stTexture -> lHeight) ;lColumnConvertCounter ++)
                p_lTexturePtr[lColumnConvertCounter] = (long) pDEF_ucReadBuffer[lColumnConvertCounter*3+2] | (((long) pDEF_ucReadBuffer[lColumnConvertCounter*3+1])<<8) | (((long) pDEF_ucReadBuffer[lColumnConvertCounter*3+0])<<16);
        }
        else if (ucBBP == 8)
        {
            p_stTexture -> lTextureCaps |= GLI_C_lPaletteTexture; 
            p_lTexturePtr = (long * )p_TexelField;
            MMG_fn_vAddMemoryInfo (MMG_C_lTypeGLI , MMG_C_lSubTypeTexture , NULL);
	        p_stTexture->p_vColorTable=TMP_M_p_Malloc(256*sizeof(RGBQUAD));
	        /* Copy loaded palette to temp texture palette*/
	        memcpy(p_stTexture->p_vColorTable,pDEF_ucReadBuffer,256*sizeof(RGBQUAD));
	        /* Copy loaded bitmap to TexelField*/
	        memcpy(p_lTexturePtr,pDEF_ucReadBuffer+256*sizeof(RGBQUAD),p_stTexture->lHeight*p_stTexture->lWidth*ucBBP);
        }
        else
            TEX_M_ERROR(d_ucFileName);
    }
    else
    {
        p_stTexture = NULL;
#if defined(_DEBUG)
        {
            FILE *p_stFile;
            if ((p_stFile=fopen("EngTex.log","at"))!=NULL)
            {
                fprintf(p_stFile,"Can not load : %s\n",d_ucFileName);
                fclose(p_stFile);
            }
        }
#endif /* _DEBUG */
    } 
 
    FIL_fn_vTGAFree(&pDEF_ucReadBuffer);
}
 
 
/*
 ----------------------------------------------------------------------------------------
  Description   : analyse texture name and load texture header to set texture parameters
 ----------------------------------------------------------------------------------------
 */
long TEX_fnl_LoadTextureParameters(GLI_tdstTexture **h_stTexture, char *d_ucFileName, long  lTextureCaps, long  lTextureQuality)
{
    /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
    unsigned char ucCyclingMode;
    /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
 
    if ( ( h_stTexture == NULL ) || (*h_stTexture == NULL) )
        return 0;

    if ( GLI_fn_lAnalyseTextureName( d_ucFileName, &lTextureCaps, &ucCyclingMode ) == 0)
    {
        return 0;
    }
    
    if ( lTextureCaps & GLI_C_lBMPTexture)
    {
        if ( !TEX_fnl_LoadHeaderTextureBMP( *h_stTexture, d_ucFileName, lTextureCaps, lTextureQuality) )
            return 0;
    }
    else if (lTextureCaps & GLI_C_lTGATexture) 
    {
        if (!TEX_fnl_LoadHeaderTextureTGA( *h_stTexture, d_ucFileName,lTextureCaps, lTextureQuality) )
            return 0;
    }
    
	/*
	 * if texture mirror in case they are not supported
	 */
	if ( (ucCyclingMode & GLI_C_lMirrorUV) && !(GLI_g_stCaps.ulTextureCaps & GLICAPS_TEX_C_ulSupportMirror) )
	{
		if (ucCyclingMode & GLI_C_lMirrorU)
		{
			(*h_stTexture)->lWidth *= 2;
			(*h_stTexture)->lRealWidth *= 2;
		}
		if (ucCyclingMode & GLI_C_lMirrorV)
		{
			(*h_stTexture)->lHeight *= 2;
			(*h_stTexture)->lRealHeight *= 2;
		}
	}
 
    /*
     * special for texture maa : double texture use to do multitexture with Ultra64
     */
    if ( lTextureCaps & GLI_C_lMAATexture )
    {
        (*h_stTexture)->lHeight /= 2;
	    (*h_stTexture)->lRealHeight /= 2;
    }
    
    /*
     * VL : we set Cycling mode of texture with the one we found in the name of file
     *      we keep the 4 high bit of cycling mode because we have to keep bit 5 :
     *      ---X000 : indicate that texture is a texture used for shadow drawing
     */
    (*h_stTexture)->ucCylingMode = ((*h_stTexture)->ucCylingMode & 0xF0) | ucCyclingMode;
    return 1;
}
 
/*
 ----------------------------------------------------------------------------------------
  Description   : Create new texture and set its parameters
 ----------------------------------------------------------------------------------------
 */
void GLI_xLoadTexture(GLI_tdstTexture **h_stTexture, GLD_tdstDeviceAttributes *p_stDev, char *d_ucFileName, long  lTextureCaps, long  lTextureQuality)
{
    char szTextureName[ 256 ];

    TEX_fnv_FixTextureName( szTextureName, d_ucFileName );

    (*h_stTexture) = TEX_fnpst_DoesTextureExist( szTextureName );
    if ((*h_stTexture) != NULL) 
        return;
 
    GLI_xCreateTexture ( h_stTexture );
    if ( !TEX_fnl_LoadTextureParameters(h_stTexture, szTextureName, lTextureCaps, lTextureQuality) )
        return;
        
    TEX_fnv_MakeItExisting( (*h_stTexture) );
}
 
 
/*
 ----------------------------------------------------------------------------------------
  Description   : set texture parameters and make texture existing
 ----------------------------------------------------------------------------------------
 */
void GLI_xLoadTextureHeader(GLI_tdstTexture **h_stTexture, GLD_tdstDeviceAttributes *p_stDev, char *d_ucFileName, long  lTextureCaps, long  lTextureQuality)
{
    if ((*h_stTexture) == NULL) 
        return ;

    if ( !TEX_fnl_LoadTextureParameters(h_stTexture, d_ucFileName, lTextureCaps, lTextureQuality) )
        return;

    TEX_fnv_MakeItExisting( (*h_stTexture) );
}
 
 
/*
 ----------------------------------------------------------------------------------------
  Description   : load texture bitmap data
 ----------------------------------------------------------------------------------------
 */
void GLI_xLoadTextureInTexelField(GLI_tdstTexture *p_stTexture, long *p_lTexelField, BOOL bReloading)
{
    /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
    unsigned short  lWidth,lHeight;
    /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
 
    if (p_stTexture == NULL) 
        return;
 
    /*
     * progress bar information
     */
    GLI_g_ulNumberOfLoadedTexture++;

    if (!bReloading) {
		/* No progress bar for textures in binary load mode*/
		if( SNA_fn_ucGetLoadType() != SNA_LOAD_SNAPSHOT )
			if (!(GLI_g_ulNumberOfLoadedTexture%20))
				VIG_fn_vAddToProgressBar(1);
	}

    /* 
     * keep compression information 
     */
    lWidth  = p_stTexture->lWidth;
    lHeight = p_stTexture->lHeight;
 
    /*
     * load texture bitmap
     */
    if ( p_stTexture->lTextureCaps & GLI_C_lTGATexture)
        GLI_xLoadTextureTGA(p_stTexture, p_stTexture->a255_cFileName, p_lTexelField);
    else if ( p_stTexture->lTextureCaps & GLI_C_lBMPTexture)
        GLI_xLoadTextureBMP(p_stTexture, p_stTexture->a255_cFileName, p_lTexelField);
    else
        return;
  
    p_stTexture->p_vBitMap = p_lTexelField;
 
    /*
     * restore compression information 
     */
    p_stTexture->lHeight = lHeight;
    p_stTexture->lWidth  = lWidth;
 
    /*
     * special thing to do with texture reserved for shadow
     */
    if ( p_stTexture->ucCylingMode & GLI_C_lSpecialMirrorForShadow )
        p_stTexture->ucCylingMode |= GLI_C_lMirrorUV;
 
	/*
	 * in case of mirror texture and if mirror texture are not supported
	 */
	if ( ( p_stTexture->ucCylingMode & GLI_C_lMirrorUV ) && !(GLI_g_stCaps.ulTextureCaps & GLICAPS_TEX_C_ulSupportMirror))
	{
        /*
         * Mirror X/U
         */
        if (p_stTexture->ucCylingMode & GLI_C_lMirrorU )
		{
            if ( p_stTexture->ucCylingMode & GLI_C_lSpecialMirrorForShadow )
			    p_stTexture->ucCylingMode &= ~GLI_C_lMirrorU;
 
			p_stTexture->ucCylingMode |= GLI_C_lCylingU;
			TEX_vMirrorX( p_lTexelField, p_stTexture->lRealWidth, p_stTexture->lRealHeight );
			p_stTexture->lRealWidth *= 2;
        }
        
        /*
         * Mirror Y/V
         */
        if (p_stTexture->ucCylingMode & GLI_C_lMirrorV )
		{
            p_stTexture->ucCylingMode |= GLI_C_lCylingV;
 
            if ( p_stTexture->ucCylingMode & GLI_C_lSpecialMirrorForShadow )
            {
			    p_stTexture->ucCylingMode &= ~GLI_C_lMirrorV;
                TEX_vMirrorY( p_lTexelField, p_stTexture->lRealWidth, p_stTexture->lRealHeight );
            }
            else
            {
			    TEX_vMirrorY_WithInversion( p_lTexelField, p_stTexture->lRealWidth, p_stTexture->lRealHeight );
            }
 
			p_stTexture->lRealHeight *= 2;
		}
 
	}
 
    /*
     * special for texture maa : double texture use to do multitexture with Ultra64
     */
    if ( p_stTexture->lTextureCaps & GLI_C_lMAATexture )
    {
	    p_stTexture->lRealHeight /= 2;
        memmove( p_lTexelField, p_lTexelField + p_stTexture->lRealHeight * p_stTexture->lRealWidth , p_stTexture->lRealHeight * p_stTexture->lRealWidth * 4);
    }
    
    /* 
     * Compress texelfield 
     */
    lHeight = p_stTexture->lRealHeight;
    lWidth  = p_stTexture->lRealWidth;
 
    if ( p_stTexture->lTextureCaps & GLI_C_lNZTexture )
    {
        while (lWidth > p_stTexture->lWidth)
        {
            GLI_vDivideBitmapBy2InXNonZero(p_lTexelField, p_lTexelField, lHeight, lWidth, p_stTexture->lChromakeyColorRGBA); /* G.CLEMENT 29/07/1999 : added chromakey */
            lWidth >>= 1;
        }
        while (lHeight > p_stTexture->lHeight)
        {
            GLI_vDivideBitmapBy2InYNonZero(p_lTexelField, p_lTexelField, lHeight, lWidth, p_stTexture->lChromakeyColorRGBA); /* G.CLEMENT 29/07/1999 : added chromakey */
            lHeight >>= 1;
        }
    }
    else
    {
        while (lWidth > p_stTexture->lWidth)
        {
            GLI_vDivideBitmapBy2InX(p_lTexelField, p_lTexelField, lHeight ,lWidth );
            lWidth >>= 1;
        }
        while (lHeight > p_stTexture->lHeight)
        {
            GLI_vDivideBitmapBy2InY(p_lTexelField, p_lTexelField, lHeight, lWidth );
            lHeight >>= 1;
        }
    }
 
    /* 
     * other filterings 
     */
	if ( (p_stTexture->lTextureCaps & GLI_C_lAlphaTest) || ( (p_stTexture->lTextureCaps & GLI_C_lNZTexture) && (GLI_g_stCaps.ulDriverCaps & GLICAPS_DRV_C_ulSupportAlphaTest ) ) )
    {
        GLI_fn_vFilterNZForAlphaTest( p_lTexelField, p_stTexture->lWidth, p_stTexture->lHeight, p_stTexture->lChromakeyColorRGBA );
        p_stTexture->lTextureCaps &= 0xFFFFFFFF - GLI_C_lNZTexture - GLI_C_lNZFilteredTexture;
        p_stTexture->lTextureCaps |= GLI_C_lAlphaTest;
    }
    else
    {
        if ((!(p_stTexture -> lTextureCaps & GLI_C_lAlphaTexture)) && (p_stTexture -> lTextureCaps & GLI_C_lNZFilteredTexture))
            GLI_vComputeNZFiltering ( p_stTexture , p_lTexelField);
    }
}
 
/*
 =======================================================================================
    Mipmap LOD function
 =======================================================================================
 */
 
/*
 ----------------------------------------------------------------------------------------
  Description   :  load mipmap LOD and add it to texture
 ----------------------------------------------------------------------------------------
 */
void GLI_vLoadLodAndAddItToTexture(GLI_tdstTexture *p_stTexture, GLD_tdstDeviceAttributes *p_stDev,char *d_ucFileName, long  lTextureCaps, long  lTextureQuality)
{
}
 
/*
 ----------------------------------------------------------------------------------------
  Description   :  compute LOD (just set texture as texture with Mipmap LOD)
 ----------------------------------------------------------------------------------------
 */
void GLI_vComputeLod(GLI_tdstTexture *p_stTexture)
{
    p_stTexture -> lNumberOfLod = 1;
}
 
/*
 ----------------------------------------------------------------------------------------
  Description   :  compute LOD
 ----------------------------------------------------------------------------------------
 */
void GLI_vRealyComputeLod(GLI_tdstTexture *p_stTexture)
{
    /* Compute Number of LOD*/
    if ( (p_stTexture->lHeight<=1) || (p_stTexture -> lWidth <= 1) )
        return;
    
    if ( GLI_lGetLog2n(p_stTexture -> lHeight) < GLI_lGetLog2n(p_stTexture -> lWidth) )
        p_stTexture -> lNumberOfLod = GLI_lGetLog2n(p_stTexture -> lHeight) + 1;
    else 
        p_stTexture -> lNumberOfLod = GLI_lGetLog2n(p_stTexture -> lWidth) + 1;
}
 
/*
 ----------------------------------------------------------------------------------------
  Description   :  compute LOD of all textures
 ----------------------------------------------------------------------------------------
 */
void TEX_fn_vComputeLODForAllTextures( void )
{
    long lTextureCounter;
 
    for  (lTextureCounter =0 ; lTextureCounter < GLI_C_lNBMaxOfTextures; lTextureCounter ++)
    {
	    if (gs_aDEFTableOfTextureMemoryChannels[ lTextureCounter ] != GLI_TEXIsUnallocated)
        {
		    if (gs_aDEFTableOfTextureAlreadyRead [lTextureCounter] -> lNumberOfLod != 0)
            {
    		    GLI_vRealyComputeLod(gs_aDEFTableOfTextureAlreadyRead[ lTextureCounter ]);
            }
        }
    }
}
 
/*
 =======================================================================================
    Function to unload / download all textures 
 =======================================================================================
 */
 
/*
 ----------------------------------------------------------------------------------------
  Description   : Compute textures :
                    Init (init tree name and unload/uncompress textures)
                    compute compression
                    Compute LOD and download textures
 ----------------------------------------------------------------------------------------
 */
void GLI_vComputeTextures ()
{ 

	TEXBENCH_fn_vInitTextureSize();

    TEXBENCH_fn_vSetTime( TEXBENCH_C_cBeginUnload );
	GLI_vUnloadTexture();
    TEXBENCH_fn_vSetTime( TEXBENCH_C_cEndUnload );

    TEXBENCH_fn_vSetTime( TEXBENCH_C_cBeginUncompress );
	GLI_vUnCompressExistantTexture();
    TEXBENCH_fn_vSetTime( TEXBENCH_C_cEndUncompress );
    
    TEXBENCH_fn_vSetTime( TEXBENCH_C_cBeginCompression );
	TEX_lComputeCompression();
    TEXBENCH_fn_vSetTime( TEXBENCH_C_cEndcompression );
     
    TEXBENCH_fn_vSetTime( TEXBENCH_C_cBeginComputeLod );
	TEX_fn_vComputeLODForAllTextures();
	TEXBENCH_fn_vSetTime( TEXBENCH_C_cEndComputeLod );
    
    TEXBENCH_fn_vSetTime( TEXBENCH_C_cBeginDownload );
    GLI_vDownLoadTexture(FALSE);
    TEXBENCH_fn_vSetTime( TEXBENCH_C_cEndDownload );
	
    TEXBENCH_fn_vWriteSizeInFile();
    MATBENCH_fn_vWriteMaterialInfoInFile( "After download texture" );
}
 
 
/*
 ----------------------------------------------------------------------------------------
  Description   : Unload all textures
 ----------------------------------------------------------------------------------------
 */
void GLI_vUnloadTexture(void)
{
    GLI_DRV_vUnLoadTextures();
    //GLITEXT_fnv_Close();
}
 
/*
 ----------------------------------------------------------------------------------------
  Description   : Alloc loading bloc ( alarge bloc that will contain the bigest texture)
 ----------------------------------------------------------------------------------------
 */
void GLI_vAllocLoadingBloc()
{
    GLI_gs_lConvertBufferMipMappingSizeInBytes = GLI_lGetBigestSizeOfTexture();
    if (GLI_gs_lConvertBufferMipMappingSizeInBytes != 0)
    {
        MMG_fn_vAddMemoryInfo (MMG_C_lTypeGLI , MMG_C_lSubTypeMipMapping , NULL);
        GLI_gs_p_ConvertBufferMipMapping = TMP_M_p_Malloc(GLI_gs_lConvertBufferMipMappingSizeInBytes);
        GLI_DRV_lSendDataToDll("ConvertBufferMipMapping", GLI_gs_p_ConvertBufferMipMapping);
    }
}
 
/*
 ----------------------------------------------------------------------------------------
  Description   : Free loading bloc
 ----------------------------------------------------------------------------------------
 */
void GLI_vUnAllocLoadingBloc()
{
    if (GLI_gs_lConvertBufferMipMappingSizeInBytes != 0)
        TMP_M_Free(GLI_gs_p_ConvertBufferMipMapping);
	
	FIL_fn_vFreeGlobalHandleToFileInConcatFile();
}
 
/*
 ----------------------------------------------------------------------------------------
  Description   : Load all textures
 ----------------------------------------------------------------------------------------
 */
void GLI_vDownLoadTexture(BOOL bReloading)
{

    /*
     * initialize text data (for raster display) in retail mode this line does nothing
     */
    GLITEXT_fnv_Init();

    /*
     * Init
     */
    TEXBENCH_fn_vSetTime( TEXBENCH_C_cBeginDownload1 );
    GLI_vAllocLoadingBloc();
    FIL_fn_vInitGlobalHandleToFileInConcatFile();
    TEXBENCH_fn_vSetTime( TEXBENCH_C_cEndDownload1 );
 
    TEXBENCH_fn_vSetTime( TEXBENCH_C_cBeginDownload2 );
    GLI_g_ulNumberOfLoadedTexture = 0;
    GLI_DRV_vDownLoadTextures(0, GLI_lGetTextureMode(), bReloading );
    TEXBENCH_fn_vSetTime( TEXBENCH_C_cEndDownload2 );
  
    /*
     * end
     */
    TEXBENCH_fn_vSetTime( TEXBENCH_C_cBeginDownload3 );
    GLI_vUnAllocLoadingBloc();
    FIL_fn_vFreeGlobalHandleToFileInConcatFile();
    TEXBENCH_fn_vSetTime( TEXBENCH_C_cEndDownload3 );
}
 
/*
 ----------------------------------------------------------------------------------------
  Description   : Load all textures
 ----------------------------------------------------------------------------------------
 */
void GLI_vReloadTextures(void)
{
    GLI_vDownLoadTexture(TRUE);
}
 
 
#ifdef __cplusplus
}
#endif
 
