1 /* $Id: joyhh.c,v 1.6 2005-04-04 09:18:08 btb Exp $ */
2 //JOYC.C for D1_3Dfx and D1OpenGL
3 //D1_3Dfx is a Win32 executable using Glide and DirectX 3
4 //D1OpenGL is a Win32 executable using OpenGL and DirectX 3
5 //This joystick code should run on DirectInput 2 and higher
6 //We are not using DirectX 5 for now, since we want to stay compatible to the HH-loved Windows NT :).
7 //So ForceFeedback is not supported
10 // 1) Windows DirectX supports up to 7 axes, D1/DOS only 4, so we needed to increase the number to 7 at several points
11 // Also JOY_ALL_AXIS must be (1+2+4+8+16+32+64) in JOY.H file
12 // 2) Windows DirectX supports up to 32 buttons. So far we however only support 4. Adding support for more should be however easily possible.
13 // 3) _enable and _disable are not needed
14 // 4) joy_bogus_reading is not needed, so all calls are just removed
15 // 5) The joystick query goes over the DirectInputs function
16 // MMRESULT joyGetPosEx(UINT uJoyID, LPJOYINFOEX pji);
17 // All functions reading over BIOS, including the ASM code are removed
22 THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX
23 SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO
24 END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A
25 ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS
26 IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS
27 SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE
28 FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE
29 CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS
30 AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE.
31 COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED.
35 Modifications by Heiko Herrmann
36 Later modified by Owen Evans to work with D1X (3/7/99)
40 #define _WIN32_OS //HH
42 #include <windows.h> //HH
43 #include <mmsystem.h> //HH
52 #define my_hwnd g_hWnd // D1X compatibility
55 char joy_installed = 0;
58 typedef struct Button_info {
67 typedef struct Joy_info {
75 Button_info buttons[JOY_MAX_BUTTONS];
76 int axis_min[JOY_NUM_AXES]; //changed
77 int axis_center[JOY_NUM_AXES]; //changed --orulz
78 int axis_max[JOY_NUM_AXES]; //changed
86 void joy_get_cal_vals(int *axis_min, int *axis_center, int *axis_max)
90 for (i=0; i<JOY_NUM_AXES; i++) { //changed - orulz
91 axis_min[i] = joystick.axis_min[i];
92 axis_center[i] = joystick.axis_center[i];
93 axis_max[i] = joystick.axis_max[i];
97 void joy_set_cal_vals(int *axis_min, int *axis_center, int *axis_max)
101 for (i=0; i<JOY_NUM_AXES; i++) { //changed - orulz
102 joystick.axis_min[i] = axis_min[i];
103 joystick.axis_center[i] = axis_center[i];
104 joystick.axis_max[i] = axis_max[i];
108 ubyte joy_get_present_mask() {
109 return joystick.present_mask;
112 void joy_set_timer_rate(int max_value ) {
113 joystick.max_timer = max_value;
116 int joy_get_timer_rate() {
117 return joystick.max_timer;
123 if (!joy_installed) return;
125 for (i = 0; i < JOY_MAX_BUTTONS; i++)
127 joystick.buttons[i].ignore = 0;
128 joystick.buttons[i].state = 0;
129 joystick.buttons[i].timedown = 0;
130 joystick.buttons[i].downcount = 0;
131 joystick.buttons[i].upcount = 0;
137 //Begin section modified 3/7/99 - Owen Evans
139 ubyte joy_read_raw_buttons()
147 memset(&joy, 0, sizeof(joy));
148 joy.dwSize = sizeof(joy);
149 joy.dwFlags = JOY_RETURNBUTTONS | JOY_RETURNPOVCTS | JOY_USEDEADZONE;
151 if (joyGetPosEx(joystick.joyid, &joy)!=JOYERR_NOERROR)
154 for (i = 0; i < JOY_MAX_BUTTONS; i++)
156 joystick.buttons[i].last_state = joystick.buttons[i].state;
157 joystick.buttons[i].state = (joy.dwButtons >> i) & 0x1;
158 if (!joystick.buttons[i].last_state && joystick.buttons[i].state) {
159 joystick.buttons[i].timedown = timer_get_fixed_seconds();
160 joystick.buttons[i].downcount++;
166 if (joystick.hat_present && joy.dwPOV != JOY_POVCENTERED)
168 joystick.buttons[19].state = (joy.dwPOV < JOY_POVRIGHT || joy.dwPOV > JOY_POVLEFT);
169 joystick.buttons[15].state = (joy.dwPOV < JOY_POVBACKWARD && joy.dwPOV > JOY_POVFORWARD);
170 joystick.buttons[11].state = (joy.dwPOV < JOY_POVLEFT && joy.dwPOV > JOY_POVRIGHT);
171 joystick.buttons[7].state = (joy.dwPOV > JOY_POVBACKWARD);
174 return (ubyte)joy.dwButtons;
177 //end changed section - OE
180 ubyte joystick_read_raw_axis( ubyte mask, int * axis )
183 ubyte read_masks = 0;
185 axis[0] = 0; axis[1] = 0; //orulz: 1=x 2=y 3=r 4=z 5=u 6=v
186 axis[2] = 0; axis[3] = 0;
187 axis[4] = 0; axis[5] = 0; //HH: Added support for axes R and U
189 if (!joy_installed) {
193 memset(&joy, 0, sizeof(joy));
194 joy.dwSize = sizeof(joy);
195 joy.dwFlags = JOY_RETURNALL | JOY_USEDEADZONE;
196 if (joyGetPosEx(joystick.joyid, &joy)!=JOYERR_NOERROR) {
200 mask &= joystick.present_mask; // Don't read non-present channels
202 return 0; // Don't read if no stick connected.
205 if (mask & JOY_1_X_AXIS) { axis[0] = joy.dwXpos; read_masks |= JOY_1_X_AXIS; }
206 if (mask & JOY_1_Y_AXIS) { axis[1] = joy.dwYpos; read_masks |= JOY_1_Y_AXIS; }
208 // if (mask & JOY_1_Z_AXIS) { axis[2] = joy.dwZpos; read_masks |= JOY_1_Z_AXIS; }
209 // if (mask & JOY_1_POV) { axis[3] = joy.dwPOV; read_masks |= JOY_1_POV; }
210 // if (mask & JOY_1_R_AXIS) { axis[4] = joy.dwRpos; read_masks |= JOY_1_R_AXIS; }
211 // if (mask & JOY_1_U_AXIS) { axis[5] = joy.dwUpos; read_masks |= JOY_1_U_AXIS; }
212 // if (mask & JOY_1_V_AXIS) { axis[6] = joy.dwVpos; read_masks |= JOY_1_V_AXIS; }
213 if (mask & JOY_1_R_AXIS) { axis[2] = joy.dwRpos; read_masks |= JOY_1_R_AXIS; }
214 if (mask & JOY_1_Z_AXIS) { axis[3] = joy.dwZpos; read_masks |= JOY_1_Z_AXIS; }
215 if (mask & JOY_1_U_AXIS) { axis[4] = joy.dwZpos; read_masks |= JOY_1_U_AXIS; }
216 if (mask & JOY_1_V_AXIS) { axis[5] = joy.dwUpos; read_masks |= JOY_1_V_AXIS; }
221 int hh_average(int val1, int val2)
223 return abs(val1-val2)/2;
226 int joy_init(int joyid) //HH: added joyid parameter
229 int temp_axis[JOY_NUM_AXES]; //changed - orulz
232 if (FindArg("-nojoystick"))
235 atexit(joy_close); //HH: we are a bit lazy :). Errors are ignored, so we are even double-lazy :)
238 memset(&joystick, 0, sizeof(joystick));
240 for (i = 0; i < JOY_MAX_BUTTONS; i++)
241 joystick.buttons[i].last_state = 0;
243 if ( !joy_installed ) {
246 joystick.max_timer = 65536;
247 joystick.read_count = 0;
248 joystick.last_value = 0;
252 joystick.present_mask = JOY_ALL_AXIS; // Assume they're all present
253 joystick.present_mask = joystick_read_raw_axis( JOY_ALL_AXIS, temp_axis );
255 if ( joystick.present_mask & 3 )
261 //HH: Main Win32 joystick initialization, incl. reading cal. stuff
263 if (joyGetDevCaps(joyid, &pjc, sizeof(pjc))!=JOYERR_NOERROR) {
267 if (joySetThreshold(joyid, pjc.wXmax/256)!=JOYERR_NOERROR) {
271 joystick.max_timer = pjc.wPeriodMax;
272 joystick.axis_min[0] = pjc.wXmin;
273 joystick.axis_min[1] = pjc.wYmin;
275 // joystick.axis_min[2] = pjc.wZmin;
276 // //HH: joystick.axis_min[3] = pov-stuff
277 // joystick.axis_min[4] = pjc.wRmin;
278 // joystick.axis_min[5] = pjc.wUmin;
279 // joystick.axis_min[6] = pjc.wVmin;
280 joystick.axis_min[2] = pjc.wRmin;
281 joystick.axis_min[3] = pjc.wZmin;
282 joystick.axis_min[4] = pjc.wUmin;
283 joystick.axis_min[5] = pjc.wVmin;
285 joystick.axis_max[0] = pjc.wXmax;
286 joystick.axis_max[1] = pjc.wYmax;
288 // joystick.axis_max[2] = pjc.wZmax;
289 // //HH: joystick.axis_max[3] = pov-stuff
290 // joystick.axis_max[4] = pjc.wRmax;
291 // joystick.axis_max[5] = pjc.wUmax;
292 // joystick.axis_max[6] = pjc.wVmax;
293 joystick.axis_max[2] = pjc.wRmax;
294 joystick.axis_max[3] = pjc.wZmax;
295 joystick.axis_max[4] = pjc.wUmax;
296 joystick.axis_max[5] = pjc.wVmax;
298 joystick.axis_center[0] = hh_average(pjc.wXmax,pjc.wXmin);
299 joystick.axis_center[1] = hh_average(pjc.wYmax,pjc.wYmin);
301 // joystick.axis_center[2] = hh_average(pjc.wZmax,pjc.wZmin);
302 // joystick.axis_center[3] = JOY_POVCENTERED;
303 // joystick.axis_center[4] = hh_average(pjc.wRmax,pjc.wRmin);
304 // joystick.axis_center[5] = hh_average(pjc.wUmax,pjc.wUmin);
305 // joystick.axis_center[6] = hh_average(pjc.wVmax,pjc.wVmin);
306 joystick.axis_center[2] = hh_average(pjc.wRmax,pjc.wRmin);
307 joystick.axis_center[3] = hh_average(pjc.wZmax,pjc.wZmin);
308 joystick.axis_center[4] = hh_average(pjc.wUmax,pjc.wUmin);
309 joystick.axis_center[5] = hh_average(pjc.wVmax,pjc.wVmin);
311 joystick.present_mask = JOY_1_X_AXIS | JOY_1_Y_AXIS;
312 if (pjc.wCaps & JOYCAPS_HASZ) joystick.present_mask |= JOY_1_Z_AXIS;
313 joystick.hat_present = (pjc.wCaps & JOYCAPS_HASPOV) > 0;
314 if (pjc.wCaps & JOYCAPS_HASR) joystick.present_mask |= JOY_1_R_AXIS;
315 if (pjc.wCaps & JOYCAPS_HASU) joystick.present_mask |= JOY_1_U_AXIS;
316 if (pjc.wCaps & JOYCAPS_HASV) joystick.present_mask |= JOY_1_V_AXIS;
324 if (!joy_installed) return;
331 joystick.present_mask = JOY_ALL_AXIS; // Assume they're all present
332 joystick.present_mask = joystick_read_raw_axis( JOY_ALL_AXIS, joystick.axis_min );
334 if ( joystick.present_mask & 3 )
342 joystick.present_mask = JOY_ALL_AXIS; // Assume they're all present
343 joystick.present_mask = joystick_read_raw_axis( JOY_ALL_AXIS, joystick.axis_max );
345 if ( joystick.present_mask & 3 )
353 joystick.present_mask = JOY_ALL_AXIS; // Assume they're all present
354 joystick.present_mask = joystick_read_raw_axis( JOY_ALL_AXIS, joystick.axis_center );
356 if ( joystick.present_mask & 3 )
362 void joy_set_cen_fake(int channel)
366 int joy_get_scaled_reading( int raw, int axn )
370 // Make sure it's calibrated properly.
371 if ( joystick.axis_center[axn] - joystick.axis_min[axn] < 128 )
372 return 0; //HH: had to increase to 128
373 if ( joystick.axis_max[axn] - joystick.axis_center[axn] < 128 )
374 return 0; //HH: had to increase to 128
376 if (!(joystick.present_mask & (1 << axn)))
377 return 0; // fixes joy config bug where it'll always set an axis you don't even have. - 2000/01/14 Matt Mueller
379 raw -= joystick.axis_center[axn];
382 d = joystick.axis_center[axn]-joystick.axis_min[axn];
384 d = joystick.axis_max[axn]-joystick.axis_center[axn];
393 if ( x < -128 ) x = -128;
394 if ( x > 127 ) x = 127;
396 //added on 4/13/99 by Victor Rachels to add deadzone control
397 d = (joy_deadzone) * 6;
398 if ((x > (-1*d)) && (x < d))
400 //end this section addition -VR
405 void joy_get_pos( int *x, int *y )
408 int axis[JOY_NUM_AXES];
410 if ((!joy_installed)||(!joy_present)) { *x=*y=0; return; }
412 flags=joystick_read_raw_axis( JOY_1_X_AXIS+JOY_1_Y_AXIS, axis );
414 if ( flags & JOY_1_X_AXIS )
415 *x = joy_get_scaled_reading( axis[0], 0 );
419 if ( flags & JOY_1_Y_AXIS )
420 *y = joy_get_scaled_reading( axis[1], 1 );
425 ubyte joy_read_stick( ubyte masks, int *axis )
428 int raw_axis[JOY_NUM_AXES];
430 if ((!joy_installed)||(!joy_present)) {
431 axis[0] = 0; axis[1] = 0;
432 axis[2] = 0; axis[3] = 0;
433 axis[4] = 0; axis[5] = 0;
437 flags=joystick_read_raw_axis( masks, raw_axis );
439 if ( flags & JOY_1_X_AXIS )
440 axis[0] = joy_get_scaled_reading( raw_axis[0], 0 );
444 if ( flags & JOY_1_Y_AXIS )
445 axis[1] = joy_get_scaled_reading( raw_axis[1], 1 );
449 if ( flags & JOY_1_R_AXIS )
450 axis[2] = joy_get_scaled_reading( raw_axis[2], 2 );
454 if ( flags & JOY_1_Z_AXIS )
455 axis[3] = joy_get_scaled_reading( raw_axis[3], 3 );
459 if ( flags & JOY_1_U_AXIS )
460 axis[4] = joy_get_scaled_reading( raw_axis[4], 4);
464 if ( flags & JOY_1_V_AXIS )
465 axis[5] = joy_get_scaled_reading( raw_axis[5], 5 );
475 if ((!joy_installed)||(!joy_present)) return 0;
477 return joy_read_raw_buttons();
481 //Begin section modified 3/7/99 - Owen Evans
483 void joy_get_btn_down_cnt( int *btn0, int *btn1 )
485 if ((!joy_installed)||(!joy_present)) { *btn0=*btn1=0; return; }
489 *btn0 = joystick.buttons[0].downcount;
490 joystick.buttons[0].downcount = 0;
491 *btn1 = joystick.buttons[1].downcount;
492 joystick.buttons[1].downcount = 0;
495 int joy_get_button_state( int btn )
497 if ((!joy_installed)||(!joy_present)) return 0;
498 if (btn >= JOY_MAX_BUTTONS)
503 return joystick.buttons[btn].state;
506 int joy_get_button_up_cnt( int btn )
510 if ((!joy_installed)||(!joy_present)) return 0;
512 if (btn >= JOY_MAX_BUTTONS)
515 count = joystick.buttons[btn].upcount;
516 joystick.buttons[btn].upcount = 0;
521 int joy_get_button_down_cnt( int btn )
525 if ((!joy_installed)||(!joy_present)) return 0;
526 if (btn >= JOY_MAX_BUTTONS)
531 count = joystick.buttons[btn].downcount;
532 joystick.buttons[btn].downcount = 0;
537 fix joy_get_button_down_time( int btn )
541 if ((!joy_installed)||(!joy_present)) return 0;
542 if (btn >= JOY_MAX_BUTTONS)
547 if (joystick.buttons[btn].state) {
548 count = timer_get_fixed_seconds() - joystick.buttons[btn].timedown;
549 joystick.buttons[btn].timedown = 0;
555 //end changed section - OE
558 void joy_get_btn_up_cnt( int *btn0, int *btn1 )
560 if ((!joy_installed)||(!joy_present)) { *btn0=*btn1=0; return; }
562 *btn0 = joystick.buttons[0].upcount;
563 joystick.buttons[0].upcount = 0;
564 *btn1 = joystick.buttons[1].upcount;
565 joystick.buttons[1].upcount = 0;
568 void joy_set_btn_values( int btn, int state, fix timedown, int downcount, int upcount )
570 joystick.buttons[btn].ignore = 1;
571 joystick.buttons[btn].state = state;
572 joystick.buttons[btn].timedown = fixmuldiv( timedown, 1193180, 65536 );
573 joystick.buttons[btn].downcount = downcount;
574 joystick.buttons[btn].upcount = upcount;