src/timer/wince/SDL_systimer.c
author Sam Lantinga
Fri, 14 Apr 2006 04:46:47 +0000
changeset 1635 92947e3a18db
parent 1497 420b3f47806d
child 1662 782fd950bd46
child 1895 c121d94672cb
child 4159 a1b03ba2fcd0
permissions -rw-r--r--
Make sure code is only compiled if the appropriate subsystem is enabled
icculus@1180
     1
/*
icculus@1180
     2
    SDL - Simple DirectMedia Layer
slouken@1312
     3
    Copyright (C) 1997-2006 Sam Lantinga
icculus@1180
     4
icculus@1180
     5
    This library is free software; you can redistribute it and/or
slouken@1312
     6
    modify it under the terms of the GNU Lesser General Public
icculus@1180
     7
    License as published by the Free Software Foundation; either
slouken@1312
     8
    version 2.1 of the License, or (at your option) any later version.
icculus@1180
     9
icculus@1180
    10
    This library is distributed in the hope that it will be useful,
icculus@1180
    11
    but WITHOUT ANY WARRANTY; without even the implied warranty of
icculus@1180
    12
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
slouken@1312
    13
    Lesser General Public License for more details.
icculus@1180
    14
slouken@1312
    15
    You should have received a copy of the GNU Lesser General Public
slouken@1312
    16
    License along with this library; if not, write to the Free Software
slouken@1312
    17
    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
icculus@1180
    18
icculus@1180
    19
    Sam Lantinga
icculus@1180
    20
    slouken@libsdl.org
icculus@1180
    21
*/
slouken@1402
    22
#include "SDL_config.h"
icculus@1180
    23
slouken@1635
    24
#ifdef SDL_TIMER_WINCE
slouken@1635
    25
slouken@1433
    26
#define WIN32_LEAN_AND_MEAN
slouken@1433
    27
#include <windows.h>
icculus@1180
    28
#include <mmsystem.h>
icculus@1180
    29
slouken@1497
    30
#include "SDL_thread.h"
icculus@1180
    31
#include "SDL_timer.h"
slouken@1361
    32
#include "../SDL_timer_c.h"
icculus@1180
    33
icculus@1180
    34
static Uint64 start_date;
icculus@1180
    35
static Uint64 start_ticks;
icculus@1180
    36
icculus@1180
    37
static Uint64 wce_ticks(void)
icculus@1180
    38
{
icculus@1180
    39
  return((Uint64)GetTickCount());
icculus@1180
    40
}
icculus@1180
    41
icculus@1180
    42
static Uint64 wce_date(void)
icculus@1180
    43
{
icculus@1180
    44
  union
icculus@1180
    45
  {
icculus@1180
    46
	FILETIME ftime;
icculus@1180
    47
	Uint64 itime;
icculus@1180
    48
  } ftime;
icculus@1180
    49
  SYSTEMTIME stime;
icculus@1180
    50
icculus@1180
    51
  GetSystemTime(&stime);
icculus@1180
    52
  SystemTimeToFileTime(&stime,&ftime.ftime);
icculus@1180
    53
  ftime.itime/=10000; // Convert 100ns intervals to 1ms intervals
icculus@1180
    54
  // Remove ms portion, which can't be relied on
icculus@1180
    55
  ftime.itime -= (ftime.itime % 1000);
icculus@1180
    56
  return(ftime.itime);
icculus@1180
    57
}
icculus@1180
    58
icculus@1180
    59
static Sint32 wce_rel_ticks(void)
icculus@1180
    60
{
icculus@1180
    61
  return((Sint32)(wce_ticks()-start_ticks));
icculus@1180
    62
}
icculus@1180
    63
icculus@1180
    64
static Sint32 wce_rel_date(void)
icculus@1180
    65
{
icculus@1180
    66
  return((Sint32)(wce_date()-start_date));
icculus@1180
    67
}
icculus@1180
    68
icculus@1180
    69
/* Return time in ms relative to when SDL was started */
icculus@1180
    70
Uint32 SDL_GetTicks()
icculus@1180
    71
{
icculus@1180
    72
  Sint32 offset=wce_rel_date()-wce_rel_ticks();
icculus@1180
    73
  if((offset < -1000) || (offset > 1000))
icculus@1180
    74
  {
icculus@1180
    75
//    fprintf(stderr,"Time desync(%+d), resyncing\n",offset/1000);
icculus@1180
    76
	start_ticks-=offset;
icculus@1180
    77
  }
icculus@1180
    78
icculus@1180
    79
  return((Uint32)wce_rel_ticks());
icculus@1180
    80
}
icculus@1180
    81
icculus@1180
    82
/* Give up approx. givem milliseconds to the OS. */
icculus@1180
    83
void SDL_Delay(Uint32 ms)
icculus@1180
    84
{
icculus@1180
    85
  Sleep(ms);
icculus@1180
    86
}
icculus@1180
    87
icculus@1180
    88
/* Recard start-time of application for reference */
icculus@1180
    89
void SDL_StartTicks(void)
icculus@1180
    90
{
icculus@1180
    91
  start_date=wce_date();
icculus@1180
    92
  start_ticks=wce_ticks();
icculus@1180
    93
}
icculus@1180
    94
icculus@1180
    95
static UINT WIN_timer;
icculus@1180
    96
slouken@1497
    97
#if ( _WIN32_WCE <= 420 )
slouken@1497
    98
slouken@1497
    99
static HANDLE timersThread = 0;
slouken@1497
   100
static HANDLE timersQuitEvent = 0;
slouken@1497
   101
slouken@1497
   102
DWORD TimersThreadProc(void *data)
slouken@1497
   103
{
slouken@1497
   104
	while(WaitForSingleObject(timersQuitEvent, 10) == WAIT_TIMEOUT)
slouken@1497
   105
	{
slouken@1497
   106
		SDL_ThreadedTimerCheck();
slouken@1497
   107
	}
slouken@1497
   108
	return 0;
slouken@1497
   109
}
slouken@1497
   110
icculus@1180
   111
int SDL_SYS_TimerInit(void)
icculus@1180
   112
{
slouken@1497
   113
	// create a thread to process a threaded timers
slouken@1497
   114
	// SetTimer does not suit the needs because 
slouken@1497
   115
	// TimerCallbackProc will be called only when WM_TIMER occured
slouken@1497
   116
slouken@1497
   117
	timersQuitEvent = CreateEvent(0, TRUE, FALSE, 0);
slouken@1497
   118
	if( !timersQuitEvent )
slouken@1497
   119
	{
slouken@1497
   120
		SDL_SetError("Cannot create event for timers thread");
slouken@1497
   121
		return -1;
slouken@1497
   122
	}
slouken@1497
   123
	timersThread = CreateThread(NULL, 0, TimersThreadProc, 0, 0, 0);
slouken@1497
   124
	if( !timersThread )
slouken@1497
   125
	{
slouken@1497
   126
		SDL_SetError("Cannot create timers thread, check amount of RAM available");
slouken@1497
   127
		return -1;
slouken@1497
   128
	}
slouken@1497
   129
	SetThreadPriority(timersThread, THREAD_PRIORITY_HIGHEST);
slouken@1497
   130
slouken@1497
   131
	return(SDL_SetTimerThreaded(1));
icculus@1180
   132
}
icculus@1180
   133
icculus@1180
   134
void SDL_SYS_TimerQuit(void)
icculus@1180
   135
{
slouken@1497
   136
	SetEvent(timersQuitEvent);
slouken@1497
   137
	if( WaitForSingleObject(timersThread, 2000) == WAIT_TIMEOUT )
slouken@1497
   138
		TerminateThread(timersThread, 0);
slouken@1497
   139
	CloseHandle(timersThread);
slouken@1497
   140
	CloseHandle(timersQuitEvent);
icculus@1180
   141
	return;
icculus@1180
   142
}
icculus@1180
   143
slouken@1497
   144
#else
slouken@1497
   145
slouken@1497
   146
#pragma comment(lib, "mmtimer.lib")
slouken@1497
   147
slouken@1497
   148
/* Data to handle a single periodic alarm */
slouken@1497
   149
static UINT timerID = 0;
icculus@1180
   150
slouken@1497
   151
static void CALLBACK HandleAlarm(UINT uID,  UINT uMsg, DWORD dwUser,
slouken@1497
   152
						DWORD dw1, DWORD dw2)
icculus@1180
   153
{
slouken@1497
   154
	SDL_ThreadedTimerCheck();
slouken@1497
   155
}
slouken@1497
   156
slouken@1497
   157
slouken@1497
   158
int SDL_SYS_TimerInit(void)
slouken@1497
   159
{
slouken@1497
   160
	MMRESULT result;
icculus@1180
   161
slouken@1497
   162
	/* Set timer resolution */
slouken@1497
   163
	result = timeBeginPeriod(TIMER_RESOLUTION);
slouken@1497
   164
	if ( result != TIMERR_NOERROR ) {
slouken@1497
   165
		SDL_SetError("Warning: Can't set %d ms timer resolution",
slouken@1497
   166
							TIMER_RESOLUTION);
slouken@1497
   167
	}
slouken@1497
   168
	/* Allow 10 ms of drift so we don't chew on CPU */
slouken@1497
   169
	timerID = timeSetEvent(TIMER_RESOLUTION,1,HandleAlarm,0,TIME_PERIODIC);
slouken@1497
   170
	if ( ! timerID ) {
slouken@1497
   171
		SDL_SetError("timeSetEvent() failed");
slouken@1497
   172
		return(-1);
icculus@1180
   173
	}
slouken@1497
   174
	return(SDL_SetTimerThreaded(1));
icculus@1180
   175
}
icculus@1180
   176
slouken@1497
   177
void SDL_SYS_TimerQuit(void)
slouken@1497
   178
{
slouken@1497
   179
	if ( timerID ) {
slouken@1497
   180
		timeKillEvent(timerID);
slouken@1497
   181
	}
slouken@1497
   182
	timeEndPeriod(TIMER_RESOLUTION);
slouken@1497
   183
}
slouken@1497
   184
slouken@1497
   185
#endif
slouken@1497
   186
icculus@1180
   187
int SDL_SYS_StartTimer(void)
icculus@1180
   188
{
slouken@1497
   189
	SDL_SetError("Internal logic error: WinCE uses threaded timer");
slouken@1497
   190
	return(-1);
icculus@1180
   191
}
icculus@1180
   192
icculus@1180
   193
void SDL_SYS_StopTimer(void)
icculus@1180
   194
{
slouken@1497
   195
	return;
icculus@1180
   196
}
slouken@1635
   197
slouken@1635
   198
#endif /* SDL_TIMER_WINCE */