From a855d6202536ff28e5aae4f22a0f31d8f5b325d0 Mon Sep 17 00:00:00 2001 From: Franklin Wei Date: Sat, 21 Jan 2017 15:18:31 -0500 Subject: Port of Duke Nukem 3D This ports Fabien Sanglard's Chocolate Duke to run on a version of SDL for Rockbox. Change-Id: I8f2c4c78af19de10c1633ed7bb7a997b43256dd9 --- apps/plugins/sdl/src/timer/macos/FastTimes.c | 352 ++++++++++++++++++++++++ apps/plugins/sdl/src/timer/macos/FastTimes.h | 27 ++ apps/plugins/sdl/src/timer/macos/SDL_MPWtimer.c | 152 ++++++++++ apps/plugins/sdl/src/timer/macos/SDL_systimer.c | 186 +++++++++++++ 4 files changed, 717 insertions(+) create mode 100644 apps/plugins/sdl/src/timer/macos/FastTimes.c create mode 100644 apps/plugins/sdl/src/timer/macos/FastTimes.h create mode 100644 apps/plugins/sdl/src/timer/macos/SDL_MPWtimer.c create mode 100644 apps/plugins/sdl/src/timer/macos/SDL_systimer.c (limited to 'apps/plugins/sdl/src/timer/macos') diff --git a/apps/plugins/sdl/src/timer/macos/FastTimes.c b/apps/plugins/sdl/src/timer/macos/FastTimes.c new file mode 100644 index 0000000000..2da74b7d18 --- /dev/null +++ b/apps/plugins/sdl/src/timer/macos/FastTimes.c @@ -0,0 +1,352 @@ +/* File "FastTimes.c" - Original code by Matt Slot */ +/* Created 4/24/99 - This file is hereby placed in the public domain */ +/* Updated 5/21/99 - Calibrate to VIA, add TBR support, renamed functions */ +/* Updated 10/4/99 - Use AbsoluteToNanoseconds() in case Absolute = double */ +/* Updated 2/15/00 - Check for native Time Manager, no need to calibrate */ +/* Updated 2/19/00 - Fixed default value for gScale under native Time Mgr */ +/* Updated 3/21/00 - Fixed ns conversion, create 2 different scale factors */ +/* Updated 5/03/00 - Added copyright and placed into PD. No code changes */ +/* Updated 8/01/00 - Made "Carbon-compatible" by replacing LMGetTicks() */ + +/* This file is Copyright (C) Matt Slot, 1999-2012. It is hereby placed into + the public domain. The author makes no warranty as to fitness or stability */ + +#include +#include +#include +#include +#include + +#include "FastTimes.h" + +#ifdef TARGET_CPU_PPC +#undef GENERATINGPOWERPC /* stop whining */ +#define GENERATINGPOWERPC TARGET_CPU_PPC +#endif + +/* **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** */ +/* **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** */ +/* + On 680x0 machines, we just use Microseconds(). + + On PowerPC machines, we try several methods: + * DriverServicesLib is available on all PCI PowerMacs, and perhaps + some NuBus PowerMacs. If it is, we use UpTime() : Overhead = 2.1 µsec. + * The PowerPC 601 has a built-in "real time clock" RTC, and we fall + back to that, accessing it directly from asm. Overhead = 1.3 µsec. + * Later PowerPCs have an accurate "time base register" TBR, and we + fall back to that, access it from PowerPC asm. Overhead = 1.3 µsec. + * We can also try Microseconds() which is emulated : Overhead = 36 µsec. + + On PowerPC machines, we avoid the following: + * OpenTransport is available on all PCI and some NuBus PowerMacs, but it + uses UpTime() if available and falls back to Microseconds() otherwise. + * InputSprocket is available on many PowerMacs, but again it uses + UpTime() if available and falls back to Microseconds() otherwise. + + Another PowerPC note: certain configurations, especially 3rd party upgrade + cards, may return inaccurate timings for the CPU or memory bus -- causing + skew in various system routines (up to 20% drift!). The VIA chip is very + accurate, and it's the basis for the Time Manager and Microseconds(). + Unfortunately, it's also very slow because the MacOS has to (a) switch to + 68K and (b) poll for a VIA event. + + We compensate for the drift by calibrating a floating point scale factor + between our fast method and the accurate timer at startup, then convert + each sample quickly on the fly. I'd rather not have the initialization + overhead -- but it's simply necessary for accurate timing. You can drop + it down to 30 ticks if you prefer, but that's as low as I'd recommend. + + Under MacOS 9, "new world" Macs (iMacs, B+W G3s and G+W G4s) have a native + Time Manager implementation: UpTime(), Microseconds(), and TickCount() are + all based on the same underlying counter. This makes it silly to calibrate + UpTime() against TickCount(). We now check for this feature using Gestalt(), + and skip the whole calibration step if possible. + +*/ +/* **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** */ +/* **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** */ + +#define RTCToNano(w) ((double) (w).hi * 1000000000.0 + (double) (w).lo) +#define WideTo64bit(w) (*(UInt64 *) &(w)) + +/* LMGetTicks() is not in Carbon and TickCount() has a fair bit of overhead, + so for speed we always read lowmem directly. This is a Mac OS X no-no, but + it always work on those systems that don't have a native Time Manager (ie, + anything before MacOS 9) -- regardless whether we are in Carbon or not! */ +#define MyLMGetTicks() (*(volatile UInt32 *) 0x16A) + +#if GENERATINGPOWERPC + +static asm UnsignedWide PollRTC(void); +static asm UnsignedWide PollTBR(void); +static Ptr FindFunctionInSharedLib(StringPtr libName, StringPtr funcName); + +static Boolean gInited = false; +static Boolean gNative = false; +static Boolean gUseRTC = false; +static Boolean gUseTBR = false; +static double gScaleUSec = 1.0 / 1000.0; /* 1 / ( nsec / usec) */ +static double gScaleMSec = 1.0 / 1000000.0; /* 1 / ( nsec / msec) */ + +/* Functions loaded from DriverServicesLib */ +typedef AbsoluteTime (*UpTimeProcPtr)(void); +typedef Nanoseconds (*A2NSProcPtr)(AbsoluteTime); +static UpTimeProcPtr gUpTime = NULL; +static A2NSProcPtr gA2NS = NULL; + +#endif /* GENERATINGPOWERPC */ + +/* **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** */ +/* **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** */ + +void FastInitialize() { + SInt32 result; + + if (!gInited) { + +#if GENERATINGPOWERPC + + /* Initialize the feature flags */ + gNative = gUseRTC = gUseTBR = false; + + /* We use CFM to find and load needed symbols from shared libraries, so + the application doesn't have to weak-link them, for convenience. */ + gUpTime = (UpTimeProcPtr) FindFunctionInSharedLib( + "\pDriverServicesLib", "\pUpTime"); + if (gUpTime) gA2NS = (A2NSProcPtr) FindFunctionInSharedLib( + "\pDriverServicesLib", "\pAbsoluteToNanoseconds"); + if (!gA2NS) gUpTime = nil; /* Pedantic but necessary */ + + if (gUpTime) { + /* If we loaded UpTime(), then we need to know if the system has + a native implementation of the Time Manager. If so, then it's + pointless to calculate a scale factor against the missing VIA */ + + /* gestaltNativeTimeMgr = 4 in some future version of the headers */ + if (!Gestalt(gestaltTimeMgrVersion, &result) && + (result > gestaltExtendedTimeMgr)) + gNative = true; + } + else { + /* If no DriverServicesLib, use Gestalt() to get the processor type. + Only NuBus PowerMacs with old System Software won't have DSL, so + we know it should either be a 601 or 603. */ + + /* Use the processor gestalt to determine which register to use */ + if (!Gestalt(gestaltNativeCPUtype, &result)) { + if (result == gestaltCPU601) gUseRTC = true; + else if (result > gestaltCPU601) gUseTBR = true; + } + } + + /* Now calculate a scale factor to keep us accurate. */ + if ((gUpTime && !gNative) || gUseRTC || gUseTBR) { + UInt64 tick, usec1, usec2; + UnsignedWide wide; + + /* Wait for the beginning of the very next tick */ + for(tick = MyLMGetTicks() + 1; tick > MyLMGetTicks(); ); + + /* Poll the selected timer and prepare it (since we have time) */ + wide = (gUpTime) ? (*gA2NS)((*gUpTime)()) : + ((gUseRTC) ? PollRTC() : PollTBR()); + usec1 = (gUseRTC) ? RTCToNano(wide) : WideTo64bit(wide); + + /* Wait for the exact 60th tick to roll over */ + while(tick + 60 > MyLMGetTicks()); + + /* Poll the selected timer again and prepare it */ + wide = (gUpTime) ? (*gA2NS)((*gUpTime)()) : + ((gUseRTC) ? PollRTC() : PollTBR()); + usec2 = (gUseRTC) ? RTCToNano(wide) : WideTo64bit(wide); + + /* Calculate a scale value that will give microseconds per second. + Remember, there are actually 60.15 ticks in a second, not 60. */ + gScaleUSec = (60.0 * 1000000.0) / ((usec2 - usec1) * 60.15); + gScaleMSec = gScaleUSec / 1000.0; + } + +#endif /* GENERATINGPOWERPC */ + + /* We've initialized our globals */ + gInited = true; + } + } + +/* **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** */ +/* **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** */ + +UInt64 FastMicroseconds() { + UnsignedWide wide; + UInt64 usec; + +#if GENERATINGPOWERPC + /* Initialize globals the first time we are called */ + if (!gInited) FastInitialize(); + + if (gNative) { + /* Use DriverServices if it's available -- it's fast and compatible */ + wide = (*gA2NS)((*gUpTime)()); + usec = (double) WideTo64bit(wide) * gScaleUSec + 0.5; + } + else if (gUpTime) { + /* Use DriverServices if it's available -- it's fast and compatible */ + wide = (*gA2NS)((*gUpTime)()); + usec = (double) WideTo64bit(wide) * gScaleUSec + 0.5; + } + else if (gUseTBR) { + /* On a recent PowerPC, we poll the TBR directly */ + wide = PollTBR(); + usec = (double) WideTo64bit(wide) * gScaleUSec + 0.5; + } + else if (gUseRTC) { + /* On a 601, we can poll the RTC instead */ + wide = PollRTC(); + usec = (double) RTCToNano(wide) * gScaleUSec + 0.5; + } + else +#endif /* GENERATINGPOWERPC */ + { + /* If all else fails, suffer the mixed mode overhead */ + Microseconds(&wide); + usec = WideTo64bit(wide); + } + + return(usec); + } + +/* **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** */ +/* **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** */ + +UInt64 FastMilliseconds() { + UnsignedWide wide; + UInt64 msec; + +#if GENERATINGPOWERPC + /* Initialize globals the first time we are called */ + if (!gInited) FastInitialize(); + + if (gNative) { + /* Use DriverServices if it's available -- it's fast and compatible */ + wide = (*gA2NS)((*gUpTime)()); + msec = (double) WideTo64bit(wide) * gScaleMSec + 0.5; + } + else if (gUpTime) { + /* Use DriverServices if it's available -- it's fast and compatible */ + wide = (*gA2NS)((*gUpTime)()); + msec = (double) WideTo64bit(wide) * gScaleMSec + 0.5; + } + else if (gUseTBR) { + /* On a recent PowerPC, we poll the TBR directly */ + wide = PollTBR(); + msec = (double) WideTo64bit(wide) * gScaleMSec + 0.5; + } + else if (gUseRTC) { + /* On a 601, we can poll the RTC instead */ + wide = PollRTC(); + msec = (double) RTCToNano(wide) * gScaleMSec + 0.5; + } + else +#endif /* GENERATINGPOWERPC */ + { + /* If all else fails, suffer the mixed mode overhead */ + Microseconds(&wide); + msec = ((double) WideTo64bit(wide) + 500.0) / 1000.0; + } + + return(msec); + } + +/* **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** */ +/* **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** */ + +StringPtr FastMethod() { + StringPtr method = "\p"; + +#if GENERATINGPOWERPC + /* Initialize globals the first time we are called */ + if (!gInited) FastInitialize(); + + if (gNative) { + /* The Time Manager and UpTime() are entirely native on this machine */ + method = "\pNative UpTime()"; + } + else if (gUpTime) { + /* Use DriverServices if it's available -- it's fast and compatible */ + method = "\pUpTime()"; + } + else if (gUseTBR) { + /* On a recent PowerPC, we poll the TBR directly */ + method = "\pPowerPC TBR"; + } + else if (gUseRTC) { + /* On a 601, we can poll the RTC instead */ + method = "\pPowerPC RTC"; + } + else +#endif /* GENERATINGPOWERPC */ + { + /* If all else fails, suffer the mixed mode overhead */ + method = "\pMicroseconds()"; + } + + return(method); + } + +/* **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** */ +/* **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** */ +#pragma mark - + +#if GENERATINGPOWERPC +asm static UnsignedWide PollRTC_() { +entry PollRTC /* Avoid CodeWarrior glue */ + machine 601 +@AGAIN: + mfrtcu r4 /* RTCU = SPR 4 */ + mfrtcl r5 /* RTCL = SPR 5 */ + mfrtcu r6 + cmpw r4,r6 + bne @AGAIN + stw r4,0(r3) + stw r5,4(r3) + blr + } + +/* **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** */ +/* **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** */ + +asm static UnsignedWide PollTBR_() { +entry PollTBR /* Avoid CodeWarrior glue */ + machine 604 +@AGAIN: + mftbu r4 /* TBRU = SPR 268 */ + mftb r5 /* TBRL = SPR 269 */ + mftbu r6 + cmpw r4,r6 + bne @AGAIN + stw r4,0(r3) + stw r5,4(r3) + blr + } + +/* **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** */ +/* **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** */ + +static Ptr FindFunctionInSharedLib(StringPtr libName, StringPtr funcName) { + OSErr error = noErr; + Str255 errorStr; + Ptr func = NULL; + Ptr entry = NULL; + CFragSymbolClass symClass; + CFragConnectionID connID; + + /* Find CFM containers for the current archecture -- CFM-PPC or CFM-68K */ + if (/* error = */ GetSharedLibrary(libName, kCompiledCFragArch, + kLoadCFrag, &connID, &entry, errorStr)) return(NULL); + if (/* error = */ FindSymbol(connID, funcName, &func, &symClass)) + return(NULL); + + return(func); + } +#endif /* GENERATINGPOWERPC */ diff --git a/apps/plugins/sdl/src/timer/macos/FastTimes.h b/apps/plugins/sdl/src/timer/macos/FastTimes.h new file mode 100644 index 0000000000..d25744c330 --- /dev/null +++ b/apps/plugins/sdl/src/timer/macos/FastTimes.h @@ -0,0 +1,27 @@ +/* File "FastTimes.h" - Original code by Matt Slot */ +#include "SDL_config.h" +/* Created 4/24/99 - This file is hereby placed in the public domain */ +/* Updated 5/21/99 - Calibrate to VIA, add TBR support, renamed functions */ +/* Updated 10/4/99 - Use AbsoluteToNanoseconds() in case Absolute = double */ +/* Updated 2/15/00 - Check for native Time Manager, no need to calibrate */ +/* Updated 3/21/00 - Fixed ns conversion, create 2 different scale factors */ +/* Updated 5/03/00 - Added copyright and placed into PD. No code changes */ + +/* This file is Copyright (C) Matt Slot, 1999-2012. It is hereby placed into + the public domain. The author makes no warranty as to fitness or stability */ + +#ifndef __FAST_TIMES_HEADER__ +#define __FAST_TIMES_HEADER__ + +/* **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** */ +/* **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** */ + +extern void FastInitialize(void); +extern UInt64 FastMicroseconds(void); +extern UInt64 FastMilliseconds(void); +extern StringPtr FastMethod(void); + +/* **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** */ +/* **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** */ + +#endif /* __FAST_TIMES_HEADER__ */ diff --git a/apps/plugins/sdl/src/timer/macos/SDL_MPWtimer.c b/apps/plugins/sdl/src/timer/macos/SDL_MPWtimer.c new file mode 100644 index 0000000000..114b6c7c0a --- /dev/null +++ b/apps/plugins/sdl/src/timer/macos/SDL_MPWtimer.c @@ -0,0 +1,152 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#ifdef SDL_TIMER_MACOS + +#include +#include +#include +#include +#include + +#include + +#include "SDL_timer.h" +#include "../SDL_timer_c.h" + +#define MS_PER_TICK (1000/60) /* MacOS tick = 1/60 second */ + +/* Note: This is only a step above the original 1/60s implementation. + * For a good implementation, see FastTimes.[ch], by Matt Slot. + */ +#define USE_MICROSECONDS +#define WideTo64bit(w) (*(UInt64 *) &(w)) + +UInt64 start; + +void SDL_StartTicks(void) +{ +#ifdef USE_MICROSECONDS + UnsignedWide now; + + Microseconds(&now); + start = WideTo64bit(now); +#else + /* FIXME: Should we implement a wrapping algorithm, like Win32? */ +#endif +} + +Uint32 SDL_GetTicks(void) +{ +#ifdef USE_MICROSECONDS + UnsignedWide now; + + Microseconds(&now); + return (Uint32)((WideTo64bit(now)-start)/1000); +#else + return(LMGetTicks()*MS_PER_TICK); +#endif +} + +void SDL_Delay(Uint32 ms) +{ +#ifdef USE_MICROSECONDS + Uint32 end_ms; + + end_ms = SDL_GetTicks() + ms; + do { + /* FIXME: Yield CPU? */ ; + } while ( SDL_GetTicks() < end_ms ); +#else + UInt32 unused; /* MJS */ + Delay(ms/MS_PER_TICK, &unused); +#endif +} + + +/* Data to handle a single periodic alarm */ +typedef struct _ExtendedTimerRec +{ + TMTask tmTask; + ProcessSerialNumber taskPSN; +} ExtendedTimerRec, *ExtendedTimerPtr; + +static ExtendedTimerRec gExtendedTimerRec; + + +int SDL_SYS_TimerInit(void) +{ + /* We don't need a setup? */ + return(0); +} + +void SDL_SYS_TimerQuit(void) +{ + /* We don't need a cleanup? */ + return; +} + +/* Our Stub routine to set up and then call the real routine. */ +pascal void TimerCallbackProc(TMTaskPtr tmTaskPtr) +{ + Uint32 ms; + + WakeUpProcess(&((ExtendedTimerPtr) tmTaskPtr)->taskPSN); + + ms = SDL_alarm_callback(SDL_alarm_interval); + if ( ms ) { + SDL_alarm_interval = ROUND_RESOLUTION(ms); + PrimeTime((QElemPtr)&gExtendedTimerRec.tmTask, + SDL_alarm_interval); + } else { + SDL_alarm_interval = 0; + } +} + +int SDL_SYS_StartTimer(void) +{ + /* + * Configure the global structure that stores the timing information. + */ + gExtendedTimerRec.tmTask.qLink = NULL; + gExtendedTimerRec.tmTask.qType = 0; + gExtendedTimerRec.tmTask.tmAddr = NewTimerUPP(TimerCallbackProc); + gExtendedTimerRec.tmTask.tmCount = 0; + gExtendedTimerRec.tmTask.tmWakeUp = 0; + gExtendedTimerRec.tmTask.tmReserved = 0; + GetCurrentProcess(&gExtendedTimerRec.taskPSN); + + /* Install the task record */ + InsXTime((QElemPtr)&gExtendedTimerRec.tmTask); + + /* Go! */ + PrimeTime((QElemPtr)&gExtendedTimerRec.tmTask, SDL_alarm_interval); + return(0); +} + +void SDL_SYS_StopTimer(void) +{ + RmvTime((QElemPtr)&gExtendedTimerRec.tmTask); +} + +#endif /* SDL_TIMER_MACOS */ diff --git a/apps/plugins/sdl/src/timer/macos/SDL_systimer.c b/apps/plugins/sdl/src/timer/macos/SDL_systimer.c new file mode 100644 index 0000000000..7a8063e57d --- /dev/null +++ b/apps/plugins/sdl/src/timer/macos/SDL_systimer.c @@ -0,0 +1,186 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#ifdef SDL_TIMER_MACOS + +#include +#include +#include +#include +#include + +#include + +#include "SDL_timer.h" +#include "../SDL_timer_c.h" + +#include "FastTimes.h" + +#if TARGET_API_MAC_CARBON +#define NewTimerProc NewTimerUPP +#endif + +#define MS_PER_TICK (1000.0/60.0) /* MacOS tick = 1/60 second */ + + +#define kTwoPower32 (4294967296.0) /* 2^32 */ + +static double start_tick; +static int is_fast_inited = 0; + +void SDL_StartTicks(void) +{ + if ( ! is_fast_inited ) // important to check or FastTime may hang machine! + SDL_SYS_TimerInit(); + + start_tick = FastMicroseconds(); +} + +Uint32 SDL_GetTicks(void) +{ + + if ( ! is_fast_inited ) + SDL_SYS_TimerInit(); + + return FastMilliseconds(); +} + +void SDL_Delay(Uint32 ms) +{ + Uint32 stop, now; + + stop = SDL_GetTicks() + ms; + do { + #if TARGET_API_MAC_CARBON + MPYield(); + #else + SystemTask(); + #endif + + now = SDL_GetTicks(); + + } while ( stop > now ); +} + +/* +void SDL_StartTicks(void) +{ + // FIXME: Should we implement a wrapping algorithm, like Win32? +} + +Uint32 SDL_GetTicks(void) +{ + UnsignedWide ms; + + Microseconds (&ms); + + return ( ms.lo / 1000 ); +} + +void SDL_Delay(Uint32 ms) +{ + + UnsignedWide microsecs; + UInt32 stop; + + Microseconds (µsecs); + + stop = microsecs.lo + (ms * 1000); + + while ( stop > microsecs.lo ) { + + SystemTask (); + + Microseconds (µsecs); + } + +}*/ + +/* Data to handle a single periodic alarm */ +typedef struct _ExtendedTimerRec +{ + TMTask tmTask; + ProcessSerialNumber taskPSN; +} ExtendedTimerRec, *ExtendedTimerPtr; + +static ExtendedTimerRec gExtendedTimerRec; + + +int SDL_SYS_TimerInit(void) +{ + FastInitialize (); + is_fast_inited = 1; + + return(0); +} + +void SDL_SYS_TimerQuit(void) +{ + /* We don't need a cleanup? */ + return; +} + +/* Our Stub routine to set up and then call the real routine. */ +pascal void TimerCallbackProc(TMTaskPtr tmTaskPtr) +{ + Uint32 ms; + + WakeUpProcess(&((ExtendedTimerPtr) tmTaskPtr)->taskPSN); + + ms = SDL_alarm_callback(SDL_alarm_interval); + if ( ms ) { + SDL_alarm_interval = ROUND_RESOLUTION(ms); + PrimeTime((QElemPtr)&gExtendedTimerRec.tmTask, + SDL_alarm_interval); + } else { + SDL_alarm_interval = 0; + } +} + +int SDL_SYS_StartTimer(void) +{ + /* + * Configure the global structure that stores the timing information. + */ + gExtendedTimerRec.tmTask.qLink = NULL; + gExtendedTimerRec.tmTask.qType = 0; + gExtendedTimerRec.tmTask.tmAddr = NewTimerProc(TimerCallbackProc); + gExtendedTimerRec.tmTask.tmCount = 0; + gExtendedTimerRec.tmTask.tmWakeUp = 0; + gExtendedTimerRec.tmTask.tmReserved = 0; + GetCurrentProcess(&gExtendedTimerRec.taskPSN); + + /* Install the task record */ + InsXTime((QElemPtr)&gExtendedTimerRec.tmTask); + + /* Go! */ + PrimeTime((QElemPtr)&gExtendedTimerRec.tmTask, SDL_alarm_interval); + return(0); +} + +void SDL_SYS_StopTimer(void) +{ + RmvTime((QElemPtr)&gExtendedTimerRec.tmTask); +} + +#endif /* SDL_TIMER_MACOS */ -- cgit v1.2.3