#include <sps2lib.h>
#include <sps2tags.h>
#include <sps2util.h>
#include <sps2regstructs.h>
#include "PS2Defines.h"
#include "ps2matrix4x4.h"
#include "sps2wrap.h"
#include "dma.h"
#include "primitives.h"


PS2Sprite::PS2Sprite()
{
	m_x = 0.0f;
	m_y = 0.0f;
	
	Initialise();
}

PS2Sprite::PS2Sprite(float x, float y)
{
	m_x = x; 
	m_y = y;
	
	Initialise();	
}

PS2Sprite::~PS2Sprite()
{
	// Nothing to destruct
}

void PS2Sprite::Initialise(void)
{
	m_z = 128.0f;
	m_w = m_h = 32.0f;
	m_r = m_g = m_b = m_a = 0x80;
	
	m_Vx = 1.7f;
	m_Vy = 2.2f;
	
	m_TopLeft.x 		= -m_w/2.0f;
	m_TopLeft.y 		= -m_h/2.0f;
	m_BottomLeft.x 		= -m_w/2.0f;
	m_BottomLeft.y 		=  m_h/2.0f;
	m_TopRight.x 		=  m_w/2.0f;
	m_TopRight.y 		= -m_h/2.0f;
	m_BottomRight.x 	=  m_w/2.0f;
	m_BottomRight.y 	=  m_h/2.0f;
	
	m_ScreenW = 640.0f;
	m_ScreenH = 512.0f;
}


// ********* Don't Change anything in this method
void PS2Sprite::Render(void) const
{
	VIFDynamicDMA.StartDirect();
	
	// Add the GIFTag
	VIFDynamicDMA.Add128(GS_GIFTAG_BATCH(	4,							// NLOOP
											1,							// EOP
											1,							// PRE
											GS_PRIM(PRIM_TRI_STRIP, 	// PRIM
												PRIM_IIP_FLAT, 
												PRIM_TME_OFF,
												PRIM_FGE_OFF, 
												PRIM_ABE_OFF, 
												PRIM_AA1_OFF, 
												PRIM_FST_UV, 
												PRIM_CTXT_CONTEXT1, 
												PRIM_FIX_NOFIXDDA),
											GIF_FLG_PACKED,					//FLG
											GS_BATCH_2(	GIF_REG_RGBAQ, 
														GIF_REG_XYZ2)));	//BATCH	
		
	// Add the colour (Top Left)
	VIFDynamicDMA.Add128(PACKED_RGBA(m_r ,m_g, m_b, m_a));
		    	
	// Add the position (Top Left)  	   	
	VIFDynamicDMA.Add128(PACKED_XYZ2((int)((2048.0f + m_x + m_TopLeft.x)*16.0f), 
									 (int)((2048.0f + m_y + m_TopLeft.y)*16.0f),  
									 (int)m_z, 
									  0));
	
	// Add the colour (Bottom Left)
	VIFDynamicDMA.Add128(PACKED_RGBA(m_r ,m_g, m_b, m_a));
		    	
	// Add the position (Bottom Left)  	
	VIFDynamicDMA.Add128(PACKED_XYZ2((int)((2048.0f + m_x + m_BottomLeft.x)*16.0f), 
									 (int)((2048.0f + m_y + m_BottomLeft.y)*16.0f),  
									 (int)m_z, 
									  0));
									  
	
	// Add the colour (Top Right)
	VIFDynamicDMA.Add128(PACKED_RGBA(m_r ,m_g, m_b, m_a));
		    	
	// Add the position (Top Right)  	
	VIFDynamicDMA.Add128(PACKED_XYZ2((int)((2048.0f + m_x + m_TopRight.x)*16.0f), 
									 (int)((2048.0f + m_y + m_TopRight.y)*16.0f),  
									 (int)m_z, 
									  0));

	// Add the colour (Bottom Right)
	VIFDynamicDMA.Add128(PACKED_RGBA(m_r ,m_g, m_b, m_a));
		    	
	// Add the position  (Bottom Right)  	
	VIFDynamicDMA.Add128(PACKED_XYZ2((int)((2048.0f + m_x + m_BottomRight.x)*16.0f), 
									 (int)((2048.0f + m_y + m_BottomRight.y)*16.0f),  
									 (int)m_z, 
									  0));
	
	
	VIFDynamicDMA.EndDirect();
}

void PS2Sprite::MoveTo(const float x, const float y)
{
	m_x = x;
	m_y = y;
}

void PS2Sprite::MoveDeltaX(const float x)
{
	m_x += x;
}

void PS2Sprite::MoveDeltaY(const float y)
{
	m_y += y;
}


void PS2Sprite::Move(void)
{
	m_x += m_Vx;
	m_y += m_Vy;
	
	if((m_x >= (m_ScreenW - m_w)/2.0f) && (m_Vx > 0.0f))m_Vx = -m_Vx;
	if((m_x <= (-m_ScreenW + m_w)/2.0f) && (m_Vx < 0.0f))m_Vx = -m_Vx;
	
	if((m_y >= (m_ScreenH - m_h)/2.0f) && (m_Vy > 0.0f))m_Vy = -m_Vy;
	if((m_y <= (-m_ScreenH + m_h)/2.0f) && (m_Vy < 0.0f))m_Vy = -m_Vy;
}

void PS2Sprite::Scale(const float s)
{
	m_w *= s;
	m_h *= s;
	
	m_TopLeft.x 		*= s;
	m_TopLeft.y 		*= s;
	m_BottomLeft.x 		*= s;
	m_BottomLeft.y 		*= s;
	m_TopRight.x 		*= s;
	m_TopRight.y 		*= s;
	m_BottomRight.x 	*= s;
	m_BottomRight.y 	*= s;
	
}

void PS2Sprite::ScaleX(const float s)
{
	m_w *= s;
	
	m_TopLeft.x 		*= s;
	m_BottomLeft.x 		*= s;
	m_TopRight.x 		*= s;
	m_BottomRight.x 	*= s;
}

void PS2Sprite::ScaleY(const float s)
{
	m_h *= s;
	
	m_TopLeft.y 		*= s;
	m_BottomLeft.y 		*= s;
	m_TopRight.y 		*= s;
	m_BottomRight.y 	*= s;
	
}


void PS2Sprite::Rotate(const float a)
{
	float cosi = Cos(a);
	float sini = Sin(a);
		
	// Starting vertices	
	Vector2 TopLeft = m_TopLeft;
	Vector2 TopRight = m_TopRight;
	Vector2 BottomLeft = m_BottomLeft;
	Vector2 BottomRight = m_BottomRight;


	// Rotate the coordinates
	m_TopLeft.x  = TopLeft.x * cosi - TopLeft.y * sini;
	m_TopLeft.y  = TopLeft.y * cosi + TopLeft.x * sini;
	
	m_TopRight.x  = TopRight.x * cosi - TopRight.y * sini;
	m_TopRight.y  = TopRight.y * cosi + TopRight.x * sini;
	
	m_BottomLeft.x  = BottomLeft.x * cosi - BottomLeft.y * sini;
	m_BottomLeft.y  = BottomLeft.y * cosi + BottomLeft.x * sini;
	
	m_BottomRight.x  = BottomRight.x * cosi - BottomRight.y * sini;
	m_BottomRight.y  = BottomRight.y * cosi + BottomRight.x * sini;
}

PS2SpriteT::PS2SpriteT()
{
	m_tu = 32;
	m_tv = 0;
	m_tw = 32;
	m_th = 32;
	
}
	
PS2SpriteT::PS2SpriteT(const float x, const float y):
PS2Sprite(x, y)
{
	m_tu = 32;
	m_tv = 0;
	m_tw = 32;
	m_th = 32;
}

PS2SpriteT::~PS2SpriteT()
{
	// Nothing to destruct
}

// ********* Don't Change anything in this method
void PS2SpriteT::Render(void) const
{
	VIFDynamicDMA.StartDirect();
	
	// Add the GIFTag
	VIFDynamicDMA.Add128(GS_GIFTAG_BATCH(	4,							// NLOOP
											1,							// EOP
											1,							// PRE
											GS_PRIM(PRIM_TRI_STRIP, 	// PRIM
												PRIM_IIP_FLAT, 
												PRIM_TME_ON,
												PRIM_FGE_OFF, 
												PRIM_ABE_ON, 
												PRIM_AA1_OFF, 
												PRIM_FST_UV, 
												PRIM_CTXT_CONTEXT1, 
												PRIM_FIX_NOFIXDDA),
											GIF_FLG_PACKED,					//FLG
											GS_BATCH_3(	GIF_REG_RGBAQ,
														GIF_REG_UV, 
														GIF_REG_XYZ2)));	//BATCH	
		
	// Add the colour (Top Left)
	VIFDynamicDMA.Add128(PACKED_RGBA(m_r ,m_g, m_b, m_a));
	
	// Add UV texture coordinates (Top Left)
    VIFDynamicDMA.Add128(PACKED_UV(	((m_tu)<<4)+8, ((m_tv)<<4)+8));
		    	
	// Add the position (Top Left)  	   	
	VIFDynamicDMA.Add128(PACKED_XYZ2((int)((2048.0f + m_x + m_TopLeft.x)*16.0f), 
									 (int)((2048.0f + m_y + m_TopLeft.y)*16.0f),  
									 (int)m_z, 
									  0));
	
	// Add the colour (Bottom Left)
	VIFDynamicDMA.Add128(PACKED_RGBA(m_r ,m_g, m_b, m_a));
	
	// Add UV texture coordinates (Bottom Left)
    VIFDynamicDMA.Add128(PACKED_UV(	((m_tu)<<4)+8, ((m_tv + m_th)<<4)+8));
	
		    	
	// Add the position (Bottom Left)  	
	VIFDynamicDMA.Add128(PACKED_XYZ2((int)((2048.0f + m_x + m_BottomLeft.x)*16.0f), 
									 (int)((2048.0f + m_y + m_BottomLeft.y)*16.0f),  
									 (int)m_z, 
									  0));
									  
	
	// Add the colour (Top Right)
	VIFDynamicDMA.Add128(PACKED_RGBA(m_r ,m_g, m_b, m_a));
	
	// Add UV texture coordinates (Top Right)
    VIFDynamicDMA.Add128(PACKED_UV(	((m_tu + m_tw)<<4)+8, ((m_tv)<<4)+8));
		    	
	// Add the position (Top Right)  	
	VIFDynamicDMA.Add128(PACKED_XYZ2((int)((2048.0f + m_x + m_TopRight.x)*16.0f), 
									 (int)((2048.0f + m_y + m_TopRight.y)*16.0f),  
									 (int)m_z, 
									  0));

	// Add the colour (Bottom Right)
	VIFDynamicDMA.Add128(PACKED_RGBA(m_r ,m_g, m_b, m_a));
	
	// Add UV texture coordinates
    VIFDynamicDMA.Add128(PACKED_UV(	((m_tu + m_tw)<<4)+8, ((m_tv + m_th)<<4)+8));
		    	
	// Add the position  (Bottom Right)  	
	VIFDynamicDMA.Add128(PACKED_XYZ2((int)((2048.0f + m_x + m_BottomRight.x)*16.0f), 
									 (int)((2048.0f + m_y + m_BottomRight.y)*16.0f),  
									 (int)m_z, 
									  0));
	
	
	VIFDynamicDMA.EndDirect();
}
