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