#include <mungal4.hpp>
#pragma hdrstop

#if !defined(L4TIME_HPP)
#	include <l4time.hpp>
#endif

#include <bios.h>
#include <sos.h>

//#############################################################################
//###########################    System Clock    ##############################
//#############################################################################

SystemClock
	SystemClock::timer;
Scalar
	SystemClock::ticksPerSecond;

volatile long fast_time=0L;
WORD timer_handler_handle=0xFFFF;

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	Timer_Handler()
{
	++fast_time;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
long
	SystemClock::GetRTC()
{
	if (timer_handler_handle == 0xFFFF)
	{
		//
		//----------------------------------------------------------------------
		// Read the BIOS time.  If it is less than the value it was last time we
		// read it, then we have crossed midnight.  All the clock values start
		// over again, so we will subtract 24 hours worth of ticks from when we
		// started the application, allowing the application to simply see the
		// clock continue to get bigger, regardless of the boundary condition
		//----------------------------------------------------------------------
		//
		static long last_time=0L;
		long new_time = biostime(0, 0L);
		if (new_time < last_time)
		{
			fast_time -= 1573040L;
		}
		last_time = new_time;
		return new_time - fast_time;
	}
	else
	{
		return fast_time;
	}
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
SystemClock::SystemClock()
{
	//
	//-------------------------------
	// Initialize the timer variables
	//-------------------------------
	//
	pauseStart = 0L;
	pauseTime = 0L;

	//
	//------------------------------
	// Initialize the platform timer
	//------------------------------
	//
	fast_time = 0L;
	char *time_options = getenv(TIMER_ENV);
	if (time_options && !strcmp(time_options,USE_SOS_TIMER))
	{
		#if DEBUG_LEVEL>0
			WORD err = sosTIMERInitSystem(_TIMER_DOS_RATE, _SOS_DEBUG_NORMAL);
			Verify(err == _ERR_NO_ERROR);
			err =
				sosTIMERRegisterEvent(28, Timer_Handler, &timer_handler_handle);
			Verify(err == _ERR_NO_ERROR);
		#else
			sosTIMERInitSystem(_TIMER_DOS_RATE, _SOS_DEBUG_NORMAL);
			sosTIMERRegisterEvent(28, Timer_Handler, &timer_handler_handle);
		#endif
		ticksPerSecond = 28.0f;
	}
	else
	{
		ticksPerSecond = 1193180.0f / 65536.0f;
		fast_time = biostime(0, 0L);
	}
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	SystemClock::Shutdown()
{
	if (timer_handler_handle != 0xFFFF)
	{
	#if DEBUG_LEVEL>0
		WORD err = sosTIMERRemoveEvent(timer_handler_handle);
		Verify(err == _ERR_NO_ERROR);
		err = sosTIMERUnInitSystem(0);
		Verify(err == _ERR_NO_ERROR);
	#else
		sosTIMERRemoveEvent(timer_handler_handle);
		sosTIMERUnInitSystem(0);
	#endif
	}
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
#define TIMER_CONTROL		0x43
#define GET_TIMER0			0xC2
#define TIMER0_PORT			0x40
#define OUTPUT_BIT			0x80

#undef inportb
#undef outportb

float
	Get_Frame_Percent_Used()
{
	outportb(TIMER_CONTROL, GET_TIMER0);
	int half = inportb(TIMER0_PORT) & OUTPUT_BIT;
	int subtick = ((int)inportb(TIMER0_PORT)) >> 1;
	subtick += (((int)inportb(TIMER0_PORT)) << 7);

	if (timer_handler_handle == 0xFFFF)
	{
		subtick += half << 8;
		return (65535 - subtick) / 65536.0f;
	}
	else
	{
		if (half)
		{
			subtick += _wTIMERValue >> 1;
		}
		return (_wTIMERValue - 1 - subtick) / (float)_wTIMERValue;
	}
}

