input.c 24 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136
  1. /* -*- mode: c; tab-width: 4; c-basic-offset: 3; c-file-style: "linux" -*- */
  2. //
  3. // Copyright (c) 2009, Wei Mingzhi <whistler_wmz@users.sf.net>.
  4. // Portions Copyright (c) 2009, netwan.
  5. //
  6. // All rights reserved.
  7. //
  8. // This file is part of SDLPAL.
  9. //
  10. // SDLPAL is free software: you can redistribute it and/or modify
  11. // it under the terms of the GNU General Public License as published by
  12. // the Free Software Foundation, either version 3 of the License, or
  13. // (at your option) any later version.
  14. //
  15. // This program is distributed in the hope that it will be useful,
  16. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  18. // GNU General Public License for more details.
  19. //
  20. // You should have received a copy of the GNU General Public License
  21. // along with this program. If not, see <http://www.gnu.org/licenses/>.
  22. //
  23. #include "main.h"
  24. #include <math.h>
  25. volatile PALINPUTSTATE g_InputState;
  26. static SDL_Joystick *g_pJoy = NULL;
  27. BOOL g_fUseJoystick = TRUE;
  28. #if defined(GPH)
  29. #define MIN_DEADZONE -16384
  30. #define MAX_DEADZONE 16384
  31. #endif
  32. #if defined(__WINPHONE__)
  33. unsigned int g_uiLastBackKeyTime = 0;
  34. #endif
  35. static VOID
  36. PAL_KeyboardEventFilter(
  37. const SDL_Event *lpEvent
  38. )
  39. /*++
  40. Purpose:
  41. Handle keyboard events.
  42. Parameters:
  43. [IN] lpEvent - pointer to the event.
  44. Return value:
  45. None.
  46. --*/
  47. {
  48. switch (lpEvent->type)
  49. {
  50. case SDL_KEYDOWN:
  51. //
  52. // Pressed a key
  53. //
  54. if (lpEvent->key.keysym.mod & KMOD_ALT)
  55. {
  56. if (lpEvent->key.keysym.sym == SDLK_RETURN)
  57. {
  58. //
  59. // Pressed Alt+Enter (toggle fullscreen)...
  60. //
  61. VIDEO_ToggleFullscreen();
  62. return;
  63. }
  64. else if (lpEvent->key.keysym.sym == SDLK_F4)
  65. {
  66. //
  67. // Pressed Alt+F4 (Exit program)...
  68. //
  69. PAL_Shutdown();
  70. exit(0);
  71. }
  72. }
  73. switch (lpEvent->key.keysym.sym)
  74. {
  75. #ifdef __SYMBIAN32__
  76. //
  77. // Symbian-specific stuff
  78. //
  79. case SDLK_0:
  80. VIDEO_ToggleScaleScreen();
  81. break;
  82. case SDLK_1:
  83. SOUND_AdjustVolume(0);
  84. break;
  85. case SDLK_3:
  86. SOUND_AdjustVolume(1);
  87. break;
  88. #endif
  89. #ifdef __WINPHONE__
  90. case SDLK_AC_BACK:
  91. if (g_uiLastBackKeyTime != 0 && SDL_GetTicks() - g_uiLastBackKeyTime < 800)
  92. {
  93. PAL_Shutdown();
  94. exit(0);
  95. }
  96. g_uiLastBackKeyTime = SDL_GetTicks();
  97. VIDEO_UpdateScreen(NULL);
  98. break;
  99. #endif
  100. case SDLK_UP:
  101. case SDLK_KP8:
  102. g_InputState.prevdir = (gpGlobals->fInBattle ? kDirUnknown : g_InputState.dir);
  103. g_InputState.dir = kDirNorth;
  104. g_InputState.dwKeyPress |= kKeyUp;
  105. break;
  106. case SDLK_DOWN:
  107. case SDLK_KP2:
  108. g_InputState.prevdir = (gpGlobals->fInBattle ? kDirUnknown : g_InputState.dir);
  109. g_InputState.dir = kDirSouth;
  110. g_InputState.dwKeyPress |= kKeyDown;
  111. break;
  112. case SDLK_LEFT:
  113. case SDLK_KP4:
  114. g_InputState.prevdir = (gpGlobals->fInBattle ? kDirUnknown : g_InputState.dir);
  115. g_InputState.dir = kDirWest;
  116. g_InputState.dwKeyPress |= kKeyLeft;
  117. break;
  118. case SDLK_RIGHT:
  119. case SDLK_KP6:
  120. g_InputState.prevdir = (gpGlobals->fInBattle ? kDirUnknown : g_InputState.dir);
  121. g_InputState.dir = kDirEast;
  122. g_InputState.dwKeyPress |= kKeyRight;
  123. break;
  124. #if defined(DINGOO)
  125. case SDLK_SPACE:
  126. g_InputState.dwKeyPress = kKeyMenu;
  127. break;
  128. case SDLK_LCTRL:
  129. g_InputState.dwKeyPress = kKeySearch;
  130. break;
  131. #else
  132. case SDLK_ESCAPE:
  133. case SDLK_INSERT:
  134. case SDLK_LALT:
  135. case SDLK_RALT:
  136. case SDLK_KP0:
  137. g_InputState.dwKeyPress |= kKeyMenu;
  138. break;
  139. case SDLK_RETURN:
  140. case SDLK_SPACE:
  141. case SDLK_KP_ENTER:
  142. case SDLK_LCTRL:
  143. g_InputState.dwKeyPress |= kKeySearch;
  144. break;
  145. case SDLK_PAGEUP:
  146. case SDLK_KP9:
  147. g_InputState.dwKeyPress |= kKeyPgUp;
  148. break;
  149. case SDLK_PAGEDOWN:
  150. case SDLK_KP3:
  151. g_InputState.dwKeyPress |= kKeyPgDn;
  152. break;
  153. case SDLK_7: //7 for mobile device
  154. case SDLK_r:
  155. g_InputState.dwKeyPress |= kKeyRepeat;
  156. break;
  157. case SDLK_2: //2 for mobile device
  158. case SDLK_a:
  159. g_InputState.dwKeyPress |= kKeyAuto;
  160. break;
  161. case SDLK_d:
  162. g_InputState.dwKeyPress |= kKeyDefend;
  163. break;
  164. case SDLK_e:
  165. g_InputState.dwKeyPress |= kKeyUseItem;
  166. break;
  167. case SDLK_w:
  168. g_InputState.dwKeyPress |= kKeyThrowItem;
  169. break;
  170. case SDLK_q:
  171. g_InputState.dwKeyPress |= kKeyFlee;
  172. break;
  173. case SDLK_s:
  174. g_InputState.dwKeyPress |= kKeyStatus;
  175. break;
  176. case SDLK_f:
  177. case SDLK_5: // 5 for mobile device
  178. g_InputState.dwKeyPress |= kKeyForce;
  179. break;
  180. case SDLK_HASH: //# for mobile device
  181. case SDLK_p:
  182. VIDEO_SaveScreenshot();
  183. break;
  184. #endif
  185. default:
  186. break;
  187. }
  188. break;
  189. case SDL_KEYUP:
  190. //
  191. // Released a key
  192. //
  193. switch (lpEvent->key.keysym.sym)
  194. {
  195. case SDLK_UP:
  196. case SDLK_KP8:
  197. if (g_InputState.dir == kDirNorth)
  198. {
  199. g_InputState.dir = g_InputState.prevdir;
  200. }
  201. g_InputState.prevdir = kDirUnknown;
  202. break;
  203. case SDLK_DOWN:
  204. case SDLK_KP2:
  205. if (g_InputState.dir == kDirSouth)
  206. {
  207. g_InputState.dir = g_InputState.prevdir;
  208. }
  209. g_InputState.prevdir = kDirUnknown;
  210. break;
  211. case SDLK_LEFT:
  212. case SDLK_KP4:
  213. if (g_InputState.dir == kDirWest)
  214. {
  215. g_InputState.dir = g_InputState.prevdir;
  216. }
  217. g_InputState.prevdir = kDirUnknown;
  218. break;
  219. case SDLK_RIGHT:
  220. case SDLK_KP6:
  221. if (g_InputState.dir == kDirEast)
  222. {
  223. g_InputState.dir = g_InputState.prevdir;
  224. }
  225. g_InputState.prevdir = kDirUnknown;
  226. break;
  227. default:
  228. break;
  229. }
  230. break;
  231. }
  232. }
  233. static VOID
  234. PAL_MouseEventFilter(
  235. const SDL_Event *lpEvent
  236. )
  237. /*++
  238. Purpose:
  239. Handle mouse events.
  240. Parameters:
  241. [IN] lpEvent - pointer to the event.
  242. Return value:
  243. None.
  244. --*/
  245. {
  246. #ifdef PAL_HAS_MOUSE
  247. static short hitTest = 0; // Double click detect;
  248. const SDL_VideoInfo *vi;
  249. double screenWidth, gridWidth;
  250. double screenHeight, gridHeight;
  251. double mx, my;
  252. double thumbx;
  253. double thumby;
  254. INT gridIndex;
  255. BOOL isLeftMouseDBClick = FALSE;
  256. BOOL isLeftMouseClick = FALSE;
  257. BOOL isRightMouseClick = FALSE;
  258. static INT lastReleaseButtonTime, lastPressButtonTime, betweenTime;
  259. static INT lastPressx = 0;
  260. static INT lastPressy = 0;
  261. static INT lastReleasex = 0;
  262. static INT lastReleasey = 0;
  263. if (lpEvent->type!= SDL_MOUSEBUTTONDOWN && lpEvent->type != SDL_MOUSEBUTTONUP)
  264. return;
  265. vi = SDL_GetVideoInfo();
  266. screenWidth = vi->current_w;
  267. screenHeight = vi->current_h;
  268. gridWidth = screenWidth / 3;
  269. gridHeight = screenHeight / 3;
  270. mx = lpEvent->button.x;
  271. my = lpEvent->button.y;
  272. thumbx = ceil(mx / gridWidth);
  273. thumby = floor(my / gridHeight);
  274. gridIndex = thumbx + thumby * 3 - 1;
  275. switch (lpEvent->type)
  276. {
  277. case SDL_MOUSEBUTTONDOWN:
  278. lastPressButtonTime = SDL_GetTicks();
  279. lastPressx = lpEvent->button.x;
  280. lastPressy = lpEvent->button.y;
  281. switch (gridIndex)
  282. {
  283. case 2:
  284. g_InputState.prevdir = g_InputState.dir;
  285. g_InputState.dir = kDirNorth;
  286. break;
  287. case 6:
  288. g_InputState.prevdir = g_InputState.dir;
  289. g_InputState.dir = kDirSouth;
  290. break;
  291. case 0:
  292. g_InputState.prevdir = g_InputState.dir;
  293. g_InputState.dir = kDirWest;
  294. break;
  295. case 8:
  296. g_InputState.prevdir = g_InputState.dir;
  297. g_InputState.dir = kDirEast;
  298. break;
  299. case 1:
  300. //g_InputState.prevdir = g_InputState.dir;
  301. //g_InputState.dir = kDirNorth;
  302. g_InputState.dwKeyPress |= kKeyUp;
  303. break;
  304. case 7:
  305. //g_InputState.prevdir = g_InputState.dir;
  306. //g_InputState.dir = kDirSouth;
  307. g_InputState.dwKeyPress |= kKeyDown;
  308. break;
  309. case 3:
  310. //g_InputState.prevdir = g_InputState.dir;
  311. //g_InputState.dir = kDirWest;
  312. g_InputState.dwKeyPress |= kKeyLeft;
  313. break;
  314. case 5:
  315. //g_InputState.prevdir = g_InputState.dir;
  316. //g_InputState.dir = kDirEast;
  317. g_InputState.dwKeyPress |= kKeyRight;
  318. break;
  319. }
  320. break;
  321. case SDL_MOUSEBUTTONUP:
  322. lastReleaseButtonTime = SDL_GetTicks();
  323. lastReleasex = lpEvent->button.x;
  324. lastReleasey = lpEvent->button.y;
  325. hitTest ++;
  326. if (abs(lastPressx - lastReleasex) < 25 &&
  327. abs(lastPressy - lastReleasey) < 25)
  328. {
  329. betweenTime = lastReleaseButtonTime - lastPressButtonTime;
  330. if (betweenTime >500)
  331. {
  332. isRightMouseClick = TRUE;
  333. }
  334. else if (betweenTime >=0)
  335. {
  336. if((betweenTime < 100) && (hitTest >= 2))
  337. {
  338. isLeftMouseClick = TRUE;
  339. hitTest = 0;
  340. }
  341. else
  342. {
  343. isLeftMouseClick = TRUE;
  344. if(betweenTime > 100)
  345. {
  346. hitTest = 0;
  347. }
  348. }
  349. }
  350. }
  351. switch (gridIndex)
  352. {
  353. case 2:
  354. if( isLeftMouseDBClick )
  355. {
  356. SOUND_AdjustVolume(1);
  357. break;
  358. }
  359. case 6:
  360. case 0:
  361. if( isLeftMouseDBClick )
  362. {
  363. SOUND_AdjustVolume(0);
  364. break;
  365. }
  366. case 7:
  367. if (isRightMouseClick) //repeat attack
  368. {
  369. g_InputState.dwKeyPress |= kKeyRepeat;
  370. break;
  371. }
  372. case 8:
  373. g_InputState.dir = kDirUnknown;
  374. g_InputState.prevdir = kDirUnknown;
  375. break;
  376. case 1:
  377. if( isRightMouseClick )
  378. {
  379. g_InputState.dwKeyPress |= kKeyForce;
  380. }
  381. break;
  382. case 3:
  383. if( isRightMouseClick )
  384. {
  385. g_InputState.dwKeyPress |= kKeyAuto;
  386. }
  387. break;
  388. case 5:
  389. if( isRightMouseClick )
  390. {
  391. g_InputState.dwKeyPress |= kKeyDefend;
  392. }
  393. break;
  394. case 4:
  395. if (isRightMouseClick) // menu
  396. {
  397. g_InputState.dwKeyPress |= kKeyMenu;
  398. }
  399. else if (isLeftMouseClick) // search
  400. {
  401. g_InputState.dwKeyPress |= kKeySearch;
  402. }
  403. break;
  404. }
  405. break;
  406. }
  407. #endif
  408. }
  409. static VOID
  410. PAL_JoystickEventFilter(
  411. const SDL_Event *lpEvent
  412. )
  413. /*++
  414. Purpose:
  415. Handle joystick events.
  416. Parameters:
  417. [IN] lpEvent - pointer to the event.
  418. Return value:
  419. None.
  420. --*/
  421. {
  422. #ifdef PAL_HAS_JOYSTICKS
  423. switch (lpEvent->type)
  424. {
  425. #if defined (GEKKO)
  426. case SDL_JOYHATMOTION:
  427. switch (lpEvent->jhat.value)
  428. {
  429. case SDL_HAT_LEFT:
  430. g_InputState.prevdir = (gpGlobals->fInBattle ? kDirUnknown : g_InputState.dir);
  431. g_InputState.dir = kDirWest;
  432. g_InputState.dwKeyPress = kKeyLeft;
  433. break;
  434. case SDL_HAT_RIGHT:
  435. g_InputState.prevdir = (gpGlobals->fInBattle ? kDirUnknown : g_InputState.dir);
  436. g_InputState.dir = kDirEast;
  437. g_InputState.dwKeyPress = kKeyRight;
  438. break;
  439. case SDL_HAT_UP:
  440. g_InputState.prevdir = (gpGlobals->fInBattle ? kDirUnknown : g_InputState.dir);
  441. g_InputState.dir = kDirNorth;
  442. g_InputState.dwKeyPress = kKeyUp;
  443. break;
  444. case SDL_HAT_DOWN:
  445. g_InputState.prevdir = (gpGlobals->fInBattle ? kDirUnknown : g_InputState.dir);
  446. g_InputState.dir = kDirSouth;
  447. g_InputState.dwKeyPress = kKeyDown;
  448. break;
  449. }
  450. break;
  451. #else
  452. case SDL_JOYAXISMOTION:
  453. //
  454. // Moved an axis on joystick
  455. //
  456. switch (lpEvent->jaxis.axis)
  457. {
  458. case 0:
  459. //
  460. // X axis
  461. //
  462. #if defined(GPH)
  463. if (lpEvent->jaxis.value > MAX_DEADZONE) {
  464. g_InputState.prevdir = (gpGlobals->fInBattle ? kDirUnknown : g_InputState.dir);
  465. g_InputState.dir = kDirEast;
  466. g_InputState.dwKeyPress = kKeyRight;
  467. } else if (lpEvent->jaxis.value < MIN_DEADZONE) {
  468. g_InputState.prevdir = (gpGlobals->fInBattle ? kDirUnknown : g_InputState.dir);
  469. g_InputState.dir = kDirWest;
  470. g_InputState.dwKeyPress = kKeyLeft;
  471. } else {
  472. g_InputState.dir = kDirUnknown;
  473. }
  474. #else
  475. if (lpEvent->jaxis.value > 20000)
  476. {
  477. if (g_InputState.dir != kDirEast)
  478. {
  479. g_InputState.dwKeyPress |= kKeyRight;
  480. }
  481. g_InputState.prevdir = g_InputState.dir;
  482. g_InputState.dir = kDirEast;
  483. }
  484. else if (lpEvent->jaxis.value < -20000)
  485. {
  486. if (g_InputState.dir != kDirWest)
  487. {
  488. g_InputState.dwKeyPress |= kKeyLeft;
  489. }
  490. g_InputState.prevdir = g_InputState.dir;
  491. g_InputState.dir = kDirWest;
  492. }
  493. else
  494. {
  495. if (g_InputState.prevdir != kDirEast &&
  496. g_InputState.prevdir != kDirWest)
  497. {
  498. g_InputState.dir = g_InputState.prevdir;
  499. }
  500. g_InputState.prevdir = kDirUnknown;
  501. }
  502. #endif
  503. break;
  504. case 1:
  505. //
  506. // Y axis
  507. //
  508. #if defined(GPH)
  509. if (lpEvent->jaxis.value > MAX_DEADZONE) {
  510. g_InputState.prevdir = (gpGlobals->fInBattle ? kDirUnknown : g_InputState.dir);
  511. g_InputState.dir = kDirSouth;
  512. g_InputState.dwKeyPress = kKeyDown;
  513. } else if (lpEvent->jaxis.value < MIN_DEADZONE) {
  514. g_InputState.prevdir = (gpGlobals->fInBattle ? kDirUnknown : g_InputState.dir);
  515. g_InputState.dir = kDirNorth;
  516. g_InputState.dwKeyPress = kKeyUp;
  517. } else {
  518. g_InputState.dir = kDirUnknown;
  519. }
  520. #else
  521. if (lpEvent->jaxis.value > 20000)
  522. {
  523. if (g_InputState.dir != kDirSouth)
  524. {
  525. g_InputState.dwKeyPress |= kKeyDown;
  526. }
  527. g_InputState.prevdir = g_InputState.dir;
  528. g_InputState.dir = kDirSouth;
  529. }
  530. else if (lpEvent->jaxis.value < -20000)
  531. {
  532. if (g_InputState.dir != kDirNorth)
  533. {
  534. g_InputState.dwKeyPress |= kKeyUp;
  535. }
  536. g_InputState.prevdir = g_InputState.dir;
  537. g_InputState.dir = kDirNorth;
  538. }
  539. else
  540. {
  541. if (g_InputState.prevdir != kDirNorth &&
  542. g_InputState.prevdir != kDirSouth)
  543. {
  544. g_InputState.dir = g_InputState.prevdir;
  545. }
  546. g_InputState.prevdir = kDirUnknown;
  547. }
  548. #endif
  549. break;
  550. }
  551. break;
  552. #endif
  553. case SDL_JOYBUTTONDOWN:
  554. //
  555. // Pressed the joystick button
  556. //
  557. #if defined(GPH)
  558. switch (lpEvent->jbutton.button)
  559. {
  560. #if defined(GP2XWIZ)
  561. case 14:
  562. #elif defined(CAANOO)
  563. case 3:
  564. #endif
  565. g_InputState.dwKeyPress = kKeyMenu;
  566. break;
  567. #if defined(GP2XWIZ)
  568. case 13:
  569. #elif defined(CAANOO)
  570. case 2:
  571. #endif
  572. g_InputState.dwKeyPress = kKeySearch;
  573. break;
  574. #else
  575. #if defined(GEKKO)
  576. switch (lpEvent->jbutton.button)
  577. {
  578. case 2:
  579. g_InputState.dwKeyPress |= kKeyMenu;
  580. break;
  581. case 3:
  582. g_InputState.dwKeyPress |= kKeySearch;
  583. break;
  584. #else
  585. switch (lpEvent->jbutton.button & 1)
  586. {
  587. case 0:
  588. g_InputState.dwKeyPress |= kKeyMenu;
  589. break;
  590. case 1:
  591. g_InputState.dwKeyPress |= kKeySearch;
  592. break;
  593. #endif
  594. #endif
  595. }
  596. break;
  597. }
  598. #endif
  599. }
  600. #ifdef PAL_HAS_TOUCH
  601. #define TOUCH_NONE 0
  602. #define TOUCH_UP 1
  603. #define TOUCH_DOWN 2
  604. #define TOUCH_LEFT 3
  605. #define TOUCH_RIGHT 4
  606. #define TOUCH_BUTTON1 5
  607. #define TOUCH_BUTTON2 6
  608. #define TOUCH_BUTTON3 7
  609. #define TOUCH_BUTTON4 8
  610. static int
  611. PAL_GetTouchArea(
  612. float X,
  613. float Y
  614. )
  615. {
  616. if (Y < 0.5)
  617. {
  618. //
  619. // Upper area
  620. //
  621. return TOUCH_NONE;
  622. }
  623. else if (X < 1.0 / 3)
  624. {
  625. if (Y - 0.5 < (1.0 / 6 - fabs(X - 1.0 / 3 / 2)) * (0.5 / (1.0 / 3)))
  626. {
  627. return TOUCH_UP;
  628. }
  629. else if (Y - 0.75 > fabs(X - 1.0 / 3 / 2) * (0.5 / (1.0 / 3)))
  630. {
  631. return TOUCH_DOWN;
  632. }
  633. else if (X < 1.0 / 3 / 2 && fabs(Y - 0.75) < 0.25 - X * (0.5 / (1.0 / 3)))
  634. {
  635. return TOUCH_LEFT;
  636. }
  637. else
  638. {
  639. return TOUCH_RIGHT;
  640. }
  641. }
  642. else if (X > 1.0 - 1.0 / 3)
  643. {
  644. if (X < 1.0 - (1.0 / 3 / 2))
  645. {
  646. if (Y < 0.75)
  647. {
  648. return TOUCH_BUTTON1;
  649. }
  650. else
  651. {
  652. return TOUCH_BUTTON3;
  653. }
  654. }
  655. else
  656. {
  657. if (Y < 0.75)
  658. {
  659. return TOUCH_BUTTON2;
  660. }
  661. else
  662. {
  663. return TOUCH_BUTTON4;
  664. }
  665. }
  666. }
  667. return TOUCH_NONE;
  668. }
  669. static VOID
  670. PAL_SetTouchAction(
  671. int area
  672. )
  673. {
  674. switch (area)
  675. {
  676. case TOUCH_UP:
  677. g_InputState.dir = kDirNorth;
  678. g_InputState.dwKeyPress |= kKeyUp;
  679. break;
  680. case TOUCH_DOWN:
  681. g_InputState.dir = kDirSouth;
  682. g_InputState.dwKeyPress |= kKeyDown;
  683. break;
  684. case TOUCH_LEFT:
  685. g_InputState.dir = kDirWest;
  686. g_InputState.dwKeyPress |= kKeyLeft;
  687. break;
  688. case TOUCH_RIGHT:
  689. g_InputState.dir = kDirEast;
  690. g_InputState.dwKeyPress |= kKeyRight;
  691. break;
  692. case TOUCH_BUTTON1:
  693. if (gpGlobals->fInBattle)
  694. {
  695. g_InputState.dwKeyPress |= kKeyRepeat;
  696. }
  697. else
  698. {
  699. g_InputState.dwKeyPress |= kKeyForce;
  700. }
  701. break;
  702. case TOUCH_BUTTON2:
  703. g_InputState.dwKeyPress |= kKeyMenu;
  704. break;
  705. case TOUCH_BUTTON3:
  706. g_InputState.dwKeyPress |= kKeyUseItem;
  707. break;
  708. case TOUCH_BUTTON4:
  709. g_InputState.dwKeyPress |= kKeySearch;
  710. break;
  711. }
  712. }
  713. static VOID
  714. PAL_UnsetTouchAction(
  715. int area
  716. )
  717. {
  718. switch (area)
  719. {
  720. case TOUCH_UP:
  721. case TOUCH_DOWN:
  722. case TOUCH_LEFT:
  723. case TOUCH_RIGHT:
  724. g_InputState.dir = kDirUnknown;
  725. break;
  726. }
  727. }
  728. #endif
  729. static VOID
  730. PAL_TouchEventFilter(
  731. const SDL_Event *lpEvent
  732. )
  733. /*++
  734. Purpose:
  735. Handle touch events.
  736. Parameters:
  737. [IN] lpEvent - pointer to the event.
  738. Return value:
  739. None.
  740. --*/
  741. {
  742. #ifdef PAL_HAS_TOUCH
  743. static SDL_TouchID finger1 = -1, finger2 = -1;
  744. static int prev_touch1 = TOUCH_NONE;
  745. static int prev_touch2 = TOUCH_NONE;
  746. switch (lpEvent->type)
  747. {
  748. case SDL_FINGERDOWN:
  749. if (finger1 == -1)
  750. {
  751. int area = PAL_GetTouchArea(lpEvent->tfinger.x, lpEvent->tfinger.y);
  752. finger1 = lpEvent->tfinger.fingerId;
  753. prev_touch1 = area;
  754. PAL_SetTouchAction(area);
  755. }
  756. else if (finger2 == -1)
  757. {
  758. int area = PAL_GetTouchArea(lpEvent->tfinger.x, lpEvent->tfinger.y);
  759. finger2 = lpEvent->tfinger.fingerId;
  760. prev_touch2 = area;
  761. PAL_SetTouchAction(area);
  762. }
  763. break;
  764. case SDL_FINGERUP:
  765. if (lpEvent->tfinger.fingerId == finger1)
  766. {
  767. PAL_UnsetTouchAction(prev_touch1);
  768. finger1 = -1;
  769. prev_touch1 = TOUCH_NONE;
  770. }
  771. else if (lpEvent->tfinger.fingerId == finger2)
  772. {
  773. PAL_UnsetTouchAction(prev_touch2);
  774. finger2 = -1;
  775. prev_touch2 = TOUCH_NONE;
  776. }
  777. break;
  778. case SDL_FINGERMOTION:
  779. if (lpEvent->tfinger.fingerId == finger1)
  780. {
  781. int area = PAL_GetTouchArea(lpEvent->tfinger.x, lpEvent->tfinger.y);
  782. if (prev_touch1 != area && area != TOUCH_NONE)
  783. {
  784. PAL_UnsetTouchAction(prev_touch1);
  785. prev_touch1 = area;
  786. PAL_SetTouchAction(area);
  787. }
  788. }
  789. else if (lpEvent->tfinger.fingerId == finger2)
  790. {
  791. int area = PAL_GetTouchArea(lpEvent->tfinger.x, lpEvent->tfinger.y);
  792. if (prev_touch2 != area && area != TOUCH_NONE)
  793. {
  794. PAL_UnsetTouchAction(prev_touch2);
  795. prev_touch2 = area;
  796. PAL_SetTouchAction(area);
  797. }
  798. }
  799. break;
  800. }
  801. #endif
  802. }
  803. static int SDLCALL
  804. PAL_EventFilter(
  805. const SDL_Event *lpEvent
  806. )
  807. /*++
  808. Purpose:
  809. SDL event filter function. A filter to process all events.
  810. Parameters:
  811. [IN] lpEvent - pointer to the event.
  812. Return value:
  813. 1 = the event will be added to the internal queue.
  814. 0 = the event will be dropped from the queue.
  815. --*/
  816. {
  817. switch (lpEvent->type)
  818. {
  819. #if SDL_VERSION_ATLEAST(2,0,0)
  820. case SDL_WINDOWEVENT:
  821. if (lpEvent->window.event == SDL_WINDOWEVENT_RESIZED)
  822. {
  823. //
  824. // resized the window
  825. //
  826. VIDEO_Resize(lpEvent->window.data1, lpEvent->window.data2);
  827. }
  828. break;
  829. #ifdef __IOS__
  830. case SDL_APP_WILLENTERBACKGROUND:
  831. g_bRenderPaused = TRUE;
  832. break;
  833. case SDL_APP_DIDENTERFOREGROUND:
  834. g_bRenderPaused = FALSE;
  835. VIDEO_UpdateScreen(NULL);
  836. break;
  837. #endif
  838. #else
  839. case SDL_VIDEORESIZE:
  840. //
  841. // resized the window
  842. //
  843. VIDEO_Resize(lpEvent->resize.w, lpEvent->resize.h);
  844. break;
  845. #endif
  846. case SDL_QUIT:
  847. //
  848. // clicked on the close button of the window. Quit immediately.
  849. //
  850. PAL_Shutdown();
  851. exit(0);
  852. }
  853. PAL_KeyboardEventFilter(lpEvent);
  854. PAL_MouseEventFilter(lpEvent);
  855. PAL_JoystickEventFilter(lpEvent);
  856. PAL_TouchEventFilter(lpEvent);
  857. //
  858. // All events are handled here; don't put anything to the internal queue
  859. //
  860. return 0;
  861. }
  862. VOID
  863. PAL_ClearKeyState(
  864. VOID
  865. )
  866. /*++
  867. Purpose:
  868. Clear the record of pressed keys.
  869. Parameters:
  870. None.
  871. Return value:
  872. None.
  873. --*/
  874. {
  875. g_InputState.dwKeyPress = 0;
  876. }
  877. VOID
  878. PAL_InitInput(
  879. VOID
  880. )
  881. /*++
  882. Purpose:
  883. Initialize the input subsystem.
  884. Parameters:
  885. None.
  886. Return value:
  887. None.
  888. --*/
  889. {
  890. memset((void *)&g_InputState, 0, sizeof(g_InputState));
  891. g_InputState.dir = kDirUnknown;
  892. g_InputState.prevdir = kDirUnknown;
  893. //
  894. // Check for joystick
  895. //
  896. #ifdef PAL_HAS_JOYSTICKS
  897. if (SDL_NumJoysticks() > 0 && g_fUseJoystick)
  898. {
  899. //
  900. // HACKHACK: applesmc shouldn't be considered as a real joystick
  901. //
  902. if (strcmp(SDL_JoystickName(0), "applesmc") != 0)
  903. {
  904. if (SDL_NumJoysticks() > 1)
  905. {
  906. g_pJoy = SDL_JoystickOpen(1);
  907. }
  908. }
  909. if (g_pJoy != NULL)
  910. {
  911. SDL_JoystickEventState(SDL_ENABLE);
  912. }
  913. }
  914. #endif
  915. #ifdef PAL_ALLOW_KEYREPEAT
  916. SDL_EnableKeyRepeat(0, 0);
  917. #endif
  918. }
  919. VOID
  920. PAL_ShutdownInput(
  921. VOID
  922. )
  923. /*++
  924. Purpose:
  925. Shutdown the input subsystem.
  926. Parameters:
  927. None.
  928. Return value:
  929. None.
  930. --*/
  931. {
  932. #ifdef PAL_HAS_JOYSTICKS
  933. #if SDL_VERSION_ATLEAST(2,0,0)
  934. if (g_pJoy != NULL)
  935. {
  936. SDL_JoystickClose(g_pJoy);
  937. g_pJoy = NULL;
  938. }
  939. #else
  940. if (SDL_JoystickOpened(0))
  941. {
  942. assert(g_pJoy != NULL);
  943. SDL_JoystickClose(g_pJoy);
  944. g_pJoy = NULL;
  945. }
  946. #endif
  947. #endif
  948. }
  949. VOID
  950. PAL_ProcessEvent(
  951. VOID
  952. )
  953. /*++
  954. Purpose:
  955. Process all events.
  956. Parameters:
  957. None.
  958. Return value:
  959. None.
  960. --*/
  961. {
  962. #ifdef PAL_HAS_NATIVEMIDI
  963. MIDI_CheckLoop();
  964. #endif
  965. while (PAL_PollEvent(NULL));
  966. }
  967. int
  968. PAL_PollEvent(
  969. SDL_Event *event
  970. )
  971. /*++
  972. Purpose:
  973. Poll and process one event.
  974. Parameters:
  975. [OUT] event - Events polled from SDL.
  976. Return value:
  977. Return value of PAL_PollEvent.
  978. --*/
  979. {
  980. SDL_Event evt;
  981. int ret = SDL_PollEvent(&evt);
  982. if (ret != 0)
  983. {
  984. PAL_EventFilter(&evt);
  985. }
  986. if (event != NULL)
  987. {
  988. *event = evt;
  989. }
  990. return ret;
  991. }