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