home *** CD-ROM | disk | FTP | other *** search
/ Frostbyte's 1980s DOS Shareware Collection / floppyshareware.zip / floppyshareware / USCX / DOSUT-03.ZIP / KEYLK3.ASM < prev    next >
Assembly Source File  |  1983-07-20  |  14KB  |  370 lines

  1.                 page    64,132
  2.  
  3. Comment @
  4.     This is a patch to the ROM BIOS keyboard routine.  When the patch is
  5.     loaded, the Alt, Ctrl, Left Shift and Right Shift keys toggle between
  6.     their shifted and unshifted states.
  7.  
  8.     There are two main entry points.
  9.  
  10.     1.  'Keyloc' sets up the keyboard interupt vector to point to the patch
  11.         instead of the normal BIOS routine.  After Keyloc executes, it
  12.         leaves the new interupt handler resident in memory.
  13.  
  14.     2.  'Ikeyloc' is the new keyboard interupt handler.  The first section
  15.         is a duplication of the ROM BIOS routine until a point where tests
  16.         for the input of a Alt, Ctrl, Left Shift or Right Shift key can be
  17.         made.  If it is one of those keys, the appropriate bits in the
  18.         keyboard flag byte are twiddled.
  19.  
  20.     John Black
  21.     5225 Pooks Hill Rd. #1715 N.
  22.     Bethesda MD. 20814
  23. @
  24.  
  25. port_b          equ     60h     ; 8255 port a addr
  26. timer           equ     40h
  27. kb_data         equ     60h     ; keyboard scan code port
  28. kb_ctl          equ     61h     ; control bits for keyboard sense data
  29.  
  30. abso            segment at 0
  31.                 org     24h
  32. kb_vector       label   dword
  33. abso            ends
  34.  
  35. rom_version = 3
  36.  
  37.    if   (rom_version eq 1) or (rom_version eq 2)
  38. bioscode        segment at 0F000h
  39. ;
  40. ;  Location definitions from Technical Reference Manual for Versions
  41. ;  04/24/81 or 10/19/81 of BIOS rom.
  42. ;
  43.                 org     0E9AFh          ; page A-27 of Technical Reference
  44. K16             label   far             ; resume code if not shift
  45.  
  46.                 org     0EA23h          ; page A-27
  47. K23             label   far             ; break for shift key
  48.  
  49.                 org     0EA5Eh          ; page A-27
  50. K26             label   far             ; return from interupt
  51.  
  52.                 org     0EC24h          ; page A-31
  53. K62             label   far             ; error
  54. bioscode        ends
  55.    endif
  56.  
  57.  
  58.     if  rom_version eq 3
  59. bioscode        segment at 0F000h
  60. ;
  61. ;  Location definitions from Technical Reference Manual for Version
  62. ;  10/27/82 of BIOS rom
  63. ;
  64.                 org     0E9ADh          ; page A-30 of Technical Reference
  65. K16             label   far             ; resume code if not shift
  66.  
  67.                 org     0EA1Eh          ; page A-30
  68. K23             label   far             ; break for shift key
  69.  
  70.                 org     0EA59h          ; page A-31
  71. K26             label   far             ; return from interupt
  72.  
  73.                 org     0EC27h          ; page A-35
  74. K62             label   far             ; error
  75. bioscode        ends
  76.     endif
  77.  
  78. biosdata        segment at 40h
  79.  
  80.                 org     17h
  81. kb_flag         label   byte
  82. ;       ...bit definitions for kb_flag
  83. ins_state       equ     80h             ; insert state is active
  84. caps_state      equ     40h             ; caps lock state has been toggled
  85. num_state       equ     20h             ; num lock state has been toggled
  86. scroll_state    equ     10h             ; scroll lock state has been toggled
  87. alt_shift       equ     08h             ; alternate shift key depressed
  88. ctl_shift       equ     04h             ; control shift key depressed
  89. left_shift      equ     02h             ; left shift key depressed
  90. right_shift     equ     01h             ; right shift key depressed
  91.  
  92. ;       ...scan codes
  93. num_key         equ     69
  94. scroll_key      equ     70
  95. alt_key         equ     56
  96. ctl_key         equ     29
  97. caps_key        equ     58
  98. left_key        equ     42
  99. right_key       equ     54
  100. ins_key         equ     82
  101. del_key         equ     83
  102. biosdata        ends
  103.  
  104. keylocs segment para public 'CODE'
  105.                 assume  cs:keylocs
  106.  
  107. keyloc_ident    db      'KEYLOC'
  108. ident_length    equ     6
  109. ikeyloc         proc    far             ; interupt entry point
  110.                 sti                     ; begin copy of ROM BIOS
  111.                 push    ax
  112.                 push    bx
  113.                 push    cx
  114.                 push    dx
  115.                 push    si
  116.                 push    di
  117.                 push    ds
  118.                 push    es
  119.                 cld
  120.                 mov     ax,biosdata
  121.                 mov     ds,ax
  122.                 in      al,kb_data
  123.                 push    ax
  124.                 in      al,kb_ctl
  125.                 mov     ah,al
  126.                 or      al,80h
  127.                 out     kb_ctl,al
  128.                 xchg    ah,al
  129.                 out     kb_ctl,al
  130.                 pop     ax
  131.                 mov     ah,al
  132.                 cmp     al,0FFh
  133.                 jnz     keylocpatch
  134.                 jmp     K62
  135.                                         ; End of rom code copy
  136. keylocpatch:
  137.                 push    ax
  138.                 assume  ds:biosdata
  139.  
  140.                 and     al,01111111b    ; mask out break indicator
  141.                 cmp     al,alt_key
  142.                 je      alt_in
  143.                 cmp     al,ctl_key
  144.                 je      ctrl_in
  145.                 cmp     al,left_key
  146.                 je      leftshift_in
  147.                 cmp     al,right_key
  148.                 je      rightshift_in
  149. ;               ...return to normal bios keyboard routine
  150. retbioskey:     pop     ax
  151.                 jmp     K16
  152.  
  153.  
  154. alt_in:
  155.                 mov     al,alt_shift
  156.                 call    Depress_lock
  157. ;               ... if this is a break, enter bios at K23
  158.                 pop     ax
  159.                 mov     ah,alt_shift
  160.                 test    al,80h                  ;  if
  161.                 jz      fi                      ;  .
  162.                 test    kb_flag,alt_shift       ;  .
  163.                 jnz     fi                      ;  .
  164.                                                 ;  / break and not depressed
  165.                                                 ;  .
  166.                 or      kb_flag,alt_shift       ;  .  Reset depressed flag
  167.                 jmp     K23                     ;  .  Return in case using
  168.                                                 ;  .  alt keypad entry
  169. fi:                                             ;  fi
  170.                 jmp     K26
  171.  
  172. ctrl_in:
  173.                 mov     al,ctl_shift
  174.                 call    Depress_lock
  175.                 jmp     retdone
  176. leftshift_in:
  177.                 mov     al,left_shift
  178.                 call    Depress_lock
  179.                 jmp     retdone
  180. rightshift_in:
  181.                 mov     al,right_shift
  182.                 call    Depress_lock
  183.                 jmp     retdone
  184.  
  185. retdone:        pop     ax
  186.                 jmp     K26
  187. ikeyloc         endp
  188.  
  189. ;---------------------------------------------
  190. ;
  191. ;   Depress_lock
  192. ;
  193. ;       For keys that normally are depressed and held down
  194. ;       while another key is depressed. (Cntl for example)
  195. ;
  196. ;       ah      input key, with break indicator (80h)
  197. ;       al      contains depressed indicator bit mask
  198. ;
  199. Down            db      ?       ; indicates the key is held down
  200. Depress_lock    proc    near
  201.                 push    dx
  202.                 test    ah,80h                  ; if1
  203.                 jnz     fi1                     ; .
  204.                 test    Down,al                 ; .
  205.                 jnz     fi1                     ; .
  206.                                                 ; / make and not down
  207.                 test    kb_flag,al              ; .   if2
  208.                 je      else2                   ; .   .
  209.                                                 ; .   / depressed
  210.                 call    high_beep               ; .   .
  211.                 call    delay                   ; .   .
  212.                 call    low_beep                ; .   .
  213.                 mov     dl,al                   ; .   . dl:=depressed bit
  214.                 not     dl                      ; .   .
  215.                 and     kb_flag,dl              ; .   . key := not depressed
  216.                 jmp     fi1                     ; .   .
  217. else2:                                          ; .   / not depressed
  218.                 call    low_beep                ; .   .
  219.                 call    delay                   ; .   .
  220.                 call    high_beep               ; .   .
  221.                 or      kb_flag,al              ; .   . key := depressed
  222. fi1:                                            ; fi1 fi2
  223.  
  224.                 test    ah,80h                  ; if5
  225.                 jnz     else5                   ; .
  226.                                                 ; / make
  227.                 or      Down,al                 ; .  down := true
  228.                 jmp     fi5                     ; .
  229. else5:                                          ; / break
  230.                 mov     dl,al                   ; .
  231.                 not     dl                      ; .
  232.                 and     Down,dl                 ; .  down := false
  233. fi5:                                            ; fi5
  234.                 pop     dx
  235.                 ret
  236. Depress_lock    endp
  237.  
  238.  
  239. ;---------------------------------
  240. h_cycles        equ     20
  241. h_half          equ     300
  242. l_cycles        equ     h_cycles / 3
  243. l_half          equ     h_half * 3
  244.  
  245. low_beep        proc
  246.                 push    dx
  247.                 push    bx
  248.                 mov     bx,l_cycles
  249.                 mov     dx,l_half
  250.                 call    beep
  251.                 pop     bx
  252.                 pop     dx
  253.                 ret
  254. low_beep        endp
  255.  
  256. high_beep       proc
  257.                 push    dx
  258.                 push    bx
  259.                 mov     bx,h_cycles
  260.                 mov     dx,h_half
  261.                 call    beep
  262.                 pop     bx
  263.                 pop     dx
  264.                 ret
  265. high_beep       endp
  266.  
  267. ;---------------------------------
  268. ; Adapted from BIOS Beep routine
  269. ;
  270. ;  bx = # of cycles
  271. ;  dx = length of half cycle
  272.  
  273. beep            proc    near
  274.                 push    ax
  275.                 push    cx
  276.                 in      al,kb_ctl
  277.                 push    ax
  278. k65:
  279.                 and     al,0FCh
  280.                 out     kb_ctl,al
  281.                 mov     cx,dx
  282. k66:            loop    k66
  283.                 or      al,2
  284.                 out     kb_ctl,al
  285.                 mov     cx,dx
  286. k67:            loop    k67
  287.                 dec     bx
  288.                 jnz     k65
  289.                 pop     ax
  290.                 out     kb_ctl,al
  291.                 pop     cx
  292.                 pop     ax
  293.                 ret
  294. beep            endp
  295.  
  296. ;--------------------------------
  297. delay           proc    near
  298.                 push    cx
  299.                 mov     cx,15000
  300.                 loop    $
  301.                 pop     cx
  302.                 ret
  303. delay           endp
  304.  
  305. ikeylast        equ     $       ; last location + 1 to remain in memory
  306.  
  307. stacks          segment stack 'STACK'
  308.                 db      64 dup('stack   ')
  309. stacks          ends
  310.  
  311. ;-------------------------------------
  312. loaded_mess     db      'KEYLOC loaded$'
  313. err_mess        db      'error - KEYLOC is already loaded$'
  314. keyloc          proc    far
  315.                 push    ds
  316.                 sub     ax,ax
  317.                 push    ax
  318.                 push    ds                      ; save program seg
  319.  
  320. ;               ...Check to see if a copy of KEYLOC has
  321. ;                  already been loaded by comparing Keyloc_ident
  322. ;                  with the same locations relative the the current
  323. ;                  keyboard interupt routine ( it is pointed to by the
  324. ;                  the keyboard interupt vector)
  325.                 cld                                     ; increment
  326.                 assume  ds:abso
  327.                 mov     ax,abso
  328.                 mov     ds,ax
  329.                 mov     si,offset keyloc_ident
  330.                 mov     ax,kb_vector+2                  ; segment
  331.                 mov     di,kb_vector                    ; offset to ident
  332.                 sub     di,ident_length
  333.                 mov     es,ax
  334.                 assume  ds:keylocs
  335.                 mov     ax,keylocs
  336.                 mov     ds,ax
  337.                 mov     cx,ident_length
  338.                 repne   cmpsb                           ; ds:[si],es:[di]
  339.                 cmp     cx,0                            ; if
  340.                 je      NotLoaded                       ; .
  341.                                                         ; / already loaded
  342.                 mov     ah,9h                           ; .  print string
  343.                 mov     dx,offset err_mess              ; .
  344.                 int     21h                             ; .
  345.                 pop     ds                              ; . get rid of pseg
  346.                 ret                                     ; . return to DOS
  347. NotLoaded:                                              ; fi
  348.  
  349. ;               ...set up keyboard interupt vector
  350.                 mov     ah,9h
  351.                 mov     dx,offset loaded_mess
  352.                 int     21h
  353.                 assume  ds:abso
  354.                 mov     ax,abso
  355.                 mov     ds,ax
  356.                 mov     ax,offset ikeyloc               ; ip
  357.                 mov     kb_vector,ax
  358.                 mov     ax,seg ikeyloc                  ; cs
  359.                 mov     kb_vector+2,ax
  360. ;               ...return to DOS, but leave ikeyloc resident
  361.                 pop     es                              ; get program segment
  362.                 mov     es:byte ptr 1,27h               ; change int 20 to 27
  363.                 mov     dx,offset ikeylast+100h         ; dx:=lastaddr+1+prfx
  364.                 ret
  365. keyloc          endp
  366.  
  367. keylocs         ends
  368.  
  369.                 end     keyloc
  370.