1 //JOYC.C for D1_3Dfx and D1OpenGL
2 //D1_3Dfx is a Win32 executable using Glide and DirectX 3
3 //D1OpenGL is a Win32 executable using OpenGL and DirectX 3
4 //This joystick code should run on DirectInput 2 and higher
5 //We are not using DirectX 5 for now, since we want to stay compatible to the HH-loved Windows NT :).
6 //So ForceFeedback is not supported
9 // 1) Windows DirectX supports up to 7 axes, D1/DOS only 4, so we needed to increase the number to 7 at several points
10 // Also JOY_ALL_AXIS must be (1+2+4+8+16+32+64) in JOY.H file
11 // 2) Windows DirectX supports up to 32 buttons. So far we however only support 4. Adding support for more should be however easily possible.
12 // 3) _enable and _disable are not needed
13 // 4) joy_bogus_reading is not needed, so all calls are just removed
14 // 5) The joystick query goes over the DirectInputs function
15 // MMRESULT joyGetPosEx(UINT uJoyID, LPJOYINFOEX pji);
16 // All functions reading over BIOS, including the ASM code are removed
21 THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX
22 SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO
23 END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A
24 ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS
25 IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS
26 SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE
27 FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE
28 CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS
29 AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE.
30 COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED.
34 Modifications by Heiko Herrmann
35 Later modified by Owen Evans to work with D1X (3/7/99)
39 #define _WIN32_OS //HH
41 #include <windows.h> //HH
42 #include <mmsystem.h> //HH
50 #define my_hwnd g_hWnd // D1X compatibility
53 char joy_installed = 0;
56 typedef struct Button_info {
65 typedef struct Joy_info {
72 Button_info buttons[MAX_BUTTONS];
73 int axis_min[JOY_NUM_AXES]; //changed
74 int axis_center[JOY_NUM_AXES]; //changed --orulz
75 int axis_max[JOY_NUM_AXES]; //changed
83 void joy_get_cal_vals(int *axis_min, int *axis_center, int *axis_max)
87 for (i=0; i<JOY_NUM_AXES; i++) { //changed - orulz
88 axis_min[i] = joystick.axis_min[i];
89 axis_center[i] = joystick.axis_center[i];
90 axis_max[i] = joystick.axis_max[i];
94 void joy_set_cal_vals(int *axis_min, int *axis_center, int *axis_max)
98 for (i=0; i<JOY_NUM_AXES; i++) { //changed - orulz
99 joystick.axis_min[i] = axis_min[i];
100 joystick.axis_center[i] = axis_center[i];
101 joystick.axis_max[i] = axis_max[i];
105 ubyte joy_get_present_mask() {
106 return joystick.present_mask;
109 void joy_set_timer_rate(int max_value ) {
110 joystick.max_timer = max_value;
113 int joy_get_timer_rate() {
114 return joystick.max_timer;
120 if (!joy_installed) return;
122 for (i=0; i<MAX_BUTTONS; i++ ) {
123 joystick.buttons[i].ignore = 0;
124 joystick.buttons[i].state = 0;
125 joystick.buttons[i].timedown = 0;
126 joystick.buttons[i].downcount = 0;
127 joystick.buttons[i].upcount = 0;
133 //Begin section modified 3/7/99 - Owen Evans
135 ubyte joy_read_raw_buttons()
143 memset(&joy, 0, sizeof(joy));
144 joy.dwSize = sizeof(joy);
145 joy.dwFlags = JOY_RETURNBUTTONS | JOY_RETURNPOVCTS | JOY_USEDEADZONE;
147 if (joyGetPosEx(joystick.joyid, &joy)!=JOYERR_NOERROR)
150 for (i = 0; i < MAX_BUTTONS; i++) {
151 joystick.buttons[i].last_state = joystick.buttons[i].state;
152 joystick.buttons[i].state = (joy.dwButtons >> i) & 0x1;
153 if (!joystick.buttons[i].last_state && joystick.buttons[i].state) {
154 joystick.buttons[i].timedown = timer_get_fixed_seconds();
155 joystick.buttons[i].downcount++;
161 if (joy.dwPOV != JOY_POVCENTERED)
163 joystick.buttons[19].state = (joy.dwPOV < JOY_POVRIGHT || joy.dwPOV > JOY_POVLEFT);
164 joystick.buttons[15].state = (joy.dwPOV < JOY_POVBACKWARD && joy.dwPOV > JOY_POVFORWARD);
165 joystick.buttons[11].state = (joy.dwPOV < JOY_POVLEFT && joy.dwPOV > JOY_POVRIGHT);
166 joystick.buttons[7].state = (joy.dwPOV > JOY_POVBACKWARD);
169 return (ubyte)joy.dwButtons;
172 //end changed section - OE
175 ubyte joystick_read_raw_axis( ubyte mask, int * axis )
178 ubyte read_masks = 0;
180 axis[0] = 0; axis[1] = 0; //orulz: 1=x 2=y 3=r 4=z 5=u 6=v
181 axis[2] = 0; axis[3] = 0;
182 axis[4] = 0; axis[5] = 0; //HH: Added support for axes R and U
184 if (!joy_installed) {
188 memset(&joy, 0, sizeof(joy));
189 joy.dwSize = sizeof(joy);
190 joy.dwFlags = JOY_RETURNALL | JOY_USEDEADZONE;
191 if (joyGetPosEx(joystick.joyid, &joy)!=JOYERR_NOERROR) {
195 mask &= joystick.present_mask; // Don't read non-present channels
197 return 0; // Don't read if no stick connected.
200 if (mask & JOY_1_X_AXIS) { axis[0] = joy.dwXpos; read_masks |= JOY_1_X_AXIS; }
201 if (mask & JOY_1_Y_AXIS) { axis[1] = joy.dwYpos; read_masks |= JOY_1_Y_AXIS; }
203 // if (mask & JOY_1_Z_AXIS) { axis[2] = joy.dwZpos; read_masks |= JOY_1_Z_AXIS; }
204 // if (mask & JOY_1_POV) { axis[3] = joy.dwPOV; read_masks |= JOY_1_POV; }
205 // if (mask & JOY_1_R_AXIS) { axis[4] = joy.dwRpos; read_masks |= JOY_1_R_AXIS; }
206 // if (mask & JOY_1_U_AXIS) { axis[5] = joy.dwUpos; read_masks |= JOY_1_U_AXIS; }
207 // if (mask & JOY_1_V_AXIS) { axis[6] = joy.dwVpos; read_masks |= JOY_1_V_AXIS; }
208 if (mask & JOY_1_R_AXIS) { axis[2] = joy.dwRpos; read_masks |= JOY_1_R_AXIS; }
209 if (mask & JOY_1_Z_AXIS) { axis[3] = joy.dwZpos; read_masks |= JOY_1_Z_AXIS; }
210 if (mask & JOY_1_U_AXIS) { axis[4] = joy.dwZpos; read_masks |= JOY_1_U_AXIS; }
211 if (mask & JOY_1_V_AXIS) { axis[5] = joy.dwUpos; read_masks |= JOY_1_V_AXIS; }
216 int hh_average(int val1, int val2)
218 return abs(val1-val2)/2;
221 int joy_init(int joyid) //HH: added joyid parameter
224 int temp_axis[JOY_NUM_AXES]; //changed - orulz
227 atexit(joy_close); //HH: we are a bit lazy :). Errors are ignored, so we are even double-lazy :)
230 memset(&joystick, 0, sizeof(joystick));
232 for (i=0; i<MAX_BUTTONS; i++)
233 joystick.buttons[i].last_state = 0;
235 if ( !joy_installed ) {
238 joystick.max_timer = 65536;
239 joystick.read_count = 0;
240 joystick.last_value = 0;
244 joystick.present_mask = JOY_ALL_AXIS; // Assume they're all present
245 joystick.present_mask = joystick_read_raw_axis( JOY_ALL_AXIS, temp_axis );
247 if ( joystick.present_mask & 3 )
253 //HH: Main Win32 joystick initialization, incl. reading cal. stuff
255 if (joyGetDevCaps(joyid, &pjc, sizeof(pjc))!=JOYERR_NOERROR) {
259 if (joySetThreshold(joyid, pjc.wXmax/256)!=JOYERR_NOERROR) {
263 joystick.max_timer = pjc.wPeriodMax;
264 joystick.axis_min[0] = pjc.wXmin;
265 joystick.axis_min[1] = pjc.wYmin;
267 // joystick.axis_min[2] = pjc.wZmin;
268 // //HH: joystick.axis_min[3] = pov-stuff
269 // joystick.axis_min[4] = pjc.wRmin;
270 // joystick.axis_min[5] = pjc.wUmin;
271 // joystick.axis_min[6] = pjc.wVmin;
272 joystick.axis_min[2] = pjc.wRmin;
273 joystick.axis_min[3] = pjc.wZmin;
274 joystick.axis_min[4] = pjc.wUmin;
275 joystick.axis_min[5] = pjc.wVmin;
277 joystick.axis_max[0] = pjc.wXmax;
278 joystick.axis_max[1] = pjc.wYmax;
280 // joystick.axis_max[2] = pjc.wZmax;
281 // //HH: joystick.axis_max[3] = pov-stuff
282 // joystick.axis_max[4] = pjc.wRmax;
283 // joystick.axis_max[5] = pjc.wUmax;
284 // joystick.axis_max[6] = pjc.wVmax;
285 joystick.axis_max[2] = pjc.wRmax;
286 joystick.axis_max[3] = pjc.wZmax;
287 joystick.axis_max[4] = pjc.wUmax;
288 joystick.axis_max[5] = pjc.wVmax;
290 joystick.axis_center[0] = hh_average(pjc.wXmax,pjc.wXmin);
291 joystick.axis_center[1] = hh_average(pjc.wYmax,pjc.wYmin);
293 // joystick.axis_center[2] = hh_average(pjc.wZmax,pjc.wZmin);
294 // joystick.axis_center[3] = JOY_POVCENTERED;
295 // joystick.axis_center[4] = hh_average(pjc.wRmax,pjc.wRmin);
296 // joystick.axis_center[5] = hh_average(pjc.wUmax,pjc.wUmin);
297 // joystick.axis_center[6] = hh_average(pjc.wVmax,pjc.wVmin);
298 joystick.axis_center[2] = hh_average(pjc.wRmax,pjc.wRmin);
299 joystick.axis_center[3] = hh_average(pjc.wZmax,pjc.wZmin);
300 joystick.axis_center[4] = hh_average(pjc.wUmax,pjc.wUmin);
301 joystick.axis_center[5] = hh_average(pjc.wVmax,pjc.wVmin);
303 joystick.present_mask = JOY_1_X_AXIS | JOY_1_Y_AXIS;
304 if (pjc.wCaps & JOYCAPS_HASZ) joystick.present_mask |= JOY_1_Z_AXIS;
305 // if (pjc.wCaps & JOYCAPS_HASPOV) joystick.present_mask |= JOY_1_POV;
306 if (pjc.wCaps & JOYCAPS_HASR) joystick.present_mask |= JOY_1_R_AXIS;
307 if (pjc.wCaps & JOYCAPS_HASU) joystick.present_mask |= JOY_1_U_AXIS;
308 if (pjc.wCaps & JOYCAPS_HASV) joystick.present_mask |= JOY_1_V_AXIS;
316 if (!joy_installed) return;
323 joystick.present_mask = JOY_ALL_AXIS; // Assume they're all present
324 joystick.present_mask = joystick_read_raw_axis( JOY_ALL_AXIS, joystick.axis_min );
326 if ( joystick.present_mask & 3 )
334 joystick.present_mask = JOY_ALL_AXIS; // Assume they're all present
335 joystick.present_mask = joystick_read_raw_axis( JOY_ALL_AXIS, joystick.axis_max );
337 if ( joystick.present_mask & 3 )
345 joystick.present_mask = JOY_ALL_AXIS; // Assume they're all present
346 joystick.present_mask = joystick_read_raw_axis( JOY_ALL_AXIS, joystick.axis_center );
348 if ( joystick.present_mask & 3 )
354 void joy_set_cen_fake(int channel)
358 int joy_get_scaled_reading( int raw, int axn )
362 // Make sure it's calibrated properly.
363 if ( joystick.axis_center[axn] - joystick.axis_min[axn] < 128 )
364 return 0; //HH: had to increase to 128
365 if ( joystick.axis_max[axn] - joystick.axis_center[axn] < 128 )
366 return 0; //HH: had to increase to 128
368 raw -= joystick.axis_center[axn];
371 d = joystick.axis_center[axn]-joystick.axis_min[axn];
373 d = joystick.axis_max[axn]-joystick.axis_center[axn];
382 if ( x < -128 ) x = -128;
383 if ( x > 127 ) x = 127;
385 //added on 4/13/99 by Victor Rachels to add deadzone control
386 d = (joy_deadzone) * 6;
387 if ((x > (-1*d)) && (x < d))
389 //end this section addition -VR
394 void joy_get_pos( int *x, int *y )
397 int axis[JOY_NUM_AXES];
399 if ((!joy_installed)||(!joy_present)) { *x=*y=0; return; }
401 flags=joystick_read_raw_axis( JOY_1_X_AXIS+JOY_1_Y_AXIS, axis );
403 if ( flags & JOY_1_X_AXIS )
404 *x = joy_get_scaled_reading( axis[0], 0 );
408 if ( flags & JOY_1_Y_AXIS )
409 *y = joy_get_scaled_reading( axis[1], 1 );
414 ubyte joy_read_stick( ubyte masks, int *axis )
417 int raw_axis[JOY_NUM_AXES];
419 if ((!joy_installed)||(!joy_present)) {
420 axis[0] = 0; axis[1] = 0;
421 axis[2] = 0; axis[3] = 0;
422 axis[4] = 0; axis[5] = 0;
426 flags=joystick_read_raw_axis( masks, raw_axis );
428 if ( flags & JOY_1_X_AXIS )
429 axis[0] = joy_get_scaled_reading( raw_axis[0], 0 );
433 if ( flags & JOY_1_Y_AXIS )
434 axis[1] = joy_get_scaled_reading( raw_axis[1], 1 );
438 if ( flags & JOY_1_R_AXIS )
439 axis[2] = joy_get_scaled_reading( raw_axis[2], 2 );
443 if ( flags & JOY_1_Z_AXIS )
444 axis[3] = joy_get_scaled_reading( raw_axis[3], 3 );
448 if ( flags & JOY_1_U_AXIS )
449 axis[4] = joy_get_scaled_reading( raw_axis[4], 4);
453 if ( flags & JOY_1_V_AXIS )
454 axis[5] = joy_get_scaled_reading( raw_axis[5], 5 );
464 if ((!joy_installed)||(!joy_present)) return 0;
466 return joy_read_raw_buttons();
470 //Begin section modified 3/7/99 - Owen Evans
472 void joy_get_btn_down_cnt( int *btn0, int *btn1 )
474 if ((!joy_installed)||(!joy_present)) { *btn0=*btn1=0; return; }
478 *btn0 = joystick.buttons[0].downcount;
479 joystick.buttons[0].downcount = 0;
480 *btn1 = joystick.buttons[1].downcount;
481 joystick.buttons[1].downcount = 0;
484 int joy_get_button_state( int btn )
486 if ((!joy_installed)||(!joy_present)) return 0;
487 if ( btn >= MAX_BUTTONS ) return 0;
491 return joystick.buttons[btn].state;
494 int joy_get_button_up_cnt( int btn )
498 if ((!joy_installed)||(!joy_present)) return 0;
500 if ( btn >= MAX_BUTTONS ) return 0;
502 count = joystick.buttons[btn].upcount;
503 joystick.buttons[btn].upcount = 0;
508 int joy_get_button_down_cnt( int btn )
512 if ((!joy_installed)||(!joy_present)) return 0;
513 if ( btn >= MAX_BUTTONS ) return 0;
517 count = joystick.buttons[btn].downcount;
518 joystick.buttons[btn].downcount = 0;
523 fix joy_get_button_down_time( int btn )
527 if ((!joy_installed)||(!joy_present)) return 0;
528 if ( btn >= MAX_BUTTONS ) return 0;
532 if (joystick.buttons[btn].state) {
533 count = timer_get_fixed_seconds() - joystick.buttons[btn].timedown;
534 joystick.buttons[btn].timedown = 0;
540 //end changed section - OE
543 void joy_get_btn_up_cnt( int *btn0, int *btn1 )
545 if ((!joy_installed)||(!joy_present)) { *btn0=*btn1=0; return; }
547 *btn0 = joystick.buttons[0].upcount;
548 joystick.buttons[0].upcount = 0;
549 *btn1 = joystick.buttons[1].upcount;
550 joystick.buttons[1].upcount = 0;
553 void joy_set_btn_values( int btn, int state, fix timedown, int downcount, int upcount )
555 joystick.buttons[btn].ignore = 1;
556 joystick.buttons[btn].state = state;
557 joystick.buttons[btn].timedown = fixmuldiv( timedown, 1193180, 65536 );
558 joystick.buttons[btn].downcount = downcount;
559 joystick.buttons[btn].upcount = upcount;