//
// Asura_Platform_Timers.cpp
//
// Created by KJFL - Wednesday, February 18, 2004
//
// Copyright (C) 2004 Rebellion, All Rights Reserved.
//

#include "Core/Asura.h"

// This file's header.
#include "Core/Asura_Timers.h"

#include <kernel.h>

// C O N S T A N T S /////////////////////////////////////////////////////////
static const u_int uASURA_PSP_MAX_TICKS = 0xffffffff;
static const float fASURA_PSP_TICKS_PER_SECOND = 1000000.0f;

// I N T E R N A L   G L O B A L S ///////////////////////////////////////////
static u_int g_uLastTickCount;

// I N T E R N A L   F U N C T I O N S ///////////////////////////////////////
static u_int Asura_PSP_GetCurrentTickCount()
{
	return sceKernelGetSystemTimeLow();
}

// copied from PS2 code
static u_int Asura_PSP_GetElapsedTicks(u_int uStartCycles, u_int uEndCycles)
{
	// handle one timer wrap (about every 71 minutes)
	return( uEndCycles >= uStartCycles ? uEndCycles - uStartCycles : uEndCycles + (uASURA_PSP_MAX_TICKS - uStartCycles) );
}

// copied from PS2 code
static float Asura_PSP_ConvertTicksToSeconds(u_int uCycles)
{
    // Avoid software u_int->float conversion while retaining full range...
    u_int uTopBit = uCycles & 0x80000000u;
    uCycles &= 0x7FFFFFFFu;
    float fCycles = static_cast<int>( uCycles );
    if( uTopBit ) { fCycles += 2147483648.0f; }

    return( fCycles / fASURA_PSP_TICKS_PER_SECOND );
}

// C L A S S   I M P L E M E N T A T I O N ///////////////////////////////////
void Asura_Timers::Platform_Initialise()
{}

void Asura_Timers::Platform_Reset()
{
	g_uLastTickCount = Asura_PSP_GetCurrentTickCount();
}


void Asura_Timers::Platform_Shutdown()
{}


void Asura_Timers::Platform_Update()
{
	// Rotate the threads to see if anybody else needs to run e.g. atrac playing, file-cache loading
	sceKernelRotateThreadReadyQueue(SCE_KERNEL_TPRI_RUN);
}

u_int Asura_Timers::Platform_GetTicksThisFrame()
{
	u_int uNewCycleCount = Asura_PSP_GetCurrentTickCount();
    u_int uDuration      = Asura_PSP_GetElapsedTicks( g_uLastTickCount, uNewCycleCount );
	g_uLastTickCount	 = uNewCycleCount;
	return uDuration;
}

u_int Asura_Timers::Platform_GetTicksInFrame()
{
	return Asura_PSP_GetElapsedTicks(g_uLastTickCount, Asura_PSP_GetCurrentTickCount());
}

float Asura_Timers::Platform_GetTickFrequency()
{
	return fASURA_PSP_TICKS_PER_SECOND;
}


float Asura_Timers::Platform_GetDefaultFrameRate()
{
	return 60.0f;
}

Asura_TickCount Asura_Timers::Platform_GetCurTicks()
{
	return Asura_PSP_GetCurrentTickCount();
}

Asura_TickCount Asura_Timers::Platform_GetElapsedTicks(Asura_TickCount xStartTicks)
{
	return Asura_PSP_GetElapsedTicks(xStartTicks, Asura_PSP_GetCurrentTickCount());
}

float Asura_Timers::Platform_TicksToSeconds(Asura_TickCount xTicks)
{
	return Asura_PSP_ConvertTicksToSeconds(xTicks);
}

Asura_TickCount Asura_Timers::Platform_SecondsToTicks(float fSeconds)
{
	return static_cast<Asura_TickCount>(fSeconds * fASURA_PSP_TICKS_PER_SECOND);
}


/// End of file. ///
