input.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821
  1. //
  2. // Copyright (c) 2009, Wei Mingzhi <whistler_wmz@users.sf.net>.
  3. // Portions Copyright (c) 2009, netwan.
  4. //
  5. // All rights reserved.
  6. //
  7. // This file is part of SDLPAL.
  8. //
  9. // SDLPAL is free software: you can redistribute it and/or modify
  10. // it under the terms of the GNU General Public License as published by
  11. // the Free Software Foundation, either version 3 of the License, or
  12. // (at your option) any later version.
  13. //
  14. // This program is distributed in the hope that it will be useful,
  15. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  17. // GNU General Public License for more details.
  18. //
  19. // You should have received a copy of the GNU General Public License
  20. // along with this program. If not, see <http://www.gnu.org/licenses/>.
  21. //
  22. #include "main.h"
  23. #include <math.h>
  24. PALINPUTSTATE g_InputState;
  25. static SDL_Joystick *g_pJoy = NULL;
  26. BOOL g_fUseJoystick = TRUE;
  27. #if defined(GPH)
  28. #define MIN_DEADZONE -16384
  29. #define MAX_DEADZONE 16384
  30. #endif
  31. static VOID
  32. PAL_KeyboardEventFilter(
  33. const SDL_Event *lpEvent
  34. )
  35. /*++
  36. Purpose:
  37. Handle keyboard events.
  38. Parameters:
  39. [IN] lpEvent - pointer to the event.
  40. Return value:
  41. None.
  42. --*/
  43. {
  44. switch (lpEvent->type)
  45. {
  46. case SDL_KEYDOWN:
  47. //
  48. // Pressed a key
  49. //
  50. if (lpEvent->key.keysym.mod & KMOD_ALT)
  51. {
  52. if (lpEvent->key.keysym.sym == SDLK_RETURN)
  53. {
  54. //
  55. // Pressed Alt+Enter (toggle fullscreen)...
  56. //
  57. VIDEO_ToggleFullscreen();
  58. return;
  59. }
  60. else if (lpEvent->key.keysym.sym == SDLK_F4)
  61. {
  62. //
  63. // Pressed Alt+F4 (Exit program)...
  64. //
  65. PAL_Shutdown();
  66. exit(0);
  67. }
  68. }
  69. switch (lpEvent->key.keysym.sym)
  70. {
  71. #ifdef __SYMBIAN32__
  72. //
  73. // Symbian-specific stuff
  74. //
  75. case SDLK_0:
  76. VIDEO_ToggleScaleScreen();
  77. break;
  78. case SDLK_1:
  79. SOUND_AdjustVolume(0);
  80. break;
  81. case SDLK_3:
  82. SOUND_AdjustVolume(1);
  83. break;
  84. #endif
  85. case SDLK_UP:
  86. case SDLK_KP8:
  87. g_InputState.prevdir = (gpGlobals->fInBattle ? kDirUnknown : g_InputState.dir);
  88. g_InputState.dir = kDirNorth;
  89. g_InputState.dwKeyPress |= kKeyUp;
  90. break;
  91. case SDLK_DOWN:
  92. case SDLK_KP2:
  93. g_InputState.prevdir = (gpGlobals->fInBattle ? kDirUnknown : g_InputState.dir);
  94. g_InputState.dir = kDirSouth;
  95. g_InputState.dwKeyPress |= kKeyDown;
  96. break;
  97. case SDLK_LEFT:
  98. case SDLK_KP4:
  99. g_InputState.prevdir = (gpGlobals->fInBattle ? kDirUnknown : g_InputState.dir);
  100. g_InputState.dir = kDirWest;
  101. g_InputState.dwKeyPress |= kKeyLeft;
  102. break;
  103. case SDLK_RIGHT:
  104. case SDLK_KP6:
  105. g_InputState.prevdir = (gpGlobals->fInBattle ? kDirUnknown : g_InputState.dir);
  106. g_InputState.dir = kDirEast;
  107. g_InputState.dwKeyPress |= kKeyRight;
  108. break;
  109. #if defined(DINGOO)
  110. case SDLK_SPACE:
  111. g_InputState.dwKeyPress = kKeyMenu;
  112. break;
  113. case SDLK_LCTRL:
  114. g_InputState.dwKeyPress = kKeySearch;
  115. break;
  116. #else
  117. case SDLK_ESCAPE:
  118. case SDLK_INSERT:
  119. case SDLK_LALT:
  120. case SDLK_RALT:
  121. case SDLK_KP0:
  122. g_InputState.dwKeyPress |= kKeyMenu;
  123. break;
  124. case SDLK_RETURN:
  125. case SDLK_SPACE:
  126. case SDLK_KP_ENTER:
  127. case SDLK_LCTRL:
  128. g_InputState.dwKeyPress |= kKeySearch;
  129. break;
  130. case SDLK_PAGEUP:
  131. case SDLK_KP9:
  132. g_InputState.dwKeyPress |= kKeyPgUp;
  133. break;
  134. case SDLK_PAGEDOWN:
  135. case SDLK_KP3:
  136. g_InputState.dwKeyPress |= kKeyPgDn;
  137. break;
  138. case SDLK_7: //7 for mobile device
  139. case SDLK_r:
  140. g_InputState.dwKeyPress |= kKeyRepeat;
  141. break;
  142. case SDLK_2: //2 for mobile device
  143. case SDLK_a:
  144. g_InputState.dwKeyPress |= kKeyAuto;
  145. break;
  146. case SDLK_d:
  147. g_InputState.dwKeyPress |= kKeyDefend;
  148. break;
  149. case SDLK_e:
  150. g_InputState.dwKeyPress |= kKeyUseItem;
  151. break;
  152. case SDLK_w:
  153. g_InputState.dwKeyPress |= kKeyThrowItem;
  154. break;
  155. case SDLK_q:
  156. g_InputState.dwKeyPress |= kKeyFlee;
  157. break;
  158. case SDLK_s:
  159. g_InputState.dwKeyPress |= kKeyStatus;
  160. break;
  161. case SDLK_f:
  162. case SDLK_5: // 5 for mobile device
  163. g_InputState.dwKeyPress |= kKeyForce;
  164. break;
  165. case SDLK_HASH: //# for mobile device
  166. case SDLK_p:
  167. VIDEO_SaveScreenshot();
  168. break;
  169. #endif
  170. default:
  171. break;
  172. }
  173. break;
  174. case SDL_KEYUP:
  175. //
  176. // Released a key
  177. //
  178. switch (lpEvent->key.keysym.sym)
  179. {
  180. case SDLK_UP:
  181. case SDLK_KP8:
  182. if (g_InputState.dir == kDirNorth)
  183. {
  184. g_InputState.dir = g_InputState.prevdir;
  185. }
  186. g_InputState.prevdir = kDirUnknown;
  187. break;
  188. case SDLK_DOWN:
  189. case SDLK_KP2:
  190. if (g_InputState.dir == kDirSouth)
  191. {
  192. g_InputState.dir = g_InputState.prevdir;
  193. }
  194. g_InputState.prevdir = kDirUnknown;
  195. break;
  196. case SDLK_LEFT:
  197. case SDLK_KP4:
  198. if (g_InputState.dir == kDirWest)
  199. {
  200. g_InputState.dir = g_InputState.prevdir;
  201. }
  202. g_InputState.prevdir = kDirUnknown;
  203. break;
  204. case SDLK_RIGHT:
  205. case SDLK_KP6:
  206. if (g_InputState.dir == kDirEast)
  207. {
  208. g_InputState.dir = g_InputState.prevdir;
  209. }
  210. g_InputState.prevdir = kDirUnknown;
  211. break;
  212. default:
  213. break;
  214. }
  215. break;
  216. }
  217. }
  218. static VOID
  219. PAL_MouseEventFilter(
  220. const SDL_Event *lpEvent
  221. )
  222. /*++
  223. Purpose:
  224. Handle mouse events.
  225. Parameters:
  226. [IN] lpEvent - pointer to the event.
  227. Return value:
  228. None.
  229. --*/
  230. {
  231. #ifdef PAL_HAS_MOUSE
  232. static short hitTest = 0; // Double click detect;
  233. const SDL_VideoInfo *vi;
  234. double screenWidth, gridWidth;
  235. double screenHeight, gridHeight;
  236. double mx, my;
  237. double thumbx;
  238. double thumby;
  239. INT gridIndex;
  240. BOOL isLeftMouseDBClick = FALSE;
  241. BOOL isLeftMouseClick = FALSE;
  242. BOOL isRightMouseClick = FALSE;
  243. static INT lastReleaseButtonTime, lastPressButtonTime, betweenTime;
  244. static INT lastPressx = 0;
  245. static INT lastPressy = 0;
  246. static INT lastReleasex = 0;
  247. static INT lastReleasey = 0;
  248. if (lpEvent->type!= SDL_MOUSEBUTTONDOWN && lpEvent->type != SDL_MOUSEBUTTONUP)
  249. return;
  250. vi = SDL_GetVideoInfo();
  251. screenWidth = vi->current_w;
  252. screenHeight = vi->current_h;
  253. gridWidth = screenWidth / 3;
  254. gridHeight = screenHeight / 3;
  255. mx = lpEvent->button.x;
  256. my = lpEvent->button.y;
  257. thumbx = ceil(mx / gridWidth);
  258. thumby = floor(my / gridHeight);
  259. gridIndex = thumbx + thumby * 3 - 1;
  260. switch (lpEvent->type)
  261. {
  262. case SDL_MOUSEBUTTONDOWN:
  263. lastPressButtonTime = SDL_GetTicks();
  264. lastPressx = lpEvent->button.x;
  265. lastPressy = lpEvent->button.y;
  266. switch (gridIndex)
  267. {
  268. case 2:
  269. g_InputState.prevdir = g_InputState.dir;
  270. g_InputState.dir = kDirNorth;
  271. break;
  272. case 6:
  273. g_InputState.prevdir = g_InputState.dir;
  274. g_InputState.dir = kDirSouth;
  275. break;
  276. case 0:
  277. g_InputState.prevdir = g_InputState.dir;
  278. g_InputState.dir = kDirWest;
  279. break;
  280. case 8:
  281. g_InputState.prevdir = g_InputState.dir;
  282. g_InputState.dir = kDirEast;
  283. break;
  284. case 1:
  285. //g_InputState.prevdir = g_InputState.dir;
  286. //g_InputState.dir = kDirNorth;
  287. g_InputState.dwKeyPress |= kKeyUp;
  288. break;
  289. case 7:
  290. //g_InputState.prevdir = g_InputState.dir;
  291. //g_InputState.dir = kDirSouth;
  292. g_InputState.dwKeyPress |= kKeyDown;
  293. break;
  294. case 3:
  295. //g_InputState.prevdir = g_InputState.dir;
  296. //g_InputState.dir = kDirWest;
  297. g_InputState.dwKeyPress |= kKeyLeft;
  298. break;
  299. case 5:
  300. //g_InputState.prevdir = g_InputState.dir;
  301. //g_InputState.dir = kDirEast;
  302. g_InputState.dwKeyPress |= kKeyRight;
  303. break;
  304. }
  305. break;
  306. case SDL_MOUSEBUTTONUP:
  307. lastReleaseButtonTime = SDL_GetTicks();
  308. lastReleasex = lpEvent->button.x;
  309. lastReleasey = lpEvent->button.y;
  310. hitTest ++;
  311. if (abs(lastPressx - lastReleasex) < 25 &&
  312. abs(lastPressy - lastReleasey) < 25)
  313. {
  314. betweenTime = lastReleaseButtonTime - lastPressButtonTime;
  315. if (betweenTime >500)
  316. {
  317. isRightMouseClick = TRUE;
  318. }
  319. else if (betweenTime >=0)
  320. {
  321. if((betweenTime < 100) && (hitTest >= 2))
  322. {
  323. isLeftMouseClick = TRUE;
  324. hitTest = 0;
  325. }
  326. else
  327. {
  328. isLeftMouseClick = TRUE;
  329. if(betweenTime > 100)
  330. {
  331. hitTest = 0;
  332. }
  333. }
  334. }
  335. }
  336. switch (gridIndex)
  337. {
  338. case 2:
  339. if( isLeftMouseDBClick )
  340. {
  341. SOUND_AdjustVolume(1);
  342. break;
  343. }
  344. case 6:
  345. case 0:
  346. if( isLeftMouseDBClick )
  347. {
  348. SOUND_AdjustVolume(0);
  349. break;
  350. }
  351. case 7:
  352. if (isRightMouseClick) //repeat attack
  353. {
  354. g_InputState.dwKeyPress |= kKeyRepeat;
  355. break;
  356. }
  357. case 8:
  358. g_InputState.dir = kDirUnknown;
  359. g_InputState.prevdir = kDirUnknown;
  360. break;
  361. case 1:
  362. if( isRightMouseClick )
  363. {
  364. g_InputState.dwKeyPress |= kKeyForce;
  365. }
  366. break;
  367. case 3:
  368. if( isRightMouseClick )
  369. {
  370. g_InputState.dwKeyPress |= kKeyAuto;
  371. }
  372. break;
  373. case 5:
  374. if( isRightMouseClick )
  375. {
  376. g_InputState.dwKeyPress |= kKeyDefend;
  377. }
  378. break;
  379. case 4:
  380. if (isRightMouseClick) // menu
  381. {
  382. g_InputState.dwKeyPress |= kKeyMenu;
  383. }
  384. else if (isLeftMouseClick) // search
  385. {
  386. g_InputState.dwKeyPress |= kKeySearch;
  387. }
  388. break;
  389. }
  390. break;
  391. }
  392. #endif
  393. }
  394. static VOID
  395. PAL_JoystickEventFilter(
  396. const SDL_Event *lpEvent
  397. )
  398. /*++
  399. Purpose:
  400. Handle joystick events.
  401. Parameters:
  402. [IN] lpEvent - pointer to the event.
  403. Return value:
  404. None.
  405. --*/
  406. {
  407. #ifdef PAL_HAS_JOYSTICKS
  408. switch (lpEvent->type)
  409. {
  410. #if defined (GEKKO)
  411. case SDL_JOYHATMOTION:
  412. switch (lpEvent->jhat.value)
  413. {
  414. case SDL_HAT_LEFT:
  415. g_InputState.prevdir = (gpGlobals->fInBattle ? kDirUnknown : g_InputState.dir);
  416. g_InputState.dir = kDirWest;
  417. g_InputState.dwKeyPress = kKeyLeft;
  418. break;
  419. case SDL_HAT_RIGHT:
  420. g_InputState.prevdir = (gpGlobals->fInBattle ? kDirUnknown : g_InputState.dir);
  421. g_InputState.dir = kDirEast;
  422. g_InputState.dwKeyPress = kKeyRight;
  423. break;
  424. case SDL_HAT_UP:
  425. g_InputState.prevdir = (gpGlobals->fInBattle ? kDirUnknown : g_InputState.dir);
  426. g_InputState.dir = kDirNorth;
  427. g_InputState.dwKeyPress = kKeyUp;
  428. break;
  429. case SDL_HAT_DOWN:
  430. g_InputState.prevdir = (gpGlobals->fInBattle ? kDirUnknown : g_InputState.dir);
  431. g_InputState.dir = kDirSouth;
  432. g_InputState.dwKeyPress = kKeyDown;
  433. break;
  434. }
  435. break;
  436. #else
  437. case SDL_JOYAXISMOTION:
  438. //
  439. // Moved an axis on joystick
  440. //
  441. switch (lpEvent->jaxis.axis)
  442. {
  443. case 0:
  444. //
  445. // X axis
  446. //
  447. #if defined(GPH)
  448. if (lpEvent->jaxis.value > MAX_DEADZONE) {
  449. g_InputState.prevdir = (gpGlobals->fInBattle ? kDirUnknown : g_InputState.dir);
  450. g_InputState.dir = kDirEast;
  451. g_InputState.dwKeyPress = kKeyRight;
  452. } else if (lpEvent->jaxis.value < MIN_DEADZONE) {
  453. g_InputState.prevdir = (gpGlobals->fInBattle ? kDirUnknown : g_InputState.dir);
  454. g_InputState.dir = kDirWest;
  455. g_InputState.dwKeyPress = kKeyLeft;
  456. } else {
  457. g_InputState.dir = kDirUnknown;
  458. }
  459. #else
  460. if (lpEvent->jaxis.value > 20000)
  461. {
  462. if (g_InputState.dir != kDirEast)
  463. {
  464. g_InputState.dwKeyPress |= kKeyRight;
  465. }
  466. g_InputState.prevdir = g_InputState.dir;
  467. g_InputState.dir = kDirEast;
  468. }
  469. else if (lpEvent->jaxis.value < -20000)
  470. {
  471. if (g_InputState.dir != kDirWest)
  472. {
  473. g_InputState.dwKeyPress |= kKeyLeft;
  474. }
  475. g_InputState.prevdir = g_InputState.dir;
  476. g_InputState.dir = kDirWest;
  477. }
  478. else
  479. {
  480. if (g_InputState.prevdir != kDirEast &&
  481. g_InputState.prevdir != kDirWest)
  482. {
  483. g_InputState.dir = g_InputState.prevdir;
  484. }
  485. g_InputState.prevdir = kDirUnknown;
  486. }
  487. #endif
  488. break;
  489. case 1:
  490. //
  491. // Y axis
  492. //
  493. #if defined(GPH)
  494. if (lpEvent->jaxis.value > MAX_DEADZONE) {
  495. g_InputState.prevdir = (gpGlobals->fInBattle ? kDirUnknown : g_InputState.dir);
  496. g_InputState.dir = kDirSouth;
  497. g_InputState.dwKeyPress = kKeyDown;
  498. } else if (lpEvent->jaxis.value < MIN_DEADZONE) {
  499. g_InputState.prevdir = (gpGlobals->fInBattle ? kDirUnknown : g_InputState.dir);
  500. g_InputState.dir = kDirNorth;
  501. g_InputState.dwKeyPress = kKeyUp;
  502. } else {
  503. g_InputState.dir = kDirUnknown;
  504. }
  505. #else
  506. if (lpEvent->jaxis.value > 20000)
  507. {
  508. if (g_InputState.dir != kDirSouth)
  509. {
  510. g_InputState.dwKeyPress |= kKeyDown;
  511. }
  512. g_InputState.prevdir = g_InputState.dir;
  513. g_InputState.dir = kDirSouth;
  514. }
  515. else if (lpEvent->jaxis.value < -20000)
  516. {
  517. if (g_InputState.dir != kDirNorth)
  518. {
  519. g_InputState.dwKeyPress |= kKeyUp;
  520. }
  521. g_InputState.prevdir = g_InputState.dir;
  522. g_InputState.dir = kDirNorth;
  523. }
  524. else
  525. {
  526. if (g_InputState.prevdir != kDirNorth &&
  527. g_InputState.prevdir != kDirSouth)
  528. {
  529. g_InputState.dir = g_InputState.prevdir;
  530. }
  531. g_InputState.prevdir = kDirUnknown;
  532. }
  533. #endif
  534. break;
  535. }
  536. break;
  537. #endif
  538. case SDL_JOYBUTTONDOWN:
  539. //
  540. // Pressed the joystick button
  541. //
  542. #if defined(GPH)
  543. switch (lpEvent->jbutton.button)
  544. {
  545. #if defined(GP2XWIZ)
  546. case 14:
  547. #elif defined(CAANOO)
  548. case 3:
  549. #endif
  550. g_InputState.dwKeyPress = kKeyMenu;
  551. break;
  552. #if defined(GP2XWIZ)
  553. case 13:
  554. #elif defined(CAANOO)
  555. case 2:
  556. #endif
  557. g_InputState.dwKeyPress = kKeySearch;
  558. break;
  559. #else
  560. #if defined(GEKKO)
  561. switch (lpEvent->jbutton.button)
  562. {
  563. case 2:
  564. g_InputState.dwKeyPress |= kKeyMenu;
  565. break;
  566. case 3:
  567. g_InputState.dwKeyPress |= kKeySearch;
  568. break;
  569. #else
  570. switch (lpEvent->jbutton.button & 1)
  571. {
  572. case 0:
  573. g_InputState.dwKeyPress |= kKeyMenu;
  574. break;
  575. case 1:
  576. g_InputState.dwKeyPress |= kKeySearch;
  577. break;
  578. #endif
  579. #endif
  580. }
  581. break;
  582. }
  583. #endif
  584. }
  585. #if SDL_MAJOR_VERSION == 1 && SDL_MINOR_VERSION <= 2
  586. static int SDLCALL
  587. PAL_EventFilter(
  588. const SDL_Event *lpEvent
  589. )
  590. #else
  591. static int SDLCALL
  592. PAL_EventFilter(
  593. void *userdata,
  594. const SDL_Event *lpEvent
  595. )
  596. #endif
  597. /*++
  598. Purpose:
  599. SDL event filter function. A filter to process all events.
  600. Parameters:
  601. [IN] lpEvent - pointer to the event.
  602. Return value:
  603. 1 = the event will be added to the internal queue.
  604. 0 = the event will be dropped from the queue.
  605. --*/
  606. {
  607. switch (lpEvent->type)
  608. {
  609. case SDL_VIDEORESIZE:
  610. //
  611. // resized the window
  612. //
  613. VIDEO_Resize(lpEvent->resize.w, lpEvent->resize.h);
  614. break;
  615. case SDL_QUIT:
  616. //
  617. // clicked on the close button of the window. Quit immediately.
  618. //
  619. PAL_Shutdown();
  620. exit(0);
  621. }
  622. PAL_KeyboardEventFilter(lpEvent);
  623. PAL_MouseEventFilter(lpEvent);
  624. PAL_JoystickEventFilter(lpEvent);
  625. //
  626. // All events are handled here; don't put anything to the internal queue
  627. //
  628. return 0;
  629. }
  630. VOID
  631. PAL_ClearKeyState(
  632. VOID
  633. )
  634. /*++
  635. Purpose:
  636. Clear the record of pressed keys.
  637. Parameters:
  638. None.
  639. Return value:
  640. None.
  641. --*/
  642. {
  643. g_InputState.dwKeyPress = 0;
  644. }
  645. VOID
  646. PAL_InitInput(
  647. VOID
  648. )
  649. /*++
  650. Purpose:
  651. Initialize the input subsystem.
  652. Parameters:
  653. None.
  654. Return value:
  655. None.
  656. --*/
  657. {
  658. memset(&g_InputState, 0, sizeof(g_InputState));
  659. g_InputState.dir = kDirUnknown;
  660. g_InputState.prevdir = kDirUnknown;
  661. #if SDL_MAJOR_VERSION == 1 && SDL_MINOR_VERSION <= 2
  662. SDL_SetEventFilter(PAL_EventFilter);
  663. #else
  664. SDL_SetEventFilter(PAL_EventFilter, NULL);
  665. #endif
  666. //
  667. // Check for joystick
  668. //
  669. #ifdef PAL_HAS_JOYSTICKS
  670. if (SDL_NumJoysticks() > 0 && g_fUseJoystick)
  671. {
  672. g_pJoy = SDL_JoystickOpen(0);
  673. if (g_pJoy != NULL)
  674. {
  675. SDL_JoystickEventState(SDL_ENABLE);
  676. }
  677. }
  678. #endif
  679. }
  680. VOID
  681. PAL_ShutdownInput(
  682. VOID
  683. )
  684. /*++
  685. Purpose:
  686. Shutdown the input subsystem.
  687. Parameters:
  688. None.
  689. Return value:
  690. None.
  691. --*/
  692. {
  693. #ifdef PAL_HAS_JOYSTICKS
  694. if (SDL_JoystickOpened(0))
  695. {
  696. assert(g_pJoy != NULL);
  697. SDL_JoystickClose(g_pJoy);
  698. g_pJoy = NULL;
  699. }
  700. #endif
  701. }
  702. VOID
  703. PAL_ProcessEvent(
  704. VOID
  705. )
  706. /*++
  707. Purpose:
  708. Process all events.
  709. Parameters:
  710. None.
  711. Return value:
  712. None.
  713. --*/
  714. {
  715. #ifdef PAL_HAS_NATIVEMIDI
  716. MIDI_CheckLoop();
  717. #endif
  718. while (SDL_PollEvent(NULL));
  719. }