/*
	This file is part of Frogger II, Copyright 2000 Interactive Studios Ltd

	File        : shell.c
	Description : Main core routine and system initialisation
	Date        : 09/03/2000
	Version     : 0.01
*/

#include "include.h"		// so we can use mw_pr() which outputs to the debug window
#include "frogger.h"

KMPACKEDARGB 	borderColour;
KMDWORD 		FBarea[24576 + 19456];
//PDS_PERIPHERAL 	*per;

KMSTRIPCONTEXT 	stripContext00;
KMSTRIPHEAD 	stripHead00;
KMSTRIPCONTEXT 	StripContext;
KMSTRIPHEAD 	StripHead;
KMVERTEX_00		vertices[8];

DCKVERTEX 		*globalVerts;

KMSURFACEDESC	TexList[256];

int				matrixSize = 0;
DCKMATRIX		matrixStack[256];
DCKMATRIX		viewMatrix;

KMPACKEDARGB	colourClampMin,colourClampMax;

//psFont 			*font;

INT				textPosX = 10;
INT				textPosY = 10;

GsRVIEW2		camera;

int				polyCount;

/*	--------------------------------------------------------------------------------
	Function 	: Kamui_Init
	Purpose 	: Initialise Kamui system configuration
	Parameters 	: none
	Returns 	: none
	Info 		:
*/

void Kamui_Init()
{
	// create the frame buffers
	pFB[0] = &primarySurfaceDesc;
	pFB[1] = &renderSurfaceDesc;

    // vertex buffer pointer
    dwDataPtr = (PKMDWORD)(((KMDWORD)syMalloc(0x200000) & 0x0FFFFFFFUL) | 0xA0000000);

	// set the system configuration
	kmSystemConfig.dwSize						= sizeof(KMSYSTEMCONFIGSTRUCT);
	kmSystemConfig.flags						= KM_CONFIGFLAG_ENABLE_CLEAR_FRAMEBUFFER;
	// for frame buffer
	kmSystemConfig.ppSurfaceDescArray			= pFB;
	kmSystemConfig.fb.nNumOfFrameBuffer			= 2;
	// for texture memory
    kmSystemConfig.nTextureMemorySize       	= 0x100000 * 2;		// 2 MB for textures
    kmSystemConfig.nNumOfTextureStruct        	= 4096;
    kmSystemConfig.nNumOfSmallVQStruct        	= 1024;
    kmSystemConfig.pTextureWork               	= &FBarea[0];
    // for Vertex buffer
    kmSystemConfig.pBufferDesc                	= &vertexBufferDesc;
    kmSystemConfig.nNumOfVertexBank           	= 2;
    kmSystemConfig.pVertexBuffer              	= dwDataPtr;		// pointer to vertex buffer
    kmSystemConfig.nVertexBufferSize          	= 0x100000 * 2;		// 2MB for vertex buffer
    kmSystemConfig.nPassDepth                 	= 1;
    kmSystemConfig.Pass[0].dwRegionArrayFlag  	= KM_PASSINFO_AUTOSORT;
    kmSystemConfig.Pass[0].fBufferSize[0]     	= 80.0f;
    kmSystemConfig.Pass[0].fBufferSize[1]     	= 0.0f;
    kmSystemConfig.Pass[0].fBufferSize[2]     	= 20.0f;
    kmSystemConfig.Pass[0].fBufferSize[3]     	= 0.0f;
    kmSystemConfig.Pass[0].fBufferSize[4]     	= 0.0f;

	kmSetSystemConfiguration(&kmSystemConfig);

    // initialise border colour
    borderColour.dwPacked = RGBA(0,0,0,255);	// black border
    kmSetBorderColor(borderColour);
    
    // user initialisation
	InitCRCTable();
}

void SetCam(VECTOR src, VECTOR tar)
{
	camera.vpx = src.vx;
	camera.vpy = src.vy;
	camera.vpz = src.vz;

	camera.vrx = tar.vx;
	camera.vry = tar.vy;
	camera.vrz = tar.vz;

	camera.rz  =  0;

//	GsSetRefView2(&camera);
	GsSetRefView2L(&camera);

	gte_SetRotMatrix(&GsWSMATRIX);
	gte_SetTransMatrix(&GsWSMATRIX);
}

void InitCam(void)
{
	// Set up an ambient light
	GsSetAmbient(128*16, 128*16, 128*16);
 	GsSetLightMode(2);

	// Set up a simple camera
	GsSetProjection(350);			// default distance of projection; alters perspective
	SetGeomOffset(640/2,480/2);		// camera focused on middle of screen
//	SetGeomOffset(0,0);				// camera focused on middle of screen

 	bbsrc.vx = 500;
	bbsrc.vy = -350;
 	bbsrc.vz = 11000;
   
	bbtar.vx = bbsrc.vx + (sinf(viewAngle) * viewDist);
	bbtar.vy = bbsrc.vy;// + 200;
	bbtar.vz = bbsrc.vz + (cosf(viewAngle) * viewDist);	

/* 	bbsrc.vx = 0;
 	bbsrc.vy = 00;
 	bbsrc.vz = -300;
  
 	bbtar.vx = 0;
 	bbtar.vy = 0;
 	bbtar.vz = 1300;
*/
	SetCam(bbsrc,bbtar);
}

VOID VSyncCallbackFunc(PVOID pCallbackArguments)
{
	frame++;
}

int vsyncCounter = 0;

static void vsyncCallback()
{
	frame++;
	vsyncCounter++;
}

/*	--------------------------------------------------------------------------------
	Function 	: 
	Purpose 	: 
	Parameters 	: 
	Returns 	: 
	Info 		:
*/

unsigned long 	*sqrtable;
short			*acostable;

void InitLookupTables()
{
	int	fileLength;
	
	sqrtable = fileLoad("Sqrtable.bin","incbins",&fileLength);
	acostable = fileLoad("Asintabl.bin","incbins",&fileLength);
}

/*	--------------------------------------------------------------------------------
	Function 	: main
	Purpose 	: main code loop
	Parameters 	: none
	Returns 	: none
	Info 		:
*/

TEXTOVERLAY *startText;
PSIOBJECT 	*world;
ACTOR2 		*me = NULL;
ACTOR2 		*me2 = NULL;
char		textbuffer[256];
float		myframe = 0;
DCKVECTOR	camPos = {0.0f,0.0f,-50.0f};
DCKVECTOR	camTarg = {0.0f,0.0f,0.0f};
float		viewAngle = 3.34;
float		viewDist = 1000;
int			tempStride = 32;

extern int	frogFacing[4];
extern int	camFacing;
extern struct gameStateStruct gameState;

void main()
{
	#ifdef __GNUC__
	shinobi_workaround();
	#endif
	
	mw_pr("Starting demo...");

	// initialise video mode
	switch(syCblCheck())
	{
		case SYE_CBL_VGA:
			sbInitSystem((int)KM_DSPMODE_VGA,(int)KM_DSPBPP_RGB565,1);
			break;
			
		case SYE_CBL_PAL:
			sbInitSystem((int)KM_DSPMODE_PALNI640x480EXT,(int)KM_DSPBPP_RGB565,1);
			break;
			
		case SYE_CBL_NTSC:
		default:
			sbInitSystem((int)KM_DSPMODE_NTSCNI640x480,(int)KM_DSPBPP_RGB565,1);
			break;
	}

    // Check malloc alignment
    Init32Malloc();

	mw_pr("Kamui Init...");
	Kamui_Init();

//	kmSetCullingRegister(1.0f);

	InitLookupTables();
	utilInitCRC();
	utilSeedRandomInt(398623);
	font = fontLoad("font.pvr");
	InitCam();
	actorInitialise();
//	InitBackdrop("frogger2.pvr");

	initialisePsxStrips();

	CommonInit();

	// render loop
	while(TRUE)
	{
		polyCount = 0;
	
		per = pdGetPeripheral(PDD_PORT_A0);

		// temp pad emulation
		padData.digital[0] = 0;
		if(per->press & PDD_DGT_KU)
			padData.digital[0] |= PAD_UP;
		if(per->press & PDD_DGT_KD)
			padData.digital[0] |= PAD_DOWN;
		if(per->press & PDD_DGT_KR)
			padData.digital[0] |= PAD_RIGHT;
		if(per->press & PDD_DGT_KL)
			padData.digital[0] |= PAD_LEFT;

		if(per->press & PDD_DGT_TY)
			padData.digital[0] |= PAD_TRIANGLE;
		if(per->press & PDD_DGT_TA)
			padData.digital[0] |= PAD_CROSS;
		if(per->press & PDD_DGT_TX)
			padData.digital[0] |= PAD_SQUARE;
		if(per->press & PDD_DGT_TB)
			padData.digital[0] |= PAD_CIRCLE;
		if(per->press & PDD_DGT_ST)
			padData.digital[0] |= PAD_START;

//		if(per->press & PDD_DGT_KRB)
//			padData.digital[0] |= PAD_R1;
//		if(per->press & PDD_DGT_KLB)
//			padData.digital[0] |= PAD_R2;
				
		// set camera view
//		bbtar.vx = bbsrc.vx + (sinf(viewAngle) * viewDist);
//		bbtar.vy = bbsrc.vy;// + 200;
//		bbtar.vz = bbsrc.vz + (cosf(viewAngle) * viewDist);	
//		SetCam(bbsrc,bbtar);			

		GameLoop();
		
		kmBeginScene(&kmSystemConfig);
		kmBeginPass(&vertexBufferDesc);

		DrawBackDrop();
	
		// draw backdrop and test font stuff
//		fontPrint(font, textPosX,textPosY, "FROGGER II", 255,255,255);

/*		sprintf(textbuffer,"ACTFRAMECOUNT: %d",actFrameCount);
		fontPrint(font, textPosX,textPosY+32, textbuffer, 255,255,255);

		sprintf(textbuffer,"PAD: 0x%x",padData.digital[0]);
		fontPrint(font, textPosX,textPosY+64, textbuffer, 255,255,255);

		sprintf(textbuffer,"(%d,%d,%d)",bbtar.vx,bbtar.vy,bbtar.vz);
		fontPrint(font, textPosX,textPosY+64, textbuffer, 255,255,255);

		sprintf(textbuffer,"%f",viewAngle);
		fontPrint(font, textPosX,textPosY+96, textbuffer, 255,255,255);

		sprintf(textbuffer,"S: %d",tempStride);
		fontPrint(font, textPosX,textPosY+128, textbuffer, 255,255,255);
*/
			
//		Orientate(&frog[i]->actor->qRot, &currTile[i]->dirVector[frogFacing[i]], &currTile[i]->normal);
//		void Orientate(IQUATERNION *me, FVECTOR *fd, FVECTOR *up)

//		if(gameState.mode == INGAME_MODE)
			DrawWorld();
			
		DrawScenicObjList();
			
//		DrawSpecialFX();

//		PrintSprites();

//		if(gameState.mode == INGAME_MODE)
			DrawWaterList();
				
//		if(gameState.mode == INGAME_MODE)
			DrawActorList();
				
//		PrintTextOverlays();

		// START button pressed
/*		if(per->press & PDD_DGT_ST)
		{
			update = !update;
			globalTime = 0;
			mw_pr("START pressed");
		}

		// move forwards and backwards
		if(per->on & PDD_DGT_KU)
		{		
			bbsrc.vx += (sinf(viewAngle) * 50);
			bbsrc.vz += (cosf(viewAngle) * 50);
		}
		if(per->on & PDD_DGT_KD)
		{
			bbsrc.vx -= (sinf(viewAngle) * 50);
			bbsrc.vz -= (cosf(viewAngle) * 50);			
		}

		// rotate left and right
		if(per->on & PDD_DGT_KL)
		{			
			viewAngle -= 0.1;
		}
		if(per->on & PDD_DGT_KR)
		{
			viewAngle += 0.1;
		}
		
		// adjust animation frame
		if(per->on & PDD_DGT_TB)
		{
			frog[0]->actor->position.vy++;
		}
		if(per->on & PDD_DGT_TX)
		{
			frog[0]->actor->position.vy--;
		}

		// move up and down
		if(per->on & PDD_DGT_TY)
		{
			bbsrc.vy += 15;
			bbtar.vy += 15;
		}
*/		
		gte_SetRotMatrix(&GsWSMATRIX);
		gte_SetTransMatrix(&GsWSMATRIX);

		kmEndPass(&vertexBufferDesc);
				
		kmRender(KM_RENDER_FLIP);
		kmEndScene(&kmSystemConfig);

		if(gameState.mode != PAUSE_MODE)
		{
//			gameSpeed = vsyncCounter<<12;
			frame++;
			vsyncCounter++;
			actFrameCount+=4;
		}
		
		pdExecPeripheralServer();
	}
	
	FreeBackDrop();

	sbExitSystem();
}
