src/timer/wince/SDL_systimer.c
author Ryan C. Gordon
Tue, 22 Nov 2005 07:10:07 +0000
changeset 1180 bdcb8bb4c831
child 1312 c9b51268668f
permissions -rw-r--r--
From: Tyler Montbriand <tsm@accesscomm.ca>
To: sdl@libsdl.org
Date: Fri, 30 Sep 2005 02:24:50 -0600
Subject: [SDL] WinCE timers, continued

Here's a strange timer for Windows CE that doesn't ignore time across
suspends. It uses GetSystemTime to keep the time continuous, and GetTicks to
get finer-grained readings than 1 second. It detects the difference between
the GetTicks time and GetSystemTime time on power-on to keep the error within
one second max.

It's not a patch on the current win32 timer code -- took one look at that and
figured it had more than enough #ifdefs already. It's windows-ce specific.

Another thing I've noticed is that the Windows CE 4.0 and newer API has
functions warn processes about suspends. This is something SDL REALLY needs
for audio in particular, because turning it off while it's playing causes
anything that uses audio to hardlock the system on power-on. Unfortunately I
don't have 4.0 to play with. :(
icculus@1180
     1
/*
icculus@1180
     2
    SDL - Simple DirectMedia Layer
icculus@1180
     3
    Copyright (C) 1997-2004 Sam Lantinga
icculus@1180
     4
icculus@1180
     5
    This library is free software; you can redistribute it and/or
icculus@1180
     6
    modify it under the terms of the GNU Library General Public
icculus@1180
     7
    License as published by the Free Software Foundation; either
icculus@1180
     8
    version 2 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
icculus@1180
    13
    Library General Public License for more details.
icculus@1180
    14
icculus@1180
    15
    You should have received a copy of the GNU Library General Public
icculus@1180
    16
    License along with this library; if not, write to the Free
icculus@1180
    17
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
icculus@1180
    18
icculus@1180
    19
    Sam Lantinga
icculus@1180
    20
    slouken@libsdl.org
icculus@1180
    21
*/
icculus@1180
    22
icculus@1180
    23
#ifdef SAVE_RCSID
icculus@1180
    24
static char rcsid =
icculus@1180
    25
 "@(#) $Id$";
icculus@1180
    26
#endif
icculus@1180
    27
icculus@1180
    28
#include <windows.h>
icculus@1180
    29
#include <mmsystem.h>
icculus@1180
    30
icculus@1180
    31
#include "SDL_timer.h"
icculus@1180
    32
#include "SDL_timer_c.h"
icculus@1180
    33
#include "SDL_error.h"
icculus@1180
    34
icculus@1180
    35
static Uint64 start_date;
icculus@1180
    36
static Uint64 start_ticks;
icculus@1180
    37
icculus@1180
    38
static Uint64 wce_ticks(void)
icculus@1180
    39
{
icculus@1180
    40
  return((Uint64)GetTickCount());
icculus@1180
    41
}
icculus@1180
    42
icculus@1180
    43
static Uint64 wce_date(void)
icculus@1180
    44
{
icculus@1180
    45
  union
icculus@1180
    46
  {
icculus@1180
    47
	FILETIME ftime;
icculus@1180
    48
	Uint64 itime;
icculus@1180
    49
  } ftime;
icculus@1180
    50
  SYSTEMTIME stime;
icculus@1180
    51
icculus@1180
    52
  GetSystemTime(&stime);
icculus@1180
    53
  SystemTimeToFileTime(&stime,&ftime.ftime);
icculus@1180
    54
  ftime.itime/=10000; // Convert 100ns intervals to 1ms intervals
icculus@1180
    55
  // Remove ms portion, which can't be relied on
icculus@1180
    56
  ftime.itime -= (ftime.itime % 1000);
icculus@1180
    57
  return(ftime.itime);
icculus@1180
    58
}
icculus@1180
    59
icculus@1180
    60
static Sint32 wce_rel_ticks(void)
icculus@1180
    61
{
icculus@1180
    62
  return((Sint32)(wce_ticks()-start_ticks));
icculus@1180
    63
}
icculus@1180
    64
icculus@1180
    65
static Sint32 wce_rel_date(void)
icculus@1180
    66
{
icculus@1180
    67
  return((Sint32)(wce_date()-start_date));
icculus@1180
    68
}
icculus@1180
    69
icculus@1180
    70
/* Return time in ms relative to when SDL was started */
icculus@1180
    71
Uint32 SDL_GetTicks()
icculus@1180
    72
{
icculus@1180
    73
  Sint32 offset=wce_rel_date()-wce_rel_ticks();
icculus@1180
    74
  if((offset < -1000) || (offset > 1000))
icculus@1180
    75
  {
icculus@1180
    76
//    fprintf(stderr,"Time desync(%+d), resyncing\n",offset/1000);
icculus@1180
    77
	start_ticks-=offset;
icculus@1180
    78
  }
icculus@1180
    79
icculus@1180
    80
  return((Uint32)wce_rel_ticks());
icculus@1180
    81
}
icculus@1180
    82
icculus@1180
    83
/* Give up approx. givem milliseconds to the OS. */
icculus@1180
    84
void SDL_Delay(Uint32 ms)
icculus@1180
    85
{
icculus@1180
    86
  Sleep(ms);
icculus@1180
    87
}
icculus@1180
    88
icculus@1180
    89
/* Recard start-time of application for reference */
icculus@1180
    90
void SDL_StartTicks(void)
icculus@1180
    91
{
icculus@1180
    92
  start_date=wce_date();
icculus@1180
    93
  start_ticks=wce_ticks();
icculus@1180
    94
}
icculus@1180
    95
icculus@1180
    96
static UINT WIN_timer;
icculus@1180
    97
icculus@1180
    98
int SDL_SYS_TimerInit(void)
icculus@1180
    99
{
icculus@1180
   100
	return(0);
icculus@1180
   101
}
icculus@1180
   102
icculus@1180
   103
void SDL_SYS_TimerQuit(void)
icculus@1180
   104
{
icculus@1180
   105
	return;
icculus@1180
   106
}
icculus@1180
   107
icculus@1180
   108
/* Forward declaration because this is called by the timer callback */
icculus@1180
   109
int SDL_SYS_StartTimer(void);
icculus@1180
   110
icculus@1180
   111
static VOID CALLBACK TimerCallbackProc(HWND hwnd, UINT uMsg, UINT idEvent, DWORD dwTime)
icculus@1180
   112
{
icculus@1180
   113
	Uint32 ms;
icculus@1180
   114
icculus@1180
   115
	ms = SDL_alarm_callback(SDL_alarm_interval);
icculus@1180
   116
	if ( ms != SDL_alarm_interval ) {
icculus@1180
   117
		KillTimer(NULL, idEvent);
icculus@1180
   118
		if ( ms ) {
icculus@1180
   119
			SDL_alarm_interval = ROUND_RESOLUTION(ms);
icculus@1180
   120
			SDL_SYS_StartTimer();
icculus@1180
   121
		} else {
icculus@1180
   122
			SDL_alarm_interval = 0;
icculus@1180
   123
		}
icculus@1180
   124
	}
icculus@1180
   125
}
icculus@1180
   126
icculus@1180
   127
int SDL_SYS_StartTimer(void)
icculus@1180
   128
{
icculus@1180
   129
	int retval;
icculus@1180
   130
icculus@1180
   131
	WIN_timer = SetTimer(NULL, 0, SDL_alarm_interval, TimerCallbackProc);
icculus@1180
   132
	if ( WIN_timer ) {
icculus@1180
   133
		retval = 0;
icculus@1180
   134
	} else {
icculus@1180
   135
		retval = -1;
icculus@1180
   136
	}
icculus@1180
   137
	return retval;
icculus@1180
   138
}
icculus@1180
   139
icculus@1180
   140
void SDL_SYS_StopTimer(void)
icculus@1180
   141
{
icculus@1180
   142
	if ( WIN_timer ) {
icculus@1180
   143
		KillTimer(NULL, WIN_timer);
icculus@1180
   144
		WIN_timer = 0;
icculus@1180
   145
	}
icculus@1180
   146
}
icculus@1180
   147