Home | History | Annotate | Download | only in macos
      1 /*
      2     SDL - Simple DirectMedia Layer
      3     Copyright (C) 1997-2012 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_MACOS
     25 
     26 #include <Types.h>
     27 #include <Timer.h>
     28 #include <OSUtils.h>
     29 #include <Gestalt.h>
     30 #include <Processes.h>
     31 
     32 #include <LowMem.h>
     33 
     34 #include "SDL_timer.h"
     35 #include "../SDL_timer_c.h"
     36 
     37 #include "FastTimes.h"
     38 
     39 #if TARGET_API_MAC_CARBON
     40 #define NewTimerProc NewTimerUPP
     41 #endif
     42 
     43 #define MS_PER_TICK	(1000.0/60.0)		/* MacOS tick = 1/60 second */
     44 
     45 
     46 #define kTwoPower32     (4294967296.0)          /* 2^32 */
     47 
     48 static double start_tick;
     49 static int    is_fast_inited = 0;
     50 
     51 void SDL_StartTicks(void)
     52 {
     53         if ( ! is_fast_inited )     // important to check or FastTime may hang machine!
     54             SDL_SYS_TimerInit();
     55 
     56         start_tick = FastMicroseconds();
     57 }
     58 
     59 Uint32 SDL_GetTicks(void)
     60 {
     61 
     62         if ( ! is_fast_inited )
     63             SDL_SYS_TimerInit();
     64 
     65         return FastMilliseconds();
     66 }
     67 
     68 void SDL_Delay(Uint32 ms)
     69 {
     70         Uint32 stop, now;
     71 
     72         stop = SDL_GetTicks() + ms;
     73         do {
     74             #if TARGET_API_MAC_CARBON
     75                 MPYield();
     76             #else
     77                 SystemTask();
     78             #endif
     79 
     80                 now = SDL_GetTicks();
     81 
     82         } while ( stop > now );
     83 }
     84 
     85 /*
     86 void SDL_StartTicks(void)
     87 {
     88 	// FIXME: Should we implement a wrapping algorithm, like Win32?
     89 }
     90 
     91 Uint32 SDL_GetTicks(void)
     92 {
     93 	UnsignedWide ms;
     94 
     95 	Microseconds (&ms);
     96 
     97 	return ( ms.lo / 1000 );
     98 }
     99 
    100 void SDL_Delay(Uint32 ms)
    101 {
    102 
    103 	UnsignedWide microsecs;
    104 	UInt32       stop;
    105 
    106 	Microseconds (&microsecs);
    107 
    108 	stop = microsecs.lo + (ms * 1000);
    109 
    110 	while ( stop > microsecs.lo ) {
    111 
    112 	   SystemTask ();
    113 
    114 	   Microseconds (&microsecs);
    115 	}
    116 
    117 }*/
    118 
    119 /* Data to handle a single periodic alarm */
    120 typedef struct _ExtendedTimerRec
    121 {
    122 	TMTask		     tmTask;
    123 	ProcessSerialNumber  taskPSN;
    124 } ExtendedTimerRec, *ExtendedTimerPtr;
    125 
    126 static ExtendedTimerRec gExtendedTimerRec;
    127 
    128 
    129 int SDL_SYS_TimerInit(void)
    130 {
    131 	FastInitialize ();
    132 	is_fast_inited = 1;
    133 
    134 	return(0);
    135 }
    136 
    137 void SDL_SYS_TimerQuit(void)
    138 {
    139 	/* We don't need a cleanup? */
    140 	return;
    141 }
    142 
    143 /* Our Stub routine to set up and then call the real routine. */
    144 pascal void TimerCallbackProc(TMTaskPtr tmTaskPtr)
    145 {
    146 	Uint32 ms;
    147 
    148 	WakeUpProcess(&((ExtendedTimerPtr) tmTaskPtr)->taskPSN);
    149 
    150 	ms = SDL_alarm_callback(SDL_alarm_interval);
    151 	if ( ms ) {
    152 		SDL_alarm_interval = ROUND_RESOLUTION(ms);
    153 		PrimeTime((QElemPtr)&gExtendedTimerRec.tmTask,
    154 		          SDL_alarm_interval);
    155 	} else {
    156 		SDL_alarm_interval = 0;
    157 	}
    158 }
    159 
    160 int SDL_SYS_StartTimer(void)
    161 {
    162 	/*
    163 	 * Configure the global structure that stores the timing information.
    164 	 */
    165 	gExtendedTimerRec.tmTask.qLink = NULL;
    166 	gExtendedTimerRec.tmTask.qType = 0;
    167 	gExtendedTimerRec.tmTask.tmAddr = NewTimerProc(TimerCallbackProc);
    168 	gExtendedTimerRec.tmTask.tmCount = 0;
    169 	gExtendedTimerRec.tmTask.tmWakeUp = 0;
    170 	gExtendedTimerRec.tmTask.tmReserved = 0;
    171 	GetCurrentProcess(&gExtendedTimerRec.taskPSN);
    172 
    173 	/* Install the task record */
    174 	InsXTime((QElemPtr)&gExtendedTimerRec.tmTask);
    175 
    176 	/* Go! */
    177 	PrimeTime((QElemPtr)&gExtendedTimerRec.tmTask, SDL_alarm_interval);
    178 	return(0);
    179 }
    180 
    181 void SDL_SYS_StopTimer(void)
    182 {
    183 	RmvTime((QElemPtr)&gExtendedTimerRec.tmTask);
    184 }
    185 
    186 #endif /* SDL_TIMER_MACOS */
    187