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