// Floor.c

#include "ult_64.h"
#include "file.h"
#include "define.h"
#include "ml.h"
#include "defs.h"
#include "swd.h"
#include "stats.h"

#include "misc.h"
#include "stadium.h"
#include "floor.h"


#define LOGO_W 48
#define LOGO_H 80


typedef struct SLogo
{
	RGBA16
		Palette[16];
	u8
		Texture[LOGO_W * LOGO_H / 2];
} SLogo;

typedef struct Vec2s
{
	s16
		x,
		y;
} Vec2s;


static const Vec2s
	LogoPosz[] =
	{
		5800, -3400,			// All-Stars
		5400, -3000,			// Atlanta Hawks
		5800, -3400,			// Boston Celtics
		5800, -3400,			// Charlotte Hornets
		5800, -3000,			// Chicago Bulls
		6100, -2300,			// Cleveland Cavaliers
		6000, -2200,			// Dallas Mavericks
		5300, -3000,			// Denver Nuggets
		5300, -3300,			// Detroit Pistons
		5800, -3400,			// Golden State Warriors
		5700, -5700,			// Houston Rockets
		3900, +3300,			// Indiana Pacers
		5800, -3400,			// Los Angeles Clippers
		5400, -2800,			// Los Angeles Lakers
		5400, +3100,			// Miami Heat
		6000, -3300,			// Milwaukee Bucks
		5800, -2700,			// Minnesota Timberwolves
		5800, +3100,			// New Jersey Nets
		5500, -3700,			// New York Knicks
		5800, -3400,			// Orlando Magic
		6000, +2900,			// Philadelphia 76'ers
		6200, -2200,			// Pheonix Suns
		5800, -4000,			// Portland Trailblazers
		5200, -2800,			// Sacramento Kings
		5800, -3400,			// San Antonio Spurs
		6200, +2800,			// Seattle Sonics
		5800, -3400,			// Toronto Raptors
		5800, -2700,			// Utah Jazz
		5800, -3400,			// Vancouver Grizzlies
		5900, -2800,			// Washington Wizards
	};

static SLogo
	Logo;

static u8
	*FloorData,
	*LinesData;

static Gfx
	*FloorGfx,
	*LinesGfx;


static void SetLogoVerts( Vtx *verts, const s32 x, const s32 y )
{
	VertexN64
		*v = (VertexN64 *)verts;

	v[0].x = x - (LOGO_W*16);
	v[0].y = 0;
	v[0].z = y + (LOGO_H*16);
	v[0].u = 32;
	v[0].v = 32;
	v[0].a = 255;

	v[1].x = x + (LOGO_W*16);
	v[1].y = 0;
	v[1].z = y + (LOGO_H*16);
	v[1].u = (LOGO_W << 6) - 32;
	v[1].v = 32;
	v[1].a = 255;

	v[2].x = x + (LOGO_W*16);
	v[2].y = 0;
	v[2].z = y - (LOGO_H*16);
	v[2].u = (LOGO_W << 6) - 32;
	v[2].v = (LOGO_H << 6) - 32;
	v[2].a = 255;

	v[3].x = x - (LOGO_W*16);
	v[3].y = 0;
	v[3].z = y - (LOGO_H*16);
	v[3].u = 32;
	v[3].v = (LOGO_H << 6) - 32;
	v[3].a = 255;
}


static Gfx *DrawLogo( Gfx *gp )
{
	static Vtx
		verts[2*4];
	const Vec2s
		*pos;
	s32
		team;

	if (sb___gPlyRound < 0)
		return( gp );


	team = Stadium_GetNum( pcl__gMatch->asb__mTeam[HOME_TEAM] );
	pos = &LogoPosz[team];

	SetLogoVerts( &verts[0], +pos->x, +pos->y );
	SetLogoVerts( &verts[4], -pos->x, -pos->y );


	gDPPipeSync( gp++ );
	gSPTexture( gp++, 0x8000, 0x8000, 0, G_TX_RENDERTILE, G_ON );
	gDPSetRenderMode( gp++, G_RM_OPA_SURF, G_RM_OPA_SURF2 );
	gDPSetCombineMode( gp++, G_CC_DECALRGBA, G_CC_DECALRGBA );
	gDPSetAlphaCompare( gp++, G_AC_THRESHOLD );
	gDPSetBlendColor( gp++, 0, 0, 0, 255 );

	gDPLoadTLUT_pal16( gp++, 0, &Logo.Palette[0] );

	gDPLoadTextureBlock_4b( gp++,
													&Logo.Texture[0],
													G_IM_FMT_CI,
													LOGO_W,
													LOGO_H,
													0,
													G_TX_CLAMP,
													G_TX_CLAMP,
													6, 7,
													G_TX_NOLOD, G_TX_NOLOD );

	gSPVertex( gp++, verts, 2*4, 0 );

	gSP2Triangles( gp++, 0, 2, 1, 0, 0, 3, 2, 0 );
	gSP2Triangles( gp++, 4, 6, 5, 0, 4, 7, 6, 0 );

	return( gp );
}


static Gfx *DrawFloor( Gfx *gp, u8 *ptr )
{
	static u8
		c = 0;
	s32
		count,
		command;
	u8
		*cmd,
		*tex;

	gDPPipeSync( gp++ );
	gSPTexture( gp++, 0x8000, 0x8000, 0, G_TX_RENDERTILE, G_ON );
	gDPSetRenderMode( gp++, G_RM_OPA_SURF, G_RM_OPA_SURF2 );
//	gDPSetCombineMode( gp++, G_CC_DECALRGB, G_CC_DECALRGB );
gDPSetCombineMode( gp++, G_CC_MODULATERGB, G_CC_MODULATERGB );

	cmd = &ptr[*(s32 *)&ptr[6*4]];
	tex = &ptr[8*4];

	count = *(s32 *)&ptr[4*4];
	count *= (32*64);
	ptr += (8*4) + (256*2) + count;

	gDPLoadTLUT_pal256( gp++, tex );
	tex += (256*2);

	while (cmd[0] != 0)
	{
		command = cmd[0];
		count = cmd[1];
		cmd += 2;

		switch (command)
		{
			case 1:
				gDPLoadTextureBlock( gp++,
														 tex,
														 G_IM_FMT_CI,
														 G_IM_SIZ_8b,
														 32,
														 64,
														 0,
														 G_TX_CLAMP,
														 G_TX_CLAMP,
														 5, 6,
														 G_TX_NOLOD, G_TX_NOLOD );
				tex += (32*64);
				break;

			case 2:
				gSPVertex( gp++, ptr, count, 0 );
				ptr += (count * 16);
				break;

			case 3:
				while (count >= 2)
				{
					gSP2Triangles( gp++,
												 cmd[0], cmd[1], cmd[2], 0,
												 cmd[3], cmd[4], cmd[5], 0 );
					cmd += 2*3;
					count -= 2;
				}
				if (count > 0)
				{
					gSP1Triangle( gp++, cmd[0], cmd[1], cmd[2], 0 );
					cmd += 3;
				}
				break;
		}
	}

	return( gp );
}


static Gfx *DrawLines( Gfx *gp, u8 *ptr )
{
	s32
		verts,
		faces;
	u8
		*cmd;

	cmd = &ptr[5*4];
	ptr += *(s32 *)&ptr[4*4];

	gDPPipeSync( gp++ );
	gDPSetRenderMode( gp++, G_RM_AA_OPA_SURF, G_RM_AA_OPA_SURF2 );
	gSPTexture( gp++, 0, 0, 0, 0, G_OFF );
	gDPSetCombineMode( gp++, G_CC_SHADE, G_CC_SHADE );

	while (cmd[0] > 0)
	{
		verts = cmd[0];
		faces = cmd[1];
		cmd += 2;

		gSPVertex( gp++, ptr, verts, 0 );
		ptr += (verts * 16);

		while (faces >= 2)
		{
			gSP2Triangles( gp++, cmd[0], cmd[1], cmd[2], 0, cmd[3], cmd[4], cmd[5], 0 );
			cmd += 2*3;
			faces -= 2;
		}
		if (faces > 0)
		{
			gSP1Triangle( gp++, cmd[0], cmd[1], cmd[2], 0 );
			cmd += 3;
			faces--;
		}
	}

	return( gp );
}


void Floor_Init( void *workspace )
{
	FH
		file;
	Gfx
		*gp;
	s32
		team,
		pos,
		size;
	u8
		*ptr;

	file = FileOpen( "SpecLogo.TEX", "rb" );

	if (sb___gPlyRound == 3)
		FileSeek( file, sizeof( SLogo ), SEEK_SET );

	FileRead( &Logo, sizeof( SLogo ), 1, file );

	FileClose( file );

	Pal_SetAlpha( &Logo.Palette[1], 255, 15 );


	team = Stadium_GetNum( pcl__gMatch->asb__mTeam[HOME_TEAM] );
	pos = 4 + (team * 8);

	file = FileOpen( "FLOORS.DIR", "rb" );
	if (file)
	{
		FileSeek( file, pos, SEEK_SET );
		FileRead( &pos, 4, 1, file );
		FileRead( &size, 4, 1, file );

		FileSeek( file, pos, SEEK_SET );
		FileRead( workspace, size, 1, file );

		FileClose( file );


		pub__LoadCur = workspace;

		pub__SaveCur = workspace;
		pub__SaveCur += (64*1024);

		ptr = pub__SaveCur;

		SwdExpand();

		size = (u32)pub__SaveCur - (u32)ptr;
		FloorData = MemMalloc( size, MEM_ANY );
		memcpy( FloorData, ptr, size );
	}


//	pos = pcl__gMatch->asb__mTeam[0]-1;
	pos = 4 + (team * 8);

	file = FileOpen( "LINES.SWD", "rb" );
	if (file)
	{
		FileSeek( file, pos, SEEK_SET );
		FileRead( &pos, 4, 1, file );
		FileRead( &size, 4, 1, file );

		LinesData = MemMalloc( size, MEM_ANY );
		FileSeek( file, pos, SEEK_SET );
		FileRead( LinesData, size, 1, file );

		FileClose( file );
	}


	gp = DrawFloor( workspace, FloorData );
	gp = DrawLogo( gp );
	gSPEndDisplayList( gp++ );
	size = (s32)gp - (s32)workspace;
	FloorGfx = (Gfx *)MemMalloc( size, MEM_ANY );
	gp = DrawFloor( FloorGfx, FloorData );
	gp = DrawLogo( gp );
	gSPEndDisplayList( gp++ );


	gp = DrawLines( workspace, LinesData );
	gSPEndDisplayList( gp++ );
	size = (s32)gp - (s32)workspace;
	LinesGfx = (Gfx *)MemMalloc( size, MEM_ANY );
	gp = DrawLines( LinesGfx, LinesData );
	gSPEndDisplayList( gp++ );
}


void Floor_Deinit()
{
	MemFree( LinesGfx );
	MemFree( FloorGfx );
	MemFree( LinesData );
	MemFree( FloorData );
}


Gfx *Floor_DrawWood( Gfx *gp )
{
	gSPDisplayList( gp++, FloorGfx );

	return( gp );
}


Gfx *Floor_DrawLines( Gfx *gp )
{
	gSPDisplayList( gp++, LinesGfx );

	return( gp );
}


int ErrorCheckTeamStadium(int team)
{
	if(team < 1 || team > 29)	// error correct for missing floors, stadiums etc.
	{
		team = TEAM_LAL;	// default to Lakers if error
	}

	return( team-1 );		// scale 1-29 to 0-28 for correct indexing
}
