#define VerifAlphaBlend			if (effet==FX_TRANS)		{			\
									if (niveau<=0)		return;			\
									if (niveau>=256)		{			\
										effet=FX_OPAQUE;				\
									}									\
								}

enum effets {FX_OPAQUE,FX_ADD,FX_SOUS,FX_MASQUE,FX_TRANS,FX_XOR,FX_AND,FX_OR,FX_MILIEU};

/*
	FxSprite

	Dessine un sprite avec la possibilité d'appliquer les effets suivants:
	-FX_OPAQUE, FX_ADD, FX_SOUS, FX_MASQUE, FX_TRANS
*/

void FxSprite(int x0, int y0, int l, int h, register unsigned char *sprite, int effet=0, register int niveau=0)		{
	int x, y, a=-(l*2);
	register unsigned char *bits=Bits+LARG_BUF*3*(HAUT_BUF), *ptr, nv=256-niveau;

	sprite+=(h-1)*l*3;
	ClipSprite;
	VerifAlphaBlend;

	if (effet==FX_OPAQUE)		{
		for (y=y0;y<y0+h;y++)	{
			ptr=bits-LARG_BUF*3*y+3*x0;
			for (x=0;x<l;x++)	{
				if (*sprite==0xfe)		{
					sprite+=3;
					ptr+=3;
					continue;
				}
				*(ptr++)=*(sprite++);
				*(ptr++)=*(sprite++);
				*(ptr++)=*(sprite++);
			}
			sprite+=a;
		}
	}
	else if (effet==FX_ADD)		{
		for (y=y0;y<y0+h;y++)	{
			ptr=bits-LARG_BUF*3*y+3*x0;
			for (x=0;x<l;x++)	{
				if (*sprite==0xfe)		{
					sprite+=3;
					ptr+=3;
					continue;
				}
				if (*ptr>=255-*sprite)		*ptr=255;
				else						*ptr+=*sprite;
				ptr++, sprite++;
				if (*ptr>=255-*sprite)		*ptr=255;
				else						*ptr+=*sprite;
				ptr++, sprite++;
				if (*ptr>=255-*sprite)		*ptr=255;
				else						*ptr+=*sprite;
				ptr++, sprite++;
			}
			sprite+=a;
		}
	}
	else if (effet==FX_SOUS)		{
		for (y=y0;y<y0+h;y++)	{
			ptr=bits-LARG_BUF*3*y+3*x0;
			for (x=0;x<l;x++)	{
				if (*sprite==0xfe)		{
					sprite+=3;
					ptr+=3;
					continue;
				}
				if (*ptr<=*sprite)			*ptr=0;
				else						*ptr-=*sprite;
				ptr++, sprite++;
				if (*ptr<=*sprite)			*ptr=0;
				else						*ptr-=*sprite;
				ptr++, sprite++;
				if (*ptr<=*sprite)			*ptr=0;
				else						*ptr-=*sprite;
				ptr++, sprite++;
			}
			sprite+=a;
		}
	}
	else if (effet==FX_MASQUE)		{
		for (y=y0;y<y0+h;y++)	{
			ptr=bits-LARG_BUF*3*y+3*x0;
			for (x=0;x<l;x++)	{
				if (*sprite==0xfe)		{
					sprite+=3;
					ptr+=3;
					continue;
				}
				if (*ptr<=((*sprite)^0xff))	*ptr=0;
				else						*ptr-=(*sprite)^0xff;
				ptr++, sprite++;
				if (*ptr<=((*sprite)^0xff))	*ptr=0;
				else						*ptr-=(*sprite)^0xff;
				ptr++, sprite++;
				if (*ptr<=((*sprite)^0xff))	*ptr=0;
				else						*ptr-=(*sprite)^0xff;
				ptr++, sprite++;
			}
			sprite+=a;
		}
	}
	else if (effet==FX_TRANS)		{
		for (y=y0;y<y0+h;y++)	{
			ptr=bits-LARG_BUF*3*y+3*x0;
			for (x=0;x<l;x++)	{
				if (*sprite==0xfe)		{
					sprite+=3;
					ptr+=3;
					continue;
				}
				*(ptr++)=((*ptr)*nv+niveau*(*sprite++))>>8;
				*(ptr++)=((*ptr)*nv+niveau*(*sprite++))>>8;
				*(ptr++)=((*ptr)*nv+niveau*(*sprite++))>>8;
			}
			sprite+=a;
		}
	}
	else if (effet==FX_XOR)		{
		for (y=y0;y<y0+h;y++)	{
			ptr=bits-LARG_BUF*3*y+3*x0;
			for (x=0;x<l;x++)	{
				if (*sprite==0xfe)		{
					sprite+=3;
					ptr+=3;
					continue;
				}
				*(ptr++)^=*(sprite++);
				*(ptr++)^=*(sprite++);
				*(ptr++)^=*(sprite++);
			}
			sprite+=a;
		}
	}
	else if (effet==FX_MILIEU)		{
		register int i;
		for (y=y0;y<y0+h;y++)	{
			ptr=bits-LARG_BUF*3*y+3*x0;
			for (x=0;x<l;x++)	{
				if (*sprite==0xfe)		{
					sprite+=3;
					ptr+=3;
					continue;
				}
				i=(*ptr)+(((*sprite++)-128)<<1);
				if (i>255)					*ptr=255;
				else if (i<0)				*ptr=0;
				else						*ptr=i;
				ptr++;
				i=(*ptr)+(((*sprite++)-128)<<1);
				if (i>255)					*ptr=255;
				else if (i<0)				*ptr=0;
				else						*ptr=i;
				ptr++;
				i=(*ptr)+(((*sprite++)-128)<<1);
				if (i>255)					*ptr=255;
				else if (i<0)				*ptr=0;
				else						*ptr=i;
				ptr++;
			}
			sprite+=a;
		}
	}
}


/*
	FxCadre

	Dessine un cadre avec la possibilité d'appliquer les effets suivants:
	-FX_OPAQUE, FX_ADD, FX_SOUS, FX_MASQUE, FX_TRANS, FX_XOR, FX_AND, FX_OR
*/

void FxCadre(int x0, int y0, int l, int h, int couleur, int effet=0, register int niveau=0)	{
	register unsigned char *bits=Bits+LARG_BUF*3*(HAUT_BUF), *ptr;
	int x, y;
	unsigned char rouge=couleur&0x000000ff, vert=(couleur&0x0000ff00)>>8, bleu=(couleur&0x00ff0000)>>16;

	ClipRect;
	VerifAlphaBlend;

	if (effet==FX_OPAQUE)		{
		for (y=y0;y<y0+h;y++)	{
			ptr=bits-LARG_BUF*3*y+3*x0;
			for (x=0;x<l;x++)	{
				*(ptr++)=bleu;
				*(ptr++)=vert;
				*(ptr++)=rouge;
			}
		}
	}
	else if (effet==FX_ADD)		{
		for (y=y0;y<y0+h;y++)	{
			ptr=bits-LARG_BUF*3*y+3*x0;
			for (x=0;x<l;x++)	{
				if (*ptr>=255-bleu)			*ptr=255;
				else						*ptr+=bleu;
				ptr++;
				if (*ptr>=255-vert)			*ptr=255;
				else						*ptr+=vert;
				ptr++;
				if (*ptr>=255-rouge)		*ptr=255;
				else						*ptr+=rouge;
				ptr++;
			}
		}
	}
	else if (effet==FX_SOUS || effet==FX_MASQUE)		{
		if (effet==FX_MASQUE)		bleu^=0xff, vert^=0xff, rouge^=0xff;
		for (y=y0;y<y0+h;y++)	{
			ptr=bits-LARG_BUF*3*y+3*x0;
			for (x=0;x<l;x++)	{
				if (*ptr<=bleu)				*ptr=0;
				else						*ptr-=bleu;
				ptr++;
				if (*ptr<=vert)				*ptr=0;
				else						*ptr-=vert;
				ptr++;
				if (*ptr<=rouge)			*ptr=0;
				else						*ptr-=rouge;
				ptr++;
			}
		}
	}
	else if (effet==FX_TRANS)		{
		int nv=niveau-255, factb=bleu*niveau, factv=vert*niveau, factr=rouge*niveau;
		for (y=y0;y<y0+h;y++)	{
			ptr=bits-LARG_BUF*3*y+3*x0;
			for (x=0;x<l;x++)	{
				*ptr=(factb-nv*(*ptr))>>8;
				ptr++;
				*ptr=(factv-nv*(*ptr))>>8;
				ptr++;
				*ptr=(factr-nv*(*ptr))>>8;
				ptr++;
			}
		}
	}
	else if (effet==FX_XOR)		{
		for (y=y0;y<y0+h;y++)	{
			ptr=bits-LARG_BUF*3*y+3*x0;
			for (x=0;x<l;x++)	{
				*(ptr++)^=bleu;
				*(ptr++)^=vert;
				*(ptr++)^=rouge;
			}
		}
	}
	else if (effet==FX_AND)		{
		for (y=y0;y<y0+h;y++)	{
			ptr=bits-LARG_BUF*3*y+3*x0;
			for (x=0;x<l;x++)	{
				*(ptr++)&=bleu;
				*(ptr++)&=vert;
				*(ptr++)&=rouge;
			}
		}
	}
	else if (effet==FX_OR)		{
		for (y=y0;y<y0+h;y++)	{
			ptr=bits-LARG_BUF*3*y+3*x0;
			for (x=0;x<l;x++)	{
				*(ptr++)|=bleu;
				*(ptr++)|=vert;
				*(ptr++)|=rouge;
			}
		}
	}
}


/*
	FxLigne

	Dessine une ligne avec la possibilité d'appliquer les effets suivants:
	-FX_OPAQUE, FX_ADD, FX_SOUS, FX_MASQUE, FX_TRANS, FX_XOR, FX_AND, FX_OR
*/

void FxLigne (int x1, int y1, int x2, int y2, int couleur, int effet=0, register int niveau=0)		{
	int deltax,deltay;
	/*register */int x,y, xinc1,xinc2, yinc1,yinc2, den,num,numadd;
	int numpixels,curpixel;

	if (effet==FX_MASQUE)	{
		effet=FX_SOUS;
		couleur^=0xffffff;
	}
	VerifAlphaBlend;

	deltax = abs(x2 - x1);        // The difference between the x's
	deltay = abs(y2 - y1);        // The difference between the y's
	x = x1;                       // Start x off at the first pixel
	y = y1;                       // Start y off at the first pixel

	if (x2 >= x1)                 // The x-values are increasing
	{
	  xinc1 = 1;
	  xinc2 = 1;
	}
	else                          // The x-values are decreasing
	{
	  xinc1 = -1;
	  xinc2 = -1;
	}

	if (y2 >= y1)                 // The y-values are increasing
	{
	  yinc1 = 1;
	  yinc2 = 1;
	}
	else                          // The y-values are decreasing
	{
	  yinc1 = -1;
	  yinc2 = -1;
	}

	if (deltax >= deltay)         // There is at least one x-value for every y-value
	{
	  xinc1 = 0;                  // Don't change the x when numerator >= denominator
	  yinc2 = 0;                  // Don't change the y for every iteration
	  den = deltax;
	  num = deltax / 2;
	  numadd = deltay;
	  numpixels = deltax;         // There are more x-values than y-values
	}
	else                          // There is at least one y-value for every x-value
	{
	  xinc2 = 0;                  // Don't change the x for every iteration
	  yinc1 = 0;                  // Don't change the y when numerator >= denominator
	  den = deltay;
	  num = deltay / 2;
	  numadd = deltax;
	  numpixels = deltay;         // There are more y-values than x-values
	}

	if (effet==FX_OPAQUE)		{
		for (curpixel = 0; curpixel <= numpixels; curpixel++)
		{
		  DessPix(x,y,couleur);             // Draw the current pixel

		  num += numadd;              // Increase the numerator by the top of the fraction
		  if (num >= den)             // Check if numerator >= denominator
		  {
			num -= den;               // Calculate the new numerator value
			x += xinc1;               // Change the x as appropriate
			y += yinc1;               // Change the y as appropriate
		  }
		  x += xinc2;                 // Change the x as appropriate
		  y += yinc2;                 // Change the y as appropriate
		}
	}
	else if (effet==FX_ADD)		{
		for (curpixel = 0; curpixel <= numpixels; curpixel++)
		{
		  AddPix(x,y,couleur);

		  num += numadd;              // Increase the numerator by the top of the fraction
		  if (num >= den)             // Check if numerator >= denominator
		  {
			num -= den;               // Calculate the new numerator value
			x += xinc1;               // Change the x as appropriate
			y += yinc1;               // Change the y as appropriate
		  }
		  x += xinc2;                 // Change the x as appropriate
		  y += yinc2;                 // Change the y as appropriate
		}
	}
	else if (effet==FX_SOUS)		{
		for (curpixel = 0; curpixel <= numpixels; curpixel++)
		{
		  SousPix(x,y,couleur);

		  num += numadd;              // Increase the numerator by the top of the fraction
		  if (num >= den)             // Check if numerator >= denominator
		  {
			num -= den;               // Calculate the new numerator value
			x += xinc1;               // Change the x as appropriate
			y += yinc1;               // Change the y as appropriate
		  }
		  x += xinc2;                 // Change the x as appropriate
		  y += yinc2;                 // Change the y as appropriate
		}
	}
	else if (effet==FX_TRANS)		{
		for (curpixel = 0; curpixel <= numpixels; curpixel++)
		{
		  TransPix(x,y,couleur,niveau);

		  num += numadd;              // Increase the numerator by the top of the fraction
		  if (num >= den)             // Check if numerator >= denominator
		  {
			num -= den;               // Calculate the new numerator value
			x += xinc1;               // Change the x as appropriate
			y += yinc1;               // Change the y as appropriate
		  }
		  x += xinc2;                 // Change the x as appropriate
		  y += yinc2;                 // Change the y as appropriate
		}
	}
	else if (effet==FX_XOR)		{
		for (curpixel = 0; curpixel <= numpixels; curpixel++)
		{
		  XorPix(x,y,couleur);

		  num += numadd;              // Increase the numerator by the top of the fraction
		  if (num >= den)             // Check if numerator >= denominator
		  {
			num -= den;               // Calculate the new numerator value
			x += xinc1;               // Change the x as appropriate
			y += yinc1;               // Change the y as appropriate
		  }
		  x += xinc2;                 // Change the x as appropriate
		  y += yinc2;                 // Change the y as appropriate
		}
	}
	else if (effet==FX_AND)		{
		for (curpixel = 0; curpixel <= numpixels; curpixel++)
		{
		  AndPix(x,y,couleur);

		  num += numadd;              // Increase the numerator by the top of the fraction
		  if (num >= den)             // Check if numerator >= denominator
		  {
			num -= den;               // Calculate the new numerator value
			x += xinc1;               // Change the x as appropriate
			y += yinc1;               // Change the y as appropriate
		  }
		  x += xinc2;                 // Change the x as appropriate
		  y += yinc2;                 // Change the y as appropriate
		}
	}
	else if (effet==FX_OR)		{
		for (curpixel = 0; curpixel <= numpixels; curpixel++)
		{
		  OrPix(x,y,couleur);

		  num += numadd;              // Increase the numerator by the top of the fraction
		  if (num >= den)             // Check if numerator >= denominator
		  {
			num -= den;               // Calculate the new numerator value
			x += xinc1;               // Change the x as appropriate
			y += yinc1;               // Change the y as appropriate
		  }
		  x += xinc2;                 // Change the x as appropriate
		  y += yinc2;                 // Change the y as appropriate
		}
	}
}


/*
	FxRect

	Dessine un rectangle avec la possibilité d'appliquer les effets suivants:
	-FX_OPAQUE, FX_ADD, FX_SOUS, FX_MASQUE, FX_TRANS, FX_XOR
*/

void FxRect(int x0, int y0, int l, int h, int couleur, int effet=0, register int niveau=0)		{
	register unsigned char *bits=Bits+LARG_BUF*3*HAUT_BUF, *ptr;
	register int x, y;
	register unsigned char rouge=couleur&0x000000ff, vert=(couleur&0x0000ff00)>>8, bleu=(couleur&0x00ff0000)>>16;
	int yBase=y0+CLIP_Y0, xBase=x0+CLIP_X0, lBase=l, hBase=h;
	int nv=niveau-255, factb=bleu*niveau, factv=vert*niveau, factr=rouge*niveau;

	ClipRect;
	VerifAlphaBlend;

	if (effet==FX_MASQUE)	{
		effet=FX_SOUS;
		couleur^=0xffffff;
	}

	for (y=0;y<hBase;y+=hBase-1)		{
		if (yBase+y>=CLIP_Y0 && yBase+y<CLIP_Y1)		{
			ptr=bits-LARG_BUF*3*(yBase+y)+3*x0+3;
			if (effet==FX_OPAQUE)		{
				for (x=2;x<l;x++)	{
					*(ptr++)=bleu;
					*(ptr++)=vert;
					*(ptr++)=rouge;
				}
			}
			else if (effet==FX_ADD)		{
				for (x=2;x<l;x++)	{
					if (*ptr>=255-bleu)			*ptr=255;
					else						*ptr+=bleu;
					ptr++;
					if (*ptr>=255-vert)			*ptr=255;
					else						*ptr+=vert;
					ptr++;
					if (*ptr>=255-rouge)		*ptr=255;
					else						*ptr+=rouge;
					ptr++;
				}
			}
			else if (effet==FX_SOUS)		{
				for (x=2;x<l;x++)	{
					if (*ptr<=bleu)				*ptr=0;
					else						*ptr-=bleu;
					ptr++;
					if (*ptr<=vert)				*ptr=0;
					else						*ptr-=vert;
					ptr++;
					if (*ptr<=rouge)			*ptr=0;
					else						*ptr-=rouge;
					ptr++;
				}
			}
			else if (effet==FX_TRANS)		{
				for (x=2;x<l;x++)	{
					*ptr=(factb-nv*(*ptr))>>8;
					ptr++;
					*ptr=(factv-nv*(*ptr))>>8;
					ptr++;
					*ptr=(factr-nv*(*ptr))>>8;
					ptr++;
				}
			}
			else if (effet==FX_XOR)		{
				for (x=2;x<l;x++)	{
					*(ptr++)^=bleu;
					*(ptr++)^=vert;
					*(ptr++)^=rouge;
				}
			}
		}
		if (hBase<=1)	break;
	}
	for (x=0;x<lBase;x+=lBase-1)		{
		if (xBase+x>=CLIP_X0 && xBase+x<CLIP_X1)		{
			ptr=bits-LARG_BUF*3*y0+3*(xBase+x);
			if (effet==FX_OPAQUE)		{
				for (y=0;y<h;y++)	{
					*(ptr++)=bleu;
					*(ptr++)=vert;
					*(ptr++)=rouge;
					ptr-=LARG_BUF*3+3;
				}
			}
			else if (effet==FX_ADD)		{
				for (y=0;y<h;y++)	{
					if (*ptr>=255-bleu)			*ptr=255;
					else						*ptr+=bleu;
					ptr++;
					if (*ptr>=255-vert)			*ptr=255;
					else						*ptr+=vert;
					ptr++;
					if (*ptr>=255-rouge)		*ptr=255;
					else						*ptr+=rouge;
					ptr++;
					ptr-=LARG_BUF*3+3;
				}
			}
			else if (effet==FX_SOUS)		{
				for (y=0;y<h;y++)	{
					if (*ptr<=bleu)				*ptr=0;
					else						*ptr-=bleu;
					ptr++;
					if (*ptr<=vert)				*ptr=0;
					else						*ptr-=vert;
					ptr++;
					if (*ptr<=rouge)			*ptr=0;
					else						*ptr-=rouge;
					ptr++;
					ptr-=LARG_BUF*3+3;
				}
			}
			else if (effet==FX_TRANS)		{
				for (y=0;y<h;y++)	{
					*ptr=(factb-nv*(*ptr))>>8;
					ptr++;
					*ptr=(factv-nv*(*ptr))>>8;
					ptr++;
					*ptr=(factr-nv*(*ptr))>>8;
					ptr++;
					ptr-=LARG_BUF*3+3;
				}
			}
			else if (effet==FX_XOR)		{
				for (y=0;y<h;y++)	{
					*(ptr++)^=bleu;
					*(ptr++)^=vert;
					*(ptr++)^=rouge;
					ptr-=LARG_BUF*3+3;
				}
			}
		}
		if (lBase<=1)	break;
	}
}


void FxRedimensionne(register unsigned char *spr, int x0, int y0, int lb, int hb, int l, int h, int effet=0, register int niveau=0)		{
	int x, y, a=0;
	register unsigned char *bits=Bits+LARG_BUF*3*HAUT_BUF, *ptr, *spr2, *sprite, nv=256-niveau;
	int y_min, x_min, y_max, x_max;
	long scaleX, scaleY, dstX, dstY;
	int x1, y1;

//	ClipSprite;
	if (!spr || l<=0 || h<=0)		return;
	VerifAlphaBlend;

	x0+=CLIP_X0;
	y0+=CLIP_Y0;
	if (x0>=CLIP_X0)	x_min=x0;
	else				x_min=CLIP_X0;
	if (y0>=CLIP_Y0)	y_min=y0;
	else				y_min=CLIP_Y0;

	x1=x0+l, y1=y0+h;
	if (x1<CLIP_X1)		x_max=x1;
	else				x_max=CLIP_X1;
	if (y1<HAUT)		y_max=y1;
	else				y_max=CLIP_Y1;
	spr+=3*(hb-1)*lb;
	scaleX=(lb<<VIRGULE)/l;
	scaleY=(hb<<VIRGULE)/h;
	dstY=scaleY*(y_min-y0);

	if (effet==FX_OPAQUE)		{
		for (y=y_min;y<y_max;y++)	{
			ptr=bits-LARG_BUF*3*y+3*x_min;
			spr2=spr-lb*3*(dstY>>VIRGULE);
			dstX=scaleX*(x_min-x0);
			dstY+=scaleY;

			for (x=x_min;x<x_max;x++)	{
				sprite=spr2+3*(dstX>>VIRGULE);
				dstX+=scaleX;
				if (*sprite==0xfe)		{
					sprite+=3;
					ptr+=3;
					continue;
				}
				*ptr++=*sprite++;
				*ptr++=*sprite++;
				*ptr++=*sprite++;
			}
			sprite+=a;
		}
	}
	else if (effet==FX_ADD)		{
		for (y=y_min;y<y_max;y++)	{
			ptr=bits-LARG_BUF*3*y+3*x_min;
			spr2=spr-lb*3*(dstY>>VIRGULE);
			dstX=scaleX*(x_min-x0);
			dstY+=scaleY;

			for (x=x_min;x<x_max;x++)	{
				sprite=spr2+3*(dstX>>VIRGULE);
				dstX+=scaleX;
				if (*sprite==0xfe)		{
					sprite+=3;
					ptr+=3;
					continue;
				}
				if (*ptr>=255-*sprite)		*ptr=255;
				else						*ptr+=*sprite;
				ptr++, sprite++;
				if (*ptr>=255-*sprite)		*ptr=255;
				else						*ptr+=*sprite;
				ptr++, sprite++;
				if (*ptr>=255-*sprite)		*ptr=255;
				else						*ptr+=*sprite;
				ptr++, sprite++;
			}
			sprite+=a;
		}
	}
	else if (effet==FX_SOUS)		{
		for (y=y_min;y<y_max;y++)	{
			ptr=bits-LARG_BUF*3*y+3*x_min;
			spr2=spr-lb*3*(dstY>>VIRGULE);
			dstX=scaleX*(x_min-x0);
			dstY+=scaleY;

			for (x=x_min;x<x_max;x++)	{
				sprite=spr2+3*(dstX>>VIRGULE);
				dstX+=scaleX;
				if (*sprite==0xfe)		{
					sprite+=3;
					ptr+=3;
					continue;
				}
				if (*ptr<=*sprite)			*ptr=0;
				else						*ptr-=*sprite;
				ptr++, sprite++;
				if (*ptr<=*sprite)			*ptr=0;
				else						*ptr-=*sprite;
				ptr++, sprite++;
				if (*ptr<=*sprite)			*ptr=0;
				else						*ptr-=*sprite;
				ptr++, sprite++;
			}
			sprite+=a;
		}
	}
	else if (effet==FX_MASQUE)		{
		for (y=y_min;y<y_max;y++)	{
			ptr=bits-LARG_BUF*3*y+3*x_min;
			spr2=spr-lb*3*(dstY>>VIRGULE);
			dstX=scaleX*(x_min-x0);
			dstY+=scaleY;

			for (x=x_min;x<x_max;x++)	{
				sprite=spr2+3*(dstX>>VIRGULE);
				dstX+=scaleX;
				if (*sprite==0xfe)		{
					sprite+=3;
					ptr+=3;
					continue;
				}
				if (*ptr<=((*sprite)^0xff))	*ptr=0;
				else						*ptr-=(*sprite)^0xff;
				ptr++, sprite++;
				if (*ptr<=((*sprite)^0xff))	*ptr=0;
				else						*ptr-=(*sprite)^0xff;
				ptr++, sprite++;
				if (*ptr<=((*sprite)^0xff))	*ptr=0;
				else						*ptr-=(*sprite)^0xff;
				ptr++, sprite++;
			}
			sprite+=a;
		}
	}
	else if (effet==FX_TRANS)		{
		for (y=y_min;y<y_max;y++)	{
			ptr=bits-LARG_BUF*3*y+3*x_min;
			spr2=spr-lb*3*(dstY>>VIRGULE);
			dstX=scaleX*(x_min-x0);
			dstY+=scaleY;

			for (x=x_min;x<x_max;x++)	{
				sprite=spr2+3*(dstX>>VIRGULE);
				dstX+=scaleX;
				if (*sprite==0xfe)		{
					sprite+=3;
					ptr+=3;
					continue;
				}
				*(ptr++)=((*ptr)*nv+niveau*(*sprite++))>>8;
				*(ptr++)=((*ptr)*nv+niveau*(*sprite++))>>8;
				*(ptr++)=((*ptr)*nv+niveau*(*sprite++))>>8;
			}
			sprite+=a;
		}
	}
	else if (effet==FX_MILIEU)		{
		register int i;
		for (y=y_min;y<y_max;y++)	{
			ptr=bits-LARG_BUF*3*y+3*x_min;
			spr2=spr-lb*3*(dstY>>VIRGULE);
			dstX=scaleX*(x_min-x0);
			dstY+=scaleY;

			for (x=x_min;x<x_max;x++)	{
				sprite=spr2+3*(dstX>>VIRGULE);
				dstX+=scaleX;
				if (*sprite==0xfe)		{
					sprite+=3;
					ptr+=3;
					continue;
				}
				i=(*ptr)+(((*sprite++)-128)<<1);
				if (i>255)					*ptr=255;
				else if (i<0)				*ptr=0;
				else						*ptr=i;
				ptr++;
				i=(*ptr)+(((*sprite++)-128)<<1);
				if (i>255)					*ptr=255;
				else if (i<0)				*ptr=0;
				else						*ptr=i;
				ptr++;
				i=(*ptr)+(((*sprite++)-128)<<1);
				if (i>255)					*ptr=255;
				else if (i<0)				*ptr=0;
				else						*ptr=i;
				ptr++;
			}
			sprite+=a;
		}
	}
	else if (effet==FX_XOR)		{
		for (y=y_min;y<y_max;y++)	{
			ptr=bits-LARG_BUF*3*y+3*x_min;
			spr2=spr-lb*3*(dstY>>VIRGULE);
			dstX=scaleX*(x_min-x0);
			dstY+=scaleY;

			for (x=x_min;x<x_max;x++)	{
				sprite=spr2+3*(dstX>>VIRGULE);
				dstX+=scaleX;
				if (*sprite==0xfe)		{
					sprite+=3;
					ptr+=3;
					continue;
				}
				*ptr++^=*sprite++;
				*ptr++^=*sprite++;
				*ptr++^=*sprite++;
			}
			sprite+=a;
		}
	}

}

__inline void AddPixInvMasque(register int x,register int y,int c)		{
	register unsigned char *ptr, *spr;
	x+=CLIP_X0;
	y+=CLIP_Y0;
	if (x<0 || y<0 || x>=CLIP_X1 || y>=CLIP_Y1)
		return;
	ptr=Bits+LARG_BUF*3*(HAUT_BUF-y)+3*x;
	if ((c&0x0000ff)==0xfe)
		return;
	spr=((unsigned char *)(&c));
	if (*ptr>=255-*spr)			*ptr=255;
	else						*ptr+=*spr;
	ptr++, spr++;
	if (*ptr>=255-*spr)			*ptr=255;
	else						*ptr+=*spr;
	ptr++, spr++;
	if (*ptr>=255-*spr)			*ptr=255;
	else						*ptr+=*spr;
	ptr++, spr++;
}

__inline void SousPixInvMasque(register int x,register int y,int c)		{
	register unsigned char *ptr, *spr;
	x+=CLIP_X0;
	y+=CLIP_Y0;
	if (x<0 || y<0 || x>=CLIP_X1 || y>=CLIP_Y1)
		return;
	ptr=Bits+LARG_BUF*3*(HAUT_BUF-y)+3*x;
	if ((c&0x0000ff)==0xfe)
		return;
	spr=((unsigned char *)(&c));
	if (*ptr<=*spr)				*ptr=0;
	else						*ptr-=*spr;
	ptr++, spr++;
	if (*ptr<=*spr)				*ptr=0;
	else						*ptr-=*spr;
	ptr++, spr++;
	if (*ptr<=*spr)				*ptr=0;
	else						*ptr-=*spr;
	ptr++, spr++;
}

__inline void MasquePixInvMasque(register int x,register int y,int c)		{
	register unsigned char *ptr, *spr;
	x+=CLIP_X0;
	y+=CLIP_Y0;
	if (x<0 || y<0 || x>=CLIP_X1 || y>=CLIP_Y1)
		return;
	ptr=Bits+LARG_BUF*3*(HAUT_BUF-y)+3*x;
	if ((c&0x0000ff)==0xfe)
		return;
	spr=((unsigned char *)(&c));
	if (*ptr<=((*spr)^0xff))	*ptr=0;
	else						*ptr-=(*spr)^0xff;
	ptr++, spr++;
	if (*ptr<=((*spr)^0xff))	*ptr=0;
	else						*ptr-=(*spr)^0xff;
	ptr++, spr++;
	if (*ptr<=((*spr)^0xff))	*ptr=0;
	else						*ptr-=(*spr)^0xff;
	ptr++, spr++;
}

__inline void TransPixInvMasque(register int x,register int y,int c, register int niveau)		{
	register unsigned char *ptr, *spr, nv=255-niveau;
	x+=CLIP_X0;
	y+=CLIP_Y0;
	if (x<0 || y<0 || x>=CLIP_X1 || y>=CLIP_Y1)
		return;
	ptr=Bits+LARG_BUF*3*(HAUT_BUF-y)+3*x;
	if ((c&0x0000ff)==0xfe)
		return;
	spr=((unsigned char *)(&c));
	*(ptr++)=((*ptr)*nv+niveau*(*spr++))>>8;
	*(ptr++)=((*ptr)*nv+niveau*(*spr++))>>8;
	*(ptr++)=((*ptr)*nv+niveau*(*spr++))>>8;
}

__inline void XorPixInvMasque(register int x,register int y,int c)		{
	register unsigned char *ptr, *spr;
	x+=CLIP_X0;
	y+=CLIP_Y0;
	if (x<0 || y<0 || x>=CLIP_X1 || y>=CLIP_Y1)
		return;
	ptr=Bits+LARG_BUF*3*(HAUT_BUF-y)+3*x;
	if ((c&0x0000ff)==0xfe)
		return;
	spr=((unsigned char *)(&c));
	*(ptr++)^=*(spr++);
	*(ptr++)^=*(spr++);
	*(ptr++)^=*(spr++);
}


__inline void MilieuPixInvMasque(register int x,register int y,int c)		{
	register unsigned char *ptr, *spr;
	register int i;
	x+=CLIP_X0;
	y+=CLIP_Y0;
	if (x<0 || y<0 || x>=CLIP_X1 || y>=CLIP_Y1)
		return;
	ptr=Bits+LARG_BUF*3*(HAUT_BUF-y)+3*x;
	if ((c&0x0000ff)==0xfe)
		return;
	spr=((unsigned char *)(&c));
	i=(*ptr)+(((*spr++)-128)<<1);
	if (i>255)					*ptr=255;
	else if (i<0)				*ptr=0;
	else						*ptr=i;
	ptr++;
	i=(*ptr)+(((*spr++)-128)<<1);
	if (i>255)					*ptr=255;
	else if (i<0)				*ptr=0;
	else						*ptr=i;
	ptr++;
	i=(*ptr)+(((*spr++)-128)<<1);
	if (i>255)					*ptr=255;
	else if (i<0)				*ptr=0;
	else						*ptr=i;
	ptr++;
}


void FxRotozoom(register unsigned char *sprite, int x1, int y1, int l, int h, double facteur, double t, int effet=0, register int niveau=0)		{
	int x, y, centrex,centrey,dmax, min_x,max_x,min_y,max_y;
	long cosT, sinT;
	long xp, yp, x1p=(l<<VIRGULE)/2, y1p=(h<<VIRGULE)/2;
	register short xpentier, ypentier;

	if (!sprite)	return;
	VerifAlphaBlend;

    cosT = (long)((cos(t)*MULT)/facteur);
    sinT = (long)((sin(t)*MULT)/facteur);

	centrex=x1;
	centrey=y1;
	dmax=(int)((float)(max(l+h-2,0)/2)*(float)facteur);
	min_x=max(centrex-dmax,0);
	max_x=min(centrex+dmax,CLIP_X1-CLIP_X0-1);
	min_y=max(centrey-dmax,0);
	max_y=min(centrey+dmax,CLIP_Y1-CLIP_Y0-1);
	sprite+=3*(h-1)*l;

	if (effet==FX_OPAQUE)		{
		for (y=min_y;y<max_y;y++)		{
				xp = (min_x-x1) * cosT + (y-y1) * sinT + x1p + (1>>VIRGULE)/4;
				yp = (y-y1) * cosT - (min_x-x1) * sinT + y1p + (1>>VIRGULE)/4;

				for (x = min_x; x <= max_x; x++)
				{
					xpentier=(short)(xp>>VIRGULE), ypentier=(short)(yp>>VIRGULE);
					if (xpentier>=0 && xpentier<l && ypentier>=0 && ypentier<h)
						DessPixInvMasque(x,y,SpriteGetPix(sprite,(int)xpentier,(int)ypentier,l));
					xp += cosT;
					yp -= sinT;
				}
		}
	}
	else if (effet==FX_ADD)		{
		for (y=min_y;y<max_y;y++)		{
				xp = (min_x-x1) * cosT + (y-y1) * sinT + x1p + (1>>VIRGULE)/4;
				yp = (y-y1) * cosT - (min_x-x1) * sinT + y1p + (1>>VIRGULE)/4;

				for (x = min_x; x <= max_x; x++)
				{
					xpentier=(short)(xp>>VIRGULE), ypentier=(short)(yp>>VIRGULE);
					if (xpentier>=0 && xpentier<l && ypentier>=0 && ypentier<h)
						AddPixInvMasque(x,y,SpriteGetPix(sprite,(int)xpentier,(int)ypentier,l));
					xp += cosT;
					yp -= sinT;
				}
		}
	}
	else if (effet==FX_SOUS)		{
		for (y=min_y;y<max_y;y++)		{
				xp = (min_x-x1) * cosT + (y-y1) * sinT + x1p + (1>>VIRGULE)/4;
				yp = (y-y1) * cosT - (min_x-x1) * sinT + y1p + (1>>VIRGULE)/4;

				for (x = min_x; x <= max_x; x++)
				{
					xpentier=(short)(xp>>VIRGULE), ypentier=(short)(yp>>VIRGULE);
					if (xpentier>=0 && xpentier<l && ypentier>=0 && ypentier<h)
						SousPixInvMasque(x,y,SpriteGetPix(sprite,(int)xpentier,(int)ypentier,l));
					xp += cosT;
					yp -= sinT;
				}
		}
	}
	else if (effet==FX_TRANS)		{
		for (y=min_y;y<max_y;y++)		{
				xp = (min_x-x1) * cosT + (y-y1) * sinT + x1p + (1>>VIRGULE)/4;
				yp = (y-y1) * cosT - (min_x-x1) * sinT + y1p + (1>>VIRGULE)/4;

				for (x = min_x; x <= max_x; x++)
				{
					xpentier=(short)(xp>>VIRGULE), ypentier=(short)(yp>>VIRGULE);
					if (xpentier>=0 && xpentier<l && ypentier>=0 && ypentier<h)
						TransPixInvMasque(x,y,SpriteGetPix(sprite,(int)xpentier,(int)ypentier,l),niveau);
					xp += cosT;
					yp -= sinT;
				}
		}
	}
	else if (effet==FX_XOR)		{
		for (y=min_y;y<max_y;y++)		{
				xp = (min_x-x1) * cosT + (y-y1) * sinT + x1p + (1>>VIRGULE)/4;
				yp = (y-y1) * cosT - (min_x-x1) * sinT + y1p + (1>>VIRGULE)/4;

				for (x = min_x; x <= max_x; x++)
				{
					xpentier=(short)(xp>>VIRGULE), ypentier=(short)(yp>>VIRGULE);
					if (xpentier>=0 && xpentier<l && ypentier>=0 && ypentier<h)
						XorPixInvMasque(x,y,SpriteGetPix(sprite,(int)xpentier,(int)ypentier,l));
					xp += cosT;
					yp -= sinT;
				}
		}
	}
	else if (effet==FX_MILIEU)		{
		for (y=min_y;y<max_y;y++)		{
				xp = (min_x-x1) * cosT + (y-y1) * sinT + x1p + (1>>VIRGULE)/4;
				yp = (y-y1) * cosT - (min_x-x1) * sinT + y1p + (1>>VIRGULE)/4;

				for (x = min_x; x <= max_x; x++)
				{
					xpentier=(short)(xp>>VIRGULE), ypentier=(short)(yp>>VIRGULE);
					if (xpentier>=0 && xpentier<l && ypentier>=0 && ypentier<h)
						MilieuPixInvMasque(x,y,SpriteGetPix(sprite,(int)xpentier,(int)ypentier,l));
					xp += cosT;
					yp -= sinT;
				}
		}
	}
	else if (effet==FX_MASQUE)		{
		for (y=min_y;y<max_y;y++)		{
				xp = (min_x-x1) * cosT + (y-y1) * sinT + x1p + (1>>VIRGULE)/4;
				yp = (y-y1) * cosT - (min_x-x1) * sinT + y1p + (1>>VIRGULE)/4;

				for (x = min_x; x <= max_x; x++)
				{
					xpentier=(short)(xp>>VIRGULE), ypentier=(short)(yp>>VIRGULE);
					if (xpentier>=0 && xpentier<l && ypentier>=0 && ypentier<h)
						MasquePixInvMasque(x,y,SpriteGetPix(sprite,(int)xpentier,(int)ypentier,l));
					xp += cosT;
					yp -= sinT;
				}
		}
	}
}

