
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///																																      ///
///		FICHIER :	ZooSoft.cpp																								         ///
///																																    ///
///		NATURE	:	Defintion of the class to visualise the 3D in soft configuration											   ///
///																																  ///
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////






#include	"..\Basic\ZooSoft.h"



#include	"..\Basic\ZooScene.h"
#include	"..\SCOL\winuser.h"
#include	"..\SCOL\ext.h"
#include	"..\SCOL\objstr.h"
#include	"..\SCOL\macro.h"
#include    "../scol/colors.h"







int		tabtrame[4]={0x0000,0x8000,0xc000,0x4000};


CELL	*Zbuffer;

//$LB short	palette16[TABCOL*64*16];
unsigned char palette24[TABCOL*64*16];



int fillRenderBuffer(mmachine m, RenderBuffer *buffer, int surf)
{
	PtrObjVoid		OB;
	PtrObjBitmap	B;

	if(surf==NIL)			return -1;

	OB	= (PtrObjVoid)	 MMstart(m,MTOP(surf));
	B	= (PtrObjBitmap) MMstart(m,MTOP(OB->Buffer));

	if(B->bits==NULL)		return -1;

	buffer->Image	= (OBJBITMAP_BUFFER) B->bits;
	buffer->BPL		= B->BPL;
	buffer->width	= B->TailleW;
	buffer->height	= B->TailleH;

	return 0;
}
















///////////////////////////////////////////////////////////////////////////////////////
///		Render_FLAT																	///
///////////////////////////////////////////////////////////////////////////////////////
//$LB
void Render_FLAT(OBJBITMAP_BUFFER buffer, CELL *Zbuf, int tailleX, ZFaceSOFT *face, int xa, int xb, float za, float zb, int yscan)
{
	int		i, li, x, dx, dxa, l, dl, dy;
	float	fl, fdl;
	unsigned char bufb, bufg, bufr;
	

	CELL	Zcur;
	float	Zpente;



	if(xa!=xb)		Zpente = (zb-za)/(xb-xa); 
	else			Zpente = 0;

	Zcur.f	 = za;
	Zbuf += xa+tailleX;

	//$LB
	buffer	+= xa*3;

	//$LB
	if (face->color24 > 0xFFFFFF)		return;

	//$LB
	_COLOR_I_TO_BGR (face->color24, &bufb, &bufg, &bufr);

	// Remplissage flat
	if(!face->table24)
	{
		for(i=xa; i<xb; i++)
		{
			if(Zcur.d > (*Zbuf).d)
			{
				//$LB
				*(buffer+0)	=  bufb; *(buffer+1)	=  bufg; *(buffer+2)	=  bufr; 
				(*Zbuf).f	= Zcur.f;
			}

			Zcur.f += Zpente;
			Zbuf++;
			//$LB
			buffer+=3;
		}
		return;
	}

	x   = (int) face->xg; 
	dx  = (int) face->xd; 
	dx -= x; 
	dxa = xa - x;

	if (dx==0) return;


	fdl = (face->lgtd - face->lgtg) * 65536 / dx;
	fl  = face->lgtg*65536+fdl*dxa;
	l   = (int) fl;
	dl  = (int) fdl;
	dy  = (yscan&1) << 1;


	for (i=xa; i<xb; i++)
	{
		if (Zcur.d > (*Zbuf).d)
		{
			li			= ( ((l + tabtrame[dy+(i&1)])>>16)&63 ) << LOGTABCOL;
			//$LB
			*(buffer+0) = (face->table24)[li+bufr]; *(buffer+1) = (face->table24)[TABCOL_OFFSET1+li+bufg]; *(buffer+2) = (face->table24)[TABCOL_OFFSET2+li+bufb]; 
			(*Zbuf).f	= Zcur.f;
		}

		Zcur.f += Zpente;
		Zbuf++;
		//$LB
		buffer+=3;
		l += dl;
	}

}



///////////////////////////////////////////////////////////////////////////////////////
///		Render_TRANSP_NOTEX															///
///////////////////////////////////////////////////////////////////////////////////////

void Render_TRANSP_NOTEX(OBJBITMAP_BUFFER buffer, CELL *Zbuf, int tailleX, ZFaceSOFT *face, int xa, int xb, float za, float zb, int yscan)
{
	int		i;
	//$LB
	unsigned char *pal1;
	unsigned char *pal2;


	CELL	Zcur;												
	float	Zpente;							
	if(xa!=xb)		Zpente = (zb-za)/(xb-xa); 
	else			Zpente = 0;

	Zcur.f	 = za;												
	Zbuf += xa+tailleX;

	//$LB
	buffer	+= xa*3;

	pal1 = face->table24 + TABCOL_OFFSET1;
	pal2 = face->table24 + TABCOL_OFFSET2;

	for(i=xa; i<xb; i++)
	{
		if(Zcur.d > (*Zbuf).d)
		{
			//$LB
			*(buffer+0) = (face->table24) [*(buffer+0)]; *(buffer+1) = pal1[*(buffer+1)]; *(buffer+2) = pal2[*(buffer+2)]; 
		}

		Zcur.f += Zpente;
		Zbuf++;
		//$LB
		buffer+=3;
	}
}




#define MICRO_SCAN		16
#define LOG_MICRO_SCAN	4



///////////////////////////////////////////////////////////////////////////////////////
///		Macro INIT_TRACE															///
///////////////////////////////////////////////////////////////////////////////////////
#define INIT_TRACE												\
	int		i, x, dx, dxa, dy;									\
	/* $LB                                                    */\
	unsigned char *pal0, *pal1, *pal2;							\
	float	fu, fv, fnu, fnv, fdnu, fdnv, fz, fdz, k, fl, fdl;  \
	/* $LB                                                    */\
	OBJBITMAP_BUFFER bitm;										\
	int		w, h, du, dv, u, v, u1, v1, li, l, dl;		        \
	/*$LB                                                     */\
	int	   z, zrr, zgg, zbb, z0, offset;						\
																\
	CELL	Zcur;												\
	float	Zpente;												\
	if (xa==xb) return;											\
	Zcur.f   = za;	 Zpente = (zb-za)/(xb-xa);					\
	Zbuf += xa + tailleX;										\
	/*$LB                                                     */\
	buffer  += xa*3;											\
																\
	x   = face->xg;												\
	dx  = face->xd;												\
	dx -= x;													\
	dxa = xa-x;													\
																\
	if (dx==0) return;											\
	i	 = face->lgtg;											\
	/* $LB                                                    */\
	pal0 = (unsigned char*)face->table24;   					\
	pal1 = pal0 + TABCOL_OFFSET1;								\
	pal2 = pal0 + TABCOL_OFFSET2;								\
																\
	fdnu = (face->ud - face->ug)*256;							\
	fnu	 = dx*face->ug*256 + dxa*fdnu;							\
	fdnv = (face->vd - face->vg)*256;							\
	fnv	 = dx*face->vg*256 + dxa*fdnv;							\
	fdz	 = face->zd - face->zg;									\
	fz	 = dx*face->zg + dxa*fdz;								\
	fdl	 = (face->lgtd - face->lgtg)*65536/dx;					\
	fl	 = face->lgtg*65536 + fdl*dxa;							\
    dl	 = fdl;													\
	l	 = fl;													\
	dy	 = (yscan&1)<<1;										\
																\
	fu	 = fnu/fz;												\
	fv	 = fnv/fz;												\
	u	 = fu;													\
	v	 = fv;													\
	bitm = (OBJBITMAP_BUFFER) face->bitmap24;					\
	z0	 = face->color24;											


///////////////////////////////////////////////////////////////////////////////////////
///		Macro EXACT_TRACE															///
///////////////////////////////////////////////////////////////////////////////////////
#define EXACT_TRACE(blit)										\
	while(xb-xa >= MICRO_SCAN)									\
	{															\
	    fnu += MICRO_SCAN*fdnu;                                 \
		fnv += MICRO_SCAN*fdnv;                                 \
		fz	+= MICRO_SCAN*fdz;                                  \
		k	= 1/fz;												\
		fu	= fnu*k;											\
		fv	= fnv*k;											\
																\
		u1	= fu;												\
		v1	= fv;												\
		du	= (u1-u)>>LOG_MICRO_SCAN;							\
		dv	= (v1-v)>>LOG_MICRO_SCAN;							\
		for(i=0; i<MICRO_SCAN; i++)                             \
		{														\
            li = (((l+tabtrame[dy+(i&1)])>>16)&63)<<LOGTABCOL;	\
			blit                                                \
			u += du;											\
			v += dv;											\
			l += dl;											\
		}														\
		xa	+= MICRO_SCAN;                                      \
	}															\
	dx = xb-xa;													\
	if (dx==0) return;											\
																\
	fnu += dx*fdnu;												\
	fnv += dx*fdnv;												\
	fz	+= dx*fdz;												\
	k	= 1/fz;													\
	fu	= fnu*k;												\
	fv	= fnv*k;												\
																\
	u1 = fu;													\
	v1 = fv;													\
	du = (u1-u)/dx;												\
	dv = (v1-v)/dx;												\
	for(i=0; i<dx; i++)											\
	{															\
		li = (((l+tabtrame[dy+(i&1)])>>16)&63)<<LOGTABCOL;		\
		blit													\
		u += du;                                                \
		v += dv;                                                \
		l += dl;												\
	}



///////////////////////////////////////////////////////////////////////////////////////
///		Macro DISPATCH_TRACE														///
///////////////////////////////////////////////////////////////////////////////////////
#define DISPATCH_TRACE(copy_func)																	                                                                                \
	w = face->width;																					                                                                    	    \
	h = face->height;                                                                                                                                                               \
    /* $LB           */                                                                                                                                                             \
	if ((w==1024)&&(h==1024)) { EXACT_TRACE( offset =((v<<4)&0xffc00)+((u>>6)&1023); offset *= 3; zrr=bitm[offset+0]; zgg=bitm[offset+1]; zbb=bitm[offset+2]; copy_func ) return; }	\
	if ((w==1024)&&(h==512))  { EXACT_TRACE( offset =((v<<3)&0x7fc00)+((u>>6)&1023); offset *= 3; zrr=bitm[offset+0]; zgg=bitm[offset+1]; zbb=bitm[offset+2]; copy_func ) return; }	\
	if ((w==512)&&(h==1024))  { EXACT_TRACE( offset =((v<<3)&0x7fe00)+((u>>7)&511);  offset *= 3; zrr=bitm[offset+0]; zgg=bitm[offset+1]; zbb=bitm[offset+2]; copy_func ) return; }	\
	if ((w==512)&&(h==512))   { EXACT_TRACE( offset =((v<<2)&0x3fe00)+((u>>7)&511);  offset *= 3; zrr=bitm[offset+0]; zgg=bitm[offset+1]; zbb=bitm[offset+2]; copy_func ) return; }	\
	if ((w==512)&&(h==256))   { EXACT_TRACE( offset =((v<<1)&0x1fe00)+((u>>7)&511);  offset *= 3; zrr=bitm[offset+0]; zgg=bitm[offset+1]; zbb=bitm[offset+2]; copy_func ) return; }	\
	if ((w==256)&&(h==512))   { EXACT_TRACE( offset =((v<<1)&0x1ff00)+((u>>8)&255);  offset *= 3; zrr=bitm[offset+0]; zgg=bitm[offset+1]; zbb=bitm[offset+2]; copy_func ) return; }	\
	if ((w==256)&&(h==256))   { EXACT_TRACE( offset =(v&0xff00)+((u>>8)&255);        offset *= 3; zrr=bitm[offset+0]; zgg=bitm[offset+1]; zbb=bitm[offset+2]; copy_func ) return; }	\
	if ((w==256)&&(h==128))   { EXACT_TRACE( offset =((v&0xfe00)>>1)+((u>>8)&255);   offset *= 3; zrr=bitm[offset+0]; zgg=bitm[offset+1]; zbb=bitm[offset+2]; copy_func ) return; }	\
	if ((w==128)&&(h==256))   { EXACT_TRACE( offset =((v&0xff00)>>1)+((u>>9)&127);   offset *= 3; zrr=bitm[offset+0]; zgg=bitm[offset+1]; zbb=bitm[offset+2]; copy_func ) return; }	\
	if ((w==128)&&(h==128))   { EXACT_TRACE( offset =((v&0xfe00)>>2)+((u>>9)&127);   offset *= 3; zrr=bitm[offset+0]; zgg=bitm[offset+1]; zbb=bitm[offset+2]; copy_func ) return; }	\
	if ((w==128)&&(h==64))    { EXACT_TRACE( offset =((v&0xfc00)>>3)+((u>>9)&127);   offset *= 3; zrr=bitm[offset+0]; zgg=bitm[offset+1]; zbb=bitm[offset+2]; copy_func ) return; }	\
	if ((w==64) &&(h==128))   { EXACT_TRACE( offset =((v&0xfe00)>>3)+((u>>10)&63);   offset *= 3; zrr=bitm[offset+0]; zgg=bitm[offset+1]; zbb=bitm[offset+2]; copy_func ) return; }	\
	if ((w==64) &&(h==64))    { EXACT_TRACE( offset =((v&0xfc00)>>4)+((u>>10)&63);   offset *= 3; zrr=bitm[offset+0]; zgg=bitm[offset+1]; zbb=bitm[offset+2]; copy_func ) return; }	\
	if ((w==64) &&(h==32))    { EXACT_TRACE( offset =((v&0xf800)>>5)+((u>>10)&63);   offset *= 3; zrr=bitm[offset+0]; zgg=bitm[offset+1]; zbb=bitm[offset+2]; copy_func ) return; }	\
	if ((w==32) &&(h==64))    { EXACT_TRACE( offset =((v&0xfc00)>>5)+((u>>11)&31);   offset *= 3; zrr=bitm[offset+0]; zgg=bitm[offset+1]; zbb=bitm[offset+2]; copy_func ) return; }	\
	if ((w==32) &&(h==32))    { EXACT_TRACE( offset =((v&0xf800)>>6)+((u>>11)&31);   offset *= 3; zrr=bitm[offset+0]; zgg=bitm[offset+1]; zbb=bitm[offset+2]; copy_func ) return; }	\



//$LB
#define Z_COMPUTE                                        \
  z = ((zbb<<16)&0xFF0000)|((zgg<<8)&0xFF00)|(zrr&0xFF);


///////////////////////////////////////////////////////////////////////////////////////
///		M3DtraceExactL																///
///////////////////////////////////////////////////////////////////////////////////////

void Render_TEX(OBJBITMAP_BUFFER buffer, CELL *Zbuf, int tailleX, ZFaceSOFT *face, int xa, int xb, float za, float zb, int yscan)
{

	INIT_TRACE
	DISPATCH_TRACE
	(
		if (Zcur.d > (*Zbuf).d)
		{
			//$LB
			*(buffer+0) = pal0[li+zbb]; *(buffer+1) = pal1[li+zgg]; *(buffer+2) = pal2[li+zrr]; 
			(*Zbuf).f	= Zcur.f;
		}

		Zcur.f += Zpente;
		Zbuf++;
		//$LB
		buffer+=3;
	)
	
	
}



///////////////////////////////////////////////////////////////////////////////////////
///		Render_TRANSP_TEX_1															///
///////////////////////////////////////////////////////////////////////////////////////
void Render_TRANSP_TEX_1(OBJBITMAP_BUFFER buffer, CELL *Zbuf, int tailleX, ZFaceSOFT *face, int xa, int xb, float za, float zb, int yscan)
{

	INIT_TRACE
	DISPATCH_TRACE
	(	
		Z_COMPUTE

		if (z!=z0) 
		{
			if (Zcur.d > (*Zbuf).d)
			{
				//$LB
				*(buffer+0) = pal0[li+zbb]; *(buffer+1) = pal1[li+zgg]; *(buffer+2) = pal2[li+zrr]; 
				(*Zbuf).f	= Zcur.f;
			}

			Zcur.f += Zpente;
			Zbuf++;
			//$LB
			buffer+=3;
		}
		else
		{
			Zcur.f += Zpente;
			Zbuf++;
			//$LB
			buffer+=3;
		}
	)
}



///////////////////////////////////////////////////////////////////////////////////////
///		M3DtraceExactTranspLA														///
///////////////////////////////////////////////////////////////////////////////////////
void Render_TRANSP_TEX_2(OBJBITMAP_BUFFER buffer, CELL *Zbuf, int tailleX, ZFaceSOFT *face, int xa, int xb, float za, float zb, int yscan)
{
 


	INIT_TRACE
	DISPATCH_TRACE 
	(	
		Z_COMPUTE

		if (z!=z0) 
		{
			if (Zcur.d > (*Zbuf).d)
			{
				*(buffer+0) = (*(buffer+0) + pal0[li+zbb])>>1;
				*(buffer+1) = (*(buffer+1) + pal1[li+zgg])>>1;
				*(buffer+2) = (*(buffer+2) + pal2[li+zrr])>>1;
			}

			Zcur.f += Zpente;
			Zbuf++;
			//$LB
			buffer+=3;
		}
		else
		{
			Zcur.f += Zpente;
			Zbuf++;
			//$LB
			buffer+=3;
		}
	)
}



///////////////////////////////////////////////////////////////////////////////////////
///		M3Dline																		///
///////////////////////////////////////////////////////////////////////////////////////


int M3Dline(RenderBuffer *rendbuf, float x1, float y1, float x2, float y2, int col)
{
	float	xclip, yclip;
	int		ax, ay, bx, by, dx, dy, kx, ky, k, i;
	//$LB
	OBJBITMAP_BUFFER	buffer;
	unsigned char colb, colg, colr;


	//$LB
	x1 += rendbuf->width>>1; 
	x2 += rendbuf->width>>1;

	//$LB
	_COLOR_I_TO_BGR (col, &colb, &colg, &colr);

	// Clipping 2D //
	xclip = (float) (1);
	if (x1 < xclip)
	{
		if (x2 < xclip) return 0;
		y1 += (xclip-x1) * (y2-y1)/(x2-x1);
		x1  = xclip;
	}
	if (x2 < xclip)
	{
		if (x1 < xclip) return 0;
		y2 += (xclip-x2) * (y1-y2)/(x1-x2);
		x2  = xclip;
	}

	xclip = (float) (rendbuf->width - 1);
	if (x1 > xclip)
	{
		if (x2 > xclip) return 0;
		y1 += (xclip-x1) * (y2-y1)/(x2-x1);
		x1  = xclip;
	}
	if (x2 > xclip)
	{
		if (x1 > xclip) return 0;
		y2 += (xclip-x2) * (y1-y2)/(x1-x2);
		x2  = xclip;
	}

//	yclip = (float) (- rendbuf->height + 1);
	yclip = (float) (1);
	if (y1 < yclip)
	{
		if (y2 < yclip) return 0;
		x1 += (yclip-y1) * (x2-x1)/(y2-y1);
		y1  = yclip;
	}
	if (y2 < yclip)
	{
		if (y1 < yclip) return 0;
		x2 += (yclip-y2) * (x1-x2)/(y1-y2);
		y2  = yclip;
	}

//	yclip = (float) (- 1);
	yclip = (float) (rendbuf->height - 1);
	if (y1 > yclip)
	{
		if (y2 > yclip) return 0;
		x1 += (yclip-y1) * (x2-x1)/(y2-y1);
		y1  = yclip;
	}
	if (y2 > yclip)
	{
		if (y1 > yclip) return 0;
		x2 += (yclip-y2) * (x1-x2)/(y1-y2);
		y2  = yclip;
	}

	// Tracé de la ligne //
	dx = abs((int) (x2-x1));
	dy = abs((int) (y2-y1));
	if (dx >= dy)
	{
		if (x2>x1)
		{
			ax = (int) x1; 
			ay = (int) y1; 
			bx = (int) x2; 
			by = (int) y2;
		}
		else
		{
			ax = (int) x2; 
			ay = (int) y2; 
			bx = (int) x1; 
			by = (int) y1;
		}

		kx = bx - ax; //  +
		ky = by - ay; // +/-
		dx = 3;
		//$LB
		dy = rendbuf->BPL;

		if (ky>0)	dy = -dy; 
		else		ky = -ky;
		//$LB
		buffer  = (OBJBITMAP_BUFFER) rendbuf->Image;
		buffer += ax*3 + ((rendbuf->height-ay)*rendbuf->BPL);
		k		= kx>>1;

		for(i=ax; i<=bx; i++)
		{
			*(buffer+0) = colb;  *(buffer+1) = colg;  *(buffer+2) = colr;
			k	   += ky;
			if (k > kx)
			{
				k	   -= kx;
				buffer += dy;
			}
			buffer += dx;
		}
	}
	else
	{
		if (y2 > y1) 
		{ 
			ax = (int) x1; 
			ay = (int) y1; 
			bx = (int) x2; 
			by = (int) y2;
		}
		else 
		{ 
			ax = (int) x2; 
			ay = (int) y2; 
			bx = (int) x1; 
			by = (int) y1;
		}

		kx = bx - ax; 
		ky = by - ay;
		dx = 3;
		//$LB
		dy = - rendbuf->BPL;

		if (kx<0) 
		{ 
			dx = -dx; 
			kx = -kx;
		}

		buffer  = (OBJBITMAP_BUFFER) rendbuf->Image;
		//$LB buffer += ax + ((rendbuf->height-ay)*(rendbuf->BPL>>1));
		buffer += ax*3 + ((rendbuf->height-ay)*rendbuf->BPL);
		k		= ky>>1;


		for(i=ay; i<=by; i++)
		{
			*(buffer+0) = colb;  *(buffer+1) = colg;  *(buffer+2) = colr;
			k += kx;
			if (k > ky)
			{
				k -= ky;
				buffer += dx;
			}
			buffer += dy;
		}
	}
	return 0;
}







int lastFogColor = -1;


///////////////////////////////////////////////////////////////////////////////////////
///		InitFogPalette																///
///////////////////////////////////////////////////////////////////////////////////////
///
///		Initialise la palette de FOG courant -- 15 bits par couleur
///
//$LB (13/06/2003) : 24 bits par couleur
//
int InitFogPalette(int color)
{
	int		l, i, x, r, g, b, k, lp, i0, i1;

	int		b_shift = 4;
	int		g_shift = 4;
	int		r_shift = 4;

	if(color == lastFogColor)		return 0;

	r = (color>>16) &0xFF;
	g = (color>>8)  &0xFF;
	b = color       &0xFF;


	for(l=1; l<16; l++)
	{
		lp = 16-l;
		i0 = l*TABCOL*64;

		for(i=0; i<64; i++)
		{
			i1 = i<<LOGTABCOL;
			//$LB
			for(k=0; k<256; k++)
			{
				x = palette24[i1+k];
				x = ((x*lp+b*l) >> b_shift) & 0xFF;
				palette24[i0+i1+k]	  = x;

				x = palette24[i1+TABCOL_OFFSET1+k];
				x = ((x*lp+g*l) >> g_shift) & 0xFF;
				palette24[i0+i1+TABCOL_OFFSET1+k] = x;

				x = palette24[i1+TABCOL_OFFSET2+k];
				x = ((x*lp+r*l) >> r_shift) & 0xFF;
				palette24[i0+i1+TABCOL_OFFSET2+k] = x;


			}
		}
	}

	lastFogColor = color;

	return 0;
}



///////////////////////////////////////////////////////////////////////////////////////
///		InitPaletteSOFT																///
///////////////////////////////////////////////////////////////////////////////////////
///
///		Initialise la palette utilisée pour le FOG -- 15 bits par couleur
///
//$LB (13/06/2003) : 24 bits par couleur
//
int	InitPaletteSOFT()
{
	int l, i, j;

	for(l=0; l<64; l++)
	{

		//$LB
		for(i=0; i<256; i++)
		{
			if (i)		j = i+ (((l-31)*1024)>>8);
			else		j = 0;
			
			if (j>255)	j = 255;
			if (j<0)	j = 0;

			//$LB
			palette24[(l<<LOGTABCOL)                  + i]  = j;
			palette24[(l<<LOGTABCOL) + TABCOL_OFFSET1 + i]	= j;
			palette24[(l<<LOGTABCOL) + TABCOL_OFFSET2 + i]	= j;
		}
	}

	InitFogPalette(0xffffff);

	return 0;
}