in_dos.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616
  1. /*
  2. Copyright (C) 1996-1997 Id Software, Inc.
  3. This program is free software; you can redistribute it and/or
  4. modify it under the terms of the GNU General Public License
  5. as published by the Free Software Foundation; either version 2
  6. of the License, or (at your option) any later version.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  10. See the GNU General Public License for more details.
  11. You should have received a copy of the GNU General Public License
  12. along with this program; if not, write to the Free Software
  13. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  14. */
  15. // in_mouse.c -- dos mouse code
  16. #include "quakedef.h"
  17. #include "dosisms.h"
  18. #define AUX_FLAG_FREELOOK 0x00000001
  19. typedef struct
  20. {
  21. long interruptVector;
  22. char deviceName[16];
  23. long numAxes;
  24. long numButtons;
  25. long flags;
  26. vec3_t viewangles;
  27. // intended velocities
  28. float forwardmove;
  29. float sidemove;
  30. float upmove;
  31. long buttons;
  32. } externControl_t;
  33. /*
  34. #define AUX_FLAG_FORCEFREELOOK 0x00000001 // r/o
  35. #define AUX_FLAG_EXTENDED 0x00000002 // r/o
  36. #define AUX_FLAG_RUN 0x00000004 // w/o
  37. #define AUX_FLAG_STRAFE 0x00000008 // w/o
  38. #define AUX_FLAG_FREELOOK 0x00000010 // w/o
  39. #define AUX_MAP_UNDEFINED 0
  40. #define AUX_MAP_PITCH 1
  41. #define AUX_MAP_YAW 2
  42. #define AUX_MAP_ROLL 3
  43. #define AUX_MAP_FORWARD 4
  44. #define AUX_MAP_SIDE 5
  45. #define AUX_MAP_UP 6
  46. typedef struct
  47. {
  48. long interruptVector;
  49. // r/o
  50. char deviceName[16];
  51. // r/o
  52. long numAxes;
  53. // r/o 1-6
  54. long numButtons; // r/o 0-32
  55. long flags; // see above
  56. byte axisMapping[6]; // w/o default = p,y,r,f,s,u
  57. float axisValue[6]; // r/w
  58. float sensitivity[6]; // w/o default = 1.0
  59. long buttons; // r/o
  60. float last_frame_time; // w/o
  61. } externControl_t;
  62. */
  63. cvar_t m_filter = {"m_filter","1"};
  64. qboolean mouse_avail;
  65. int mouse_buttons;
  66. int mouse_oldbuttonstate;
  67. int mouse_buttonstate;
  68. float mouse_x, mouse_y;
  69. float old_mouse_x, old_mouse_y;
  70. cvar_t in_joystick = {"joystick","1"};
  71. cvar_t joy_numbuttons = {"joybuttons","4", true};
  72. qboolean joy_avail;
  73. int joy_oldbuttonstate;
  74. int joy_buttonstate;
  75. int joyxl, joyxh, joyyl, joyyh;
  76. int joystickx, joysticky;
  77. qboolean need_center;
  78. qboolean extern_avail;
  79. int extern_buttons;
  80. int extern_oldbuttonstate;
  81. int extern_buttonstate;
  82. cvar_t aux_look = {"auxlook","1", true};
  83. externControl_t *extern_control;
  84. void IN_StartupExternal (void);
  85. void IN_ExternalMove (usercmd_t *cmd);
  86. void IN_StartupJoystick (void);
  87. qboolean IN_ReadJoystick (void);
  88. void Toggle_AuxLook_f (void)
  89. {
  90. if (aux_look.value)
  91. Cvar_Set ("auxlook","0");
  92. else
  93. Cvar_Set ("auxlook","1");
  94. }
  95. void Force_CenterView_f (void)
  96. {
  97. cl.viewangles[PITCH] = 0;
  98. }
  99. /*
  100. ===========
  101. IN_StartupMouse
  102. ===========
  103. */
  104. void IN_StartupMouse (void)
  105. {
  106. if ( COM_CheckParm ("-nomouse") )
  107. return;
  108. // check for mouse
  109. regs.x.ax = 0;
  110. dos_int86(0x33);
  111. mouse_avail = regs.x.ax;
  112. if (!mouse_avail)
  113. {
  114. Con_Printf ("No mouse found\n");
  115. return;
  116. }
  117. mouse_buttons = regs.x.bx;
  118. if (mouse_buttons > 3)
  119. mouse_buttons = 3;
  120. Con_Printf("%d-button mouse available\n", mouse_buttons);
  121. }
  122. /*
  123. ===========
  124. IN_Init
  125. ===========
  126. */
  127. void IN_Init (void)
  128. {
  129. int i;
  130. Cvar_RegisterVariable (&m_filter);
  131. Cvar_RegisterVariable (&in_joystick);
  132. Cvar_RegisterVariable (&joy_numbuttons);
  133. Cvar_RegisterVariable (&aux_look);
  134. Cmd_AddCommand ("toggle_auxlook", Toggle_AuxLook_f);
  135. Cmd_AddCommand ("force_centerview", Force_CenterView_f);
  136. IN_StartupMouse ();
  137. IN_StartupJoystick ();
  138. i = COM_CheckParm ("-control");
  139. if (i)
  140. {
  141. extern_control = real2ptr(Q_atoi (com_argv[i+1]));
  142. IN_StartupExternal ();
  143. }
  144. }
  145. /*
  146. ===========
  147. IN_Shutdown
  148. ===========
  149. */
  150. void IN_Shutdown (void)
  151. {
  152. }
  153. /*
  154. ===========
  155. IN_Commands
  156. ===========
  157. */
  158. void IN_Commands (void)
  159. {
  160. int i;
  161. if (mouse_avail)
  162. {
  163. regs.x.ax = 3; // read buttons
  164. dos_int86(0x33);
  165. mouse_buttonstate = regs.x.bx;
  166. // perform button actions
  167. for (i=0 ; i<mouse_buttons ; i++)
  168. {
  169. if ( (mouse_buttonstate & (1<<i)) &&
  170. !(mouse_oldbuttonstate & (1<<i)) )
  171. {
  172. Key_Event (K_MOUSE1 + i, true);
  173. }
  174. if ( !(mouse_buttonstate & (1<<i)) &&
  175. (mouse_oldbuttonstate & (1<<i)) )
  176. {
  177. Key_Event (K_MOUSE1 + i, false);
  178. }
  179. }
  180. mouse_oldbuttonstate = mouse_buttonstate;
  181. }
  182. if (joy_avail)
  183. {
  184. joy_buttonstate = ((dos_inportb(0x201) >> 4)&15)^15;
  185. // perform button actions
  186. for (i=0 ; i<joy_numbuttons.value ; i++)
  187. {
  188. if ( (joy_buttonstate & (1<<i)) &&
  189. !(joy_oldbuttonstate & (1<<i)) )
  190. {
  191. Key_Event (K_JOY1 + i, true);
  192. }
  193. if ( !(joy_buttonstate & (1<<i)) &&
  194. (joy_oldbuttonstate & (1<<i)) )
  195. {
  196. Key_Event (K_JOY1 + i, false);
  197. }
  198. }
  199. joy_oldbuttonstate = joy_buttonstate;
  200. }
  201. if (extern_avail)
  202. {
  203. extern_buttonstate = extern_control->buttons;
  204. // perform button actions
  205. for (i=0 ; i<extern_buttons ; i++)
  206. {
  207. if ( (extern_buttonstate & (1<<i)) &&
  208. !(extern_oldbuttonstate & (1<<i)) )
  209. {
  210. Key_Event (K_AUX1 + i, true);
  211. }
  212. if ( !(extern_buttonstate & (1<<i)) &&
  213. (extern_oldbuttonstate & (1<<i)) )
  214. {
  215. Key_Event (K_AUX1 + i, false);
  216. }
  217. }
  218. extern_oldbuttonstate = extern_buttonstate;
  219. }
  220. }
  221. /*
  222. ===========
  223. IN_Move
  224. ===========
  225. */
  226. void IN_MouseMove (usercmd_t *cmd)
  227. {
  228. int mx, my;
  229. if (!mouse_avail)
  230. return;
  231. regs.x.ax = 11; // read move
  232. dos_int86(0x33);
  233. mx = (short)regs.x.cx;
  234. my = (short)regs.x.dx;
  235. if (m_filter.value)
  236. {
  237. mouse_x = (mx + old_mouse_x) * 0.5;
  238. mouse_y = (my + old_mouse_y) * 0.5;
  239. }
  240. else
  241. {
  242. mouse_x = mx;
  243. mouse_y = my;
  244. }
  245. old_mouse_x = mx;
  246. old_mouse_y = my;
  247. mouse_x *= sensitivity.value;
  248. mouse_y *= sensitivity.value;
  249. // add mouse X/Y movement to cmd
  250. if ( (in_strafe.state & 1) || (lookstrafe.value && (in_mlook.state & 1) ))
  251. cmd->sidemove += m_side.value * mouse_x;
  252. else
  253. cl.viewangles[YAW] -= m_yaw.value * mouse_x;
  254. if (in_mlook.state & 1)
  255. V_StopPitchDrift ();
  256. if ( (in_mlook.state & 1) && !(in_strafe.state & 1))
  257. {
  258. cl.viewangles[PITCH] += m_pitch.value * mouse_y;
  259. if (cl.viewangles[PITCH] > 80)
  260. cl.viewangles[PITCH] = 80;
  261. if (cl.viewangles[PITCH] < -70)
  262. cl.viewangles[PITCH] = -70;
  263. }
  264. else
  265. {
  266. if ((in_strafe.state & 1) && noclip_anglehack)
  267. cmd->upmove -= m_forward.value * mouse_y;
  268. else
  269. cmd->forwardmove -= m_forward.value * mouse_y;
  270. }
  271. }
  272. /*
  273. ===========
  274. IN_JoyMove
  275. ===========
  276. */
  277. void IN_JoyMove (usercmd_t *cmd)
  278. {
  279. float speed, aspeed;
  280. if (!joy_avail || !in_joystick.value)
  281. return;
  282. IN_ReadJoystick ();
  283. if (joysticky > joyyh*2 || joystickx > joyxh*2)
  284. return; // assume something jumped in and messed up the joystick
  285. // reading time (win 95)
  286. if (in_speed.state & 1)
  287. speed = cl_movespeedkey.value;
  288. else
  289. speed = 1;
  290. aspeed = speed*host_frametime;
  291. if (in_strafe.state & 1)
  292. {
  293. if (joystickx < joyxl)
  294. cmd->sidemove -= speed*cl_sidespeed.value;
  295. else if (joystickx > joyxh)
  296. cmd->sidemove += speed*cl_sidespeed.value;
  297. }
  298. else
  299. {
  300. if (joystickx < joyxl)
  301. cl.viewangles[YAW] += aspeed*cl_yawspeed.value;
  302. else if (joystickx > joyxh)
  303. cl.viewangles[YAW] -= aspeed*cl_yawspeed.value;
  304. cl.viewangles[YAW] = anglemod(cl.viewangles[YAW]);
  305. }
  306. if (in_mlook.state & 1)
  307. {
  308. if (m_pitch.value < 0)
  309. speed *= -1;
  310. if (joysticky < joyyl)
  311. cl.viewangles[PITCH] += aspeed*cl_pitchspeed.value;
  312. else if (joysticky > joyyh)
  313. cl.viewangles[PITCH] -= aspeed*cl_pitchspeed.value;
  314. }
  315. else
  316. {
  317. if (joysticky < joyyl)
  318. cmd->forwardmove += speed*cl_forwardspeed.value;
  319. else if (joysticky > joyyh)
  320. cmd->forwardmove -= speed*cl_backspeed.value;
  321. }
  322. }
  323. /*
  324. ===========
  325. IN_Move
  326. ===========
  327. */
  328. void IN_Move (usercmd_t *cmd)
  329. {
  330. IN_MouseMove (cmd);
  331. IN_JoyMove (cmd);
  332. IN_ExternalMove (cmd);
  333. }
  334. /*
  335. ============================================================================
  336. JOYSTICK
  337. ============================================================================
  338. */
  339. qboolean IN_ReadJoystick (void)
  340. {
  341. int b;
  342. int count;
  343. joystickx = 0;
  344. joysticky = 0;
  345. count = 0;
  346. b = dos_inportb(0x201);
  347. dos_outportb(0x201, b);
  348. // clear counters
  349. while (++count < 10000)
  350. {
  351. b = dos_inportb(0x201);
  352. joystickx += b&1;
  353. joysticky += (b&2)>>1;
  354. if ( !(b&3) )
  355. return true;
  356. }
  357. Con_Printf ("IN_ReadJoystick: no response\n");
  358. joy_avail = false;
  359. return false;
  360. }
  361. /*
  362. =============
  363. WaitJoyButton
  364. =============
  365. */
  366. qboolean WaitJoyButton (void)
  367. {
  368. int oldbuttons, buttons;
  369. oldbuttons = 0;
  370. do
  371. {
  372. key_count = -1;
  373. Sys_SendKeyEvents ();
  374. key_count = 0;
  375. if (key_lastpress == K_ESCAPE)
  376. {
  377. Con_Printf ("aborted.\n");
  378. return false;
  379. }
  380. key_lastpress = 0;
  381. SCR_UpdateScreen ();
  382. buttons = ((dos_inportb(0x201) >> 4)&1)^1;
  383. if (buttons != oldbuttons)
  384. {
  385. oldbuttons = buttons;
  386. continue;
  387. }
  388. } while ( !buttons);
  389. do
  390. {
  391. key_count = -1;
  392. Sys_SendKeyEvents ();
  393. key_count = 0;
  394. if (key_lastpress == K_ESCAPE)
  395. {
  396. Con_Printf ("aborted.\n");
  397. return false;
  398. }
  399. key_lastpress = 0;
  400. SCR_UpdateScreen ();
  401. buttons = ((dos_inportb(0x201) >> 4)&1)^1;
  402. if (buttons != oldbuttons)
  403. {
  404. oldbuttons = buttons;
  405. continue;
  406. }
  407. } while ( buttons);
  408. return true;
  409. }
  410. /*
  411. ===============
  412. IN_StartupJoystick
  413. ===============
  414. */
  415. void IN_StartupJoystick (void)
  416. {
  417. int centerx, centery;
  418. Con_Printf ("\n");
  419. joy_avail = false;
  420. if ( COM_CheckParm ("-nojoy") )
  421. return;
  422. if (!IN_ReadJoystick ())
  423. {
  424. joy_avail = false;
  425. Con_Printf ("joystick not found\n");
  426. return;
  427. }
  428. Con_Printf ("joystick found\n");
  429. Con_Printf ("CENTER the joystick\nand press button 1 (ESC to skip):\n");
  430. if (!WaitJoyButton ())
  431. return;
  432. IN_ReadJoystick ();
  433. centerx = joystickx;
  434. centery = joysticky;
  435. Con_Printf ("Push the joystick to the UPPER LEFT\nand press button 1 (ESC to skip):\n");
  436. if (!WaitJoyButton ())
  437. return;
  438. IN_ReadJoystick ();
  439. joyxl = (centerx + joystickx)/2;
  440. joyyl = (centerx + joysticky)/2;
  441. Con_Printf ("Push the joystick to the LOWER RIGHT\nand press button 1 (ESC to skip):\n");
  442. if (!WaitJoyButton ())
  443. return;
  444. IN_ReadJoystick ();
  445. joyxh = (centerx + joystickx)/2;
  446. joyyh = (centery + joysticky)/2;
  447. joy_avail = true;
  448. Con_Printf ("joystick configured.\n");
  449. Con_Printf ("\n");
  450. }
  451. /*
  452. ============================================================================
  453. EXTERNAL
  454. ============================================================================
  455. */
  456. /*
  457. ===============
  458. IN_StartupExternal
  459. ===============
  460. */
  461. void IN_StartupExternal (void)
  462. {
  463. if (extern_control->numButtons > 32)
  464. extern_control->numButtons = 32;
  465. Con_Printf("%s Initialized\n", extern_control->deviceName);
  466. Con_Printf(" %u axes %u buttons\n", extern_control->numAxes, extern_control->numButtons);
  467. extern_avail = true;
  468. extern_buttons = extern_control->numButtons;
  469. }
  470. /*
  471. ===========
  472. IN_ExternalMove
  473. ===========
  474. */
  475. void IN_ExternalMove (usercmd_t *cmd)
  476. {
  477. qboolean freelook;
  478. if (! extern_avail)
  479. return;
  480. extern_control->viewangles[YAW] = cl.viewangles[YAW];
  481. extern_control->viewangles[PITCH] = cl.viewangles[PITCH];
  482. extern_control->viewangles[ROLL] = cl.viewangles[ROLL];
  483. extern_control->forwardmove = cmd->forwardmove;
  484. extern_control->sidemove = cmd->sidemove;
  485. extern_control->upmove = cmd->upmove;
  486. Con_DPrintf("IN: y:%f p:%f r:%f f:%f s:%f u:%f\n", extern_control->viewangles[YAW], extern_control->viewangles[PITCH], extern_control->viewangles[ROLL], extern_control->forwardmove, extern_control->sidemove, extern_control->upmove);
  487. dos_int86(extern_control->interruptVector);
  488. Con_DPrintf("OUT: y:%f p:%f r:%f f:%f s:%f u:%f\n", extern_control->viewangles[YAW], extern_control->viewangles[PITCH], extern_control->viewangles[ROLL], extern_control->forwardmove, extern_control->sidemove, extern_control->upmove);
  489. cl.viewangles[YAW] = extern_control->viewangles[YAW];
  490. cl.viewangles[PITCH] = extern_control->viewangles[PITCH];
  491. cl.viewangles[ROLL] = extern_control->viewangles[ROLL];
  492. cmd->forwardmove = extern_control->forwardmove;
  493. cmd->sidemove = extern_control->sidemove;
  494. cmd->upmove = extern_control->upmove;
  495. if (cl.viewangles[PITCH] > 80)
  496. cl.viewangles[PITCH] = 80;
  497. if (cl.viewangles[PITCH] < -70)
  498. cl.viewangles[PITCH] = -70;
  499. freelook = (extern_control->flags & AUX_FLAG_FREELOOK || aux_look.value || in_mlook.state & 1);
  500. if (freelook)
  501. V_StopPitchDrift ();
  502. }