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