2 SDL - Simple DirectMedia Layer
3 Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 Sam Lantinga
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public
7 License as published by the Free Software Foundation; either
8 version 2 of the License, or (at your option) any later version.
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 Library General Public License for more details.
15 You should have received a copy of the GNU Library General Public
16 License along with this library; if not, write to the Free
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 #define __TIMER_NOLIBBASE__
29 #define __GRAPHICS_NOLIBBASE__
38 #include <exec/types.h>
40 #include <proto/dos.h>
41 #include <clib/graphics_protos.h>
42 #include <pragmas/graphics.h>
43 #include <clib/exec_protos.h>
44 #include <pragmas/exec.h>
45 #elif defined(WARPOS) || defined(__AROS__)
46 #include <proto/dos.h>
47 #include <proto/exec.h>
48 #include <proto/graphics.h>
50 #include <inline/dos.h>
51 #include <inline/exec.h>
52 #include <inline/graphics.h>
56 extern struct DosLibrary
*DOSBase
;
57 extern struct ExecBase
*SysBase
;
58 static struct GfxBase
*GfxBase
;
60 #include "SDL_error.h"
61 #include "SDL_timer.h"
62 #include "SDL_timer_c.h"
64 #if defined(DISABLE_THREADS) || defined(FORK_HACK)
68 /* The first ticks value of the application */
70 #if defined (__AROS__) || !defined(__PPC__) || defined(MORPHOS)
76 #include <devices/timer.h>
77 #include <proto/timer.h>
79 static struct timerequest
*TimerIO
= NULL
;
80 static struct Device
*TimerBase
= NULL
;
81 static struct timeval basetime
;
82 static struct MsgPort
*TimerMP
= NULL
;
84 static int fallback
= 0;
86 static void close_timer(void)
88 D(bug("freeing timer resources..."));
90 CloseDevice((struct IORequest
*)TimerIO
);
91 DeleteIORequest((struct IORequest
*)TimerIO
);
95 DeleteMsgPort(TimerMP
);
102 void SDL_StartTicks(void)
105 /* Set first ticks value */
108 struct MsgPort
*TimerMP
;
110 if (TimerBase
|| fallback
) return;
112 if (!(TimerMP
= CreateMsgPort())) {
118 if (!(TimerIO
= (struct timerequest
*)
119 CreateIORequest(TimerMP
, sizeof(struct timerequest
)))) {
120 DeleteMsgPort(TimerMP
);
126 if (OpenDevice("timer.device", UNIT_VBLANK
, &TimerIO
->tr_node
, 0)) {
127 DeleteMsgPort(TimerMP
);
128 DeleteIORequest((struct IORequest
*)TimerIO
);
134 TimerBase
= TimerIO
->tr_node
.io_Device
;
135 D(bug("Timer resource allocated.\n"));
137 GetSysTime(&basetime
);
138 D(bug("Basetime: %lusecs %lumicro\n", basetime
.tv_secs
, basetime
.tv_micro
));
147 Uint32
SDL_GetTicks (void)
156 #if CLOCKS_PER_SEC == 1000
159 return ticks
*(1000/CLOCKS_PER_SEC
);
170 if(basetime
.tv_micro
> tv
.tv_micro
) {
173 tv
.tv_micro
+= 1000000;
175 tics
= ((tv
.tv_secs
- basetime
.tv_secs
) * 1000) +
176 ((tv
.tv_micro
- basetime
.tv_micro
)/1000);
183 void SDL_Delay (Uint32 ms
)
185 // Do a busy wait if time is less than 50ms
190 clock_t to_wait
=clock();
191 // most archs have clocks per sec == 1000
192 #if CLOCKS_PER_SEC != 1000
193 ms
*=(CLOCKS_PER_SEC
/1000);
197 while(clock()<to_wait
);
199 Uint32 to_wait
= SDL_GetTicks() + ms
;
201 while(SDL_GetTicks() < to_wait
);
210 #elif defined(WARPOS)
211 /* Use the powerpc.library function GetSysTimePPC to get the time */
214 void SDL_StartTicks(void)
216 /* Set first ticks value */
218 GetSysTimePPC(&tval
);
219 start
= (tval
.tv_secs
*1000 + tval
.tv_micro
/1000);
222 Uint32
SDL_GetTicks (void)
226 GetSysTimePPC(&tval
);
228 ticks
= (tval
.tv_secs
*1000 + tval
.tv_micro
/1000);
230 return (ticks
-start
); /* return time in ms */
233 void SDL_Delay (Uint32 ms
)
235 // Do a busy wait if time is less than 50ms
242 GetSysTimePPC(&tval
);
243 t
= (tval
.tv_secs
*1000000 + tval
.tv_micro
);
244 to_wait
= t
+ (ms
*1000);
247 GetSysTimePPC(&tval
);
248 t
= (tval
.tv_secs
*1000000 + tval
.tv_micro
);
261 ULONG MY_CLOCKS_PER_SEC
;
263 void PPC_TimerInit(void);
268 void SDL_StartTicks(void)
270 /* Set first ticks value */
274 PPCGetTimerObject(MyTimer
,PPCTIMERTAG_CURRENTTICKS
,start
);
276 start
[1]|=((result
[0]&0x3ff)<<22);
280 Uint32
SDL_GetTicks (void)
283 PPCGetTimerObject(MyTimer
,PPCTIMERTAG_CURRENTTICKS
,result
);
285 // PPCAsr64p(result,10);
289 result
[1]|=((result
[0]&0x3ff)<<22);
291 // Non mi interessa piu' result[0]
293 return result
[1]*1000/MY_CLOCKS_PER_SEC
;
296 void SDL_Delay (Uint32 ms
)
298 // Do a busy wait if time is less than 50ms
302 ULONG to_wait
[2],actual
[2];
303 PPCGetTimerObject(MyTimer
,PPCTIMERTAG_CURRENTTICKS
,result
);
305 to_wait
[1]+=ms
*1000/MY_CLOCKS_PER_SEC
;
307 while(actual
[1]<to_wait
[1])
309 PPCGetTimerObject(MyTimer
,PPCTIMERTAG_CURRENTTICKS
,actual
);
318 void PPC_TimerInit(void)
320 struct TagItem tags
[]=
322 PPCTIMERTAG_CPU
,TRUE
,
327 if(MyTimer
=PPCCreateTimerObject(tags
))
331 PPCGetTimerObject(MyTimer
,PPCTIMERTAG_TICKSPERSEC
,result
);
332 D(bug("Timer inizializzato, TPS: %lu - %lu\n",result
[0],result
[1]));
333 // PPCAsr64p(result,10);
335 result
[1]|=((result
[0]&0x3ff)<<22);
338 D(bug("Shiftato TPS: %lu - %lu\n",result
[0],result
[1]));
339 MY_CLOCKS_PER_SEC
=result
[1];
341 PPCGetTimerObject(MyTimer
,PPCTIMERTAG_CURRENTTICKS
,result
);
343 D(bug("Current ticks: %lu - %lu\n",result
[0],result
[1]));
345 result
[1]|=((result
[0]&0x3ff)<<22);
347 // PPCAsr64p(result,10);
348 D(bug("Shiftato: %lu - %lu\n",result
[0],result
[1]));
352 D(bug("Errore nell'inizializzazione del timer!\n"));
358 #include "SDL_thread.h"
360 /* Data to handle a single periodic alarm */
361 static int timer_alive
= 0;
362 static SDL_Thread
*timer_thread
= NULL
;
364 static int RunTimer(void *unused
)
366 D(bug("SYSTimer: Entering RunTimer loop..."));
369 GfxBase
=(struct GfxBase
*)OpenLibrary("graphics.library",37);
371 while ( timer_alive
) {
372 if ( SDL_timer_running
) {
373 SDL_ThreadedTimerCheck();
376 WaitTOF(); // Check the timer every fifth of seconds. Was SDL_Delay(1)->BusyWait!
380 D(bug("SYSTimer: EXITING RunTimer loop..."));
384 /* This is only called if the event thread is not running */
385 int SDL_SYS_TimerInit(void)
387 D(bug("Creating thread for the timer (NOITIMER)...\n"));
390 timer_thread
= SDL_CreateThread(RunTimer
, NULL
);
391 if ( timer_thread
== NULL
)
393 D(bug("Creazione del thread fallita...\n"));
397 return(SDL_SetTimerThreaded(1));
400 void SDL_SYS_TimerQuit(void)
403 if ( timer_thread
) {
404 SDL_WaitThread(timer_thread
, NULL
);
409 int SDL_SYS_StartTimer(void)
411 SDL_SetError("Internal logic error: AmigaOS uses threaded timer");
415 void SDL_SYS_StopTimer(void)