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
51 #define my_hwnd g_hWnd // D1X compatibility
54 char joy_installed = 0;
57 typedef struct Button_info {
66 typedef struct Joy_info {
74 Button_info buttons[JOY_MAX_BUTTONS];
75 int axis_min[JOY_NUM_AXES]; //changed
76 int axis_center[JOY_NUM_AXES]; //changed --orulz
77 int axis_max[JOY_NUM_AXES]; //changed
85 void joy_get_cal_vals(int *axis_min, int *axis_center, int *axis_max)
89 for (i=0; i<JOY_NUM_AXES; i++) { //changed - orulz
90 axis_min[i] = joystick.axis_min[i];
91 axis_center[i] = joystick.axis_center[i];
92 axis_max[i] = joystick.axis_max[i];
96 void joy_set_cal_vals(int *axis_min, int *axis_center, int *axis_max)
100 for (i=0; i<JOY_NUM_AXES; i++) { //changed - orulz
101 joystick.axis_min[i] = axis_min[i];
102 joystick.axis_center[i] = axis_center[i];
103 joystick.axis_max[i] = axis_max[i];
107 ubyte joy_get_present_mask() {
108 return joystick.present_mask;
111 void joy_set_timer_rate(int max_value ) {
112 joystick.max_timer = max_value;
115 int joy_get_timer_rate() {
116 return joystick.max_timer;
122 if (!joy_installed) return;
124 for (i = 0; i < JOY_MAX_BUTTONS; i++)
126 joystick.buttons[i].ignore = 0;
127 joystick.buttons[i].state = 0;
128 joystick.buttons[i].timedown = 0;
129 joystick.buttons[i].downcount = 0;
130 joystick.buttons[i].upcount = 0;
136 //Begin section modified 3/7/99 - Owen Evans
138 ubyte joy_read_raw_buttons()
146 memset(&joy, 0, sizeof(joy));
147 joy.dwSize = sizeof(joy);
148 joy.dwFlags = JOY_RETURNBUTTONS | JOY_RETURNPOVCTS | JOY_USEDEADZONE;
150 if (joyGetPosEx(joystick.joyid, &joy)!=JOYERR_NOERROR)
153 for (i = 0; i < JOY_MAX_BUTTONS; i++)
155 joystick.buttons[i].last_state = joystick.buttons[i].state;
156 joystick.buttons[i].state = (joy.dwButtons >> i) & 0x1;
157 if (!joystick.buttons[i].last_state && joystick.buttons[i].state) {
158 joystick.buttons[i].timedown = timer_get_fixed_seconds();
159 joystick.buttons[i].downcount++;
165 if (joystick.hat_present && joy.dwPOV != JOY_POVCENTERED)
167 joystick.buttons[19].state = (joy.dwPOV < JOY_POVRIGHT || joy.dwPOV > JOY_POVLEFT);
168 joystick.buttons[15].state = (joy.dwPOV < JOY_POVBACKWARD && joy.dwPOV > JOY_POVFORWARD);
169 joystick.buttons[11].state = (joy.dwPOV < JOY_POVLEFT && joy.dwPOV > JOY_POVRIGHT);
170 joystick.buttons[7].state = (joy.dwPOV > JOY_POVBACKWARD);
173 return (ubyte)joy.dwButtons;
176 //end changed section - OE
179 ubyte joystick_read_raw_axis( ubyte mask, int * axis )
182 ubyte read_masks = 0;
184 axis[0] = 0; axis[1] = 0; //orulz: 1=x 2=y 3=r 4=z 5=u 6=v
185 axis[2] = 0; axis[3] = 0;
186 axis[4] = 0; axis[5] = 0; //HH: Added support for axes R and U
188 if (!joy_installed) {
192 memset(&joy, 0, sizeof(joy));
193 joy.dwSize = sizeof(joy);
194 joy.dwFlags = JOY_RETURNALL | JOY_USEDEADZONE;
195 if (joyGetPosEx(joystick.joyid, &joy)!=JOYERR_NOERROR) {
199 mask &= joystick.present_mask; // Don't read non-present channels
201 return 0; // Don't read if no stick connected.
204 if (mask & JOY_1_X_AXIS) { axis[0] = joy.dwXpos; read_masks |= JOY_1_X_AXIS; }
205 if (mask & JOY_1_Y_AXIS) { axis[1] = joy.dwYpos; read_masks |= JOY_1_Y_AXIS; }
207 // if (mask & JOY_1_Z_AXIS) { axis[2] = joy.dwZpos; read_masks |= JOY_1_Z_AXIS; }
208 // if (mask & JOY_1_POV) { axis[3] = joy.dwPOV; read_masks |= JOY_1_POV; }
209 // if (mask & JOY_1_R_AXIS) { axis[4] = joy.dwRpos; read_masks |= JOY_1_R_AXIS; }
210 // if (mask & JOY_1_U_AXIS) { axis[5] = joy.dwUpos; read_masks |= JOY_1_U_AXIS; }
211 // if (mask & JOY_1_V_AXIS) { axis[6] = joy.dwVpos; read_masks |= JOY_1_V_AXIS; }
212 if (mask & JOY_1_R_AXIS) { axis[2] = joy.dwRpos; read_masks |= JOY_1_R_AXIS; }
213 if (mask & JOY_1_Z_AXIS) { axis[3] = joy.dwZpos; read_masks |= JOY_1_Z_AXIS; }
214 if (mask & JOY_1_U_AXIS) { axis[4] = joy.dwZpos; read_masks |= JOY_1_U_AXIS; }
215 if (mask & JOY_1_V_AXIS) { axis[5] = joy.dwUpos; read_masks |= JOY_1_V_AXIS; }
220 int hh_average(int val1, int val2)
222 return abs(val1-val2)/2;
225 int joy_init(int joyid) //HH: added joyid parameter
228 int temp_axis[JOY_NUM_AXES]; //changed - orulz
231 if (FindArg("-nojoystick"))
234 atexit(joy_close); //HH: we are a bit lazy :). Errors are ignored, so we are even double-lazy :)
237 memset(&joystick, 0, sizeof(joystick));
239 for (i = 0; i < JOY_MAX_BUTTONS; i++)
240 joystick.buttons[i].last_state = 0;
242 if ( !joy_installed ) {
245 joystick.max_timer = 65536;
246 joystick.read_count = 0;
247 joystick.last_value = 0;
251 joystick.present_mask = JOY_ALL_AXIS; // Assume they're all present
252 joystick.present_mask = joystick_read_raw_axis( JOY_ALL_AXIS, temp_axis );
254 if ( joystick.present_mask & 3 )
260 //HH: Main Win32 joystick initialization, incl. reading cal. stuff
262 if (joyGetDevCaps(joyid, &pjc, sizeof(pjc))!=JOYERR_NOERROR) {
266 if (joySetThreshold(joyid, pjc.wXmax/256)!=JOYERR_NOERROR) {
270 joystick.max_timer = pjc.wPeriodMax;
271 joystick.axis_min[0] = pjc.wXmin;
272 joystick.axis_min[1] = pjc.wYmin;
274 // joystick.axis_min[2] = pjc.wZmin;
275 // //HH: joystick.axis_min[3] = pov-stuff
276 // joystick.axis_min[4] = pjc.wRmin;
277 // joystick.axis_min[5] = pjc.wUmin;
278 // joystick.axis_min[6] = pjc.wVmin;
279 joystick.axis_min[2] = pjc.wRmin;
280 joystick.axis_min[3] = pjc.wZmin;
281 joystick.axis_min[4] = pjc.wUmin;
282 joystick.axis_min[5] = pjc.wVmin;
284 joystick.axis_max[0] = pjc.wXmax;
285 joystick.axis_max[1] = pjc.wYmax;
287 // joystick.axis_max[2] = pjc.wZmax;
288 // //HH: joystick.axis_max[3] = pov-stuff
289 // joystick.axis_max[4] = pjc.wRmax;
290 // joystick.axis_max[5] = pjc.wUmax;
291 // joystick.axis_max[6] = pjc.wVmax;
292 joystick.axis_max[2] = pjc.wRmax;
293 joystick.axis_max[3] = pjc.wZmax;
294 joystick.axis_max[4] = pjc.wUmax;
295 joystick.axis_max[5] = pjc.wVmax;
297 joystick.axis_center[0] = hh_average(pjc.wXmax,pjc.wXmin);
298 joystick.axis_center[1] = hh_average(pjc.wYmax,pjc.wYmin);
300 // joystick.axis_center[2] = hh_average(pjc.wZmax,pjc.wZmin);
301 // joystick.axis_center[3] = JOY_POVCENTERED;
302 // joystick.axis_center[4] = hh_average(pjc.wRmax,pjc.wRmin);
303 // joystick.axis_center[5] = hh_average(pjc.wUmax,pjc.wUmin);
304 // joystick.axis_center[6] = hh_average(pjc.wVmax,pjc.wVmin);
305 joystick.axis_center[2] = hh_average(pjc.wRmax,pjc.wRmin);
306 joystick.axis_center[3] = hh_average(pjc.wZmax,pjc.wZmin);
307 joystick.axis_center[4] = hh_average(pjc.wUmax,pjc.wUmin);
308 joystick.axis_center[5] = hh_average(pjc.wVmax,pjc.wVmin);
310 joystick.present_mask = JOY_1_X_AXIS | JOY_1_Y_AXIS;
311 if (pjc.wCaps & JOYCAPS_HASZ) joystick.present_mask |= JOY_1_Z_AXIS;
312 joystick.hat_present = (pjc.wCaps & JOYCAPS_HASPOV) > 0;
313 if (pjc.wCaps & JOYCAPS_HASR) joystick.present_mask |= JOY_1_R_AXIS;
314 if (pjc.wCaps & JOYCAPS_HASU) joystick.present_mask |= JOY_1_U_AXIS;
315 if (pjc.wCaps & JOYCAPS_HASV) joystick.present_mask |= JOY_1_V_AXIS;
323 if (!joy_installed) return;
330 joystick.present_mask = JOY_ALL_AXIS; // Assume they're all present
331 joystick.present_mask = joystick_read_raw_axis( JOY_ALL_AXIS, joystick.axis_min );
333 if ( joystick.present_mask & 3 )
341 joystick.present_mask = JOY_ALL_AXIS; // Assume they're all present
342 joystick.present_mask = joystick_read_raw_axis( JOY_ALL_AXIS, joystick.axis_max );
344 if ( joystick.present_mask & 3 )
352 joystick.present_mask = JOY_ALL_AXIS; // Assume they're all present
353 joystick.present_mask = joystick_read_raw_axis( JOY_ALL_AXIS, joystick.axis_center );
355 if ( joystick.present_mask & 3 )
361 void joy_set_cen_fake(int channel)
365 int joy_get_scaled_reading( int raw, int axn )
369 // Make sure it's calibrated properly.
370 if ( joystick.axis_center[axn] - joystick.axis_min[axn] < 128 )
371 return 0; //HH: had to increase to 128
372 if ( joystick.axis_max[axn] - joystick.axis_center[axn] < 128 )
373 return 0; //HH: had to increase to 128
375 if (!(joystick.present_mask & (1 << axn)))
376 return 0; // fixes joy config bug where it'll always set an axis you don't even have. - 2000/01/14 Matt Mueller
378 raw -= joystick.axis_center[axn];
381 d = joystick.axis_center[axn]-joystick.axis_min[axn];
383 d = joystick.axis_max[axn]-joystick.axis_center[axn];
392 if ( x < -128 ) x = -128;
393 if ( x > 127 ) x = 127;
395 //added on 4/13/99 by Victor Rachels to add deadzone control
396 d = (joy_deadzone) * 6;
397 if ((x > (-1*d)) && (x < d))
399 //end this section addition -VR
404 void joy_get_pos( int *x, int *y )
407 int axis[JOY_NUM_AXES];
409 if ((!joy_installed)||(!joy_present)) { *x=*y=0; return; }
411 flags=joystick_read_raw_axis( JOY_1_X_AXIS+JOY_1_Y_AXIS, axis );
413 if ( flags & JOY_1_X_AXIS )
414 *x = joy_get_scaled_reading( axis[0], 0 );
418 if ( flags & JOY_1_Y_AXIS )
419 *y = joy_get_scaled_reading( axis[1], 1 );
424 ubyte joy_read_stick( ubyte masks, int *axis )
427 int raw_axis[JOY_NUM_AXES];
429 if ((!joy_installed)||(!joy_present)) {
430 axis[0] = 0; axis[1] = 0;
431 axis[2] = 0; axis[3] = 0;
432 axis[4] = 0; axis[5] = 0;
436 flags=joystick_read_raw_axis( masks, raw_axis );
438 if ( flags & JOY_1_X_AXIS )
439 axis[0] = joy_get_scaled_reading( raw_axis[0], 0 );
443 if ( flags & JOY_1_Y_AXIS )
444 axis[1] = joy_get_scaled_reading( raw_axis[1], 1 );
448 if ( flags & JOY_1_R_AXIS )
449 axis[2] = joy_get_scaled_reading( raw_axis[2], 2 );
453 if ( flags & JOY_1_Z_AXIS )
454 axis[3] = joy_get_scaled_reading( raw_axis[3], 3 );
458 if ( flags & JOY_1_U_AXIS )
459 axis[4] = joy_get_scaled_reading( raw_axis[4], 4);
463 if ( flags & JOY_1_V_AXIS )
464 axis[5] = joy_get_scaled_reading( raw_axis[5], 5 );
474 if ((!joy_installed)||(!joy_present)) return 0;
476 return joy_read_raw_buttons();
480 //Begin section modified 3/7/99 - Owen Evans
482 void joy_get_btn_down_cnt( int *btn0, int *btn1 )
484 if ((!joy_installed)||(!joy_present)) { *btn0=*btn1=0; return; }
488 *btn0 = joystick.buttons[0].downcount;
489 joystick.buttons[0].downcount = 0;
490 *btn1 = joystick.buttons[1].downcount;
491 joystick.buttons[1].downcount = 0;
494 int joy_get_button_state( int btn )
496 if ((!joy_installed)||(!joy_present)) return 0;
497 if (btn >= JOY_MAX_BUTTONS)
502 return joystick.buttons[btn].state;
505 int joy_get_button_up_cnt( int btn )
509 if ((!joy_installed)||(!joy_present)) return 0;
511 if (btn >= JOY_MAX_BUTTONS)
514 count = joystick.buttons[btn].upcount;
515 joystick.buttons[btn].upcount = 0;
520 int joy_get_button_down_cnt( int btn )
524 if ((!joy_installed)||(!joy_present)) return 0;
525 if (btn >= JOY_MAX_BUTTONS)
530 count = joystick.buttons[btn].downcount;
531 joystick.buttons[btn].downcount = 0;
536 fix joy_get_button_down_time( int btn )
540 if ((!joy_installed)||(!joy_present)) return 0;
541 if (btn >= JOY_MAX_BUTTONS)
546 if (joystick.buttons[btn].state) {
547 count = timer_get_fixed_seconds() - joystick.buttons[btn].timedown;
548 joystick.buttons[btn].timedown = 0;
554 //end changed section - OE
557 void joy_get_btn_up_cnt( int *btn0, int *btn1 )
559 if ((!joy_installed)||(!joy_present)) { *btn0=*btn1=0; return; }
561 *btn0 = joystick.buttons[0].upcount;
562 joystick.buttons[0].upcount = 0;
563 *btn1 = joystick.buttons[1].upcount;
564 joystick.buttons[1].upcount = 0;
567 void joy_set_btn_values( int btn, int state, fix timedown, int downcount, int upcount )
569 joystick.buttons[btn].ignore = 1;
570 joystick.buttons[btn].state = state;
571 joystick.buttons[btn].timedown = fixmuldiv( timedown, 1193180, 65536 );
572 joystick.buttons[btn].downcount = downcount;
573 joystick.buttons[btn].upcount = upcount;