1 /* $Id: joyhh.c,v 1.4 2004-05-20 23:10:17 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 {
74 Button_info buttons[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<MAX_BUTTONS; i++ ) {
125 joystick.buttons[i].ignore = 0;
126 joystick.buttons[i].state = 0;
127 joystick.buttons[i].timedown = 0;
128 joystick.buttons[i].downcount = 0;
129 joystick.buttons[i].upcount = 0;
135 //Begin section modified 3/7/99 - Owen Evans
137 ubyte joy_read_raw_buttons()
145 memset(&joy, 0, sizeof(joy));
146 joy.dwSize = sizeof(joy);
147 joy.dwFlags = JOY_RETURNBUTTONS | JOY_RETURNPOVCTS | JOY_USEDEADZONE;
149 if (joyGetPosEx(joystick.joyid, &joy)!=JOYERR_NOERROR)
152 for (i = 0; i < MAX_BUTTONS; i++) {
153 joystick.buttons[i].last_state = joystick.buttons[i].state;
154 joystick.buttons[i].state = (joy.dwButtons >> i) & 0x1;
155 if (!joystick.buttons[i].last_state && joystick.buttons[i].state) {
156 joystick.buttons[i].timedown = timer_get_fixed_seconds();
157 joystick.buttons[i].downcount++;
163 if (joy.dwPOV != JOY_POVCENTERED)
165 joystick.buttons[19].state = (joy.dwPOV < JOY_POVRIGHT || joy.dwPOV > JOY_POVLEFT);
166 joystick.buttons[15].state = (joy.dwPOV < JOY_POVBACKWARD && joy.dwPOV > JOY_POVFORWARD);
167 joystick.buttons[11].state = (joy.dwPOV < JOY_POVLEFT && joy.dwPOV > JOY_POVRIGHT);
168 joystick.buttons[7].state = (joy.dwPOV > JOY_POVBACKWARD);
171 return (ubyte)joy.dwButtons;
174 //end changed section - OE
177 ubyte joystick_read_raw_axis( ubyte mask, int * axis )
180 ubyte read_masks = 0;
182 axis[0] = 0; axis[1] = 0; //orulz: 1=x 2=y 3=r 4=z 5=u 6=v
183 axis[2] = 0; axis[3] = 0;
184 axis[4] = 0; axis[5] = 0; //HH: Added support for axes R and U
186 if (!joy_installed) {
190 memset(&joy, 0, sizeof(joy));
191 joy.dwSize = sizeof(joy);
192 joy.dwFlags = JOY_RETURNALL | JOY_USEDEADZONE;
193 if (joyGetPosEx(joystick.joyid, &joy)!=JOYERR_NOERROR) {
197 mask &= joystick.present_mask; // Don't read non-present channels
199 return 0; // Don't read if no stick connected.
202 if (mask & JOY_1_X_AXIS) { axis[0] = joy.dwXpos; read_masks |= JOY_1_X_AXIS; }
203 if (mask & JOY_1_Y_AXIS) { axis[1] = joy.dwYpos; read_masks |= JOY_1_Y_AXIS; }
205 // if (mask & JOY_1_Z_AXIS) { axis[2] = joy.dwZpos; read_masks |= JOY_1_Z_AXIS; }
206 // if (mask & JOY_1_POV) { axis[3] = joy.dwPOV; read_masks |= JOY_1_POV; }
207 // if (mask & JOY_1_R_AXIS) { axis[4] = joy.dwRpos; read_masks |= JOY_1_R_AXIS; }
208 // if (mask & JOY_1_U_AXIS) { axis[5] = joy.dwUpos; read_masks |= JOY_1_U_AXIS; }
209 // if (mask & JOY_1_V_AXIS) { axis[6] = joy.dwVpos; read_masks |= JOY_1_V_AXIS; }
210 if (mask & JOY_1_R_AXIS) { axis[2] = joy.dwRpos; read_masks |= JOY_1_R_AXIS; }
211 if (mask & JOY_1_Z_AXIS) { axis[3] = joy.dwZpos; read_masks |= JOY_1_Z_AXIS; }
212 if (mask & JOY_1_U_AXIS) { axis[4] = joy.dwZpos; read_masks |= JOY_1_U_AXIS; }
213 if (mask & JOY_1_V_AXIS) { axis[5] = joy.dwUpos; read_masks |= JOY_1_V_AXIS; }
218 int hh_average(int val1, int val2)
220 return abs(val1-val2)/2;
223 int joy_init(int joyid) //HH: added joyid parameter
226 int temp_axis[JOY_NUM_AXES]; //changed - orulz
229 if (FindArg("-nojoystick"))
232 atexit(joy_close); //HH: we are a bit lazy :). Errors are ignored, so we are even double-lazy :)
235 memset(&joystick, 0, sizeof(joystick));
237 for (i=0; i<MAX_BUTTONS; i++)
238 joystick.buttons[i].last_state = 0;
240 if ( !joy_installed ) {
243 joystick.max_timer = 65536;
244 joystick.read_count = 0;
245 joystick.last_value = 0;
249 joystick.present_mask = JOY_ALL_AXIS; // Assume they're all present
250 joystick.present_mask = joystick_read_raw_axis( JOY_ALL_AXIS, temp_axis );
252 if ( joystick.present_mask & 3 )
258 //HH: Main Win32 joystick initialization, incl. reading cal. stuff
260 if (joyGetDevCaps(joyid, &pjc, sizeof(pjc))!=JOYERR_NOERROR) {
264 if (joySetThreshold(joyid, pjc.wXmax/256)!=JOYERR_NOERROR) {
268 joystick.max_timer = pjc.wPeriodMax;
269 joystick.axis_min[0] = pjc.wXmin;
270 joystick.axis_min[1] = pjc.wYmin;
272 // joystick.axis_min[2] = pjc.wZmin;
273 // //HH: joystick.axis_min[3] = pov-stuff
274 // joystick.axis_min[4] = pjc.wRmin;
275 // joystick.axis_min[5] = pjc.wUmin;
276 // joystick.axis_min[6] = pjc.wVmin;
277 joystick.axis_min[2] = pjc.wRmin;
278 joystick.axis_min[3] = pjc.wZmin;
279 joystick.axis_min[4] = pjc.wUmin;
280 joystick.axis_min[5] = pjc.wVmin;
282 joystick.axis_max[0] = pjc.wXmax;
283 joystick.axis_max[1] = pjc.wYmax;
285 // joystick.axis_max[2] = pjc.wZmax;
286 // //HH: joystick.axis_max[3] = pov-stuff
287 // joystick.axis_max[4] = pjc.wRmax;
288 // joystick.axis_max[5] = pjc.wUmax;
289 // joystick.axis_max[6] = pjc.wVmax;
290 joystick.axis_max[2] = pjc.wRmax;
291 joystick.axis_max[3] = pjc.wZmax;
292 joystick.axis_max[4] = pjc.wUmax;
293 joystick.axis_max[5] = pjc.wVmax;
295 joystick.axis_center[0] = hh_average(pjc.wXmax,pjc.wXmin);
296 joystick.axis_center[1] = hh_average(pjc.wYmax,pjc.wYmin);
298 // joystick.axis_center[2] = hh_average(pjc.wZmax,pjc.wZmin);
299 // joystick.axis_center[3] = JOY_POVCENTERED;
300 // joystick.axis_center[4] = hh_average(pjc.wRmax,pjc.wRmin);
301 // joystick.axis_center[5] = hh_average(pjc.wUmax,pjc.wUmin);
302 // joystick.axis_center[6] = hh_average(pjc.wVmax,pjc.wVmin);
303 joystick.axis_center[2] = hh_average(pjc.wRmax,pjc.wRmin);
304 joystick.axis_center[3] = hh_average(pjc.wZmax,pjc.wZmin);
305 joystick.axis_center[4] = hh_average(pjc.wUmax,pjc.wUmin);
306 joystick.axis_center[5] = hh_average(pjc.wVmax,pjc.wVmin);
308 joystick.present_mask = JOY_1_X_AXIS | JOY_1_Y_AXIS;
309 if (pjc.wCaps & JOYCAPS_HASZ) joystick.present_mask |= JOY_1_Z_AXIS;
310 // if (pjc.wCaps & JOYCAPS_HASPOV) joystick.present_mask |= JOY_1_POV;
311 if (pjc.wCaps & JOYCAPS_HASR) joystick.present_mask |= JOY_1_R_AXIS;
312 if (pjc.wCaps & JOYCAPS_HASU) joystick.present_mask |= JOY_1_U_AXIS;
313 if (pjc.wCaps & JOYCAPS_HASV) joystick.present_mask |= JOY_1_V_AXIS;
321 if (!joy_installed) return;
328 joystick.present_mask = JOY_ALL_AXIS; // Assume they're all present
329 joystick.present_mask = joystick_read_raw_axis( JOY_ALL_AXIS, joystick.axis_min );
331 if ( joystick.present_mask & 3 )
339 joystick.present_mask = JOY_ALL_AXIS; // Assume they're all present
340 joystick.present_mask = joystick_read_raw_axis( JOY_ALL_AXIS, joystick.axis_max );
342 if ( joystick.present_mask & 3 )
350 joystick.present_mask = JOY_ALL_AXIS; // Assume they're all present
351 joystick.present_mask = joystick_read_raw_axis( JOY_ALL_AXIS, joystick.axis_center );
353 if ( joystick.present_mask & 3 )
359 void joy_set_cen_fake(int channel)
363 int joy_get_scaled_reading( int raw, int axn )
367 // Make sure it's calibrated properly.
368 if ( joystick.axis_center[axn] - joystick.axis_min[axn] < 128 )
369 return 0; //HH: had to increase to 128
370 if ( joystick.axis_max[axn] - joystick.axis_center[axn] < 128 )
371 return 0; //HH: had to increase to 128
373 if (!(joystick.present_mask & (1 << axn)))
374 return 0; // fixes joy config bug where it'll always set an axis you don't even have. - 2000/01/14 Matt Mueller
376 raw -= joystick.axis_center[axn];
379 d = joystick.axis_center[axn]-joystick.axis_min[axn];
381 d = joystick.axis_max[axn]-joystick.axis_center[axn];
390 if ( x < -128 ) x = -128;
391 if ( x > 127 ) x = 127;
393 //added on 4/13/99 by Victor Rachels to add deadzone control
394 d = (joy_deadzone) * 6;
395 if ((x > (-1*d)) && (x < d))
397 //end this section addition -VR
402 void joy_get_pos( int *x, int *y )
405 int axis[JOY_NUM_AXES];
407 if ((!joy_installed)||(!joy_present)) { *x=*y=0; return; }
409 flags=joystick_read_raw_axis( JOY_1_X_AXIS+JOY_1_Y_AXIS, axis );
411 if ( flags & JOY_1_X_AXIS )
412 *x = joy_get_scaled_reading( axis[0], 0 );
416 if ( flags & JOY_1_Y_AXIS )
417 *y = joy_get_scaled_reading( axis[1], 1 );
422 ubyte joy_read_stick( ubyte masks, int *axis )
425 int raw_axis[JOY_NUM_AXES];
427 if ((!joy_installed)||(!joy_present)) {
428 axis[0] = 0; axis[1] = 0;
429 axis[2] = 0; axis[3] = 0;
430 axis[4] = 0; axis[5] = 0;
434 flags=joystick_read_raw_axis( masks, raw_axis );
436 if ( flags & JOY_1_X_AXIS )
437 axis[0] = joy_get_scaled_reading( raw_axis[0], 0 );
441 if ( flags & JOY_1_Y_AXIS )
442 axis[1] = joy_get_scaled_reading( raw_axis[1], 1 );
446 if ( flags & JOY_1_R_AXIS )
447 axis[2] = joy_get_scaled_reading( raw_axis[2], 2 );
451 if ( flags & JOY_1_Z_AXIS )
452 axis[3] = joy_get_scaled_reading( raw_axis[3], 3 );
456 if ( flags & JOY_1_U_AXIS )
457 axis[4] = joy_get_scaled_reading( raw_axis[4], 4);
461 if ( flags & JOY_1_V_AXIS )
462 axis[5] = joy_get_scaled_reading( raw_axis[5], 5 );
472 if ((!joy_installed)||(!joy_present)) return 0;
474 return joy_read_raw_buttons();
478 //Begin section modified 3/7/99 - Owen Evans
480 void joy_get_btn_down_cnt( int *btn0, int *btn1 )
482 if ((!joy_installed)||(!joy_present)) { *btn0=*btn1=0; return; }
486 *btn0 = joystick.buttons[0].downcount;
487 joystick.buttons[0].downcount = 0;
488 *btn1 = joystick.buttons[1].downcount;
489 joystick.buttons[1].downcount = 0;
492 int joy_get_button_state( int btn )
494 if ((!joy_installed)||(!joy_present)) return 0;
495 if ( btn >= MAX_BUTTONS ) return 0;
499 return joystick.buttons[btn].state;
502 int joy_get_button_up_cnt( int btn )
506 if ((!joy_installed)||(!joy_present)) return 0;
508 if ( btn >= MAX_BUTTONS ) return 0;
510 count = joystick.buttons[btn].upcount;
511 joystick.buttons[btn].upcount = 0;
516 int joy_get_button_down_cnt( int btn )
520 if ((!joy_installed)||(!joy_present)) return 0;
521 if ( btn >= MAX_BUTTONS ) return 0;
525 count = joystick.buttons[btn].downcount;
526 joystick.buttons[btn].downcount = 0;
531 fix joy_get_button_down_time( int btn )
535 if ((!joy_installed)||(!joy_present)) return 0;
536 if ( btn >= MAX_BUTTONS ) return 0;
540 if (joystick.buttons[btn].state) {
541 count = timer_get_fixed_seconds() - joystick.buttons[btn].timedown;
542 joystick.buttons[btn].timedown = 0;
548 //end changed section - OE
551 void joy_get_btn_up_cnt( int *btn0, int *btn1 )
553 if ((!joy_installed)||(!joy_present)) { *btn0=*btn1=0; return; }
555 *btn0 = joystick.buttons[0].upcount;
556 joystick.buttons[0].upcount = 0;
557 *btn1 = joystick.buttons[1].upcount;
558 joystick.buttons[1].upcount = 0;
561 void joy_set_btn_values( int btn, int state, fix timedown, int downcount, int upcount )
563 joystick.buttons[btn].ignore = 1;
564 joystick.buttons[btn].state = state;
565 joystick.buttons[btn].timedown = fixmuldiv( timedown, 1193180, 65536 );
566 joystick.buttons[btn].downcount = downcount;
567 joystick.buttons[btn].upcount = upcount;