KEYIPROT.ASM 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032
  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 C KeyNum_Translate:FAR
  167. PROC KeyNum_Translate C FAR
  168. USES cx,di,es,ds
  169. ARG keycode:WORD
  170. ifdef NOT_FOR_WIN95
  171. mov ax,cs ; since we are in tiny model
  172. mov ds,ax ; set cs = ds
  173. mov es,ax ; set es up for scansb
  174. mov ax,[keycode]
  175. test [KeyFlags],TRACKEXT
  176. jne short ??fini
  177. mov cx,ExtRemap-ExtNums
  178. mov di,OFFSET ExtNums
  179. repne scasb
  180. jcxz short ??fini ; No match found.
  181. mov di,OFFSET ExtRemapEnd
  182. dec di
  183. sub di,cx
  184. mov al,[es:di]
  185. ??fini:
  186. endif ;NOT_FOR_WIN95
  187. ret
  188. ENDP KeyNum_Translate
  189. ;***************************************************************************
  190. ;* STUFF_KEY_WORD -- Stuffs a word of data into keyboard buffer *
  191. ;* *
  192. ;* INPUT: WORD the code to stick into the circular buffer *
  193. ;* *
  194. ;* OUTPUT: WORD !=0 is sucessful, ==0 is not enough room *
  195. ;* *
  196. ;* PROTO: VOID Stuff_Key_WORD(WORD code); *
  197. ;* *
  198. ;* HISTORY: *
  199. ;* 07/11/1994 PWG : Created. *
  200. ;*=========================================================================*
  201. GLOBAL C Stuff_Key_WORD:FAR
  202. PROC Stuff_Key_WORD C FAR
  203. USES si,bx,ds
  204. ARG code:WORD
  205. ifdef NOT_FOR_WIN95
  206. mov ax,cs ; since we are in tiny model
  207. mov ds,ax ; set cs = ds
  208. mov ax,[KeyBufferTail]
  209. mov si,ax
  210. add ax,2
  211. and ax,0FFh ; New KeyBufferTail value.
  212. cmp [KeyBufferHead],ax
  213. je short ??noroom
  214. mov bx,[code]
  215. mov [KeyBuffer+si],bx ; Record the keystroke.
  216. mov [KeyBufferTail],ax
  217. xor ax,ax
  218. ret
  219. ??noroom:
  220. mov ax,1
  221. endif ; NOT_FOR_WIN95
  222. ret
  223. ENDP Stuff_Key_WORD
  224. ;***************************************************************************
  225. ;* STUFF_KEY_NUM -- Stuffs a key num code into the circular buffer *
  226. ;* *
  227. ;* INPUT: WORD the keycode to stuff *
  228. ;* *
  229. ;* OUTPUT: WORD !=0 is sucessful, ==0 is not enough room *
  230. ;* *
  231. ;* PROTO: VOID Stuff_Key_Num(WORD keynum); *
  232. ;* *
  233. ;* HISTORY: *
  234. ;* 07/11/1994 PWG : Created. *
  235. ;*=========================================================================*
  236. GLOBAL C Stuff_Key_Num:FAR
  237. PROC Stuff_Key_Num C FAR
  238. USES ax,bx,cx,dx,di,si,ds
  239. ARG keycode:WORD
  240. LOCAL tail:WORD ; Original keybuffer tail (safety copy).
  241. LOCAL size:WORD ; Size of write.
  242. ifdef NOT_FOR_WIN95
  243. pushf
  244. cli ; disable interrupts
  245. ; Abort key recognition if in record mode and unable
  246. ; to output key due to simultaneous DOS operation.
  247. mov ax,cs ; since we are in tiny model
  248. mov ds,ax ; set cs = ds
  249. ; Record the mouse position to be stuffed into buffer.
  250. mov ax,[MouseX]
  251. mov [LocalMouseX],ax
  252. mov ax,[MouseY]
  253. mov [LocalMouseY],ax
  254. ??cando:
  255. mov ax,[keycode] ; get the code
  256. or ax,ax ; Null keycodes are not recorded.
  257. jne short ??validkey
  258. jmp ??exit
  259. ??validkey:
  260. test [KeyFlags],KEYMOUSE ; is the numeric keypad moving the mouse?
  261. je ??no_pad_move
  262. ; ALT-cursor keys are undefined. Pass them on to the program.
  263. test ah,ALTPRESS ; is either alt key down?
  264. jne ??no_pad_move
  265. test [KeyFlags],SIMLBUTTON ; are we simulating left mouse presses
  266. je short ??chkinsert
  267. cmp al,KN_RETURN
  268. je short ??forceleft
  269. cmp al,KN_SPACE
  270. je short ??forceleft
  271. cmp al,KN_KEYPAD_RETURN
  272. je short ??forceleft
  273. ??chkinsert:
  274. cmp al,KN_INSERT
  275. jne short ??regular
  276. ??forceleft:
  277. mov al,KN_LMOUSE
  278. or [Button],1 ; Left mouse bit.
  279. test ah,KEYRELEASE
  280. je ??mousefake
  281. and [Button],NOT 1
  282. jmp ??mousefake
  283. ??regular:
  284. cmp al,KN_DELETE
  285. jne short ??regular2
  286. mov al,KN_RMOUSE
  287. or [Button],2 ; Right mouse bit.
  288. test ah,KEYRELEASE
  289. je ??mousefake
  290. and [Button],NOT 2
  291. jmp ??mousefake
  292. ??regular2:
  293. ; DRD correction to ignore key releases for key mouse movement
  294. test ah,KEYRELEASE
  295. jne ??no_pad_move
  296. cmp al,KN_CENTER
  297. je short ??pad_move
  298. cmp al,KN_UPLEFT ; less than upleft?
  299. jb ??no_pad_move ; yes, then it isn't a keypad key
  300. cmp al,KN_DOWNRIGHT ; greater than downright?
  301. ja ??no_pad_move ; yes, then it isn't a keypad key
  302. cmp al,KN_DOWNLEFT ; is it UPLEFT, LEFT, or DOWNLEFT?
  303. jbe short ??pad_move
  304. cmp al,KN_UPRIGHT ; is it UPRIGHT, RIGHT, or DOWNRIGHT?
  305. jae short ??pad_move
  306. cmp al,KN_UP ; up?
  307. je short ??pad_move
  308. cmp al,KN_DOWN ; down?
  309. jne ??no_pad_move
  310. ??pad_move:
  311. ; DRD correction to use ch for ah
  312. mov ch,ah ; save shift-ctrl-alt-rlse status
  313. xor ah,ah ; get rid of any bits
  314. sub al,KN_UPLEFT ; get a number between 0 and 12
  315. mov bx,ax
  316. shl bx,1 ; double for WORD index
  317. add bx,OFFSET XYAdjust
  318. mov ax,[bx] ; get x,y add value
  319. mov bl,ah
  320. cbw
  321. xchg ax,bx
  322. cbw
  323. xchg ax,bx ; AX = mouse x delta, BX = mouse y delta
  324. ; DRD correction to use ch
  325. ; The CTRL key moves the mouse to the edge of the screen.
  326. test ch,CTRLPRESS ; is either ctrl key down?
  327. jne short ??ctrlon ; if so, ctrl is on
  328. ; DRD correction to use ch
  329. ; use fast speed of the mouse move if the shift key is held down.
  330. mov dx,1 ; for slow speed
  331. test ch,SHIFTPRESS ; is either shift key down?
  332. je short ??normspeed ; if not then neither shift is down
  333. ??doublespeed:
  334. add dx,3 ; for fast speed
  335. ??normspeed:
  336. add bx,dx ; add speed for y index
  337. mov bl,[KeyMouseMove+bx] ; get speed for y delta
  338. xchg ax,bx ; swap with ax to extend sign
  339. cbw
  340. xchg ax,bx
  341. xchg bx,dx ; save mouse y delta
  342. add bx,ax ; add speed for x index
  343. mov al,[KeyMouseMove+bx] ; get speed for x delta
  344. cbw
  345. xchg bx,dx ; restore mouse y delta
  346. jmp short ??ctrloff
  347. ??ctrlon:
  348. ; Table lookup method for determining hotkey positions for CTRL
  349. ; cursor combination. This algorithm is hard coded for an ADJUST
  350. ; value of 3. If this value changed, then this section will also
  351. ; have to be modified.
  352. and bx,011b ; Y = 1, 0, 3
  353. and ax,011b ; X = 1, 0, 3
  354. ; Table lookup method for determining hotkey positions for CTRL
  355. ; cursor combination. This algorithm is hard coded.
  356. ; -1, 0, 1
  357. and bx,011b ; Y = 3, 0, 1
  358. and ax,011b ; X = 3, 0, 1
  359. shl bx,1
  360. shl bx,1
  361. or bx,ax ; Lookup index.
  362. ; Convert raw index into logical (clockwise) index.
  363. shl bx,1
  364. mov bx,[EdgeConv+bx]
  365. shl bx,1
  366. shl bx,1
  367. mov ax,[ScreenEdge+bx] ; New absolute X
  368. mov bx,[ScreenEdge+bx+2] ; New absolute Y
  369. mov [LocalMouseX],ax
  370. mov [LocalMouseY],bx
  371. ??set_xyz:
  372. mov ax,[LocalMouseX] ; get new mouse x,y
  373. mov bx,[LocalMouseY]
  374. jmp short ??set_xy
  375. ; Process a normal faked mouse move.
  376. ??ctrloff:
  377. ; DRD change
  378. add [LocalMouseX],ax ; save it in our local
  379. jns short ??not_negative_x
  380. xor ax,ax
  381. mov [LocalMouseX],ax ; clear our local
  382. ??not_negative_x:
  383. ; DRD change
  384. add [LocalMouseY],bx ; save it in our local
  385. jns short ??not_negative_y
  386. xor bx,bx
  387. mov [LocalMouseY],bx ; clear our local
  388. ??not_negative_y:
  389. mov ax,[LocalMouseX] ; get new mouse x,y
  390. mov bx,[LocalMouseY]
  391. cmp ax,MAX_X_PIXEL ; bigger than
  392. jle short ??check_y
  393. mov ax,MAX_X_PIXEL
  394. ??check_y:
  395. cmp bx,MAX_Y_PIXEL ; bigger than
  396. jle short ??set_xy
  397. mov bx,MAX_Y_PIXEL
  398. ??set_xy:
  399. mov [LocalMouseX],ax
  400. mov [LocalMouseY],bx
  401. mov [MouseX],ax
  402. mov [MouseY],bx
  403. cmp [MouseUpdate],0 ; wait until mouse interrupt is done
  404. jne short ??noshow
  405. ; PWG: ARRGGGHHHH!
  406. ; call Low_Hide_Mouse
  407. ; call Low_Show_Mouse
  408. ??noshow:
  409. mov ax,KN_MOUSE_MOVE
  410. ??mousefake:
  411. mov [keycode],ax ; Fake a MOUSE_MOVE event.
  412. ??no_pad_move:
  413. ; Fetch working pointers to the keyboard ends.
  414. mov si,[KeyBufferTail]
  415. mov [tail],si ; Safety record.
  416. mov di,[KeyBufferHead]
  417. ; Record the base keycode (if there is room).
  418. push ax
  419. call Stuff_Key_WORD
  420. add sp,2
  421. or ax,ax
  422. jne short ??jmpnoroom
  423. ; Also record the mouse coordinates if necessary.
  424. mov ax,[keycode] ; get key code
  425. cmp al,KN_MOUSE_MOVE ; mouse move?
  426. je short ??recordmouse ; yes? then record the mouse cooordinates
  427. cmp al,KN_LMOUSE
  428. je short ??recordmouse
  429. cmp al,KN_RMOUSE
  430. je short ??recordmouse
  431. jmp short ??ok
  432. ??jmpnoroom:
  433. jmp ??noroom
  434. ; Record mouse coordinate X.
  435. ??recordmouse:
  436. push [LocalMouseX]
  437. call Stuff_Key_WORD
  438. add sp,2
  439. or ax,ax
  440. jne ??jmpnoroom
  441. add [size],2
  442. ; Record mouse coordinate Y.
  443. push [LocalMouseY]
  444. call Stuff_Key_WORD
  445. add sp,2
  446. or ax,ax
  447. jne ??jmpnoroom
  448. add [size],2
  449. ??ok:
  450. ; If PASSBREAKS is not active and this is a keyboard
  451. ; break AND it is not a mouse event, then don't put
  452. ; it into the buffer.
  453. mov bx,0101h ; Bit control tools.
  454. mov ax,[keycode]
  455. cmp al,KN_MOUSE_MOVE
  456. je short ??notreal
  457. cmp al,127
  458. je short ??notreal
  459. test ah,KEYRELEASE
  460. je short ??real
  461. xor bl,bl
  462. test [KeyFlags],PASSBREAKS
  463. jne short ??real
  464. cmp al,KN_LMOUSE
  465. je short ??real
  466. cmp al,KN_RMOUSE
  467. je short ??real
  468. ??notreal:
  469. mov [KeyBufferTail],si ; Nullify any KeyBufferTail changes.
  470. ??real:
  471. ; Update the KeysUpDown bit array.
  472. mov di,ax
  473. and di,07Fh
  474. mov cl,3
  475. shr di,cl ; DI = Byte offset into bit table.
  476. mov cl,al
  477. and cl,0111b ; CL = Bit offset into bit table byte.
  478. shl bx,cl
  479. not bh
  480. ; If this is a reapeat key and the key is already being held
  481. ; down, then don't stuff it into the keyboard buffer.
  482. test bl,[KeysUpDown+di]
  483. je short ??notalready
  484. test [KeyFlags],REPEATON
  485. jne short ??notalready
  486. mov [KeyBufferTail],si ; Nullify any KeyBufferTail changes.
  487. ??notalready:
  488. and [KeysUpDown+di],bh ; Force key bit to zero.
  489. or [KeysUpDown+di],bl ; Insert key bit as appropriate.
  490. ;??notreal:
  491. ; Successful keybuffer stuff could result in a
  492. ??norecord:
  493. mov ax,1
  494. jmp short ??exit
  495. ; Unsuccessful keybuffer stuff.
  496. ??noroom:
  497. mov ax,[tail]
  498. mov [KeyBufferTail],ax
  499. xor ax,ax ; Signal an error.
  500. ??exit:
  501. popf
  502. endif; NOT_FOR_WIN95
  503. ret
  504. ENDP Stuff_Key_Num
  505. ;***********************************************************
  506. ;***************************************************************************
  507. ;* KEYSTROKE_INTERRUPT -- Handles input that comes from the keyboard *
  508. ;* *
  509. ;* This routine intercepts the key codes on their way to the *
  510. ;* BIOS. With the adjustment of the Flags described above *
  511. ;* you can get a wide variety of effects. *
  512. ;* *
  513. ;* INPUT: none *
  514. ;* *
  515. ;* OUTPUT: none *
  516. ;* *
  517. ;* WARNINGS: This is an interrupt function *
  518. ;* *
  519. ;* HISTORY: *
  520. ;* 07/13/1994 PWG : Created. *
  521. ;*=========================================================================*
  522. label RM_Keystroke_Interrupt
  523. GLOBAL C Keystroke_Interrupt:FAR
  524. PROC Keystroke_Interrupt C FAR
  525. ifdef NOT_FOR_WIN95
  526. IF 0
  527. push ax
  528. inc ax
  529. pop ax
  530. iret
  531. ELSE
  532. push ax
  533. push bx
  534. push cx
  535. push di
  536. push ds
  537. push dx
  538. push es
  539. push si
  540. cld
  541. mov ax,cs ; set ds to cs to avoid cs overide
  542. mov ds,ax
  543. mov dx,[KeyFlags]
  544. ;*** The following fix allows proper caps and num lock tracking on Tandy
  545. ; 10-6-89 LJC, DRD
  546. and [KeyLock],NOT (NUMLOCK OR CAPSLOCK); assume caps and num inactive
  547. mov ax,040H ; BIOS segment
  548. mov es,ax ; put in es
  549. test [BYTE PTR es:017H],040H ; test Caps lock bit in BIOS
  550. je short ??bioscapsoff ; skip activate code
  551. or [KeyLock],CAPSLOCK ; Caps Lock active
  552. ??bioscapsoff:
  553. test [BYTE PTR es:017H],020H ; test Num lock bit in BIOS
  554. je short ??biosnumoff ; skip activate code
  555. or [KeyLock],NUMLOCK ; Num Lock active
  556. ??biosnumoff:
  557. mov [ExtKeyboard],TRUE ; assume 101/102-key keyboard
  558. test [BYTE PTR es:096H],010H ; test for 101/102-key keyboard
  559. jne short ??extkeyboard ; skip deactivate code
  560. mov [ExtKeyboard],FALSE ; no 101/102-key keyboard
  561. ??extkeyboard:
  562. mov ax,cs ; set ds to cs to avoid cs overide
  563. mov es,ax
  564. cld ; clear direction flag for strings
  565. xor ah,ah ; clear ctrl flags to 0
  566. mov bx,0101H ; set key to a make by default
  567. in al,KEYDATA ; get a code from the keyboard
  568. ;
  569. ; New CODE to montior key stream
  570. ;
  571. mov bx,[KeyStreamIndex]
  572. mov [KeyStream+bx],al
  573. inc bx
  574. and bx,15
  575. mov [KeyStreamIndex],bx
  576. mov bx,0101H ; set key to a make by default
  577. ;
  578. ; END OF SEQUENCE
  579. ;
  580. ;
  581. ; Handle the PAUSE key being pressed. If it is pressed, then
  582. ; signal that the next two input codes are to be thrown out.
  583. ;
  584. cmp al,0E1H ; see if this is a pause/break
  585. jne short ??notpcode ; not a pause/break start code
  586. mov [LastKeyE1],3 ; absorb this and next two codes
  587. ??notpcode:
  588. cmp [LastKeyE1],0 ; are we in a pause/break code
  589. je short ??notpause ; no, just keep going
  590. dec [LastKeyE1] ; yes, dec the count
  591. test dx,PAUSEON ; should it pass these codes
  592. jne ??passcode ; pass the code
  593. jmp ??absorbcode ; don't pass code
  594. ??notpause:
  595. ;
  596. ; Record any extended key codes that arrive. They will be
  597. ; taken into account with the next code.
  598. ;
  599. cmp al,0E0H ; is it an extended code
  600. jne short ??notextcode ; if not skip to handle key
  601. mov [LastKeyE0],TRUE ; set the extended code to 1
  602. ??jmppasscode:
  603. jmp ??passcode ; always pass E0s
  604. ??notextcode:
  605. ;
  606. ; Check and acknowledge if the key is a make or a break.
  607. ;
  608. test al,080H ; test for high bit
  609. je short ??make ; if off its a make
  610. xor bl,bl ; set make/break to break
  611. and al,07FH ; clear high bit
  612. or ah,KEYRELEASE ; CDY NEW -- ABSENT IN OLD CODE
  613. ??make:
  614. ;
  615. ; Translate the raw keycode into the Westwood keycode.
  616. ;
  617. cmp [LastKeyE0],FALSE ; was the prev byte an E0?
  618. je short ??normal ; if not it is a normal key
  619. mov [LastKeyE0],FALSE ; if so clear for next read
  620. mov [IsExtKey],TRUE ; it is an extended key
  621. mov di,OFFSET ExtCodes ; get offset of extended codes table
  622. mov cx,(ExtNums-ExtCodes) ; get number of entrys in ext table
  623. repne scasb ; look for a match
  624. jcxz ??absorbcode ; Not recognized, so throw it away.
  625. mov al,[(ExtNums - ExtCodes) - 1 + di] ; get the match
  626. mov [IsExtKey],FALSE ; it is not an extended key
  627. jmp short ??notext
  628. ??normal:
  629. cmp al,07Ah
  630. jne short ??normok
  631. mov al,128
  632. jmp short ??notext
  633. ??normok:
  634. mov di,ax ; use code as an index
  635. and di,007Fh ; Mask off any release bit.
  636. mov al,[KeyNums+di] ; get the key number of this key
  637. ??notext:
  638. ;
  639. ; Test and set the CTRL bit.
  640. ;
  641. test [KeysUpDown+8],001H ; is the right ctrl down?
  642. jne short ??ctrlon ; if so, ctrl is on
  643. test [KeysUpDown+7],004H ; is the left ctrl down?
  644. je short ??ctrloff ; if not, neither are down, no ctrl
  645. ; DRD
  646. ; check for CTRL-NUMLOCK for pause on some keyboards
  647. cmp al,KN_NUMLOCK ; check for CTRL-NUMLOCK
  648. jne short ??ctrlon
  649. cmp [ExtKeyboard],TRUE ; if 101/102-key keyboard it is ok
  650. je short ??ctrlon
  651. test dx,PAUSEON ; should it pass these codes
  652. jne short ??ctrlon ; pass the code
  653. jmp ??absorbcode ; don't pass code
  654. ??ctrlon:
  655. or ah,CTRLPRESS ; or on the ctrl bit in flags
  656. ??ctrloff:
  657. ;
  658. ; Test and set the ALT bit.
  659. ;
  660. test [KeysUpDown + 7],050H ; is either alt key down?
  661. je short ??altoff
  662. or ah,ALTPRESS ; or on the alt bit in flags
  663. ??altoff:
  664. ;
  665. ; Remap the keyboard keys if this is requested. (Do not set DGROUP
  666. ; as it is unecessary)
  667. push ax
  668. call KeyNum_Translate
  669. add sp,2
  670. ;------ Set the shift bit if necessary.
  671. test [KeysUpDown+5],010H ; is the left shift down?
  672. jne short ??shifton ; if so the shift is on
  673. test [KeysUpDown+7],002H ; is the right shift down?
  674. je short ??shiftoff ; if not then neither shift is down
  675. ??shifton:
  676. or ah,SHIFTPRESS ; or on the shift bit in flags
  677. ??shiftoff:
  678. ;
  679. ;------ Toggle the shift state if the caps lock key is on (if necessary).
  680. ;
  681. mov di,ax
  682. and di,07Fh
  683. shr di,1
  684. shr di,1
  685. shr di,1
  686. mov bx,ax
  687. and bx,07Fh
  688. and bl,0111b
  689. mov ch,[Bits+bx] ; get the bit to test
  690. test [KeyLock],CAPSLOCK ; is the caps lock on?
  691. je short ??capsoff ; if not don't worry about it
  692. test ch,[KeysCapsLock+di] ; get code for keycaps
  693. je short ??capsoff ; its not effected
  694. xor ah,SHIFTPRESS ; toggle the shift flag
  695. ??capsoff:
  696. ;
  697. ;------ Toggle the shift state if the num-lock key is on (if necessary).
  698. ;
  699. test [KeyLock],NUMLOCK ; is the num lock key on?
  700. je short ??numlockoff ; if not don't worry about it
  701. test ch,[KeysNumLock+di] ; get code for numlock
  702. je short ??numlockoff ; if not effected skip toggle
  703. xor ah,SHIFTPRESS ; toggle the shift flag if effected
  704. ??numlockoff:
  705. ;------ Remember the current control/shift/alt bit settings for later use.
  706. ;??noshiftever:
  707. mov [CtrlFlags],ah ; save off shift-ctrl-alt flags
  708. ; for the mouse and joystick routines
  709. ; to use in stuffing key into the
  710. ; keyboard buffer.
  711. ;------ The CTRL-ALT-DEL key combination always gets passed to the system.
  712. cmp ax,0668H ; is it ctrl alt del?
  713. je ??passcode
  714. cmp ax,064CH ; is it ctrl alt ext del?
  715. je ??passcode ; if so don't add it to the buffer
  716. ;------ Special Ctrl-C check.
  717. cmp ax,0230h
  718. je short ??breaker
  719. cmp ax,027Eh
  720. jne short ??nobreak
  721. ??breaker:
  722. mov [Break],1
  723. ??nobreak:
  724. ;------ Check for Music and Sound control keys.
  725. cmp ax,0420H ; is this an alt s
  726. jne short ??checkmusic ; toggle the Sound variable
  727. push ax
  728. mov ax,[SoundOn]
  729. xor ax,01H
  730. push ax
  731. add sp,2
  732. pop ax
  733. ??checkmusic:
  734. cmp ax,0434H ; is this an alt m
  735. jne short ??esc ; toggle the Music variable
  736. push ax
  737. mov ax,[MusicOn]
  738. xor ax,01H
  739. push ax
  740. add sp,2
  741. pop ax
  742. ??esc:
  743. push ax
  744. call Stuff_Key_Num
  745. pop ax
  746. ??skipstuff:
  747. ;------ Do the special ESC routine if necessary.
  748. cmp al,110 ; is this the esc key?
  749. jne short ??noroutine ; if not goto the pass always
  750. cmp [WORD PTR EscRoutine+2],0 ;if vector is 0 don't jump
  751. je short ??noroutine
  752. push ax
  753. call [EscRoutine]
  754. pop ax
  755. ??noroutine:
  756. ;------ Check to see if the key is to be passed to the system or not.
  757. mov di,OFFSET PassAlways ; get offset to table
  758. mov cx,(PassAlwaysEnd - PassAlways) ; get number of pass always CDY JLB MOD 7/11 was +1
  759. repne scasb ; look for a match
  760. or cx,cx ; see if there was no match
  761. jne ??passcode ; CDY JLB 7/11 optimization
  762. ??passalways:
  763. ; now check for conditional passes
  764. mov di,OFFSET CondPassKey ; get offset to cond key table
  765. mov cx,(CondPassCond-CondPassKey) ; get number of entries
  766. shr cx,1 ; cut in half for words
  767. repne scasw ; look for a match
  768. jcxz short ??notcondpass ; OPTIMIZATION CDY JLB
  769. mov bx,[(CondPassCond - CondPassKey) - 2 + di]
  770. and bx,dx ; are the conditions met?
  771. je short ??notcondpass ; NO... check normally.
  772. jmp short ??passcode ; YES... pass back to system.
  773. ;
  774. ;------ Last check before passing keycode back to the system.
  775. ;
  776. ??notcondpass:
  777. test dx,FILTERONLY ; is the filter only flag on?
  778. je short ??absorbcode ; if not, absorb the code.
  779. ;***********************************************************
  780. pushf
  781. ; push di
  782. ; push es
  783. mov ax,0B000h
  784. mov es,ax
  785. inc [BYTE PTR es:0]
  786. ; pop es
  787. ; pop di
  788. popf
  789. ;***********************************************************
  790. ??passcode:
  791. pop si
  792. pop es
  793. pop dx
  794. pop ds
  795. pop di
  796. pop cx
  797. pop bx
  798. pop ax
  799. inc [cs:PassCount]
  800. jmp [cs:OldRMI]
  801. ??absorbcode:
  802. in al,KEYCTRL ; get the control port
  803. mov ah,al
  804. or al,080H ; reset bit for keyboard
  805. out KEYCTRL,al
  806. xchg ah,al ; get orig control data
  807. out KEYCTRL,al ; restore control data
  808. mov ax,040h ; BIOS paragraph is always @ 040h
  809. mov es,ax ; put in es as BIOS paragraph
  810. mov al,[es:96h] ; get extended keys
  811. and al,0FDh ; turn off last key e0 flag
  812. mov [es:96h],al ; set extended keys
  813. mov al,CLEARISR ; value to clear In Service Register
  814. out INTCHIP0,al ; 8259 interrupt chip controller 0
  815. pop si
  816. pop es
  817. pop dx
  818. pop ds
  819. pop di
  820. pop cx
  821. pop bx
  822. pop ax
  823. iret
  824. ENDIF
  825. endif ;NOT_FOR_WIN95
  826. ENDP Keystroke_Interrupt
  827. ;***************************************************************************
  828. ;* BREAK_INTERRUPT -- Handles the break key interrupt *
  829. ;* *
  830. ;* INPUT: none *
  831. ;* *
  832. ;* OUTPUT: none *
  833. ;* *
  834. ;* WARNINGS: This is an interrupt routine. *
  835. ;* *
  836. ;* HISTORY: *
  837. ;* 07/13/1994 PWG : Created. *
  838. ;*=========================================================================*
  839. GLOBAL C Break_Interrupt:FAR
  840. PROC Break_Interrupt C FAR
  841. iret
  842. ENDP Break_Interrupt
  843. ;**************************************************************************
  844. ;* CALL_INTERRUPT_CHAIN -- Function PM calls to call the RM interrupt chain*
  845. ;* *
  846. ;* *
  847. ;* INPUT: *
  848. ;* *
  849. ;* OUTPUT: *
  850. ;* *
  851. ;* WARNINGS: *
  852. ;* *
  853. ;* HISTORY: *
  854. ;* 07/08/1994 SKB : Created. *
  855. ;*=========================================================================*
  856. Call_Interrupt_Chain:
  857. ifdef NOT_FOR_WIN95
  858. IF 0
  859. pushf
  860. push ax
  861. push di
  862. push es
  863. mov ax,0B000h ; ES:DI = Mono RAM address.
  864. mov es,ax
  865. mov al,'A'
  866. mov ah,2
  867. and di,63
  868. stosw
  869. in al,KEYDATA ; get a code from the keyboard
  870. mov al,CLEARISR ; value to clear In Service Register
  871. out INTCHIP0,al ; 8259 interrupt chip controller 0
  872. pop es
  873. pop di
  874. pop ax
  875. popf
  876. ENDIF
  877. pushf
  878. call Keystroke_Interrupt ;[OldRMI]
  879. endif; NOT_FOR_WIN95
  880. retf
  881. STACK ; Don't really need this
  882. ;***********************************************************
  883. END