/*
Copyright (C) 1996-1997 Id Software, Inc.

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  

See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

*/
// sys_null.h -- null system driver to aid porting efforts

#include "cyg-profile.h"

#include "ds.h"

//#define USE_DEBUGGER
#define USE_REAL_TIMEBASE
//#define PROFILE_CODE
#define USE_SOUND
#define USE_WIFI
#define USE_THUMB
//#define USE_TEXTURE_CACHE

#ifndef USE_THUMB
#define THUMB_REDUCTION (64 * 1024)
#else
#define THUMB_REDUCTION (0)
#endif

#ifdef USE_TEXTURE_CACHE
#define TEXTURE_CACHE_SIZE (2048 * 1024)
#else
#define TEXTURE_CACHE_SIZE (0)
#endif

#ifdef USE_DEBUGGER

#include <user_debugger.h>
#define DEBUG_MSG(x) debug_msg(x)

#else
#define DEBUG_MSG(x)
#endif

#include "quakedef.h"
#include "errno.h"

void Sys_mkdir (char *path)
{
	Sys_Error("mkdir not written\n");
}

extern cvar_t ds_screen_clears;


/*
===============================================================================

SYSTEM IO

===============================================================================
*/

void Sys_MakeCodeWriteable (unsigned long startaddr, unsigned long length)
{
}


void Sys_Error (char *error, ...)
{
	va_list         argptr;
	char message[100];

	DEBUG_MSG ("Sys_Error: ");   
	va_start (argptr,error);
	
	vprintf (error,argptr);
	vsnprintf(message, 100, error, argptr);
	DEBUG_MSG(message);
	
	va_end (argptr);
	printf ("\n");
	
	__asm__ __volatile__ (".word 0xE1200070");
	while(1);

	exit (1);
}

void Sys_Printf (char *fmt, ...)
{
//	union {
//		float f;
//		unsigned int i;
//	} temp;
//	
//	temp.f = scr_con_current;
//	
//	if (temp.i != 0)
//		return;
//	if (scr_con_current)
//		return;
	
	va_list         argptr;
	char message[100];
	
	va_start (argptr,fmt);
	
	vprintf (fmt,argptr);
	/*vsnprintf(message, 100, fmt, argptr);
	DEBUG_MSG(message);*/
	
	va_end (argptr);
	
/*	volatile int count = 0;
	for (count = 0; count < 1000000; count++);*/
}

void Sys_Quit (void)
{
	__asm__ __volatile__ (".word 0xE1200070");
	exit (0);
}

char *Sys_ConsoleInput (void)
{
	return 0;
}

void Sys_Sleep (void)
{
}

void Sys_SendKeyEvents (void)
{
}

void Sys_HighFPPrecision (void)
{
}

void Sys_LowFPPrecision (void)
{
}

//=============================================================================

extern "C" void scanKeys();

extern float minx;
extern float maxx;
extern float miny;
extern float maxy;
extern float minz;
extern float maxz;

extern void print_top_four_blocks_kb(void);

extern int in_menu;
int first_in_menu = 1;
int first_out_menu = 1;

extern unsigned int time_to_sleep;
void ds_handle_sleep(void);

unsigned int sound_memory;

unsigned int super_framecount = 0;

void quake_main (int argc, char **argv)
{
	static quakeparms_t    parms;
	
//	print_top_four_blocks_kb();
//	while(1);

#ifdef USE_EXTRA_RAM
	parms.memsize = ds_exram_size() - TEXTURE_CACHE_SIZE;
//	init_texture_cache((void *)((unsigned int)ds_exram_base() + parms.memsize), TEXTURE_CACHE_SIZE);
#else
	parms.memsize = 2097152 + 1024 * 1100 - THUMB_REDUCTION;
#endif
#ifdef USE_WIFI
	parms.memsize -= (240 * 1024);
#endif
#ifdef PROFILE_CODE
	parms.memsize -= (150 * 1024);
#endif

#ifdef USE_EXTRA_RAM
	parms.membase = (void *)((unsigned int)ds_exram_base());
#else
	parms.membase = malloc (parms.memsize);
#endif

#ifdef USE_SOUND
	if (parms.membase)
	{
#ifdef USE_EXTRA_RAM
		sound_memory = (unsigned int)malloc(512 * 1024);
		
		if (sound_memory == 0)
			Sys_Error("couldn\'t allocate memory for sound\n");
#else
		sound_memory = (unsigned int)parms.membase;
		parms.membase = (void *)((unsigned int)parms.membase + 128 * 1024);
		parms.memsize -= 128 * 1024;
#endif
	}
#endif
	
//	print_top_four_blocks_kb();
//	while(1);
	
	parms.basedir = "";

	COM_InitArgv (argc, argv);

	parms.argc = com_argc;
	parms.argv = com_argv;
	
	Sys_Printf ("Host_Init, memory base at 0x%08x\n", parms.membase);
	
	if (parms.membase == NULL)
	{
		printf("couln\'t allocate heap of %d bytes!\n", parms.memsize);
		print_top_four_blocks_kb();
		*(int *)0 = 0;
		while(1);
	}

	Host_Init (&parms);

#ifdef PROFILE_CODE
	cygprofile_begin();
#endif

	double oldtime = Sys_FloatTime();
	double newtime = Sys_FloatTime() + 0.1;
	double the_time;

	while (1)
	{
		scanKeys();
		
//		if (time_to_sleep)
//		{
//			ds_handle_sleep();
//			time_to_sleep = 0;
//		}
		
#ifdef PROFILE_CODE
		extern int host_framecount;
		
		if (host_framecount == 1)
			cygprofile_enable();
		else if (host_framecount > 700)
		{
			cygprofile_disable();
			cygprofile_end();
			printf("profiling done\n");
			while(1);
		}
#endif

//		if (super_framecount > 2000)
//		{
//			extern int texture_loads;
//			extern int texture_caches;
//			
//			printf("did %d disk loads, %d cached loads, %.2f cache usage\n",
//				texture_loads, texture_caches, (float)texture_caches / (texture_loads + texture_caches) * 100);
//			while(1);
//		}

#ifdef USE_REAL_TIMEBASE
		the_time = newtime - oldtime;
		oldtime = newtime;
		Host_Frame (the_time);
		newtime = Sys_FloatTime();
#else
		Host_Frame(0.1);
#endif
		super_framecount++;
		
		if (in_menu == 0)
		{
			first_in_menu = 1;
			
			if (first_out_menu)
			{
				first_out_menu = 0;
				if (ds_screen_clears.value)
				{
					printf("\x1b[2J\n\n\n");		//extra newline?
//					printf("megaclear 1\n");
				}
			}
		}
		else
		{
			if (first_in_menu == 1)
			{
				first_in_menu = 0;
				if (ds_screen_clears.value)
				{
					printf("\x1b[2J\n\n");
//					printf("megaclear 2\n");
				}
			}
			first_out_menu = 1;
		}
		
		unsigned short *text_map = (unsigned short *)(((9)*0x800)+0x6200000);
		
		if (host_framecount & 0x1)
			text_map[31] = 0xf058;
		else
			text_map[31] = 0xf02b;
		
#ifdef USE_DEBUGGER
		user_debugger_update();
#endif
		minz = 10;
		maxz = 0;
	}
}


