#include "standard.h"
#include "global.h"
#include "drawprimitive.h"
#include "scanlines.h"


#define PIXELOUT(x)	PIXELOUT555LOOKUP(x)


/*

#ifdef LOOKUP

#define PIXELOUT565(x)  {int t;\
						texel = *(Texture + ((u>>16))+((v>>16)<<8));\
						t = (redleft>>16)<<8;\
						tr = ((texel>>8))&0xf8;\
						t  += tr;\
						ro = *(RGBTable+t);\
						ro = (ro>>3)<<11;\
						tg = ((texel>>3))&0xfa;\
						t  = (greenleft>>16)<<8;\
						t  += tg;\
						go = *(RGBTable+t);\
						go = (go>>2)<<5;\
						tb = ((texel)<<3)&0xf8;\
						t  = (blueleft>>16)<<8;\
						t  += tb;\
						bo = *(RGBTable+t);\
						bo = (bo>>3);\
						u+=du;\
						v+=dv;\
						redleft+=dr;\
						greenleft+=dg;\
						blueleft+=db;\
						*(pDestination+x) = (unsigned short)(ro|go|bo);}

#else

#define PIXELOUT565(x) {texel = *(Texture + ((u>>16))+((v>>16)<<8));\
					   tr = ((texel>>8))&0xf8;\
					   tg = ((texel>>3))&0xf8;\
					   tb = ((texel)<<3)&0xf8;\
					   ro = (short)(tr*(redleft>>16));\
					   go = (short)(tg*(greenleft>>16))>>5;\
					   bo = (short)(tb*(blueleft>>16))>>11;\
					   ro &= 0xf800;\
					   go &= 0x07e0;\
					   bo &= 0x1f;\
					   v += dv;\
					   u += du;\
	 				   redleft += dr;\
					   greenleft += dg;\
					   blueleft += db;\
					   *(pDestination+x) = (unsigned short)(ro|go|bo);}\

#endif
*/

#define PIXELOUT555LOOKUP(x)  {int t;\
						unsigned short out;\
						texel = *(Texture + ((u>>16))+((v>>16)<<8));\
						if(texel!=0){\
						t = (redleft>>19);\
						tr = ((texel>>5)&0x3e0)+t;\
						out = short(*(RGBTable+tr)<<10);\
						t  = (greenleft>>19);\
						tg = ((texel)&0x3e0)+t;\
						out|= short(*(RGBTable+tg)<<5);\
						t  = (blueleft>>19);\
						tb = ((texel<<5)&0x3e0)+t;\
						out|= short(*(RGBTable+tb));\
						*(pDestination+x) = (unsigned short) out;}\
						u+=du;\
						v+=dv;\
						redleft+=dr;\
						greenleft+=dg;\
						blueleft+=db;}


#define PIXELOUT555MUL(x) {texel = *(Texture + ((u>>16))+((v>>16)<<8));\
					   if(texel != 0){\
					   tr = ((texel>>7))&0xf8;\
					   tg = ((texel>>2))&0xf8;\
					   tb = ((texel)<<3)&0xf8;\
					   ro = (short)(tr*(redleft>>16))>>1;\
					   go = (short)(tg*(greenleft>>16))>>6;\
					   bo = (short)(tb*(blueleft>>16))>>11;\
					   ro &= 0x7c00;\
					   go &= 0x03e0;\
					   bo &= 0x1f;\
					   *(pDestination+x) = (unsigned short)(ro|go|bo);}\
					   v += dv;\
					   u += du;\
	 				   redleft += dr;\
					   greenleft += dg;\
					   blueleft += db;}


/*
	Function : ScanLinesTGDecalAffine
	Useage	 : Textured Goruaud Decal Affine 
*/

void ScanLinesTGDecalAffine(GRADIENT* Gradients,EDGE* pLeft,EDGE* pRight,EDGE* StepLeft,EDGE* StepRight)
{
	int Width;
	unsigned short* pDestination;
	long u,v,du,dv;
	long yline;
	float oowidth;
	short subdivcnt;
	short texel;
	long redleft,greenleft,blueleft;
	short tr,tg,tb;
	long dr,dg,db;
	short ro,go,bo;
	double fconv;

	yline = long(Output)+YTable[pLeft->y];
	
	while(StepLeft->height--)
	{
		Width  = pRight->x;
		Width -= pLeft->x;

		if(Width > 0)
		{
			pDestination = (unsigned short*) yline + pLeft->x;
			
			u = pLeft->uozf;
			v = pLeft->vozf;
			
			redleft   = pLeft->rf;
			greenleft = pLeft->gf;
			blueleft  = pLeft->bf;

			oowidth = WidthTable[Width];

			du = (pRight->uozf - pLeft->uozf);
			du = FTOL(float(du)*oowidth);
			dv = (pRight->vozf - pLeft->vozf);
			dv = FTOL(float(dv)*oowidth);
			dr = (pRight->rf - pLeft->rf);			
			dr = FTOL(float(dr)*oowidth);
			dg = (pRight->gf - pLeft->gf);			
			dg = FTOL(float(dg)*oowidth);
			db = (pRight->bf - pLeft->bf);			
			db = FTOL(float(db)*oowidth);
			
			subdivcnt = Width>>4;
			Width = Width-(subdivcnt<<4);
			
			while(subdivcnt--)
			{
				PIXELOUT(0);
				PIXELOUT(1);
				PIXELOUT(2);
				PIXELOUT(3);
				PIXELOUT(4);
				PIXELOUT(5);
				PIXELOUT(6);
				PIXELOUT(7);
				PIXELOUT(8);
				PIXELOUT(9);
				PIXELOUT(10);
				PIXELOUT(11);
				PIXELOUT(12);
				PIXELOUT(13);
				PIXELOUT(14);
				PIXELOUT(15);

				pDestination += 16;
			}

			for(int n=0;n<Width;n++)
			{
				PIXELOUT(0);
				pDestination++;
			}
		}

		yline += bytepitch;

		StepLeft->uozf += StepLeft->uozstepf;
		StepLeft->vozf += StepLeft->vozstepf;
		StepLeft->x    += StepLeft->xstep;
		StepLeft->y++;
		
		StepLeft->rf   += StepLeft->rstepf;
		StepLeft->gf   += StepLeft->gstepf;
		StepLeft->bf   += StepLeft->bstepf;

		StepLeft->ErrorTerm += StepLeft->Numerator;

		if(StepLeft->ErrorTerm >= StepLeft->Denominator)
		{
			StepLeft->x++;
			StepLeft->uozf += StepLeft->uozxtraf;
			StepLeft->vozf += StepLeft->vozxtraf;
			StepLeft->ErrorTerm -= StepLeft->Denominator;
	
			StepLeft->rf += StepLeft->rxtraf;
			StepLeft->gf += StepLeft->gxtraf;
			StepLeft->bf += StepLeft->bxtraf;
		}

		StepRight->x    += StepRight->xstep;
		StepRight->uozf += StepRight->uozstepf;
		StepRight->vozf += StepRight->vozstepf;
		StepRight->y++;

		StepRight->rf   += StepRight->rstepf;
		StepRight->gf   += StepRight->gstepf;
		StepRight->bf   += StepRight->bstepf;

		StepRight->ErrorTerm += StepRight->Numerator;

		if(StepRight->ErrorTerm >= StepRight->Denominator)
		{
			StepRight->x++;
			StepRight->uozf += StepRight->uozxtraf;
			StepRight->vozf += StepRight->vozxtraf;
			StepRight->ErrorTerm -= StepRight->Denominator;

			StepRight->rf += StepRight->rxtraf;
			StepRight->gf += StepRight->gxtraf;
			StepRight->bf += StepRight->bxtraf;
		}
	}
}


// EOF : ScanLinesTGAffine




/*
	Function : ScanLinesTGDecal
	Useage	 : Textured Gouraud Decal Perspective Correct
*/

void ScanLinesTGDecal(GRADIENT* Gradients,EDGE* pLeft,EDGE* pRight,EDGE* StepLeft,EDGE* StepRight)
{
	int Width;
	long u,v;
	long du,dv,dr,dg,db;
	unsigned short* pDestination;
	int subdivcnt;
	int pixelsleft;
	float oozr,uozr,vozr;
	float ZLeft,ULeft,VLeft;
	float ZRight,URight,VRight;
	float oozdx,uozdx,vozdx;
	float one = 1.0f;
	long yline;
	long rdx,gdx,bdx;
	long redleft,greenleft,blueleft;
	long redright,greenright,blueright;
	short texel;
	short tr,tg,tb;
	double fconv;



	oozdx = Gradients->dozx * float(SUBDIVSPAN);
	rdx   = StepLeft->rxtraf*SUBDIVSPAN;
	uozdx = Gradients->duzx * float(SUBDIVSPAN);
	gdx   = StepLeft->gxtraf*SUBDIVSPAN;
	vozdx = Gradients->dvzx * float(SUBDIVSPAN);
	bdx   = StepLeft->bxtraf*SUBDIVSPAN;

	yline = long(Output)+YTable[pLeft->y];

	while(StepLeft->height--)
	{
		ZLeft = pLeft->ooz;

		_asm
		{
			// 1.0f/pLeft->ooz
			fld  [one]
			fdiv [ZLeft]
		}
			
		pDestination = (unsigned short*) yline + pLeft->x;
		Width = (pRight->x - pLeft->x);

		redleft   = pLeft->rf;
		greenleft = pLeft->gf;
		blueleft  = pLeft->bf;
		
		redright   = redleft+rdx;
		greenright = greenleft+gdx;
		blueright  = blueleft+bdx;

		_asm
		{
			// ZLeft = 1.0f/pLeft->ooz
			fstp [ZLeft]
		}

		oozr = pLeft->ooz+oozdx;
		uozr = pLeft->uoz+uozdx;
		vozr = pLeft->voz+vozdx;
		
		ULeft = pLeft->uoz * ZLeft;
		VLeft = pLeft->voz * ZLeft;

		if(Width > 0)
		{
			
			_asm
			{
				fld	 one
				fdiv [oozr]
			}

			subdivcnt  = Width>>SUBDIVSHIFT;				
			pixelsleft = Width-(subdivcnt<<SUBDIVSHIFT);

			_asm
			{
				fstp [ZRight]
			}
			
			while(subdivcnt-- > 0)
			{

				URight = uozr * ZRight;
				VRight = vozr * ZRight;
								
				u  = FTOLFIX(ULeft);
				v  = FTOLFIX(VLeft);
				
				du = FTOLFIX(URight - ULeft)>>SUBDIVSHIFT;
				dv = FTOLFIX(VRight - VLeft)>>SUBDIVSHIFT;
				
				dr = (redright - redleft)>>SUBDIVSHIFT; 
				dg = (greenright - greenleft)>>SUBDIVSHIFT; 
				db = (blueright - blueleft)>>SUBDIVSHIFT; 

				oozr += oozdx;
			
				_asm
				{
					// one/oozr;
					fld	 [one]
					fdiv [oozr]
				}

				PIXELOUT(0);
				PIXELOUT(1);
				PIXELOUT(2);
				PIXELOUT(3);
				PIXELOUT(4);
				PIXELOUT(5);
				PIXELOUT(6);
				PIXELOUT(7);
				PIXELOUT(8);
				PIXELOUT(9);
				PIXELOUT(10);
				PIXELOUT(11);
				PIXELOUT(12);
				PIXELOUT(13);
				PIXELOUT(14);
				PIXELOUT(15);
									
				pDestination += 16;
				
				_asm
				{
					// ZRight = one/oozr
					fstp	[ZRight]		
				}

				ULeft = URight;
				VLeft = VRight;
				
				redleft   = redright;
				greenleft = greenright;
				blueleft  = blueright;

				vozr += vozdx;
				uozr += uozdx;

				redright   += rdx;
				greenright += gdx;
				blueright  += bdx;

			}
			
			if(pixelsleft)
			{
				u  = FTOLFIX(ULeft);
				v  = FTOLFIX(VLeft);
			
				if(--pixelsleft)
				{
					ZRight = 1.0f/(pRight->ooz - Gradients->dozx);
	
					URight = ZRight * (pRight->uoz - Gradients->duzx);
					VRight = ZRight * (pRight->voz - Gradients->dvzx);
					
					float opixf;
					opixf = WidthTable[pixelsleft];

					du = FTOLFIX(URight - ULeft);
					dv = FTOLFIX(VRight - VLeft);

					dr = (pRight->rf - StepLeft->rxtraf) - redleft;
					dg = (pRight->gf - StepLeft->gxtraf) - greenleft;
					db = (pRight->bf - StepLeft->bxtraf) - blueleft;

					du = FTOL(float(du)*opixf);
					dv = FTOL(float(dv)*opixf);
	
					dr = FTOL(float(dr)*opixf);
					dg = FTOL(float(dg)*opixf);
					db = FTOL(float(db)*opixf);
				
				}

				for(int n=0;n<=(pixelsleft);n++)
				{	
					PIXELOUT(0);
					pDestination++;
				}
  
			}
		
		}

		yline += bytepitch;

		StepLeft->x += StepLeft->xstep;
		StepLeft->y++;
		StepLeft->uoz += StepLeft->uozstep;
		StepLeft->voz += StepLeft->vozstep;
		StepLeft->ooz += StepLeft->oozstep;

		StepLeft->rf   += StepLeft->rstepf;
		StepLeft->gf   += StepLeft->gstepf;
		StepLeft->bf   += StepLeft->bstepf;

		StepLeft->ErrorTerm += StepLeft->Numerator;
	
		if(StepLeft->ErrorTerm >= StepLeft->Denominator)
		{
			StepLeft->x++;
			StepLeft->ooz += StepLeft->oozxtra;
			StepLeft->uoz += StepLeft->uozxtra;
			StepLeft->voz += StepLeft->vozxtra;
			StepLeft->ErrorTerm -= StepLeft->Denominator;

			StepLeft->rf += StepLeft->rxtraf;
			StepLeft->gf += StepLeft->gxtraf;
			StepLeft->bf += StepLeft->bxtraf;
		}


		StepRight->x += StepRight->xstep;
		StepRight->y++;
		StepRight->uoz += StepRight->uozstep;
		StepRight->voz += StepRight->vozstep;
		StepRight->ooz += StepRight->oozstep;

		StepRight->rf   += StepRight->rstepf;
		StepRight->gf   += StepRight->gstepf;
		StepRight->bf   += StepRight->bstepf;

		StepRight->ErrorTerm += StepRight->Numerator;
	
		if(StepRight->ErrorTerm >= StepRight->Denominator)
		{
			StepRight->x++;
			StepRight->ooz += StepRight->oozxtra;
			StepRight->uoz += StepRight->uozxtra;
			StepRight->voz += StepRight->vozxtra;
			StepRight->ErrorTerm -= StepRight->Denominator;
			
			StepRight->rf += StepRight->rxtraf;
			StepRight->gf += StepRight->gxtraf;
			StepRight->bf += StepRight->bxtraf;
		}
	}
}

// EOF : ScanLinesTGDecal
