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