This commit was generated by cvs2svn to compensate for changes in r5,
[btb/d2x.git] / arch / dos / joyc.c
1 /*
2 THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX
3 SOFTWARE CORPORATION ("PARALLAX").  PARALLAX, IN DISTRIBUTING THE CODE TO
4 END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A
5 ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS
6 IN USING, DISPLAYING,  AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS
7 SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE
8 FREE PURPOSES.  IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE
9 CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES.  THE END-USER UNDERSTANDS
10 AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE.  
11 COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION.  ALL RIGHTS RESERVED.
12 */
13 /*
14  * $Source: /cvs/cvsroot/d2x/arch/dos/joyc.c,v $
15  * $Revision: 1.1.1.2 $
16  * $Author: bradleyb $
17  * $Date: 2001-01-19 03:33:52 $
18  * 
19  * Routines for joystick reading.
20  * 
21  * $Log: not supported by cvs2svn $
22  * Revision 1.1.1.1  1999/06/14 21:58:26  donut
23  * Import of d1x 1.37 source.
24  *
25  * Revision 1.37  1995/10/07  13:22:31  john
26  * Added new method of reading joystick that allows higher-priority
27  * interrupts to go off.
28  * 
29  * Revision 1.36  1995/03/30  11:03:40  john
30  * Made -JoyBios read buttons using BIOS.
31  * 
32  * Revision 1.35  1995/02/14  11:39:25  john
33  * Added polled/bios joystick readers..
34  * 
35  * Revision 1.34  1995/02/10  17:06:12  john
36  * Fixed bug with plugging in a joystick not getting detected.
37  * 
38  * Revision 1.33  1995/01/27  16:39:42  john
39  * Made so that if no joystick detected, it wont't
40  * read buttons.
41  * 
42  * Revision 1.32  1995/01/12  13:16:40  john
43  * Made it so that joystick can't lose an axis
44  * by 1 weird reading. Reading has to occurr during
45  * calibration for this to happen.
46  * 
47  * Revision 1.31  1994/12/28  15:56:03  john
48  * Fixed bug that refused to read joysticks whose 
49  * min,cen,max were less than 100 apart.
50  * 
51  * Revision 1.30  1994/12/28  15:31:53  john
52  * Added code to read joystick axis not all at one time.
53  * 
54  * Revision 1.29  1994/12/27  15:44:36  john
55  * Made the joystick timeout be at 1/100th of a second, 
56  * regardless of CPU speed.
57  * 
58  * Revision 1.28  1994/12/04  11:54:54  john
59  * Made stick read at whatever rate the clock is at, not
60  * at 18.2 times/second.
61  * 
62  * Revision 1.27  1994/11/29  02:25:40  john
63  * Made it so that the scaled reading returns 0 
64  * if the calibration factors look funny..
65  * 
66  * Revision 1.26  1994/11/22  11:08:07  john
67  * Commented out the ARCADE joystick.
68  * 
69  * Revision 1.25  1994/11/14  19:40:26  john
70  * Fixed bug with no joystick being detected.
71  * 
72  * Revision 1.24  1994/11/14  19:36:40  john
73  * Took out initial cheapy calibration.
74  * 
75  * Revision 1.23  1994/11/14  19:13:27  john
76  * Took out the calibration in joy_init
77  * 
78  * Revision 1.22  1994/10/17  10:09:57  john
79  * Made the state look at last_State, so that a joy_flush
80  * doesn't cause a new down state to be added next reading.
81  * 
82  * Revision 1.21  1994/10/13  11:36:23  john
83  * Made joy_down_time be kept track of in fixed seconds,
84  * not ticks.
85  * 
86  * Revision 1.20  1994/10/12  16:58:50  john
87  * Fixed bug w/ previous comment.
88  * 
89  * Revision 1.19  1994/10/12  16:57:44  john
90  * Added function to set a joystick button's state.
91  * 
92  * Revision 1.18  1994/10/11  10:20:13  john
93  * Fixed Flightstick Pro/
94  * ..
95  * 
96  * Revision 1.17  1994/09/29  18:29:20  john
97  * *** empty log message ***
98  * 
99  * Revision 1.16  1994/09/27  19:17:23  john
100  * Added code so that is joy_init is never called, joystick is not
101  * used at all.
102  * 
103  * Revision 1.15  1994/09/22  16:09:23  john
104  * Fixed some virtual memory lockdown problems with timer and
105  * joystick.
106  * 
107  * Revision 1.14  1994/09/16  11:44:42  john
108  * Fixed bug with slow joystick.
109  * 
110  * Revision 1.13  1994/09/16  11:36:15  john
111  * Fixed bug with reading non-present channels.
112  * 
113  * Revision 1.12  1994/09/15  20:52:48  john
114  * rme john
115  * Added support for the Arcade style joystick.
116  * 
117  * Revision 1.11  1994/09/13  20:04:49  john
118  * Fixed bug with joystick button down_time.
119  * 
120  * Revision 1.10  1994/09/10  13:48:07  john
121  * Made all 20 buttons read.
122  * 
123  * Revision 1.9  1994/08/31  09:55:02  john
124  * *** empty log message ***
125  * 
126  * Revision 1.8  1994/08/29  21:02:14  john
127  * Added joy_set_cal_values...
128  * 
129  * Revision 1.7  1994/08/29  20:52:17  john
130  * Added better cyberman support; also, joystick calibration
131  * value return funcctiionn,
132  * 
133  * Revision 1.6  1994/08/24  18:53:12  john
134  * Made Cyberman read like normal mouse; added dpmi module; moved
135  * mouse from assembly to c. Made mouse buttons return time_down.
136  * 
137  * Revision 1.5  1994/07/14  22:12:23  john
138  * Used intrinsic forms of outp to fix vmm error.
139  * 
140  * Revision 1.4  1994/07/07  19:52:59  matt
141  * Made joy_init() return success/fail flag
142  * Made joy_init() properly detect a stick if one is plugged in after joy_init()
143  * was called the first time.
144  * 
145  * Revision 1.3  1994/07/01  10:55:55  john
146  * Fixed some bugs... added support for 4 axis.
147  * 
148  * Revision 1.2  1994/06/30  20:36:55  john
149  * Revamped joystick code.
150  * 
151  * Revision 1.1  1994/06/30  15:42:15  john
152  * Initial revision
153  * 
154  * 
155  */
156
157
158 #include <conf.h>
159
160 #include <stdlib.h>
161 #include <stdio.h>
162 #include <dos.h>
163
164 //#define ARCADE 1
165
166 #include "pstypes.h"
167 #include "mono.h"
168 #include "joy.h"
169 #include "u_dpmi.h"
170 #include "timer.h"
171
172 #include "args.h"
173
174 extern int joy_bogus_reading;
175 int JOY_PORT = 513; //201h;
176 int joy_deadzone = 0;
177
178 int joy_read_stick_asm2( int read_masks, int * event_buffer, int timeout );
179 int joy_read_stick_friendly2( int read_masks, int * event_buffer, int timeout );
180 int joy_read_stick_polled2( int read_masks, int * event_buffer, int timeout );
181 int joy_read_stick_bios2( int read_masks, int * event_buffer, int timeout );
182 int joy_read_buttons_bios2();
183 void joy_read_buttons_bios_end2();
184
185
186 //In key.c
187 // ebx = read mask                                                                           
188 // edi = pointer to buffer                                                                                                                                                                                      
189 // returns number of events                                                                                                                                                                             
190
191 char joy_installed = 0;
192 char joy_present = 0;
193
194 typedef struct Button_info {
195         ubyte           ignore;
196         ubyte           state;
197         ubyte           last_state;
198         int             timedown;
199         ubyte           downcount;
200         ubyte           upcount;
201 } Button_info;
202
203 typedef struct Joy_info {
204         ubyte                   present_mask;
205         ubyte                   slow_read;
206         int                     max_timer;
207         int                     read_count;
208         ubyte                   last_value;
209         Button_info     buttons[MAX_BUTTONS];
210         int                     axis_min[4];
211         int                     axis_center[4];
212         int                     axis_max[4];
213 } Joy_info;
214
215 Joy_info joystick;
216
217 ubyte joy_read_buttons()
218 {
219  return ((~(inp(JOY_PORT) >> 4))&0xf);
220 }
221
222 void joy_get_cal_vals(int *axis_min, int *axis_center, int *axis_max)
223 {
224         int i;
225
226         for (i=0; i<4; i++)             {
227                 axis_min[i] = joystick.axis_min[i];
228                 axis_center[i] = joystick.axis_center[i];
229                 axis_max[i] = joystick.axis_max[i];
230         }
231 }
232
233 void joy_set_cal_vals(int *axis_min, int *axis_center, int *axis_max)
234 {
235         int i;
236
237         for (i=0; i<4; i++)             {
238                 joystick.axis_min[i] = axis_min[i];
239                 joystick.axis_center[i] = axis_center[i];
240                 joystick.axis_max[i] = axis_max[i];
241         }
242 }
243
244
245 ubyte joy_get_present_mask()    {
246         return joystick.present_mask;
247 }
248
249 void joy_set_timer_rate(int max_value ) {
250         _disable();
251         joystick.max_timer = max_value;
252         _enable();
253 }
254
255 int joy_get_timer_rate()        {
256         return joystick.max_timer;
257 }
258
259
260 void joy_flush()        {
261         int i;
262
263         if (!joy_installed) return;
264
265         _disable();
266         for (i=0; i<MAX_BUTTONS; i++ )  {
267                 joystick.buttons[i].ignore = 0;
268                 joystick.buttons[i].state = 0;
269                 joystick.buttons[i].timedown = 0;
270                 joystick.buttons[i].downcount = 0;      
271                 joystick.buttons[i].upcount = 0;        
272         }
273         _enable();
274
275 }
276
277 #pragma off (check_stack)
278
279 void joy_handler(int ticks_this_time)   {
280         ubyte value;
281         int i, state;
282         Button_info * button;
283
284 //      joystick.max_timer = ticks_this_time;
285
286         if ( joystick.slow_read & JOY_BIOS_READINGS )           {
287                 joystick.read_count++;
288                 if ( joystick.read_count > 7 )  {
289                         joystick.read_count = 0;
290                         value = joy_read_buttons_bios2();
291                         joystick.last_value = value;
292                 } else {
293                         value = joystick.last_value;
294                 }               
295         } else {
296                 value = joy_read_buttons(); //JOY_READ_BUTTONS;
297         }
298
299         for (i=0; i<MAX_BUTTONS; i++ )  {
300                 button = &joystick.buttons[i];
301                 if (!button->ignore) {
302                         if ( i < 5 )
303                                 state = (value >> i) & 1;
304                         else if (i==(value+4))  
305                                 state = 1;
306                         else
307                                 state = 0;
308
309                         if ( button->last_state == state )      {
310                                 if (state) button->timedown += ticks_this_time;
311                         } else {
312                                 if (state)      {
313                                         button->downcount += state;
314                                         button->state = 1;
315                                 } else {        
316                                         button->upcount += button->state;
317                                         button->state = 0;
318                                 }
319                                 button->last_state = state;
320                         }
321                 }
322         }
323 }
324
325 void joy_handler_end()  {               // Dummy function to help calculate size of joystick handler function
326 }
327
328 #pragma off (check_stack)
329
330 ubyte joy_read_raw_buttons()    {
331         if ( joystick.slow_read & JOY_BIOS_READINGS )   
332                 return joy_read_buttons_bios2();
333         else 
334                 return joy_read_buttons(); //JOY_READ_BUTTONS;
335 }
336
337 void joy_set_slow_reading(int flag)
338 {
339         joystick.slow_read |= flag;
340         joy_set_cen();
341 }
342
343 ubyte joystick_read_raw_axis( ubyte mask, int * axis )
344 {
345         ubyte read_masks, org_masks;
346         int t, t1, t2, buffer[4*2+2];
347         int e, i, num_channels, c;
348
349         axis[0] = 0; axis[1] = 0;
350         axis[2] = 0; axis[3] = 0;
351
352         if (!joy_installed) return 0;
353
354         read_masks = 0;
355         org_masks = mask;
356
357         mask &= joystick.present_mask;                  // Don't read non-present channels
358         if ( mask==0 )  {
359                 return 0;               // Don't read if no stick connected.
360         }
361
362         if ( joystick.slow_read & JOY_SLOW_READINGS )   {
363                 for (c=0; c<4; c++ )    {               
364                         if ( mask & (1 << c))   {
365                                 // Time out at  (1/100th of a second)
366
367                                 if ( joystick.slow_read & JOY_POLLED_READINGS )
368                                         num_channels = joy_read_stick_polled2( (1 << c), buffer, 65536 );
369                                 else if ( joystick.slow_read & JOY_BIOS_READINGS )
370                                         num_channels = joy_read_stick_bios2( (1 << c), buffer, 65536 );
371                                 else if ( joystick.slow_read & JOY_FRIENDLY_READINGS )
372                                         num_channels = joy_read_stick_friendly2( (1 << c), buffer, (1193180/100) );
373                                 else
374                                         num_channels = joy_read_stick_asm2( (1 << c), buffer, (1193180/100) );
375         
376                                 if ( num_channels > 0 ) {
377                                         t1 = buffer[0];
378                                         e = buffer[1];
379                                         t2 = buffer[2];
380                                         if ( joystick.slow_read & (JOY_POLLED_READINGS|JOY_BIOS_READINGS) )     {
381                                                 t = t2 - t1;
382                                         } else {                        
383                                                 if ( t1 > t2 )
384                                                         t = t1 - t2;
385                                                 else                            {
386                                                         t = t1 + joystick.max_timer - t2;
387                                                         //mprintf( 0, "%d, %d, %d, %d\n", t1, t2, joystick.max_timer, t );
388                                                 }
389                                         }
390         
391                                         if ( e & 1 ) { axis[0] = t; read_masks |= 1; }
392                                         if ( e & 2 ) { axis[1] = t; read_masks |= 2; }
393                                         if ( e & 4 ) { axis[2] = t; read_masks |= 4; }
394                                         if ( e & 8 ) { axis[3] = t; read_masks |= 8; }
395                                 }
396                         }
397                 }
398         } else {
399                 // Time out at  (1/100th of a second)
400                 if ( joystick.slow_read & JOY_POLLED_READINGS )
401                         num_channels = joy_read_stick_polled2( mask, buffer, 65536 );
402                 else if ( joystick.slow_read & JOY_BIOS_READINGS )
403                         num_channels = joy_read_stick_bios2( mask, buffer, 65536 );
404                 else if ( joystick.slow_read & JOY_FRIENDLY_READINGS )
405                         num_channels = joy_read_stick_friendly2( mask, buffer, (1193180/100) );
406                 else 
407                         num_channels = joy_read_stick_asm2( mask, buffer, (1193180/100) );
408                 //mprintf(( 0, "(%d)\n", num_channels ));
409         
410                 for (i=0; i<num_channels; i++ ) {
411                         t1 = buffer[0];
412                         t2 = buffer[i*2+2];
413                         
414                         if ( joystick.slow_read & (JOY_POLLED_READINGS|JOY_BIOS_READINGS) )     {
415                                 t = t2 - t1;
416                         } else {                        
417                                 if ( t1 > t2 )
418                                         t = t1 - t2;
419                                 else                            {
420                                         t = t1 + joystick.max_timer - t2;
421                                         //mprintf(( 0, "%d, %d, %d, %d\n", t1, t2, joystick.max_timer, t ));
422                                 }
423                         }               
424                         e = buffer[i*2+1];
425         
426                         if ( e & 1 ) { axis[0] = t; read_masks |= 1; }
427                         if ( e & 2 ) { axis[1] = t; read_masks |= 2; }
428                         if ( e & 4 ) { axis[2] = t; read_masks |= 4; }
429                         if ( e & 8 ) { axis[3] = t; read_masks |= 8; }
430                 }
431                 
432         }
433
434         return read_masks;
435 }
436
437 #ifdef __GNUC__
438 #define near
439 #endif
440
441 int joy_init()  
442 {
443         int i;
444         int temp_axis[4];
445
446 //        if(args_find("-joy209"))
447 //         use_alt_joyport=1;
448         if(args_find("-joy209"))
449          JOY_PORT = 521;  //209h;
450          
451         joy_flush();
452
453         _disable();
454         for (i=0; i<MAX_BUTTONS; i++ )  
455                 joystick.buttons[i].last_state = 0;
456         _enable();
457
458         if ( !joy_installed )   {
459                 joy_present = 0;
460                 joy_installed = 1;
461                 //joystick.max_timer = 65536;
462                 joystick.slow_read = 0;
463                 joystick.read_count = 0;
464                 joystick.last_value = 0;
465
466                 //--------------- lock everything for the virtal memory ----------------------------------
467                 if (!dpmi_lock_region ((void near *)joy_read_buttons_bios2, (char *)joy_read_buttons_bios_end2 - (char near *)joy_read_buttons_bios2))   {
468                         printf( "Error locking joystick handler (read bios)!\n" );
469                         exit(1);
470                 }
471
472
473
474                 if (!dpmi_lock_region ((void near *)joy_handler, (char *)joy_handler_end - (char near *)joy_handler))   {
475                         printf( "Error locking joystick handler!\n" );
476                         exit(1);
477                 }
478
479                 if (!dpmi_lock_region (&joystick, sizeof(Joy_info)))    {
480                         printf( "Error locking joystick handler's data!\n" );
481                         exit(1);
482                 }
483
484                 timer_set_joyhandler(joy_handler);
485         }
486
487         // Do initial cheapy calibration...
488         joystick.present_mask = JOY_ALL_AXIS;           // Assume they're all present
489         do      {
490                 joystick.present_mask = joystick_read_raw_axis( JOY_ALL_AXIS, temp_axis );
491         } while( joy_bogus_reading );
492
493         if ( joystick.present_mask & 3 )
494                 joy_present = 1;
495         else
496                 joy_present = 0;
497
498         return joy_present;
499 }
500
501 void joy_close()        
502 {
503         if (!joy_installed) return;
504         joy_installed = 0;
505 }
506
507 void joy_set_ul()       
508 {
509         joystick.present_mask = JOY_ALL_AXIS;           // Assume they're all present
510         do      {
511                 joystick.present_mask = joystick_read_raw_axis( JOY_ALL_AXIS, joystick.axis_min );
512         } while( joy_bogus_reading );
513         if ( joystick.present_mask & 3 )
514                 joy_present = 1;
515         else
516                 joy_present = 0;
517 }
518
519 void joy_set_lr()       
520 {
521         joystick.present_mask = JOY_ALL_AXIS;           // Assume they're all present
522         do {
523                 joystick.present_mask = joystick_read_raw_axis( JOY_ALL_AXIS, joystick.axis_max );
524         } while( joy_bogus_reading );
525
526         if ( joystick.present_mask & 3 )
527                 joy_present = 1;
528         else
529                 joy_present = 0;
530 }
531
532 void joy_set_cen() 
533 {
534         joystick.present_mask = JOY_ALL_AXIS;           // Assume they're all present
535         do {
536                 joystick.present_mask = joystick_read_raw_axis( JOY_ALL_AXIS, joystick.axis_center );
537         } while( joy_bogus_reading );
538
539         if ( joystick.present_mask & 3 )
540                 joy_present = 1;
541         else
542                 joy_present = 0;
543 }
544
545 void joy_set_cen_fake(int channel)      
546 {
547
548         int i,n=0;
549         int minx, maxx, cenx;
550         
551         minx=maxx=cenx=0;
552
553         for (i=0; i<4; i++ )    {
554                 if ( (joystick.present_mask & (1<<i)) && (i!=channel) ) {
555                         n++;
556                         minx += joystick.axis_min[i];
557                         maxx += joystick.axis_max[i];
558                         cenx += joystick.axis_center[i];
559                 }
560         }
561         minx /= n;
562         maxx /= n;
563         cenx /= n;
564
565         joystick.axis_min[channel] = minx;
566         joystick.axis_max[channel] = maxx;
567         joystick.axis_center[channel] = cenx;
568 }
569
570 int joy_get_scaled_reading( int raw, int axn )  
571 {
572  int x, d, dz;
573
574  // Make sure it's calibrated properly.
575 //added/changed on 8/14/98 to allow smaller calibrating sticks to work (by Eivind Brendryen)--was <5
576    if ( joystick.axis_center[axn] - joystick.axis_min[axn] < 2 )
577     return 0;
578    if ( joystick.axis_max[axn] - joystick.axis_center[axn] < 2 )
579     return 0;
580 //end change - Victor Rachels  (by Eivind Brendryen)
581
582   raw -= joystick.axis_center[axn];
583
584    if ( raw < 0 )
585     d = joystick.axis_center[axn]-joystick.axis_min[axn];
586    else
587     d = joystick.axis_max[axn]-joystick.axis_center[axn];
588
589
590    if ( d )
591     x = (raw << 7) / d;
592    else
593     x = 0;
594
595
596    if ( x < -128 )
597     x = -128;
598    if ( x > 127 )
599     x = 127;
600
601 //added on 4/13/99 by Victor Rachels to add deadzone control
602   dz =  (joy_deadzone) * 6;
603    if ((x > (-1*dz)) && (x < dz))
604     x = 0;
605 //end this section addition -VR
606
607   return x;
608 }
609
610 int last_reading[4] = { 0, 0, 0, 0 };
611
612 void joy_get_pos( int *x, int *y )      
613 {
614         ubyte flags;
615         int axis[4];
616
617         if ((!joy_installed)||(!joy_present)) { *x=*y=0; return; }
618
619         flags=joystick_read_raw_axis( JOY_1_X_AXIS+JOY_1_Y_AXIS, axis );
620
621         if ( joy_bogus_reading )        {
622                 axis[0] = last_reading[0];
623                 axis[1] = last_reading[1];
624                 flags = JOY_1_X_AXIS+JOY_1_Y_AXIS;
625         } else {
626                 last_reading[0] = axis[0];
627                 last_reading[1] = axis[1];
628         }
629
630         if ( flags & JOY_1_X_AXIS )
631                 *x = joy_get_scaled_reading( axis[0], 0 );
632         else
633                 *x = 0;
634
635         if ( flags & JOY_1_Y_AXIS )
636                 *y = joy_get_scaled_reading( axis[1], 1 );
637         else
638                 *y = 0;
639 }
640
641 ubyte joy_read_stick( ubyte masks, int *axis )  
642 {
643         ubyte flags;
644         int raw_axis[4];
645
646         if ((!joy_installed)||(!joy_present)) { 
647                 axis[0] = 0; axis[1] = 0;
648                 axis[2] = 0; axis[3] = 0;
649                 return 0;  
650         }
651
652         flags=joystick_read_raw_axis( masks, raw_axis );
653
654         if ( joy_bogus_reading )        {
655                 axis[0] = last_reading[0];
656                 axis[1] = last_reading[1];
657                 axis[2] = last_reading[2];
658                 axis[3] = last_reading[3];
659                 flags = masks;
660         } else {
661                 last_reading[0] = axis[0];
662                 last_reading[1] = axis[1];
663                 last_reading[2] = axis[2];
664                 last_reading[3] = axis[3];
665         }
666
667         if ( flags & JOY_1_X_AXIS )
668                 axis[0] = joy_get_scaled_reading( raw_axis[0], 0 );
669         else
670                 axis[0] = 0;
671
672         if ( flags & JOY_1_Y_AXIS )
673                 axis[1] = joy_get_scaled_reading( raw_axis[1], 1 );
674         else
675                 axis[1] = 0;
676
677         if ( flags & JOY_2_X_AXIS )
678                 axis[2] = joy_get_scaled_reading( raw_axis[2], 2 );
679         else
680                 axis[2] = 0;
681
682         if ( flags & JOY_2_Y_AXIS )
683                 axis[3] = joy_get_scaled_reading( raw_axis[3], 3 );
684         else
685                 axis[3] = 0;
686
687         return flags;
688 }
689
690
691 int joy_get_btns()      
692 {
693         if ((!joy_installed)||(!joy_present)) return 0;
694
695         return joy_read_raw_buttons();
696 }
697
698 void joy_get_btn_down_cnt( int *btn0, int *btn1 ) 
699 {
700         if ((!joy_installed)||(!joy_present)) { *btn0=*btn1=0; return; }
701
702         _disable();
703         *btn0 = joystick.buttons[0].downcount;
704         joystick.buttons[0].downcount = 0;
705         *btn1 = joystick.buttons[1].downcount;
706         joystick.buttons[1].downcount = 0;
707         _enable();
708 }
709
710 int joy_get_button_state( int btn )     
711 {
712         int count;
713
714         if ((!joy_installed)||(!joy_present)) return 0;
715
716         if ( btn >= MAX_BUTTONS ) return 0;
717
718         _disable();
719         count = joystick.buttons[btn].state;
720         _enable();
721         
722         return  count;
723 }
724
725 int joy_get_button_up_cnt( int btn ) 
726 {
727         int count;
728
729         if ((!joy_installed)||(!joy_present)) return 0;
730
731         if ( btn >= MAX_BUTTONS ) return 0;
732
733         _disable();
734         count = joystick.buttons[btn].upcount;
735         joystick.buttons[btn].upcount = 0;
736         _enable();
737
738         return count;
739 }
740
741 int joy_get_button_down_cnt( int btn ) 
742 {
743         int count;
744
745         if ((!joy_installed)||(!joy_present)) return 0;
746         if ( btn >= MAX_BUTTONS ) return 0;
747
748         _disable();
749         count = joystick.buttons[btn].downcount;
750         joystick.buttons[btn].downcount = 0;
751         _enable();
752
753         return count;
754 }
755
756         
757 fix joy_get_button_down_time( int btn ) 
758 {
759         fix count;
760
761         if ((!joy_installed)||(!joy_present)) return 0;
762         if ( btn >= MAX_BUTTONS ) return 0;
763
764         _disable();
765         count = joystick.buttons[btn].timedown;
766         joystick.buttons[btn].timedown = 0;
767         _enable();
768
769         return fixmuldiv(count, 65536, 1193180 );
770 }
771
772 void joy_get_btn_up_cnt( int *btn0, int *btn1 ) 
773 {
774         if ((!joy_installed)||(!joy_present)) { *btn0=*btn1=0; return; }
775
776         _disable();
777         *btn0 = joystick.buttons[0].upcount;
778         joystick.buttons[0].upcount = 0;
779         *btn1 = joystick.buttons[1].upcount;
780         joystick.buttons[1].upcount = 0;
781         _enable();
782 }
783
784 void joy_set_btn_values( int btn, int state, fix timedown, int downcount, int upcount )
785 {
786         _disable();
787         joystick.buttons[btn].ignore = 1;
788         joystick.buttons[btn].state = state;
789         joystick.buttons[btn].timedown = fixmuldiv( timedown, 1193180, 65536 );
790         joystick.buttons[btn].downcount = downcount;
791         joystick.buttons[btn].upcount = upcount;
792         _enable();
793 }
794
795 void joy_poll()
796 {
797         if ( joystick.slow_read & JOY_BIOS_READINGS )   
798                 joystick.last_value = joy_read_buttons_bios2();
799 }