]> icculus.org git repositories - btb/d2x.git/blob - arch/dos/joyc.c
442873abfffac2728be6b52d5a3c742c6f29800f
[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.1 $
16  * $Author: bradleyb $
17  * $Date: 2001-01-19 03:30:15 $
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 #ifdef RCS
159 static char rcsid[] = "$Id: joyc.c,v 1.1.1.1 2001-01-19 03:30:15 bradleyb Exp $";
160 #endif
161
162 #include <stdlib.h>
163 #include <stdio.h>
164 #include <conio.h>
165 #include <dos.h>
166 #include <i86.h>
167
168 //#define ARCADE 1
169
170 #include "types.h"
171 #include "mono.h"
172 #include "joy.h"
173 #include "u_dpmi.h"
174 #include "timer.h"
175
176 #include "args.h"
177
178 extern int joy_bogus_reading;
179 int JOY_PORT = 513; //201h;
180 int joy_deadzone = 0;
181
182 int joy_read_stick_asm2( int read_masks, int * event_buffer, int timeout );
183 int joy_read_stick_friendly2( int read_masks, int * event_buffer, int timeout );
184 int joy_read_stick_polled2( int read_masks, int * event_buffer, int timeout );
185 int joy_read_stick_bios2( int read_masks, int * event_buffer, int timeout );
186 int joy_read_buttons_bios2();
187 void joy_read_buttons_bios_end2();
188
189
190 //In key.c
191 // ebx = read mask                                                                           
192 // edi = pointer to buffer                                                                                                                                                                                      
193 // returns number of events                                                                                                                                                                             
194
195 char joy_installed = 0;
196 char joy_present = 0;
197
198 typedef struct Button_info {
199         ubyte           ignore;
200         ubyte           state;
201         ubyte           last_state;
202         int             timedown;
203         ubyte           downcount;
204         ubyte           upcount;
205 } Button_info;
206
207 typedef struct Joy_info {
208         ubyte                   present_mask;
209         ubyte                   slow_read;
210         int                     max_timer;
211         int                     read_count;
212         ubyte                   last_value;
213         Button_info     buttons[MAX_BUTTONS];
214         int                     axis_min[4];
215         int                     axis_center[4];
216         int                     axis_max[4];
217 } Joy_info;
218
219 Joy_info joystick;
220
221 ubyte joy_read_buttons()
222 {
223  return ((~(inp(JOY_PORT) >> 4))&0xf);
224 }
225
226 void joy_get_cal_vals(int *axis_min, int *axis_center, int *axis_max)
227 {
228         int i;
229
230         for (i=0; i<4; i++)             {
231                 axis_min[i] = joystick.axis_min[i];
232                 axis_center[i] = joystick.axis_center[i];
233                 axis_max[i] = joystick.axis_max[i];
234         }
235 }
236
237 void joy_set_cal_vals(int *axis_min, int *axis_center, int *axis_max)
238 {
239         int i;
240
241         for (i=0; i<4; i++)             {
242                 joystick.axis_min[i] = axis_min[i];
243                 joystick.axis_center[i] = axis_center[i];
244                 joystick.axis_max[i] = axis_max[i];
245         }
246 }
247
248
249 ubyte joy_get_present_mask()    {
250         return joystick.present_mask;
251 }
252
253 void joy_set_timer_rate(int max_value ) {
254         _disable();
255         joystick.max_timer = max_value;
256         _enable();
257 }
258
259 int joy_get_timer_rate()        {
260         return joystick.max_timer;
261 }
262
263
264 void joy_flush()        {
265         int i;
266
267         if (!joy_installed) return;
268
269         _disable();
270         for (i=0; i<MAX_BUTTONS; i++ )  {
271                 joystick.buttons[i].ignore = 0;
272                 joystick.buttons[i].state = 0;
273                 joystick.buttons[i].timedown = 0;
274                 joystick.buttons[i].downcount = 0;      
275                 joystick.buttons[i].upcount = 0;        
276         }
277         _enable();
278
279 }
280
281 #pragma off (check_stack)
282
283 void joy_handler(int ticks_this_time)   {
284         ubyte value;
285         int i, state;
286         Button_info * button;
287
288 //      joystick.max_timer = ticks_this_time;
289
290         if ( joystick.slow_read & JOY_BIOS_READINGS )           {
291                 joystick.read_count++;
292                 if ( joystick.read_count > 7 )  {
293                         joystick.read_count = 0;
294                         value = joy_read_buttons_bios2();
295                         joystick.last_value = value;
296                 } else {
297                         value = joystick.last_value;
298                 }               
299         } else {
300                 value = joy_read_buttons(); //JOY_READ_BUTTONS;
301         }
302
303         for (i=0; i<MAX_BUTTONS; i++ )  {
304                 button = &joystick.buttons[i];
305                 if (!button->ignore) {
306                         if ( i < 5 )
307                                 state = (value >> i) & 1;
308                         else if (i==(value+4))  
309                                 state = 1;
310                         else
311                                 state = 0;
312
313                         if ( button->last_state == state )      {
314                                 if (state) button->timedown += ticks_this_time;
315                         } else {
316                                 if (state)      {
317                                         button->downcount += state;
318                                         button->state = 1;
319                                 } else {        
320                                         button->upcount += button->state;
321                                         button->state = 0;
322                                 }
323                                 button->last_state = state;
324                         }
325                 }
326         }
327 }
328
329 void joy_handler_end()  {               // Dummy function to help calculate size of joystick handler function
330 }
331
332 #pragma off (check_stack)
333
334 ubyte joy_read_raw_buttons()    {
335         if ( joystick.slow_read & JOY_BIOS_READINGS )   
336                 return joy_read_buttons_bios2();
337         else 
338                 return joy_read_buttons(); //JOY_READ_BUTTONS;
339 }
340
341 void joy_set_slow_reading(int flag)
342 {
343         joystick.slow_read |= flag;
344         joy_set_cen();
345 }
346
347 ubyte joystick_read_raw_axis( ubyte mask, int * axis )
348 {
349         ubyte read_masks, org_masks;
350         int t, t1, t2, buffer[4*2+2];
351         int e, i, num_channels, c;
352
353         axis[0] = 0; axis[1] = 0;
354         axis[2] = 0; axis[3] = 0;
355
356         if (!joy_installed) return 0;
357
358         read_masks = 0;
359         org_masks = mask;
360
361         mask &= joystick.present_mask;                  // Don't read non-present channels
362         if ( mask==0 )  {
363                 return 0;               // Don't read if no stick connected.
364         }
365
366         if ( joystick.slow_read & JOY_SLOW_READINGS )   {
367                 for (c=0; c<4; c++ )    {               
368                         if ( mask & (1 << c))   {
369                                 // Time out at  (1/100th of a second)
370
371                                 if ( joystick.slow_read & JOY_POLLED_READINGS )
372                                         num_channels = joy_read_stick_polled2( (1 << c), buffer, 65536 );
373                                 else if ( joystick.slow_read & JOY_BIOS_READINGS )
374                                         num_channels = joy_read_stick_bios2( (1 << c), buffer, 65536 );
375                                 else if ( joystick.slow_read & JOY_FRIENDLY_READINGS )
376                                         num_channels = joy_read_stick_friendly2( (1 << c), buffer, (1193180/100) );
377                                 else
378                                         num_channels = joy_read_stick_asm2( (1 << c), buffer, (1193180/100) );
379         
380                                 if ( num_channels > 0 ) {
381                                         t1 = buffer[0];
382                                         e = buffer[1];
383                                         t2 = buffer[2];
384                                         if ( joystick.slow_read & (JOY_POLLED_READINGS|JOY_BIOS_READINGS) )     {
385                                                 t = t2 - t1;
386                                         } else {                        
387                                                 if ( t1 > t2 )
388                                                         t = t1 - t2;
389                                                 else                            {
390                                                         t = t1 + joystick.max_timer - t2;
391                                                         //mprintf( 0, "%d, %d, %d, %d\n", t1, t2, joystick.max_timer, t );
392                                                 }
393                                         }
394         
395                                         if ( e & 1 ) { axis[0] = t; read_masks |= 1; }
396                                         if ( e & 2 ) { axis[1] = t; read_masks |= 2; }
397                                         if ( e & 4 ) { axis[2] = t; read_masks |= 4; }
398                                         if ( e & 8 ) { axis[3] = t; read_masks |= 8; }
399                                 }
400                         }
401                 }
402         } else {
403                 // Time out at  (1/100th of a second)
404                 if ( joystick.slow_read & JOY_POLLED_READINGS )
405                         num_channels = joy_read_stick_polled2( mask, buffer, 65536 );
406                 else if ( joystick.slow_read & JOY_BIOS_READINGS )
407                         num_channels = joy_read_stick_bios2( mask, buffer, 65536 );
408                 else if ( joystick.slow_read & JOY_FRIENDLY_READINGS )
409                         num_channels = joy_read_stick_friendly2( mask, buffer, (1193180/100) );
410                 else 
411                         num_channels = joy_read_stick_asm2( mask, buffer, (1193180/100) );
412                 //mprintf(( 0, "(%d)\n", num_channels ));
413         
414                 for (i=0; i<num_channels; i++ ) {
415                         t1 = buffer[0];
416                         t2 = buffer[i*2+2];
417                         
418                         if ( joystick.slow_read & (JOY_POLLED_READINGS|JOY_BIOS_READINGS) )     {
419                                 t = t2 - t1;
420                         } else {                        
421                                 if ( t1 > t2 )
422                                         t = t1 - t2;
423                                 else                            {
424                                         t = t1 + joystick.max_timer - t2;
425                                         //mprintf(( 0, "%d, %d, %d, %d\n", t1, t2, joystick.max_timer, t ));
426                                 }
427                         }               
428                         e = buffer[i*2+1];
429         
430                         if ( e & 1 ) { axis[0] = t; read_masks |= 1; }
431                         if ( e & 2 ) { axis[1] = t; read_masks |= 2; }
432                         if ( e & 4 ) { axis[2] = t; read_masks |= 4; }
433                         if ( e & 8 ) { axis[3] = t; read_masks |= 8; }
434                 }
435                 
436         }
437
438         return read_masks;
439 }
440
441 #ifdef __GNUC__
442 #define near
443 #endif
444
445 int joy_init()  
446 {
447         int i;
448         int temp_axis[4];
449
450 //        if(FindArg("-joy209"))
451 //         use_alt_joyport=1;
452         if(FindArg("-joy209"))
453          JOY_PORT = 521;  //209h;
454          
455         joy_flush();
456
457         _disable();
458         for (i=0; i<MAX_BUTTONS; i++ )  
459                 joystick.buttons[i].last_state = 0;
460         _enable();
461
462         if ( !joy_installed )   {
463                 joy_present = 0;
464                 joy_installed = 1;
465                 //joystick.max_timer = 65536;
466                 joystick.slow_read = 0;
467                 joystick.read_count = 0;
468                 joystick.last_value = 0;
469
470                 //--------------- lock everything for the virtal memory ----------------------------------
471                 if (!dpmi_lock_region ((void near *)joy_read_buttons_bios2, (char *)joy_read_buttons_bios_end2 - (char near *)joy_read_buttons_bios2))   {
472                         printf( "Error locking joystick handler (read bios)!\n" );
473                         exit(1);
474                 }
475
476
477
478                 if (!dpmi_lock_region ((void near *)joy_handler, (char *)joy_handler_end - (char near *)joy_handler))   {
479                         printf( "Error locking joystick handler!\n" );
480                         exit(1);
481                 }
482
483                 if (!dpmi_lock_region (&joystick, sizeof(Joy_info)))    {
484                         printf( "Error locking joystick handler's data!\n" );
485                         exit(1);
486                 }
487
488                 timer_set_joyhandler(joy_handler);
489         }
490
491         // Do initial cheapy calibration...
492         joystick.present_mask = JOY_ALL_AXIS;           // Assume they're all present
493         do      {
494                 joystick.present_mask = joystick_read_raw_axis( JOY_ALL_AXIS, temp_axis );
495         } while( joy_bogus_reading );
496
497         if ( joystick.present_mask & 3 )
498                 joy_present = 1;
499         else
500                 joy_present = 0;
501
502         return joy_present;
503 }
504
505 void joy_close()        
506 {
507         if (!joy_installed) return;
508         joy_installed = 0;
509 }
510
511 void joy_set_ul()       
512 {
513         joystick.present_mask = JOY_ALL_AXIS;           // Assume they're all present
514         do      {
515                 joystick.present_mask = joystick_read_raw_axis( JOY_ALL_AXIS, joystick.axis_min );
516         } while( joy_bogus_reading );
517         if ( joystick.present_mask & 3 )
518                 joy_present = 1;
519         else
520                 joy_present = 0;
521 }
522
523 void joy_set_lr()       
524 {
525         joystick.present_mask = JOY_ALL_AXIS;           // Assume they're all present
526         do {
527                 joystick.present_mask = joystick_read_raw_axis( JOY_ALL_AXIS, joystick.axis_max );
528         } while( joy_bogus_reading );
529
530         if ( joystick.present_mask & 3 )
531                 joy_present = 1;
532         else
533                 joy_present = 0;
534 }
535
536 void joy_set_cen() 
537 {
538         joystick.present_mask = JOY_ALL_AXIS;           // Assume they're all present
539         do {
540                 joystick.present_mask = joystick_read_raw_axis( JOY_ALL_AXIS, joystick.axis_center );
541         } while( joy_bogus_reading );
542
543         if ( joystick.present_mask & 3 )
544                 joy_present = 1;
545         else
546                 joy_present = 0;
547 }
548
549 void joy_set_cen_fake(int channel)      
550 {
551
552         int i,n=0;
553         int minx, maxx, cenx;
554         
555         minx=maxx=cenx=0;
556
557         for (i=0; i<4; i++ )    {
558                 if ( (joystick.present_mask & (1<<i)) && (i!=channel) ) {
559                         n++;
560                         minx += joystick.axis_min[i];
561                         maxx += joystick.axis_max[i];
562                         cenx += joystick.axis_center[i];
563                 }
564         }
565         minx /= n;
566         maxx /= n;
567         cenx /= n;
568
569         joystick.axis_min[channel] = minx;
570         joystick.axis_max[channel] = maxx;
571         joystick.axis_center[channel] = cenx;
572 }
573
574 int joy_get_scaled_reading( int raw, int axn )  
575 {
576  int x, d, dz;
577
578  // Make sure it's calibrated properly.
579 //added/changed on 8/14/98 to allow smaller calibrating sticks to work (by Eivind Brendryen)--was <5
580    if ( joystick.axis_center[axn] - joystick.axis_min[axn] < 2 )
581     return 0;
582    if ( joystick.axis_max[axn] - joystick.axis_center[axn] < 2 )
583     return 0;
584 //end change - Victor Rachels  (by Eivind Brendryen)
585
586   raw -= joystick.axis_center[axn];
587
588    if ( raw < 0 )
589     d = joystick.axis_center[axn]-joystick.axis_min[axn];
590    else
591     d = joystick.axis_max[axn]-joystick.axis_center[axn];
592
593
594    if ( d )
595     x = (raw << 7) / d;
596    else
597     x = 0;
598
599
600    if ( x < -128 )
601     x = -128;
602    if ( x > 127 )
603     x = 127;
604
605 //added on 4/13/99 by Victor Rachels to add deadzone control
606   dz =  (joy_deadzone) * 6;
607    if ((x > (-1*dz)) && (x < dz))
608     x = 0;
609 //end this section addition -VR
610
611   return x;
612 }
613
614 int last_reading[4] = { 0, 0, 0, 0 };
615
616 void joy_get_pos( int *x, int *y )      
617 {
618         ubyte flags;
619         int axis[4];
620
621         if ((!joy_installed)||(!joy_present)) { *x=*y=0; return; }
622
623         flags=joystick_read_raw_axis( JOY_1_X_AXIS+JOY_1_Y_AXIS, axis );
624
625         if ( joy_bogus_reading )        {
626                 axis[0] = last_reading[0];
627                 axis[1] = last_reading[1];
628                 flags = JOY_1_X_AXIS+JOY_1_Y_AXIS;
629         } else {
630                 last_reading[0] = axis[0];
631                 last_reading[1] = axis[1];
632         }
633
634         if ( flags & JOY_1_X_AXIS )
635                 *x = joy_get_scaled_reading( axis[0], 0 );
636         else
637                 *x = 0;
638
639         if ( flags & JOY_1_Y_AXIS )
640                 *y = joy_get_scaled_reading( axis[1], 1 );
641         else
642                 *y = 0;
643 }
644
645 ubyte joy_read_stick( ubyte masks, int *axis )  
646 {
647         ubyte flags;
648         int raw_axis[4];
649
650         if ((!joy_installed)||(!joy_present)) { 
651                 axis[0] = 0; axis[1] = 0;
652                 axis[2] = 0; axis[3] = 0;
653                 return 0;  
654         }
655
656         flags=joystick_read_raw_axis( masks, raw_axis );
657
658         if ( joy_bogus_reading )        {
659                 axis[0] = last_reading[0];
660                 axis[1] = last_reading[1];
661                 axis[2] = last_reading[2];
662                 axis[3] = last_reading[3];
663                 flags = masks;
664         } else {
665                 last_reading[0] = axis[0];
666                 last_reading[1] = axis[1];
667                 last_reading[2] = axis[2];
668                 last_reading[3] = axis[3];
669         }
670
671         if ( flags & JOY_1_X_AXIS )
672                 axis[0] = joy_get_scaled_reading( raw_axis[0], 0 );
673         else
674                 axis[0] = 0;
675
676         if ( flags & JOY_1_Y_AXIS )
677                 axis[1] = joy_get_scaled_reading( raw_axis[1], 1 );
678         else
679                 axis[1] = 0;
680
681         if ( flags & JOY_2_X_AXIS )
682                 axis[2] = joy_get_scaled_reading( raw_axis[2], 2 );
683         else
684                 axis[2] = 0;
685
686         if ( flags & JOY_2_Y_AXIS )
687                 axis[3] = joy_get_scaled_reading( raw_axis[3], 3 );
688         else
689                 axis[3] = 0;
690
691         return flags;
692 }
693
694
695 int joy_get_btns()      
696 {
697         if ((!joy_installed)||(!joy_present)) return 0;
698
699         return joy_read_raw_buttons();
700 }
701
702 void joy_get_btn_down_cnt( int *btn0, int *btn1 ) 
703 {
704         if ((!joy_installed)||(!joy_present)) { *btn0=*btn1=0; return; }
705
706         _disable();
707         *btn0 = joystick.buttons[0].downcount;
708         joystick.buttons[0].downcount = 0;
709         *btn1 = joystick.buttons[1].downcount;
710         joystick.buttons[1].downcount = 0;
711         _enable();
712 }
713
714 int joy_get_button_state( int btn )     
715 {
716         int count;
717
718         if ((!joy_installed)||(!joy_present)) return 0;
719
720         if ( btn >= MAX_BUTTONS ) return 0;
721
722         _disable();
723         count = joystick.buttons[btn].state;
724         _enable();
725         
726         return  count;
727 }
728
729 int joy_get_button_up_cnt( int btn ) 
730 {
731         int count;
732
733         if ((!joy_installed)||(!joy_present)) return 0;
734
735         if ( btn >= MAX_BUTTONS ) return 0;
736
737         _disable();
738         count = joystick.buttons[btn].upcount;
739         joystick.buttons[btn].upcount = 0;
740         _enable();
741
742         return count;
743 }
744
745 int joy_get_button_down_cnt( int btn ) 
746 {
747         int count;
748
749         if ((!joy_installed)||(!joy_present)) return 0;
750         if ( btn >= MAX_BUTTONS ) return 0;
751
752         _disable();
753         count = joystick.buttons[btn].downcount;
754         joystick.buttons[btn].downcount = 0;
755         _enable();
756
757         return count;
758 }
759
760         
761 fix joy_get_button_down_time( int btn ) 
762 {
763         fix count;
764
765         if ((!joy_installed)||(!joy_present)) return 0;
766         if ( btn >= MAX_BUTTONS ) return 0;
767
768         _disable();
769         count = joystick.buttons[btn].timedown;
770         joystick.buttons[btn].timedown = 0;
771         _enable();
772
773         return fixmuldiv(count, 65536, 1193180 );
774 }
775
776 void joy_get_btn_up_cnt( int *btn0, int *btn1 ) 
777 {
778         if ((!joy_installed)||(!joy_present)) { *btn0=*btn1=0; return; }
779
780         _disable();
781         *btn0 = joystick.buttons[0].upcount;
782         joystick.buttons[0].upcount = 0;
783         *btn1 = joystick.buttons[1].upcount;
784         joystick.buttons[1].upcount = 0;
785         _enable();
786 }
787
788 void joy_set_btn_values( int btn, int state, fix timedown, int downcount, int upcount )
789 {
790         _disable();
791         joystick.buttons[btn].ignore = 1;
792         joystick.buttons[btn].state = state;
793         joystick.buttons[btn].timedown = fixmuldiv( timedown, 1193180, 65536 );
794         joystick.buttons[btn].downcount = downcount;
795         joystick.buttons[btn].upcount = upcount;
796         _enable();
797 }
798
799 void joy_poll()
800 {
801         if ( joystick.slow_read & JOY_BIOS_READINGS )   
802                 joystick.last_value = joy_read_buttons_bios2();
803 }