/****************************************************************************
*
* Ultra Long Period Timer
*
* Copyright (C) 1993-4 SciTech Software
* All rights reserved.
*
* Filename: $Workfile: ulztimer.c $
* Version: $Revision: 1.0 $
*
* Language: ANSI C
* Environment: IBM PC (MSDOS and Windows)
*
* Description: Module to interface to the BIOS Timer Tick for timing
* code that takes up to 24 hours (ray tracing etc). There
* is a small overhead in calculating the time, this
* will be negligible for such long periods of time.
*
* $Date: 05 Feb 1996 14:50:22 $ $Author: KendallB $
*
****************************************************************************/
#include "ztimer.h"
#include "pmode.h"
#ifdef __WINDOWS32__
#undef TRUE
#undef FALSE
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <mmsystem.h>
/* Win32 compatability routines. Win32 apps cannot program the timer and
* ToolHelp is not available. However we can use the timeGetTime() function
* to get the current time in ms since Windows started
*/
PRIVATE ulong tmStart,tmEnd;
PRIVATE ulong start,finish;
void ZTimerInit(void) {}
void _ASMAPI LZTimerOn(void)
{ tmStart = timeGetTime(); }
ulong _ASMAPI LZTimerLap(void)
{
ulong tmLap = timeGetTime();
return (tmLap - tmStart) * 1000L;
}
void _ASMAPI LZTimerOff(void)
{ tmEnd = timeGetTime(); }
ulong _ASMAPI LZTimerCount(void)
{ return (tmEnd - tmStart) * 1000L; }
void ULZTimerOn(void)
{ start = timeGetTime(); }
void ULZTimerOff(void)
{ finish = timeGetTime(); }
ulong ULZTimerLap(void)
{ return (timeGetTime() - start); }
ulong ULZTimerCount(void)
{ return (start - finish); }
float ULZTimerResolution(void)
{ return 0.001; }
#elif defined(__WINDOWS16__)
#undef TRUE
#undef FALSE
#include <windows.h>
#include <toolhelp.h>
/* 16 bit Windows compatability routines. Rather than reading the timer
* directly under Windows, we use the Windows API routines (which only
* provide an accuracy of 1ms however). The timer interrupts are virtualised
* under windows, which causes us to get incorrect results if we program
* the timer directly.
*/
PRIVATE TIMERINFO tmStart,tmEnd,tmLap;
PRIVATE TIMERINFO start,finish;
void ZTimerInit(void)
{
tmStart.dwSize = tmEnd.dwSize = tmLap.dwSize = sizeof(TIMERINFO);
start.dwSize = finish.dwSize = sizeof(TIMERINFO);
}
void _ASMAPI LZTimerOn(void)
{ TimerCount(&tmStart); }
ulong _ASMAPI LZTimerLap(void)
{
TimerCount(&tmLap);
return (tmLap.dwmsSinceStart - tmStart.dwmsSinceStart) * 1000L;
}
void _ASMAPI LZTimerOff(void)
{ TimerCount(&tmEnd); }
ulong _ASMAPI LZTimerCount(void)
{ return (tmEnd.dwmsSinceStart - tmStart.dwmsSinceStart) * 1000L; }
void ULZTimerOn(void)
{ TimerCount(&start); }
void ULZTimerOff(void)
{ TimerCount(&finish); }
ulong ULZTimerLap(void)
{
TimerCount(&tmLap);
return (tmLap.dwmsSinceStart - start.dwmsSinceStart);
}
ulong ULZTimerCount(void)
{ return (finish.dwmsSinceStart - start.dwmsSinceStart); }
float ULZTimerResolution(void)
{ return 0.001; }
#else
PRIVATE ulong start,finish;
ushort _ASMAPI _ZTimerBIOS;
void _ASMAPI LZ_disable(void);
void _ASMAPI LZ_enable(void);
void ZTimerInit(void)
{ _ZTimerBIOS = PM_getBIOSSelector(); }
void ULZTimerOn(void)
{ start = ULZReadTime(); }
void ULZTimerOff(void)
{ finish = ULZReadTime(); }
ulong ULZTimerLap(void)
{ return ULZElapsedTime(start,ULZReadTime()); }
ulong ULZTimerCount(void)
{ return ULZElapsedTime(start,finish); }
ulong ULZReadTime(void)
/****************************************************************************
*
* Function: ULZReadTime
* Returns: Current timer tick count.
*
* Description: We turn of interrupts while we
* get the value from the BIOS data area since it is stored
* as two bytes and an interrupt COULD stuff up our reading.
*
****************************************************************************/
{
ulong ticks;
LZ_disable(); /* Turn of interrupts */
ticks = PM_getLong(_ZTimerBIOS,0x6C);
LZ_enable(); /* Turn on interrupts again */
return ticks;
}
ulong ULZElapsedTime(ulong start,ulong finish)
/****************************************************************************
*
* Function: ULZElapsedTime
* Parameters: start - Starting timer tick value
* finish - Ending timer tick value
*
* Returns: Elapsed timer between starting time and ending time in
* 1/18 ths of a second.
*
****************************************************************************/
{
/* Check to see whether a midnight boundary has passed, and if so
* adjust the finish time to account for this. We cannot detect if
* more that one midnight boundary has passed, so if this happens
* we will be generating erronous results.
*/
if (finish < start)
finish += 1573040L; /* Number of ticks in 24 hours */
return finish - start;
}
float ULZTimerResolution(void)
/****************************************************************************
*
* Function: ULZTimerResolution
* Returns: Resolution of the ULZTimer routines (seconds in a tick)
*
****************************************************************************/
{
return 0.054925;
}
#endif /* DOS */