00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "config_wdxdisplay9.h"
00016 #include "dxInput9.h"
00017
00018 #define AXIS_RESOLUTION 2000 // use this many levels of resolution by default (could be more if needed and device supported it)
00019 #define AXIS_RANGE_CENTERED // if defined, axis range is centered on 0, instead of starting on 0
00020
00021 BOOL CALLBACK EnumGameCtrlsCallback( const DIDEVICEINSTANCE* pdidInstance,
00022 VOID* pContext ) {
00023 DI_DeviceInfos *pDevInfos = (DI_DeviceInfos *)pContext;
00024
00025 (*pDevInfos).push_back(*pdidInstance);
00026
00027 if(wdxdisplay_cat.is_debug())
00028 wdxdisplay_cat.debug() << "Found DevType 0x" << (void*)pdidInstance->dwDevType << ": " << pdidInstance->tszInstanceName << ": " << pdidInstance->tszProductName <<endl;
00029
00030 return DIENUM_CONTINUE;
00031 }
00032
00033 extern BOOL CALLBACK EnumObjectsCallbackJoystick(const DIDEVICEOBJECTINSTANCE* pdidoi,VOID* pContext);
00034
00035 DInput9Info::DInput9Info() {
00036 _pDInput9 = NULL;
00037 _hDInputDLL = NULL;
00038 _JoystickPollTimer = NULL;
00039 }
00040
00041 DInput9Info::~DInput9Info() {
00042 for(UINT i=0;i<_DeviceList.size();i++) {
00043 _DeviceList[i]->Unacquire();
00044 SAFE_RELEASE(_DeviceList[i]);
00045 }
00046
00047
00048
00049
00050
00051 SAFE_RELEASE(_pDInput9);
00052 if(_hDInputDLL) {
00053 FreeLibrary(_hDInputDLL);
00054 _hDInputDLL=NULL;
00055 }
00056 }
00057
00058 bool DInput9Info::InitDirectInput() {
00059 HRESULT hr;
00060
00061
00062
00063 #define DLLNAME "dinput9.dll"
00064 #define DINPUTCREATE "DirectInput9Create"
00065
00066 HINSTANCE _hDInputDLL = LoadLibrary(DLLNAME);
00067 if(_hDInputDLL == 0) {
00068 wdxdisplay_cat.fatal() << "LoadLibrary(" << DLLNAME <<") failed!, error=" << GetLastError() << endl;
00069 exit(1);
00070 }
00071
00072 typedef HRESULT (WINAPI * LPDIRECTINPUT9CREATE)(HINSTANCE hinst, DWORD dwVersion, REFIID riidltf, LPVOID *ppvOut, LPUNKNOWN punkOuter);
00073 LPDIRECTINPUT9CREATE pDInputCreate9;
00074
00075 pDInputCreate9 = (LPDIRECTINPUT9CREATE) GetProcAddress(_hDInputDLL,DINPUTCREATE);
00076 if(pDInputCreate9 == NULL) {
00077 wdxdisplay_cat.fatal() << "GetProcAddr failed for " << DINPUTCREATE << endl;
00078 exit(1);
00079 }
00080
00081
00082
00083
00084 if( FAILED( hr = (*pDInputCreate9)(GetModuleHandle(NULL), DIRECTINPUT_VERSION,
00085 IID_IDirectInput9, (VOID**)&_pDInput9, NULL ) ) ) {
00086 wdxdisplay_cat.error() << DINPUTCREATE << "failed" << D3DERRORSTRING(hr);
00087 return false;
00088 }
00089
00090
00091 if( FAILED( hr = _pDInput9->EnumDevices(DI9DEVCLASS_GAMECTRL,
00092 EnumGameCtrlsCallback,
00093 (LPVOID)&_DevInfos, DIEDFL_ATTACHEDONLY ) ) ) {
00094 wdxdisplay_cat.error() << "EnumDevices failed" << D3DERRORSTRING(hr);
00095 return false;
00096 }
00097
00098 return true;
00099 }
00100
00101 bool DInput9Info::CreateJoystickOrPad(HWND _window) {
00102 bool bFoundDev = false;
00103 UINT devnum=0;
00104 char *errstr=NULL;
00105
00106
00107 for(;devnum<_DevInfos.size();devnum++) {
00108 DWORD devType = GET_DIDEVICE_TYPE(_DevInfos[devnum].dwDevType);
00109 if((devType==DI9DEVTYPE_GAMEPAD) ||(devType==DI9DEVTYPE_JOYSTICK)) {
00110 bFoundDev=true;
00111 break;
00112 }
00113 }
00114
00115 if(!bFoundDev) {
00116 wdxdisplay_cat.error() << "Cant find an attached Joystick or GamePad!\n";
00117 return false;
00118 }
00119
00120 LPDIRECTINPUTDEVICE9 pJoyDevice;
00121
00122
00123 HRESULT hr = _pDInput9->CreateDevice(_DevInfos[devnum].guidInstance, &pJoyDevice, NULL );
00124 if(FAILED(hr)) {
00125 errstr="CreateDevice";
00126 goto handle_error;
00127 }
00128
00129 assert(pJoyDevice!=NULL);
00130 _DeviceList.push_back(pJoyDevice);
00131
00132
00133
00134
00135
00136
00137 hr = pJoyDevice->SetDataFormat(&c_dfDIJoystick2);
00138 if(FAILED(hr)) {
00139 errstr="SetDataFormat";
00140 goto handle_error;
00141 }
00142
00143
00144 DX_DECLARE_CLEAN(DIDEVCAPS, DIDevCaps);
00145 hr = pJoyDevice->GetCapabilities(&DIDevCaps);
00146 assert(SUCCEEDED(hr));
00147
00148 _DevCaps.push_back(DIDevCaps);
00149
00150 if(wdxdisplay_cat.is_debug())
00151 wdxdisplay_cat.debug() << "Joy/Pad has " << DIDevCaps.dwAxes << " Axes, " << DIDevCaps.dwButtons << " Buttons, " << DIDevCaps.dwPOVs << " POVs" << endl;
00152
00153
00154
00155 hr = pJoyDevice->SetCooperativeLevel( _window, DISCL_EXCLUSIVE | DISCL_FOREGROUND);
00156 if(FAILED(hr)) {
00157 errstr="SetCooperativeLevel";
00158 goto handle_error;
00159 }
00160
00161
00162 hr = pJoyDevice->EnumObjects(EnumObjectsCallbackJoystick, (LPVOID)pJoyDevice, DIDFT_AXIS);
00163 if(FAILED(hr)) {
00164 errstr="EnumObjects";
00165 goto handle_error;
00166 }
00167
00168 return true;
00169
00170 handle_error:
00171 wdxdisplay_cat.error() << errstr << " failed for (" << _DevInfos[devnum].tszInstanceName << ":" << _DevInfos[devnum].tszProductName << ")" << D3DERRORSTRING(hr);
00172 return false;
00173 }
00174
00175
00176
00177
00178
00179
00180
00181 BOOL CALLBACK EnumObjectsCallbackJoystick( const DIDEVICEOBJECTINSTANCE* pdidoi,
00182 VOID* pContext ) {
00183
00184 LPDIRECTINPUTDEVICE9 pJoyDevice = (LPDIRECTINPUTDEVICE9) pContext;
00185 HRESULT hr;
00186
00187
00188
00189 if( pdidoi->dwType & DIDFT_AXIS ) {
00190 DIPROPRANGE diprg;
00191 diprg.diph.dwSize = sizeof(DIPROPRANGE);
00192 diprg.diph.dwHeaderSize = sizeof(DIPROPHEADER);
00193 diprg.diph.dwHow = DIPH_BYID;
00194 diprg.diph.dwObj = pdidoi->dwType;
00195
00196 #ifdef AXIS_RANGE_CENTERED
00197 diprg.lMin = -AXIS_RESOLUTION/2;
00198 diprg.lMax = +AXIS_RESOLUTION/2;
00199 #else
00200 diprg.lMin = 0;
00201 diprg.lMax = +AXIS_RESOLUTION;
00202 #endif
00203
00204
00205 hr = pJoyDevice->SetProperty( DIPROP_RANGE, &diprg.diph);
00206 if(FAILED(hr)) {
00207 wdxdisplay_cat.error() << "SetProperty on axis failed" << D3DERRORSTRING(hr);
00208 return DIENUM_STOP;
00209 }
00210 }
00211
00212 return DIENUM_CONTINUE;
00213 }
00214
00215 bool DInput9Info::ReadJoystick(int devnum, DIJOYSTATE2 &js) {
00216 LPDIRECTINPUTDEVICE9 pJoystick = _DeviceList[devnum];
00217 assert(pJoystick!=NULL);
00218 HRESULT hr;
00219 char *errstr;
00220
00221
00222
00223 hr = pJoystick->Poll();
00224
00225 if( FAILED(hr) ) {
00226
00227
00228
00229
00230
00231 if((hr==DIERR_NOTACQUIRED)||(hr == DIERR_INPUTLOST)) {
00232 hr = pJoystick->Acquire();
00233
00234 if(FAILED(hr)) {
00235 if(wdxdisplay_cat.is_spam())
00236 wdxdisplay_cat.spam() << "Acquire failed" << D3DERRORSTRING(hr);
00237
00238
00239
00240
00241 return false;
00242 }
00243
00244 hr = pJoystick->Poll();
00245 if(FAILED(hr)) {
00246
00247 errstr = "Poll after successful Acquire failed";
00248 goto handle_error;
00249 }
00250 } else {
00251 errstr = "Unknown Poll failure";
00252 goto handle_error;
00253 }
00254 }
00255
00256
00257
00258
00259 hr = pJoystick->GetDeviceState( sizeof(DIJOYSTATE2), &js);
00260 if(FAILED(hr)) {
00261 errstr = "GetDeviceState failed";
00262 goto handle_error;
00263 }
00264
00265 return true;
00266
00267 handle_error:
00268 wdxdisplay_cat.fatal() << errstr << D3DERRORSTRING(hr);
00269 return false;
00270 }