mirror of
https://github.com/Rockbox/rockbox.git
synced 2025-11-10 13:42:29 -05:00
Port of Duke Nukem 3D
This ports Fabien Sanglard's Chocolate Duke to run on a version of SDL for Rockbox. Change-Id: I8f2c4c78af19de10c1633ed7bb7a997b43256dd9
This commit is contained in:
parent
01c6dcf6c7
commit
a855d62025
994 changed files with 336924 additions and 15 deletions
40
apps/plugins/sdl/src/timer/SDL_systimer.h
Normal file
40
apps/plugins/sdl/src/timer/SDL_systimer.h
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
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"
|
||||
|
||||
/* The system dependent timer handling functions */
|
||||
|
||||
#include "SDL_timer.h"
|
||||
#include "SDL_timer_c.h"
|
||||
|
||||
|
||||
/* Initialize the system dependent timer subsystem */
|
||||
extern int SDL_SYS_TimerInit(void);
|
||||
|
||||
/* Quit the system dependent timer subsystem */
|
||||
extern void SDL_SYS_TimerQuit(void);
|
||||
|
||||
/* Start a timer set up by SDL_SetTimer() */
|
||||
extern int SDL_SYS_StartTimer(void);
|
||||
|
||||
/* Stop a previously started timer */
|
||||
extern void SDL_SYS_StopTimer(void);
|
||||
285
apps/plugins/sdl/src/timer/SDL_timer.c
Normal file
285
apps/plugins/sdl/src/timer/SDL_timer.c
Normal file
|
|
@ -0,0 +1,285 @@
|
|||
/*
|
||||
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"
|
||||
|
||||
#include "SDL_timer.h"
|
||||
#include "SDL_timer_c.h"
|
||||
#include "SDL_mutex.h"
|
||||
#include "SDL_systimer.h"
|
||||
|
||||
/* #define DEBUG_TIMERS */
|
||||
|
||||
int SDL_timer_started = 0;
|
||||
int SDL_timer_running = 0;
|
||||
|
||||
/* Data to handle a single periodic alarm */
|
||||
Uint32 SDL_alarm_interval = 0;
|
||||
SDL_TimerCallback SDL_alarm_callback;
|
||||
|
||||
/* Data used for a thread-based timer */
|
||||
static int SDL_timer_threaded = 0;
|
||||
|
||||
struct _SDL_TimerID {
|
||||
Uint32 interval;
|
||||
SDL_NewTimerCallback cb;
|
||||
void *param;
|
||||
Uint32 last_alarm;
|
||||
struct _SDL_TimerID *next;
|
||||
};
|
||||
|
||||
static SDL_TimerID SDL_timers = NULL;
|
||||
static SDL_mutex *SDL_timer_mutex;
|
||||
static volatile SDL_bool list_changed = SDL_FALSE;
|
||||
|
||||
/* Set whether or not the timer should use a thread.
|
||||
This should not be called while the timer subsystem is running.
|
||||
*/
|
||||
int SDL_SetTimerThreaded(int value)
|
||||
{
|
||||
int retval;
|
||||
|
||||
if ( SDL_timer_started ) {
|
||||
SDL_SetError("Timer already initialized");
|
||||
retval = -1;
|
||||
} else {
|
||||
retval = 0;
|
||||
SDL_timer_threaded = value;
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
int SDL_TimerInit(void)
|
||||
{
|
||||
int retval;
|
||||
|
||||
retval = 0;
|
||||
if ( SDL_timer_started ) {
|
||||
SDL_TimerQuit();
|
||||
}
|
||||
if ( ! SDL_timer_threaded ) {
|
||||
retval = SDL_SYS_TimerInit();
|
||||
}
|
||||
if ( SDL_timer_threaded ) {
|
||||
SDL_timer_mutex = SDL_CreateMutex();
|
||||
}
|
||||
if ( retval == 0 ) {
|
||||
SDL_timer_started = 1;
|
||||
}
|
||||
return(retval);
|
||||
}
|
||||
|
||||
void SDL_TimerQuit(void)
|
||||
{
|
||||
SDL_SetTimer(0, NULL);
|
||||
if ( SDL_timer_threaded < 2 ) {
|
||||
SDL_SYS_TimerQuit();
|
||||
}
|
||||
if ( SDL_timer_threaded ) {
|
||||
SDL_DestroyMutex(SDL_timer_mutex);
|
||||
SDL_timer_mutex = NULL;
|
||||
}
|
||||
SDL_timer_started = 0;
|
||||
SDL_timer_threaded = 0;
|
||||
}
|
||||
|
||||
void SDL_ThreadedTimerCheck(void)
|
||||
{
|
||||
Uint32 now, ms;
|
||||
SDL_TimerID t, prev, next;
|
||||
SDL_bool removed;
|
||||
|
||||
SDL_mutexP(SDL_timer_mutex);
|
||||
list_changed = SDL_FALSE;
|
||||
now = SDL_GetTicks();
|
||||
for ( prev = NULL, t = SDL_timers; t; t = next ) {
|
||||
removed = SDL_FALSE;
|
||||
ms = t->interval - SDL_TIMESLICE;
|
||||
next = t->next;
|
||||
if ( (int)(now - t->last_alarm) > (int)ms ) {
|
||||
struct _SDL_TimerID timer;
|
||||
|
||||
if ( (now - t->last_alarm) < t->interval ) {
|
||||
t->last_alarm += t->interval;
|
||||
} else {
|
||||
t->last_alarm = now;
|
||||
}
|
||||
#ifdef DEBUG_TIMERS
|
||||
printf("Executing timer %p (thread = %d)\n",
|
||||
t, SDL_ThreadID());
|
||||
#endif
|
||||
timer = *t;
|
||||
SDL_mutexV(SDL_timer_mutex);
|
||||
ms = timer.cb(timer.interval, timer.param);
|
||||
SDL_mutexP(SDL_timer_mutex);
|
||||
if ( list_changed ) {
|
||||
/* Abort, list of timers modified */
|
||||
/* FIXME: what if ms was changed? */
|
||||
break;
|
||||
}
|
||||
if ( ms != t->interval ) {
|
||||
if ( ms ) {
|
||||
t->interval = ROUND_RESOLUTION(ms);
|
||||
} else {
|
||||
/* Remove timer from the list */
|
||||
#ifdef DEBUG_TIMERS
|
||||
printf("SDL: Removing timer %p\n", t);
|
||||
#endif
|
||||
if ( prev ) {
|
||||
prev->next = next;
|
||||
} else {
|
||||
SDL_timers = next;
|
||||
}
|
||||
SDL_free(t);
|
||||
--SDL_timer_running;
|
||||
removed = SDL_TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Don't update prev if the timer has disappeared */
|
||||
if ( ! removed ) {
|
||||
prev = t;
|
||||
}
|
||||
}
|
||||
SDL_mutexV(SDL_timer_mutex);
|
||||
}
|
||||
|
||||
static SDL_TimerID SDL_AddTimerInternal(Uint32 interval, SDL_NewTimerCallback callback, void *param)
|
||||
{
|
||||
SDL_TimerID t;
|
||||
t = (SDL_TimerID) SDL_malloc(sizeof(struct _SDL_TimerID));
|
||||
if ( t ) {
|
||||
t->interval = ROUND_RESOLUTION(interval);
|
||||
t->cb = callback;
|
||||
t->param = param;
|
||||
t->last_alarm = SDL_GetTicks();
|
||||
t->next = SDL_timers;
|
||||
SDL_timers = t;
|
||||
++SDL_timer_running;
|
||||
list_changed = SDL_TRUE;
|
||||
}
|
||||
#ifdef DEBUG_TIMERS
|
||||
printf("SDL_AddTimer(%d) = %08x num_timers = %d\n", interval, (Uint32)t, SDL_timer_running);
|
||||
#endif
|
||||
return t;
|
||||
}
|
||||
|
||||
SDL_TimerID SDL_AddTimer(Uint32 interval, SDL_NewTimerCallback callback, void *param)
|
||||
{
|
||||
SDL_TimerID t;
|
||||
if ( ! SDL_timer_mutex ) {
|
||||
if ( SDL_timer_started ) {
|
||||
SDL_SetError("This platform doesn't support multiple timers");
|
||||
} else {
|
||||
SDL_SetError("You must call SDL_Init(SDL_INIT_TIMER) first");
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
if ( ! SDL_timer_threaded ) {
|
||||
SDL_SetError("Multiple timers require threaded events!");
|
||||
return NULL;
|
||||
}
|
||||
SDL_mutexP(SDL_timer_mutex);
|
||||
t = SDL_AddTimerInternal(interval, callback, param);
|
||||
SDL_mutexV(SDL_timer_mutex);
|
||||
return t;
|
||||
}
|
||||
|
||||
SDL_bool SDL_RemoveTimer(SDL_TimerID id)
|
||||
{
|
||||
SDL_TimerID t, prev = NULL;
|
||||
SDL_bool removed;
|
||||
|
||||
removed = SDL_FALSE;
|
||||
SDL_mutexP(SDL_timer_mutex);
|
||||
/* Look for id in the linked list of timers */
|
||||
for (t = SDL_timers; t; prev=t, t = t->next ) {
|
||||
if ( t == id ) {
|
||||
if(prev) {
|
||||
prev->next = t->next;
|
||||
} else {
|
||||
SDL_timers = t->next;
|
||||
}
|
||||
SDL_free(t);
|
||||
--SDL_timer_running;
|
||||
removed = SDL_TRUE;
|
||||
list_changed = SDL_TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
#ifdef DEBUG_TIMERS
|
||||
printf("SDL_RemoveTimer(%08x) = %d num_timers = %d thread = %d\n", (Uint32)id, removed, SDL_timer_running, SDL_ThreadID());
|
||||
#endif
|
||||
SDL_mutexV(SDL_timer_mutex);
|
||||
return removed;
|
||||
}
|
||||
|
||||
/* Old style callback functions are wrapped through this */
|
||||
static Uint32 SDLCALL callback_wrapper(Uint32 ms, void *param)
|
||||
{
|
||||
SDL_TimerCallback func = (SDL_TimerCallback) param;
|
||||
return (*func)(ms);
|
||||
}
|
||||
|
||||
int SDL_SetTimer(Uint32 ms, SDL_TimerCallback callback)
|
||||
{
|
||||
int retval;
|
||||
|
||||
#ifdef DEBUG_TIMERS
|
||||
printf("SDL_SetTimer(%d)\n", ms);
|
||||
#endif
|
||||
retval = 0;
|
||||
|
||||
if ( SDL_timer_threaded ) {
|
||||
SDL_mutexP(SDL_timer_mutex);
|
||||
}
|
||||
if ( SDL_timer_running ) { /* Stop any currently running timer */
|
||||
if ( SDL_timer_threaded ) {
|
||||
while ( SDL_timers ) {
|
||||
SDL_TimerID freeme = SDL_timers;
|
||||
SDL_timers = SDL_timers->next;
|
||||
SDL_free(freeme);
|
||||
}
|
||||
SDL_timer_running = 0;
|
||||
list_changed = SDL_TRUE;
|
||||
} else {
|
||||
SDL_SYS_StopTimer();
|
||||
SDL_timer_running = 0;
|
||||
}
|
||||
}
|
||||
if ( ms ) {
|
||||
if ( SDL_timer_threaded ) {
|
||||
if ( SDL_AddTimerInternal(ms, callback_wrapper, (void *)callback) == NULL ) {
|
||||
retval = -1;
|
||||
}
|
||||
} else {
|
||||
SDL_timer_running = 1;
|
||||
SDL_alarm_interval = ms;
|
||||
SDL_alarm_callback = callback;
|
||||
retval = SDL_SYS_StartTimer();
|
||||
}
|
||||
}
|
||||
if ( SDL_timer_threaded ) {
|
||||
SDL_mutexV(SDL_timer_mutex);
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
46
apps/plugins/sdl/src/timer/SDL_timer_c.h
Normal file
46
apps/plugins/sdl/src/timer/SDL_timer_c.h
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
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"
|
||||
|
||||
/* Useful functions and variables from SDL_timer.c */
|
||||
#include "SDL_timer.h"
|
||||
|
||||
#define ROUND_RESOLUTION(X) \
|
||||
(((X+TIMER_RESOLUTION-1)/TIMER_RESOLUTION)*TIMER_RESOLUTION)
|
||||
|
||||
extern int SDL_timer_started;
|
||||
extern int SDL_timer_running;
|
||||
|
||||
/* Data to handle a single periodic alarm */
|
||||
extern Uint32 SDL_alarm_interval;
|
||||
extern SDL_TimerCallback SDL_alarm_callback;
|
||||
|
||||
/* Set whether or not the timer should use a thread.
|
||||
This should be called while the timer subsystem is running.
|
||||
*/
|
||||
extern int SDL_SetTimerThreaded(int value);
|
||||
|
||||
extern int SDL_TimerInit(void);
|
||||
extern void SDL_TimerQuit(void);
|
||||
|
||||
/* This function is called from the SDL event thread if it is available */
|
||||
extern void SDL_ThreadedTimerCheck(void);
|
||||
95
apps/plugins/sdl/src/timer/beos/SDL_systimer.c
Normal file
95
apps/plugins/sdl/src/timer/beos/SDL_systimer.c
Normal file
|
|
@ -0,0 +1,95 @@
|
|||
/*
|
||||
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_BEOS
|
||||
|
||||
#include <be/kernel/OS.h>
|
||||
|
||||
#include "SDL_thread.h"
|
||||
#include "SDL_timer.h"
|
||||
#include "../SDL_timer_c.h"
|
||||
|
||||
static bigtime_t start;
|
||||
|
||||
void SDL_StartTicks(void)
|
||||
{
|
||||
/* Set first ticks value */
|
||||
start = system_time();
|
||||
}
|
||||
|
||||
Uint32 SDL_GetTicks(void)
|
||||
{
|
||||
return((system_time()-start)/1000);
|
||||
}
|
||||
|
||||
void SDL_Delay(Uint32 ms)
|
||||
{
|
||||
snooze(ms*1000);
|
||||
}
|
||||
|
||||
/* Data to handle a single periodic alarm */
|
||||
static int timer_alive = 0;
|
||||
static SDL_Thread *timer = NULL;
|
||||
|
||||
static int RunTimer(void *unused)
|
||||
{
|
||||
while ( timer_alive ) {
|
||||
if ( SDL_timer_running ) {
|
||||
SDL_ThreadedTimerCheck();
|
||||
}
|
||||
SDL_Delay(10);
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
/* This is only called if the event thread is not running */
|
||||
int SDL_SYS_TimerInit(void)
|
||||
{
|
||||
timer_alive = 1;
|
||||
timer = SDL_CreateThread(RunTimer, NULL);
|
||||
if ( timer == NULL )
|
||||
return(-1);
|
||||
return(SDL_SetTimerThreaded(1));
|
||||
}
|
||||
|
||||
void SDL_SYS_TimerQuit(void)
|
||||
{
|
||||
timer_alive = 0;
|
||||
if ( timer ) {
|
||||
SDL_WaitThread(timer, NULL);
|
||||
timer = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
int SDL_SYS_StartTimer(void)
|
||||
{
|
||||
SDL_SetError("Internal logic error: BeOS uses threaded timer");
|
||||
return(-1);
|
||||
}
|
||||
|
||||
void SDL_SYS_StopTimer(void)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
#endif /* SDL_TIMER_BEOS */
|
||||
100
apps/plugins/sdl/src/timer/dc/SDL_systimer.c
Normal file
100
apps/plugins/sdl/src/timer/dc/SDL_systimer.c
Normal file
|
|
@ -0,0 +1,100 @@
|
|||
/*
|
||||
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_DC
|
||||
|
||||
#include <kos.h>
|
||||
|
||||
#include "SDL_thread.h"
|
||||
#include "SDL_timer.h"
|
||||
#include "../SDL_timer_c.h"
|
||||
|
||||
static unsigned start;
|
||||
|
||||
/*
|
||||
jif = ms * HZ /1000
|
||||
ms = jif * 1000/HZ
|
||||
*/
|
||||
|
||||
void SDL_StartTicks(void)
|
||||
{
|
||||
/* Set first ticks value */
|
||||
start = jiffies;
|
||||
}
|
||||
|
||||
Uint32 SDL_GetTicks(void)
|
||||
{
|
||||
return((jiffies-start)*1000/HZ);
|
||||
}
|
||||
|
||||
void SDL_Delay(Uint32 ms)
|
||||
{
|
||||
thd_sleep(ms);
|
||||
}
|
||||
|
||||
/* Data to handle a single periodic alarm */
|
||||
static int timer_alive = 0;
|
||||
static SDL_Thread *timer = NULL;
|
||||
|
||||
static int RunTimer(void *unused)
|
||||
{
|
||||
while ( timer_alive ) {
|
||||
if ( SDL_timer_running ) {
|
||||
SDL_ThreadedTimerCheck();
|
||||
}
|
||||
SDL_Delay(10);
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
/* This is only called if the event thread is not running */
|
||||
int SDL_SYS_TimerInit(void)
|
||||
{
|
||||
timer_alive = 1;
|
||||
timer = SDL_CreateThread(RunTimer, NULL);
|
||||
if ( timer == NULL )
|
||||
return(-1);
|
||||
return(SDL_SetTimerThreaded(1));
|
||||
}
|
||||
|
||||
void SDL_SYS_TimerQuit(void)
|
||||
{
|
||||
timer_alive = 0;
|
||||
if ( timer ) {
|
||||
SDL_WaitThread(timer, NULL);
|
||||
timer = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
int SDL_SYS_StartTimer(void)
|
||||
{
|
||||
SDL_SetError("Internal logic error: DC uses threaded timer");
|
||||
return(-1);
|
||||
}
|
||||
|
||||
void SDL_SYS_StopTimer(void)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
#endif /* SDL_TIMER_DC */
|
||||
91
apps/plugins/sdl/src/timer/dummy/SDL_systimer.c
Normal file
91
apps/plugins/sdl/src/timer/dummy/SDL_systimer.c
Normal file
|
|
@ -0,0 +1,91 @@
|
|||
/*
|
||||
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"
|
||||
|
||||
#if defined(SDL_TIMER_DUMMY) || defined(SDL_TIMERS_DISABLED)
|
||||
|
||||
#include "SDL_timer.h"
|
||||
#include "../SDL_timer_c.h"
|
||||
|
||||
void SDL_StartTicks(void)
|
||||
{
|
||||
}
|
||||
|
||||
Uint32 SDL_GetTicks (void)
|
||||
{
|
||||
SDL_Unsupported();
|
||||
return 0;
|
||||
}
|
||||
|
||||
void SDL_Delay (Uint32 ms)
|
||||
{
|
||||
SDL_Unsupported();
|
||||
}
|
||||
|
||||
#include "SDL_thread.h"
|
||||
|
||||
/* Data to handle a single periodic alarm */
|
||||
static int timer_alive = 0;
|
||||
static SDL_Thread *timer = NULL;
|
||||
|
||||
static int RunTimer(void *unused)
|
||||
{
|
||||
while ( timer_alive ) {
|
||||
if ( SDL_timer_running ) {
|
||||
SDL_ThreadedTimerCheck();
|
||||
}
|
||||
SDL_Delay(1);
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
/* This is only called if the event thread is not running */
|
||||
int SDL_SYS_TimerInit(void)
|
||||
{
|
||||
timer_alive = 1;
|
||||
timer = SDL_CreateThread(RunTimer, NULL);
|
||||
if ( timer == NULL )
|
||||
return(-1);
|
||||
return(SDL_SetTimerThreaded(1));
|
||||
}
|
||||
|
||||
void SDL_SYS_TimerQuit(void)
|
||||
{
|
||||
timer_alive = 0;
|
||||
if ( timer ) {
|
||||
SDL_WaitThread(timer, NULL);
|
||||
timer = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
int SDL_SYS_StartTimer(void)
|
||||
{
|
||||
SDL_SetError("Internal logic error: threaded timer in use");
|
||||
return(-1);
|
||||
}
|
||||
|
||||
void SDL_SYS_StopTimer(void)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
#endif /* SDL_TIMER_DUMMY || SDL_TIMERS_DISABLED */
|
||||
352
apps/plugins/sdl/src/timer/macos/FastTimes.c
Normal file
352
apps/plugins/sdl/src/timer/macos/FastTimes.c
Normal file
|
|
@ -0,0 +1,352 @@
|
|||
/* 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-2012. 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 µ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<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 */
|
||||
27
apps/plugins/sdl/src/timer/macos/FastTimes.h
Normal file
27
apps/plugins/sdl/src/timer/macos/FastTimes.h
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
/* 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-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__ */
|
||||
152
apps/plugins/sdl/src/timer/macos/SDL_MPWtimer.c
Normal file
152
apps/plugins/sdl/src/timer/macos/SDL_MPWtimer.c
Normal file
|
|
@ -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 <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 */
|
||||
186
apps/plugins/sdl/src/timer/macos/SDL_systimer.c
Normal file
186
apps/plugins/sdl/src/timer/macos/SDL_systimer.c
Normal file
|
|
@ -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 <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 */
|
||||
149
apps/plugins/sdl/src/timer/mint/SDL_systimer.c
Normal file
149
apps/plugins/sdl/src/timer/mint/SDL_systimer.c
Normal file
|
|
@ -0,0 +1,149 @@
|
|||
/*
|
||||
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_MINT
|
||||
|
||||
/*
|
||||
* TOS/MiNT timer driver
|
||||
* based on vbl vector
|
||||
*
|
||||
* Patrice Mandin
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <sys/time.h>
|
||||
#include <signal.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <mint/cookie.h>
|
||||
#include <mint/sysvars.h>
|
||||
#include <mint/osbind.h>
|
||||
#include <mint/mintbind.h>
|
||||
|
||||
#include "SDL_timer.h"
|
||||
#include "../SDL_timer_c.h"
|
||||
#include "SDL_thread.h"
|
||||
|
||||
#include "../../video/ataricommon/SDL_atarisuper.h"
|
||||
|
||||
#include "SDL_vbltimer_s.h"
|
||||
|
||||
/* from audio/mint */
|
||||
void SDL_MintAudio_CheckFpu(void);
|
||||
|
||||
/* The first ticks value of the application */
|
||||
static Uint32 start;
|
||||
static SDL_bool read_hz200_from_vbl = SDL_FALSE;
|
||||
static int mint_present; /* can we use Syield() ? */
|
||||
|
||||
void SDL_StartTicks(void)
|
||||
{
|
||||
void *old_stack;
|
||||
long dummy;
|
||||
|
||||
/* Set first ticks value */
|
||||
old_stack = (void *)Super(0);
|
||||
start = *((volatile long *)_hz_200);
|
||||
SuperToUser(old_stack);
|
||||
|
||||
start *= 5; /* One _hz_200 tic is 5ms */
|
||||
|
||||
mint_present = (Getcookie(C_MiNT, &dummy) == C_FOUND);
|
||||
}
|
||||
|
||||
Uint32 SDL_GetTicks (void)
|
||||
{
|
||||
Uint32 now = start;
|
||||
|
||||
if (read_hz200_from_vbl) {
|
||||
now = SDL_Atari_hz200;
|
||||
} else {
|
||||
void *old_stack = (void *)Super(0);
|
||||
now = *((volatile long *)_hz_200);
|
||||
SuperToUser(old_stack);
|
||||
}
|
||||
|
||||
return((now*5)-start);
|
||||
}
|
||||
|
||||
void SDL_Delay (Uint32 ms)
|
||||
{
|
||||
Uint32 now;
|
||||
|
||||
now = SDL_GetTicks();
|
||||
while ((SDL_GetTicks()-now)<ms){
|
||||
if (mint_present) {
|
||||
Syield();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Data to handle a single periodic alarm */
|
||||
static SDL_bool timer_installed=SDL_FALSE;
|
||||
|
||||
/* This is only called if the event thread is not running */
|
||||
int SDL_SYS_TimerInit(void)
|
||||
{
|
||||
void *old_stack;
|
||||
|
||||
SDL_MintAudio_CheckFpu();
|
||||
|
||||
/* Install RunTimer in vbl vector */
|
||||
old_stack = (void *)Super(0);
|
||||
timer_installed = !SDL_AtariVblInstall(SDL_ThreadedTimerCheck);
|
||||
SuperToUser(old_stack);
|
||||
|
||||
if (!timer_installed) {
|
||||
return(-1);
|
||||
}
|
||||
|
||||
read_hz200_from_vbl = SDL_TRUE;
|
||||
return(SDL_SetTimerThreaded(0));
|
||||
}
|
||||
|
||||
void SDL_SYS_TimerQuit(void)
|
||||
{
|
||||
/* Uninstall RunTimer vbl vector */
|
||||
if (timer_installed) {
|
||||
void *old_stack = (void *)Super(0);
|
||||
SDL_AtariVblUninstall(SDL_ThreadedTimerCheck);
|
||||
SuperToUser(old_stack);
|
||||
timer_installed = SDL_FALSE;
|
||||
}
|
||||
read_hz200_from_vbl = SDL_FALSE;
|
||||
}
|
||||
|
||||
int SDL_SYS_StartTimer(void)
|
||||
{
|
||||
SDL_SetError("Internal logic error: MiNT uses vbl timer");
|
||||
return(-1);
|
||||
}
|
||||
|
||||
void SDL_SYS_StopTimer(void)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
#endif /* SDL_TIMER_MINT */
|
||||
228
apps/plugins/sdl/src/timer/mint/SDL_vbltimer.S
Normal file
228
apps/plugins/sdl/src/timer/mint/SDL_vbltimer.S
Normal file
|
|
@ -0,0 +1,228 @@
|
|||
/*
|
||||
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
|
||||
*/
|
||||
|
||||
/*
|
||||
* VBL queue routine
|
||||
*
|
||||
* Patrice Mandin
|
||||
*/
|
||||
|
||||
#define _vbl_queue 0x456
|
||||
#define _hz_200 0x4ba
|
||||
|
||||
.text
|
||||
|
||||
.globl _SDL_AtariVblInstall
|
||||
.globl _SDL_AtariVblUninstall
|
||||
|
||||
.globl _SDL_MintAudio_hasfpu
|
||||
|
||||
/*--- Save/restore FPU context ---*/
|
||||
|
||||
#if defined(__mcoldfire__)
|
||||
|
||||
#define SAVE_FPU_CONTEXT \
|
||||
lea sp@(-216),sp; \
|
||||
fsave sp@; \
|
||||
fmovel fpiar,sp@-; \
|
||||
lea sp@(-64),sp; \
|
||||
fmovemd fp0-fp7,sp@
|
||||
|
||||
#define RESTORE_FPU_CONTEXT \
|
||||
fmovemd sp@,fp0-fp7; \
|
||||
lea sp@(64),sp; \
|
||||
fmovel sp@+,fpiar; \
|
||||
frestore sp@; \
|
||||
lea sp@(216),sp
|
||||
|
||||
#else
|
||||
|
||||
#define SAVE_FPU_CONTEXT \
|
||||
.chip 68k/68881; \
|
||||
fsave sp@-; \
|
||||
fmoveml fpcr/fpsr/fpiar,sp@-; \
|
||||
fmovemx fp0-fp7,sp@-; \
|
||||
.chip 68k
|
||||
|
||||
#define RESTORE_FPU_CONTEXT \
|
||||
.chip 68k/68881; \
|
||||
fmovemx sp@+,fp0-fp7; \
|
||||
fmoveml sp@+,fpcr/fpsr/fpiar; \
|
||||
frestore sp@+; \
|
||||
.chip 68k
|
||||
|
||||
#endif
|
||||
|
||||
/*--- Vector installer ---*/
|
||||
|
||||
_SDL_AtariVblInstall:
|
||||
#if defined(__mcoldfire__)
|
||||
movel sp@(4),d0
|
||||
movel d0,my_vector
|
||||
#else
|
||||
movel sp@(4),my_vector
|
||||
#endif
|
||||
|
||||
lea _my_vbl,a0
|
||||
|
||||
clrw vbl_mutex
|
||||
#if defined(__mcoldfire__)
|
||||
movel _hz_200.w,d0
|
||||
movel d0, _SDL_Atari_hz200
|
||||
#else
|
||||
movel _hz_200.w, _SDL_Atari_hz200
|
||||
#endif
|
||||
|
||||
/* Stop interrupts */
|
||||
|
||||
movew #0x2700,sr
|
||||
|
||||
/* Read vbl_queue pointer */
|
||||
movel _vbl_queue.w,a1
|
||||
|
||||
/* Search a free place */
|
||||
moveq #7,d0
|
||||
bcl_search_place:
|
||||
movel (a1),d1
|
||||
beqs place_found
|
||||
addql #4,a1
|
||||
#if defined(__mcoldfire__)
|
||||
subql #1,d0
|
||||
bpls bcl_search_place
|
||||
#else
|
||||
dbra d0,bcl_search_place
|
||||
#endif
|
||||
|
||||
/* Not found */
|
||||
moveq #1,d0
|
||||
bras exit_vbl_queue
|
||||
|
||||
/* Then install ourselves */
|
||||
place_found:
|
||||
movel a0,(a1)
|
||||
moveq #0,d0
|
||||
|
||||
exit_vbl_queue:
|
||||
/* Restart interrupts */
|
||||
movew #0x2300,sr
|
||||
|
||||
rts
|
||||
|
||||
/*--- Vector uninstaller ---*/
|
||||
|
||||
_SDL_AtariVblUninstall:
|
||||
movel sp@(4),d0
|
||||
cmpl my_vector,d0
|
||||
bnes badvector
|
||||
|
||||
movel #_my_vbl,d0
|
||||
|
||||
/* Stop interrupts */
|
||||
|
||||
movew #0x2700,sr
|
||||
|
||||
/* Read vbl_queue pointer */
|
||||
movel _vbl_queue.w,a1
|
||||
|
||||
/* Search where we are */
|
||||
moveq #7,d1
|
||||
bcl2_search_place:
|
||||
cmpl (a1),d0
|
||||
bnes next_place
|
||||
clrl (a1)
|
||||
moveq #0,d1
|
||||
next_place:
|
||||
addql #4,a1
|
||||
#if defined(__mcoldfire__)
|
||||
subql #1,d1
|
||||
bpls bcl_search_place
|
||||
#else
|
||||
dbra d1,bcl2_search_place
|
||||
#endif
|
||||
|
||||
/* Restart interrupts */
|
||||
movew #0x2300,sr
|
||||
badvector:
|
||||
rts
|
||||
|
||||
/*--- Our vbl ---*/
|
||||
|
||||
_my_vbl:
|
||||
#if defined(__mcoldfire__)
|
||||
lea sp@(-60),sp
|
||||
moveml d0-d7/a0-a6,sp@
|
||||
#else
|
||||
moveml d0-d7/a0-a6,sp@-
|
||||
#endif
|
||||
|
||||
/* Update _hz_200 */
|
||||
#if defined(__mcoldfire__)
|
||||
movel _hz_200.w,d0
|
||||
movel d0, _SDL_Atari_hz200
|
||||
#else
|
||||
movel _hz_200.w, _SDL_Atari_hz200
|
||||
#endif
|
||||
|
||||
/* Verify if this is not already running */
|
||||
|
||||
tstw vbl_mutex
|
||||
bnes vbl_end
|
||||
#if defined(__mcoldfire__)
|
||||
movew vbl_mutex,d0
|
||||
notl d0
|
||||
movew d0,vbl_mutex
|
||||
#else
|
||||
notw vbl_mutex
|
||||
#endif
|
||||
|
||||
/* Save FPU if needed */
|
||||
tstw _SDL_MintAudio_hasfpu
|
||||
beqs SDL_AtariVbl_nofpu1
|
||||
SAVE_FPU_CONTEXT
|
||||
SDL_AtariVbl_nofpu1:
|
||||
|
||||
movel my_vector,a0
|
||||
jsr a0@
|
||||
|
||||
/* Restore FPU if needed */
|
||||
tstw _SDL_MintAudio_hasfpu
|
||||
beqs SDL_AtariVbl_Xbios_nofpu2
|
||||
RESTORE_FPU_CONTEXT
|
||||
SDL_AtariVbl_Xbios_nofpu2:
|
||||
|
||||
clrw vbl_mutex
|
||||
vbl_end:
|
||||
#if defined(__mcoldfire__)
|
||||
moveml sp@,d0-d7/a0-a6
|
||||
lea sp@(60),sp
|
||||
#else
|
||||
moveml sp@+,d0-d7/a0-a6
|
||||
#endif
|
||||
rts
|
||||
|
||||
.data
|
||||
.even
|
||||
.comm _SDL_Atari_hz200,4*1
|
||||
.even
|
||||
.comm vbl_mutex,2*1
|
||||
.even
|
||||
.comm my_vector,4*1
|
||||
35
apps/plugins/sdl/src/timer/mint/SDL_vbltimer_s.h
Normal file
35
apps/plugins/sdl/src/timer/mint/SDL_vbltimer_s.h
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
/*
|
||||
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"
|
||||
|
||||
/*
|
||||
* TOS/MiNT timer driver
|
||||
* based on vbl vector
|
||||
*
|
||||
* Patrice Mandin
|
||||
*/
|
||||
|
||||
extern volatile long SDL_Atari_hz200;
|
||||
|
||||
/* Functions prototypes */
|
||||
extern int SDL_AtariVblInstall(void *newvector);
|
||||
extern void SDL_AtariVblUninstall(void *newvector);
|
||||
73
apps/plugins/sdl/src/timer/nds/SDL_systimer.c
Normal file
73
apps/plugins/sdl/src/timer/nds/SDL_systimer.c
Normal file
|
|
@ -0,0 +1,73 @@
|
|||
/*
|
||||
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"
|
||||
|
||||
#include "SDL_thread.h"
|
||||
#include "SDL_timer.h"
|
||||
#include "SDL_error.h"
|
||||
#include "../SDL_timer_c.h"
|
||||
|
||||
#include <nds.h>
|
||||
|
||||
#define timers2ms(tlow,thigh)(tlow | (thigh<<16)) >> 5
|
||||
|
||||
|
||||
void SDL_StartTicks(void)
|
||||
{
|
||||
TIMER0_DATA=0;
|
||||
TIMER1_DATA=0;
|
||||
TIMER0_CR=TIMER_ENABLE|TIMER_DIV_1024;
|
||||
TIMER1_CR=TIMER_ENABLE|TIMER_CASCADE;
|
||||
}
|
||||
|
||||
Uint32 SDL_GetTicks(void)
|
||||
{
|
||||
return timers2ms(TIMER0_DATA, TIMER1_DATA);
|
||||
}
|
||||
|
||||
void SDL_Delay(Uint32 ms)
|
||||
{
|
||||
Uint32 now;
|
||||
now=timers2ms(TIMER0_DATA, TIMER1_DATA);
|
||||
while((Uint32)timers2ms(TIMER0_DATA, TIMER1_DATA)<now+ms);
|
||||
|
||||
}
|
||||
|
||||
/* This is only called if the event thread is not running */
|
||||
int SDL_SYS_TimerInit(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void SDL_SYS_TimerQuit(void)
|
||||
{
|
||||
}
|
||||
|
||||
int SDL_SYS_StartTimer(void)
|
||||
{
|
||||
SDL_SetError("Timers not implemented on NDS");
|
||||
return -1;
|
||||
}
|
||||
|
||||
void SDL_SYS_StopTimer(void)
|
||||
{
|
||||
}
|
||||
227
apps/plugins/sdl/src/timer/os2/SDL_systimer.c
Normal file
227
apps/plugins/sdl/src/timer/os2/SDL_systimer.c
Normal file
|
|
@ -0,0 +1,227 @@
|
|||
/*
|
||||
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_OS2
|
||||
|
||||
#define INCL_DOSMISC
|
||||
#define INCL_DOSERRORS
|
||||
#define INCL_DOSSEMAPHORES
|
||||
#define INCL_DOSDATETIME
|
||||
#define INCL_DOSPROCESS
|
||||
#define INCL_DOSPROFILE
|
||||
#define INCL_DOSEXCEPTIONS
|
||||
#include <os2.h>
|
||||
|
||||
#include "SDL_thread.h"
|
||||
#include "SDL_timer.h"
|
||||
#include "../SDL_timer_c.h"
|
||||
|
||||
|
||||
#define TIME_WRAP_VALUE (~(DWORD)0)
|
||||
|
||||
/* The first high-resolution ticks value of the application */
|
||||
static long long hires_start_ticks;
|
||||
/* The number of ticks per second of the high-resolution performance counter */
|
||||
static ULONG hires_ticks_per_second;
|
||||
|
||||
void SDL_StartTicks(void)
|
||||
{
|
||||
DosTmrQueryFreq(&hires_ticks_per_second);
|
||||
DosTmrQueryTime((PQWORD)&hires_start_ticks);
|
||||
}
|
||||
|
||||
DECLSPEC Uint32 SDLCALL SDL_GetTicks(void)
|
||||
{
|
||||
long long hires_now;
|
||||
ULONG ticks = ticks;
|
||||
|
||||
DosTmrQueryTime((PQWORD)&hires_now);
|
||||
/*
|
||||
hires_now -= hires_start_ticks;
|
||||
hires_now *= 1000;
|
||||
hires_now /= hires_ticks_per_second;
|
||||
*/
|
||||
/* inline asm to avoid runtime inclusion */
|
||||
_asm {
|
||||
push edx
|
||||
push eax
|
||||
mov eax, dword ptr hires_now
|
||||
mov edx, dword ptr hires_now+4
|
||||
sub eax, dword ptr hires_start_ticks
|
||||
sbb edx, dword ptr hires_start_ticks+4
|
||||
mov ebx,1000
|
||||
mov ecx,edx
|
||||
mul ebx
|
||||
push eax
|
||||
push edx
|
||||
mov eax,ecx
|
||||
mul ebx
|
||||
pop eax
|
||||
add edx,eax
|
||||
pop eax
|
||||
mov ebx, dword ptr hires_ticks_per_second
|
||||
div ebx
|
||||
mov dword ptr ticks, eax
|
||||
pop edx
|
||||
pop eax
|
||||
}
|
||||
|
||||
return ticks;
|
||||
|
||||
}
|
||||
|
||||
/* High resolution sleep, originally made by Ilya Zakharevich */
|
||||
DECLSPEC void SDLCALL SDL_Delay(Uint32 ms)
|
||||
{
|
||||
/* This is similar to DosSleep(), but has 8ms granularity in time-critical
|
||||
threads even on Warp3. */
|
||||
HEV hevEvent1 = 0; /* Event semaphore handle */
|
||||
HTIMER htimerEvent1 = 0; /* Timer handle */
|
||||
APIRET rc = NO_ERROR; /* Return code */
|
||||
int ret = 1;
|
||||
ULONG priority = 0, nesting; /* Shut down the warnings */
|
||||
PPIB pib;
|
||||
PTIB tib;
|
||||
char *e = NULL;
|
||||
APIRET badrc;
|
||||
int switch_priority = 50;
|
||||
|
||||
DosCreateEventSem(NULL, /* Unnamed */
|
||||
&hevEvent1, /* Handle of semaphore returned */
|
||||
DC_SEM_SHARED, /* Shared needed for DosAsyncTimer */
|
||||
FALSE); /* Semaphore is in RESET state */
|
||||
|
||||
if (ms >= switch_priority)
|
||||
switch_priority = 0;
|
||||
if (switch_priority)
|
||||
{
|
||||
if (DosGetInfoBlocks(&tib, &pib)!=NO_ERROR)
|
||||
switch_priority = 0;
|
||||
else
|
||||
{
|
||||
/* In Warp3, to switch scheduling to 8ms step, one needs to do
|
||||
DosAsyncTimer() in time-critical thread. On laters versions,
|
||||
more and more cases of wait-for-something are covered.
|
||||
|
||||
It turns out that on Warp3fp42 it is the priority at the time
|
||||
of DosAsyncTimer() which matters. Let's hope that this works
|
||||
with later versions too... XXXX
|
||||
*/
|
||||
priority = (tib->tib_ptib2->tib2_ulpri);
|
||||
if ((priority & 0xFF00) == 0x0300) /* already time-critical */
|
||||
switch_priority = 0;
|
||||
/* Make us time-critical. Just modifying TIB is not enough... */
|
||||
/* tib->tib_ptib2->tib2_ulpri = 0x0300;*/
|
||||
/* We do not want to run at high priority if a signal causes us
|
||||
to longjmp() out of this section... */
|
||||
if (DosEnterMustComplete(&nesting))
|
||||
switch_priority = 0;
|
||||
else
|
||||
DosSetPriority(PRTYS_THREAD, PRTYC_TIMECRITICAL, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
if ((badrc = DosAsyncTimer(ms,
|
||||
(HSEM) hevEvent1, /* Semaphore to post */
|
||||
&htimerEvent1))) /* Timer handler (returned) */
|
||||
e = "DosAsyncTimer";
|
||||
|
||||
if (switch_priority && tib->tib_ptib2->tib2_ulpri == 0x0300)
|
||||
{
|
||||
/* Nobody switched priority while we slept... Ignore errors... */
|
||||
/* tib->tib_ptib2->tib2_ulpri = priority; */ /* Get back... */
|
||||
if (!(rc = DosSetPriority(PRTYS_THREAD, (priority>>8) & 0xFF, 0, 0)))
|
||||
rc = DosSetPriority(PRTYS_THREAD, 0, priority & 0xFF, 0);
|
||||
}
|
||||
if (switch_priority)
|
||||
rc = DosExitMustComplete(&nesting); /* Ignore errors */
|
||||
|
||||
/* The actual blocking call is made with "normal" priority. This way we
|
||||
should not bother with DosSleep(0) etc. to compensate for us interrupting
|
||||
higher-priority threads. The goal is to prohibit the system spending too
|
||||
much time halt()ing, not to run us "no matter what". */
|
||||
if (!e) /* Wait for AsyncTimer event */
|
||||
badrc = DosWaitEventSem(hevEvent1, SEM_INDEFINITE_WAIT);
|
||||
|
||||
if (e) ; /* Do nothing */
|
||||
else if (badrc == ERROR_INTERRUPT)
|
||||
ret = 0;
|
||||
else if (badrc)
|
||||
e = "DosWaitEventSem";
|
||||
if ((rc = DosCloseEventSem(hevEvent1)) && !e) { /* Get rid of semaphore */
|
||||
e = "DosCloseEventSem";
|
||||
badrc = rc;
|
||||
}
|
||||
if (e)
|
||||
{
|
||||
SDL_SetError("[SDL_Delay] : Had error in %s(), rc is 0x%x\n", e, badrc);
|
||||
}
|
||||
}
|
||||
|
||||
/* Data to handle a single periodic alarm */
|
||||
static int timer_alive = 0;
|
||||
static SDL_Thread *timer = NULL;
|
||||
|
||||
static int SDLCALL RunTimer(void *unused)
|
||||
{
|
||||
DosSetPriority(PRTYS_THREAD, PRTYC_TIMECRITICAL, 0, 0);
|
||||
while ( timer_alive ) {
|
||||
if ( SDL_timer_running ) {
|
||||
SDL_ThreadedTimerCheck();
|
||||
}
|
||||
SDL_Delay(10);
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
/* This is only called if the event thread is not running */
|
||||
int SDL_SYS_TimerInit(void)
|
||||
{
|
||||
timer_alive = 1;
|
||||
timer = SDL_CreateThread(RunTimer, NULL);
|
||||
if ( timer == NULL )
|
||||
return(-1);
|
||||
return(SDL_SetTimerThreaded(1));
|
||||
}
|
||||
|
||||
void SDL_SYS_TimerQuit(void)
|
||||
{
|
||||
timer_alive = 0;
|
||||
if ( timer ) {
|
||||
SDL_WaitThread(timer, NULL);
|
||||
timer = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
int SDL_SYS_StartTimer(void)
|
||||
{
|
||||
SDL_SetError("Internal logic error: OS/2 uses threaded timer");
|
||||
return(-1);
|
||||
}
|
||||
|
||||
void SDL_SYS_StopTimer(void)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
#endif /* SDL_TIMER_OS2 */
|
||||
233
apps/plugins/sdl/src/timer/riscos/SDL_systimer.c
Normal file
233
apps/plugins/sdl/src/timer/riscos/SDL_systimer.c
Normal file
|
|
@ -0,0 +1,233 @@
|
|||
/*
|
||||
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_RISCOS
|
||||
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
#include <sys/time.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "SDL_timer.h"
|
||||
#include "../SDL_timer_c.h"
|
||||
|
||||
#if SDL_THREADS_DISABLED
|
||||
/* Timer SDL_arraysize(Timer ),start/reset time */
|
||||
static Uint32 timerStart;
|
||||
/* Timer running function */
|
||||
void RISCOS_CheckTimer();
|
||||
#else
|
||||
#include <pthread.h>
|
||||
extern Uint32 riscos_main_thread;
|
||||
extern int riscos_using_threads;
|
||||
extern Uint32 SDL_ThreadID();
|
||||
extern Uint32 SDL_EventThreadID(void);
|
||||
#endif
|
||||
|
||||
|
||||
extern void RISCOS_BackgroundTasks(void);
|
||||
|
||||
/* The first ticks value of the application */
|
||||
clock_t start;
|
||||
|
||||
void SDL_StartTicks(void)
|
||||
{
|
||||
/* Set first ticks value */
|
||||
start = clock();
|
||||
}
|
||||
|
||||
Uint32 SDL_GetTicks (void)
|
||||
{
|
||||
clock_t ticks;
|
||||
|
||||
ticks=clock()-start;
|
||||
|
||||
|
||||
#if CLOCKS_PER_SEC == 1000
|
||||
|
||||
return(ticks);
|
||||
|
||||
#elif CLOCKS_PER_SEC == 100
|
||||
|
||||
return (ticks * 10);
|
||||
|
||||
#else
|
||||
|
||||
return ticks*(1000/CLOCKS_PER_SEC);
|
||||
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
void SDL_Delay (Uint32 ms)
|
||||
{
|
||||
Uint32 now,then,elapsed;
|
||||
#if !SDL_THREADS_DISABLED
|
||||
int is_event_thread;
|
||||
if (riscos_using_threads)
|
||||
{
|
||||
is_event_thread = 0;
|
||||
if (SDL_EventThreadID())
|
||||
{
|
||||
if (SDL_EventThreadID() == SDL_ThreadID()) is_event_thread = 1;
|
||||
} else if (SDL_ThreadID() == riscos_main_thread) is_event_thread = 1;
|
||||
} else is_event_thread = 1;
|
||||
#endif
|
||||
|
||||
/*TODO: Next version of Unixlib may allow us to use usleep here */
|
||||
/* for non event threads */
|
||||
|
||||
/* Set the timeout interval - Linux only needs to do this once */
|
||||
then = SDL_GetTicks();
|
||||
|
||||
do {
|
||||
/* Do background tasks required while sleeping as we are not multithreaded */
|
||||
#if SDL_THREADS_DISABLED
|
||||
RISCOS_BackgroundTasks();
|
||||
#else
|
||||
/* For threaded build only run background tasks in event thread */
|
||||
if (is_event_thread) RISCOS_BackgroundTasks();
|
||||
#endif
|
||||
|
||||
/* Calculate the time interval left (in case of interrupt) */
|
||||
now = SDL_GetTicks();
|
||||
elapsed = (now-then);
|
||||
then = now;
|
||||
if ( elapsed >= ms ) {
|
||||
break;
|
||||
}
|
||||
ms -= elapsed;
|
||||
#if !SDL_THREADS_DISABLED
|
||||
/* Need to yield to let other threads have a go */
|
||||
if (riscos_using_threads) pthread_yield();
|
||||
#endif
|
||||
|
||||
} while ( 1 );
|
||||
}
|
||||
|
||||
#if SDL_THREADS_DISABLED
|
||||
|
||||
/* Non-threaded version of timer */
|
||||
|
||||
int SDL_SYS_TimerInit(void)
|
||||
{
|
||||
return(0);
|
||||
}
|
||||
|
||||
void SDL_SYS_TimerQuit(void)
|
||||
{
|
||||
SDL_SetTimer(0, NULL);
|
||||
}
|
||||
|
||||
int SDL_SYS_StartTimer(void)
|
||||
{
|
||||
timerStart = SDL_GetTicks();
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
void SDL_SYS_StopTimer(void)
|
||||
{
|
||||
/* Don't need to do anything as we use SDL_timer_running
|
||||
to detect if we need to check the timer */
|
||||
}
|
||||
|
||||
|
||||
void RISCOS_CheckTimer()
|
||||
{
|
||||
if (SDL_timer_running && SDL_GetTicks() - timerStart >= SDL_alarm_interval)
|
||||
{
|
||||
Uint32 ms;
|
||||
|
||||
ms = SDL_alarm_callback(SDL_alarm_interval);
|
||||
if ( ms != SDL_alarm_interval )
|
||||
{
|
||||
if ( ms )
|
||||
{
|
||||
SDL_alarm_interval = ROUND_RESOLUTION(ms);
|
||||
} else
|
||||
{
|
||||
SDL_alarm_interval = 0;
|
||||
SDL_timer_running = 0;
|
||||
}
|
||||
}
|
||||
if (SDL_alarm_interval) timerStart = SDL_GetTicks();
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
/* Threaded version of timer - based on code for linux */
|
||||
|
||||
#include "SDL_thread.h"
|
||||
|
||||
/* Data to handle a single periodic alarm */
|
||||
static int timer_alive = 0;
|
||||
static SDL_Thread *timer = NULL;
|
||||
|
||||
static int RunTimer(void *unused)
|
||||
{
|
||||
while ( timer_alive ) {
|
||||
if ( SDL_timer_running ) {
|
||||
SDL_ThreadedTimerCheck();
|
||||
}
|
||||
SDL_Delay(1);
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
/* This is only called if the event thread is not running */
|
||||
int SDL_SYS_TimerInit(void)
|
||||
{
|
||||
timer_alive = 1;
|
||||
timer = SDL_CreateThread(RunTimer, NULL);
|
||||
if ( timer == NULL )
|
||||
return(-1);
|
||||
return(SDL_SetTimerThreaded(1));
|
||||
}
|
||||
|
||||
void SDL_SYS_TimerQuit(void)
|
||||
{
|
||||
timer_alive = 0;
|
||||
if ( timer ) {
|
||||
SDL_WaitThread(timer, NULL);
|
||||
timer = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
int SDL_SYS_StartTimer(void)
|
||||
{
|
||||
SDL_SetError("Internal logic error: RISC OS uses threaded timer");
|
||||
return(-1);
|
||||
}
|
||||
|
||||
void SDL_SYS_StopTimer(void)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
#endif /* SDL_THREADS_DISABLED */
|
||||
|
||||
#endif /* SDL_TIMER_RISCOS */
|
||||
117
apps/plugins/sdl/src/timer/rockbox/SDL_systimer.c
Normal file
117
apps/plugins/sdl/src/timer/rockbox/SDL_systimer.c
Normal file
|
|
@ -0,0 +1,117 @@
|
|||
/*
|
||||
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_ROCKBOX
|
||||
|
||||
#include "SDL_timer.h"
|
||||
#include "../SDL_timer_c.h"
|
||||
|
||||
#include "plugin.h"
|
||||
|
||||
#if defined(HAVE_LCD_COLOR) && !defined(SIMULATOR) && !defined(RB_PROFILE)
|
||||
#define USE_TIMER
|
||||
#endif
|
||||
|
||||
/* based off doom */
|
||||
#ifdef USE_TIMER
|
||||
static volatile unsigned int ticks = 0;
|
||||
|
||||
static void sdltime(void)
|
||||
{
|
||||
ticks++;
|
||||
}
|
||||
#else
|
||||
static unsigned long start;
|
||||
#endif
|
||||
|
||||
void SDL_StartTicks(void)
|
||||
{
|
||||
#ifdef USE_TIMER
|
||||
rb->timer_register(1, NULL, TIMER_FREQ/1000, sdltime IF_COP(, CPU));
|
||||
#else
|
||||
start = *rb->current_tick;
|
||||
#endif
|
||||
}
|
||||
|
||||
Uint32 SDL_GetTicks (void)
|
||||
{
|
||||
#ifdef USE_TIMER
|
||||
return ticks;
|
||||
#else
|
||||
return (*rb->current_tick - start) * (1000 / HZ);
|
||||
#endif
|
||||
}
|
||||
|
||||
void SDL_Delay (Uint32 ms)
|
||||
{
|
||||
rb->sleep(ms / (1000 / HZ));
|
||||
}
|
||||
|
||||
#include "SDL_thread.h"
|
||||
|
||||
/* Data to handle a single periodic alarm */
|
||||
static int timer_alive = 0;
|
||||
static SDL_Thread *timer = NULL;
|
||||
|
||||
static int RunTimer(void *unused)
|
||||
{
|
||||
while ( timer_alive ) {
|
||||
if ( SDL_timer_running ) {
|
||||
SDL_ThreadedTimerCheck();
|
||||
}
|
||||
SDL_Delay(1);
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
/* This is only called if the event thread is not running */
|
||||
int SDL_SYS_TimerInit(void)
|
||||
{
|
||||
timer_alive = 1;
|
||||
timer = SDL_CreateThread(RunTimer, NULL);
|
||||
if ( timer == NULL )
|
||||
return(-1);
|
||||
return(SDL_SetTimerThreaded(1));
|
||||
}
|
||||
|
||||
void SDL_SYS_TimerQuit(void)
|
||||
{
|
||||
timer_alive = 0;
|
||||
if ( timer ) {
|
||||
SDL_WaitThread(timer, NULL);
|
||||
timer = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
int SDL_SYS_StartTimer(void)
|
||||
{
|
||||
SDL_SetError("Internal logic error: threaded timer in use");
|
||||
return(-1);
|
||||
}
|
||||
|
||||
void SDL_SYS_StopTimer(void)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
#endif /* SDL_TIMER_DUMMY || SDL_TIMERS_DISABLED */
|
||||
114
apps/plugins/sdl/src/timer/symbian/SDL_systimer.cpp
Normal file
114
apps/plugins/sdl/src/timer/symbian/SDL_systimer.cpp
Normal file
|
|
@ -0,0 +1,114 @@
|
|||
/*
|
||||
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 Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 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
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the Free
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
Sam Lantinga
|
||||
slouken@devolution.com
|
||||
*/
|
||||
|
||||
/*
|
||||
SDL_systimer.cpp
|
||||
|
||||
Epoc version by Hannu Viitala (hannu.j.viitala@mbnet.fi)
|
||||
Markus Mertama
|
||||
*/
|
||||
|
||||
#include <e32std.h>
|
||||
#include <e32hal.h>
|
||||
|
||||
extern "C" {
|
||||
#include "SDL_error.h"
|
||||
#include "SDL_thread.h"
|
||||
#include "SDL_timer.h"
|
||||
#include "SDL_timer_c.h"
|
||||
|
||||
static TUint start = 0;
|
||||
static TInt tickPeriodMilliSeconds;
|
||||
|
||||
|
||||
void SDL_StartTicks(void)
|
||||
{
|
||||
/* Set first ticks value */
|
||||
start = User::TickCount();
|
||||
|
||||
TTimeIntervalMicroSeconds32 period;
|
||||
TInt tmp = UserHal::TickPeriod(period);
|
||||
tickPeriodMilliSeconds = period.Int() / 1000;
|
||||
}
|
||||
|
||||
Uint32 SDL_GetTicks(void)
|
||||
{
|
||||
TUint deltaTics = User::TickCount() - start;
|
||||
return(deltaTics * tickPeriodMilliSeconds);
|
||||
}
|
||||
|
||||
void SDL_Delay(Uint32 ms)
|
||||
{
|
||||
User::After(TTimeIntervalMicroSeconds32(ms*1000));
|
||||
}
|
||||
|
||||
/* Data to handle a single periodic alarm */
|
||||
static int timer_alive = 0;
|
||||
static SDL_Thread *timer = NULL;
|
||||
|
||||
static int RunTimer(void *unused)
|
||||
{
|
||||
while ( timer_alive )
|
||||
{
|
||||
if (SDL_timer_running)
|
||||
{
|
||||
SDL_ThreadedTimerCheck();
|
||||
}
|
||||
SDL_Delay(10);
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
/* This is only called if the event thread is not running */
|
||||
int SDL_SYS_TimerInit(void)
|
||||
{
|
||||
if(timer != NULL)
|
||||
return (-1);
|
||||
timer_alive = 1;
|
||||
timer = SDL_CreateThread(RunTimer, NULL);
|
||||
if ( timer == NULL )
|
||||
return(-1);
|
||||
return(SDL_SetTimerThreaded(1));
|
||||
}
|
||||
|
||||
void SDL_SYS_TimerQuit(void)
|
||||
{
|
||||
timer_alive = 0;
|
||||
if ( timer )
|
||||
{
|
||||
SDL_WaitThread(timer, NULL);
|
||||
timer = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
int SDL_SYS_StartTimer(void)
|
||||
{
|
||||
SDL_SetError("Internal logic error: Epoc uses threaded timer");
|
||||
return(-1);
|
||||
}
|
||||
|
||||
void SDL_SYS_StopTimer(void)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
} // extern "C"
|
||||
240
apps/plugins/sdl/src/timer/unix/SDL_systimer.c
Normal file
240
apps/plugins/sdl/src/timer/unix/SDL_systimer.c
Normal file
|
|
@ -0,0 +1,240 @@
|
|||
/*
|
||||
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_UNIX
|
||||
|
||||
#include <stdio.h>
|
||||
#include <sys/time.h>
|
||||
#include <signal.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "SDL_timer.h"
|
||||
#include "../SDL_timer_c.h"
|
||||
|
||||
/* The clock_gettime provides monotonous time, so we should use it if
|
||||
it's available. The clock_gettime function is behind ifdef
|
||||
for __USE_POSIX199309
|
||||
Tommi Kyntola (tommi.kyntola@ray.fi) 27/09/2005
|
||||
*/
|
||||
#if HAVE_NANOSLEEP || HAVE_CLOCK_GETTIME
|
||||
#include <time.h>
|
||||
#endif
|
||||
|
||||
#if SDL_THREAD_PTH
|
||||
#include <pth.h>
|
||||
#endif
|
||||
|
||||
#if SDL_THREADS_DISABLED
|
||||
#define USE_ITIMER
|
||||
#endif
|
||||
|
||||
/* The first ticks value of the application */
|
||||
#ifdef HAVE_CLOCK_GETTIME
|
||||
static struct timespec start;
|
||||
#else
|
||||
static struct timeval start;
|
||||
#endif /* HAVE_CLOCK_GETTIME */
|
||||
|
||||
|
||||
void SDL_StartTicks(void)
|
||||
{
|
||||
/* Set first ticks value */
|
||||
#if HAVE_CLOCK_GETTIME
|
||||
clock_gettime(CLOCK_MONOTONIC,&start);
|
||||
#else
|
||||
gettimeofday(&start, NULL);
|
||||
#endif
|
||||
}
|
||||
|
||||
Uint32 SDL_GetTicks (void)
|
||||
{
|
||||
#if HAVE_CLOCK_GETTIME
|
||||
Uint32 ticks;
|
||||
struct timespec now;
|
||||
clock_gettime(CLOCK_MONOTONIC,&now);
|
||||
ticks=(now.tv_sec-start.tv_sec)*1000+(now.tv_nsec-start.tv_nsec)/1000000;
|
||||
return(ticks);
|
||||
#else
|
||||
Uint32 ticks;
|
||||
struct timeval now;
|
||||
gettimeofday(&now, NULL);
|
||||
ticks=(now.tv_sec-start.tv_sec)*1000+(now.tv_usec-start.tv_usec)/1000;
|
||||
return(ticks);
|
||||
#endif
|
||||
}
|
||||
|
||||
void SDL_Delay (Uint32 ms)
|
||||
{
|
||||
#if SDL_THREAD_PTH
|
||||
pth_time_t tv;
|
||||
tv.tv_sec = ms/1000;
|
||||
tv.tv_usec = (ms%1000)*1000;
|
||||
pth_nap(tv);
|
||||
#else
|
||||
int was_error;
|
||||
|
||||
#if HAVE_NANOSLEEP
|
||||
struct timespec elapsed, tv;
|
||||
#else
|
||||
struct timeval tv;
|
||||
Uint32 then, now, elapsed;
|
||||
#endif
|
||||
|
||||
/* Set the timeout interval */
|
||||
#if HAVE_NANOSLEEP
|
||||
elapsed.tv_sec = ms/1000;
|
||||
elapsed.tv_nsec = (ms%1000)*1000000;
|
||||
#else
|
||||
then = SDL_GetTicks();
|
||||
#endif
|
||||
do {
|
||||
errno = 0;
|
||||
|
||||
#if HAVE_NANOSLEEP
|
||||
tv.tv_sec = elapsed.tv_sec;
|
||||
tv.tv_nsec = elapsed.tv_nsec;
|
||||
was_error = nanosleep(&tv, &elapsed);
|
||||
#else
|
||||
/* Calculate the time interval left (in case of interrupt) */
|
||||
now = SDL_GetTicks();
|
||||
elapsed = (now-then);
|
||||
then = now;
|
||||
if ( elapsed >= ms ) {
|
||||
break;
|
||||
}
|
||||
ms -= elapsed;
|
||||
tv.tv_sec = ms/1000;
|
||||
tv.tv_usec = (ms%1000)*1000;
|
||||
|
||||
was_error = select(0, NULL, NULL, NULL, &tv);
|
||||
#endif /* HAVE_NANOSLEEP */
|
||||
} while ( was_error && (errno == EINTR) );
|
||||
#endif /* SDL_THREAD_PTH */
|
||||
}
|
||||
|
||||
#ifdef USE_ITIMER
|
||||
|
||||
static void HandleAlarm(int sig)
|
||||
{
|
||||
Uint32 ms;
|
||||
|
||||
if ( SDL_alarm_callback ) {
|
||||
ms = (*SDL_alarm_callback)(SDL_alarm_interval);
|
||||
if ( ms != SDL_alarm_interval ) {
|
||||
SDL_SetTimer(ms, SDL_alarm_callback);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int SDL_SYS_TimerInit(void)
|
||||
{
|
||||
struct sigaction action;
|
||||
|
||||
/* Set the alarm handler (Linux specific) */
|
||||
SDL_memset(&action, 0, sizeof(action));
|
||||
action.sa_handler = HandleAlarm;
|
||||
action.sa_flags = SA_RESTART;
|
||||
sigemptyset(&action.sa_mask);
|
||||
sigaction(SIGALRM, &action, NULL);
|
||||
return(0);
|
||||
}
|
||||
|
||||
void SDL_SYS_TimerQuit(void)
|
||||
{
|
||||
SDL_SetTimer(0, NULL);
|
||||
}
|
||||
|
||||
int SDL_SYS_StartTimer(void)
|
||||
{
|
||||
struct itimerval timer;
|
||||
|
||||
timer.it_value.tv_sec = (SDL_alarm_interval/1000);
|
||||
timer.it_value.tv_usec = (SDL_alarm_interval%1000)*1000;
|
||||
timer.it_interval.tv_sec = (SDL_alarm_interval/1000);
|
||||
timer.it_interval.tv_usec = (SDL_alarm_interval%1000)*1000;
|
||||
setitimer(ITIMER_REAL, &timer, NULL);
|
||||
return(0);
|
||||
}
|
||||
|
||||
void SDL_SYS_StopTimer(void)
|
||||
{
|
||||
struct itimerval timer;
|
||||
|
||||
SDL_memset(&timer, 0, (sizeof timer));
|
||||
setitimer(ITIMER_REAL, &timer, NULL);
|
||||
}
|
||||
|
||||
#else /* USE_ITIMER */
|
||||
|
||||
#include "SDL_thread.h"
|
||||
|
||||
/* Data to handle a single periodic alarm */
|
||||
static int timer_alive = 0;
|
||||
static SDL_Thread *timer = NULL;
|
||||
|
||||
static int RunTimer(void *unused)
|
||||
{
|
||||
while ( timer_alive ) {
|
||||
if ( SDL_timer_running ) {
|
||||
SDL_ThreadedTimerCheck();
|
||||
}
|
||||
SDL_Delay(1);
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
/* This is only called if the event thread is not running */
|
||||
int SDL_SYS_TimerInit(void)
|
||||
{
|
||||
timer_alive = 1;
|
||||
timer = SDL_CreateThread(RunTimer, NULL);
|
||||
if ( timer == NULL )
|
||||
return(-1);
|
||||
return(SDL_SetTimerThreaded(1));
|
||||
}
|
||||
|
||||
void SDL_SYS_TimerQuit(void)
|
||||
{
|
||||
timer_alive = 0;
|
||||
if ( timer ) {
|
||||
SDL_WaitThread(timer, NULL);
|
||||
timer = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
int SDL_SYS_StartTimer(void)
|
||||
{
|
||||
SDL_SetError("Internal logic error: Linux uses threaded timer");
|
||||
return(-1);
|
||||
}
|
||||
|
||||
void SDL_SYS_StopTimer(void)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
#endif /* USE_ITIMER */
|
||||
|
||||
#endif /* SDL_TIMER_UNIX */
|
||||
160
apps/plugins/sdl/src/timer/win32/SDL_systimer.c
Normal file
160
apps/plugins/sdl/src/timer/win32/SDL_systimer.c
Normal file
|
|
@ -0,0 +1,160 @@
|
|||
/*
|
||||
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_WIN32
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
#include <mmsystem.h>
|
||||
|
||||
#include "SDL_timer.h"
|
||||
#include "../SDL_timer_c.h"
|
||||
|
||||
#ifdef _WIN32_WCE
|
||||
#error This is WinCE. Please use src/timer/wince/SDL_systimer.c instead.
|
||||
#endif
|
||||
|
||||
#define TIME_WRAP_VALUE (~(DWORD)0)
|
||||
|
||||
/* The first (low-resolution) ticks value of the application */
|
||||
static DWORD start;
|
||||
|
||||
#ifndef USE_GETTICKCOUNT
|
||||
/* Store if a high-resolution performance counter exists on the system */
|
||||
static BOOL hires_timer_available;
|
||||
/* The first high-resolution ticks value of the application */
|
||||
static LARGE_INTEGER hires_start_ticks;
|
||||
/* The number of ticks per second of the high-resolution performance counter */
|
||||
static LARGE_INTEGER hires_ticks_per_second;
|
||||
#endif
|
||||
|
||||
void SDL_StartTicks(void)
|
||||
{
|
||||
/* Set first ticks value */
|
||||
#ifdef USE_GETTICKCOUNT
|
||||
start = GetTickCount();
|
||||
#else
|
||||
#if 0 /* Apparently there are problems with QPC on Win2K */
|
||||
if (QueryPerformanceFrequency(&hires_ticks_per_second) == TRUE)
|
||||
{
|
||||
hires_timer_available = TRUE;
|
||||
QueryPerformanceCounter(&hires_start_ticks);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
hires_timer_available = FALSE;
|
||||
timeBeginPeriod(1); /* use 1 ms timer precision */
|
||||
start = timeGetTime();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
Uint32 SDL_GetTicks(void)
|
||||
{
|
||||
DWORD now, ticks;
|
||||
#ifndef USE_GETTICKCOUNT
|
||||
LARGE_INTEGER hires_now;
|
||||
#endif
|
||||
|
||||
#ifdef USE_GETTICKCOUNT
|
||||
now = GetTickCount();
|
||||
#else
|
||||
if (hires_timer_available)
|
||||
{
|
||||
QueryPerformanceCounter(&hires_now);
|
||||
|
||||
hires_now.QuadPart -= hires_start_ticks.QuadPart;
|
||||
hires_now.QuadPart *= 1000;
|
||||
hires_now.QuadPart /= hires_ticks_per_second.QuadPart;
|
||||
|
||||
return (DWORD)hires_now.QuadPart;
|
||||
}
|
||||
else
|
||||
{
|
||||
now = timeGetTime();
|
||||
}
|
||||
#endif
|
||||
|
||||
if ( now < start ) {
|
||||
ticks = (TIME_WRAP_VALUE-start) + now;
|
||||
} else {
|
||||
ticks = (now - start);
|
||||
}
|
||||
return(ticks);
|
||||
}
|
||||
|
||||
void SDL_Delay(Uint32 ms)
|
||||
{
|
||||
Sleep(ms);
|
||||
}
|
||||
|
||||
/* Data to handle a single periodic alarm */
|
||||
static UINT timerID = 0;
|
||||
|
||||
static void CALLBACK HandleAlarm(UINT uID, UINT uMsg, DWORD_PTR dwUser,
|
||||
DWORD_PTR dw1, DWORD_PTR dw2)
|
||||
{
|
||||
SDL_ThreadedTimerCheck();
|
||||
}
|
||||
|
||||
|
||||
int SDL_SYS_TimerInit(void)
|
||||
{
|
||||
MMRESULT result;
|
||||
|
||||
/* Set timer resolution */
|
||||
result = timeBeginPeriod(TIMER_RESOLUTION);
|
||||
if ( result != TIMERR_NOERROR ) {
|
||||
SDL_SetError("Warning: Can't set %d ms timer resolution",
|
||||
TIMER_RESOLUTION);
|
||||
}
|
||||
/* Allow 10 ms of drift so we don't chew on CPU */
|
||||
timerID = timeSetEvent(TIMER_RESOLUTION,1,HandleAlarm,0,TIME_PERIODIC);
|
||||
if ( ! timerID ) {
|
||||
SDL_SetError("timeSetEvent() failed");
|
||||
return(-1);
|
||||
}
|
||||
return(SDL_SetTimerThreaded(1));
|
||||
}
|
||||
|
||||
void SDL_SYS_TimerQuit(void)
|
||||
{
|
||||
if ( timerID ) {
|
||||
timeKillEvent(timerID);
|
||||
}
|
||||
timeEndPeriod(TIMER_RESOLUTION);
|
||||
}
|
||||
|
||||
int SDL_SYS_StartTimer(void)
|
||||
{
|
||||
SDL_SetError("Internal logic error: Win32 uses threaded timer");
|
||||
return(-1);
|
||||
}
|
||||
|
||||
void SDL_SYS_StopTimer(void)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
#endif /* SDL_TIMER_WIN32 */
|
||||
198
apps/plugins/sdl/src/timer/wince/SDL_systimer.c
Normal file
198
apps/plugins/sdl/src/timer/wince/SDL_systimer.c
Normal file
|
|
@ -0,0 +1,198 @@
|
|||
/*
|
||||
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_WINCE
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
#include <mmsystem.h>
|
||||
|
||||
#include "SDL_thread.h"
|
||||
#include "SDL_timer.h"
|
||||
#include "../SDL_timer_c.h"
|
||||
|
||||
static Uint64 start_date;
|
||||
static Uint64 start_ticks;
|
||||
|
||||
static Uint64 wce_ticks(void)
|
||||
{
|
||||
return((Uint64)GetTickCount());
|
||||
}
|
||||
|
||||
static Uint64 wce_date(void)
|
||||
{
|
||||
union
|
||||
{
|
||||
FILETIME ftime;
|
||||
Uint64 itime;
|
||||
} ftime;
|
||||
SYSTEMTIME stime;
|
||||
|
||||
GetSystemTime(&stime);
|
||||
SystemTimeToFileTime(&stime,&ftime.ftime);
|
||||
ftime.itime/=10000; // Convert 100ns intervals to 1ms intervals
|
||||
// Remove ms portion, which can't be relied on
|
||||
ftime.itime -= (ftime.itime % 1000);
|
||||
return(ftime.itime);
|
||||
}
|
||||
|
||||
static Sint32 wce_rel_ticks(void)
|
||||
{
|
||||
return((Sint32)(wce_ticks()-start_ticks));
|
||||
}
|
||||
|
||||
static Sint32 wce_rel_date(void)
|
||||
{
|
||||
return((Sint32)(wce_date()-start_date));
|
||||
}
|
||||
|
||||
/* Return time in ms relative to when SDL was started */
|
||||
Uint32 SDL_GetTicks()
|
||||
{
|
||||
Sint32 offset=wce_rel_date()-wce_rel_ticks();
|
||||
if((offset < -1000) || (offset > 1000))
|
||||
{
|
||||
// fprintf(stderr,"Time desync(%+d), resyncing\n",offset/1000);
|
||||
start_ticks-=offset;
|
||||
}
|
||||
|
||||
return((Uint32)wce_rel_ticks());
|
||||
}
|
||||
|
||||
/* Give up approx. givem milliseconds to the OS. */
|
||||
void SDL_Delay(Uint32 ms)
|
||||
{
|
||||
Sleep(ms);
|
||||
}
|
||||
|
||||
/* Recard start-time of application for reference */
|
||||
void SDL_StartTicks(void)
|
||||
{
|
||||
start_date=wce_date();
|
||||
start_ticks=wce_ticks();
|
||||
}
|
||||
|
||||
static UINT WIN_timer;
|
||||
|
||||
#if ( _WIN32_WCE <= 420 )
|
||||
|
||||
static HANDLE timersThread = 0;
|
||||
static HANDLE timersQuitEvent = 0;
|
||||
|
||||
DWORD TimersThreadProc(void *data)
|
||||
{
|
||||
while(WaitForSingleObject(timersQuitEvent, 10) == WAIT_TIMEOUT)
|
||||
{
|
||||
SDL_ThreadedTimerCheck();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int SDL_SYS_TimerInit(void)
|
||||
{
|
||||
// create a thread to process a threaded timers
|
||||
// SetTimer does not suit the needs because
|
||||
// TimerCallbackProc will be called only when WM_TIMER occured
|
||||
|
||||
timersQuitEvent = CreateEvent(0, TRUE, FALSE, 0);
|
||||
if( !timersQuitEvent )
|
||||
{
|
||||
SDL_SetError("Cannot create event for timers thread");
|
||||
return -1;
|
||||
}
|
||||
timersThread = CreateThread(NULL, 0, TimersThreadProc, 0, 0, 0);
|
||||
if( !timersThread )
|
||||
{
|
||||
SDL_SetError("Cannot create timers thread, check amount of RAM available");
|
||||
return -1;
|
||||
}
|
||||
SetThreadPriority(timersThread, THREAD_PRIORITY_HIGHEST);
|
||||
|
||||
return(SDL_SetTimerThreaded(1));
|
||||
}
|
||||
|
||||
void SDL_SYS_TimerQuit(void)
|
||||
{
|
||||
SetEvent(timersQuitEvent);
|
||||
if( WaitForSingleObject(timersThread, 2000) == WAIT_TIMEOUT )
|
||||
TerminateThread(timersThread, 0);
|
||||
CloseHandle(timersThread);
|
||||
CloseHandle(timersQuitEvent);
|
||||
return;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#pragma comment(lib, "mmtimer.lib")
|
||||
|
||||
/* Data to handle a single periodic alarm */
|
||||
static UINT timerID = 0;
|
||||
|
||||
static void CALLBACK HandleAlarm(UINT uID, UINT uMsg, DWORD dwUser,
|
||||
DWORD dw1, DWORD dw2)
|
||||
{
|
||||
SDL_ThreadedTimerCheck();
|
||||
}
|
||||
|
||||
|
||||
int SDL_SYS_TimerInit(void)
|
||||
{
|
||||
MMRESULT result;
|
||||
|
||||
/* Set timer resolution */
|
||||
result = timeBeginPeriod(TIMER_RESOLUTION);
|
||||
if ( result != TIMERR_NOERROR ) {
|
||||
SDL_SetError("Warning: Can't set %d ms timer resolution",
|
||||
TIMER_RESOLUTION);
|
||||
}
|
||||
/* Allow 10 ms of drift so we don't chew on CPU */
|
||||
timerID = timeSetEvent(TIMER_RESOLUTION,1,HandleAlarm,0,TIME_PERIODIC);
|
||||
if ( ! timerID ) {
|
||||
SDL_SetError("timeSetEvent() failed");
|
||||
return(-1);
|
||||
}
|
||||
return(SDL_SetTimerThreaded(1));
|
||||
}
|
||||
|
||||
void SDL_SYS_TimerQuit(void)
|
||||
{
|
||||
if ( timerID ) {
|
||||
timeKillEvent(timerID);
|
||||
}
|
||||
timeEndPeriod(TIMER_RESOLUTION);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
int SDL_SYS_StartTimer(void)
|
||||
{
|
||||
SDL_SetError("Internal logic error: WinCE uses threaded timer");
|
||||
return(-1);
|
||||
}
|
||||
|
||||
void SDL_SYS_StopTimer(void)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
#endif /* SDL_TIMER_WINCE */
|
||||
Loading…
Add table
Add a link
Reference in a new issue