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

#include <exec/types.h>
#include <graphics/rastport.h>
#include <devices/timer.h>

#include <proto/exec.h>
#include <proto/timer.h>
#include <proto/graphics.h>

#include "EE_timer.h"


struct Library *TimerBase = NULL;
TIMER *Timer;
char InfoText[40];

BOOL InitTimer(VOID)
{

  if((Timer = malloc(sizeof(TIMER))) == NULL)
    return FALSE;

  memset(Timer, 0, sizeof(TIMER));

  if((Timer->TimeIO = malloc(sizeof(struct timerequest))) == NULL)
  {
    RemoveTimer();
    return FALSE;
  }

  memset(Timer->TimeIO, 0, sizeof(struct timerequest));

  if(OpenDevice(TIMERNAME, UNIT_ECLOCK, (struct IORequest *)Timer->TimeIO, 0))
  {
    RemoveTimer();
    return FALSE;
  }

  TimerBase = (struct Library *)Timer->TimeIO->tr_node.io_Device;

  Timer->EClockFreq = ReadEClock(&Timer->LastFrameTime);

  return TRUE;
}


VOID RemoveTimer(VOID)
{

  if(Timer)
  {
    if(Timer->TimeIO)
    {
      if(TimerBase)
        CloseDevice((struct IORequest *)Timer->TimeIO);

      free(Timer->TimeIO);
    }

    free(Timer);
  }
}


VOID FrameEvent(VOID)
{
struct EClockVal TmpEClock;

  ReadEClock(&TmpEClock);

  DiffEClock(&Timer->LastFrameTime, &TmpEClock);

	Timer->FrameTime = TmpEClock.ev_lo;

	if(TmpEClock.ev_lo)
		Timer->FPS = (DOUBLE)Timer->EClockFreq /
								 (DOUBLE)TmpEClock.ev_lo;
}


ULONG GetFrameTime(VOID)
{
	return Timer->FrameTime;
}


VOID XEvent(VOID)
{
struct EClockVal TmpEClock;

  ReadEClock(&TmpEClock);

  DiffEClock(&Timer->LastXTime, &TmpEClock);

	Timer->XTime = TmpEClock.ev_lo;
}


ULONG GetXTime(VOID)
{
	return Timer->XTime;
}


ULONG GetCurrentXTime(VOID)
{
struct EClockVal TmpEClock;
struct EClockVal Tmp2EClock;

  ReadEClock(&TmpEClock);

	Tmp2EClock.ev_hi = Timer->LastXTime.ev_hi;
	Tmp2EClock.ev_lo = Timer->LastXTime.ev_lo;

  DiffEClock(&Tmp2EClock, &TmpEClock);

	return TmpEClock.ev_lo;
}


VOID RenderInfoBar(struct RastPort *RP, ULONG Pen)
{

  sprintf(InfoText, "Speed: %6.2f fps", Timer->FPS);

  memset(&InfoText[strlen(InfoText)], ' ', 40-strlen(InfoText));

  SetAPen(RP, Pen);
  SetDrMd(RP, JAM1);
  Move(RP, 0, 7);
  Text(RP, InfoText, 40);
}
