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.
15 * $Source: /cvs/cvsroot/d2x/arch/dos/joyc.c,v $
18 * $Date: 2004-05-22 01:40:12 $
20 * Routines for joystick reading.
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.
26 * Revision 1.3 2001/01/29 14:03:56 bradleyb
27 * Fixed build, minor fixes
29 * Revision 1.2 2001/01/24 04:29:45 bradleyb
30 * changed args_find to FindArg
32 * Revision 1.1.1.2 2001/01/19 03:33:52 bradleyb
33 * Import of d2x-0.0.9-pre1
35 * Revision 1.1.1.1 1999/06/14 21:58:26 donut
36 * Import of d1x 1.37 source.
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.
42 * Revision 1.36 1995/03/30 11:03:40 john
43 * Made -JoyBios read buttons using BIOS.
45 * Revision 1.35 1995/02/14 11:39:25 john
46 * Added polled/bios joystick readers..
48 * Revision 1.34 1995/02/10 17:06:12 john
49 * Fixed bug with plugging in a joystick not getting detected.
51 * Revision 1.33 1995/01/27 16:39:42 john
52 * Made so that if no joystick detected, it wont't
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.
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.
64 * Revision 1.30 1994/12/28 15:31:53 john
65 * Added code to read joystick axis not all at one time.
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.
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.
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..
79 * Revision 1.26 1994/11/22 11:08:07 john
80 * Commented out the ARCADE joystick.
82 * Revision 1.25 1994/11/14 19:40:26 john
83 * Fixed bug with no joystick being detected.
85 * Revision 1.24 1994/11/14 19:36:40 john
86 * Took out initial cheapy calibration.
88 * Revision 1.23 1994/11/14 19:13:27 john
89 * Took out the calibration in joy_init
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.
95 * Revision 1.21 1994/10/13 11:36:23 john
96 * Made joy_down_time be kept track of in fixed seconds,
99 * Revision 1.20 1994/10/12 16:58:50 john
100 * Fixed bug w/ previous comment.
102 * Revision 1.19 1994/10/12 16:57:44 john
103 * Added function to set a joystick button's state.
105 * Revision 1.18 1994/10/11 10:20:13 john
106 * Fixed Flightstick Pro/
109 * Revision 1.17 1994/09/29 18:29:20 john
110 * *** empty log message ***
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
116 * Revision 1.15 1994/09/22 16:09:23 john
117 * Fixed some virtual memory lockdown problems with timer and
120 * Revision 1.14 1994/09/16 11:44:42 john
121 * Fixed bug with slow joystick.
123 * Revision 1.13 1994/09/16 11:36:15 john
124 * Fixed bug with reading non-present channels.
126 * Revision 1.12 1994/09/15 20:52:48 john
128 * Added support for the Arcade style joystick.
130 * Revision 1.11 1994/09/13 20:04:49 john
131 * Fixed bug with joystick button down_time.
133 * Revision 1.10 1994/09/10 13:48:07 john
134 * Made all 20 buttons read.
136 * Revision 1.9 1994/08/31 09:55:02 john
137 * *** empty log message ***
139 * Revision 1.8 1994/08/29 21:02:14 john
140 * Added joy_set_cal_values...
142 * Revision 1.7 1994/08/29 20:52:17 john
143 * Added better cyberman support; also, joystick calibration
144 * value return funcctiionn,
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.
150 * Revision 1.5 1994/07/14 22:12:23 john
151 * Used intrinsic forms of outp to fix vmm error.
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.
158 * Revision 1.3 1994/07/01 10:55:55 john
159 * Fixed some bugs... added support for 4 axis.
161 * Revision 1.2 1994/06/30 20:36:55 john
162 * Revamped joystick code.
164 * Revision 1.1 1994/06/30 15:42:15 john
188 extern int joy_bogus_reading;
189 int JOY_PORT = 513; //201h;
190 int joy_deadzone = 0;
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();
202 // edi = pointer to buffer
203 // returns number of events
205 char joy_installed = 0;
206 char joy_present = 0;
208 typedef struct Button_info {
217 typedef struct Joy_info {
223 Button_info buttons[MAX_BUTTONS];
231 ubyte joy_read_buttons()
233 return ((~(inp(JOY_PORT) >> 4))&0xf);
236 void joy_get_cal_vals(int *axis_min, int *axis_center, int *axis_max)
240 for (i = 0; i < JOY_NUM_AXES; i++)
242 axis_min[i] = joystick.axis_min[i];
243 axis_center[i] = joystick.axis_center[i];
244 axis_max[i] = joystick.axis_max[i];
248 void joy_set_cal_vals(int *axis_min, int *axis_center, int *axis_max)
252 for (i = 0; i < JOY_NUM_AXES; i++)
254 joystick.axis_min[i] = axis_min[i];
255 joystick.axis_center[i] = axis_center[i];
256 joystick.axis_max[i] = axis_max[i];
261 ubyte joy_get_present_mask() {
262 return joystick.present_mask;
265 void joy_set_timer_rate(int max_value ) {
267 joystick.max_timer = max_value;
271 int joy_get_timer_rate() {
272 return joystick.max_timer;
279 if (!joy_installed) return;
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;
294 void joy_handler(int ticks_this_time) {
297 Button_info * button;
299 // joystick.max_timer = ticks_this_time;
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;
308 value = joystick.last_value;
311 value = joy_read_buttons(); //JOY_READ_BUTTONS;
314 for (i=0; i<MAX_BUTTONS; i++ ) {
315 button = &joystick.buttons[i];
316 if (!button->ignore) {
318 state = (value >> i) & 1;
319 else if (i==(value+4))
324 if ( button->last_state == state ) {
325 if (state) button->timedown += ticks_this_time;
328 button->downcount += state;
331 button->upcount += button->state;
334 button->last_state = state;
340 void joy_handler_end() { // Dummy function to help calculate size of joystick handler function
344 ubyte joy_read_raw_buttons() {
345 if ( joystick.slow_read & JOY_BIOS_READINGS )
346 return joy_read_buttons_bios2();
348 return joy_read_buttons(); //JOY_READ_BUTTONS;
351 void joy_set_slow_reading(int flag)
353 joystick.slow_read |= flag;
357 ubyte joystick_read_raw_axis( ubyte mask, int * axis )
359 ubyte read_masks, org_masks;
360 int t, t1, t2, buffer[4*2+2];
361 int e, i, num_channels, c;
363 axis[0] = 0; axis[1] = 0;
364 axis[2] = 0; axis[3] = 0;
366 if (!joy_installed) return 0;
371 mask &= joystick.present_mask; // Don't read non-present channels
373 return 0; // Don't read if no stick connected.
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)
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) );
388 num_channels = joy_read_stick_asm2( (1 << c), buffer, (1193180/100) );
390 if ( num_channels > 0 ) {
394 if ( joystick.slow_read & (JOY_POLLED_READINGS|JOY_BIOS_READINGS) ) {
400 t = t1 + joystick.max_timer - t2;
401 //mprintf( 0, "%d, %d, %d, %d\n", t1, t2, joystick.max_timer, t );
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; }
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) );
421 num_channels = joy_read_stick_asm2( mask, buffer, (1193180/100) );
422 //mprintf(( 0, "(%d)\n", num_channels ));
424 for (i=0; i<num_channels; i++ ) {
428 if ( joystick.slow_read & (JOY_POLLED_READINGS|JOY_BIOS_READINGS) ) {
434 t = t1 + joystick.max_timer - t2;
435 //mprintf(( 0, "%d, %d, %d, %d\n", t1, t2, joystick.max_timer, t ));
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; }
460 // if(FindArg("-joy209"))
461 // use_alt_joyport=1;
462 if(FindArg("-joy209"))
463 JOY_PORT = 521; //209h;
468 for (i=0; i<MAX_BUTTONS; i++ )
469 joystick.buttons[i].last_state = 0;
472 if ( !joy_installed ) {
475 //joystick.max_timer = 65536;
476 joystick.slow_read = 0;
477 joystick.read_count = 0;
478 joystick.last_value = 0;
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" );
488 if (!dpmi_lock_region ((void near *)joy_handler, (char *)joy_handler_end - (char near *)joy_handler)) {
489 printf( "Error locking joystick handler!\n" );
493 if (!dpmi_lock_region (&joystick, sizeof(Joy_info))) {
494 printf( "Error locking joystick handler's data!\n" );
498 timer_set_joyhandler(joy_handler);
501 // Do initial cheapy calibration...
502 joystick.present_mask = JOY_ALL_AXIS; // Assume they're all present
504 joystick.present_mask = joystick_read_raw_axis( JOY_ALL_AXIS, temp_axis );
505 } while( joy_bogus_reading );
507 if ( joystick.present_mask & 3 )
517 if (!joy_installed) return;
523 joystick.present_mask = JOY_ALL_AXIS; // Assume they're all present
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 )
535 joystick.present_mask = JOY_ALL_AXIS; // Assume they're all present
537 joystick.present_mask = joystick_read_raw_axis( JOY_ALL_AXIS, joystick.axis_max );
538 } while( joy_bogus_reading );
540 if ( joystick.present_mask & 3 )
548 joystick.present_mask = JOY_ALL_AXIS; // Assume they're all present
550 joystick.present_mask = joystick_read_raw_axis( JOY_ALL_AXIS, joystick.axis_center );
551 } while( joy_bogus_reading );
553 if ( joystick.present_mask & 3 )
559 void joy_set_cen_fake(int channel)
563 int minx, maxx, cenx;
567 for (i=0; i<4; i++ ) {
568 if ( (joystick.present_mask & (1<<i)) && (i!=channel) ) {
570 minx += joystick.axis_min[i];
571 maxx += joystick.axis_max[i];
572 cenx += joystick.axis_center[i];
579 joystick.axis_min[channel] = minx;
580 joystick.axis_max[channel] = maxx;
581 joystick.axis_center[channel] = cenx;
584 int joy_get_scaled_reading( int raw, int axn )
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 )
592 if ( joystick.axis_max[axn] - joystick.axis_center[axn] < 2 )
594 //end change - Victor Rachels (by Eivind Brendryen)
596 raw -= joystick.axis_center[axn];
599 d = joystick.axis_center[axn]-joystick.axis_min[axn];
601 d = joystick.axis_max[axn]-joystick.axis_center[axn];
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))
619 //end this section addition -VR
624 int last_reading[4] = { 0, 0, 0, 0 };
626 void joy_get_pos( int *x, int *y )
631 if ((!joy_installed)||(!joy_present)) { *x=*y=0; return; }
633 flags=joystick_read_raw_axis( JOY_1_X_AXIS+JOY_1_Y_AXIS, axis );
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;
640 last_reading[0] = axis[0];
641 last_reading[1] = axis[1];
644 if ( flags & JOY_1_X_AXIS )
645 *x = joy_get_scaled_reading( axis[0], 0 );
649 if ( flags & JOY_1_Y_AXIS )
650 *y = joy_get_scaled_reading( axis[1], 1 );
655 ubyte joy_read_stick( ubyte masks, int *axis )
660 if ((!joy_installed)||(!joy_present)) {
661 axis[0] = 0; axis[1] = 0;
662 axis[2] = 0; axis[3] = 0;
666 flags=joystick_read_raw_axis( masks, raw_axis );
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];
675 last_reading[0] = axis[0];
676 last_reading[1] = axis[1];
677 last_reading[2] = axis[2];
678 last_reading[3] = axis[3];
681 if ( flags & JOY_1_X_AXIS )
682 axis[0] = joy_get_scaled_reading( raw_axis[0], 0 );
686 if ( flags & JOY_1_Y_AXIS )
687 axis[1] = joy_get_scaled_reading( raw_axis[1], 1 );
691 if ( flags & JOY_2_X_AXIS )
692 axis[2] = joy_get_scaled_reading( raw_axis[2], 2 );
696 if ( flags & JOY_2_Y_AXIS )
697 axis[3] = joy_get_scaled_reading( raw_axis[3], 3 );
707 if ((!joy_installed)||(!joy_present)) return 0;
709 return joy_read_raw_buttons();
712 void joy_get_btn_down_cnt( int *btn0, int *btn1 )
714 if ((!joy_installed)||(!joy_present)) { *btn0=*btn1=0; return; }
717 *btn0 = joystick.buttons[0].downcount;
718 joystick.buttons[0].downcount = 0;
719 *btn1 = joystick.buttons[1].downcount;
720 joystick.buttons[1].downcount = 0;
724 int joy_get_button_state( int btn )
728 if ((!joy_installed)||(!joy_present)) return 0;
730 if ( btn >= MAX_BUTTONS ) return 0;
733 count = joystick.buttons[btn].state;
739 int joy_get_button_up_cnt( int btn )
743 if ((!joy_installed)||(!joy_present)) return 0;
745 if ( btn >= MAX_BUTTONS ) return 0;
748 count = joystick.buttons[btn].upcount;
749 joystick.buttons[btn].upcount = 0;
755 int joy_get_button_down_cnt( int btn )
759 if ((!joy_installed)||(!joy_present)) return 0;
760 if ( btn >= MAX_BUTTONS ) return 0;
763 count = joystick.buttons[btn].downcount;
764 joystick.buttons[btn].downcount = 0;
771 fix joy_get_button_down_time( int btn )
775 if ((!joy_installed)||(!joy_present)) return 0;
776 if ( btn >= MAX_BUTTONS ) return 0;
779 count = joystick.buttons[btn].timedown;
780 joystick.buttons[btn].timedown = 0;
783 return fixmuldiv(count, 65536, 1193180 );
786 void joy_get_btn_up_cnt( int *btn0, int *btn1 )
788 if ((!joy_installed)||(!joy_present)) { *btn0=*btn1=0; return; }
791 *btn0 = joystick.buttons[0].upcount;
792 joystick.buttons[0].upcount = 0;
793 *btn1 = joystick.buttons[1].upcount;
794 joystick.buttons[1].upcount = 0;
798 void joy_set_btn_values( int btn, int state, fix timedown, int downcount, int upcount )
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;
811 if ( joystick.slow_read & JOY_BIOS_READINGS )
812 joystick.last_value = joy_read_buttons_bios2();