home *** CD-ROM | disk | FTP | other *** search
/ Phoenix CD 2.0 / Phoenix_CD.cdr / 24b / keyboard.zip / KEYLOC.ASM < prev    next >
Assembly Source File  |  1985-08-21  |  7KB  |  351 lines

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