mirror of
https://github.com/yawut/SDL.git
synced 2026-09-08 09:06:29 -05:00
MacOS Classic is no longer supported.
This commit is contained in:
@@ -1,348 +0,0 @@
|
||||
/* File "FastTimes.c" - Original code by Matt Slot <fprefect@ambrosiasw.com> */
|
||||
/* 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-2000. It is hereby placed into
|
||||
the public domain. The author makes no warranty as to fitness or stability */
|
||||
|
||||
#include <Gestalt.h>
|
||||
#include <LowMem.h>
|
||||
#include <CodeFragments.h>
|
||||
#include <DriverServices.h>
|
||||
#include <Timer.h>
|
||||
|
||||
#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 <20>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 <20>sec.
|
||||
* Later PowerPCs have an accurate "time base register" TBR, and we
|
||||
fall back to that, access it from PowerPC asm. Overhead = 1.3 <20>sec.
|
||||
* We can also try Microseconds() which is emulated : Overhead = 36 <20>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<Unknown>";
|
||||
|
||||
#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 */
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
@@ -1,28 +0,0 @@
|
||||
/* File "FastTimes.h" - Original code by Matt Slot <fprefect@ambrosiasw.com> */
|
||||
#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-2000. 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__ */
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
@@ -1,161 +0,0 @@
|
||||
/*
|
||||
SDL - Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2006 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 <Types.h>
|
||||
#include <Timer.h>
|
||||
#include <OSUtils.h>
|
||||
#include <Gestalt.h>
|
||||
#include <Processes.h>
|
||||
|
||||
#include <LowMem.h>
|
||||
|
||||
#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 */
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
@@ -1,195 +0,0 @@
|
||||
/*
|
||||
SDL - Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2006 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 <Types.h>
|
||||
#include <Timer.h>
|
||||
#include <OSUtils.h>
|
||||
#include <Gestalt.h>
|
||||
#include <Processes.h>
|
||||
|
||||
#include <LowMem.h>
|
||||
|
||||
#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 */
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
Reference in New Issue
Block a user