Store the 16-bit callback in the timer structure instead of using a
[wine/multimedia.git] / misc / system.c
blobb6f089d42c2efe31efa751b28ff7e0ec9f82c8fc
1 /*
2 * SYSTEM DLL routines
4 * Copyright 1996 Alexandre Julliard
5 */
7 #include "windef.h"
8 #include "wingdi.h"
9 #include "wine/winbase16.h"
10 #include "wine/winuser16.h"
11 #include "services.h"
12 #include "stackframe.h"
13 #include "debugtools.h"
15 DEFAULT_DEBUG_CHANNEL(system);
17 typedef struct
19 SYSTEMTIMERPROC callback; /* NULL if not in use */
20 FARPROC16 callback16;
21 INT rate;
22 INT ticks;
23 } SYSTEM_TIMER;
25 #define NB_SYS_TIMERS 8
26 #define SYS_TIMER_RATE 54925
28 static SYSTEM_TIMER SYS_Timers[NB_SYS_TIMERS];
29 static int SYS_NbTimers = 0;
30 static HANDLE SYS_Service = INVALID_HANDLE_VALUE;
33 /***********************************************************************
34 * SYSTEM_TimerTick
36 static void CALLBACK SYSTEM_TimerTick( ULONG_PTR arg )
38 int i;
40 for (i = 0; i < NB_SYS_TIMERS; i++)
42 if (!SYS_Timers[i].callback) continue;
43 if ((SYS_Timers[i].ticks -= SYS_TIMER_RATE) <= 0)
45 SYS_Timers[i].ticks += SYS_Timers[i].rate;
46 SYS_Timers[i].callback( i+1 );
51 /**********************************************************************
52 * SYSTEM_StartTicks
54 * Start the system tick timer.
56 static void SYSTEM_StartTicks(void)
58 if ( SYS_Service == INVALID_HANDLE_VALUE )
59 SYS_Service = SERVICE_AddTimer( (SYS_TIMER_RATE+500)/1000, SYSTEM_TimerTick, 0L );
63 /**********************************************************************
64 * SYSTEM_StopTicks
66 * Stop the system tick timer.
68 static void SYSTEM_StopTicks(void)
70 if ( SYS_Service != INVALID_HANDLE_VALUE )
72 SERVICE_Delete( SYS_Service );
73 SYS_Service = INVALID_HANDLE_VALUE;
78 /***********************************************************************
79 * InquireSystem (SYSTEM.1)
81 * Note: the function always takes 2 WORD arguments, contrary to what
82 * "Undocumented Windows" says.
84 DWORD WINAPI InquireSystem16( WORD code, WORD arg )
86 WORD drivetype;
88 switch(code)
90 case 0: /* Get timer resolution */
91 return SYS_TIMER_RATE;
93 case 1: /* Get drive type */
94 drivetype = GetDriveType16( arg );
95 return MAKELONG( drivetype, drivetype );
97 case 2: /* Enable one-drive logic */
98 FIXME("Case %d: set single-drive %d not supported\n", code, arg );
99 return 0;
101 WARN("Unknown code %d\n", code );
102 return 0;
106 /***********************************************************************
107 * CreateSystemTimer (SYSTEM.2)
109 WORD WINAPI CreateSystemTimer( WORD rate, SYSTEMTIMERPROC callback )
111 int i;
112 for (i = 0; i < NB_SYS_TIMERS; i++)
113 if (!SYS_Timers[i].callback) /* Found one */
115 SYS_Timers[i].rate = (UINT)rate * 1000;
116 if (SYS_Timers[i].rate < SYS_TIMER_RATE)
117 SYS_Timers[i].rate = SYS_TIMER_RATE;
118 SYS_Timers[i].ticks = SYS_Timers[i].rate;
119 SYS_Timers[i].callback = callback;
120 if (++SYS_NbTimers == 1) SYSTEM_StartTicks();
121 return i + 1; /* 0 means error */
123 return 0;
126 /**********************************************************************/
128 static void call_timer_proc16( WORD timer )
130 CONTEXT86 context;
131 FARPROC16 proc = SYS_Timers[timer-1].callback16;
133 memset( &context, '\0', sizeof(context) );
135 context.SegCs = SELECTOROF( proc );
136 context.Eip = OFFSETOF( proc );
137 context.Ebp = OFFSETOF( NtCurrentTeb()->cur_stack )
138 + (WORD)&((STACK16FRAME*)0)->bp;
140 AX_reg( &context ) = timer;
142 wine_call_to_16_regs_short( &context, 0 );
145 /**********************************************************************/
147 WORD WINAPI WIN16_CreateSystemTimer( WORD rate, FARPROC16 proc )
149 WORD ret = CreateSystemTimer( rate, call_timer_proc16 );
150 if (ret) SYS_Timers[ret - 1].callback16 = proc;
151 return ret;
155 /***********************************************************************
156 * KillSystemTimer (SYSTEM.3)
158 * Note: do not confuse this function with USER.182
160 WORD WINAPI SYSTEM_KillSystemTimer( WORD timer )
162 if ( !timer || timer > NB_SYS_TIMERS || !SYS_Timers[timer-1].callback )
163 return timer; /* Error */
164 SYS_Timers[timer-1].callback = NULL;
165 if (!--SYS_NbTimers) SYSTEM_StopTicks();
166 return 0;
170 /***********************************************************************
171 * EnableSystemTimers (SYSTEM.4)
173 void WINAPI EnableSystemTimers16(void)
175 if ( SYS_Service != INVALID_HANDLE_VALUE )
176 SERVICE_Enable( SYS_Service );
180 /***********************************************************************
181 * DisableSystemTimers (SYSTEM.5)
183 void WINAPI DisableSystemTimers16(void)
185 if ( SYS_Service != INVALID_HANDLE_VALUE )
186 SERVICE_Disable( SYS_Service );
190 /***********************************************************************
191 * Get80x87SaveSize (SYSTEM.7)
193 WORD WINAPI Get80x87SaveSize16(void)
195 return 94;
199 /***********************************************************************
200 * Save80x87State (SYSTEM.8)
202 void WINAPI Save80x87State16( char *ptr )
204 #ifdef __i386__
205 __asm__(".byte 0x66; fsave %0; fwait" : "=m" (ptr) );
206 #endif
210 /***********************************************************************
211 * Restore80x87State (SYSTEM.9)
213 void WINAPI Restore80x87State16( const char *ptr )
215 #ifdef __i386__
216 __asm__(".byte 0x66; frstor %0" : : "m" (ptr) );
217 #endif