Mercurial > sdl-ios-xcode
annotate src/timer/os2/SDL_systimer.c @ 1551:02e19471a694
Fixed bug #4
[Note: I'm applying this patch since it's a cleaner version of what's already implemented, and supports this controller on older kernels. I'll ask to make sure this doesn't break on the new kernels where it's no longer necessary]
Date: Mon, 21 Mar 2005 09:41:11 -0500
From: Chris Nelson
Subject: SDL Patch
Hey, Ryan.
I submitted the following patch about a year ago. It's just a simple
patch for the linux port, to make multiple joysticks each appear to SDL
as their own device, if they are on the same USB port (specifically,
these guys
<http://www.consoleplus.co.uk/product_info.php?pName=super-joybox-5-quad-joypad-converter>,
which allow 4 Playstation2 controllers to be accessed via a single USB
port). Without this patch, SDL pretty much drops the ball, and reports
that there are 4 joysticks available when less than that number are
plugged in.
My work built upon the work of another person with the same device. When
I submitted the patch to the list, he tested it, but it didn't work for
him, so the patch was never accepted. Maybe about 3 times in the past
year, I've tried to email the guy, to see if he couldn't run my new
version, complete with debug code to diagnose the problem he was having.
He never got back to me.
So, I'm attaching the patch. I wish I knew why it didn't work for him,
but I've been using it for the last year with no problems. Let me know
if you need any more information, or have any ideas as to how I could
test it. I'd like to see it in the tree, but I want to make sure it works.
-Chris
author | Sam Lantinga <slouken@libsdl.org> |
---|---|
date | Sun, 19 Mar 2006 06:31:34 +0000 |
parents | d910939febfa |
children | 92947e3a18db |
rev | line source |
---|---|
1190 | 1 /* |
2 SDL - Simple DirectMedia Layer | |
1312
c9b51268668f
Updated copyright information and removed rcs id lines (problematic in branch merges)
Sam Lantinga <slouken@libsdl.org>
parents:
1190
diff
changeset
|
3 Copyright (C) 1997-2006 Sam Lantinga |
1190 | 4 |
5 This library is free software; you can redistribute it and/or | |
1312
c9b51268668f
Updated copyright information and removed rcs id lines (problematic in branch merges)
Sam Lantinga <slouken@libsdl.org>
parents:
1190
diff
changeset
|
6 modify it under the terms of the GNU Lesser General Public |
1190 | 7 License as published by the Free Software Foundation; either |
1312
c9b51268668f
Updated copyright information and removed rcs id lines (problematic in branch merges)
Sam Lantinga <slouken@libsdl.org>
parents:
1190
diff
changeset
|
8 version 2.1 of the License, or (at your option) any later version. |
1190 | 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 | |
1312
c9b51268668f
Updated copyright information and removed rcs id lines (problematic in branch merges)
Sam Lantinga <slouken@libsdl.org>
parents:
1190
diff
changeset
|
13 Lesser General Public License for more details. |
1190 | 14 |
1312
c9b51268668f
Updated copyright information and removed rcs id lines (problematic in branch merges)
Sam Lantinga <slouken@libsdl.org>
parents:
1190
diff
changeset
|
15 You should have received a copy of the GNU Lesser General Public |
c9b51268668f
Updated copyright information and removed rcs id lines (problematic in branch merges)
Sam Lantinga <slouken@libsdl.org>
parents:
1190
diff
changeset
|
16 License along with this library; if not, write to the Free Software |
c9b51268668f
Updated copyright information and removed rcs id lines (problematic in branch merges)
Sam Lantinga <slouken@libsdl.org>
parents:
1190
diff
changeset
|
17 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
1190 | 18 |
19 Sam Lantinga | |
20 slouken@libsdl.org | |
21 */ | |
1402
d910939febfa
Use consistent identifiers for the various platforms we support.
Sam Lantinga <slouken@libsdl.org>
parents:
1361
diff
changeset
|
22 #include "SDL_config.h" |
1190 | 23 |
24 #define INCL_DOSMISC | |
25 #define INCL_DOSERRORS | |
26 #define INCL_DOSSEMAPHORES | |
27 #define INCL_DOSDATETIME | |
28 #define INCL_DOSPROCESS | |
29 #define INCL_DOSPROFILE | |
30 #define INCL_DOSEXCEPTIONS | |
31 #include <os2.h> | |
32 | |
33 #include "SDL_thread.h" | |
34 #include "SDL_timer.h" | |
1361
19418e4422cb
New configure-based build system. Still work in progress, but much improved
Sam Lantinga <slouken@libsdl.org>
parents:
1358
diff
changeset
|
35 #include "../SDL_timer_c.h" |
1190 | 36 |
37 | |
38 #define TIME_WRAP_VALUE (~(DWORD)0) | |
39 | |
40 /* The first high-resolution ticks value of the application */ | |
41 static long long hires_start_ticks; | |
42 /* The number of ticks per second of the high-resolution performance counter */ | |
43 static ULONG hires_ticks_per_second; | |
44 | |
45 void SDL_StartTicks(void) | |
46 { | |
47 DosTmrQueryFreq(&hires_ticks_per_second); | |
48 DosTmrQueryTime((PQWORD)&hires_start_ticks); | |
49 } | |
50 | |
51 DECLSPEC Uint32 SDLCALL SDL_GetTicks(void) | |
52 { | |
53 long long hires_now; | |
54 ULONG ticks = ticks; | |
55 | |
56 DosTmrQueryTime((PQWORD)&hires_now); | |
57 /* | |
58 hires_now -= hires_start_ticks; | |
59 hires_now *= 1000; | |
60 hires_now /= hires_ticks_per_second; | |
61 */ | |
62 /* inline asm to avoid runtime inclusion */ | |
63 _asm { | |
64 push edx | |
65 push eax | |
66 mov eax, dword ptr hires_now | |
67 mov edx, dword ptr hires_now+4 | |
68 sub eax, dword ptr hires_start_ticks | |
69 sbb edx, dword ptr hires_start_ticks+4 | |
70 mov ebx,1000 | |
71 mov ecx,edx | |
72 mul ebx | |
73 push eax | |
74 push edx | |
75 mov eax,ecx | |
76 mul ebx | |
77 pop eax | |
78 add edx,eax | |
79 pop eax | |
80 mov ebx, dword ptr hires_ticks_per_second | |
81 div ebx | |
82 mov dword ptr ticks, eax | |
83 pop edx | |
84 pop eax | |
85 } | |
86 | |
87 return ticks; | |
88 | |
89 } | |
90 | |
91 /* High resolution sleep, originally made by Ilya Zakharevich */ | |
92 DECLSPEC void SDLCALL SDL_Delay(Uint32 ms) | |
93 { | |
94 /* This is similar to DosSleep(), but has 8ms granularity in time-critical | |
95 threads even on Warp3. */ | |
96 HEV hevEvent1 = 0; /* Event semaphore handle */ | |
97 HTIMER htimerEvent1 = 0; /* Timer handle */ | |
98 APIRET rc = NO_ERROR; /* Return code */ | |
99 int ret = 1; | |
100 ULONG priority = 0, nesting; /* Shut down the warnings */ | |
101 PPIB pib; | |
102 PTIB tib; | |
103 char *e = NULL; | |
104 APIRET badrc; | |
105 int switch_priority = 50; | |
106 | |
107 DosCreateEventSem(NULL, /* Unnamed */ | |
108 &hevEvent1, /* Handle of semaphore returned */ | |
109 DC_SEM_SHARED, /* Shared needed for DosAsyncTimer */ | |
110 FALSE); /* Semaphore is in RESET state */ | |
111 | |
112 if (ms >= switch_priority) | |
113 switch_priority = 0; | |
114 if (switch_priority) | |
115 { | |
116 if (DosGetInfoBlocks(&tib, &pib)!=NO_ERROR) | |
117 switch_priority = 0; | |
118 else | |
119 { | |
120 /* In Warp3, to switch scheduling to 8ms step, one needs to do | |
121 DosAsyncTimer() in time-critical thread. On laters versions, | |
122 more and more cases of wait-for-something are covered. | |
123 | |
124 It turns out that on Warp3fp42 it is the priority at the time | |
125 of DosAsyncTimer() which matters. Let's hope that this works | |
126 with later versions too... XXXX | |
127 */ | |
128 priority = (tib->tib_ptib2->tib2_ulpri); | |
129 if ((priority & 0xFF00) == 0x0300) /* already time-critical */ | |
130 switch_priority = 0; | |
131 /* Make us time-critical. Just modifying TIB is not enough... */ | |
132 /* tib->tib_ptib2->tib2_ulpri = 0x0300;*/ | |
133 /* We do not want to run at high priority if a signal causes us | |
134 to longjmp() out of this section... */ | |
135 if (DosEnterMustComplete(&nesting)) | |
136 switch_priority = 0; | |
137 else | |
138 DosSetPriority(PRTYS_THREAD, PRTYC_TIMECRITICAL, 0, 0); | |
139 } | |
140 } | |
141 | |
142 if ((badrc = DosAsyncTimer(ms, | |
143 (HSEM) hevEvent1, /* Semaphore to post */ | |
144 &htimerEvent1))) /* Timer handler (returned) */ | |
145 e = "DosAsyncTimer"; | |
146 | |
147 if (switch_priority && tib->tib_ptib2->tib2_ulpri == 0x0300) | |
148 { | |
149 /* Nobody switched priority while we slept... Ignore errors... */ | |
150 /* tib->tib_ptib2->tib2_ulpri = priority; */ /* Get back... */ | |
151 if (!(rc = DosSetPriority(PRTYS_THREAD, (priority>>8) & 0xFF, 0, 0))) | |
152 rc = DosSetPriority(PRTYS_THREAD, 0, priority & 0xFF, 0); | |
153 } | |
154 if (switch_priority) | |
155 rc = DosExitMustComplete(&nesting); /* Ignore errors */ | |
156 | |
157 /* The actual blocking call is made with "normal" priority. This way we | |
158 should not bother with DosSleep(0) etc. to compensate for us interrupting | |
159 higher-priority threads. The goal is to prohibit the system spending too | |
160 much time halt()ing, not to run us "no matter what". */ | |
161 if (!e) /* Wait for AsyncTimer event */ | |
162 badrc = DosWaitEventSem(hevEvent1, SEM_INDEFINITE_WAIT); | |
163 | |
164 if (e) ; /* Do nothing */ | |
165 else if (badrc == ERROR_INTERRUPT) | |
166 ret = 0; | |
167 else if (badrc) | |
168 e = "DosWaitEventSem"; | |
169 if ((rc = DosCloseEventSem(hevEvent1)) && !e) { /* Get rid of semaphore */ | |
170 e = "DosCloseEventSem"; | |
171 badrc = rc; | |
172 } | |
173 if (e) | |
174 { | |
175 SDL_SetError("[SDL_Delay] : Had error in %s(), rc is 0x%x\n", e, badrc); | |
176 } | |
177 } | |
178 | |
179 /* Data to handle a single periodic alarm */ | |
180 static int timer_alive = 0; | |
181 static SDL_Thread *timer = NULL; | |
182 | |
183 static int RunTimer(void *unused) | |
184 { | |
185 DosSetPriority(PRTYS_THREAD, PRTYC_TIMECRITICAL, 0, 0); | |
186 while ( timer_alive ) { | |
187 if ( SDL_timer_running ) { | |
188 SDL_ThreadedTimerCheck(); | |
189 } | |
190 SDL_Delay(10); | |
191 } | |
192 return(0); | |
193 } | |
194 | |
195 /* This is only called if the event thread is not running */ | |
196 int SDL_SYS_TimerInit(void) | |
197 { | |
198 timer_alive = 1; | |
199 timer = SDL_CreateThread(RunTimer, NULL); | |
200 if ( timer == NULL ) | |
201 return(-1); | |
202 return(SDL_SetTimerThreaded(1)); | |
203 } | |
204 | |
205 void SDL_SYS_TimerQuit(void) | |
206 { | |
207 timer_alive = 0; | |
208 if ( timer ) { | |
209 SDL_WaitThread(timer, NULL); | |
210 timer = NULL; | |
211 } | |
212 } | |
213 | |
214 int SDL_SYS_StartTimer(void) | |
215 { | |
216 SDL_SetError("Internal logic error: OS/2 uses threaded timer"); | |
217 return(-1); | |
218 } | |
219 | |
220 void SDL_SYS_StopTimer(void) | |
221 { | |
222 return; | |
223 } | |
224 | |
225 |