KEYIPROT.ASM 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023
  1. ;
  2. ; Command & Conquer Red Alert(tm)
  3. ; Copyright 2025 Electronic Arts Inc.
  4. ;
  5. ; This program is free software: you can redistribute it and/or modify
  6. ; it under the terms of the GNU General Public License as published by
  7. ; the Free Software Foundation, either version 3 of the License, or
  8. ; (at your option) any later version.
  9. ;
  10. ; This program is distributed in the hope that it will be useful,
  11. ; but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. ; GNU General Public License for more details.
  14. ;
  15. ; You should have received a copy of the GNU General Public License
  16. ; along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. ;
  18. ;***************************************************************************
  19. ;** C O N F I D E N T I A L --- W E S T W O O D A S S O C I A T E S **
  20. ;***************************************************************************
  21. ;* *
  22. ;* Project Name : Library *
  23. ;* *
  24. ;* File Name : KEYINTR.ASM *
  25. ;* *
  26. ;* Programmer : Christopher Yates *
  27. ;* *
  28. ;* Start Date : May 21, 1992 *
  29. ;* *
  30. ;* Last Update : July 13, 1994 [PWG] *
  31. ;* *
  32. ;*-------------------------------------------------------------------------*
  33. ;* Functions: *
  34. ;* KeyNum_Translate -- Translates the given keynum to ??? *
  35. ;* Install_Interrupt -- Installs the keyboard interrupt *
  36. ;* Stuff_Key_Word -- Stuffs a word of data into keyboard buffer *
  37. ;* Stuff_Key_Num -- Stuffs a key num code into the circular buffer *
  38. ;* Remove_Interrupt -- Removes the keyboard interrupt and restores the chai*
  39. ;* Keystroke_Interrupt -- Handles input that comes from the keyboard *
  40. ;* Break_Interrupt -- Handles the break key interrupt *
  41. ;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *
  42. ;* *
  43. ;* Keyboard driver -- 8086 Assembly portion; *
  44. ;* updated by: Phil Gorrow for 32 bit Protected Mode *
  45. ;***************************************************************************
  46. ;---------------------------------------------------------------------------
  47. ; Set the assembly directives
  48. ;---------------------------------------------------------------------------
  49. IDEAL ; the product runs in ideal mode
  50. P386N ; use 386 real mode instructions
  51. MODEL TINY ; code must be tiny so it fits
  52. LOCALS ?? ; ?? is the symbol for a local
  53. WARN ; generate all warnings we can
  54. JUMPS ; optimize jumps if possible
  55. ;---------------------------------------------------------------------------
  56. ; Include all of the keyboard specific defines
  57. ;---------------------------------------------------------------------------
  58. INCLUDE "keyboard.inc"
  59. CODESEG
  60. SoundOn DW 1 ; toggled by alt S
  61. MusicOn DW 1 ; toggled by alt M
  62. KeyFlags DW REPEATON+CTRLALTTURBO ; all but repeat for now
  63. Break DW 0
  64. KeyMouseMove DB -1,0,1
  65. DB -16,0,16
  66. ScreenEdge DW 320/2,0 ; North
  67. DW 319,0 ; North-East
  68. DW 319,138/2 ; East
  69. DW 319,137 ; South-East
  70. DW 320/2,137 ; South
  71. DW 0,137 ; South-West
  72. DW 0,138/2 ; West
  73. DW 0,0 ; North-West
  74. DW 320/2,138/2 ; Center
  75. Bits DB 01H,02H,04H,08H,10H,20H,40H,80H
  76. CondPassKey DW 0220H, 0320H, 060CH, 070DH, 066AH
  77. DW 0669H, 0230H, 0330H, 007DH, 017DH
  78. DW 025AH, 035AH, 0200H, 0410H, 046EH
  79. DW 026EH, 007CH
  80. CondPassCond DW CTRLSON, CTRLSON, CTRLALTTURBO, CTRLALTTURBO, CTRLALTTURBO
  81. DW CTRLALTTURBO, CTRLCON, CTRLCON, SCROLLLOCKON, SCROLLLOCKON
  82. DW PAUSEON, PAUSEON, BREAKON, TASKSWITCHABLE, TASKSWITCHABLE
  83. DW TASKSWITCHABLE, BREAKON
  84. EscRoutine DD 0 ; vector to execute on esc key press (0=none)
  85. ; Extended raw keycodes to be converted to Westwood keycodes.
  86. ExtCodes DB 038H,01DH,052H,053H,04BH,047H,04FH,048H,050H,049H
  87. DB 051H,04DH,035H,01CH,037H
  88. DB 046H
  89. ; The matching Westwood keycodes.
  90. ExtNums DB 62, 64, 75, 76, 79, 80, 81, 83, 84, 85
  91. DB 86, 89, 95, 108, 124, 0
  92. ; If extended mapping is disabled, then these codes really are...
  93. ExtRemap DB 60, 58, 99, 104, 92, 91, 93, 96, 98, 101
  94. DB 103, 102, 55, 43, 124, 0
  95. ExtRemapEnd DB 0
  96. ExtKeyboard DB 0 ; flag for 101/102-key keyboard
  97. KeyBuffer DW 128 DUP(0) ; set to empty
  98. KeyBufferHead DW 0 ; set to first entry
  99. KeyBufferTail DW 0 ; set to head for empty buffer
  100. KeyLock DW 0 ; num and caps lock bits
  101. KeyNums DB 127,110,002,003,004,005,006,007,008,009,010,011,012,013,015,016
  102. DB 017,018,019,020,021,022,023,024,025,026,027,028,043,058,031,032
  103. DB 033,034,035,036,037,038,039,040,041,001,044,029,046,047,048,049
  104. DB 050,051,052,053,054,055,057,100,060,061,030,112,113,114,115,116
  105. DB 117,118,119,120,121,090,125,091,096,101,105,092,097,102,106,093
  106. DB 098,103,099,104,127,127,127,122,123
  107. KeysCapsLock DB 0,0,0FEH,087H,0FFH,0C0H,01FH,0,0,0,0,0,0,0,0,0
  108. KeysNumLock DB 0,0,0,0,0,0,0,0,0,0,0,038H,0EFH,1,0,0
  109. KeysUpDown DB 16 DUP(0) ; set to all keys up
  110. KeyStream DB 16 DUP(0) ; set to all keys up
  111. PassCount DW 0
  112. KeyStreamIndex DW 0
  113. LastKeyE0 DB 0
  114. LastKeyE1 DB 0
  115. ;
  116. ; Westwood key number values of keys to pass through
  117. ;
  118. ; CAPS, LEFT_SHIFT, RIGHT_SHIFT, LEFT_CTRL, LEFT_ALT,
  119. ; RIGHT_ALT, RIGHT_CTRL, NUM_LOCK, UNKNOWN
  120. PassAlways DB 30, 44, 57, 58, 60, 62, 64, 90, 128, 128
  121. PassAlwaysEnd DB 128 ; invalid code to END PassAlways
  122. CtrlFlags DB 0
  123. Buffer DW ?
  124. Time DW ?
  125. ADJUST = 1 ; do not modify DRD
  126. XYAdjust DB -ADJUST, -ADJUST ; 91 -> upleft
  127. DB -ADJUST, 0 ; 92 -> left
  128. DB -ADJUST, ADJUST ; 93 -> downleft
  129. DB 0, 0 ; 94 illegal
  130. DB 0, 0 ; 95 illegal
  131. DB 0, -ADJUST ; 96 -> up
  132. DB 0, 0 ; 97 illegal (center)
  133. DB 0, ADJUST ; 98 -> down
  134. DB 0, 0 ; 99 illegal
  135. DB 0, 0 ; 100 illegal
  136. DB ADJUST, -ADJUST ; 101 -> upright
  137. DB ADJUST, 0 ; 102 -> right
  138. DB ADJUST, ADJUST ; 103 -> downright
  139. EdgeConv DW 8,2,8,6,4,3,8,5,8,8,8,8,0,1,8,7
  140. MouseUpdate DW 0
  141. MouseX DW 0
  142. LocalMouseX DW 0
  143. MouseY DW 0
  144. LocalMouseY DW 0
  145. Button DW 0
  146. IsExtKey DB 0
  147. ExtIndex DW 0
  148. OldRMI DD 0 ; The origianl RM interrupt seg:off.
  149. OldPMIOffset DD 0 ; The origianl PM interrupt offset
  150. OldPMISelector DD 0 ; The original PM interrupt segment.
  151. CodeOffset DW RM_Keystroke_Interrupt ; Offset of the code in the RM stuff.
  152. CallRMIntOffset DW Call_Interrupt_Chain ; Offset of function to call DOS timer interrupt.
  153. CallRMIntAddr DD 0 ; PM address of CallRealIntOffset for speed.
  154. ;***************************************************************************
  155. ;* KEYNUM_TRANSLATE -- Translates the given keynum to ??? *
  156. ;* *
  157. ;* INPUT: UWORD the keynum to translate *
  158. ;* *
  159. ;* OUTPUT: WORD the translated keynum *
  160. ;* *
  161. ;* PROTO: UWORD KeyNum_Translate(UWORD keynum); *
  162. ;* *
  163. ;* HISTORY: *
  164. ;* 07/11/1994 PWG : Created. *
  165. ;*=========================================================================*
  166. GLOBAL KeyNum_Translate:FAR
  167. PROC KeyNum_Translate C FAR
  168. USES cx,di,es,ds
  169. ARG keycode:WORD
  170. mov ax,cs ; since we are in tiny model
  171. mov ds,ax ; set cs = ds
  172. mov es,ax ; set es up for scansb
  173. mov ax,[keycode]
  174. test [KeyFlags],TRACKEXT
  175. jne short ??fini
  176. mov cx,ExtRemap-ExtNums
  177. mov di,OFFSET ExtNums
  178. repne scasb
  179. jcxz short ??fini ; No match found.
  180. mov di,OFFSET ExtRemapEnd
  181. dec di
  182. sub di,cx
  183. mov al,[es:di]
  184. ??fini:
  185. ret
  186. ENDP KeyNum_Translate
  187. ;***************************************************************************
  188. ;* STUFF_KEY_WORD -- Stuffs a word of data into keyboard buffer *
  189. ;* *
  190. ;* INPUT: WORD the code to stick into the circular buffer *
  191. ;* *
  192. ;* OUTPUT: WORD !=0 is sucessful, ==0 is not enough room *
  193. ;* *
  194. ;* PROTO: VOID Stuff_Key_WORD(WORD code); *
  195. ;* *
  196. ;* HISTORY: *
  197. ;* 07/11/1994 PWG : Created. *
  198. ;*=========================================================================*
  199. GLOBAL C Stuff_Key_WORD:FAR
  200. PROC Stuff_Key_WORD C FAR
  201. USES si,bx,ds
  202. ARG code:WORD
  203. mov ax,cs ; since we are in tiny model
  204. mov ds,ax ; set cs = ds
  205. mov ax,[KeyBufferTail]
  206. mov si,ax
  207. add ax,2
  208. and ax,0FFh ; New KeyBufferTail value.
  209. cmp [KeyBufferHead],ax
  210. je short ??noroom
  211. mov bx,[code]
  212. mov [KeyBuffer+si],bx ; Record the keystroke.
  213. mov [KeyBufferTail],ax
  214. xor ax,ax
  215. ret
  216. ??noroom:
  217. mov ax,1
  218. ret
  219. ENDP Stuff_Key_WORD
  220. ;***************************************************************************
  221. ;* STUFF_KEY_NUM -- Stuffs a key num code into the circular buffer *
  222. ;* *
  223. ;* INPUT: WORD the keycode to stuff *
  224. ;* *
  225. ;* OUTPUT: WORD !=0 is sucessful, ==0 is not enough room *
  226. ;* *
  227. ;* PROTO: VOID Stuff_Key_Num(WORD keynum); *
  228. ;* *
  229. ;* HISTORY: *
  230. ;* 07/11/1994 PWG : Created. *
  231. ;*=========================================================================*
  232. GLOBAL C Stuff_Key_Num:FAR
  233. PROC Stuff_Key_Num C FAR
  234. USES ax,bx,cx,dx,di,si,ds
  235. ARG keycode:WORD
  236. LOCAL tail:WORD ; Original keybuffer tail (safety copy).
  237. LOCAL size:WORD ; Size of write.
  238. pushf
  239. cli ; disable interrupts
  240. ; Abort key recognition if in record mode and unable
  241. ; to output key due to simultaneous DOS operation.
  242. mov ax,cs ; since we are in tiny model
  243. mov ds,ax ; set cs = ds
  244. ; Record the mouse position to be stuffed into buffer.
  245. mov ax,[MouseX]
  246. mov [LocalMouseX],ax
  247. mov ax,[MouseY]
  248. mov [LocalMouseY],ax
  249. ??cando:
  250. mov ax,[keycode] ; get the code
  251. or ax,ax ; Null keycodes are not recorded.
  252. jne short ??validkey
  253. jmp ??exit
  254. ??validkey:
  255. test [KeyFlags],KEYMOUSE ; is the numeric keypad moving the mouse?
  256. je ??no_pad_move
  257. ; ALT-cursor keys are undefined. Pass them on to the program.
  258. test ah,ALTPRESS ; is either alt key down?
  259. jne ??no_pad_move
  260. test [KeyFlags],SIMLBUTTON ; are we simulating left mouse presses
  261. je short ??chkinsert
  262. cmp al,KN_RETURN
  263. je short ??forceleft
  264. cmp al,KN_SPACE
  265. je short ??forceleft
  266. cmp al,KN_KEYPAD_RETURN
  267. je short ??forceleft
  268. ??chkinsert:
  269. cmp al,KN_INSERT
  270. jne short ??regular
  271. ??forceleft:
  272. mov al,KN_LMOUSE
  273. or [Button],1 ; Left mouse bit.
  274. test ah,KEYRELEASE
  275. je ??mousefake
  276. and [Button],NOT 1
  277. jmp ??mousefake
  278. ??regular:
  279. cmp al,KN_DELETE
  280. jne short ??regular2
  281. mov al,KN_RMOUSE
  282. or [Button],2 ; Right mouse bit.
  283. test ah,KEYRELEASE
  284. je ??mousefake
  285. and [Button],NOT 2
  286. jmp ??mousefake
  287. ??regular2:
  288. ; DRD correction to ignore key releases for key mouse movement
  289. test ah,KEYRELEASE
  290. jne ??no_pad_move
  291. cmp al,KN_CENTER
  292. je short ??pad_move
  293. cmp al,KN_UPLEFT ; less than upleft?
  294. jb ??no_pad_move ; yes, then it isn't a keypad key
  295. cmp al,KN_DOWNRIGHT ; greater than downright?
  296. ja ??no_pad_move ; yes, then it isn't a keypad key
  297. cmp al,KN_DOWNLEFT ; is it UPLEFT, LEFT, or DOWNLEFT?
  298. jbe short ??pad_move
  299. cmp al,KN_UPRIGHT ; is it UPRIGHT, RIGHT, or DOWNRIGHT?
  300. jae short ??pad_move
  301. cmp al,KN_UP ; up?
  302. je short ??pad_move
  303. cmp al,KN_DOWN ; down?
  304. jne ??no_pad_move
  305. ??pad_move:
  306. ; DRD correction to use ch for ah
  307. mov ch,ah ; save shift-ctrl-alt-rlse status
  308. xor ah,ah ; get rid of any bits
  309. sub al,KN_UPLEFT ; get a number between 0 and 12
  310. mov bx,ax
  311. shl bx,1 ; double for WORD index
  312. add bx,OFFSET XYAdjust
  313. mov ax,[bx] ; get x,y add value
  314. mov bl,ah
  315. cbw
  316. xchg ax,bx
  317. cbw
  318. xchg ax,bx ; AX = mouse x delta, BX = mouse y delta
  319. ; DRD correction to use ch
  320. ; The CTRL key moves the mouse to the edge of the screen.
  321. test ch,CTRLPRESS ; is either ctrl key down?
  322. jne short ??ctrlon ; if so, ctrl is on
  323. ; DRD correction to use ch
  324. ; use fast speed of the mouse move if the shift key is held down.
  325. mov dx,1 ; for slow speed
  326. test ch,SHIFTPRESS ; is either shift key down?
  327. je short ??normspeed ; if not then neither shift is down
  328. ??doublespeed:
  329. add dx,3 ; for fast speed
  330. ??normspeed:
  331. add bx,dx ; add speed for y index
  332. mov bl,[KeyMouseMove+bx] ; get speed for y delta
  333. xchg ax,bx ; swap with ax to extend sign
  334. cbw
  335. xchg ax,bx
  336. xchg bx,dx ; save mouse y delta
  337. add bx,ax ; add speed for x index
  338. mov al,[KeyMouseMove+bx] ; get speed for x delta
  339. cbw
  340. xchg bx,dx ; restore mouse y delta
  341. jmp short ??ctrloff
  342. ??ctrlon:
  343. ; Table lookup method for determining hotkey positions for CTRL
  344. ; cursor combination. This algorithm is hard coded for an ADJUST
  345. ; value of 3. If this value changed, then this section will also
  346. ; have to be modified.
  347. and bx,011b ; Y = 1, 0, 3
  348. and ax,011b ; X = 1, 0, 3
  349. ; Table lookup method for determining hotkey positions for CTRL
  350. ; cursor combination. This algorithm is hard coded.
  351. ; -1, 0, 1
  352. and bx,011b ; Y = 3, 0, 1
  353. and ax,011b ; X = 3, 0, 1
  354. shl bx,1
  355. shl bx,1
  356. or bx,ax ; Lookup index.
  357. ; Convert raw index into logical (clockwise) index.
  358. shl bx,1
  359. mov bx,[EdgeConv+bx]
  360. shl bx,1
  361. shl bx,1
  362. mov ax,[ScreenEdge+bx] ; New absolute X
  363. mov bx,[ScreenEdge+bx+2] ; New absolute Y
  364. mov [LocalMouseX],ax
  365. mov [LocalMouseY],bx
  366. ??set_xyz:
  367. mov ax,[LocalMouseX] ; get new mouse x,y
  368. mov bx,[LocalMouseY]
  369. jmp short ??set_xy
  370. ; Process a normal faked mouse move.
  371. ??ctrloff:
  372. ; DRD change
  373. add [LocalMouseX],ax ; save it in our local
  374. jns short ??not_negative_x
  375. xor ax,ax
  376. mov [LocalMouseX],ax ; clear our local
  377. ??not_negative_x:
  378. ; DRD change
  379. add [LocalMouseY],bx ; save it in our local
  380. jns short ??not_negative_y
  381. xor bx,bx
  382. mov [LocalMouseY],bx ; clear our local
  383. ??not_negative_y:
  384. mov ax,[LocalMouseX] ; get new mouse x,y
  385. mov bx,[LocalMouseY]
  386. cmp ax,MAX_X_PIXEL ; bigger than
  387. jle short ??check_y
  388. mov ax,MAX_X_PIXEL
  389. ??check_y:
  390. cmp bx,MAX_Y_PIXEL ; bigger than
  391. jle short ??set_xy
  392. mov bx,MAX_Y_PIXEL
  393. ??set_xy:
  394. mov [LocalMouseX],ax
  395. mov [LocalMouseY],bx
  396. mov [MouseX],ax
  397. mov [MouseY],bx
  398. cmp [MouseUpdate],0 ; wait until mouse interrupt is done
  399. jne short ??noshow
  400. ; PWG: ARRGGGHHHH!
  401. ; call Low_Hide_Mouse
  402. ; call Low_Show_Mouse
  403. ??noshow:
  404. mov ax,KN_MOUSE_MOVE
  405. ??mousefake:
  406. mov [keycode],ax ; Fake a MOUSE_MOVE event.
  407. ??no_pad_move:
  408. ; Fetch working pointers to the keyboard ends.
  409. mov si,[KeyBufferTail]
  410. mov [tail],si ; Safety record.
  411. mov di,[KeyBufferHead]
  412. ; Record the base keycode (if there is room).
  413. push ax
  414. call Stuff_Key_WORD
  415. add sp,2
  416. or ax,ax
  417. jne short ??jmpnoroom
  418. ; Also record the mouse coordinates if necessary.
  419. mov ax,[keycode] ; get key code
  420. cmp al,KN_MOUSE_MOVE ; mouse move?
  421. je short ??recordmouse ; yes? then record the mouse cooordinates
  422. cmp al,KN_LMOUSE
  423. je short ??recordmouse
  424. cmp al,KN_RMOUSE
  425. je short ??recordmouse
  426. jmp short ??ok
  427. ??jmpnoroom:
  428. jmp ??noroom
  429. ; Record mouse coordinate X.
  430. ??recordmouse:
  431. push [LocalMouseX]
  432. call Stuff_Key_WORD
  433. add sp,2
  434. or ax,ax
  435. jne ??jmpnoroom
  436. add [size],2
  437. ; Record mouse coordinate Y.
  438. push [LocalMouseY]
  439. call Stuff_Key_WORD
  440. add sp,2
  441. or ax,ax
  442. jne ??jmpnoroom
  443. add [size],2
  444. ??ok:
  445. ; If PASSBREAKS is not active and this is a keyboard
  446. ; break AND it is not a mouse event, then don't put
  447. ; it into the buffer.
  448. mov bx,0101h ; Bit control tools.
  449. mov ax,[keycode]
  450. cmp al,KN_MOUSE_MOVE
  451. je short ??notreal
  452. cmp al,127
  453. je short ??notreal
  454. test ah,KEYRELEASE
  455. je short ??real
  456. xor bl,bl
  457. test [KeyFlags],PASSBREAKS
  458. jne short ??real
  459. cmp al,KN_LMOUSE
  460. je short ??real
  461. cmp al,KN_RMOUSE
  462. je short ??real
  463. ??notreal:
  464. mov [KeyBufferTail],si ; Nullify any KeyBufferTail changes.
  465. ??real:
  466. ; Update the KeysUpDown bit array.
  467. mov di,ax
  468. and di,07Fh
  469. mov cl,3
  470. shr di,cl ; DI = Byte offset into bit table.
  471. mov cl,al
  472. and cl,0111b ; CL = Bit offset into bit table byte.
  473. shl bx,cl
  474. not bh
  475. ; If this is a reapeat key and the key is already being held
  476. ; down, then don't stuff it into the keyboard buffer.
  477. test bl,[KeysUpDown+di]
  478. je short ??notalready
  479. test [KeyFlags],REPEATON
  480. jne short ??notalready
  481. mov [KeyBufferTail],si ; Nullify any KeyBufferTail changes.
  482. ??notalready:
  483. and [KeysUpDown+di],bh ; Force key bit to zero.
  484. or [KeysUpDown+di],bl ; Insert key bit as appropriate.
  485. ;??notreal:
  486. ; Successful keybuffer stuff could result in a
  487. ??norecord:
  488. mov ax,1
  489. jmp short ??exit
  490. ; Unsuccessful keybuffer stuff.
  491. ??noroom:
  492. mov ax,[tail]
  493. mov [KeyBufferTail],ax
  494. xor ax,ax ; Signal an error.
  495. ??exit:
  496. popf
  497. ret
  498. ENDP Stuff_Key_Num
  499. ;***********************************************************
  500. ;***************************************************************************
  501. ;* KEYSTROKE_INTERRUPT -- Handles input that comes from the keyboard *
  502. ;* *
  503. ;* This routine intercepts the key codes on their way to the *
  504. ;* BIOS. With the adjustment of the Flags described above *
  505. ;* you can get a wide variety of effects. *
  506. ;* *
  507. ;* INPUT: none *
  508. ;* *
  509. ;* OUTPUT: none *
  510. ;* *
  511. ;* WARNINGS: This is an interrupt function *
  512. ;* *
  513. ;* HISTORY: *
  514. ;* 07/13/1994 PWG : Created. *
  515. ;*=========================================================================*
  516. label RM_Keystroke_Interrupt
  517. GLOBAL C Keystroke_Interrupt:FAR
  518. PROC Keystroke_Interrupt C FAR
  519. IF 0
  520. push ax
  521. inc ax
  522. pop ax
  523. iret
  524. ELSE
  525. push ax
  526. push bx
  527. push cx
  528. push di
  529. push ds
  530. push dx
  531. push es
  532. push si
  533. cld
  534. mov ax,cs ; set ds to cs to avoid cs overide
  535. mov ds,ax
  536. mov dx,[KeyFlags]
  537. ;*** The following fix allows proper caps and num lock tracking on Tandy
  538. ; 10-6-89 LJC, DRD
  539. and [KeyLock],NOT (NUMLOCK OR CAPSLOCK); assume caps and num inactive
  540. mov ax,040H ; BIOS segment
  541. mov es,ax ; put in es
  542. test [BYTE PTR es:017H],040H ; test Caps lock bit in BIOS
  543. je short ??bioscapsoff ; skip activate code
  544. or [KeyLock],CAPSLOCK ; Caps Lock active
  545. ??bioscapsoff:
  546. test [BYTE PTR es:017H],020H ; test Num lock bit in BIOS
  547. je short ??biosnumoff ; skip activate code
  548. or [KeyLock],NUMLOCK ; Num Lock active
  549. ??biosnumoff:
  550. mov [ExtKeyboard],TRUE ; assume 101/102-key keyboard
  551. test [BYTE PTR es:096H],010H ; test for 101/102-key keyboard
  552. jne short ??extkeyboard ; skip deactivate code
  553. mov [ExtKeyboard],FALSE ; no 101/102-key keyboard
  554. ??extkeyboard:
  555. mov ax,cs ; set ds to cs to avoid cs overide
  556. mov es,ax
  557. cld ; clear direction flag for strings
  558. xor ah,ah ; clear ctrl flags to 0
  559. mov bx,0101H ; set key to a make by default
  560. in al,KEYDATA ; get a code from the keyboard
  561. ;
  562. ; New CODE to montior key stream
  563. ;
  564. mov bx,[KeyStreamIndex]
  565. mov [KeyStream+bx],al
  566. inc bx
  567. and bx,15
  568. mov [KeyStreamIndex],bx
  569. mov bx,0101H ; set key to a make by default
  570. ;
  571. ; END OF SEQUENCE
  572. ;
  573. ;
  574. ; Handle the PAUSE key being pressed. If it is pressed, then
  575. ; signal that the next two input codes are to be thrown out.
  576. ;
  577. cmp al,0E1H ; see if this is a pause/break
  578. jne short ??notpcode ; not a pause/break start code
  579. mov [LastKeyE1],3 ; absorb this and next two codes
  580. ??notpcode:
  581. cmp [LastKeyE1],0 ; are we in a pause/break code
  582. je short ??notpause ; no, just keep going
  583. dec [LastKeyE1] ; yes, dec the count
  584. test dx,PAUSEON ; should it pass these codes
  585. jne ??passcode ; pass the code
  586. jmp ??absorbcode ; don't pass code
  587. ??notpause:
  588. ;
  589. ; Record any extended key codes that arrive. They will be
  590. ; taken into account with the next code.
  591. ;
  592. cmp al,0E0H ; is it an extended code
  593. jne short ??notextcode ; if not skip to handle key
  594. mov [LastKeyE0],TRUE ; set the extended code to 1
  595. ??jmppasscode:
  596. jmp ??passcode ; always pass E0s
  597. ??notextcode:
  598. ;
  599. ; Check and acknowledge if the key is a make or a break.
  600. ;
  601. test al,080H ; test for high bit
  602. je short ??make ; if off its a make
  603. xor bl,bl ; set make/break to break
  604. and al,07FH ; clear high bit
  605. or ah,KEYRELEASE ; CDY NEW -- ABSENT IN OLD CODE
  606. ??make:
  607. ;
  608. ; Translate the raw keycode into the Westwood keycode.
  609. ;
  610. cmp [LastKeyE0],FALSE ; was the prev byte an E0?
  611. je short ??normal ; if not it is a normal key
  612. mov [LastKeyE0],FALSE ; if so clear for next read
  613. mov [IsExtKey],TRUE ; it is an extended key
  614. mov di,OFFSET ExtCodes ; get offset of extended codes table
  615. mov cx,(ExtNums-ExtCodes) ; get number of entrys in ext table
  616. repne scasb ; look for a match
  617. jcxz ??absorbcode ; Not recognized, so throw it away.
  618. mov al,[(ExtNums - ExtCodes) - 1 + di] ; get the match
  619. mov [IsExtKey],FALSE ; it is not an extended key
  620. jmp short ??notext
  621. ??normal:
  622. cmp al,07Ah
  623. jne short ??normok
  624. mov al,128
  625. jmp short ??notext
  626. ??normok:
  627. mov di,ax ; use code as an index
  628. and di,007Fh ; Mask off any release bit.
  629. mov al,[KeyNums+di] ; get the key number of this key
  630. ??notext:
  631. ;
  632. ; Test and set the CTRL bit.
  633. ;
  634. test [KeysUpDown+8],001H ; is the right ctrl down?
  635. jne short ??ctrlon ; if so, ctrl is on
  636. test [KeysUpDown+7],004H ; is the left ctrl down?
  637. je short ??ctrloff ; if not, neither are down, no ctrl
  638. ; DRD
  639. ; check for CTRL-NUMLOCK for pause on some keyboards
  640. cmp al,KN_NUMLOCK ; check for CTRL-NUMLOCK
  641. jne short ??ctrlon
  642. cmp [ExtKeyboard],TRUE ; if 101/102-key keyboard it is ok
  643. je short ??ctrlon
  644. test dx,PAUSEON ; should it pass these codes
  645. jne short ??ctrlon ; pass the code
  646. jmp ??absorbcode ; don't pass code
  647. ??ctrlon:
  648. or ah,CTRLPRESS ; or on the ctrl bit in flags
  649. ??ctrloff:
  650. ;
  651. ; Test and set the ALT bit.
  652. ;
  653. test [KeysUpDown + 7],050H ; is either alt key down?
  654. je short ??altoff
  655. or ah,ALTPRESS ; or on the alt bit in flags
  656. ??altoff:
  657. ;
  658. ; Remap the keyboard keys if this is requested. (Do not set DGROUP
  659. ; as it is unecessary)
  660. push ax
  661. call KeyNum_Translate
  662. add sp,2
  663. ;------ Set the shift bit if necessary.
  664. test [KeysUpDown+5],010H ; is the left shift down?
  665. jne short ??shifton ; if so the shift is on
  666. test [KeysUpDown+7],002H ; is the right shift down?
  667. je short ??shiftoff ; if not then neither shift is down
  668. ??shifton:
  669. or ah,SHIFTPRESS ; or on the shift bit in flags
  670. ??shiftoff:
  671. ;
  672. ;------ Toggle the shift state if the caps lock key is on (if necessary).
  673. ;
  674. mov di,ax
  675. and di,07Fh
  676. shr di,1
  677. shr di,1
  678. shr di,1
  679. mov bx,ax
  680. and bx,07Fh
  681. and bl,0111b
  682. mov ch,[Bits+bx] ; get the bit to test
  683. test [KeyLock],CAPSLOCK ; is the caps lock on?
  684. je short ??capsoff ; if not don't worry about it
  685. test ch,[KeysCapsLock+di] ; get code for keycaps
  686. je short ??capsoff ; its not effected
  687. xor ah,SHIFTPRESS ; toggle the shift flag
  688. ??capsoff:
  689. ;
  690. ;------ Toggle the shift state if the num-lock key is on (if necessary).
  691. ;
  692. test [KeyLock],NUMLOCK ; is the num lock key on?
  693. je short ??numlockoff ; if not don't worry about it
  694. test ch,[KeysNumLock+di] ; get code for numlock
  695. je short ??numlockoff ; if not effected skip toggle
  696. xor ah,SHIFTPRESS ; toggle the shift flag if effected
  697. ??numlockoff:
  698. ;------ Remember the current control/shift/alt bit settings for later use.
  699. ;??noshiftever:
  700. mov [CtrlFlags],ah ; save off shift-ctrl-alt flags
  701. ; for the mouse and joystick routines
  702. ; to use in stuffing key into the
  703. ; keyboard buffer.
  704. ;------ The CTRL-ALT-DEL key combination always gets passed to the system.
  705. cmp ax,0668H ; is it ctrl alt del?
  706. je ??passcode
  707. cmp ax,064CH ; is it ctrl alt ext del?
  708. je ??passcode ; if so don't add it to the buffer
  709. ;------ Special Ctrl-C check.
  710. cmp ax,0230h
  711. je short ??breaker
  712. cmp ax,027Eh
  713. jne short ??nobreak
  714. ??breaker:
  715. mov [Break],1
  716. ??nobreak:
  717. ;------ Check for Music and Sound control keys.
  718. cmp ax,0420H ; is this an alt s
  719. jne short ??checkmusic ; toggle the Sound variable
  720. push ax
  721. mov ax,[SoundOn]
  722. xor ax,01H
  723. push ax
  724. add sp,2
  725. pop ax
  726. ??checkmusic:
  727. cmp ax,0434H ; is this an alt m
  728. jne short ??esc ; toggle the Music variable
  729. push ax
  730. mov ax,[MusicOn]
  731. xor ax,01H
  732. push ax
  733. add sp,2
  734. pop ax
  735. ??esc:
  736. push ax
  737. call Stuff_Key_Num
  738. pop ax
  739. ??skipstuff:
  740. ;------ Do the special ESC routine if necessary.
  741. cmp al,110 ; is this the esc key?
  742. jne short ??noroutine ; if not goto the pass always
  743. cmp [WORD PTR EscRoutine+2],0 ;if vector is 0 don't jump
  744. je short ??noroutine
  745. push ax
  746. call [EscRoutine]
  747. pop ax
  748. ??noroutine:
  749. ;------ Check to see if the key is to be passed to the system or not.
  750. mov di,OFFSET PassAlways ; get offset to table
  751. mov cx,(PassAlwaysEnd - PassAlways) ; get number of pass always CDY JLB MOD 7/11 was +1
  752. repne scasb ; look for a match
  753. or cx,cx ; see if there was no match
  754. jne ??passcode ; CDY JLB 7/11 optimization
  755. ??passalways:
  756. ; now check for conditional passes
  757. mov di,OFFSET CondPassKey ; get offset to cond key table
  758. mov cx,(CondPassCond-CondPassKey) ; get number of entries
  759. shr cx,1 ; cut in half for words
  760. repne scasw ; look for a match
  761. jcxz short ??notcondpass ; OPTIMIZATION CDY JLB
  762. mov bx,[(CondPassCond - CondPassKey) - 2 + di]
  763. and bx,dx ; are the conditions met?
  764. je short ??notcondpass ; NO... check normally.
  765. jmp short ??passcode ; YES... pass back to system.
  766. ;
  767. ;------ Last check before passing keycode back to the system.
  768. ;
  769. ??notcondpass:
  770. test dx,FILTERONLY ; is the filter only flag on?
  771. je short ??absorbcode ; if not, absorb the code.
  772. ;***********************************************************
  773. pushf
  774. ; push di
  775. ; push es
  776. mov ax,0B000h
  777. mov es,ax
  778. inc [BYTE PTR es:0]
  779. ; pop es
  780. ; pop di
  781. popf
  782. ;***********************************************************
  783. ??passcode:
  784. pop si
  785. pop es
  786. pop dx
  787. pop ds
  788. pop di
  789. pop cx
  790. pop bx
  791. pop ax
  792. inc [cs:PassCount]
  793. jmp [cs:OldRMI]
  794. ??absorbcode:
  795. in al,KEYCTRL ; get the control port
  796. mov ah,al
  797. or al,080H ; reset bit for keyboard
  798. out KEYCTRL,al
  799. xchg ah,al ; get orig control data
  800. out KEYCTRL,al ; restore control data
  801. mov ax,040h ; BIOS paragraph is always @ 040h
  802. mov es,ax ; put in es as BIOS paragraph
  803. mov al,[es:96h] ; get extended keys
  804. and al,0FDh ; turn off last key e0 flag
  805. mov [es:96h],al ; set extended keys
  806. mov al,CLEARISR ; value to clear In Service Register
  807. out INTCHIP0,al ; 8259 interrupt chip controller 0
  808. pop si
  809. pop es
  810. pop dx
  811. pop ds
  812. pop di
  813. pop cx
  814. pop bx
  815. pop ax
  816. iret
  817. ENDIF
  818. ENDP Keystroke_Interrupt
  819. ;***************************************************************************
  820. ;* BREAK_INTERRUPT -- Handles the break key interrupt *
  821. ;* *
  822. ;* INPUT: none *
  823. ;* *
  824. ;* OUTPUT: none *
  825. ;* *
  826. ;* WARNINGS: This is an interrupt routine. *
  827. ;* *
  828. ;* HISTORY: *
  829. ;* 07/13/1994 PWG : Created. *
  830. ;*=========================================================================*
  831. GLOBAL C Break_Interrupt:FAR
  832. PROC Break_Interrupt C FAR
  833. iret
  834. ENDP Break_Interrupt
  835. ;**************************************************************************
  836. ;* CALL_INTERRUPT_CHAIN -- Function PM calls to call the RM interrupt chain*
  837. ;* *
  838. ;* *
  839. ;* INPUT: *
  840. ;* *
  841. ;* OUTPUT: *
  842. ;* *
  843. ;* WARNINGS: *
  844. ;* *
  845. ;* HISTORY: *
  846. ;* 07/08/1994 SKB : Created. *
  847. ;*=========================================================================*
  848. Call_Interrupt_Chain:
  849. IF 0
  850. pushf
  851. push ax
  852. push di
  853. push es
  854. mov ax,0B000h ; ES:DI = Mono RAM address.
  855. mov es,ax
  856. mov al,'A'
  857. mov ah,2
  858. and di,63
  859. stosw
  860. in al,KEYDATA ; get a code from the keyboard
  861. mov al,CLEARISR ; value to clear In Service Register
  862. out INTCHIP0,al ; 8259 interrupt chip controller 0
  863. pop es
  864. pop di
  865. pop ax
  866. popf
  867. ENDIF
  868. pushf
  869. call Keystroke_Interrupt ;[OldRMI]
  870. retf
  871. STACK ; Don't really need this
  872. ;***********************************************************
  873. END