00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #include "aa_config.h"
00029
00030 #include "tSysTime.h"
00031 #include "tRecorder.h"
00032 #include "tError.h"
00033 #include "tConsole.h"
00034 #include "tConfiguration.h"
00035 #include "tLocale.h"
00036
00037 #if HAVE_UNISTD_H
00038 #include <unistd.h>
00039 #endif
00040
00041
00042
00044 struct tTime
00045 {
00046 int microseconds;
00047 int seconds;
00048
00049 #define NORMALIZER 1000000
00050
00051 tTime(): microseconds(0), seconds(0){}
00052
00054 void Normalize()
00055 {
00056 int overflow = microseconds / NORMALIZER;
00057 microseconds -= overflow * NORMALIZER;
00058 seconds += overflow;
00059
00060 while ( microseconds < 0 )
00061 {
00062 microseconds += NORMALIZER;
00063 seconds --;
00064 }
00065 }
00066
00067 tTime operator + ( const tTime & other )
00068 {
00069 tTime ret;
00070 ret.microseconds = other.microseconds + microseconds;
00071 ret.seconds = other.seconds + seconds;
00072
00073 ret.Normalize();
00074 return ret;
00075 }
00076
00077 tTime operator - ( const tTime & other )
00078 {
00079 tTime ret;
00080 ret.microseconds = -other.microseconds + microseconds;
00081 ret.seconds = -other.seconds + seconds;
00082
00083 ret.Normalize();
00084 return ret;
00085 }
00086 };
00087
00088
00089 #ifdef WIN32
00090 #include <windows.h>
00091 #include <sys/timeb.h>
00092 #ifndef DEDICATED
00093 #include "rSDL.h"
00094 #endif
00095
00096
00097 static bool st_hpcReliable = true;
00098
00099 void GetTimeInner( tTime & time )
00100 {
00101 LARGE_INTEGER mtime,frq;
00102
00103
00104 if (!QueryPerformanceFrequency(&frq))
00105 {
00106 st_hpcReliable = false;
00107 }
00108
00109 if (st_hpcReliable)
00110 {
00111 QueryPerformanceCounter(&mtime);
00112 time.seconds = mtime.QuadPart/frq.QuadPart;
00113 time.microseconds = ( ( mtime.QuadPart - time.seconds * frq.QuadPart ) * 1000000 ) / frq.QuadPart;
00114 }
00115 else
00116 {
00117
00118 struct _timeb tstruct;
00119 _ftime( &tstruct );
00120 time.microseconds = tstruct.millitm*1000;
00121 time.seconds = tstruct.time;
00122 }
00123
00124 time.Normalize();
00125 }
00126
00127 void GetTime( tTime & relative )
00128 {
00129 tTime time;
00130 GetTimeInner( time );
00131 static tTime start = time;
00132 relative = time - start;
00133
00134
00135 if ( st_hpcReliable )
00136 {
00137 static struct tTime lastTime = relative;
00138
00139
00140
00141
00142
00143 if ( (time - lastTime).seconds < 0 )
00144 {
00145 st_hpcReliable = false;
00146
00147 GetTimeInner( time );
00148 start = start + time - lastTime;
00149 relative = time - start;
00150 }
00151 lastTime = time;
00152 }
00153 }
00154
00156 bool tTimerIsAccurate()
00157 {
00158 return st_hpcReliable;
00159 }
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176 static unsigned int sleep_rest=0;
00177 void usleep(int x)
00178 {
00179 sleep_rest+=x;
00180 unsigned int r=sleep_rest/1000;
00181 #ifndef DEDICATED
00182 SDL_Delay(r);
00183 #else
00184
00185 #ifdef DEBUG
00186 double tb = tSysTimeFloat();
00187 #endif
00188
00189 SleepEx(r,false);
00190
00191 #ifdef DEBUG
00192 double ta = tSysTimeFloat();
00193 if ((tb-ta) > r*.01)
00194 {
00195 int x;
00196 x = 1;
00197 }
00198 #endif
00199
00200 #endif
00201 sleep_rest-=r*1000;
00202 }
00203
00204 #else
00205
00206 #include <sys/time.h>
00207
00208 void GetTime( tTime & time )
00209 {
00210 struct timeval tp;
00211 struct timezone tzp;
00212
00213 gettimeofday(&tp, &tzp);
00214
00215 time.microseconds = tp.tv_usec;
00216 time.seconds = tp.tv_sec;
00217
00218 time.Normalize();
00219 }
00220
00222 bool tTimerIsAccurate()
00223 {
00224 return true;
00225 }
00226
00227 #endif
00228
00229 static char const * recordingSection = "T";
00230
00231 template< class Archiver > class TimeArchiver
00232 {
00233 public:
00234 static bool Archive( tTime & time )
00235 {
00236
00237 Archiver archive;
00238 if ( archive.Initialize( recordingSection ) )
00239 {
00240 archive.Archive( time.seconds ).Archive( time.microseconds );
00241 return true;
00242 }
00243
00244 return false;
00245 }
00246 };
00247
00248 static struct tTime timeStart;
00249 static struct tTime timeRelative;
00250
00251 void tAdvanceFrameSys( tTime & start, tTime & relative )
00252 {
00253 struct tTime time;
00254
00255
00256 GetTime( time );
00257
00258
00259
00260
00261
00262 if ( start.microseconds == 0 && start.seconds == 0 )
00263 {
00264 start = time;
00265 }
00266
00267
00268 tTime newRelative = time - start;
00269 tTime timeStep = newRelative - relative;
00270 if ( !tRecorder::IsPlayingBack() && ( timeStep.seconds < 0 || timeStep.seconds > 10 ) )
00271 {
00272 static bool warn = true;
00273 if ( warn )
00274 {
00275 warn = false;
00276 con << tOutput( "$timer_hickup", float( timeStep.seconds + timeStep.microseconds * 1E-6 ) );
00277 }
00278
00279 start = start + timeStep;
00280 }
00281 else
00282 {
00283 relative = newRelative;
00284 }
00285
00286
00287 if ( relative.seconds > 20 )
00288 {
00289 int x;
00290 x = 0;
00291 }
00292 }
00293
00294 static bool s_delayedInPlayback = false;
00295 void tDelay( int usecdelay )
00296 {
00297
00298 if ( ! tRecorder::IsPlayingBack() )
00299 usleep( usecdelay );
00300 else
00301 s_delayedInPlayback = true;
00302 }
00303
00304 void tDelayForce( int usecdelay )
00305 {
00306
00307 if ( !s_delayedInPlayback )
00308 usleep( usecdelay );
00309 else
00310 {
00311
00312
00313 tTime timeDelay;
00314 timeDelay.microseconds = usecdelay;
00315 timeStart = timeStart - timeDelay;
00316 }
00317
00318 s_delayedInPlayback = false;
00319 }
00320
00321 void tAdvanceFrame( int usecdelay )
00322 {
00323
00324 if ( usecdelay > 0 )
00325 tDelay( usecdelay );
00326
00327 static tTime timeNewRelative;
00328 tAdvanceFrameSys( timeStart, timeNewRelative );
00329
00330
00331
00332 if ( TimeArchiver< tPlaybackBlock >::Archive( timeRelative ) )
00333 {
00334
00335
00336
00337 timeStart = timeStart + timeNewRelative - timeRelative;
00338 }
00339 else
00340 {
00341
00342 tASSERT( !tRecorder::IsPlayingBack() );
00343
00344 #ifdef FIXED_FRAMERATE
00345 tTime fixed, catchup, timeFixedRelative;
00346 fixed.seconds = 0;
00347 fixed.microseconds = (int)(1000000. / FIXED_FRAMERATE);
00348 timeFixedRelative = timeRelative + fixed;
00349
00350 catchup = timeFixedRelative - timeNewRelative;
00351 if (catchup.seconds >= 0) {
00352 #ifdef DEBUG
00353 printf("catching up %d.%d seconds\n", catchup.seconds, catchup.microseconds);
00354 #endif
00355 for (int i = catchup.seconds; i; --i)
00356 tDelay(1000000);
00357 tDelay(catchup.microseconds);
00358 timeNewRelative = timeFixedRelative;
00359 } else {
00360 printf("WARNING: Real time ahead of game time!\nreal: %d.%06d\ngame: %d.%06d\ncatchup: %d.%06d\n", timeNewRelative.seconds, timeNewRelative.microseconds, timeFixedRelative.seconds, timeFixedRelative.microseconds, 1 - catchup.seconds, 1000000 - catchup.microseconds);
00361 #ifdef FIXED_FRAMERATE_PRIORITY
00362 timeNewRelative = timeFixedRelative;
00363 #endif
00364 }
00365 #endif
00366
00367
00368 timeRelative = timeNewRelative;
00369 }
00370
00371
00372 TimeArchiver< tRecordingBlock >::Archive( timeRelative );
00373 #ifdef DEBUG
00374 {
00375 if ( timeRelative.microseconds == 337949 && timeRelative.seconds == 25 )
00376 {
00377 st_Breakpoint();
00378 }
00379 }
00380 #endif
00381 }
00382
00383 static float st_timeFactor = 1.0;
00384 static tSettingItem< float > st_timeFactorConf( "TIME_FACTOR", st_timeFactor );
00385
00386 double tSysTimeFloat ()
00387 {
00388 #ifdef DEBUG
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401 #endif
00402
00403 return ( timeRelative.seconds + timeRelative.microseconds*1E-6 ) * st_timeFactor;
00404 }
00405
00406 static struct tTime timeRealStart;
00407 static struct tTime timeRealRelative;
00408
00409 double tRealSysTimeFloat ()
00410 {
00411
00412 tAdvanceFrameSys( timeRealStart, timeRealRelative );
00413 return ( timeRealRelative.seconds + timeRealRelative.microseconds*1E-6 ) * st_timeFactor;
00414 }