changed window caption to include version info
[btb/d2x.git] / input / win32_joyhh.c
1 //JOYC.C for D1_3Dfx and D1OpenGL
2 //D1_3Dfx is a Win32 executable using Glide and DirectX 3
3 //D1OpenGL is a Win32 executable using OpenGL and DirectX 3
4 //This joystick code should run on DirectInput 2 and higher
5 //We are not using DirectX 5 for now, since we want to stay compatible to the HH-loved Windows NT :).
6 //So ForceFeedback is not supported
7
8 //Notes:
9 // 1) Windows DirectX supports up to 7 axes, D1/DOS only 4, so we needed to increase the number to 7 at several points
10 //    Also JOY_ALL_AXIS must be (1+2+4+8+16+32+64) in JOY.H file
11 // 2) Windows DirectX supports up to 32 buttons. So far we however only support 4. Adding support for more should be however easily possible.
12 // 3) _enable and _disable are not needed
13 // 4) joy_bogus_reading is not needed, so all calls are just removed
14 // 5) The joystick query goes over the DirectInputs function
15 //    MMRESULT joyGetPosEx(UINT uJoyID, LPJOYINFOEX pji);
16 //    All functions reading over BIOS, including the ASM code are removed
17
18
19
20 /*
21 THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX
22 SOFTWARE CORPORATION ("PARALLAX").  PARALLAX, IN DISTRIBUTING THE CODE TO
23 END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A
24 ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS
25 IN USING, DISPLAYING,  AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS
26 SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE
27 FREE PURPOSES.  IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE
28 CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES.  THE END-USER UNDERSTANDS
29 AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE.  
30 COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION.  ALL RIGHTS RESERVED.
31 */
32
33 /*
34 Modifications by Heiko Herrmann
35 Later modified by Owen Evans to work with D1X (3/7/99)
36 */
37
38 #ifdef HAVE_CONFIG_H
39 #include <conf.h>
40 #endif
41
42 #define _WIN32_OS               //HH
43
44
45 #include <windows.h>    //HH
46 #include <mmsystem.h>   //HH
47 #include <stdlib.h>
48 #include <stdio.h>
49
50 #undef min /* kludge */
51 #undef max /* kludge */
52 #include "pstypes.h"
53 #include "joy.h"
54 #include "timer.h"
55
56 #define my_hwnd g_hWnd // D1X compatibility
57 extern HWND g_hWnd;
58
59 char joy_installed = 0;
60 char joy_present = 0;
61
62 typedef struct Button_info {
63         ubyte           ignore;
64         ubyte           state;
65         ubyte           last_state;
66         int             timedown;
67         ubyte           downcount;
68         ubyte           upcount;
69 } Button_info;
70
71 typedef struct Joy_info {
72         int                     joyid;
73         ubyte                   present_mask;
74         ubyte                   slow_read;
75         int                     max_timer;
76         int                     read_count;
77         ubyte                   last_value;
78         Button_info     buttons[MAX_BUTTONS];
79         int                     axis_min[JOY_NUM_AXES];    //changed 
80         int                     axis_center[JOY_NUM_AXES]; //changed --orulz
81         int                     axis_max[JOY_NUM_AXES];    //changed 
82 } Joy_info;
83
84 Joy_info joystick;
85
86
87 int joy_deadzone = 0;
88
89 void joy_get_cal_vals(int *axis_min, int *axis_center, int *axis_max)
90 {
91         int i;
92
93         for (i=0; i<JOY_NUM_AXES; i++)             {       //changed - orulz
94                 axis_min[i] = joystick.axis_min[i];
95                 axis_center[i] = joystick.axis_center[i];
96                 axis_max[i] = joystick.axis_max[i];
97         }
98 }
99
100 void joy_set_cal_vals(int *axis_min, int *axis_center, int *axis_max)
101 {
102         int i;
103
104         for (i=0; i<JOY_NUM_AXES; i++)             {       //changed - orulz
105                 joystick.axis_min[i] = axis_min[i];
106                 joystick.axis_center[i] = axis_center[i];
107                 joystick.axis_max[i] = axis_max[i];
108         }
109 }
110
111 ubyte joy_get_present_mask()    {
112         return joystick.present_mask;
113 }
114
115 void joy_set_timer_rate(int max_value ) {
116         joystick.max_timer = max_value;
117 }
118
119 int joy_get_timer_rate()        {
120         return joystick.max_timer;
121 }
122
123 void joy_flush()        {
124         int i;
125
126         if (!joy_installed) return;
127
128         for (i=0; i<MAX_BUTTONS; i++ )  {
129                 joystick.buttons[i].ignore = 0;
130                 joystick.buttons[i].state = 0;  
131                 joystick.buttons[i].timedown = 0;       
132                 joystick.buttons[i].downcount = 0;      
133                 joystick.buttons[i].upcount = 0;        
134         }
135
136 }
137
138
139 //Repalces joy_handler
140 //Since Windows calls us directly, we have to get our time difference since last time ourselves
141 //while in DOS we got it with the paramter ticks_this_time
142 LRESULT joy_handler32(HWND hWnd, UINT joymsg, UINT wParam, LPARAM lParam)
143 {
144 #if 0
145         DWORD time_diff, time_now;
146         static DWORD time_last = 0xffffffff;
147         
148         Button_info *button;
149         int i;
150         int state=0;
151         DWORD value=0;
152
153         if (!joy_installed) return 1;
154         if (time_last == 0xffffffff) {
155                 time_last = timer_get_fixed_seconds();
156                 return 0;
157         }
158
159         if (joymsg==MM_JOY1MOVE)
160         {
161                 JOYINFOEX       joy;
162
163                 memset(&joy, 0, sizeof(joy));
164                 joy.dwSize = sizeof(joy);
165                 joy.dwFlags = JOY_RETURNBUTTONS | JOY_RETURNPOV;
166                 if (joyGetPosEx(joystick.joyid, &joy)!=JOYERR_NOERROR) {
167                         return 1;
168                 }
169                 value = joy.dwButtons;
170         }
171
172         time_now = timer_get_fixed_seconds();
173         if (time_now < time_last) {
174                 time_last = abs(time_now-time_last);
175         }
176         time_diff = time_now - time_last;
177
178         for (i = 0; i < MAX_BUTTONS; i++)
179         {
180                 button = &joystick.buttons[i];
181                 
182                 if (!button->ignore) {
183                         if ( i < (MAX_BUTTONS-4) )
184                                 state = (value >> i) & 1;
185                         else
186                                 state = 0;
187
188                         if ( button->last_state == state )      {
189                                 if (state) {
190                                         button->timedown += time_diff;  //ticks_this_time;
191                                 }
192                         } else {
193                                 if (state)      {
194                                         button->downcount += state;
195                                         button->state = 1;
196                                 } else {        
197                                         button->upcount += button->state;
198                                         button->state = 0;
199                                 }
200                                 button->last_state = state;
201                         }
202                 }
203         }
204
205         time_last = time_now;
206 #endif
207         return 0;
208 }               
209
210
211 //Begin section modified 3/7/99 - Owen Evans
212
213 ubyte joy_read_raw_buttons()
214 {
215 #if 0
216         JOYINFOEX joy;
217         int i;
218
219         if (!joy_present)
220                 return 0; 
221         
222         memset(&joy, 0, sizeof(joy));
223         joy.dwSize = sizeof(joy);
224         joy.dwFlags = JOY_RETURNBUTTONS | JOY_RETURNPOVCTS | JOY_USEDEADZONE;
225         
226         if (joyGetPosEx(joystick.joyid, &joy)!=JOYERR_NOERROR)
227                 return 0;
228
229         for (i = 0; i < MAX_BUTTONS; i++) {
230                 joystick.buttons[i].last_state = joystick.buttons[i].state;
231                 joystick.buttons[i].state = (joy.dwButtons >> i) & 0x1;
232                 if (!joystick.buttons[i].last_state && joystick.buttons[i].state) {
233                         joystick.buttons[i].timedown = timer_get_fixed_seconds();
234                         joystick.buttons[i].downcount++;
235                 }
236         }
237
238         /* Hat stuff */
239
240         if (joy.dwPOV != JOY_POVCENTERED)
241          {
242            joystick.buttons[19].state = (joy.dwPOV < JOY_POVRIGHT || joy.dwPOV > JOY_POVLEFT);
243            joystick.buttons[15].state = (joy.dwPOV < JOY_POVBACKWARD && joy.dwPOV > JOY_POVFORWARD);
244            joystick.buttons[11].state = (joy.dwPOV < JOY_POVLEFT && joy.dwPOV > JOY_POVRIGHT);
245            joystick.buttons[7].state = (joy.dwPOV > JOY_POVBACKWARD);
246          }
247
248         return (ubyte)joy.dwButtons;
249 #else
250         return 0;
251 #endif
252 }
253
254 //end changed section - OE
255
256
257 ubyte joystick_read_raw_axis( ubyte mask, int * axis )
258 {
259 #if 0
260         JOYINFOEX       joy;
261         ubyte read_masks = 0;
262
263         axis[0] = 0; axis[1] = 0; //orulz: 1=x 2=y 3=r 4=z 5=u 6=v
264         axis[2] = 0; axis[3] = 0;
265         axis[4] = 0; axis[5] = 0; //HH: Added support for axes R and U
266         
267         if (!joy_installed) {
268                 return 0;
269         }
270         
271         memset(&joy, 0, sizeof(joy));
272         joy.dwSize = sizeof(joy);
273         joy.dwFlags = JOY_RETURNALL | JOY_USEDEADZONE;
274         if (joyGetPosEx(joystick.joyid, &joy)!=JOYERR_NOERROR) {
275                 return 0;
276         }
277                         
278         mask &= joystick.present_mask;                  // Don't read non-present channels
279         if ( mask==0 )  {
280                 return 0;               // Don't read if no stick connected.
281         }
282
283         if (mask & JOY_1_X_AXIS) { axis[0] = joy.dwXpos; read_masks |= JOY_1_X_AXIS; }
284         if (mask & JOY_1_Y_AXIS) { axis[1] = joy.dwYpos; read_masks |= JOY_1_Y_AXIS; }
285 //orulz:
286 //        if (mask & JOY_1_Z_AXIS) { axis[2] = joy.dwZpos; read_masks |= JOY_1_Z_AXIS; }
287 //        if (mask & JOY_1_POV)    { axis[3] = joy.dwPOV;  read_masks |= JOY_1_POV;    }
288 //        if (mask & JOY_1_R_AXIS) { axis[4] = joy.dwRpos; read_masks |= JOY_1_R_AXIS; }
289 //        if (mask & JOY_1_U_AXIS) { axis[5] = joy.dwUpos; read_masks |= JOY_1_U_AXIS; }
290 //        if (mask & JOY_1_V_AXIS) { axis[6] = joy.dwVpos; read_masks |= JOY_1_V_AXIS; }
291         if (mask & JOY_1_R_AXIS) { axis[2] = joy.dwRpos; read_masks |= JOY_1_R_AXIS; }
292         if (mask & JOY_1_Z_AXIS) { axis[3] = joy.dwZpos; read_masks |= JOY_1_Z_AXIS; }
293         if (mask & JOY_1_U_AXIS) { axis[4] = joy.dwZpos; read_masks |= JOY_1_U_AXIS; }
294         if (mask & JOY_1_V_AXIS) { axis[5] = joy.dwUpos; read_masks |= JOY_1_V_AXIS; }
295
296         return read_masks;
297 }
298
299 int hh_average(int val1, int val2)
300 {
301         return abs(val1-val2)/2;
302 }
303
304 int joy_init(int joyid) //HH: added joyid parameter
305 {
306         int i;
307         int temp_axis[JOY_NUM_AXES];       //changed - orulz
308         JOYCAPS pjc;
309
310         atexit(joy_close);      //HH: we are a bit lazy :). Errors are ignored, so we are even double-lazy :)
311
312         joy_flush();
313         memset(&joystick, 0, sizeof(joystick));
314
315         for (i=0; i<MAX_BUTTONS; i++)
316                 joystick.buttons[i].last_state = 0;
317
318         if ( !joy_installed )   {
319                 joy_present = 0;
320                 joy_installed = 1;
321                 joystick.max_timer = 65536;
322                 joystick.read_count = 0;
323                 joystick.last_value = 0;
324         }
325
326
327         joystick.present_mask = JOY_ALL_AXIS;           // Assume they're all present
328         joystick.present_mask = joystick_read_raw_axis( JOY_ALL_AXIS, temp_axis );
329
330         if ( joystick.present_mask & 3 )
331                 joy_present = 1;
332         else
333                 joy_present = 0;
334
335         
336         //HH: Main Win32 joystick initialization, incl. reading cal. stuff
337
338         if (joyGetDevCaps(joyid, &pjc, sizeof(pjc))!=JOYERR_NOERROR) {
339                 return 0;
340         }
341
342         if (joySetThreshold(joyid, pjc.wXmax/256)!=JOYERR_NOERROR) {
343                 return 0;
344         }
345         
346         if (joySetCapture(my_hwnd, joyid, JOY_POLL_RATE, FALSE)!=JOYERR_NOERROR) {
347                 return 0;
348         }
349
350         joystick.max_timer      = pjc.wPeriodMax;
351         joystick.axis_min[0]    = pjc.wXmin;
352         joystick.axis_min[1]    = pjc.wYmin;
353 //orulz:
354 //        joystick.axis_min[2]    = pjc.wZmin;
355 //        //HH: joystick.axis_min[3]  = pov-stuff
356 //        joystick.axis_min[4]    = pjc.wRmin;
357 //        joystick.axis_min[5]    = pjc.wUmin;
358 //        joystick.axis_min[6]    = pjc.wVmin;
359         joystick.axis_min[2]    = pjc.wRmin;
360         joystick.axis_min[3]    = pjc.wZmin;
361         joystick.axis_min[4]    = pjc.wUmin;
362         joystick.axis_min[5]    = pjc.wVmin;
363
364         joystick.axis_max[0]    = pjc.wXmax;
365         joystick.axis_max[1]    = pjc.wYmax;
366 //orulz:
367 //        joystick.axis_max[2]    = pjc.wZmax;
368 //        //HH: joystick.axis_max[3]  = pov-stuff
369 //        joystick.axis_max[4]    = pjc.wRmax;
370 //        joystick.axis_max[5]    = pjc.wUmax;
371 //        joystick.axis_max[6]    = pjc.wVmax;
372         joystick.axis_max[2]    = pjc.wRmax;
373         joystick.axis_max[3]    = pjc.wZmax;
374         joystick.axis_max[4]    = pjc.wUmax;
375         joystick.axis_max[5]    = pjc.wVmax;
376
377         joystick.axis_center[0] = hh_average(pjc.wXmax,pjc.wXmin);
378         joystick.axis_center[1] = hh_average(pjc.wYmax,pjc.wYmin);
379 //orulz:
380 //        joystick.axis_center[2] = hh_average(pjc.wZmax,pjc.wZmin);
381 //        joystick.axis_center[3] = JOY_POVCENTERED;
382 //        joystick.axis_center[4] = hh_average(pjc.wRmax,pjc.wRmin);
383 //        joystick.axis_center[5] = hh_average(pjc.wUmax,pjc.wUmin);
384 //        joystick.axis_center[6] = hh_average(pjc.wVmax,pjc.wVmin);
385         joystick.axis_center[2] = hh_average(pjc.wRmax,pjc.wRmin);
386         joystick.axis_center[3] = hh_average(pjc.wZmax,pjc.wZmin);
387         joystick.axis_center[4] = hh_average(pjc.wUmax,pjc.wUmin);
388         joystick.axis_center[5] = hh_average(pjc.wVmax,pjc.wVmin);
389
390         joystick.present_mask = JOY_1_X_AXIS | JOY_1_Y_AXIS;
391         if (pjc.wCaps & JOYCAPS_HASZ)   joystick.present_mask |= JOY_1_Z_AXIS;
392 //        if (pjc.wCaps & JOYCAPS_HASPOV) joystick.present_mask |= JOY_1_POV;
393         if (pjc.wCaps & JOYCAPS_HASR)   joystick.present_mask |= JOY_1_R_AXIS;
394         if (pjc.wCaps & JOYCAPS_HASU)   joystick.present_mask |= JOY_1_U_AXIS;
395         if (pjc.wCaps & JOYCAPS_HASV)   joystick.present_mask |= JOY_1_V_AXIS;
396
397         return joy_present;
398 #else
399         return 0;
400 #endif
401 }
402
403
404 void joy_close()
405 {
406 #if 0
407         if (!joy_installed) return;
408         joyReleaseCapture(joystick.joyid); //HH: added to release joystick from the application. We ignore errors here
409         joy_installed = 0;
410 #endif
411 }
412
413
414 void joy_set_ul()       
415 {
416         joystick.present_mask = JOY_ALL_AXIS;           // Assume they're all present
417         joystick.present_mask = joystick_read_raw_axis( JOY_ALL_AXIS, joystick.axis_min );
418
419         if ( joystick.present_mask & 3 )
420                 joy_present = 1;
421         else
422                 joy_present = 0;
423 }
424
425 void joy_set_lr()       
426 {
427         joystick.present_mask = JOY_ALL_AXIS;           // Assume they're all present
428         joystick.present_mask = joystick_read_raw_axis( JOY_ALL_AXIS, joystick.axis_max );
429
430         if ( joystick.present_mask & 3 )
431                 joy_present = 1;
432         else
433                 joy_present = 0;
434 }
435
436 void joy_set_cen() 
437 {
438         joystick.present_mask = JOY_ALL_AXIS;           // Assume they're all present
439         joystick.present_mask = joystick_read_raw_axis( JOY_ALL_AXIS, joystick.axis_center );
440
441         if ( joystick.present_mask & 3 )
442                 joy_present = 1;
443         else
444                 joy_present = 0;
445 }
446
447 void joy_set_cen_fake(int channel)      
448 { }
449
450
451 int joy_get_scaled_reading( int raw, int axn )  
452 {
453  int x, d;
454
455   // Make sure it's calibrated properly.
456    if ( joystick.axis_center[axn] - joystick.axis_min[axn] < 128 )
457     return 0; //HH: had to increase to 128
458    if ( joystick.axis_max[axn] - joystick.axis_center[axn] < 128 )
459     return 0; //HH: had to increase to 128
460
461   raw -= joystick.axis_center[axn];
462
463    if ( raw < 0 )
464     d = joystick.axis_center[axn]-joystick.axis_min[axn];
465    else
466     d = joystick.axis_max[axn]-joystick.axis_center[axn];
467
468
469    if ( d )
470     x = (raw << 7) / d;
471    else 
472     x = 0;
473
474
475    if ( x < -128 ) x = -128;
476    if ( x > 127 ) x = 127;
477
478 //added on 4/13/99 by Victor Rachels to add deadzone control
479   d =  (joy_deadzone) * 6;
480    if ((x > (-1*d)) && (x < d))
481     x = 0;
482 //end this section addition -VR
483
484         return x;
485 }
486
487 void joy_get_pos( int *x, int *y )      
488 {
489         ubyte flags;
490         int axis[JOY_NUM_AXES];
491
492         if ((!joy_installed)||(!joy_present)) { *x=*y=0; return; }
493
494         flags=joystick_read_raw_axis( JOY_1_X_AXIS+JOY_1_Y_AXIS, axis );
495
496         if ( flags & JOY_1_X_AXIS )
497                 *x = joy_get_scaled_reading( axis[0], 0 );
498         else
499                 *x = 0;
500
501         if ( flags & JOY_1_Y_AXIS )
502                 *y = joy_get_scaled_reading( axis[1], 1 );
503         else
504                 *y = 0;
505 }
506
507 ubyte joy_read_stick( ubyte masks, int *axis )  
508 {
509         ubyte flags;
510         int raw_axis[JOY_NUM_AXES];
511
512         if ((!joy_installed)||(!joy_present)) { 
513                 axis[0] = 0; axis[1] = 0;
514                 axis[2] = 0; axis[3] = 0;
515                 axis[4] = 0; axis[5] = 0; 
516                 return 0;  
517         }
518
519         flags=joystick_read_raw_axis( masks, raw_axis );
520
521         if ( flags & JOY_1_X_AXIS )
522                 axis[0] = joy_get_scaled_reading( raw_axis[0], 0 );
523         else
524                 axis[0] = 0;
525
526         if ( flags & JOY_1_Y_AXIS )
527                 axis[1] = joy_get_scaled_reading( raw_axis[1], 1 );
528         else
529                 axis[1] = 0;
530
531         if ( flags & JOY_1_R_AXIS )
532                 axis[2] = joy_get_scaled_reading( raw_axis[2], 2 );
533         else
534                 axis[2] = 0;
535
536         if ( flags & JOY_1_Z_AXIS )
537                 axis[3] = joy_get_scaled_reading( raw_axis[3], 3 );
538         else
539                 axis[3] = 0;
540
541         if ( flags & JOY_1_U_AXIS )
542                 axis[4] = joy_get_scaled_reading( raw_axis[4], 4);
543         else
544                 axis[4] = 0;
545
546         if ( flags & JOY_1_V_AXIS )
547                 axis[5] = joy_get_scaled_reading( raw_axis[5], 5 );
548         else
549                 axis[5] = 0;
550
551
552         return flags;
553 }
554
555 int joy_get_btns()      
556 {
557         if ((!joy_installed)||(!joy_present)) return 0;
558
559         return joy_read_raw_buttons();
560 }
561
562
563 //Begin section modified 3/7/99 - Owen Evans
564
565 void joy_get_btn_down_cnt( int *btn0, int *btn1 )
566 {
567         if ((!joy_installed)||(!joy_present)) { *btn0=*btn1=0; return; }
568
569         joy_get_btns();
570
571         *btn0 = joystick.buttons[0].downcount;
572         joystick.buttons[0].downcount = 0;
573         *btn1 = joystick.buttons[1].downcount;
574         joystick.buttons[1].downcount = 0;
575 }
576
577 int joy_get_button_state( int btn )     
578 {    
579         if ((!joy_installed)||(!joy_present)) return 0;
580         if ( btn >= MAX_BUTTONS ) return 0;
581
582         joy_get_btns();
583
584         return joystick.buttons[btn].state;
585 }
586
587 int joy_get_button_up_cnt( int btn ) 
588 {
589         int count;
590
591         if ((!joy_installed)||(!joy_present)) return 0;
592
593         if ( btn >= MAX_BUTTONS ) return 0;
594
595         count = joystick.buttons[btn].upcount;
596         joystick.buttons[btn].upcount = 0;
597
598         return count;
599 }
600
601 int joy_get_button_down_cnt( int btn ) 
602 {
603         int count;
604
605         if ((!joy_installed)||(!joy_present)) return 0;
606         if ( btn >= MAX_BUTTONS ) return 0;
607
608         joy_get_btns();
609
610         count = joystick.buttons[btn].downcount;
611         joystick.buttons[btn].downcount = 0;
612
613         return count;
614 }
615
616 fix joy_get_button_down_time( int btn ) 
617 {
618         fix count;
619
620         if ((!joy_installed)||(!joy_present)) return 0;
621         if ( btn >= MAX_BUTTONS ) return 0;
622
623         joy_get_btns();
624
625         if (joystick.buttons[btn].state) {
626                 count = timer_get_fixed_seconds() - joystick.buttons[btn].timedown;
627                 joystick.buttons[btn].timedown = 0;
628         } else count = 0;
629         
630         return count;
631 }
632
633 //end changed section - OE
634
635
636 void joy_get_btn_up_cnt( int *btn0, int *btn1 ) 
637 {
638         if ((!joy_installed)||(!joy_present)) { *btn0=*btn1=0; return; }
639
640         *btn0 = joystick.buttons[0].upcount;
641         joystick.buttons[0].upcount = 0;
642         *btn1 = joystick.buttons[1].upcount;
643         joystick.buttons[1].upcount = 0;
644 }
645
646 #if 0
647 void joy_set_btn_values( int btn, int state, fix timedown, int downcount, int upcount )
648 {
649         joystick.buttons[btn].ignore = 1;
650         joystick.buttons[btn].state = state;
651         joystick.buttons[btn].timedown = fixmuldiv( timedown, 1193180, 65536 );
652         joystick.buttons[btn].downcount = downcount;
653         joystick.buttons[btn].upcount = upcount;
654 }
655 #endif
656
657 void joy_poll()
658 {
659 }
660
661 void joy_set_slow_reading(int flag) {
662 }
663
664 int joy_init(void)
665 {
666     return 0;
667 }