ID_IN.C 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284
  1. /* Catacomb Armageddon Source Code
  2. * Copyright (C) 1993-2014 Flat Rock Software
  3. *
  4. * This program is free software; you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License as published by
  6. * the Free Software Foundation; either version 2 of the License, or
  7. * (at your option) any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License along
  15. * with this program; if not, write to the Free Software Foundation, Inc.,
  16. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  17. */
  18. //
  19. // ID Engine
  20. // ID_IN.c - Input Manager
  21. // v1.0d1
  22. // By Jason Blochowiak
  23. //
  24. //
  25. // This module handles dealing with the various input devices
  26. //
  27. // Depends on: Memory Mgr (for demo recording), Sound Mgr (for timing stuff),
  28. // User Mgr (for command line parms)
  29. //
  30. // Globals:
  31. // LastScan - The keyboard scan code of the last key pressed
  32. // LastASCII - The ASCII value of the last key pressed
  33. // DEBUG - there are more globals
  34. //
  35. #include "ID_HEADS.H"
  36. #pragma hdrstop
  37. #define KeyInt 9 // The keyboard ISR number
  38. // Stuff for the joystick
  39. #define JoyScaleMax 32768
  40. #define JoyScaleShift 8
  41. #define MaxJoyValue 5000
  42. // Global variables
  43. boolean JoystickCalibrated=false; // MDM (GAMERS EDGE) - added
  44. ControlType ControlTypeUsed; // MDM (GAMERS EDGE) - added
  45. boolean Keyboard[NumCodes],
  46. JoysPresent[MaxJoys],
  47. MousePresent;
  48. boolean Paused;
  49. char LastASCII;
  50. ScanCode LastScan;
  51. KeyboardDef KbdDefs[MaxKbds] = {{0x1d,0x38,0x47,0x48,0x49,0x4b,0x4d,0x4f,0x50,0x51}};
  52. JoystickDef JoyDefs[MaxJoys];
  53. ControlType Controls[MaxPlayers];
  54. // Demo DemoMode = demo_Off;
  55. // byte _seg *DemoBuffer;
  56. // word DemoOffset,DemoSize;
  57. // Internal variables
  58. static boolean IN_Started;
  59. static boolean CapsLock;
  60. static ScanCode CurCode,LastCode;
  61. static byte far ASCIINames[] = // Unshifted ASCII for scan codes
  62. {
  63. // 0 1 2 3 4 5 6 7 8 9 A B C D E F
  64. 0 ,27 ,'1','2','3','4','5','6','7','8','9','0','-','=',8 ,9 , // 0
  65. 'q','w','e','r','t','y','u','i','o','p','[',']',13 ,0 ,'a','s', // 1
  66. 'd','f','g','h','j','k','l',';',39 ,'`',0 ,92 ,'z','x','c','v', // 2
  67. 'b','n','m',',','.','/',0 ,'*',0 ,' ',0 ,0 ,0 ,0 ,0 ,0 , // 3
  68. 0 ,0 ,0 ,0 ,0 ,0 ,0 ,'7','8','9','-','4','5','6','+','1', // 4
  69. '2','3','0',127,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 , // 5
  70. 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 , // 6
  71. 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 // 7
  72. },
  73. far ShiftNames[] = // Shifted ASCII for scan codes
  74. {
  75. // 0 1 2 3 4 5 6 7 8 9 A B C D E F
  76. 0 ,27 ,'!','@','#','$','%','^','&','*','(',')','_','+',8 ,9 , // 0
  77. 'Q','W','E','R','T','Y','U','I','O','P','{','}',13 ,0 ,'A','S', // 1
  78. 'D','F','G','H','J','K','L',':',34 ,'~',0 ,'|','Z','X','C','V', // 2
  79. 'B','N','M','<','>','?',0 ,'*',0 ,' ',0 ,0 ,0 ,0 ,0 ,0 , // 3
  80. 0 ,0 ,0 ,0 ,0 ,0 ,0 ,'7','8','9','-','4','5','6','+','1', // 4
  81. '2','3','0',127,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 , // 5
  82. 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 , // 6
  83. 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 // 7
  84. },
  85. far SpecialNames[] = // ASCII for 0xe0 prefixed codes
  86. {
  87. // 0 1 2 3 4 5 6 7 8 9 A B C D E F
  88. 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 , // 0
  89. 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,13 ,0 ,0 ,0 , // 1
  90. 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 , // 2
  91. 0 ,0 ,0 ,0 ,0 ,'/',0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 , // 3
  92. 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 , // 4
  93. 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 , // 5
  94. 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 , // 6
  95. 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 // 7
  96. },
  97. #if 0
  98. *ScanNames[] = // Scan code names with single chars
  99. {
  100. "?","?","1","2","3","4","5","6","7","8","9","0","-","+","?","?",
  101. "Q","W","E","R","T","Y","U","I","O","P","[","]","|","?","A","S",
  102. "D","F","G","H","J","K","L",";","\"","?","?","?","Z","X","C","V",
  103. "B","N","M",",",".","/","?","?","?","?","?","?","?","?","?","?",
  104. "?","?","?","?","?","?","?","?","\xf","?","-","\x15","5","\x11","+","?",
  105. "\x13","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?",
  106. "?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?",
  107. "?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?"
  108. }, // DEBUG - consolidate these
  109. #endif
  110. far ExtScanCodes[] = // Scan codes with >1 char names
  111. {
  112. 1,0xe,0xf,0x1d,0x2a,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,
  113. 0x3f,0x40,0x41,0x42,0x43,0x44,0x57,0x59,0x46,0x1c,0x36,
  114. 0x37,0x38,0x47,0x49,0x4f,0x51,0x52,0x53,0x45,0x48,
  115. 0x50,0x4b,0x4d,0x00
  116. };
  117. #if 0
  118. *ExtScanNames[] = // Names corresponding to ExtScanCodes
  119. {
  120. "Esc","BkSp","Tab","Ctrl","LShft","Space","CapsLk","F1","F2","F3","F4",
  121. "F5","F6","F7","F8","F9","F10","F11","F12","ScrlLk","Enter","RShft",
  122. "PrtSc","Alt","Home","PgUp","End","PgDn","Ins","Del","NumLk","Up",
  123. "Down","Left","Right",""
  124. };
  125. #endif
  126. static Direction DirTable[] = // Quick lookup for total direction
  127. {
  128. dir_NorthWest, dir_North, dir_NorthEast,
  129. dir_West, dir_None, dir_East,
  130. dir_SouthWest, dir_South, dir_SouthEast
  131. };
  132. static void (*INL_KeyHook)(void);
  133. static void interrupt (*OldKeyVect)(void);
  134. static char *ParmStrings[] = {"nojoys","nomouse",nil};
  135. // Internal routines
  136. ///////////////////////////////////////////////////////////////////////////
  137. //
  138. // INL_KeyService() - Handles a keyboard interrupt (key up/down)
  139. //
  140. ///////////////////////////////////////////////////////////////////////////
  141. static void interrupt
  142. INL_KeyService(void)
  143. {
  144. static boolean special;
  145. byte k,c,
  146. temp;
  147. k = inportb(0x60); // Get the scan code
  148. // Tell the XT keyboard controller to clear the key
  149. outportb(0x61,(temp = inportb(0x61)) | 0x80);
  150. outportb(0x61,temp);
  151. if (k == 0xe0) // Special key prefix
  152. special = true;
  153. else if (k == 0xe1) // Handle Pause key
  154. Paused = true;
  155. else
  156. {
  157. if (k & 0x80) // Break code
  158. {
  159. k &= 0x7f;
  160. // DEBUG - handle special keys: ctl-alt-delete, print scrn
  161. Keyboard[k] = false;
  162. }
  163. else // Make code
  164. {
  165. LastCode = CurCode;
  166. CurCode = LastScan = k;
  167. Keyboard[k] = true;
  168. if (special)
  169. c = SpecialNames[k];
  170. else
  171. {
  172. if (k == sc_CapsLock)
  173. {
  174. CapsLock ^= true;
  175. // DEBUG - make caps lock light work
  176. }
  177. if (Keyboard[sc_LShift] || Keyboard[sc_RShift]) // If shifted
  178. {
  179. c = ShiftNames[k];
  180. if ((c >= 'A') && (c <= 'Z') && CapsLock)
  181. c += 'a' - 'A';
  182. }
  183. else
  184. {
  185. c = ASCIINames[k];
  186. if ((c >= 'a') && (c <= 'z') && CapsLock)
  187. c -= 'a' - 'A';
  188. }
  189. }
  190. if (c)
  191. LastASCII = c;
  192. }
  193. special = false;
  194. }
  195. if (INL_KeyHook && !special)
  196. INL_KeyHook();
  197. outportb(0x20,0x20);
  198. }
  199. ///////////////////////////////////////////////////////////////////////////
  200. //
  201. // INL_GetMouseDelta() - Gets the amount that the mouse has moved from the
  202. // mouse driver
  203. //
  204. ///////////////////////////////////////////////////////////////////////////
  205. static void
  206. INL_GetMouseDelta(int *x,int *y)
  207. {
  208. Mouse(MDelta);
  209. *x = _CX;
  210. *y = _DX;
  211. }
  212. ///////////////////////////////////////////////////////////////////////////
  213. //
  214. // INL_GetMouseButtons() - Gets the status of the mouse buttons from the
  215. // mouse driver
  216. //
  217. ///////////////////////////////////////////////////////////////////////////
  218. static word
  219. INL_GetMouseButtons(void)
  220. {
  221. word buttons;
  222. Mouse(MButtons);
  223. buttons = _BX;
  224. return(buttons);
  225. }
  226. ///////////////////////////////////////////////////////////////////////////
  227. //
  228. // IN_GetJoyAbs() - Reads the absolute position of the specified joystick
  229. //
  230. ///////////////////////////////////////////////////////////////////////////
  231. void
  232. IN_GetJoyAbs(word joy,word *xp,word *yp)
  233. {
  234. byte xb,yb,
  235. xs,ys;
  236. word x,y;
  237. x = y = 0;
  238. xs = joy? 2 : 0; // Find shift value for x axis
  239. xb = 1 << xs; // Use shift value to get x bit mask
  240. ys = joy? 3 : 1; // Do the same for y axis
  241. yb = 1 << ys;
  242. // Read the absolute joystick values
  243. asm pushf // Save some registers
  244. asm push si
  245. asm push di
  246. asm cli // Make sure an interrupt doesn't screw the timings
  247. asm mov dx,0x201
  248. asm in al,dx
  249. asm out dx,al // Clear the resistors
  250. asm mov ah,[xb] // Get masks into registers
  251. asm mov ch,[yb]
  252. asm xor si,si // Clear count registers
  253. asm xor di,di
  254. asm xor bh,bh // Clear high byte of bx for later
  255. asm push bp // Don't mess up stack frame
  256. asm mov bp,MaxJoyValue
  257. loop:
  258. asm in al,dx // Get bits indicating whether all are finished
  259. asm dec bp // Check bounding register
  260. asm jz done // We have a silly value - abort
  261. asm mov bl,al // Duplicate the bits
  262. asm and bl,ah // Mask off useless bits (in [xb])
  263. asm add si,bx // Possibly increment count register
  264. asm mov cl,bl // Save for testing later
  265. asm mov bl,al
  266. asm and bl,ch // [yb]
  267. asm add di,bx
  268. asm add cl,bl
  269. asm jnz loop // If both bits were 0, drop out
  270. done:
  271. asm pop bp
  272. asm mov cl,[xs] // Get the number of bits to shift
  273. asm shr si,cl // and shift the count that many times
  274. asm mov cl,[ys]
  275. asm shr di,cl
  276. asm mov [x],si // Store the values into the variables
  277. asm mov [y],di
  278. asm pop di
  279. asm pop si
  280. asm popf // Restore the registers
  281. *xp = x;
  282. *yp = y;
  283. }
  284. ///////////////////////////////////////////////////////////////////////////
  285. //
  286. // INL_GetJoyDelta() - Returns the relative movement of the specified
  287. // joystick (from +/-127, scaled adaptively)
  288. //
  289. ///////////////////////////////////////////////////////////////////////////
  290. static void
  291. INL_GetJoyDelta(word joy,int *dx,int *dy,boolean adaptive)
  292. {
  293. word x,y;
  294. longword time;
  295. JoystickDef *def;
  296. static longword lasttime;
  297. IN_GetJoyAbs(joy,&x,&y);
  298. def = JoyDefs + joy;
  299. if (x < def->threshMinX)
  300. {
  301. if (x < def->joyMinX)
  302. x = def->joyMinX;
  303. x = -(x - def->threshMinX);
  304. x *= def->joyMultXL;
  305. x >>= JoyScaleShift;
  306. *dx = (x > 127)? -127 : -x;
  307. }
  308. else if (x > def->threshMaxX)
  309. {
  310. if (x > def->joyMaxX)
  311. x = def->joyMaxX;
  312. x = x - def->threshMaxX;
  313. x *= def->joyMultXH;
  314. x >>= JoyScaleShift;
  315. *dx = (x > 127)? 127 : x;
  316. }
  317. else
  318. *dx = 0;
  319. if (y < def->threshMinY)
  320. {
  321. if (y < def->joyMinY)
  322. y = def->joyMinY;
  323. y = -(y - def->threshMinY);
  324. y *= def->joyMultYL;
  325. y >>= JoyScaleShift;
  326. *dy = (y > 127)? -127 : -y;
  327. }
  328. else if (y > def->threshMaxY)
  329. {
  330. if (y > def->joyMaxY)
  331. y = def->joyMaxY;
  332. y = y - def->threshMaxY;
  333. y *= def->joyMultYH;
  334. y >>= JoyScaleShift;
  335. *dy = (y > 127)? 127 : y;
  336. }
  337. else
  338. *dy = 0;
  339. if (adaptive)
  340. {
  341. time = (TimeCount - lasttime) / 2;
  342. if (time)
  343. {
  344. if (time > 8)
  345. time = 8;
  346. *dx *= time;
  347. *dy *= time;
  348. }
  349. }
  350. lasttime = TimeCount;
  351. }
  352. ///////////////////////////////////////////////////////////////////////////
  353. //
  354. // INL_GetJoyButtons() - Returns the button status of the specified
  355. // joystick
  356. //
  357. ///////////////////////////////////////////////////////////////////////////
  358. static word
  359. INL_GetJoyButtons(word joy)
  360. {
  361. register word result;
  362. result = inportb(0x201); // Get all the joystick buttons
  363. result >>= joy? 6 : 4; // Shift into bits 0-1
  364. result &= 3; // Mask off the useless bits
  365. result ^= 3;
  366. return(result);
  367. }
  368. ///////////////////////////////////////////////////////////////////////////
  369. //
  370. // IN_GetJoyButtonsDB() - Returns the de-bounced button status of the
  371. // specified joystick
  372. //
  373. ///////////////////////////////////////////////////////////////////////////
  374. word
  375. IN_GetJoyButtonsDB(word joy)
  376. {
  377. longword lasttime;
  378. word result1,result2;
  379. do
  380. {
  381. result1 = INL_GetJoyButtons(joy);
  382. lasttime = TimeCount;
  383. while (TimeCount == lasttime)
  384. ;
  385. result2 = INL_GetJoyButtons(joy);
  386. } while (result1 != result2);
  387. return(result1);
  388. }
  389. ///////////////////////////////////////////////////////////////////////////
  390. //
  391. // INL_StartKbd() - Sets up my keyboard stuff for use
  392. //
  393. ///////////////////////////////////////////////////////////////////////////
  394. static void
  395. INL_StartKbd(void)
  396. {
  397. INL_KeyHook = 0; // Clear key hook
  398. IN_ClearKeysDown();
  399. OldKeyVect = getvect(KeyInt);
  400. setvect(KeyInt,INL_KeyService);
  401. }
  402. ///////////////////////////////////////////////////////////////////////////
  403. //
  404. // INL_ShutKbd() - Restores keyboard control to the BIOS
  405. //
  406. ///////////////////////////////////////////////////////////////////////////
  407. static void
  408. INL_ShutKbd(void)
  409. {
  410. poke(0x40,0x17,peek(0x40,0x17) & 0xfaf0); // Clear ctrl/alt/shift flags
  411. setvect(KeyInt,OldKeyVect);
  412. }
  413. ///////////////////////////////////////////////////////////////////////////
  414. //
  415. // INL_StartMouse() - Detects and sets up the mouse
  416. //
  417. ///////////////////////////////////////////////////////////////////////////
  418. static boolean
  419. INL_StartMouse(void)
  420. {
  421. if (getvect(MouseInt))
  422. {
  423. Mouse(MReset);
  424. if (_AX == 0xffff)
  425. return(true);
  426. }
  427. return(false);
  428. }
  429. ///////////////////////////////////////////////////////////////////////////
  430. //
  431. // INL_ShutMouse() - Cleans up after the mouse
  432. //
  433. ///////////////////////////////////////////////////////////////////////////
  434. static void
  435. INL_ShutMouse(void)
  436. {
  437. }
  438. //
  439. // INL_SetJoyScale() - Sets up scaling values for the specified joystick
  440. //
  441. static void
  442. INL_SetJoyScale(word joy)
  443. {
  444. JoystickDef *def;
  445. def = &JoyDefs[joy];
  446. def->joyMultXL = JoyScaleMax / (def->threshMinX - def->joyMinX);
  447. def->joyMultXH = JoyScaleMax / (def->joyMaxX - def->threshMaxX);
  448. def->joyMultYL = JoyScaleMax / (def->threshMinY - def->joyMinY);
  449. def->joyMultYH = JoyScaleMax / (def->joyMaxY - def->threshMaxY);
  450. }
  451. ///////////////////////////////////////////////////////////////////////////
  452. //
  453. // IN_SetupJoy() - Sets up thresholding values and calls INL_SetJoyScale()
  454. // to set up scaling values
  455. //
  456. ///////////////////////////////////////////////////////////////////////////
  457. void
  458. IN_SetupJoy(word joy,word minx,word maxx,word miny,word maxy)
  459. {
  460. word d,r;
  461. JoystickDef *def;
  462. def = &JoyDefs[joy];
  463. def->joyMinX = minx;
  464. def->joyMaxX = maxx;
  465. r = maxx - minx;
  466. d = r / 5;
  467. def->threshMinX = ((r / 2) - d) + minx;
  468. def->threshMaxX = ((r / 2) + d) + minx;
  469. def->joyMinY = miny;
  470. def->joyMaxY = maxy;
  471. r = maxy - miny;
  472. d = r / 5;
  473. def->threshMinY = ((r / 2) - d) + miny;
  474. def->threshMaxY = ((r / 2) + d) + miny;
  475. INL_SetJoyScale(joy);
  476. }
  477. ///////////////////////////////////////////////////////////////////////////
  478. //
  479. // INL_StartJoy() - Detects & auto-configures the specified joystick
  480. // The auto-config assumes the joystick is centered
  481. //
  482. ///////////////////////////////////////////////////////////////////////////
  483. static boolean
  484. INL_StartJoy(word joy)
  485. {
  486. word x,y;
  487. IN_GetJoyAbs(joy,&x,&y);
  488. if
  489. (
  490. ((x == 0) || (x > MaxJoyValue - 10))
  491. || ((y == 0) || (y > MaxJoyValue - 10))
  492. )
  493. return(false);
  494. else
  495. {
  496. IN_SetupJoy(joy,0,x * 2,0,y * 2);
  497. return(true);
  498. }
  499. }
  500. ///////////////////////////////////////////////////////////////////////////
  501. //
  502. // INL_ShutJoy() - Cleans up the joystick stuff
  503. //
  504. ///////////////////////////////////////////////////////////////////////////
  505. static void
  506. INL_ShutJoy(word joy)
  507. {
  508. JoysPresent[joy] = false;
  509. }
  510. // Public routines
  511. ///////////////////////////////////////////////////////////////////////////
  512. //
  513. // IN_Startup() - Starts up the Input Mgr
  514. //
  515. ///////////////////////////////////////////////////////////////////////////
  516. void
  517. IN_Startup(void)
  518. {
  519. boolean checkjoys,checkmouse;
  520. word i;
  521. if (IN_Started)
  522. return;
  523. checkjoys = true;
  524. checkmouse = true;
  525. for (i = 1;i < _argc;i++)
  526. {
  527. switch (US_CheckParm(_argv[i],ParmStrings))
  528. {
  529. case 0:
  530. checkjoys = false;
  531. break;
  532. case 1:
  533. checkmouse = false;
  534. break;
  535. }
  536. }
  537. INL_StartKbd();
  538. MousePresent = checkmouse? INL_StartMouse() : false;
  539. for (i = 0;i < MaxJoys;i++)
  540. JoysPresent[i] = checkjoys? INL_StartJoy(i) : false;
  541. IN_Started = true;
  542. }
  543. ///////////////////////////////////////////////////////////////////////////
  544. //
  545. // IN_Default() - Sets up default conditions for the Input Mgr
  546. //
  547. ///////////////////////////////////////////////////////////////////////////
  548. void
  549. IN_Default(boolean gotit,ControlType in)
  550. {
  551. if
  552. (
  553. (!gotit)
  554. || ((in == ctrl_Joystick1) && !JoysPresent[0])
  555. || ((in == ctrl_Joystick2) && !JoysPresent[1])
  556. || ((in == ctrl_Mouse) && !MousePresent)
  557. )
  558. in = ctrl_Keyboard1;
  559. IN_SetControlType(0,in);
  560. }
  561. ///////////////////////////////////////////////////////////////////////////
  562. //
  563. // IN_Shutdown() - Shuts down the Input Mgr
  564. //
  565. ///////////////////////////////////////////////////////////////////////////
  566. void
  567. IN_Shutdown(void)
  568. {
  569. word i;
  570. if (!IN_Started)
  571. return;
  572. INL_ShutMouse();
  573. for (i = 0;i < MaxJoys;i++)
  574. INL_ShutJoy(i);
  575. INL_ShutKbd();
  576. IN_Started = false;
  577. }
  578. ///////////////////////////////////////////////////////////////////////////
  579. //
  580. // IN_SetKeyHook() - Sets the routine that gets called by INL_KeyService()
  581. // everytime a real make/break code gets hit
  582. //
  583. ///////////////////////////////////////////////////////////////////////////
  584. void
  585. IN_SetKeyHook(void (*hook)())
  586. {
  587. INL_KeyHook = hook;
  588. }
  589. ///////////////////////////////////////////////////////////////////////////
  590. //
  591. // IN_ClearKeyDown() - Clears the keyboard array
  592. //
  593. ///////////////////////////////////////////////////////////////////////////
  594. void
  595. IN_ClearKeysDown(void)
  596. {
  597. int i;
  598. LastScan = sc_None;
  599. LastASCII = key_None;
  600. for (i = 0;i < NumCodes;i++)
  601. Keyboard[i] = false;
  602. }
  603. ///////////////////////////////////////////////////////////////////////////
  604. //
  605. // INL_AdjustCursor() - Internal routine of common code from IN_ReadCursor()
  606. //
  607. ///////////////////////////////////////////////////////////////////////////
  608. static void
  609. INL_AdjustCursor(CursorInfo *info,word buttons,int dx,int dy)
  610. {
  611. if (buttons & (1 << 0))
  612. info->button0 = true;
  613. if (buttons & (1 << 1))
  614. info->button1 = true;
  615. info->x += dx;
  616. info->y += dy;
  617. }
  618. ///////////////////////////////////////////////////////////////////////////
  619. //
  620. // IN_ReadCursor() - Reads the input devices and fills in the cursor info
  621. // struct
  622. //
  623. ///////////////////////////////////////////////////////////////////////////
  624. void
  625. IN_ReadCursor(CursorInfo *info)
  626. {
  627. word i,
  628. buttons;
  629. int dx,dy;
  630. info->x = info->y = 0;
  631. info->button0 = info->button1 = false;
  632. if (MousePresent)
  633. {
  634. buttons = INL_GetMouseButtons();
  635. INL_GetMouseDelta(&dx,&dy);
  636. INL_AdjustCursor(info,buttons,dx,dy);
  637. }
  638. for (i = 0;i < MaxJoys;i++)
  639. {
  640. if (!JoysPresent[i])
  641. continue;
  642. buttons = INL_GetJoyButtons(i);
  643. INL_GetJoyDelta(i,&dx,&dy,true);
  644. dx /= 64;
  645. dy /= 64;
  646. INL_AdjustCursor(info,buttons,dx,dy);
  647. }
  648. }
  649. ///////////////////////////////////////////////////////////////////////////
  650. //
  651. // IN_ReadControl() - Reads the device associated with the specified
  652. // player and fills in the control info struct
  653. //
  654. ///////////////////////////////////////////////////////////////////////////
  655. void
  656. IN_ReadControl(int player,ControlInfo *info)
  657. {
  658. boolean realdelta=false; // MDM (GAMERS EDGE)
  659. byte dbyte;
  660. word buttons;
  661. int dx,dy;
  662. Motion mx,my;
  663. ControlType type;
  664. register KeyboardDef *def;
  665. dx = dy = 0;
  666. mx = my = motion_None;
  667. buttons = 0;
  668. #if 0
  669. if (DemoMode == demo_Playback)
  670. {
  671. dbyte = DemoBuffer[DemoOffset + 1];
  672. my = (dbyte & 3) - 1;
  673. mx = ((dbyte >> 2) & 3) - 1;
  674. buttons = (dbyte >> 4) & 3;
  675. if (!(--DemoBuffer[DemoOffset]))
  676. {
  677. DemoOffset += 2;
  678. if (DemoOffset >= DemoSize)
  679. DemoMode = demo_PlayDone;
  680. }
  681. realdelta = false;
  682. }
  683. else if (DemoMode == demo_PlayDone)
  684. Quit("Demo playback exceeded");
  685. else
  686. #endif
  687. {
  688. // MDM begin (GAMERS EDGE) - added this block
  689. ControlTypeUsed = ctrl_None;
  690. // Handle mouse input...
  691. //
  692. if ((MousePresent) && (ControlTypeUsed == ctrl_None))
  693. {
  694. INL_GetMouseDelta(&dx,&dy);
  695. buttons = INL_GetMouseButtons();
  696. realdelta = true;
  697. if (dx || dy || buttons)
  698. ControlTypeUsed = ctrl_Mouse;
  699. }
  700. // Handle joystick input...
  701. //
  702. if ((JoystickCalibrated) && (ControlTypeUsed == ctrl_None))
  703. {
  704. type = ctrl_Joystick1;
  705. INL_GetJoyDelta(type - ctrl_Joystick,&dx,&dy,false);
  706. buttons = INL_GetJoyButtons(type - ctrl_Joystick);
  707. realdelta = true;
  708. if (dx || dy || buttons)
  709. ControlTypeUsed = ctrl_Joystick;
  710. }
  711. // Handle keyboard input...
  712. //
  713. if (ControlTypeUsed == ctrl_None)
  714. {
  715. type = ctrl_Keyboard1;
  716. def = &KbdDefs[type - ctrl_Keyboard];
  717. if (Keyboard[def->upleft])
  718. mx = motion_Left,my = motion_Up;
  719. else if (Keyboard[def->upright])
  720. mx = motion_Right,my = motion_Up;
  721. else if (Keyboard[def->downleft])
  722. mx = motion_Left,my = motion_Down;
  723. else if (Keyboard[def->downright])
  724. mx = motion_Right,my = motion_Down;
  725. if (Keyboard[def->up])
  726. my = motion_Up;
  727. else if (Keyboard[def->down])
  728. my = motion_Down;
  729. if (Keyboard[def->left])
  730. mx = motion_Left;
  731. else if (Keyboard[def->right])
  732. mx = motion_Right;
  733. if (Keyboard[def->button0])
  734. buttons += 1 << 0;
  735. if (Keyboard[def->button1])
  736. buttons += 1 << 1;
  737. realdelta = false;
  738. if (mx || my || buttons)
  739. ControlTypeUsed = ctrl_Keyboard;
  740. } // MDM end (GAMERS EDGE)
  741. }
  742. if (realdelta)
  743. {
  744. mx = (dx < 0)? motion_Left : ((dx > 0)? motion_Right : motion_None);
  745. my = (dy < 0)? motion_Up : ((dy > 0)? motion_Down : motion_None);
  746. }
  747. else
  748. {
  749. dx = mx * 127;
  750. dy = my * 127;
  751. }
  752. info->x = dx;
  753. info->xaxis = mx;
  754. info->y = dy;
  755. info->yaxis = my;
  756. info->button0 = buttons & (1 << 0);
  757. info->button1 = buttons & (1 << 1);
  758. info->dir = DirTable[((my + 1) * 3) + (mx + 1)];
  759. #if 0
  760. if (DemoMode == demo_Record)
  761. {
  762. // Pack the control info into a byte
  763. dbyte = (buttons << 4) | ((mx + 1) << 2) | (my + 1);
  764. if
  765. (
  766. (DemoBuffer[DemoOffset + 1] == dbyte)
  767. && (DemoBuffer[DemoOffset] < 255)
  768. )
  769. (DemoBuffer[DemoOffset])++;
  770. else
  771. {
  772. if (DemoOffset || DemoBuffer[DemoOffset])
  773. DemoOffset += 2;
  774. if (DemoOffset >= DemoSize)
  775. Quit("Demo buffer overflow");
  776. DemoBuffer[DemoOffset] = 1;
  777. DemoBuffer[DemoOffset + 1] = dbyte;
  778. }
  779. }
  780. #endif
  781. }
  782. #if 0
  783. ///////////////////////////////////////////////////////////////////////////
  784. //
  785. // IN_ReadControl() - Reads the device associated with the specified
  786. // player and fills in the control info struct
  787. //
  788. ///////////////////////////////////////////////////////////////////////////
  789. void
  790. IN_ReadControl(int player,ControlInfo *info)
  791. {
  792. boolean realdelta;
  793. byte dbyte;
  794. word buttons;
  795. int dx,dy;
  796. Motion mx,my;
  797. ControlType type;
  798. register KeyboardDef *def;
  799. dx = dy = 0;
  800. mx = my = motion_None;
  801. buttons = 0;
  802. #if 0
  803. if (DemoMode == demo_Playback)
  804. {
  805. dbyte = DemoBuffer[DemoOffset + 1];
  806. my = (dbyte & 3) - 1;
  807. mx = ((dbyte >> 2) & 3) - 1;
  808. buttons = (dbyte >> 4) & 3;
  809. if (!(--DemoBuffer[DemoOffset]))
  810. {
  811. DemoOffset += 2;
  812. if (DemoOffset >= DemoSize)
  813. DemoMode = demo_PlayDone;
  814. }
  815. realdelta = false;
  816. }
  817. else if (DemoMode == demo_PlayDone)
  818. Quit("Demo playback exceeded");
  819. else
  820. #endif
  821. {
  822. switch (type = Controls[player])
  823. {
  824. case ctrl_Keyboard1:
  825. case ctrl_Keyboard2:
  826. def = &KbdDefs[type - ctrl_Keyboard];
  827. if (Keyboard[def->upleft])
  828. mx = motion_Left,my = motion_Up;
  829. else if (Keyboard[def->upright])
  830. mx = motion_Right,my = motion_Up;
  831. else if (Keyboard[def->downleft])
  832. mx = motion_Left,my = motion_Down;
  833. else if (Keyboard[def->downright])
  834. mx = motion_Right,my = motion_Down;
  835. if (Keyboard[def->up])
  836. my = motion_Up;
  837. else if (Keyboard[def->down])
  838. my = motion_Down;
  839. if (Keyboard[def->left])
  840. mx = motion_Left;
  841. else if (Keyboard[def->right])
  842. mx = motion_Right;
  843. if (Keyboard[def->button0])
  844. buttons += 1 << 0;
  845. if (Keyboard[def->button1])
  846. buttons += 1 << 1;
  847. realdelta = false;
  848. break;
  849. case ctrl_Joystick1:
  850. case ctrl_Joystick2:
  851. INL_GetJoyDelta(type - ctrl_Joystick,&dx,&dy,false);
  852. buttons = INL_GetJoyButtons(type - ctrl_Joystick);
  853. realdelta = true;
  854. break;
  855. case ctrl_Mouse:
  856. INL_GetMouseDelta(&dx,&dy);
  857. buttons = INL_GetMouseButtons();
  858. realdelta = true;
  859. break;
  860. }
  861. }
  862. if (realdelta)
  863. {
  864. mx = (dx < 0)? motion_Left : ((dx > 0)? motion_Right : motion_None);
  865. my = (dy < 0)? motion_Up : ((dy > 0)? motion_Down : motion_None);
  866. }
  867. else
  868. {
  869. dx = mx * 127;
  870. dy = my * 127;
  871. }
  872. info->x = dx;
  873. info->xaxis = mx;
  874. info->y = dy;
  875. info->yaxis = my;
  876. info->button0 = buttons & (1 << 0);
  877. info->button1 = buttons & (1 << 1);
  878. info->dir = DirTable[((my + 1) * 3) + (mx + 1)];
  879. #if 0
  880. if (DemoMode == demo_Record)
  881. {
  882. // Pack the control info into a byte
  883. dbyte = (buttons << 4) | ((mx + 1) << 2) | (my + 1);
  884. if
  885. (
  886. (DemoBuffer[DemoOffset + 1] == dbyte)
  887. && (DemoBuffer[DemoOffset] < 255)
  888. )
  889. (DemoBuffer[DemoOffset])++;
  890. else
  891. {
  892. if (DemoOffset || DemoBuffer[DemoOffset])
  893. DemoOffset += 2;
  894. if (DemoOffset >= DemoSize)
  895. Quit("Demo buffer overflow");
  896. DemoBuffer[DemoOffset] = 1;
  897. DemoBuffer[DemoOffset + 1] = dbyte;
  898. }
  899. }
  900. #endif
  901. }
  902. #endif
  903. ///////////////////////////////////////////////////////////////////////////
  904. //
  905. // IN_SetControlType() - Sets the control type to be used by the specified
  906. // player
  907. //
  908. ///////////////////////////////////////////////////////////////////////////
  909. void
  910. IN_SetControlType(int player,ControlType type)
  911. {
  912. // DEBUG - check that requested type is present?
  913. Controls[player] = type;
  914. }
  915. #if 0
  916. ///////////////////////////////////////////////////////////////////////////
  917. //
  918. // IN_StartDemoRecord() - Starts the demo recording, using a buffer the
  919. // size passed. Returns if the buffer allocation was successful
  920. //
  921. ///////////////////////////////////////////////////////////////////////////
  922. boolean
  923. IN_StartDemoRecord(word bufsize)
  924. {
  925. if (!bufsize)
  926. return(false);
  927. MM_GetPtr((memptr *)&DemoBuffer,bufsize);
  928. DemoMode = demo_Record;
  929. DemoSize = bufsize & ~1;
  930. DemoOffset = 0;
  931. DemoBuffer[0] = DemoBuffer[1] = 0;
  932. return(true);
  933. }
  934. ///////////////////////////////////////////////////////////////////////////
  935. //
  936. // IN_StartDemoPlayback() - Plays back the demo pointed to of the given size
  937. //
  938. ///////////////////////////////////////////////////////////////////////////
  939. void
  940. IN_StartDemoPlayback(byte _seg *buffer,word bufsize)
  941. {
  942. DemoBuffer = buffer;
  943. DemoMode = demo_Playback;
  944. DemoSize = bufsize & ~1;
  945. DemoOffset = 0;
  946. }
  947. ///////////////////////////////////////////////////////////////////////////
  948. //
  949. // IN_StopDemo() - Turns off demo mode
  950. //
  951. ///////////////////////////////////////////////////////////////////////////
  952. void
  953. IN_StopDemo(void)
  954. {
  955. if ((DemoMode == demo_Record) && DemoOffset)
  956. DemoOffset += 2;
  957. DemoMode = demo_Off;
  958. }
  959. ///////////////////////////////////////////////////////////////////////////
  960. //
  961. // IN_FreeDemoBuffer() - Frees the demo buffer, if it's been allocated
  962. //
  963. ///////////////////////////////////////////////////////////////////////////
  964. void
  965. IN_FreeDemoBuffer(void)
  966. {
  967. if (DemoBuffer)
  968. MM_FreePtr((memptr *)&DemoBuffer);
  969. }
  970. #endif
  971. #if 0
  972. ///////////////////////////////////////////////////////////////////////////
  973. //
  974. // IN_GetScanName() - Returns a string containing the name of the
  975. // specified scan code
  976. //
  977. ///////////////////////////////////////////////////////////////////////////
  978. byte *
  979. IN_GetScanName(ScanCode scan)
  980. {
  981. byte **p;
  982. ScanCode far *s;
  983. for (s = ExtScanCodes,p = ExtScanNames;*s;p++,s++)
  984. if (*s == scan)
  985. return(*p);
  986. return(ScanNames[scan]);
  987. }
  988. #endif
  989. ///////////////////////////////////////////////////////////////////////////
  990. //
  991. // IN_WaitForKey() - Waits for a scan code, then clears LastScan and
  992. // returns the scan code
  993. //
  994. ///////////////////////////////////////////////////////////////////////////
  995. ScanCode
  996. IN_WaitForKey(void)
  997. {
  998. ScanCode result;
  999. while (!(result = LastScan))
  1000. ;
  1001. LastScan = 0;
  1002. return(result);
  1003. }
  1004. ///////////////////////////////////////////////////////////////////////////
  1005. //
  1006. // IN_WaitForASCII() - Waits for an ASCII char, then clears LastASCII and
  1007. // returns the ASCII value
  1008. //
  1009. ///////////////////////////////////////////////////////////////////////////
  1010. char
  1011. IN_WaitForASCII(void)
  1012. {
  1013. char result;
  1014. while (!(result = LastASCII))
  1015. ;
  1016. LastASCII = '\0';
  1017. return(result);
  1018. }
  1019. ///////////////////////////////////////////////////////////////////////////
  1020. //
  1021. // IN_AckBack() - Waits for either an ASCII keypress or a button press
  1022. //
  1023. ///////////////////////////////////////////////////////////////////////////
  1024. void
  1025. IN_AckBack(void)
  1026. {
  1027. word i;
  1028. while (!LastScan)
  1029. {
  1030. if (MousePresent)
  1031. {
  1032. if (INL_GetMouseButtons())
  1033. {
  1034. while (INL_GetMouseButtons())
  1035. ;
  1036. return;
  1037. }
  1038. }
  1039. for (i = 0;i < MaxJoys;i++)
  1040. {
  1041. if (JoysPresent[i])
  1042. {
  1043. if (IN_GetJoyButtonsDB(i))
  1044. {
  1045. while (IN_GetJoyButtonsDB(i))
  1046. ;
  1047. return;
  1048. }
  1049. }
  1050. }
  1051. }
  1052. IN_ClearKey(LastScan);
  1053. LastScan = sc_None;
  1054. }
  1055. ///////////////////////////////////////////////////////////////////////////
  1056. //
  1057. // IN_Ack() - Clears user input & then calls IN_AckBack()
  1058. //
  1059. ///////////////////////////////////////////////////////////////////////////
  1060. void
  1061. IN_Ack(void)
  1062. {
  1063. word i;
  1064. IN_ClearKey(LastScan);
  1065. LastScan = sc_None;
  1066. if (MousePresent)
  1067. while (INL_GetMouseButtons())
  1068. ;
  1069. for (i = 0;i < MaxJoys;i++)
  1070. if (JoysPresent[i])
  1071. while (IN_GetJoyButtonsDB(i))
  1072. ;
  1073. IN_AckBack();
  1074. }
  1075. ///////////////////////////////////////////////////////////////////////////
  1076. //
  1077. // IN_IsUserInput() - Returns true if a key has been pressed or a button
  1078. // is down
  1079. //
  1080. ///////////////////////////////////////////////////////////////////////////
  1081. boolean
  1082. IN_IsUserInput(void)
  1083. {
  1084. boolean result;
  1085. word i;
  1086. result = LastScan;
  1087. if (MousePresent)
  1088. if (INL_GetMouseButtons())
  1089. result = true;
  1090. for (i = 0;i < MaxJoys;i++)
  1091. if (JoysPresent[i])
  1092. if (INL_GetJoyButtons(i))
  1093. result = true;
  1094. return(result);
  1095. }
  1096. ///////////////////////////////////////////////////////////////////////////
  1097. //
  1098. // IN_UserInput() - Waits for the specified delay time (in ticks) or the
  1099. // user pressing a key or a mouse button. If the clear flag is set, it
  1100. // then either clears the key or waits for the user to let the mouse
  1101. // button up.
  1102. //
  1103. ///////////////////////////////////////////////////////////////////////////
  1104. boolean
  1105. IN_UserInput(longword delay,boolean clear)
  1106. {
  1107. longword lasttime;
  1108. lasttime = TimeCount;
  1109. do
  1110. {
  1111. if (IN_IsUserInput())
  1112. {
  1113. if (clear)
  1114. IN_AckBack();
  1115. return(true);
  1116. }
  1117. } while (TimeCount - lasttime < delay);
  1118. return(false);
  1119. }