1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285
|
/*
* Copyright (C) Volition, Inc. 1999. All rights reserved.
*
* All source code herein is the property of Volition, Inc. You may not sell
* or otherwise commercially exploit the source or things you created based on the
* source.
*
*/
#ifdef _WIN32
#include <windows.h>
#else
#include <SDL_timer.h>
#include <sys/time.h>
#endif
#include <limits.h>
#include "globalincs/pstypes.h"
#include "io/timer.h"
#include "graphics/2d.h"
#include "globalincs/alphacolors.h"
#define THREADED // to use the proper set of macros
#include "osapi/osapi.h" // for multi-thread macros
#ifdef _WIN32
static longlong Timer_last_value = 0, Timer_base = 0, Timer_freq = 0;
static const int precision = 1;
#endif
static longlong Timer_perf_counter_base = 0; // perf counter start time
static longlong Timer_perf_counter_freq = 0; // perf counter frequency - number of ticks per second
static int Timer_inited = 0;
static CRITICAL_SECTION Timer_lock;
#define MICROSECONDS_PER_SECOND 1000000
void timer_close()
{
if ( Timer_inited ) {
Timer_inited = 0;
#ifdef _WIN32
timeEndPeriod(precision);
#endif
DELETE_CRITICAL_SECTION( Timer_lock );
}
}
void timer_init()
{
if ( !Timer_inited ) {
INITIALIZE_CRITICAL_SECTION( Timer_lock );
#ifdef _WIN32
timeBeginPeriod(precision);
Timer_base = Timer_last_value = timeGetTime();
// get the performance counter start time
LARGE_INTEGER perf_start_time;
QueryPerformanceCounter(&perf_start_time);
Timer_perf_counter_base = perf_start_time.QuadPart;
// get the performance counter's ticks per second frequency
LARGE_INTEGER perf_frequency;
QueryPerformanceFrequency(&perf_frequency);
Timer_perf_counter_freq = perf_frequency.QuadPart;
#else
timeval time_value;
// get the performance counter start time
gettimeofday(&time_value, NULL);
Timer_perf_counter_base = time_value.tv_sec * MICROSECONDS_PER_SECOND + time_value.tv_usec;
// get the performance counter's ticks per second frequency
Timer_perf_counter_freq = 1;
#endif
Timer_inited = 1;
atexit(timer_close);
}
}
static uint timer_get()
{
#ifdef _WIN32
ENTER_CRITICAL_SECTION( Timer_lock );
longlong time_now;
time_now = timeGetTime();
if ( time_now < Timer_last_value ) {
// the clock has rolled!
Timer_base = time_now;
mprintf(("TIMER ROLLED!\n"));
}
Timer_last_value = time_now;
LEAVE_CRITICAL_SECTION( Timer_lock );
return (uint)(time_now - Timer_base);
#else
return SDL_GetTicks();
#endif
}
fix timer_get_fixed_seconds()
{
if (!Timer_inited) {
Int3(); // Make sure you call timer_init before anything that uses timer functions!
return 0;
}
longlong a = timer_get();
a *= 65536;
return (fix)(a / 1000);
}
fix timer_get_fixed_secondsX()
{
return timer_get_fixed_seconds();
}
fix timer_get_approx_seconds()
{
return timer_get_fixed_seconds();
}
int timer_get_seconds()
{
if (!Timer_inited) {
Int3();
return 0;
}
return (timer_get() / 1000);
}
int timer_get_milliseconds()
{
if (!Timer_inited) {
Int3(); // Make sure you call timer_init before anything that uses timer functions!
return 0;
}
return timer_get();
}
int timer_get_microseconds()
{
if (!Timer_inited) {
Int3(); // Make sure you call timer_init before anything that uses timer functions!
return 0;
}
return timer_get() * 1000;
}
uint timer_get_high_res_microseconds()
{
if ( !Timer_inited ) {
Int3();
return 0;
}
#ifdef _WIN32
ENTER_CRITICAL_SECTION( Timer_lock);
LARGE_INTEGER time;
QueryPerformanceCounter(&time);
longlong elapsed = time.QuadPart;// - Timer_perf_counter_base;
LEAVE_CRITICAL_SECTION( Timer_lock);
return (uint)(elapsed * MICROSECONDS_PER_SECOND / Timer_perf_counter_freq);
#else
timeval time_value;
gettimeofday(&time_value, NULL);
return time_value.tv_sec * MICROSECONDS_PER_SECOND + time_value.tv_usec;// - Timer_perf_counter_base);
#endif
}
// 0 means invalid,
// 1 means always return true
// 2 and above actually check the time
int timestamp_ticker = 2;
void timestamp_reset()
{
timestamp_ticker = 2;
}
// Restrict all time values between 0 and MAX_TIME
// so we don't have to use UINTs to calculate rollover.
// For debugging & testing, you could set this to
// something like 1 minute (6000).
#define MAX_TIME (INT_MAX/2)
void timestamp_inc(int frametime_ms)
{
timestamp_ticker += frametime_ms;
if ( timestamp_ticker > MAX_TIME ) {
timestamp_ticker = 2; // Roll!
}
if (timestamp_ticker < 2 ) {
mprintf(("Whoa!!! timestamp_ticker < 2 -- resetting to 2!!!\n"));
timestamp_ticker = 2;
}
}
int timestamp(int delta_ms )
{
int t2;
if (delta_ms < 0 ) return 0;
if (delta_ms == 0 ) return 1;
t2 = timestamp_ticker + delta_ms;
if ( t2 > MAX_TIME ) {
// wrap!!!
t2 = delta_ms - (MAX_TIME-timestamp_ticker);
}
if (t2 < 2 ) t2 = 2; // hack??
return t2;
}
// Returns milliseconds until timestamp will elapse.
// Negative value gives milliseconds ago that timestamp elapsed.
int timestamp_until(int stamp)
{
// JAS: FIX
// HACK!! This doesn't handle rollover!
// (Will it ever happen?)
return stamp - timestamp_ticker;
/*
uint delta;
delta = stamp - timestamp_ticker;
if (delta > UINT_MAX/2)
delta = UINT_MAX - delta + 1;
else if (delta < - ( (int) (UINT_MAX/2)))
delta = UINT_MAX + delta + 1;
return delta;
*/
}
// alternate timestamp functions. The way these work is you call xtimestamp() to get the
// current counter value, and then call
int timestamp()
{
return timestamp_ticker;
}
int timestamp_has_time_elapsed(int stamp, int time)
{
int t;
if (time <= 0)
return 1;
t = stamp + time;
if (t <= timestamp_ticker)
return 1; // if we are unlucky enough to have it wrap on us, this will assume time has elapsed.
return 0;
}
|