added 3dengfx into the repo, probably not the correct version for this
[summerhack] / src / 3dengfx / src / common / timer.c
1 /*
2 Copyright 2004 John Tsiombikas <nuclear@siggraph.org>
3
4 This is a cross-platform millisecond resolution timer library.
5
6 This library is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 This library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this library; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19 */
20
21 #if defined(__unix__) || defined(unix)
22 #include <time.h>
23 #include <sys/time.h>
24
25 #else   /* assume win32 */
26 #include <windows.h>
27
28 #endif  /* __unix__ */
29
30 #include "timer.h"
31
32 /* BEWARE: this function will not work correctly if we go back in time
33  * and try to use it during the first second of 1-1-1970
34  */
35 static unsigned long sys_get_msec(void) {
36 #if defined(__unix__) || defined(unix)
37         static struct timeval timeval, first_timeval;
38         
39         gettimeofday(&timeval, 0);
40
41         if(first_timeval.tv_sec == 0) {
42                 first_timeval = timeval;
43                 return 0;
44         }
45         return (timeval.tv_sec - first_timeval.tv_sec) * 1000 + (timeval.tv_usec - first_timeval.tv_usec) / 1000;
46 #else
47         return GetTickCount();
48 #endif  /* __unix__ */
49 }
50
51
52 void timer_start(ntimer *timer) {
53         timer->state = TSTATE_RUNNING;
54         timer->stopped_interval += timer_getmsec(timer) - timer->stop;
55         timer->stop = 0;
56 }
57
58 void timer_stop(ntimer *timer) {
59         timer->stop = timer_getmsec(timer);
60         timer->state = TSTATE_PAUSED;
61 }
62
63 void timer_reset(ntimer *timer) {
64         timer->state = TSTATE_RESET;
65         timer->start = sys_get_msec();
66         timer->stop = 0;
67         timer->stopped_interval = 0;
68         timer->offset = 0;
69 }
70
71 void timer_fwd(ntimer *timer, unsigned long msec) {
72         timer->offset += msec;
73         if(timer->state != TSTATE_RUNNING) {
74                 timer->stop += msec;
75         }
76 }
77
78 void timer_back(ntimer *timer, unsigned long msec) {
79         timer->offset -= msec;
80         if(timer->state != TSTATE_RUNNING) {
81                 timer->stop -= msec;
82         }
83 }
84
85 #define MAX(a, b)       ((a) > (b) ? (a) : (b))
86
87 unsigned long timer_getmsec(ntimer *timer) {
88         if(timer->state == TSTATE_RUNNING) {
89                 long time = (long)sys_get_msec() - timer->start - timer->stopped_interval + timer->offset;
90                 if(time < 0) {
91                         timer_reset(timer);
92                         timer_start(timer);
93                         return 0;
94                 }
95                 return time;
96         } else {
97                 return MAX(timer->stop, 0);
98         }
99         return 0;       /* can't happen */
100 }
101
102 unsigned long timer_getsec(ntimer *timer) {
103         return timer_getmsec(timer) / 1000;
104 }