Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

416 lines
11 KiB

  1. //-----------------------------------------------------------------------------
  2. // File: diutil.cpp
  3. //
  4. // Desc: DirectInput support
  5. //
  6. // Copyright (C) 1995-1999 Microsoft Corporation. All Rights Reserved.
  7. //-----------------------------------------------------------------------------
  8. #define STRICT
  9. #include "DIUtil.h"
  10. #include "resource.h"
  11. #include "ddraw.h"
  12. #include <tchar.h>
  13. #include <stdio.h>
  14. //-----------------------------------------------------------------------------
  15. // Function prototypes
  16. //-----------------------------------------------------------------------------
  17. BOOL CALLBACK EnumSuitableDevicesCallback(LPCDIDEVICEINSTANCE lpDIDI, LPDIRECTINPUTDEVICE8A pdiDev8A, DWORD dwFlags, DWORD dwDeviceRemaining, LPVOID lpVoid);
  18. static HRESULT CreateJoystick( HWND, LPDIRECTINPUTDEVICE2 pdidDevice );
  19. BOOL CALLBACK ConfigureDevicesCallback(LPVOID lpVoid, LPVOID lpUser);
  20. //-----------------------------------------------------------------------------
  21. // Global variables
  22. //-----------------------------------------------------------------------------
  23. #define NUMBER_OF_SEMANTICS ( sizeof(g_rgGameAction) / sizeof(DIACTION) )
  24. extern LPDIRECTDRAW7 g_pDD;
  25. static DIDEVICEINSTANCE g_didiDevices[MAX_INPUT_DEVICES+1];
  26. IDirectInput8* g_pDI = NULL; // DirectInput object
  27. IDirectInputDevice8* g_pDevices[NUMBER_OF_PLAYERS][MAX_INPUT_DEVICES+1]; //IDirectInputDevice8 ptrs
  28. DWORD g_dwNumDevices[NUMBER_OF_PLAYERS];
  29. DIACTIONFORMAT diActF;
  30. //user name
  31. TCHAR UserName[UNLEN+1];
  32. LPTSTR lpUserName = UserName;
  33. extern LPDIRECTDRAWSURFACE7 g_pddsFrontBuffer;
  34. extern DWORD dwInputState[NUMBER_OF_PLAYERS];
  35. // {238D8220-7A5D-11d3-8FB2-00C04F8EC627}
  36. static const GUID g_AppGuid =
  37. { 0x238d8220, 0x7a5d, 0x11d3, { 0x8f, 0xb2, 0x0, 0xc0, 0x4f, 0x8e, 0xc6, 0x27 } };
  38. DIACTION g_rgGameAction[] = {
  39. {AXIS_UD, DIAXIS_FPS_MOVE, 0, TEXT("Forward"),},
  40. {AXIS_LR, DIAXIS_FPS_ROTATE, 0, TEXT("Rotate"),},
  41. {KEY_FIRE, DIBUTTON_FPS_FIRE, 0, TEXT("Fire"),},
  42. {KEY_THROW, DIBUTTON_FPS_WEAPONS, 0, TEXT("Change Weapon"),},
  43. {KEY_SHIELD, DIBUTTON_FPS_APPLY, 0, TEXT("Shield"),},
  44. {KEY_STOP, DIBUTTON_FPS_SELECT, 0, TEXT("Pause"),},
  45. {KEY_THROW, DIBUTTON_FPS_CROUCH, 0, TEXT("Hyper space"),},
  46. {KEY_THROW, DIBUTTON_FPS_JUMP, 0, TEXT("Launch Probe"),},
  47. {KEY_DISPLAY,DIBUTTON_FPS_DISPLAY, 0, TEXT("Display"),},
  48. {KEY_QUIT, DIBUTTON_FPS_MENU, 0, TEXT("Quit Game"),},
  49. {KEY_EDIT, DIBUTTON_FPS_DODGE, 0, TEXT("Edit Configuration"),},
  50. {KEY_LEFT, DIKEYBOARD_LEFT, 0, TEXT("Turn +"),},
  51. {KEY_RIGHT, DIKEYBOARD_RIGHT, 0, TEXT("Turn -"),},
  52. {KEY_UP, DIKEYBOARD_UP, 0, TEXT("Move Up"),},
  53. {KEY_DOWN, DIKEYBOARD_DOWN, 0, TEXT("Move Down"),},
  54. {KEY_STOP, DIKEYBOARD_S, 0, TEXT("Stop Game"),},
  55. {KEY_FIRE, DIKEYBOARD_SPACE, 0, TEXT("Shoot"),},
  56. {KEY_THROW, DIKEYBOARD_T, 0, TEXT("Throw"),},
  57. {KEY_SHIELD, DIKEYBOARD_H, 0, TEXT("Shield"),},
  58. {KEY_DISPLAY,DIKEYBOARD_D, 0, TEXT("Display"),},
  59. {KEY_QUIT, DIKEYBOARD_Q, 0, TEXT("Quit Game"),},
  60. {KEY_EDIT, DIKEYBOARD_E, 0, TEXT("Edit Configuration"),},
  61. {AXIS_LR, DIMOUSE_XAXIS, 0, TEXT("Turn"), },
  62. {AXIS_UD, DIMOUSE_YAXIS, 0, TEXT("Move"), },
  63. {KEY_FIRE, DIMOUSE_BUTTON0, 0, TEXT("Fire"), },
  64. {KEY_SHIELD, DIMOUSE_BUTTON1, 0, TEXT("Shield"),},
  65. {KEY_THROW, DIMOUSE_BUTTON2, 0, TEXT("Change Weapon"),},
  66. // {KEY_THROW, DIMOUSE_BUTTON3, 0, TEXT("Hyper Space"),},
  67. // {KEY_THROW, DIMOUSE_BUTTON4, 0, TEXT("Launch Probe"),},
  68. // {KEY_THROW, DIMOUSE_WHEEL, 0, TEXT("Next Level"),},
  69. };
  70. //-----------------------------------------------------------------------------
  71. // Name:
  72. // Desc:
  73. //-----------------------------------------------------------------------------
  74. BOOL CALLBACK EnumSuitableDevicesCallback(LPCDIDEVICEINSTANCE lpDIDI, LPDIRECTINPUTDEVICE8A pdiDev8A, DWORD dwFlags, DWORD dwDeviceRemaining, LPVOID lpVoid)
  75. {
  76. int* ppl = (int*)(lpVoid);
  77. int pl = *ppl;
  78. pdiDev8A->AddRef();
  79. g_pDevices[pl][g_dwNumDevices[pl]] = pdiDev8A;
  80. //set up the action map
  81. TCHAR Player [UNLEN+1] = "Player";
  82. TCHAR nr[10];
  83. strcat(Player, _itoa(pl+1, nr, 10));
  84. g_pDevices[pl][g_dwNumDevices[pl]]->BuildActionMap(&diActF, Player, 0);
  85. g_pDevices[pl][g_dwNumDevices[pl]]->SetActionMap(&diActF, Player, 0);
  86. g_dwNumDevices[pl]++;
  87. return TRUE;
  88. }
  89. HRESULT DIUtil_InitEnumHelper()
  90. {
  91. HRESULT hr = S_OK;
  92. int pl, dv;
  93. if (g_pDI == NULL)
  94. return E_FAIL;
  95. for (pl = 0; pl < NUMBER_OF_PLAYERS; pl++)
  96. {
  97. for (dv=0; dv<MAX_INPUT_DEVICES+1; dv++)
  98. {
  99. g_pDevices[pl][dv] = NULL;
  100. }
  101. }
  102. //DIACTIONFORMAT diActF;
  103. ZeroMemory(&diActF, sizeof(DIACTIONFORMAT));
  104. diActF.dwSize = sizeof(DIACTIONFORMAT);
  105. diActF.dwActionSize = sizeof(DIACTION);
  106. diActF.dwDataSize = NUMBER_OF_SEMANTICS * sizeof(DWORD);
  107. diActF.guidActionMap = g_AppGuid;
  108. diActF.dwGenre = DIVIRTUAL_FIGHTING_FPS;
  109. diActF.dwNumActions = NUMBER_OF_SEMANTICS;
  110. diActF.rgoAction = g_rgGameAction;
  111. diActF.lAxisMin = -100;
  112. diActF.lAxisMax = 100;
  113. diActF.dwBufferSize = 16;
  114. strcpy(diActF.tszActionMap, "TDonuts");
  115. //reset the number of devices
  116. for (pl = 0; pl < NUMBER_OF_PLAYERS; pl ++)
  117. {
  118. g_dwNumDevices[pl] = 0;
  119. }
  120. // Enumerate suitable DirectInput devices -- per player
  121. for (pl = 0; pl < NUMBER_OF_PLAYERS; pl++)
  122. {
  123. TCHAR Player [UNLEN+1] = "Player";
  124. TCHAR nr[10];
  125. strcat(Player, _itoa(pl+1, nr, 10));
  126. hr = g_pDI->EnumDevicesBySemantics(Player, &diActF, EnumSuitableDevicesCallback, (LPVOID) &pl,
  127. DIEDBSFL_THISUSER);
  128. if( FAILED(hr) )
  129. return hr;
  130. }
  131. #define UI_USER_ASSIGNMENT
  132. #ifndef UI_USER_ASSIGNMENT
  133. //hardcoding to test on my machine because no owner assignment in UI yet.
  134. //assign user 2 a device
  135. if (g_pDevices[0][2] != NULL)
  136. {
  137. g_pDevices[1][0] = g_pDevices[0][0];
  138. g_pDevices[0][0] = g_pDevices[0][g_dwNumDevices[0] - 1];
  139. g_pDevices[0][g_dwNumDevices[0] - 1] = NULL;
  140. g_dwNumDevices[0] --;
  141. g_dwNumDevices[1] ++;
  142. }
  143. #endif
  144. //draw "ships" for all users
  145. UpdateShips();
  146. return hr;
  147. }
  148. //-----------------------------------------------------------------------------
  149. // Name: Initialize()
  150. // Desc: Creates and initializes DirectInput objects
  151. //-----------------------------------------------------------------------------
  152. HRESULT DIUtil_Initialize( HWND hWnd )
  153. {
  154. HRESULT hr;
  155. // Create the base DirectInput object
  156. hr = DirectInput8Create( (HINSTANCE)(GetWindowLongPtr( hWnd,GWLP_HINSTANCE )),
  157. DIRECTINPUT_VERSION, IID_IDirectInput8, (LPVOID*) &g_pDI, NULL );
  158. if( FAILED(hr) )
  159. return hr;
  160. //get and save the user name
  161. DWORD nBuffSize = UNLEN+1;
  162. if (!GetUserName(lpUserName, &nBuffSize))
  163. {
  164. lstrcpy(lpUserName, "");
  165. }
  166. //enumerate and stuff
  167. hr = DIUtil_InitEnumHelper();
  168. if (FAILED(hr))
  169. return hr;
  170. //acquire all the devices
  171. for (int pl = 0; pl < NUMBER_OF_PLAYERS; pl++)
  172. {
  173. for (int dv = 0; dv< (int) g_dwNumDevices[pl]; dv++)
  174. {
  175. if (g_pDevices[pl][dv] != NULL)
  176. {
  177. hr = g_pDevices[pl][dv]->Acquire();
  178. }
  179. }
  180. }
  181. return S_OK;
  182. }
  183. HRESULT DIUtil_ReleaseDevices()
  184. {
  185. HRESULT hr = S_OK;
  186. for (int pl = 0; pl < NUMBER_OF_PLAYERS; pl++)
  187. {
  188. for (int dv = 0; dv< (int) g_dwNumDevices[pl]; dv++)
  189. {
  190. if (g_pDevices[pl][dv] != NULL)
  191. {
  192. g_pDevices[pl][dv]->Unacquire();
  193. hr = g_pDevices[pl][dv]->Release();
  194. g_pDevices[pl][dv] = NULL;
  195. }
  196. }
  197. }
  198. return hr;
  199. }
  200. void DIUtil_ResetState()
  201. {
  202. //unset the buttons in the persistent state
  203. for (int pl = 0; pl < NUMBER_OF_PLAYERS; pl ++)
  204. {
  205. DWORD inputState = (dwInputState[pl] & AXIS_MASK);
  206. //blow out all of the axis data
  207. inputState &= ~(KEY_RIGHT);
  208. inputState &= ~(KEY_LEFT);
  209. inputState &= ~(KEY_UP);
  210. inputState &= ~(KEY_DOWN);
  211. dwInputState[pl] = inputState;
  212. }
  213. }
  214. HRESULT DIUtil_SetUpDevices()
  215. {
  216. //first, release the devices
  217. HRESULT hr = S_OK;
  218. hr = DIUtil_ReleaseDevices();
  219. //reset the persisted state
  220. DIUtil_ResetState();
  221. //enumerate and stuff
  222. hr = DIUtil_InitEnumHelper();
  223. if (FAILED(hr))
  224. return hr;
  225. //acquire all the devices
  226. for (int pl = 0; pl < NUMBER_OF_PLAYERS; pl++)
  227. {
  228. for (int dv = 0; dv< (int) g_dwNumDevices[pl]; dv++)
  229. {
  230. if (g_pDevices[pl][dv] != NULL)
  231. {
  232. hr = g_pDevices[pl][dv]->Acquire();
  233. }
  234. }
  235. }
  236. return hr;
  237. }
  238. HRESULT DIUtil_ConfigureDevices(HWND hWnd, IUnknown FAR * pddsDIConfig, DWORD dwFlags)
  239. {
  240. HRESULT hr = S_OK;
  241. DICONFIGUREDEVICESPARAMS diconfparams;
  242. ZeroMemory(&diconfparams, sizeof(DICONFIGUREDEVICESPARAMS));
  243. // for testing, have 2 user names
  244. TCHAR Names[MAX_PATH]; //BUGBUG this could be too small
  245. CHAR* lpNames = Names;
  246. for (int pl = 0; pl < NUMBER_OF_PLAYERS; pl ++)
  247. {
  248. char buffer[10];
  249. _stprintf(lpNames, TEXT("%s%s%c"), "Player", _itoa(pl+1, buffer, 10), TEXT('\0'));
  250. if (pl < 9)
  251. {
  252. lpNames += 8;
  253. }
  254. else
  255. {
  256. //don't worry about more than 99 players
  257. lpNames += 9;
  258. }
  259. }
  260. //extra '\0'
  261. _stprintf(lpNames, TEXT("%c"), TEXT('\0'));
  262. //for testing, have 2 DIACTIONFORMATs
  263. DIACTIONFORMAT ActF[NUMBER_OF_ACTIONFORMATS];
  264. for( int i =0x0; i < NUMBER_OF_ACTIONFORMATS; i++)
  265. {
  266. ActF[i] = diActF;
  267. }
  268. //fill in all the params
  269. diconfparams.dwSize = sizeof(DICONFIGUREDEVICESPARAMS);
  270. diconfparams.dwcUsers = NUMBER_OF_PLAYERS;
  271. diconfparams.lptszUserNames = (LPTSTR)&Names;
  272. diconfparams.dwcFormats = NUMBER_OF_ACTIONFORMATS;
  273. diconfparams.lprgFormats = (LPDIACTIONFORMAT) &ActF;
  274. diconfparams.hwnd = hWnd;
  275. diconfparams.dics.dwSize = sizeof(DICOLORSET);
  276. diconfparams.lpUnkDDSTarget = pddsDIConfig;
  277. //unacquire the devices so that mouse doesn't control the game while in control panel
  278. for (int pl = 0; pl < NUMBER_OF_PLAYERS; pl++)
  279. {
  280. for (int dv = 0; dv< (int) g_dwNumDevices[pl]; dv++)
  281. {
  282. if (g_pDevices[pl][dv] != NULL)
  283. {
  284. hr = g_pDevices[pl][dv]->Unacquire();
  285. }
  286. }
  287. }
  288. //and reset the state, since no useful data is coming through anyway
  289. DIUtil_ResetState();
  290. //call ConfigureDevices with all the user names!
  291. switch (dwFlags)
  292. {
  293. case DICD_DEFAULT: default:
  294. {
  295. hr = g_pDI->ConfigureDevices((LPDICONFIGUREDEVICESCALLBACK)ConfigureDevicesCallback, &diconfparams, DICD_DEFAULT, NULL);
  296. //re-acquire the devices
  297. for (int pl = 0; pl < NUMBER_OF_PLAYERS; pl++)
  298. {
  299. for (int dv = 0; dv< (int) g_dwNumDevices[pl]; dv++)
  300. {
  301. if (g_pDevices[pl][dv] != NULL)
  302. {
  303. hr = g_pDevices[pl][dv]->Acquire();
  304. }
  305. }
  306. }
  307. break;
  308. }
  309. case DICD_EDIT:
  310. {
  311. hr = g_pDI->ConfigureDevices((LPDICONFIGUREDEVICESCALLBACK)ConfigureDevicesCallback, &diconfparams, DICD_EDIT, NULL);
  312. //re-set up the devices
  313. DIUtil_SetUpDevices();
  314. //re-set up ships
  315. UpdateShips();
  316. break;
  317. }
  318. }
  319. return hr;
  320. }
  321. //-----------------------------------------------------------------------------
  322. // Name: DIUtil_CleanupDirectInput()
  323. // Desc: Cleans up DirectInput objects
  324. //-----------------------------------------------------------------------------
  325. VOID DIUtil_CleanupDirectInput()
  326. {
  327. //release devices
  328. DIUtil_ReleaseDevices();
  329. // Release() base object
  330. if( g_pDI )
  331. {
  332. g_pDI->Release();
  333. }
  334. g_pDI = NULL;
  335. //call CoUninitialize();
  336. CoUninitialize();
  337. }