1 /* $Id: joyhh.c,v 1.5 2004-05-22 08:00:04 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[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<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 < MAX_BUTTONS; i++) {
154 joystick.buttons[i].last_state = joystick.buttons[i].state;
155 joystick.buttons[i].state = (joy.dwButtons >> i) & 0x1;
156 if (!joystick.buttons[i].last_state && joystick.buttons[i].state) {
157 joystick.buttons[i].timedown = timer_get_fixed_seconds();
158 joystick.buttons[i].downcount++;
164 if (joystick.hat_present && joy.dwPOV != JOY_POVCENTERED)
166 joystick.buttons[19].state = (joy.dwPOV < JOY_POVRIGHT || joy.dwPOV > JOY_POVLEFT);
167 joystick.buttons[15].state = (joy.dwPOV < JOY_POVBACKWARD && joy.dwPOV > JOY_POVFORWARD);
168 joystick.buttons[11].state = (joy.dwPOV < JOY_POVLEFT && joy.dwPOV > JOY_POVRIGHT);
169 joystick.buttons[7].state = (joy.dwPOV > JOY_POVBACKWARD);
172 return (ubyte)joy.dwButtons;
175 //end changed section - OE
178 ubyte joystick_read_raw_axis( ubyte mask, int * axis )
181 ubyte read_masks = 0;
183 axis[0] = 0; axis[1] = 0; //orulz: 1=x 2=y 3=r 4=z 5=u 6=v
184 axis[2] = 0; axis[3] = 0;
185 axis[4] = 0; axis[5] = 0; //HH: Added support for axes R and U
187 if (!joy_installed) {
191 memset(&joy, 0, sizeof(joy));
192 joy.dwSize = sizeof(joy);
193 joy.dwFlags = JOY_RETURNALL | JOY_USEDEADZONE;
194 if (joyGetPosEx(joystick.joyid, &joy)!=JOYERR_NOERROR) {
198 mask &= joystick.present_mask; // Don't read non-present channels
200 return 0; // Don't read if no stick connected.
203 if (mask & JOY_1_X_AXIS) { axis[0] = joy.dwXpos; read_masks |= JOY_1_X_AXIS; }
204 if (mask & JOY_1_Y_AXIS) { axis[1] = joy.dwYpos; read_masks |= JOY_1_Y_AXIS; }
206 // if (mask & JOY_1_Z_AXIS) { axis[2] = joy.dwZpos; read_masks |= JOY_1_Z_AXIS; }
207 // if (mask & JOY_1_POV) { axis[3] = joy.dwPOV; read_masks |= JOY_1_POV; }
208 // if (mask & JOY_1_R_AXIS) { axis[4] = joy.dwRpos; read_masks |= JOY_1_R_AXIS; }
209 // if (mask & JOY_1_U_AXIS) { axis[5] = joy.dwUpos; read_masks |= JOY_1_U_AXIS; }
210 // if (mask & JOY_1_V_AXIS) { axis[6] = joy.dwVpos; read_masks |= JOY_1_V_AXIS; }
211 if (mask & JOY_1_R_AXIS) { axis[2] = joy.dwRpos; read_masks |= JOY_1_R_AXIS; }
212 if (mask & JOY_1_Z_AXIS) { axis[3] = joy.dwZpos; read_masks |= JOY_1_Z_AXIS; }
213 if (mask & JOY_1_U_AXIS) { axis[4] = joy.dwZpos; read_masks |= JOY_1_U_AXIS; }
214 if (mask & JOY_1_V_AXIS) { axis[5] = joy.dwUpos; read_masks |= JOY_1_V_AXIS; }
219 int hh_average(int val1, int val2)
221 return abs(val1-val2)/2;
224 int joy_init(int joyid) //HH: added joyid parameter
227 int temp_axis[JOY_NUM_AXES]; //changed - orulz
230 if (FindArg("-nojoystick"))
233 atexit(joy_close); //HH: we are a bit lazy :). Errors are ignored, so we are even double-lazy :)
236 memset(&joystick, 0, sizeof(joystick));
238 for (i=0; i<MAX_BUTTONS; i++)
239 joystick.buttons[i].last_state = 0;
241 if ( !joy_installed ) {
244 joystick.max_timer = 65536;
245 joystick.read_count = 0;
246 joystick.last_value = 0;
250 joystick.present_mask = JOY_ALL_AXIS; // Assume they're all present
251 joystick.present_mask = joystick_read_raw_axis( JOY_ALL_AXIS, temp_axis );
253 if ( joystick.present_mask & 3 )
259 //HH: Main Win32 joystick initialization, incl. reading cal. stuff
261 if (joyGetDevCaps(joyid, &pjc, sizeof(pjc))!=JOYERR_NOERROR) {
265 if (joySetThreshold(joyid, pjc.wXmax/256)!=JOYERR_NOERROR) {
269 joystick.max_timer = pjc.wPeriodMax;
270 joystick.axis_min[0] = pjc.wXmin;
271 joystick.axis_min[1] = pjc.wYmin;
273 // joystick.axis_min[2] = pjc.wZmin;
274 // //HH: joystick.axis_min[3] = pov-stuff
275 // joystick.axis_min[4] = pjc.wRmin;
276 // joystick.axis_min[5] = pjc.wUmin;
277 // joystick.axis_min[6] = pjc.wVmin;
278 joystick.axis_min[2] = pjc.wRmin;
279 joystick.axis_min[3] = pjc.wZmin;
280 joystick.axis_min[4] = pjc.wUmin;
281 joystick.axis_min[5] = pjc.wVmin;
283 joystick.axis_max[0] = pjc.wXmax;
284 joystick.axis_max[1] = pjc.wYmax;
286 // joystick.axis_max[2] = pjc.wZmax;
287 // //HH: joystick.axis_max[3] = pov-stuff
288 // joystick.axis_max[4] = pjc.wRmax;
289 // joystick.axis_max[5] = pjc.wUmax;
290 // joystick.axis_max[6] = pjc.wVmax;
291 joystick.axis_max[2] = pjc.wRmax;
292 joystick.axis_max[3] = pjc.wZmax;
293 joystick.axis_max[4] = pjc.wUmax;
294 joystick.axis_max[5] = pjc.wVmax;
296 joystick.axis_center[0] = hh_average(pjc.wXmax,pjc.wXmin);
297 joystick.axis_center[1] = hh_average(pjc.wYmax,pjc.wYmin);
299 // joystick.axis_center[2] = hh_average(pjc.wZmax,pjc.wZmin);
300 // joystick.axis_center[3] = JOY_POVCENTERED;
301 // joystick.axis_center[4] = hh_average(pjc.wRmax,pjc.wRmin);
302 // joystick.axis_center[5] = hh_average(pjc.wUmax,pjc.wUmin);
303 // joystick.axis_center[6] = hh_average(pjc.wVmax,pjc.wVmin);
304 joystick.axis_center[2] = hh_average(pjc.wRmax,pjc.wRmin);
305 joystick.axis_center[3] = hh_average(pjc.wZmax,pjc.wZmin);
306 joystick.axis_center[4] = hh_average(pjc.wUmax,pjc.wUmin);
307 joystick.axis_center[5] = hh_average(pjc.wVmax,pjc.wVmin);
309 joystick.present_mask = JOY_1_X_AXIS | JOY_1_Y_AXIS;
310 if (pjc.wCaps & JOYCAPS_HASZ) joystick.present_mask |= JOY_1_Z_AXIS;
311 joystick.hat_present = (pjc.wCaps & JOYCAPS_HASPOV) > 0;
312 if (pjc.wCaps & JOYCAPS_HASR) joystick.present_mask |= JOY_1_R_AXIS;
313 if (pjc.wCaps & JOYCAPS_HASU) joystick.present_mask |= JOY_1_U_AXIS;
314 if (pjc.wCaps & JOYCAPS_HASV) joystick.present_mask |= JOY_1_V_AXIS;
322 if (!joy_installed) return;
329 joystick.present_mask = JOY_ALL_AXIS; // Assume they're all present
330 joystick.present_mask = joystick_read_raw_axis( JOY_ALL_AXIS, joystick.axis_min );
332 if ( joystick.present_mask & 3 )
340 joystick.present_mask = JOY_ALL_AXIS; // Assume they're all present
341 joystick.present_mask = joystick_read_raw_axis( JOY_ALL_AXIS, joystick.axis_max );
343 if ( joystick.present_mask & 3 )
351 joystick.present_mask = JOY_ALL_AXIS; // Assume they're all present
352 joystick.present_mask = joystick_read_raw_axis( JOY_ALL_AXIS, joystick.axis_center );
354 if ( joystick.present_mask & 3 )
360 void joy_set_cen_fake(int channel)
364 int joy_get_scaled_reading( int raw, int axn )
368 // Make sure it's calibrated properly.
369 if ( joystick.axis_center[axn] - joystick.axis_min[axn] < 128 )
370 return 0; //HH: had to increase to 128
371 if ( joystick.axis_max[axn] - joystick.axis_center[axn] < 128 )
372 return 0; //HH: had to increase to 128
374 if (!(joystick.present_mask & (1 << axn)))
375 return 0; // fixes joy config bug where it'll always set an axis you don't even have. - 2000/01/14 Matt Mueller
377 raw -= joystick.axis_center[axn];
380 d = joystick.axis_center[axn]-joystick.axis_min[axn];
382 d = joystick.axis_max[axn]-joystick.axis_center[axn];
391 if ( x < -128 ) x = -128;
392 if ( x > 127 ) x = 127;
394 //added on 4/13/99 by Victor Rachels to add deadzone control
395 d = (joy_deadzone) * 6;
396 if ((x > (-1*d)) && (x < d))
398 //end this section addition -VR
403 void joy_get_pos( int *x, int *y )
406 int axis[JOY_NUM_AXES];
408 if ((!joy_installed)||(!joy_present)) { *x=*y=0; return; }
410 flags=joystick_read_raw_axis( JOY_1_X_AXIS+JOY_1_Y_AXIS, axis );
412 if ( flags & JOY_1_X_AXIS )
413 *x = joy_get_scaled_reading( axis[0], 0 );
417 if ( flags & JOY_1_Y_AXIS )
418 *y = joy_get_scaled_reading( axis[1], 1 );
423 ubyte joy_read_stick( ubyte masks, int *axis )
426 int raw_axis[JOY_NUM_AXES];
428 if ((!joy_installed)||(!joy_present)) {
429 axis[0] = 0; axis[1] = 0;
430 axis[2] = 0; axis[3] = 0;
431 axis[4] = 0; axis[5] = 0;
435 flags=joystick_read_raw_axis( masks, raw_axis );
437 if ( flags & JOY_1_X_AXIS )
438 axis[0] = joy_get_scaled_reading( raw_axis[0], 0 );
442 if ( flags & JOY_1_Y_AXIS )
443 axis[1] = joy_get_scaled_reading( raw_axis[1], 1 );
447 if ( flags & JOY_1_R_AXIS )
448 axis[2] = joy_get_scaled_reading( raw_axis[2], 2 );
452 if ( flags & JOY_1_Z_AXIS )
453 axis[3] = joy_get_scaled_reading( raw_axis[3], 3 );
457 if ( flags & JOY_1_U_AXIS )
458 axis[4] = joy_get_scaled_reading( raw_axis[4], 4);
462 if ( flags & JOY_1_V_AXIS )
463 axis[5] = joy_get_scaled_reading( raw_axis[5], 5 );
473 if ((!joy_installed)||(!joy_present)) return 0;
475 return joy_read_raw_buttons();
479 //Begin section modified 3/7/99 - Owen Evans
481 void joy_get_btn_down_cnt( int *btn0, int *btn1 )
483 if ((!joy_installed)||(!joy_present)) { *btn0=*btn1=0; return; }
487 *btn0 = joystick.buttons[0].downcount;
488 joystick.buttons[0].downcount = 0;
489 *btn1 = joystick.buttons[1].downcount;
490 joystick.buttons[1].downcount = 0;
493 int joy_get_button_state( int btn )
495 if ((!joy_installed)||(!joy_present)) return 0;
496 if ( btn >= MAX_BUTTONS ) return 0;
500 return joystick.buttons[btn].state;
503 int joy_get_button_up_cnt( int btn )
507 if ((!joy_installed)||(!joy_present)) return 0;
509 if ( btn >= MAX_BUTTONS ) return 0;
511 count = joystick.buttons[btn].upcount;
512 joystick.buttons[btn].upcount = 0;
517 int joy_get_button_down_cnt( int btn )
521 if ((!joy_installed)||(!joy_present)) return 0;
522 if ( btn >= MAX_BUTTONS ) return 0;
526 count = joystick.buttons[btn].downcount;
527 joystick.buttons[btn].downcount = 0;
532 fix joy_get_button_down_time( int btn )
536 if ((!joy_installed)||(!joy_present)) return 0;
537 if ( btn >= MAX_BUTTONS ) return 0;
541 if (joystick.buttons[btn].state) {
542 count = timer_get_fixed_seconds() - joystick.buttons[btn].timedown;
543 joystick.buttons[btn].timedown = 0;
549 //end changed section - OE
552 void joy_get_btn_up_cnt( int *btn0, int *btn1 )
554 if ((!joy_installed)||(!joy_present)) { *btn0=*btn1=0; return; }
556 *btn0 = joystick.buttons[0].upcount;
557 joystick.buttons[0].upcount = 0;
558 *btn1 = joystick.buttons[1].upcount;
559 joystick.buttons[1].upcount = 0;
562 void joy_set_btn_values( int btn, int state, fix timedown, int downcount, int upcount )
564 joystick.buttons[btn].ignore = 1;
565 joystick.buttons[btn].state = state;
566 joystick.buttons[btn].timedown = fixmuldiv( timedown, 1193180, 65536 );
567 joystick.buttons[btn].downcount = downcount;
568 joystick.buttons[btn].upcount = upcount;