#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
//#include <windows.h>

#include "SDL.h"
#include "SDL_timer.h"

#include "Outils.h"
/*
    +---------------------------------------------------------------------------+
    |                                                                           |
    |  FONCTION : OpenScreen()                                                  |
    |                                                                           |
    +---------------------------------------------------------------------------+
    |                                                                           |
    |  DESCRIPTION : Initialise le mode video                                   |
    |                                                                           |
    |                                                                           |
    +---------------------------------------------------------------------------+
    |                                                                           |
    |  PARAMETRES : unsigned short Larg, unsigned short Haut, unsigned char Bpp,|
    |               FullScreen                                                  |
    |                                                                           |
    +---------------------------------------------------------------------------+
    |                                                                           |
    |  CODE DE RETOUR : Un pointeur sur la structure StructEcran                |
    |                                                                           |
    +---------------------------------------------------------------------------+
*/

StructEcran_t *OpenScreen( unsigned short p_us_Larg, unsigned short p_us_Haut, unsigned char p_uc_Bpp, short p_s_FullScreen )
{
  StructEcran_t *l_p_Ecran;
  
  l_p_Ecran = ( StructEcran_t *) malloc( sizeof( StructEcran_t ) );
  if( l_p_Ecran == NULL)
    {
      if( DEBUG )
        perror( "Erreur dans l'allocation de la structure Ecran\n" );
      SDL_Quit();
    }
  
  /* -- Initialisation de la structure Ecran -- */
  l_p_Ecran->Largeur = p_us_Larg; /* -- Init Largeur -- */
  l_p_Ecran->Hauteur = p_us_Haut; /* -- Init Hauteur -- */
  l_p_Ecran->Bpp = p_uc_Bpp;      /* -- Init le Nb de Bits par pixel -- */
  l_p_Ecran->DonneesImage = NULL; /* -- Init Le pointeur des donnees -- */
  
  l_p_Ecran->Coords.x = 0;
  l_p_Ecran->Coords.y = 0;
  l_p_Ecran->Coords.w = l_p_Ecran->Largeur;
  l_p_Ecran->Coords.h = l_p_Ecran->Hauteur;

  /* -- Initialisation de SDL -- */
  if ( SDL_Init( SDL_INIT_VIDEO | SDL_INIT_TIMER) < 0 )
    {
		if( DEBUG )
        fprintf( stderr, "Erreur d'initialisation SDL: %s\n", SDL_GetError() ); /* -- Affiche le CodeErreur de SDL -- */
      SDL_Quit(); /* -- Pour sortir proprement -- */
    }
  
  /* -- Initialise un mode vidéo idéal pour cette image -- */
/*  if( p_s_FullScreen == TRUE )
    l_p_Ecran->DonneesImage = SDL_SetVideoMode( p_us_Larg, p_us_Haut, p_uc_Bpp, SDL_ASYNCBLIT | SDL_NOFRAME | SDL_FULLSCREEN | SDL_INIT_TIMER ); 
  else
    l_p_Ecran->DonneesImage = SDL_SetVideoMode( p_us_Larg, p_us_Haut, p_uc_Bpp, SDL_DOUBLEBUF | SDL_ASYNCBLIT | SDL_HWSURFACE | SDL_INIT_TIMER ); 
*/
	  if( p_s_FullScreen == TRUE )
    l_p_Ecran->DonneesImage = SDL_SetVideoMode( p_us_Larg, p_us_Haut, p_uc_Bpp, SDL_ANYFORMAT| SDL_FULLSCREEN | SDL_SWSURFACE); 
  else
    //l_p_Ecran->DonneesImage = SDL_SetVideoMode( p_us_Larg, p_us_Haut, p_uc_Bpp,  SDL_DOUBLEBUF |SDL_HWSURFACE | SDL_ASYNCBLIT | SDL_INIT_TIMER ); 
l_p_Ecran->DonneesImage = SDL_SetVideoMode( p_us_Larg, p_us_Haut, p_uc_Bpp,  SDL_DOUBLEBUF |SDL_HWSURFACE ); 
  
   if( !l_p_Ecran->DonneesImage )
    {
      if( DEBUG )
        fprintf( stderr, "Impossible d'allouer une surface SDL : %s\n",  SDL_GetError() );
      SDL_Quit(); /* -- Pour sortir proprement -- */
    }

  SDL_ShowCursor( SDL_DISABLE ); /* -- Desactive le curseur de souris -- */
  
  return l_p_Ecran;
  
}

/*
    +---------------------------------------------------------------------------+
    |                                                                           |
    |  FONCTION : CloseScreen()                                                 |
    |                                                                           |
    +---------------------------------------------------------------------------+
    |                                                                           |
    |  DESCRIPTION : Ferme le mode video et libere la memoire                   |
    |                                                                           |
    |                                                                           |
    +---------------------------------------------------------------------------+
    |                                                                           |
    |  PARAMETRES : le buffer video alloue                                      |
    |                                                                           |
    |                                                                           |
    +---------------------------------------------------------------------------+
    |                                                                           |
    |  CODE DE RETOUR : Aucun                                                   |
    |                                                                           |
    +---------------------------------------------------------------------------+
*/
void CloseScreen( StructEcran_t *p_p_Ecran )
{
  SDL_FreeSurface( p_p_Ecran->DonneesImage );
  if( p_p_Ecran != NULL )
    free( p_p_Ecran );
  SDL_Quit(); /* -- Remet la config ecran comme elle l'etait lors de l'init. -- */
}

/*
    +---------------------------------------------------------------------------+
    |                                                                           |
    |  FONCTION : OpenAudio()                                                   |
    |                                                                           |
    +---------------------------------------------------------------------------+
    |                                                                           |
    |  DESCRIPTION : Initialise le canal audio                                  |
    |                                                                           |
    |                                                                           |
    +---------------------------------------------------------------------------+
    |                                                                           |
    |  PARAMETRES : Aucun                                                       |
    |                                                                           |
    |                                                                           |
    +---------------------------------------------------------------------------+
    |                                                                           |
    |  CODE DE RETOUR : Le pointeur sur la structure StructAudio_t              |
    |                                                                           |
    +---------------------------------------------------------------------------+
*/

StructAudio_t *OpenAudio()
{
  StructAudio_t *l_p_Audio;
  int l_i_CodeRetour = OK;
  
  l_p_Audio = ( StructAudio_t * ) malloc( sizeof( StructAudio_t ) );
  
  if( l_p_Audio == NULL )
    {
      if( DEBUG )
        perror( "Impossible d'allouer la structure StructAudio_t\n" );
//      GLOBAL_FlagOuvrirAudio = FALSE;
      return NULL;
    }
  /* -- Initialisation de la structure audio -- */
  l_p_Audio->Frequence = FREQUENCE;
  l_p_Audio->Cannaux = CANNAUX;
  l_p_Audio->BufferDonnees = BUFFER_DONNEES;
  l_p_Audio->FormatAudio = AUDIO_FORMAT;
  l_p_Audio->Boucle = TRUE;
  l_p_Audio->DonneesAudio = NULL;
  
  /* -- Initialise SDL en Audio -- */
  l_i_CodeRetour = SDL_Init( SDL_INIT_AUDIO );
  if ( l_i_CodeRetour < OK ) 
    {
      fprintf( stderr, "Ouverture impossible de la carte son\n%s\n", SDL_GetError() );
//      GLOBAL_FlagOuvrirAudio = FALSE;
      return NULL;
    }
  
  l_i_CodeRetour = Mix_OpenAudio( l_p_Audio->Frequence,
		    l_p_Audio->FormatAudio,
		    l_p_Audio->Cannaux,
		    l_p_Audio->BufferDonnees );
  if ( l_i_CodeRetour < OK )
    {
      fprintf( stderr, "Ouverture de la carte son impossible : %s\n", SDL_GetError() );
//      GLOBAL_FlagOuvrirAudio = FALSE;
      return NULL;
    } 
//  GLOBAL_FlagOuvrirAudio = OK;


  return l_p_Audio;
}


/*
    +---------------------------------------------------------------------------+
    |                                                                           |
    |  FONCTION : CloseAudio()                                                  |
    |                                                                           |
    +---------------------------------------------------------------------------+
    |                                                                           |
    |  DESCRIPTION : Ferme le canal audio                                       |
    |                                                                           |
    |                                                                           |
    +---------------------------------------------------------------------------+
    |                                                                           |
    |  PARAMETRES : Aucun                                                       |
    |                                                                           |
    |                                                                           |
    +---------------------------------------------------------------------------+
    |                                                                           |
    |  CODE DE RETOUR : Aucun                                                   |
    |                                                                           |
    +---------------------------------------------------------------------------+
*/

void CloseAudio( StructAudio_t * p_pt_Audio )
{
//  if( GLOBAL_FlagOuvrirAudio == TRUE )
    Mix_CloseAudio();

}

/*
    +---------------------------------------------------------------------------+
    |                                                                           |
    |  FONCTION : CloseZic()                                                    |
    |                                                                           |
    +---------------------------------------------------------------------------+
    |                                                                           |
    |  DESCRIPTION : libere la memoire allouee                                  |
    |                                                                           |
    |                                                                           |
    +---------------------------------------------------------------------------+
    |                                                                           |
    |  PARAMETRES : La structure Audio                                          |
    |                                                                           |
    |                                                                           |
    +---------------------------------------------------------------------------+
    |                                                                           |
    |  CODE DE RETOUR : Aucun                                                   |
    |                                                                           |
    +---------------------------------------------------------------------------+
*/

void CloseZic( StructAudio_t *p_p_Audio )
{
   if( p_p_Audio != NULL )
    {
      free( p_p_Audio );
    }
}

/*
    +---------------------------------------------------------------------------+
    |                                                                           |
    |  FONCTION : LoadImage()                                                   |
    |                                                                           |
    +---------------------------------------------------------------------------+
    |                                                                           |
    |  DESCRIPTION : Charge l'image en mémoire la convertie dans la reso        |
    |                utilisée                                                   |
    |                                                                           |
    |                                                                           |
    +---------------------------------------------------------------------------+
    |                                                                           |
    |  PARAMETRES : char *p_pc_ImageSource, int  p_i_FlagAlpha,                 |
    |               unsigned char p_uc_Rouge, unsigned char p_uc_Vert,          |
    |               unsigned char p_uc_Bleu                                     |
    |                                                                           |
    +---------------------------------------------------------------------------+
    |                                                                           |
    |  CODE DE RETOUR : StructImage_t * si OK NULL si non                       |
    |                                                                           |
    +---------------------------------------------------------------------------+
*/

StructImage_t *O_LoadImage( char *p_pc_ImageSource, BOOL p_b_FlagAlpha, unsigned char p_uc_Rouge, unsigned char p_uc_Vert, unsigned char p_uc_Bleu )
{
  char l_c_PathImage[500 +1 ];
  unsigned long l_ul_CouleurPixel = 0;

  SDL_Surface *l_p_Image = NULL, *l_p_ImageTmp = NULL;
  StructImage_t *l_pt_Image = NULL;
  SDL_Rect l_sdl_Coords;

  memset( l_c_PathImage, 0, 500 +1 );
  sprintf( l_c_PathImage, "%s\\%s", PATH_IMAGES, p_pc_ImageSource );

  l_pt_Image = ( StructImage_t * ) malloc( sizeof( StructImage_t ) );
  if( l_pt_Image == NULL )
    {
      if( DEBUG )
        fprintf( stderr, "Impossible d'allouer de la memoire pour la structure 'StructImage_t' \n" );
      SDL_Quit(); /* -- Remet la config ecran comme elle l'etait lors de l'init. -- */
      exit(0);;
    }

  /* -- Charge l'image -- */
  if( ( l_p_Image = IMG_Load( l_c_PathImage ) ) == NULL ) /* -- ATTENTION cette ligne de code peut préter a confusion ;) -- */
  {
    if( DEBUG )
      fprintf( stderr, "Impossible de charger l'image %s: %s\n", l_c_PathImage, SDL_GetError() );
    SDL_Quit(); /* -- Remet la config ecran comme elle l'etait lors de l'init. -- */
    exit(0);
  }
  l_sdl_Coords.x = 0;
  l_sdl_Coords.y = 0;
  l_sdl_Coords.w = l_p_Image->w;
  l_sdl_Coords.h = l_p_Image->h;

  /* -- Convertion de l'image dans le meme format que celui de l'écran -- */
  if( ( l_p_ImageTmp = SDL_DisplayFormat( l_p_Image ) ) == NULL ) /* -- ATTENTION cette ligne de code peut préter a confusion ;) -- */
    {
      if( DEBUG )
        fprintf( stderr, "Impossible de convertir l'ancien l'ancien buffer Image : %s\n", SDL_GetError() );
      SDL_Quit(); /* -- Remet la config ecran comme elle l'etait lors de l'init. -- */
      exit(0);
    }
  SDL_FreeSurface( l_p_Image );

  l_pt_Image->DonneesImage = SDL_CreateRGBSurface( SDL_HWSURFACE, l_p_ImageTmp->w, l_p_ImageTmp->h, l_p_ImageTmp->format->BitsPerPixel, 0, 0, 0, 0 );
  /* -- Test l'apha channel -- */
  if( p_b_FlagAlpha == TRUE )
    {
      l_ul_CouleurPixel = SDL_MapRGB( l_pt_Image->DonneesImage->format, p_uc_Rouge, p_uc_Vert, p_uc_Bleu );
      SDL_SetColorKey( l_pt_Image->DonneesImage, SDL_SRCCOLORKEY, l_ul_CouleurPixel ); /* -- Fonction permetant la copie avec transparence -- */
    }
  SDL_BlitSurface( l_p_ImageTmp, &l_sdl_Coords, l_pt_Image->DonneesImage, &l_sdl_Coords );

  SDL_FreeSurface( l_p_ImageTmp );

  l_pt_Image->Largeur = l_pt_Image->DonneesImage->w;
  l_pt_Image->Hauteur = l_pt_Image->DonneesImage->h;
  l_pt_Image->Bpp = l_pt_Image->DonneesImage->format->BytesPerPixel;

  l_pt_Image->Coords.x = 0;
  l_pt_Image->Coords.y = 0;
  l_pt_Image->Coords.w = l_pt_Image->Largeur;
  l_pt_Image->Coords.h = l_pt_Image->Hauteur;

//  GLOBAL_NbAllocationImages++;
  return l_pt_Image;
}

/*
    +---------------------------------------------------------------------------+
    |                                                                           |
    |  FONCTION : LoadZic()                                                     |
    |                                                                           |
    +---------------------------------------------------------------------------+
    |                                                                           |
    |  DESCRIPTION : Charge le fichier de zic                                   |
    |                                                                           |
    |                                                                           |
    +---------------------------------------------------------------------------+
    |                                                                           |
    |  PARAMETRES : StructAudio_t *, char *NomZic                               |
    |                                                                           |
    |                                                                           |
    +---------------------------------------------------------------------------+
    |                                                                           |
    |  CODE DE RETOUR : OK si OK et NOK si non OK                               |
    |                                                                           |
    +---------------------------------------------------------------------------+
*/

StructAudio_t *LoadZic( StructAudio_t *p_pt_Audio, char * p_pc_NomZic )
{
  char l_sz_PathZic[ 500 +1 ];
  StructAudio_t *l_pt_Zic = NULL;

  if( ( p_pt_Audio == NULL ) )
    return NULL;

  l_pt_Zic = ( StructAudio_t * ) malloc( sizeof( StructAudio_t ) );
  if( l_pt_Zic == NULL )
    return NULL;

  memset( l_sz_PathZic, 0, 500 +1 );
  l_pt_Zic->Frequence = p_pt_Audio->Frequence;
  l_pt_Zic->Cannaux = p_pt_Audio->Cannaux;
  l_pt_Zic->BufferDonnees = p_pt_Audio->BufferDonnees;
  l_pt_Zic->FormatAudio = p_pt_Audio->FormatAudio;
  l_pt_Zic->Boucle = 0; /* -- -1 = loop et 0 = pas de loop -- */
  l_pt_Zic->DonneesAudio = NULL;

  sprintf( l_sz_PathZic, "%s\\%s", PATH_ZICS, p_pc_NomZic );
  l_pt_Zic->DonneesAudio = Mix_LoadMUS( l_sz_PathZic );

  if( l_pt_Zic->DonneesAudio == NULL )
    {
      if( DEBUG )
      {
        fprintf( stderr, "Impossible de charger <%s>\n", l_sz_PathZic );
      }
      
      SDL_Quit(); /* -- Remet la config ecran comme elle l'etait lors de l'init. -- */
      exit(0);
    }
  
//  GLOBAL_NbAllocationZics++;

  return l_pt_Zic;
}

/*
    +---------------------------------------------------------------------------+
    |                                                                           |
    |  FONCTION : PlayAudio()                                                   |
    |                                                                           |
    +---------------------------------------------------------------------------+
    |                                                                           |
    |  DESCRIPTION : Lance la zic en tache de fond                              |
    |                                                                           |
    |                                                                           |
    +---------------------------------------------------------------------------+
    |                                                                           |
    |  PARAMETRES :  StructAudio_t *                                            |
    |                                                                           |
    |                                                                           |
    +---------------------------------------------------------------------------+
    |                                                                           |
    |  CODE DE RETOUR : Aucun                                                   |
    |                                                                           |
    +---------------------------------------------------------------------------+
*/

void PlayAudio( StructAudio_t *p_pt_Zic )
{
  if( p_pt_Zic != NULL )
    Mix_PlayMusic( p_pt_Zic->DonneesAudio, p_pt_Zic->Boucle); /* -- Joue la zic en tache de fond -- */
	
}


/*
    +---------------------------------------------------------------------------+
    |                                                                           |
    |  FONCTION : CloseImage()                                                  |
    |                                                                           |
    +---------------------------------------------------------------------------+
    |                                                                           |
    |  DESCRIPTION : Libere la memoire allouee pour les images                  |
    |                                                                           |
    |                                                                           |
    +---------------------------------------------------------------------------+
    |                                                                           |
    |  PARAMETRES :  StructImage_t *                                            |
    |                                                                           |
    |                                                                           |
    +---------------------------------------------------------------------------+
    |                                                                           |
    |  CODE DE RETOUR : Aucun                                                   |
    |                                                                           |
    +---------------------------------------------------------------------------+
*/
void CloseImage( StructImage_t *p_pt_Image )
{
  SDL_FreeSurface( p_pt_Image->DonneesImage );
//  GLOBAL_NbAllocationImages--;
}


/*
    +---------------------------------------------------------------------------+
    |                                                                           |
    |  FONCTION : PutPixelRVB                                                   |
    |                                                                           |
    +---------------------------------------------------------------------------+
    |                                                                           |
    |  DESCRIPTION : Pose un pixel a l'endroit renseigné dans les arguments     |
    |                                                                           |
    |                                                                           |
    +---------------------------------------------------------------------------+
    |                                                                           |
    |  PARAMETRES :  StructImage_t *, int PosX, int PosY, char R, char V, char B|
    |                                                                           |
    |                                                                           |
    +---------------------------------------------------------------------------+
    |                                                                           |
    |  CODE DE RETOUR : Aucun                                                   |
    |                                                                           |
    +---------------------------------------------------------------------------+
*/

void PutPixelRVB( StructImage_t *p_pt_Buffer, unsigned short l_us_PositionX, unsigned short l_us_PositionY, unsigned char p_uc_Rouge, unsigned char p_uc_Vert, unsigned char p_uc_Bleu )
{
  unsigned long l_ul_CouleurPixel = 0;
  unsigned char *l_uc_Pixel = NULL;
  int l_i_Bpp = 0;
  
  l_ul_CouleurPixel = SDL_MapRGB( p_pt_Buffer->DonneesImage->format, p_uc_Rouge, p_uc_Vert, p_uc_Bleu );
  SDL_SetColorKey( p_pt_Buffer->DonneesImage, SDL_SRCCOLORKEY, l_ul_CouleurPixel ); /* -- Fonction permetant la copie avec transparance -- */
  l_i_Bpp = p_pt_Buffer->DonneesImage->format->BytesPerPixel;
  l_uc_Pixel = ( unsigned char * )  p_pt_Buffer->DonneesImage->pixels + l_us_PositionY * p_pt_Buffer->DonneesImage->pitch + l_us_PositionX * l_i_Bpp;  
  if( SDL_MUSTLOCK( p_pt_Buffer->DonneesImage ) )
    { 
      if( SDL_LockSurface( p_pt_Buffer->DonneesImage ) < OK )
        fprintf( stderr, "Impossible de locker l'ecran\n" );
      return ;
    } 
  switch( l_i_Bpp ) /* -- le Nombre de BPP -- */
  {
  case 1: /* -- 8 Bits -- */
      *l_uc_Pixel = (char)l_ul_CouleurPixel;
      break;
  case 2: /* -- 16 Bits -- */
      *( unsigned short * ) l_uc_Pixel = (char)l_ul_CouleurPixel;
      break;
  case 3:
      fprintf( stderr, "Pas de PutPixel en 24 Bits car c'est trop lent \n" );
      break;
  case 4: /* -- 32 Bits -- */
      *( unsigned long * ) l_uc_Pixel = (char)l_ul_CouleurPixel;
      break;
  default:
    fprintf( stderr, "Couleurs non gérées pas PutPixelRVB()\n" );
    break;
  } /* -- Fin du switch( sizeof( p_pt_Buffer->DonneesImage->format->BytesPerPixel ) ) -- */

  if( SDL_MUSTLOCK( p_pt_Buffer->DonneesImage ) )
    {
      SDL_UnlockSurface( p_pt_Buffer->DonneesImage );
      fprintf( stderr, "Impossible de délocker l'ecran\n" );
      return ;
    }
}


/*
    +---------------------------------------------------------------------------+
    |                                                                           |
    |  FONCTION : PutPixel (16 Bits)                                            |
    |                                                                           |
    +---------------------------------------------------------------------------+
    |                                                                           |
    |  DESCRIPTION : Pose un pixel a l'endroit renseigné dans les arguments     |
    |                                                                           |
    |                                                                           |
    +---------------------------------------------------------------------------+
    |                                                                           |
    |  PARAMETRES :  StructImage_t *, int PosX, int PosY, unsigned long Couleur |
    |                                                                           |
    |                                                                           |
    +---------------------------------------------------------------------------+
    |                                                                           |
    |  CODE DE RETOUR : Aucun                                                   |
    |                                                                           |
    +---------------------------------------------------------------------------+
*/

void O_PutPixel( StructImage_t *p_pt_Buffer, unsigned short p_us_PositionX, unsigned short p_us_PositionY, unsigned long p_ul_CouleurPixel )
{
   Uint16 *buffer;

   buffer = (Uint16 *) p_pt_Buffer->DonneesImage->pixels;

  if( SDL_MUSTLOCK( p_pt_Buffer->DonneesImage ) )
    { 
      if( SDL_LockSurface( p_pt_Buffer->DonneesImage ) < OK )
        fprintf( stderr, "Impossible de locker l'ecran\n" );
      return ;
    } 
  if( ( p_us_PositionX <= p_pt_Buffer->Largeur ) && /* -- Gère le clipping -- */
      ( p_us_PositionY <= p_pt_Buffer->Hauteur ) )
    *( buffer + ( p_pt_Buffer->Largeur * p_us_PositionY + p_us_PositionX ) ) = (char)p_ul_CouleurPixel;

  if( SDL_MUSTLOCK( p_pt_Buffer->DonneesImage ) )
    SDL_UnlockSurface( p_pt_Buffer->DonneesImage );

}					           

/*
    +---------------------------------------------------------------------------+
    |                                                                           |
    |  FONCTION : GetPixel (16 Bits)                                            |
    |                                                                           |
    +---------------------------------------------------------------------------+
    |                                                                           |
    |  DESCRIPTION : Recupère la couleur d'un pixel a l'endroit renseigné       |
    |                dans les arguments                                         |
    |                                                                           |
    |                                                                           |
    +---------------------------------------------------------------------------+
    |                                                                           |
    |  PARAMETRES :  StructImage_t *, int PosX, int PosY, char R, char V, char B|
    |                                                                           |
    |                                                                           |
    +---------------------------------------------------------------------------+
    |                                                                           |
    |  CODE DE RETOUR : Aucun                                                   |
    |                                                                           |
    +---------------------------------------------------------------------------+
*/

unsigned short O_GetPixel( StructImage_t *p_pt_Buffer, unsigned short l_us_PositionX, unsigned short l_us_PositionY  )
{
   Uint16 *buffer = (Uint16 *) p_pt_Buffer->DonneesImage->pixels;
   unsigned short l_us_Couleur = 0;

   if( SDL_MUSTLOCK( p_pt_Buffer->DonneesImage ) )
     { 
       if( SDL_LockSurface( p_pt_Buffer->DonneesImage ) < OK )
         fprintf( stderr, "Impossible de locker l'ecran\n" );
       return 0;
     } 
  if( ( l_us_PositionX <= p_pt_Buffer->Largeur ) && /* -- Gère le clipping -- */
      ( l_us_PositionY <= p_pt_Buffer->Hauteur ) )   
    l_us_Couleur = * ( buffer + ( p_pt_Buffer->Largeur*l_us_PositionY+l_us_PositionX ) );

  if( SDL_MUSTLOCK( p_pt_Buffer->DonneesImage ) )
    SDL_UnlockSurface( p_pt_Buffer->DonneesImage );

   return l_us_Couleur;
} 				           
				         

/*
    +---------------------------------------------------------------------------+
    |                                                                           |
    |  FONCTION : PutSprite()                                                   |
    |                                                                           |
    +---------------------------------------------------------------------------+
    |                                                                           |
    |  DESCRIPTION : Copie un sprite dans un buffer destination                 |
    |                                                                           |
    |                                                                           |
    +---------------------------------------------------------------------------+
    |                                                                           |
    |  PARAMETRES :  StructImage_t *Src, StructImage_t *Dest, int PosX,int PosY |
    |                                                                           |
    |                                                                           |
    +---------------------------------------------------------------------------+
    |                                                                           |
    |  CODE DE RETOUR : Aucun                                                   |
    |                                                                           |
    +---------------------------------------------------------------------------+
*/

void O_PutSprite( StructImage_t *p_pt_Sprite, StructImage_t *p_pt_BufferDestination,  short p_us_PosX,  short p_us_PosY )
{

   if( SDL_MUSTLOCK( p_pt_Sprite->DonneesImage ) )
     { 
       if( SDL_LockSurface( p_pt_Sprite->DonneesImage ) < OK )
         fprintf( stderr, "Impossible de locker l'ecran\n" );
       return ;
     } 
   p_pt_BufferDestination->Coords.x = p_us_PosX;
   p_pt_BufferDestination->Coords.y = p_us_PosY;
   p_pt_BufferDestination->Coords.w = p_pt_Sprite->Largeur;
   p_pt_BufferDestination->Coords.h = p_pt_Sprite->Hauteur;

        
   SDL_BlitSurface( p_pt_Sprite->DonneesImage, &p_pt_Sprite->Coords , p_pt_BufferDestination->DonneesImage, &p_pt_BufferDestination->Coords ); /* - Cette sublimissime fonction gère le clipping ; donc du taff en moins :) -- */
  
  if( SDL_MUSTLOCK( p_pt_Sprite->DonneesImage ) )
    SDL_UnlockSurface( p_pt_Sprite->DonneesImage );

}


/*
    +---------------------------------------------------------------------------+
    |                                                                           |
    |  FONCTION : WaitKey()                                                     |
    |                                                                           |
    +---------------------------------------------------------------------------+
    |                                                                           |
    |  DESCRIPTION : Test et renvoie l'etat de la touche passe en parametre     |
    |                ne gere que la touche "escape"                             |
    |                                                                           |
    +---------------------------------------------------------------------------+
    |                                                                           |
    |  PARAMETRES :  unsigned short p_us_Key                                    |
    |                                                                           |
    |                                                                           |
    +---------------------------------------------------------------------------+
    |                                                                           |
    |  CODE DE RETOUR : TRUE si la touche est pressee FALSE sinon               |
    |                                                                           |
    +---------------------------------------------------------------------------+
*/

BOOL WaitKey()
{
  unsigned char *l_p_KeyState = SDL_GetKeyState( NULL );
  SDL_Event l_sdl_KeyEvent;
  
  l_p_KeyState = SDL_GetKeyState( NULL );
  SDL_PollEvent( &l_sdl_KeyEvent );
  if( l_p_KeyState[ SDLK_ESCAPE ] )
    {
      SDL_Quit();
      exit(0);
    }
  if( l_sdl_KeyEvent.type == SDL_KEYDOWN )
    return TRUE;
  return FALSE;
}

/*
    +---------------------------------------------------------------------------+
    |                                                                           |
    |  FONCTION : WaitDelayAndWaitKey()                                         |
    |                                                                           |
    +---------------------------------------------------------------------------+
    |                                                                           |
    |  DESCRIPTION : Attends X millisecondes en Testant l'appui de la touche    |
    |                ne gere que la touche "escape"                             |
    |                                                                           |
    +---------------------------------------------------------------------------+
    |                                                                           |
    |  PARAMETRES :  unsigned short p_us_Delay (pas plus de 60 secondes)        |
    |                                                                           |
    |                                                                           |
    +---------------------------------------------------------------------------+
    |                                                                           |
    |  CODE DE RETOUR : Aucun                                                   |
    |                                                                           |
    +---------------------------------------------------------------------------+
*/

void WaitDelayAndWaitKey( unsigned short p_us_Delay )
{
  unsigned long l_ul_TimeBegin = 0, l_ul_TimeEnd = 0;
  
  l_ul_TimeBegin = SDL_GetTicks();

  while( 1 )
    {
      l_ul_TimeEnd = SDL_GetTicks();
      if( l_ul_TimeEnd - l_ul_TimeBegin >= p_us_Delay )
        break;
      if( WaitKey() == TRUE )
        break;
      
    }
}

/*
    +---------------------------------------------------------------------------+
    |                                                                           |
    |  FONCTION : Affiche()                                                     |
    |                                                                           |
    +---------------------------------------------------------------------------+
    |                                                                           |
    |  DESCRIPTION : Affiche le buffer passe en parametre. Il est possible de   |
    |                limiter le nombre de frames/seconde grace a la varible     |
    |                globale suivante : GLOBAL_FixeFPS ( 60 fps seble correcte) |
    |                                                                           |
    +---------------------------------------------------------------------------+
    |                                                                           |
    |  PARAMETRES :  StructImage_t *p_pt_Image                                  |
    |                                                                           |
    |                                                                           |
    +---------------------------------------------------------------------------+
    |                                                                           |
    |  CODE DE RETOUR : Aucun                                                   |
    |                                                                           |
    +---------------------------------------------------------------------------+
*/

void Affiche( StructImage_t *p_pt_Image )
{
  unsigned long l_ul_TimeBegin = 0, l_ul_TimeEnd = 0;
  //const SDL_VideoInfo *l_pt_VideoInfos = SDL_GetVideoInfo();
  
  l_ul_TimeBegin = SDL_GetTicks();
  
  l_ul_TimeEnd = SDL_GetTicks();

  while( ( l_ul_TimeEnd - l_ul_TimeBegin <= 1000 / 120  ) && ( WaitKey() == FALSE ) )
    l_ul_TimeEnd = SDL_GetTicks();

  //    if( l_pt_VideoInfos->blit_hw == SDL_HWSURFACE )
  SDL_Flip( p_pt_Image->DonneesImage );
        /*    else
        SDL_UpdateRect( p_pt_Image->DonneesImage, p_pt_Image->Coords.x, p_pt_Image->Coords.y, p_pt_Image->Coords.w, p_pt_Image->Coords.h );
        */
}


/*
    +---------------------------------------------------------------------------+
    |                                                                           |
    |  FONCTION : InitVariableGlobales()                                        |
    |                                                                           |
    +---------------------------------------------------------------------------+
    |                                                                           |
    |  DESCRIPTION : Initialise toutes les variables globales                   |
    |                                                                           |
    +---------------------------------------------------------------------------+
    |                                                                           |
    |  PARAMETRES :  Aucun                                                      |
    |                                                                           |
    +---------------------------------------------------------------------------+
    |                                                                           |
    |  CODE DE RETOUR : Aucun                                                   |
    |                                                                           |
    +---------------------------------------------------------------------------+
*/

void InitVariablesGlobales()
{
//  GLOBAL_NbAllocationImages = 0;
//  GLOBAL_NbAllocationZics = 0;
//  GLOBAL_FixeFPS = 60; /* -- 60 FPS est un bon compromis, au dessus c'est pour les CPU a 8 Ghz ;) -- */
  g_ul_CompteurSound = 0;

}

/*
    +---------------------------------------------------------------------------+
    |                                                                           |
    |  FONCTION : MappeLigneH()                                                 |
    |                                                                           |
    +---------------------------------------------------------------------------+
    |                                                                           |
    |  DESCRIPTION : Mappe une ligne quelconque en une ligne horizontale        |
    |                                                                           |
    +---------------------------------------------------------------------------+
    |                                                                           |
    |  PARAMETRES :  Aucun                                                      |
    |                                                                           |
    +---------------------------------------------------------------------------+
    |                                                                           |
    |  CODE DE RETOUR : Aucun                                                   |
    |                                                                           |
    +---------------------------------------------------------------------------+
*/
void MappeLigneH( long x1, long y1, long x2,long y2, StructImage_t *p_pt_Source, long x3, long y3, long L, StructImage_t *p_pt_Destination )
{
  long l;
  long  v1,w1,x,y;
  unsigned short  coul;
  unsigned long offp;
  unsigned short *l_pus_Source = NULL, *l_pus_Destination = NULL;

  l_pus_Source = ( unsigned short * ) p_pt_Source->DonneesImage->pixels;
  l_pus_Destination = ( unsigned short * ) p_pt_Destination->DonneesImage->pixels;
  
  if( SDL_MUSTLOCK( p_pt_Source->DonneesImage ) )
    { 
      if( SDL_LockSurface( p_pt_Source->DonneesImage ) < OK )
        fprintf( stderr, "Impossible de locker l'ecran\n" );
      return;
    } 
  
  if( SDL_MUSTLOCK( p_pt_Destination->DonneesImage ) )
    { 
      if( SDL_LockSurface( p_pt_Destination->DonneesImage ) < OK )
        fprintf( stderr, "Impossible de locker l'ecran\n" );
      return;
    } 
  
  
  if( L==0 )
    return;
  
  if( y3 < 0 || y3 > p_pt_Source->Hauteur - 1 ) /* -- Clipping haut et bas -- */
    return;
  
  
  v1 = ( ( x2 - x1 ) << 16 ) / L;
  w1 = ( ( y2 - y1 ) << 16 ) / L;
  
  y  = y1 << 16;
  x =  x1 << 16;
  
  if( x3 + L > p_pt_Source->Largeur- 1 ) /* -- Clipping droit -- */
    L = L - ( x3 + L - p_pt_Source->Largeur - 1 );
  
  offp = p_pt_Destination->Largeur * y3 + x3;
  
  for( l = 0 ; l < L ; l++ )
    {
      y += w1;
      x += v1;
      if( x3 >= 0 )  /* -- Clipping gauche -- */
        {
          coul = l_pus_Source[ ( y >> 16 ) * p_pt_Source->Largeur + ( x >> 16 ) ];
          if( coul != 0 )
            l_pus_Destination[ offp ] = coul;
        }
      x3++;
      offp++;
    }
  
  if( SDL_MUSTLOCK( p_pt_Source->DonneesImage ) )
    SDL_UnlockSurface( p_pt_Source->DonneesImage );

  if( SDL_MUSTLOCK( p_pt_Destination->DonneesImage ) )
    SDL_UnlockSurface( p_pt_Destination->DonneesImage );
}

/*
    +---------------------------------------------------------------------------+
    |                                                                           |
    |  FONCTION : SoundSync()                                                   |
    |                                                                           |
    +---------------------------------------------------------------------------+
    |                                                                           |
    |  DESCRIPTION : Incrémente une variable globale premétant la syncro sound  |
    |                                                                           |
    +---------------------------------------------------------------------------+
    |                                                                           |
    |  PARAMETRES :  unsigned long p_ul_Intervale, void *p_void_Param           |
    |                                                                           |
    +---------------------------------------------------------------------------+
    |                                                                           |
    |  CODE DE RETOUR : p_ul_Intervale                                          |
    |                                                                           |
    +---------------------------------------------------------------------------+
*/
unsigned long SoundSync( unsigned long p_ul_Intervale, void *p_void_Param )
{
	g_ul_CompteurSound++;
	return p_ul_Intervale;
}