#ifdef PSX_VERSION
#include <sys\types.h>
#include <libgte.h>
#include <libgpu.h>
#include <gtemac.h>
#include <inline_c.h>
#include "../spec_psx/typedefs.h"
#include "../spec_psx/maths.h"
#else
#include "../specific/standard.h"
#include "../specific/global.h"
#endif

#include "lara.h"
#include "sphere.h"
#include "control.h"

extern long wibble;
extern short rcossin_tbl[];

extern 	uchar	lara_meshes[];
extern	uchar	lara_last_points[];
extern	uchar	lara_line_counts[];
extern	short 	electricity_points[32][6];

void LaraElectricDeath(long copy, ITEM_INFO	*item);
void UpdateElectricityPoints();

#if defined(PSX_VERSION) && defined(RELOC)

void *func[] = {
	&UpdateElectricityPoints,
	&LaraElectricDeath,
};

#endif

#define	MAX_ELEC_POS	256
#define	MAX_ELEC_POS2	MAX_ELEC_POS+(MAX_ELEC_POS>>1)

void UpdateElectricityPoints()
{
	long			lp,random;
	long			tx,ty,tz,xv,yv,zv;
	short		*leccy;

	leccy = &electricity_points[0][0];

	for (lp=0;lp<32;lp++)
	{
		random = GetRandomDraw();

		tx = *leccy;
		ty = *(leccy+1);
		tz = *(leccy+2);
		xv = *(leccy+3);
		yv = *(leccy+4);
		zv = *(leccy+5);

		if (	((tx > MAX_ELEC_POS || tx < -MAX_ELEC_POS) &&
			(ty > MAX_ELEC_POS || ty < -MAX_ELEC_POS) &&
			(tz > MAX_ELEC_POS || tz < -MAX_ELEC_POS)) ||
			((tx > MAX_ELEC_POS2 || tx < -MAX_ELEC_POS2) ||
			(ty > MAX_ELEC_POS2 || ty < -MAX_ELEC_POS2) ||
			(tz > MAX_ELEC_POS2 || tz < -MAX_ELEC_POS2)))
			xv = tx = yv = ty =	zv = tz = 0;

		if (!xv)
		{
			if (random&1)
				xv = -(GetRandomDraw()&3)-1;
			else
				xv = (GetRandomDraw()&3)+1;
		}
		else if (xv < 0)
			xv-=2;
		else
			xv+=2;

		if (!yv)
		{
			if (random&2)
				yv = -(GetRandomDraw()&3)-1;
			else
				yv = (GetRandomDraw()&3)+1;
		}
		else if (yv < 0)
			yv-=2;
		else
			yv+=2;

		if (!zv)
		{
			if (random&4)
				zv = -(GetRandomDraw()&3)-1;
			else
				zv = (GetRandomDraw()&3)+1;
		}
		else if (zv < 0)
			zv--;
		else
			zv++;

		tx += xv;
		ty += yv;
		tz += zv;

		*leccy++ = tx;
		*leccy++ = ty;
		*leccy++ = tz;
		*leccy++ = xv;
		*leccy++ = yv;
		*leccy++ = zv;
	}
}

#ifdef PSX_VERSION

void LaraElectricDeath(long copy, ITEM_INFO *item)
{
	PHD_VECTOR	pos1,pos2;
	LINE_G2 		*lineg2;
	BITE_INFO		bite1,bite2;
	short		*scrxy;	// X,Y
	long			*scrz;	// Z
	short		*distances;	// distances for rgbs.
	short		*TempMesh;
	short		*leccy;
	long			dx,dy,dz;
	long			wx,wy,wz,tx,ty,tz,xv,yv,zv;
	long			lp,lp1;

	mPushMatrix();

//	SetRotMatrix((MATRIX*) Matrix);
//	SetTransMatrix((MATRIX*) Matrix);
//	mTranslateXYZ(lara_item->pos.x_pos,lara_item->pos.y_pos,lara_item->pos.z_pos);
	mTranslateAbsXYZ(item->pos.x_pos,item->pos.y_pos,item->pos.z_pos);

	scrxy = (short *) 0x1f800000;	// Set pointer to scratch pad.
	scrz = (long *) 0x1f800180;	// Set pointer to scratch pad.
	distances = (short *) 0x1f8002c0;	// Set pointer to scratch pad.
	TempMesh = (short *) 0x1f8003f0;	// Set pointer to scratch pad.

	for (lp=0;lp<14;lp++)
	{
		leccy = &electricity_points[(lp*5)&15][0];

		bite1.mesh_num = lara_meshes[(lp<<1)];
		bite2.mesh_num = lara_meshes[(lp<<1)+1];

		pos1.y = 0;
		if (copy)
		{
			pos1.z = -48;
			pos1.x = -48;
		}
		else
		{
			pos1.x = 48;
			pos1.z = 48;
		}
		GetJointAbsPosition(item, &pos1, bite1.mesh_num );

		pos2.y = 0;
		if (!lara_last_points[lp] || lp==13)
		{
			if (copy)
			{
				pos2.z = -48;
				pos2.x = -48;
			}
			else
			{
				pos2.z = 48;
				pos2.x = 48;
			}
			if (lp==13)
				pos2.y = -64;
		}
		else
			pos2.x = pos2.z = 0;

		GetJointAbsPosition(item, &pos2, bite2.mesh_num );

		pos1.x -= item->pos.x_pos;
		pos1.y -= item->pos.y_pos;
		pos1.z -= item->pos.z_pos;
		pos2.x -= item->pos.x_pos;
		pos2.y -= item->pos.y_pos;
		pos2.z -= item->pos.z_pos;

		wx = pos1.x;
		wy = pos1.y;
		wz = pos1.z;
		dx = (pos2.x - pos1.x) >> 2;
		dy = (pos2.y - pos1.y) >> 2;
		dz = (pos2.z - pos1.z) >> 2;

		for (lp1=0;lp1<5;lp1++)
		{
			if (lp1 == 4 && !lara_last_points[lp])
				break;
			else if (lp1 == 4 && lara_last_points[lp])	// Last point?
			{
				TempMesh[0] = pos2.x;
				TempMesh[1] = pos2.y;
				TempMesh[2] = pos2.z;
			}
			else
			{
				TempMesh[0] = wx;
				TempMesh[1] = wy;
				TempMesh[2] = wz;
			}

			if (lp1 != 0 && lp1 != 4)
			{
				tx = *leccy++;
				ty = *leccy++;
				tz = *leccy++;

				if (copy)
				{
					TempMesh[0] -= tx >> 3;
					TempMesh[1] -= ty >> 3;
					TempMesh[2] -= tz >> 3;
				}
				else
				{
					TempMesh[0] += tx >> 3;
					TempMesh[1] += ty >> 3;
					TempMesh[2] += tz >> 3;
				}
				leccy+=3;

				xv = abs(tx);
				yv = abs(ty);
				zv = abs(tz);
				if (yv > xv)
					xv = yv;
				if (zv > xv)
					xv = zv;

				*distances++ = xv;
			}
			else
				*distances++ = 0;

			gte_ldv0(TempMesh);
			gte_rtps();
			wx += dx;
			wy += dy;
			wz += dz;
			gte_stsxy(scrxy);
			gte_stsz(scrz);
			scrxy+=2;
			scrz++;
		}
	}

	scrxy = (short *) 0x1f800000;	// Set pointer to scratch pad.
	scrz = (long *) 0x1f800180;	// Set pointer to scratch pad.
	distances = (short *) 0x1f8002c0;	// Set pointer to scratch pad.

	for (lp=0;lp<6;lp++)
	{
		for (lp1=0;lp1<lara_line_counts[lp];lp1++)        	// Electricity on lara.
		{
			long	x1,x2,y1,y2,z1,rgb,rgb1;

			if (db.polyptr >= db.polybuf_limit)
			{
				mPopMatrix();
				return;
			}

			x1 = *scrxy++;
			y1 = *scrxy++;
			x2 = *scrxy;
			y2 = *(scrxy+1);
			z1 = (*scrz++)>>3;
			rgb = *distances++;
			rgb1 = *distances;

			if (z1 < 32 || z1 > 0xa00)
				continue;

			lineg2 = (LINE_G2 *)db.polyptr;
			setlen(lineg2, 4);
			setcode(lineg2, 0x52);

			if (rgb > 255)
			{
				rgb = 511-rgb;
				if (rgb < 0)
					rgb = 0;
			}

			if (rgb1 > 255)
			{
				rgb1 = 511-rgb1;
				if (rgb1 < 0)
					rgb1 = 0;
			}

			if (copy)
			{
				rgb >>= 1;
				rgb1 >>= 1;
			}

			setRGB0(lineg2,0,rgb,rgb);
			setRGB1(lineg2,0,rgb1,rgb1);
			setXY2(lineg2,x1,y1,x2,y2);
			MyaddPrim(db.ot, z1, lineg2);
			db.polyptr += sizeof(LINE_G2);

			if (db.polyptr >= db.polybuf_limit)
			{
				mPopMatrix();
				return;
			}

			setDrawTPage((DR_TPAGE *)db.polyptr, 0, 1, getTPage(0, 1, 0, 0));
			MyaddPrim( db.ot,z1,(DR_TPAGE *)db.polyptr);
			db.polyptr += sizeof(DR_TPAGE);
		}

		distances++;
		scrxy+=2;
		scrz++;
	}

	mPopMatrix();
}

#endif
