]> icculus.org git repositories - btb/d2x.git/blob - arch/dos/joyc.c
move old per-file change logs into new file ChangeLog-old
[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.6 $
17  * $Author: schaffner $
18  * $Date: 2004-08-28 23:17:45 $
19  * 
20  * Routines for joystick reading.
21  * 
22  */
23
24 #ifdef HAVE_CONFIG_H
25 #include <conf.h>
26 #endif
27
28 #include <stdlib.h>
29 #include <stdio.h>
30 #include <dos.h>
31
32 //#define ARCADE 1
33
34 #include "pstypes.h"
35 #include "mono.h"
36 #include "joy.h"
37 #include "u_dpmi.h"
38 #include "timer.h"
39
40 #include "args.h"
41
42 extern int joy_bogus_reading;
43 int JOY_PORT = 513; //201h;
44 int joy_deadzone = 0;
45
46 int joy_read_stick_asm2( int read_masks, int * event_buffer, int timeout );
47 int joy_read_stick_friendly2( int read_masks, int * event_buffer, int timeout );
48 int joy_read_stick_polled2( int read_masks, int * event_buffer, int timeout );
49 int joy_read_stick_bios2( int read_masks, int * event_buffer, int timeout );
50 int joy_read_buttons_bios2();
51 void joy_read_buttons_bios_end2();
52
53
54 //In key.c
55 // ebx = read mask                                                                           
56 // edi = pointer to buffer                                                                                                                                                                                      
57 // returns number of events                                                                                                                                                                             
58
59 char joy_installed = 0;
60 char joy_present = 0;
61
62 typedef struct Button_info {
63         ubyte           ignore;
64         ubyte           state;
65         ubyte           last_state;
66         int             timedown;
67         ubyte           downcount;
68         ubyte           upcount;
69 } Button_info;
70
71 typedef struct Joy_info {
72         ubyte                   present_mask;
73         ubyte                   slow_read;
74         int                     max_timer;
75         int                     read_count;
76         ubyte                   last_value;
77         Button_info     buttons[MAX_BUTTONS];
78         int                     axis_min[4];
79         int                     axis_center[4];
80         int                     axis_max[4];
81 } Joy_info;
82
83 Joy_info joystick;
84
85 ubyte joy_read_buttons()
86 {
87  return ((~(inp(JOY_PORT) >> 4))&0xf);
88 }
89
90 void joy_get_cal_vals(int *axis_min, int *axis_center, int *axis_max)
91 {
92         int i;
93
94         for (i = 0; i < JOY_NUM_AXES; i++)
95         {
96                 axis_min[i] = joystick.axis_min[i];
97                 axis_center[i] = joystick.axis_center[i];
98                 axis_max[i] = joystick.axis_max[i];
99         }
100 }
101
102 void joy_set_cal_vals(int *axis_min, int *axis_center, int *axis_max)
103 {
104         int i;
105
106         for (i = 0; i < JOY_NUM_AXES; i++)
107         {
108                 joystick.axis_min[i] = axis_min[i];
109                 joystick.axis_center[i] = axis_center[i];
110                 joystick.axis_max[i] = axis_max[i];
111         }
112 }
113
114
115 ubyte joy_get_present_mask()    {
116         return joystick.present_mask;
117 }
118
119 void joy_set_timer_rate(int max_value ) {
120         _disable();
121         joystick.max_timer = max_value;
122         _enable();
123 }
124
125 int joy_get_timer_rate()        {
126         return joystick.max_timer;
127 }
128
129
130 void joy_flush()        {
131         int i;
132
133         if (!joy_installed) return;
134
135         _disable();
136         for (i=0; i<MAX_BUTTONS; i++ )  {
137                 joystick.buttons[i].ignore = 0;
138                 joystick.buttons[i].state = 0;
139                 joystick.buttons[i].timedown = 0;
140                 joystick.buttons[i].downcount = 0;      
141                 joystick.buttons[i].upcount = 0;        
142         }
143         _enable();
144
145 }
146
147
148 void joy_handler(int ticks_this_time)   {
149         ubyte value;
150         int i, state;
151         Button_info * button;
152
153 //      joystick.max_timer = ticks_this_time;
154
155         if ( joystick.slow_read & JOY_BIOS_READINGS )           {
156                 joystick.read_count++;
157                 if ( joystick.read_count > 7 )  {
158                         joystick.read_count = 0;
159                         value = joy_read_buttons_bios2();
160                         joystick.last_value = value;
161                 } else {
162                         value = joystick.last_value;
163                 }               
164         } else {
165                 value = joy_read_buttons(); //JOY_READ_BUTTONS;
166         }
167
168         for (i=0; i<MAX_BUTTONS; i++ )  {
169                 button = &joystick.buttons[i];
170                 if (!button->ignore) {
171                         if ( i < 5 )
172                                 state = (value >> i) & 1;
173                         else if (i==(value+4))  
174                                 state = 1;
175                         else
176                                 state = 0;
177
178                         if ( button->last_state == state )      {
179                                 if (state) button->timedown += ticks_this_time;
180                         } else {
181                                 if (state)      {
182                                         button->downcount += state;
183                                         button->state = 1;
184                                 } else {        
185                                         button->upcount += button->state;
186                                         button->state = 0;
187                                 }
188                                 button->last_state = state;
189                         }
190                 }
191         }
192 }
193
194 void joy_handler_end()  {               // Dummy function to help calculate size of joystick handler function
195 }
196
197
198 ubyte joy_read_raw_buttons()    {
199         if ( joystick.slow_read & JOY_BIOS_READINGS )   
200                 return joy_read_buttons_bios2();
201         else 
202                 return joy_read_buttons(); //JOY_READ_BUTTONS;
203 }
204
205 void joy_set_slow_reading(int flag)
206 {
207         joystick.slow_read |= flag;
208         joy_set_cen();
209 }
210
211 ubyte joystick_read_raw_axis( ubyte mask, int * axis )
212 {
213         ubyte read_masks, org_masks;
214         int t, t1, t2, buffer[4*2+2];
215         int e, i, num_channels, c;
216
217         axis[0] = 0; axis[1] = 0;
218         axis[2] = 0; axis[3] = 0;
219
220         if (!joy_installed) return 0;
221
222         read_masks = 0;
223         org_masks = mask;
224
225         mask &= joystick.present_mask;                  // Don't read non-present channels
226         if ( mask==0 )  {
227                 return 0;               // Don't read if no stick connected.
228         }
229
230         if ( joystick.slow_read & JOY_SLOW_READINGS )   {
231                 for (c=0; c<4; c++ )    {               
232                         if ( mask & (1 << c))   {
233                                 // Time out at  (1/100th of a second)
234
235                                 if ( joystick.slow_read & JOY_POLLED_READINGS )
236                                         num_channels = joy_read_stick_polled2( (1 << c), buffer, 65536 );
237                                 else if ( joystick.slow_read & JOY_BIOS_READINGS )
238                                         num_channels = joy_read_stick_bios2( (1 << c), buffer, 65536 );
239                                 else if ( joystick.slow_read & JOY_FRIENDLY_READINGS )
240                                         num_channels = joy_read_stick_friendly2( (1 << c), buffer, (1193180/100) );
241                                 else
242                                         num_channels = joy_read_stick_asm2( (1 << c), buffer, (1193180/100) );
243         
244                                 if ( num_channels > 0 ) {
245                                         t1 = buffer[0];
246                                         e = buffer[1];
247                                         t2 = buffer[2];
248                                         if ( joystick.slow_read & (JOY_POLLED_READINGS|JOY_BIOS_READINGS) )     {
249                                                 t = t2 - t1;
250                                         } else {                        
251                                                 if ( t1 > t2 )
252                                                         t = t1 - t2;
253                                                 else                            {
254                                                         t = t1 + joystick.max_timer - t2;
255                                                         //mprintf( 0, "%d, %d, %d, %d\n", t1, t2, joystick.max_timer, t );
256                                                 }
257                                         }
258         
259                                         if ( e & 1 ) { axis[0] = t; read_masks |= 1; }
260                                         if ( e & 2 ) { axis[1] = t; read_masks |= 2; }
261                                         if ( e & 4 ) { axis[2] = t; read_masks |= 4; }
262                                         if ( e & 8 ) { axis[3] = t; read_masks |= 8; }
263                                 }
264                         }
265                 }
266         } else {
267                 // Time out at  (1/100th of a second)
268                 if ( joystick.slow_read & JOY_POLLED_READINGS )
269                         num_channels = joy_read_stick_polled2( mask, buffer, 65536 );
270                 else if ( joystick.slow_read & JOY_BIOS_READINGS )
271                         num_channels = joy_read_stick_bios2( mask, buffer, 65536 );
272                 else if ( joystick.slow_read & JOY_FRIENDLY_READINGS )
273                         num_channels = joy_read_stick_friendly2( mask, buffer, (1193180/100) );
274                 else 
275                         num_channels = joy_read_stick_asm2( mask, buffer, (1193180/100) );
276                 //mprintf(( 0, "(%d)\n", num_channels ));
277         
278                 for (i=0; i<num_channels; i++ ) {
279                         t1 = buffer[0];
280                         t2 = buffer[i*2+2];
281                         
282                         if ( joystick.slow_read & (JOY_POLLED_READINGS|JOY_BIOS_READINGS) )     {
283                                 t = t2 - t1;
284                         } else {                        
285                                 if ( t1 > t2 )
286                                         t = t1 - t2;
287                                 else                            {
288                                         t = t1 + joystick.max_timer - t2;
289                                         //mprintf(( 0, "%d, %d, %d, %d\n", t1, t2, joystick.max_timer, t ));
290                                 }
291                         }               
292                         e = buffer[i*2+1];
293         
294                         if ( e & 1 ) { axis[0] = t; read_masks |= 1; }
295                         if ( e & 2 ) { axis[1] = t; read_masks |= 2; }
296                         if ( e & 4 ) { axis[2] = t; read_masks |= 4; }
297                         if ( e & 8 ) { axis[3] = t; read_masks |= 8; }
298                 }
299                 
300         }
301
302         return read_masks;
303 }
304
305 #ifdef __GNUC__
306 #define near
307 #endif
308
309 int joy_init()  
310 {
311         int i;
312         int temp_axis[4];
313
314 //        if(FindArg("-joy209"))
315 //         use_alt_joyport=1;
316         if(FindArg("-joy209"))
317          JOY_PORT = 521;  //209h;
318          
319         joy_flush();
320
321         _disable();
322         for (i=0; i<MAX_BUTTONS; i++ )  
323                 joystick.buttons[i].last_state = 0;
324         _enable();
325
326         if ( !joy_installed )   {
327                 joy_present = 0;
328                 joy_installed = 1;
329                 //joystick.max_timer = 65536;
330                 joystick.slow_read = 0;
331                 joystick.read_count = 0;
332                 joystick.last_value = 0;
333
334                 //--------------- lock everything for the virtal memory ----------------------------------
335                 if (!dpmi_lock_region ((void near *)joy_read_buttons_bios2, (char *)joy_read_buttons_bios_end2 - (char near *)joy_read_buttons_bios2))   {
336                         printf( "Error locking joystick handler (read bios)!\n" );
337                         exit(1);
338                 }
339
340
341
342                 if (!dpmi_lock_region ((void near *)joy_handler, (char *)joy_handler_end - (char near *)joy_handler))   {
343                         printf( "Error locking joystick handler!\n" );
344                         exit(1);
345                 }
346
347                 if (!dpmi_lock_region (&joystick, sizeof(Joy_info)))    {
348                         printf( "Error locking joystick handler's data!\n" );
349                         exit(1);
350                 }
351
352                 timer_set_joyhandler(joy_handler);
353         }
354
355         // Do initial cheapy calibration...
356         joystick.present_mask = JOY_ALL_AXIS;           // Assume they're all present
357         do      {
358                 joystick.present_mask = joystick_read_raw_axis( JOY_ALL_AXIS, temp_axis );
359         } while( joy_bogus_reading );
360
361         if ( joystick.present_mask & 3 )
362                 joy_present = 1;
363         else
364                 joy_present = 0;
365
366         return joy_present;
367 }
368
369 void joy_close()        
370 {
371         if (!joy_installed) return;
372         joy_installed = 0;
373 }
374
375 void joy_set_ul()       
376 {
377         joystick.present_mask = JOY_ALL_AXIS;           // Assume they're all present
378         do      {
379                 joystick.present_mask = joystick_read_raw_axis( JOY_ALL_AXIS, joystick.axis_min );
380         } while( joy_bogus_reading );
381         if ( joystick.present_mask & 3 )
382                 joy_present = 1;
383         else
384                 joy_present = 0;
385 }
386
387 void joy_set_lr()       
388 {
389         joystick.present_mask = JOY_ALL_AXIS;           // Assume they're all present
390         do {
391                 joystick.present_mask = joystick_read_raw_axis( JOY_ALL_AXIS, joystick.axis_max );
392         } while( joy_bogus_reading );
393
394         if ( joystick.present_mask & 3 )
395                 joy_present = 1;
396         else
397                 joy_present = 0;
398 }
399
400 void joy_set_cen() 
401 {
402         joystick.present_mask = JOY_ALL_AXIS;           // Assume they're all present
403         do {
404                 joystick.present_mask = joystick_read_raw_axis( JOY_ALL_AXIS, joystick.axis_center );
405         } while( joy_bogus_reading );
406
407         if ( joystick.present_mask & 3 )
408                 joy_present = 1;
409         else
410                 joy_present = 0;
411 }
412
413 void joy_set_cen_fake(int channel)      
414 {
415
416         int i,n=0;
417         int minx, maxx, cenx;
418         
419         minx=maxx=cenx=0;
420
421         for (i=0; i<4; i++ )    {
422                 if ( (joystick.present_mask & (1<<i)) && (i!=channel) ) {
423                         n++;
424                         minx += joystick.axis_min[i];
425                         maxx += joystick.axis_max[i];
426                         cenx += joystick.axis_center[i];
427                 }
428         }
429         minx /= n;
430         maxx /= n;
431         cenx /= n;
432
433         joystick.axis_min[channel] = minx;
434         joystick.axis_max[channel] = maxx;
435         joystick.axis_center[channel] = cenx;
436 }
437
438 int joy_get_scaled_reading( int raw, int axn )  
439 {
440  int x, d, dz;
441
442  // Make sure it's calibrated properly.
443 //added/changed on 8/14/98 to allow smaller calibrating sticks to work (by Eivind Brendryen)--was <5
444    if ( joystick.axis_center[axn] - joystick.axis_min[axn] < 2 )
445     return 0;
446    if ( joystick.axis_max[axn] - joystick.axis_center[axn] < 2 )
447     return 0;
448 //end change - Victor Rachels  (by Eivind Brendryen)
449
450   raw -= joystick.axis_center[axn];
451
452    if ( raw < 0 )
453     d = joystick.axis_center[axn]-joystick.axis_min[axn];
454    else
455     d = joystick.axis_max[axn]-joystick.axis_center[axn];
456
457
458    if ( d )
459     x = (raw << 7) / d;
460    else
461     x = 0;
462
463
464    if ( x < -128 )
465     x = -128;
466    if ( x > 127 )
467     x = 127;
468
469 //added on 4/13/99 by Victor Rachels to add deadzone control
470   dz =  (joy_deadzone) * 6;
471    if ((x > (-1*dz)) && (x < dz))
472     x = 0;
473 //end this section addition -VR
474
475   return x;
476 }
477
478 int last_reading[4] = { 0, 0, 0, 0 };
479
480 void joy_get_pos( int *x, int *y )      
481 {
482         ubyte flags;
483         int axis[4];
484
485         if ((!joy_installed)||(!joy_present)) { *x=*y=0; return; }
486
487         flags=joystick_read_raw_axis( JOY_1_X_AXIS+JOY_1_Y_AXIS, axis );
488
489         if ( joy_bogus_reading )        {
490                 axis[0] = last_reading[0];
491                 axis[1] = last_reading[1];
492                 flags = JOY_1_X_AXIS+JOY_1_Y_AXIS;
493         } else {
494                 last_reading[0] = axis[0];
495                 last_reading[1] = axis[1];
496         }
497
498         if ( flags & JOY_1_X_AXIS )
499                 *x = joy_get_scaled_reading( axis[0], 0 );
500         else
501                 *x = 0;
502
503         if ( flags & JOY_1_Y_AXIS )
504                 *y = joy_get_scaled_reading( axis[1], 1 );
505         else
506                 *y = 0;
507 }
508
509 ubyte joy_read_stick( ubyte masks, int *axis )  
510 {
511         ubyte flags;
512         int raw_axis[4];
513
514         if ((!joy_installed)||(!joy_present)) { 
515                 axis[0] = 0; axis[1] = 0;
516                 axis[2] = 0; axis[3] = 0;
517                 return 0;  
518         }
519
520         flags=joystick_read_raw_axis( masks, raw_axis );
521
522         if ( joy_bogus_reading )        {
523                 axis[0] = last_reading[0];
524                 axis[1] = last_reading[1];
525                 axis[2] = last_reading[2];
526                 axis[3] = last_reading[3];
527                 flags = masks;
528         } else {
529                 last_reading[0] = axis[0];
530                 last_reading[1] = axis[1];
531                 last_reading[2] = axis[2];
532                 last_reading[3] = axis[3];
533         }
534
535         if ( flags & JOY_1_X_AXIS )
536                 axis[0] = joy_get_scaled_reading( raw_axis[0], 0 );
537         else
538                 axis[0] = 0;
539
540         if ( flags & JOY_1_Y_AXIS )
541                 axis[1] = joy_get_scaled_reading( raw_axis[1], 1 );
542         else
543                 axis[1] = 0;
544
545         if ( flags & JOY_2_X_AXIS )
546                 axis[2] = joy_get_scaled_reading( raw_axis[2], 2 );
547         else
548                 axis[2] = 0;
549
550         if ( flags & JOY_2_Y_AXIS )
551                 axis[3] = joy_get_scaled_reading( raw_axis[3], 3 );
552         else
553                 axis[3] = 0;
554
555         return flags;
556 }
557
558
559 int joy_get_btns()      
560 {
561         if ((!joy_installed)||(!joy_present)) return 0;
562
563         return joy_read_raw_buttons();
564 }
565
566 void joy_get_btn_down_cnt( int *btn0, int *btn1 ) 
567 {
568         if ((!joy_installed)||(!joy_present)) { *btn0=*btn1=0; return; }
569
570         _disable();
571         *btn0 = joystick.buttons[0].downcount;
572         joystick.buttons[0].downcount = 0;
573         *btn1 = joystick.buttons[1].downcount;
574         joystick.buttons[1].downcount = 0;
575         _enable();
576 }
577
578 int joy_get_button_state( int btn )     
579 {
580         int count;
581
582         if ((!joy_installed)||(!joy_present)) return 0;
583
584         if ( btn >= MAX_BUTTONS ) return 0;
585
586         _disable();
587         count = joystick.buttons[btn].state;
588         _enable();
589         
590         return  count;
591 }
592
593 int joy_get_button_up_cnt( int btn ) 
594 {
595         int count;
596
597         if ((!joy_installed)||(!joy_present)) return 0;
598
599         if ( btn >= MAX_BUTTONS ) return 0;
600
601         _disable();
602         count = joystick.buttons[btn].upcount;
603         joystick.buttons[btn].upcount = 0;
604         _enable();
605
606         return count;
607 }
608
609 int joy_get_button_down_cnt( int btn ) 
610 {
611         int count;
612
613         if ((!joy_installed)||(!joy_present)) return 0;
614         if ( btn >= MAX_BUTTONS ) return 0;
615
616         _disable();
617         count = joystick.buttons[btn].downcount;
618         joystick.buttons[btn].downcount = 0;
619         _enable();
620
621         return count;
622 }
623
624         
625 fix joy_get_button_down_time( int btn ) 
626 {
627         fix count;
628
629         if ((!joy_installed)||(!joy_present)) return 0;
630         if ( btn >= MAX_BUTTONS ) return 0;
631
632         _disable();
633         count = joystick.buttons[btn].timedown;
634         joystick.buttons[btn].timedown = 0;
635         _enable();
636
637         return fixmuldiv(count, 65536, 1193180 );
638 }
639
640 void joy_get_btn_up_cnt( int *btn0, int *btn1 ) 
641 {
642         if ((!joy_installed)||(!joy_present)) { *btn0=*btn1=0; return; }
643
644         _disable();
645         *btn0 = joystick.buttons[0].upcount;
646         joystick.buttons[0].upcount = 0;
647         *btn1 = joystick.buttons[1].upcount;
648         joystick.buttons[1].upcount = 0;
649         _enable();
650 }
651
652 void joy_set_btn_values( int btn, int state, fix timedown, int downcount, int upcount )
653 {
654         _disable();
655         joystick.buttons[btn].ignore = 1;
656         joystick.buttons[btn].state = state;
657         joystick.buttons[btn].timedown = fixmuldiv( timedown, 1193180, 65536 );
658         joystick.buttons[btn].downcount = downcount;
659         joystick.buttons[btn].upcount = upcount;
660         _enable();
661 }
662
663 void joy_poll()
664 {
665         if ( joystick.slow_read & JOY_BIOS_READINGS )   
666                 joystick.last_value = joy_read_buttons_bios2();
667 }