/*
	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"
#include "sg_Chain.h"
//#include <am.h>
//#include "am_audio.h"
//#include "generic.h"
#include <shinobi.h>
//#include <sg_sd.h>
//#include <sg_mw.h>
//#include "dc_timer.h"
//#include "lang.h"
//#include "psxsprite.h"
//#include "tongue.h"


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

fixed gameSpeed = 4096;
fixed globalFrogScale = 2457;

PSIMODEL *testActorModel;
ACTOR *testActor;

VECTOR bbsrc, bbtar;

/*
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;

displayPageType displayPage[2];
displayPageType *currentDisplayPage  = 0;

psFont 			*font;
psFont 			*fontSmall;

int 			drawLandscape = 1;
long 			textEntry = 0;	
char 			textString[255] = "";

long 			drawGame = 1;

INT				textPosX = 10;
INT				textPosY = 10;
*/
GsRVIEW2		camera;
/*
int				polyCount;
int				mapCount;

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;

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

SYCHAIN      	VblChain;
*/
unsigned long 	*sqrtable;
short			*acostable;
/*
int 			vsyncCounter = 0;
int 			lastframe = 0;
int 			myVsyncCounter = 0;

AM_BANK_PTR		gMyBank	= KTNULL;
AM_SOUND_PTR	gOneShot;

long 			turbo = 4096;

unsigned short 	globalClut;
signed char 	actorShiftDepth;

short			timerBars = OFF;

#define MAX_AUDIO_INSTANCES					64
#define MAX_ONE_SHOTS						4
#define FIRST_Q_CHANNEL						12
#define	NUMBER_OF_Q_CHANNELS				4

KTU32 				effectSourceMix					=	75;
KTU32 				firstQChannel					=	FIRST_Q_CHANNEL;
KTU32 				numberOfQChannels				=	NUMBER_OF_Q_CHANNELS;
KTU32 				volume							=	127;
KTU32 				pan								=	0;

KMDWORD				FogDensity;
  */

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

void Kamui_Init()
{
	int	i;
	
	// 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       	= 0x150000 * 2;		// 2 MB for textures
    kmSystemConfig.nNumOfTextureStruct        	= 4096;
    kmSystemConfig.nNumOfSmallVQStruct        	= 0;//1024;
    kmSystemConfig.pTextureWork               	= &FBarea[0];
    // for Vertex buffer
    kmSystemConfig.pBufferDesc                	= &vertexBufferDesc;
    kmSystemConfig.nNumOfVertexBank           	= 2;
    kmSystemConfig.pVertexBuffer              	= dwDataPtr;		// pointer to vertex buffer
    kmSystemConfig.nVertexBufferSize          	= 0x050000 * 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);

	gte_SetRotMatrix(&GsWSMATRIX);
	gte_SetTransMatrix(&GsWSMATRIX);
}
	  
void InitCam(void)
{
	static int dist=512;
	// Set up an ambient light
	GsSetAmbient(128*16, 128*16, 128*16);
 	GsSetLightMode(2);

	// Set up a simple camera
	GsSetProjection(900);//320);//475);			// 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 = dist;//500;
	bbsrc.vy = -100;//-350;
 	bbsrc.vz = 0;//11000;

	if(per->press & PDD_DGT_TA)
	{
		dist+=64;
		debug_printf("dist=%d\n",dist);
	}
	if(per->press & PDD_DGT_TB)
	{
		dist-=64;
		debug_printf("dist=%d\n",dist);
	}



	bbtar.vx = 0;//bbsrc.vx + (sinf(viewAngle) * viewDist);
	bbtar.vy = 0;//bbsrc.vy;// + 200;
	bbtar.vz = 0;//bbsrc.vz + (cosf(viewAngle) * viewDist);	

	SetCam(bbsrc,bbtar);
}

/*
void VblCallBack(void *arg)
{
	if(vsyncCounter > lastframe)
	{
		lastframe = vsyncCounter;
		myVsyncCounter = 0;
	}
	else
	{
		myVsyncCounter++;
	}
	frame++;
	vsyncCounter++;	
}
  */

void InitLookupTables()
{
	int	fileLength;

	sqrtable = fileLoad("Sqrtable.bin",&fileLength);
	acostable = fileLoad("acostab.bin",&fileLength);
}

 /*
void BuildFogTable (void)
{
	int				i;
	float			depth;
	KMPACKEDARGB	fogcol;
	KMFLOAT			FogTable[128];
	KMSTATUS		status;
	float			min,max,density;

	// Fog Color
	fogcol.byte.bBlue	= 0;//0.5 * 255;
	fogcol.byte.bGreen	= 0;//0.5 * 255;
	fogcol.byte.bRed	= 0.5 * 255;
	status = kmSetFogTableColor(fogcol);
	// Fog Density
	FogDensity = 0xFF0B;		// FF09 - FF0D
	status = kmSetFogDensity(FogDensity);

	// Fog Table
	for(i = 0; i < 128; i++)
	{
#define	FOG_MIN		(-0.8f)
		FogTable[i] = 1.0f - (float)i * ((1.0f - FOG_MIN) / 128.0f);
		if(FogTable[i] < 0.0f)
			FogTable[i] = 0.0f;
	}
	status = kmSetFogTable(&FogTable[0]);
}
   */
//extern int frameCount;
//extern int AllowPsiDestroy;
//extern int psiActorCount;
//extern int fmaActorCount;

void main()
{
	static int frame=1, roty=0;
	//int					i;
	//MWS_PLY_INIT_SFD	iprm;
	//Uint32 				*memfree,*memsize;

	#ifdef __GNUC__
	shinobi_workaround();
	#endif

	// 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();

	Kamui_Init();

	// setup am sound stuff
//	if(MyAmSetup(KTFALSE)==KTFALSE)
//		return;

	// setup my vb interrupt
//	VblChain = syChainAddHandler(SYD_CHAIN_EVENT_IML6_VBLANK,VblCallBack,0x60,NULL);
	
	InitLookupTables();
	utilInitCRC();
	utilSeedRandomInt(398623);
//	InitCam();
	actorInitialise();
  	psiInitialise(20);

//	InitProgressBar();
//	InitTimerbar();
	
	initialisePsxStrips();



	debug_printf("start load tex\n");
	textureLoadBank( "GENERIC.SPT" );
	debug_printf("end load tex\n");

	debug_printf("start load psi\n");
   	testActorModel = psiLoad("FROGGER.PSI");
//   	testActorModel = psiLoad("AMJET.PSI");
	debug_printf("end load psi\n");

	debug_printf("start actor create\n");
	testActor = actorCreate(testActorModel, 1, 0);
	debug_printf("end actor create\n");
	
  	psiAllocWorkspace();



//	CommonInit();

	// render loop
	while(TRUE)
	{

//		polyCount = 0;
//		actorCount = 0;		
//		mapCount = 0;
		
		per = pdGetPeripheral(PDD_PORT_A0);

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


//		if(per->press & PDD_DGT_TA)
//		{
//			debug_printf("looping\n");
//		}

		testActor->position.vx = 0;
		testActor->position.vy = 0;
		testActor->position.vz = 0;
	   	
		testActor->psiData.object->rotate.vy = roty;
		roty+=16;

		frame++;
		frame&=255;

		//if(per->press & PDD_DGT_TY)frame++;
		//if(per->press & PDD_DGT_TX)frame--;

	   	psiSetKeyFrames(testActor->psiData.object, frame/3);
	   	actorMove(testActor);
	   	actorDraw(testActor);
		


//		DrawSpecialFX();
//		PrintSprites();

//		if(drawLandscape && drawGame)
//			DrawWorld();		

//		if(drawLandscape && drawGame)
//			DrawScenicObjList();
//		if(drawLandscape && drawGame)
//			DrawWaterList();			
		
//		if(drawGame)
//			DrawActorList();

//		UpdateFrogTongue(0);
//		UpdateFrogCroak(0);

//		if(tileTexture)
//			DrawTiledBackdrop();

//		PrintSpriteOverlays(1);
//		PrintSpriteOverlays(0);
//		PrintTextOverlays();		
//		DrawScreenTransition();

//		gte_SetRotMatrix(&GsWSMATRIX);
//		gte_SetTransMatrix(&GsWSMATRIX);

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

//		if(gameState.mode != PAUSE_MODE)
//		{
//			//bb
//			lastActFrameCount = actFrameCount;

//			gameSpeed = vsyncCounter<<12;

//			if(gameSpeed > (5<<12))
//				gameSpeed = (5<<12);
					
//			actFrameCount += gameSpeed>>12;
//			vsyncCounter = 0;
//		}
		
		pdExecPeripheralServer();
	}
	
//	amShutdown();
//	syChainDeleteHandler(VblChain);                   
	
//	FreeBackDrop();

	sbExitSystem();
}
