1 /* 2 SDL - Simple DirectMedia Layer 3 Copyright (C) 1997-2006 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 (at) libsdl.org 21 */ 22 #include "SDL_config.h" 23 24 #ifdef SDL_TIMER_AMIGA 25 26 #include <stdio.h> 27 #include <time.h> 28 #include <signal.h> 29 #include <unistd.h> 30 #include <string.h> 31 #include <errno.h> 32 #include <exec/types.h> 33 #ifdef __SASC 34 #include <proto/dos.h> 35 #include <clib/graphics_protos.h> 36 #include <pragmas/graphics.h> 37 #include <clib/exec_protos.h> 38 #include <pragmas/exec.h> 39 #elif defined(STORMC4_WOS) 40 #include <proto/dos.h> 41 #include <proto/exec.h> 42 #include <proto/graphics.h> 43 #else 44 #include <inline/dos.h> 45 #include <inline/exec.h> 46 #include <inline/graphics.h> 47 #endif 48 #include "mydebug.h" 49 50 extern struct DosLibrary *DOSBase; 51 extern struct ExecBase *SysBase; 52 static struct GfxBase *GfxBase; 53 54 #include "SDL_timer.h" 55 #include "../SDL_timer_c.h" 56 57 /* The first ticks value of the application */ 58 59 #if !defined(__PPC__) || defined(STORMC4_WOS) || defined(MORPHOS) 60 static clock_t start; 61 62 void SDL_StartTicks(void) 63 { 64 /* Set first ticks value */ 65 start=clock(); 66 } 67 68 Uint32 SDL_GetTicks (void) 69 { 70 clock_t ticks; 71 72 ticks=clock()-start; 73 74 #ifdef __SASC 75 // CLOCKS_PER_SEC == 1000 ! 76 77 return(ticks); 78 #else 79 // CLOCKS_PER_SEC != 1000 ! 80 81 return ticks*(1000/CLOCKS_PER_SEC); 82 #endif 83 } 84 85 void SDL_Delay (Uint32 ms) 86 { 87 // Do a busy wait if time is less than 50ms 88 89 if(ms<50) 90 { 91 clock_t to_wait=clock(); 92 93 #ifndef __SASC 94 ms*=(CLOCKS_PER_SEC/1000); 95 #endif 96 to_wait+=ms; 97 98 while(clock()<to_wait); 99 } 100 else 101 { 102 Delay(ms/20); 103 } 104 } 105 106 #else 107 108 ULONG MY_CLOCKS_PER_SEC; 109 110 void PPC_TimerInit(void); 111 APTR MyTimer; 112 113 ULONG start[2]; 114 115 void SDL_StartTicks(void) 116 { 117 /* Set first ticks value */ 118 if(!MyTimer) 119 PPC_TimerInit(); 120 121 PPCGetTimerObject(MyTimer,PPCTIMERTAG_CURRENTTICKS,start); 122 start[1]>>=10; 123 start[1]|=((result[0]&0x3ff)<<22); 124 start[0]>>=10; 125 } 126 127 Uint32 SDL_GetTicks (void) 128 { 129 ULONG result[2]; 130 PPCGetTimerObject(MyTimer,PPCTIMERTAG_CURRENTTICKS,result); 131 132 // PPCAsr64p(result,10); 133 // Non va, la emulo: 134 135 result[1]>>=10; 136 result[1]|=((result[0]&0x3ff)<<22); 137 138 // Non mi interessa piu' result[0] 139 140 return result[1]*1000/MY_CLOCKS_PER_SEC; 141 } 142 143 void SDL_Delay (Uint32 ms) 144 { 145 // Do a busy wait if time is less than 50ms 146 147 if(ms<50) 148 { 149 ULONG to_wait[2],actual[2]; 150 PPCGetTimerObject(MyTimer,PPCTIMERTAG_CURRENTTICKS,result); 151 actual[1]=0; 152 to_wait[1]+=ms*1000/MY_CLOCKS_PER_SEC; 153 154 while(actual[1]<to_wait[1]) 155 { 156 PPCGetTimerObject(MyTimer,PPCTIMERTAG_CURRENTTICKS,actual); 157 } 158 } 159 else 160 { 161 Delay(ms/50); 162 } 163 } 164 165 void PPC_TimerInit(void) 166 { 167 struct TagItem tags[]= 168 { 169 PPCTIMERTAG_CPU,TRUE, 170 TAG_DONE,0 171 }; 172 173 174 if(MyTimer=PPCCreateTimerObject(tags)) 175 { 176 ULONG result[2]; 177 178 PPCGetTimerObject(MyTimer,PPCTIMERTAG_TICKSPERSEC,result); 179 D(bug("Timer inizializzato, TPS: %lu - %lu\n",result[0],result[1])); 180 // PPCAsr64p(result,10); 181 result[1]>>=10; 182 result[1]|=((result[0]&0x3ff)<<22); 183 result[0]>>=10; 184 185 D(bug("Shiftato TPS: %lu - %lu\n",result[0],result[1])); 186 MY_CLOCKS_PER_SEC=result[1]; 187 188 PPCGetTimerObject(MyTimer,PPCTIMERTAG_CURRENTTICKS,result); 189 190 D(bug("Current ticks: %lu - %lu\n",result[0],result[1])); 191 result[1]>>=10; 192 result[1]|=((result[0]&0x3ff)<<22); 193 result[0]>>=10; 194 // PPCAsr64p(result,10); 195 D(bug("Shiftato: %lu - %lu\n",result[0],result[1])); 196 } 197 else 198 { 199 D(bug("Errore nell'inizializzazione del timer!\n")); 200 } 201 } 202 203 #endif 204 205 #include "SDL_thread.h" 206 207 /* Data to handle a single periodic alarm */ 208 static int timer_alive = 0; 209 static SDL_Thread *timer_thread = NULL; 210 211 static int RunTimer(void *unused) 212 { 213 D(bug("SYSTimer: Entering RunTimer loop...")); 214 215 if(GfxBase==NULL) 216 GfxBase=(struct GfxBase *)OpenLibrary("graphics.library",37); 217 218 while ( timer_alive ) { 219 if ( SDL_timer_running ) { 220 SDL_ThreadedTimerCheck(); 221 } 222 if(GfxBase) 223 WaitTOF(); // Check the timer every fifth of seconds. Was SDL_Delay(1)->BusyWait! 224 else 225 Delay(1); 226 } 227 D(bug("SYSTimer: EXITING RunTimer loop...")); 228 return(0); 229 } 230 231 /* This is only called if the event thread is not running */ 232 int SDL_SYS_TimerInit(void) 233 { 234 D(bug("Creating thread for the timer (NOITIMER)...\n")); 235 236 timer_alive = 1; 237 timer_thread = SDL_CreateThread(RunTimer, NULL); 238 if ( timer_thread == NULL ) 239 { 240 D(bug("Creazione del thread fallita...\n")); 241 242 return(-1); 243 } 244 return(SDL_SetTimerThreaded(1)); 245 } 246 247 void SDL_SYS_TimerQuit(void) 248 { 249 timer_alive = 0; 250 if ( timer_thread ) { 251 SDL_WaitThread(timer_thread, NULL); 252 timer_thread = NULL; 253 } 254 } 255 256 int SDL_SYS_StartTimer(void) 257 { 258 SDL_SetError("Internal logic error: AmigaOS uses threaded timer"); 259 return(-1); 260 } 261 262 void SDL_SYS_StopTimer(void) 263 { 264 return; 265 } 266 267 #endif /* SDL_TIMER_AMIGA */ 268