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