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

*/

const char amigaversion[] = "$VER: WarpQuake 0.2 (22.1.100)\n";

#include <stdio.h>
#include <stdlib.h>

#include <utility/tagitem.h>
#include <exec/exec.h>
#include <exec/types.h>
#include <dos/exall.h>
#include <dos/dos.h>
#include <powerup/ppcproto/dos.h>
#include <powerup/ppcproto/exec.h>
#include <powerpc/powerpc.h>
#include <powerpc/powerpc_protos.h>

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

#include "amiga_timer.h"

qboolean isDedicated = FALSE;

static int cpu_type;
static int bus_clock;
static int bus_MHz;
static double clocks2secs;

extern struct Mode_Screen *msptr;

void File_Shutdown (void);

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

FILE IO

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

#define	MAX_HANDLES		10
BPTR	sys_handles[MAX_HANDLES];

int		findhandle (void)
{
	int		i;
	
	for (i=1 ; i<MAX_HANDLES ; i++)
		if (!sys_handles[i])
			return i;
	Sys_Error ("out of handles");
	return -1;
}

/*
================
filelength
================
*/
int filelength (BPTR f)
{
	LONG		pos;
	LONG		end;

	pos = Seek (f, 0, OFFSET_END);
	end = Seek (f, pos, OFFSET_BEGINNING);

	return (int) end;
}

int Sys_FileOpenRead (char *path, int *hndl)
{
	BPTR	f;
	int		i;
	
	i = findhandle ();

	printf ("Opening '%s' for read\n", path);
	f = Open(path, MODE_OLDFILE);
	if (!f)
	{
		*hndl = -1;
		return -1;
	}
	sys_handles[i] = f;
	*hndl = i;
	
	return filelength(f);
}

int Sys_FileOpenWrite (char *path)
{
	BPTR	f;
	int		i;
	
	i = findhandle ();

	printf ("Opening '%s' for write\n", path);
	f = Open(path, MODE_NEWFILE);
	if (!f)
		Sys_Error ("Error opening %s: %s", path,strerror(errno));
	sys_handles[i] = f;
	
	return i;
}

void Sys_FileClose (int handle)
{
//	printf("Sys_FileClose() %i\n", handle);
	Close (sys_handles[handle]);
	sys_handles[handle] = NULL;
}

void Sys_FileSeek (int handle, int position)
{
	/* printf ("%d: Seeking to %d\n", handle, position); */
	if (Seek (sys_handles[handle], position, OFFSET_BEGINNING) == -1)
		Sys_Error ("Error in Seek()");
}

int Sys_FileRead (int handle, void *dest, int count)
{
	/* printf ("%d: Reading %d to %08x\n", handle, count, dest); */
	return (int)Read (sys_handles[handle], dest, count);
}

int Sys_FileWrite (int handle, void *data, int count)
{
	return (int)Write (sys_handles[handle], data, count);
}

int	Sys_FileTime (char *path)
{
	BPTR	f;
	
	f = Open(path, MODE_OLDFILE);
	if (f)
	{
		Close(f);
		return 1;
	}
	
	return -1;
}

void Sys_mkdir (char *path)
{
}


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

SYSTEM IO

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

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


void Sys_DebugLog(char *file, char *fmt, ...)
{
}

void Sys_Error (char *error, ...)
{
	va_list		argptr;

	printf ("Sys_Error: ");	
	va_start (argptr,error);
	vprintf (error,argptr);
	va_end (argptr);
	printf ("\n");

	Host_Shutdown();
	File_Shutdown();
	exit (20);
}

void Sys_Printf (char *fmt, ...)
{
	va_list		argptr;
	
	va_start (argptr,fmt);
	if (!con_initialized)
	  vprintf (fmt,argptr);
	va_end (argptr);
}

void Sys_Quit (void)
{
	Host_Shutdown();
	File_Shutdown();
	exit (0);
}

void File_Shutdown (void)
{
	int i;

	for (i=1; i<MAX_HANDLES ; i++)
	{
		if (sys_handles[i])
			Sys_FileClose (i);
	}
}

double Sys_FloatTime (void)
{
  unsigned int clock[2];

  ppctimer (clock);
  return (((double)clock[0]) * 4294967296.0 + (double)clock[1]) *
         clocks2secs;
}

char *Sys_ConsoleInput (void)
{
	return NULL;
}

void Sys_Sleep (void)
{
}

/*
void Sys_SendKeyEvents (void)
{
}
*/

void Sys_HighFPPrecision (void)
{
}

void Sys_LowFPPrecision (void)
{
}

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

int main (int argc, char **argv)
{
  int j;
	int bat;
  double time, oldtime, newtime;
  quakeparms_t parms;

	msptr = NULL;

  memset (&parms, 0, sizeof(parms));

  COM_InitArgv (argc, argv);

  parms.memsize = 8*1024*1024;
  j = COM_CheckParm("-mem");
  if (j)
    parms.memsize = (int) (Q_atof(com_argv[j+1]) * 1024 * 1024);
  if ((parms.membase = malloc (parms.memsize)) == NULL)
    Sys_Error ("Can't allocate %d bytes", parms.memsize);
  parms.basedir = "PROGDIR:";
  parms.cachedir = "";

  parms.argc = com_argc;
  parms.argv = com_argv;

	bat = COM_CheckParm("-bat");
	if (bat)
		ChangeMMU (CHMMU_BAT);

  {
    struct TagItem ti_cputype = {GETINFO_CPU, 0};
    struct TagItem ti_cpuclock = {GETINFO_CPUCLOCK, 0};
    struct TagItem ti_busclock = {GETINFO_BUSCLOCK, 0};

    GetInfo (&ti_cputype);
    cpu_type = ti_cputype.ti_Data;
    switch (cpu_type) {
      case CPUF_603:
        printf ("\nCPU is PPC603 ");
        break;
      case CPUF_604:
        printf ("\nCPU is PPC604 ");
        break;
      case CPUF_603E:
        printf ("\nCPU is PPC603e ");
        break;
      case CPUF_604E:
        printf ("\nCPU is PPC604e ");
        break;
      case CPUF_620:
        printf ("\nCPU is PPC620 ");
        break;
      default:
        printf ("\nCPU is PPC ");
        break;
    }

    GetInfo (&ti_cpuclock);
    bus_clock = ti_cpuclock.ti_Data;
    printf ("running at %d MHz\n", bus_clock / 1000000);

    GetInfo (&ti_busclock);
    bus_clock = ti_busclock.ti_Data;
    bus_MHz = bus_clock / 1000000;
    printf("Bus clock is %d MHz.\n\n", bus_MHz);

    clocks2secs = 4.0 / bus_clock;

  }

//	printf ("Host_Init\n");
	Host_Init (&parms);

	Host_Frame (0.1);

	oldtime = Sys_FloatTime ();
	while (1)
	{
		newtime = Sys_FloatTime ();
		time = newtime - oldtime;

		if (time < 0.0)
			printf ("Negative time = %f!!\n", time);

		if (cls.state == ca_dedicated && (time<sys_ticrate.value))
			continue;

		Host_Frame ((float)time);

		oldtime = newtime;
	}
}

/**********************************************************************/
