e14743d1 |
1 | /* |
2 | SDL - Simple DirectMedia Layer |
3 | Copyright (C) 1997-2009 Sam Lantinga |
4 | |
5 | This library is free software; you can redistribute it and/or |
6 | modify it under the terms of the GNU Lesser General Public |
7 | License as published by the Free Software Foundation; either |
8 | version 2.1 of the License, or (at your option) any later version. |
9 | |
10 | This library is distributed in the hope that it will be useful, |
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
13 | Lesser General Public License for more details. |
14 | |
15 | You should have received a copy of the GNU Lesser General Public |
16 | License along with this library; if not, write to the Free Software |
17 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
18 | |
19 | Sam Lantinga |
20 | slouken@libsdl.org |
21 | */ |
22 | #include "SDL_config.h" |
23 | |
24 | #ifdef SDL_TIMER_WINCE |
25 | |
26 | #define WIN32_LEAN_AND_MEAN |
27 | #include <windows.h> |
28 | #include <mmsystem.h> |
29 | |
30 | #include "SDL_thread.h" |
31 | #include "SDL_timer.h" |
32 | #include "../SDL_timer_c.h" |
33 | |
34 | static Uint64 start_date; |
35 | static Uint64 start_ticks; |
36 | |
37 | static Uint64 wce_ticks(void) |
38 | { |
39 | return((Uint64)GetTickCount()); |
40 | } |
41 | |
42 | static Uint64 wce_date(void) |
43 | { |
44 | union |
45 | { |
46 | FILETIME ftime; |
47 | Uint64 itime; |
48 | } ftime; |
49 | SYSTEMTIME stime; |
50 | |
51 | GetSystemTime(&stime); |
52 | SystemTimeToFileTime(&stime,&ftime.ftime); |
53 | ftime.itime/=10000; // Convert 100ns intervals to 1ms intervals |
54 | // Remove ms portion, which can't be relied on |
55 | ftime.itime -= (ftime.itime % 1000); |
56 | return(ftime.itime); |
57 | } |
58 | |
59 | static Sint32 wce_rel_ticks(void) |
60 | { |
61 | return((Sint32)(wce_ticks()-start_ticks)); |
62 | } |
63 | |
64 | static Sint32 wce_rel_date(void) |
65 | { |
66 | return((Sint32)(wce_date()-start_date)); |
67 | } |
68 | |
69 | /* Return time in ms relative to when SDL was started */ |
70 | Uint32 SDL_GetTicks() |
71 | { |
72 | Sint32 offset=wce_rel_date()-wce_rel_ticks(); |
73 | if((offset < -1000) || (offset > 1000)) |
74 | { |
75 | // fprintf(stderr,"Time desync(%+d), resyncing\n",offset/1000); |
76 | start_ticks-=offset; |
77 | } |
78 | |
79 | return((Uint32)wce_rel_ticks()); |
80 | } |
81 | |
82 | /* Give up approx. givem milliseconds to the OS. */ |
83 | void SDL_Delay(Uint32 ms) |
84 | { |
85 | Sleep(ms); |
86 | } |
87 | |
88 | /* Recard start-time of application for reference */ |
89 | void SDL_StartTicks(void) |
90 | { |
91 | start_date=wce_date(); |
92 | start_ticks=wce_ticks(); |
93 | } |
94 | |
95 | static UINT WIN_timer; |
96 | |
97 | #if ( _WIN32_WCE <= 420 ) |
98 | |
99 | static HANDLE timersThread = 0; |
100 | static HANDLE timersQuitEvent = 0; |
101 | |
102 | DWORD TimersThreadProc(void *data) |
103 | { |
104 | while(WaitForSingleObject(timersQuitEvent, 10) == WAIT_TIMEOUT) |
105 | { |
106 | SDL_ThreadedTimerCheck(); |
107 | } |
108 | return 0; |
109 | } |
110 | |
111 | int SDL_SYS_TimerInit(void) |
112 | { |
113 | // create a thread to process a threaded timers |
114 | // SetTimer does not suit the needs because |
115 | // TimerCallbackProc will be called only when WM_TIMER occured |
116 | |
117 | timersQuitEvent = CreateEvent(0, TRUE, FALSE, 0); |
118 | if( !timersQuitEvent ) |
119 | { |
120 | SDL_SetError("Cannot create event for timers thread"); |
121 | return -1; |
122 | } |
123 | timersThread = CreateThread(NULL, 0, TimersThreadProc, 0, 0, 0); |
124 | if( !timersThread ) |
125 | { |
126 | SDL_SetError("Cannot create timers thread, check amount of RAM available"); |
127 | return -1; |
128 | } |
129 | SetThreadPriority(timersThread, THREAD_PRIORITY_HIGHEST); |
130 | |
131 | return(SDL_SetTimerThreaded(1)); |
132 | } |
133 | |
134 | void SDL_SYS_TimerQuit(void) |
135 | { |
136 | SetEvent(timersQuitEvent); |
137 | if( WaitForSingleObject(timersThread, 2000) == WAIT_TIMEOUT ) |
138 | TerminateThread(timersThread, 0); |
139 | CloseHandle(timersThread); |
140 | CloseHandle(timersQuitEvent); |
141 | return; |
142 | } |
143 | |
144 | #else |
145 | |
146 | #pragma comment(lib, "mmtimer.lib") |
147 | |
148 | /* Data to handle a single periodic alarm */ |
149 | static UINT timerID = 0; |
150 | |
151 | static void CALLBACK HandleAlarm(UINT uID, UINT uMsg, DWORD dwUser, |
152 | DWORD dw1, DWORD dw2) |
153 | { |
154 | SDL_ThreadedTimerCheck(); |
155 | } |
156 | |
157 | |
158 | int SDL_SYS_TimerInit(void) |
159 | { |
160 | MMRESULT result; |
161 | |
162 | /* Set timer resolution */ |
163 | result = timeBeginPeriod(TIMER_RESOLUTION); |
164 | if ( result != TIMERR_NOERROR ) { |
165 | SDL_SetError("Warning: Can't set %d ms timer resolution", |
166 | TIMER_RESOLUTION); |
167 | } |
168 | /* Allow 10 ms of drift so we don't chew on CPU */ |
169 | timerID = timeSetEvent(TIMER_RESOLUTION,1,HandleAlarm,0,TIME_PERIODIC); |
170 | if ( ! timerID ) { |
171 | SDL_SetError("timeSetEvent() failed"); |
172 | return(-1); |
173 | } |
174 | return(SDL_SetTimerThreaded(1)); |
175 | } |
176 | |
177 | void SDL_SYS_TimerQuit(void) |
178 | { |
179 | if ( timerID ) { |
180 | timeKillEvent(timerID); |
181 | } |
182 | timeEndPeriod(TIMER_RESOLUTION); |
183 | } |
184 | |
185 | #endif |
186 | |
187 | int SDL_SYS_StartTimer(void) |
188 | { |
189 | SDL_SetError("Internal logic error: WinCE uses threaded timer"); |
190 | return(-1); |
191 | } |
192 | |
193 | void SDL_SYS_StopTimer(void) |
194 | { |
195 | return; |
196 | } |
197 | |
198 | #endif /* SDL_TIMER_WINCE */ |