#include "include.h" 
#include "sg_Chain.h"
#include <shinobi.h>
#include "main.h"

#include "islcard.h"
#include "options.h"

#include	<sg_mw.h>
#include	"usr.h"

#include	"islvideo.h"

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

extern TextureType *hourglass_texes[5];

int testcount=0;

UBYTE *test;

fixed			gameSpeed				= 4096;
fixed			globalFrogScale			= 2457;

psFont			*font;

PSIMODEL		*testActorModel;
ACTOR			*testActor;
VECTOR			bbsrc;
VECTOR			bbtar;
GsRVIEW2		camera;
//unsigned long 	*sqrtable;
//short			*acostable;
displayPageType displayPage[2];
displayPageType *currentDisplayPage		= 0;
char			*packetSpace;				//used to hold current poly packet

int				originalTexCount		= 0;
int				afterRoomTexCount		= 0;

ULONG			frame					= 0;
ULONG			loop_ticker				= 0;
ULONG			loop_ticker2			= 0;
int				gameTextLang;
GsRVIEW2		mycamera;

VOID_SUBROUTINE draw_routine			= NULL;
VOID_SUBROUTINE cycle_routine			= NULL;

int displayMode, frameBufferFormat;	// character;
void *vertexBuffer; 










/*	--------------------------------------------------------------------------------
	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);
	vertexBuffer = dwDataPtr;

	// 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 * 4;		// 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;//frog
	static int dist=2040;//am
	// 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;//from
	bbtar.vy = -300;//am
	bbtar.vz = 0;//bbsrc.vz + (cosf(viewAngle) * viewDist);	

	SetCam(bbsrc,bbtar);
}

void InitLookupTables()
{
	int	fileLength;

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

void mikeyInit()
{
	packetSpace = syMalloc(sizeof(POLY_GT4)*20);//should be the size of freds biggest poly packet

	GsSetProjection(900);//320);//475);			// default distance of projection; alters perspective
	SetGeomOffset(640/2,480/2);		// camera focused on middle of screen

}


void languageInit(void)
{
int res, lang;

	res = syCfgGetLanguage(&lang);			// Get the language from the Dreamcast settings
	ASSERT(res == SYD_CFG_OK);				// Make sure the we retrieved the language okay...

	switch(lang)
	{
		case SYD_CFG_JAPANESE :
			gameTextLang=0;
			break;

		case SYD_CFG_ENGLISH :
			gameTextLang=0;
			break;

		case SYD_CFG_GERMAN :
			gameTextLang=0;
			break;

		case SYD_CFG_FRENCH :
			gameTextLang=0;
			break;

		case SYD_CFG_SPANISH :
			gameTextLang=0;
			break;

		case SYD_CFG_ITALIAN :
			gameTextLang=0;
			break;

		default:
			gameTextLang=0;
	} // end-switch
}



void main()
{
	void *old_cycle;
	char *cfgBuf=NULL;


	#ifdef __GNUC__
	shinobi_workaround();
	#endif



	mwPlyPreInitSofdec();
	vidInfo.ap=&ap_obj;

	//all video init stuff now done in usrinitvideo
	vidInfo.vtxbuf = UsrInitVideo(&vidInfo.mode, &vidInfo.frame, &vidInfo.count, &vidInfo.latency);
	displayMode = vidInfo.mode;

	gdFsEntryErrFuncAll((void *)ApGdErrFunc, vidInfo.ap);

	// **jim** - you may want to check this fn, make sure it doesn't cause problems for your sfx stuff
	// JIM : no conflicts as far as I can tell.....
	// sdMemBlkSetTransferMode(SDE_MEMBLK_TRANSFER_MODE_DMA);
	UsrInitSound();
	UsrSetVsyncFunc((void (*)(void))ApVsyncFunc);
	//inits the middleware
	ApInitMw(vidInfo.ap, vidInfo.mode, vidInfo.frame, vidInfo.count, vidInfo.latency, vidInfo.vtxbuf);

	// Initialise the ADX stuff......
	ADXT_Init();

    Init32Malloc();

	// ==== Initialise the buffer used for the config stuff
	cfgBuf = syMalloc(16 * 1024);
	ASSERT(cfgBuf);
	syCfgInit(cfgBuf);


	InitLookupTables();
	utilInitCRC();
	utilSeedRandomInt(398623);
	sfxInitialise(SFX_REVERB_MODE_OFF);


//ok


	//	InitCam();
	actorInitialise();
  	psiInitialise(20);
	initialisePsxStrips();
	cardInitialise();

	mikeyInit();

	debug_printf("start font load\n");
	font = fontLoad("SHELL\\FONT12_X.FON");//must be after psxstrips
//	font = fontLoad("TEXTURES\\FONT.BMP");//must be after psxstrips
	textureLoadBank("SHELL\\DCBITS.SPT");
//	textureLoadBank("INVENTORY\\BACK.SPT");
	{
		TextureBankType *generic_textures;
			TextureType *sprs[9];
			char *names[9] = {"YBUT","BBUT","ABUT","XBUT", "L1", "L2", "R1", "R2", "STARTBUTTON"};
			int i;

			generic_textures = textureLoadInOneGo("SHELL\\GENERIC.SPT");

			for(i = 0; i < 9; i++)
			{
				sprs[i] = textureFindInAllBanks(names[i]);
			}

			fontRegisterButtonSprites(sprs[0],sprs[1],sprs[2],sprs[3]);

			fontRegisterOtherSprites('L', sprs[4]);
			fontRegisterOtherSprites('l', sprs[5]);
			fontRegisterOtherSprites('R', sprs[6]);
			fontRegisterOtherSprites('r', sprs[7]);
			fontRegisterOtherSprites('A', sprs[8]);
	}

	dcSetInventory("none");//auto inventory loading! - code in empty.c
//
   //	gameTextInit("SHELL\\GAMETEXT.TXT", TEXTSTR_MAX, 11, 0);

	languageInit();
   	gameTextInit("SHELL\\GAMETEXT.TXT", TEXTSTR_MAX, LANG_FILE_NUMLANGS, gameTextLang);	// 4 is number of langs, gameTextLang is one we want

	frame = 0;
	loop_ticker = 0;
	loop_ticker2 = 0;

	syCfgExit();
	syFree(cfgBuf);

//videoPlayStream("BLITZBIG.SFD");


	originalTexCount = DCKnumTextures;

	//tmp, until language stuff works properly
 //	cardInitialGameState();




	particleInitialiseList();

// Although this is done in "startup", during development, we're not always *calling* startup
// (oops, keep after the setups!)
	cardInitialPrefs(&optionData);
 	cardInitialGameState();


//  	videoPlayStream("BLITZBIG.SFD");
//  	videoPlayStream("EIDOS20FPS.SFD");
//  	videoPlayStream("DW.SFD");
 // 	videoPlayStream("AA.SFD");


//	kmSetVSyncCallback(callbackTest,NULL);
//	kmSetWaitVsyncCallback(callbackTest,NULL);


//		viewerStart();
//		mapviewStart();
		menuStart();
//		languageStart();

		
	InitCam();//dc fn - do we need?


//	tmpVertexBuffer = MALLOC(2*1024*1024);


	// render loop
	while(TRUE)
	{

		padHandler();
		old_cycle = cycle_routine;

		soundCycle();

		loop_ticker++;
		loop_ticker2++;


		//apparently, we can get stuck here waiting for draw to finish, so bunged some stuff before
		kmBeginScene(&kmSystemConfig);
		kmBeginPass(&vertexBufferDesc);

		if(cycle_routine)
			cycle_routine();

		while(old_cycle != cycle_routine)
		{
			old_cycle = cycle_routine;
			padHandleInput();
			padHandleShock();
			cycle_routine();
		}

  		if(draw_routine)
  			draw_routine();

		kmEndPass(&vertexBufferDesc);
				
		kmRender(KM_RENDER_FLIP);
		kmEndScene(&kmSystemConfig);
	}
	
//	amShutdown();
//	syChainDeleteHandler(VblChain);                   
	
//	FreeBackDrop();
	ADXT_Finish();
	sbExitSystem();
}
