//JOYC.C for D1_3Dfx and D1OpenGL //D1_3Dfx is a Win32 executable using Glide and DirectX 3 //D1OpenGL is a Win32 executable using OpenGL and DirectX 3 //This joystick code should run on DirectInput 2 and higher //We are not using DirectX 5 for now, since we want to stay compatible to the HH-loved Windows NT :). //So ForceFeedback is not supported //Notes: // 1) Windows DirectX supports up to 7 axes, D1/DOS only 4, so we needed to increase the number to 7 at several points // Also JOY_ALL_AXIS must be (1+2+4+8+16+32+64) in JOY.H file // 2) Windows DirectX supports up to 32 buttons. So far we however only support 4. Adding support for more should be however easily possible. // 3) _enable and _disable are not needed // 4) joy_bogus_reading is not needed, so all calls are just removed // 5) The joystick query goes over the DirectInputs function // MMRESULT joyGetPosEx(UINT uJoyID, LPJOYINFOEX pji); // All functions reading over BIOS, including the ASM code are removed /* THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. */ /* Modifications by Heiko Herrmann Later modified by Owen Evans to work with D1X (3/7/99) */ #define _WIN32_OS //HH #include //HH #include //HH #include #include #include "types.h" #include "joy.h" #include "timer.h" #include "args.h" #define my_hwnd g_hWnd // D1X compatibility extern HWND g_hWnd; char joy_installed = 0; char joy_present = 0; typedef struct Button_info { ubyte ignore; ubyte state; ubyte last_state; int timedown; ubyte downcount; ubyte upcount; } Button_info; typedef struct Joy_info { int joyid; ubyte present_mask; ubyte slow_read; int max_timer; int read_count; ubyte last_value; Button_info buttons[MAX_BUTTONS]; int axis_min[JOY_NUM_AXES]; //changed int axis_center[JOY_NUM_AXES]; //changed --orulz int axis_max[JOY_NUM_AXES]; //changed } Joy_info; Joy_info joystick; int joy_deadzone = 0; void joy_get_cal_vals(int *axis_min, int *axis_center, int *axis_max) { int i; for (i=0; iignore) { if ( i < (MAX_BUTTONS-4) ) state = (value >> i) & 1; else state = 0; if ( button->last_state == state ) { if (state) { button->timedown += time_diff; //ticks_this_time; } } else { if (state) { button->downcount += state; button->state = 1; } else { button->upcount += button->state; button->state = 0; } button->last_state = state; } } } time_last = time_now; return 0; } //Begin section modified 3/7/99 - Owen Evans ubyte joy_read_raw_buttons() { JOYINFOEX joy; int i; if (!joy_present) return 0; memset(&joy, 0, sizeof(joy)); joy.dwSize = sizeof(joy); joy.dwFlags = JOY_RETURNBUTTONS | JOY_RETURNPOVCTS | JOY_USEDEADZONE; if (joyGetPosEx(joystick.joyid, &joy)!=JOYERR_NOERROR) return 0; for (i = 0; i < MAX_BUTTONS; i++) { joystick.buttons[i].last_state = joystick.buttons[i].state; joystick.buttons[i].state = (joy.dwButtons >> i) & 0x1; if (!joystick.buttons[i].last_state && joystick.buttons[i].state) { joystick.buttons[i].timedown = timer_get_fixed_seconds(); joystick.buttons[i].downcount++; } } /* Hat stuff */ if (joy.dwPOV != JOY_POVCENTERED) { joystick.buttons[19].state = (joy.dwPOV < JOY_POVRIGHT || joy.dwPOV > JOY_POVLEFT); joystick.buttons[15].state = (joy.dwPOV < JOY_POVBACKWARD && joy.dwPOV > JOY_POVFORWARD); joystick.buttons[11].state = (joy.dwPOV < JOY_POVLEFT && joy.dwPOV > JOY_POVRIGHT); joystick.buttons[7].state = (joy.dwPOV > JOY_POVBACKWARD); } return (ubyte)joy.dwButtons; } //end changed section - OE ubyte joystick_read_raw_axis( ubyte mask, int * axis ) { JOYINFOEX joy; ubyte read_masks = 0; axis[0] = 0; axis[1] = 0; //orulz: 1=x 2=y 3=r 4=z 5=u 6=v axis[2] = 0; axis[3] = 0; axis[4] = 0; axis[5] = 0; //HH: Added support for axes R and U if (!joy_installed) { return 0; } memset(&joy, 0, sizeof(joy)); joy.dwSize = sizeof(joy); joy.dwFlags = JOY_RETURNALL | JOY_USEDEADZONE; if (joyGetPosEx(joystick.joyid, &joy)!=JOYERR_NOERROR) { return 0; } mask &= joystick.present_mask; // Don't read non-present channels if ( mask==0 ) { return 0; // Don't read if no stick connected. } if (mask & JOY_1_X_AXIS) { axis[0] = joy.dwXpos; read_masks |= JOY_1_X_AXIS; } if (mask & JOY_1_Y_AXIS) { axis[1] = joy.dwYpos; read_masks |= JOY_1_Y_AXIS; } //orulz: // if (mask & JOY_1_Z_AXIS) { axis[2] = joy.dwZpos; read_masks |= JOY_1_Z_AXIS; } // if (mask & JOY_1_POV) { axis[3] = joy.dwPOV; read_masks |= JOY_1_POV; } // if (mask & JOY_1_R_AXIS) { axis[4] = joy.dwRpos; read_masks |= JOY_1_R_AXIS; } // if (mask & JOY_1_U_AXIS) { axis[5] = joy.dwUpos; read_masks |= JOY_1_U_AXIS; } // if (mask & JOY_1_V_AXIS) { axis[6] = joy.dwVpos; read_masks |= JOY_1_V_AXIS; } if (mask & JOY_1_R_AXIS) { axis[2] = joy.dwRpos; read_masks |= JOY_1_R_AXIS; } if (mask & JOY_1_Z_AXIS) { axis[3] = joy.dwZpos; read_masks |= JOY_1_Z_AXIS; } if (mask & JOY_1_U_AXIS) { axis[4] = joy.dwZpos; read_masks |= JOY_1_U_AXIS; } if (mask & JOY_1_V_AXIS) { axis[5] = joy.dwUpos; read_masks |= JOY_1_V_AXIS; } return read_masks; } int hh_average(int val1, int val2) { return abs(val1-val2)/2; } int joy_init(int joyid) //HH: added joyid parameter { int i; int temp_axis[JOY_NUM_AXES]; //changed - orulz JOYCAPS pjc; if (FindArg( "-nojoystick" )) return 0; atexit(joy_close); //HH: we are a bit lazy :). Errors are ignored, so we are even double-lazy :) joy_flush(); memset(&joystick, 0, sizeof(joystick)); for (i=0; i 127 ) x = 127; //added on 4/13/99 by Victor Rachels to add deadzone control d = (joy_deadzone) * 6; if ((x > (-1*d)) && (x < d)) x = 0; //end this section addition -VR return x; } void joy_get_pos( int *x, int *y ) { ubyte flags; int axis[JOY_NUM_AXES]; if ((!joy_installed)||(!joy_present)) { *x=*y=0; return; } flags=joystick_read_raw_axis( JOY_1_X_AXIS+JOY_1_Y_AXIS, axis ); if ( flags & JOY_1_X_AXIS ) *x = joy_get_scaled_reading( axis[0], 0 ); else *x = 0; if ( flags & JOY_1_Y_AXIS ) *y = joy_get_scaled_reading( axis[1], 1 ); else *y = 0; } ubyte joy_read_stick( ubyte masks, int *axis ) { ubyte flags; int raw_axis[JOY_NUM_AXES]; if ((!joy_installed)||(!joy_present)) { axis[0] = 0; axis[1] = 0; axis[2] = 0; axis[3] = 0; axis[4] = 0; axis[5] = 0; return 0; } flags=joystick_read_raw_axis( masks, raw_axis ); if ( flags & JOY_1_X_AXIS ) axis[0] = joy_get_scaled_reading( raw_axis[0], 0 ); else axis[0] = 0; if ( flags & JOY_1_Y_AXIS ) axis[1] = joy_get_scaled_reading( raw_axis[1], 1 ); else axis[1] = 0; if ( flags & JOY_1_R_AXIS ) axis[2] = joy_get_scaled_reading( raw_axis[2], 2 ); else axis[2] = 0; if ( flags & JOY_1_Z_AXIS ) axis[3] = joy_get_scaled_reading( raw_axis[3], 3 ); else axis[3] = 0; if ( flags & JOY_1_U_AXIS ) axis[4] = joy_get_scaled_reading( raw_axis[4], 4); else axis[4] = 0; if ( flags & JOY_1_V_AXIS ) axis[5] = joy_get_scaled_reading( raw_axis[5], 5 ); else axis[5] = 0; return flags; } int joy_get_btns() { if ((!joy_installed)||(!joy_present)) return 0; return joy_read_raw_buttons(); } //Begin section modified 3/7/99 - Owen Evans void joy_get_btn_down_cnt( int *btn0, int *btn1 ) { if ((!joy_installed)||(!joy_present)) { *btn0=*btn1=0; return; } joy_get_btns(); *btn0 = joystick.buttons[0].downcount; joystick.buttons[0].downcount = 0; *btn1 = joystick.buttons[1].downcount; joystick.buttons[1].downcount = 0; } int joy_get_button_state( int btn ) { if ((!joy_installed)||(!joy_present)) return 0; if ( btn >= MAX_BUTTONS ) return 0; joy_get_btns(); return joystick.buttons[btn].state; } int joy_get_button_up_cnt( int btn ) { int count; if ((!joy_installed)||(!joy_present)) return 0; if ( btn >= MAX_BUTTONS ) return 0; count = joystick.buttons[btn].upcount; joystick.buttons[btn].upcount = 0; return count; } int joy_get_button_down_cnt( int btn ) { int count; if ((!joy_installed)||(!joy_present)) return 0; if ( btn >= MAX_BUTTONS ) return 0; joy_get_btns(); count = joystick.buttons[btn].downcount; joystick.buttons[btn].downcount = 0; return count; } fix joy_get_button_down_time( int btn ) { fix count; if ((!joy_installed)||(!joy_present)) return 0; if ( btn >= MAX_BUTTONS ) return 0; joy_get_btns(); if (joystick.buttons[btn].state) { count = timer_get_fixed_seconds() - joystick.buttons[btn].timedown; joystick.buttons[btn].timedown = 0; } else count = 0; return count; } //end changed section - OE void joy_get_btn_up_cnt( int *btn0, int *btn1 ) { if ((!joy_installed)||(!joy_present)) { *btn0=*btn1=0; return; } *btn0 = joystick.buttons[0].upcount; joystick.buttons[0].upcount = 0; *btn1 = joystick.buttons[1].upcount; joystick.buttons[1].upcount = 0; } void joy_set_btn_values( int btn, int state, fix timedown, int downcount, int upcount ) { joystick.buttons[btn].ignore = 1; joystick.buttons[btn].state = state; joystick.buttons[btn].timedown = fixmuldiv( timedown, 1193180, 65536 ); joystick.buttons[btn].downcount = downcount; joystick.buttons[btn].upcount = upcount; } void joy_poll() { }