home *** CD-ROM | disk | FTP | other *** search
/ Programmer 7500 / MAX_PROGRAMMERS.iso / INFO / EDITOR / TDE120.ZIP / SIMUL101.ASM < prev    next >
Encoding:
Assembly Source File  |  1991-10-05  |  11.1 KB  |  267 lines

  1. ; This function simulates the scan codes of the 101 keyboard on older 83/84 key
  2. ; keyboard systems that lack bios support for some often used 101 keyboard
  3. ; control key combinations.  I miss being able to use the Control+Up, which is
  4. ; one of the key combinations that the old BIOS does not support on my old
  5. ; machine at home.  Not all of the 101 keys are simulated.  I decided to return
  6. ; simulated scan codes for the 83/84 keypad keys only.  It would be trivial to
  7. ; expand this utility to include almost all of the 101 extended codes, but
  8. ; I sorta doubt users will miss keys like Alt + ; or Alt + ~ on 83/84 keyboards
  9. ; (especially if they couldn't use them in the first place).
  10. ;
  11. ; If this routine were to mimic the enhanced BIOS exactly, it would return
  12. ; 0xE0 in register al and the extended code in ah for the simulated scan codes.
  13. ; I have decided to stay with the original BIOS convention and return 0x00 in
  14. ; register al and the extended code in register ah.
  15. ;
  16. ; To see if control+up is pressed, we have to look at the keyboard status flags
  17. ; in the bios data area.  The flags at byte 0040:0017 are as follows:
  18. ;
  19. ;   Bit
  20. ;    7   Insert state  1 = active,  0 = inactive
  21. ;    6   Caps Lock     1 = active,  0 = inactive
  22. ;    5   Num Lock      1 = active,  0 = inactive
  23. ;    4   Scroll Lock   1 = active,  0 = inactive
  24. ;    3   Alt Shift     1 = active,  0 = inactive
  25. ;    2   Ctrl Shift    1 = active,  0 = inactive
  26. ;    1   Left Shift    1 = active,  0 = inactive
  27. ;    0   Right Shift   1 = active,  0 = inactive
  28. ;
  29. ; We are only concerned with bits 0-3, the shift status bits.  At label "k1"
  30. ; in this routine, the status byte is tested with 0x0f.  With simple tests,
  31. ; the status of the shift keys can be determined.  Then, it easy to use the
  32. ; tables to translate (XLAT) the raw key codes to extended scan codes.
  33. ;
  34. ; This function was designed to be linked with C object code.  The prototype
  35. ; for this function is far so it may be easily used with any memory model.
  36. ;
  37. ; For those of you (like me) who use keyboard speed up or other keyboard TSRs
  38. ; on XT's, you will find that those TSRs do not work with simulated scan codes
  39. ; generated by this utility.  This function grabs the raw keys before the TSR
  40. ; gets them and they don't get passed to the TSR.  This is the reason I mapped
  41. ; the "Keypad -" and "Keypad +" to the scroll up and scroll down functions -
  42. ; they aren't filtered by this function and get through to the typefast (TSR)
  43. ; utilities.
  44. ;
  45. ; Editor name:   tde, the Thomson-Davis Editor.
  46. ; Author:        Frank Davis
  47. ; Date:          September 9, 1991
  48. ;
  49. ; This code is released into the public domain, Frank Davis.  You may
  50. ; distribute it freely.
  51.  
  52. kb_data_port    EQU     60h
  53. kb_cntl_port    EQU     61h
  54.  
  55. bios_data       SEGMENT AT 40h
  56.                 ORG     17h
  57. kb_status       DB      ?
  58.                 ORG     1ah
  59. buffer_head     DW      ?
  60. buffer_tail     DW      ?
  61.                 ORG     80h
  62. buffer_start    DW      ?
  63. buffer_end      DW      ?
  64. bios_data       ENDS
  65.  
  66.  
  67. _TEXT   SEGMENT WORD PUBLIC 'CODE'
  68.         ASSUME  cs:_TEXT, ds:NOTHING, es:bios_data
  69.         public  _simulate_enh_kbd
  70.  
  71.  
  72. ;
  73. ; Prototype this function as far in the C header file so it may be used easily
  74. ; with any memory model.
  75. ;
  76. _simulate_enh_kbd       PROC    FAR
  77.         jmp     initialize
  78.  
  79.  
  80. ; Map the keys starting at scan code 47h, which is the Home key.  This routine
  81. ; DOES NOT return most of these values from systems with a 101 enhanced keyboard
  82. ; connected, but the codes are included here for reference.  One should use the
  83. ; extended BIOS keyboard services with the 101 keyboard and not this function.
  84. ; Indeed, tde uses the extended BIOS if a 101 keyboard is detected.
  85. ;
  86. ;       Home   = 47h    Left   = 4bh    End   = 4fh    Del    = 53h   F11 = 57h
  87. ;       Up     = 48h    Center = 4ch    Down  = 50h    SysReq = 54h   F12 = 58h
  88. ;       PgUp   = 49h    Right  = 4dh    PgDn  = 51h    ---    = 55h
  89. ;       Grey - = 4ah    Grey + = 4eh    Ins   = 52h    ---    = 56h
  90. ;
  91. ;               47,  48,  49,  4a,  4b,  4c,  4d,  4e,  4f,  50,  51,  52,
  92. ;               53   54,  55,  56,  57,  58
  93. table:
  94.         DB      -1,  -1,  -1,  -1,  -1,  76,  -1,  -1,  -1,  -1,  -1,  -1
  95.         DB      -1,  -1,  -1,  -1, 133, 134
  96. shift_table:
  97.         DB      -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1
  98.         DB      -1,  -1,  -1,  -1, 135, 136
  99. ctrl_table:
  100.         DB      -1, 141,  -1, 142,  -1, 143,  -1, 144,  -1, 145,  -1, 146
  101.         DB     147,  -1,  -1,  -1, 137, 138
  102. alt_table:
  103.         DB      -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1
  104.         DB      -1,  -1,  -1,  -1, 139, 140
  105.  
  106. old_int_9       DW      ?,?     ; space for old interrupt
  107.  
  108. start:
  109.         sti
  110.         push    ax      ; push the registers we use
  111.         push    bx
  112.         push    dx
  113.         push    ds
  114.         push    es
  115.  
  116.         in      al, kb_data_port        ; let's look at the waiting key
  117.  
  118.         cmp     al, 47h         ; is it less than home?
  119.         jb      pop_out_9       ; yes, let regular int handle it
  120.         cmp     al, 80h         ; is it less than a break code?
  121.         jb      k1              ; yes, let's look at this key - a keypad key
  122.         ALIGN   2
  123. pop_out_9:
  124.         jmp     regular_int_9   ; default - let regular int 9 handle break codes
  125.                                 ; and other stuff
  126.  
  127. k1:
  128.         mov     dx, 0040h       ; segment of bios data area
  129.         mov     es, dx          ; put it in es
  130.         mov     dl, BYTE PTR es:kb_status  ; get shift status of alt & ctrl keys
  131.         test    dl, 0fh         ; & it with 0x0f to see if any shift keys down
  132.         jnz     k2              ; one of the shift keys is pressed - find it
  133.         mov     bx, OFFSET table        ; get offset of table
  134.         jmp     SHORT k5        ; no shift keys were down, translate normal keys
  135. k2:
  136.         test    dl, 03h                 ; are the left or right shift keys down?
  137.         jz      k3                      ; not pressed, must be a ctrl or an alt
  138.         mov     bx, OFFSET shift_table  ; get offset of shift table
  139.         jmp     SHORT k5
  140. k3:
  141.         test    dl, 04h                 ; is the control shift key down?
  142.         jz      k4                      ; not pressed, must be an alt
  143.         mov     bx, OFFSET ctrl_table   ; get offset of control table
  144.         jmp     SHORT k5
  145. k4:
  146.                                         ; the only shift key left is alt
  147.         mov     bx, OFFSET alt_table    ; get offset of alt table
  148.         ALIGN   2
  149. k5:
  150.         sub     al, 47h         ; normalize key to zero
  151.  
  152.         mov     dx, cs          ; put code segment in dx
  153.         mov     ds, dx          ; now transfer code segment to ds
  154.  
  155.         xlat                    ; table look up
  156.         cmp     al, -1          ; is it -1?
  157.         je      regular_int_9   ; yes, let regular interrupt 9 handle it
  158.  
  159.         mov     ah, al          ; put copy of character in ah
  160.         xor     al, al          ; zero out scan code - simulate extended key
  161.  
  162. ;
  163. ; We now have a key we want to emulate.  Put it in the keyboard buffer and
  164. ; end our interrupt.
  165. ;
  166.  
  167.         mov     bx, WORD PTR es:buffer_tail     ; get the end pointer to buffer
  168.         mov     dx, bx                          ; save in dx
  169.         inc     dx                              ; move to next word in list
  170.         inc     dx
  171.         cmp     dx, WORD PTR es:buffer_end      ; at end of buffer?
  172.         jnz     ck_full_kbd                     ; if no, continue
  173.         mov     dx, WORD PTR es:buffer_start    ; yes, reset to buffer start
  174.         ALIGN   2
  175.  
  176. ck_full_kbd:
  177.         cmp     dx, WORD PTR es:buffer_head     ; has the buffer wrapped?
  178.         jz      end_int_9       ; yes, kbd full - enable keyboard for next key
  179.         mov     WORD PTR es:[bx], ax    ; store simulated key into kbd buffer
  180.         mov     WORD PTR es:buffer_tail, dx     ; move the tail up for next key
  181.         ALIGN   2
  182.  
  183. end_int_9:
  184.         cli                     ; no interrupts now
  185.         mov     al, 20h         ; end of interrupt command
  186.         out     20h, al         ; send command to interrupt control port
  187.         in      al, kb_cntl_port        ; get char from control port
  188.         mov     ah, al                  ; save it in ah
  189.         or      al, 80h                 ; set bit 7
  190.         out     kb_cntl_port, al        ; output reset value
  191.         mov     al, ah                  ; send original value
  192.         jmp     SHORT $+2               ; take your time
  193.         out     kb_cntl_port, al        ; send it to enable keyboard
  194.         sti
  195.         pop     es              ; restore registers
  196.         pop     ds
  197.         pop     dx
  198.         pop     bx
  199.         pop     ax
  200.         iret                    ; return from interrupt
  201. regular_int_9:
  202.         pop     es              ; restore registers
  203.         pop     ds
  204.         pop     dx
  205.         pop     bx
  206.         pop     ax
  207.         jmp     DWORD PTR old_int_9     ; no interrupt return - old one does it
  208.  
  209. ; ***********************************************************************
  210. ; prototype for _simulate_enh_kbd is
  211. ;
  212. ;               void far simulate_enh_kbd( int )
  213. ;
  214. ; The formal parameter is available on the stack.  Use the bp register to
  215. ; access it.
  216. ;
  217. ; Passing any non-zero value will make this function grab interrupt 9.
  218. ; Pass a zero to this function to restore the old interrupt 9.
  219. ;
  220. ; If this function were really clever, it would have a "unique" signature.
  221. ; Before "installing", it would check to see if it was already installed.
  222. ; Similarly, before "uninstalling", this function would check to make sure
  223. ; it was installed so it wouldn't uninstall the regular interrupt 9
  224. ; handler by accident.  What the hell, live dangerously.
  225. ;
  226. ; ***********************************************************************
  227.  
  228. initialize:
  229.         push    bp
  230.         mov     bp, sp
  231.  
  232.         mov     dx, [bp+6]      ; put the parameter in dx
  233.  
  234.         push    ds
  235.         ASSUME  es:_TEXT,ds:_TEXT
  236.         mov     ax, cs          ; put cs in ds
  237.         mov     es, ax
  238.         mov     ds, ax
  239.  
  240.         cmp     dx, 0           ; 'NULL' character unhooks interrupt 9
  241.         je      restore_9       ; any non NULL character grabs interrupt 9
  242. grab_9:
  243.         mov     ax, 3509h       ; get old interrupt 9 location
  244.         int     21h             ; call MSDOS to get it
  245.         mov     WORD PTR old_int_9, bx          ; save old int 9 offset
  246.         mov     WORD PTR old_int_9+2, es        ; save old int 9 segment
  247.  
  248.         mov     dx, OFFSET start        ; get new offset of int 9
  249.         mov     ax, 2509h               ; use function 25 so int 9 points
  250.         int     21h                     ;  to my routine
  251.         jmp     SHORT get_out           ; continue with editor
  252.  
  253. restore_9:
  254.         mov     dx, WORD PTR old_int_9          ; get offset of old int 9
  255.         mov     ax, WORD PTR old_int_9+2        ; get segment of old int 9
  256.         mov     ds, ax                          ;  put segment in ds
  257.         mov     ax, 2509h                       ; restore old int 9
  258.         int     21h
  259.  
  260. get_out:
  261.         pop     ds              ; clean up
  262.         pop     bp
  263.         retf
  264. _simulate_enh_kbd       endp
  265. _TEXT   ends
  266.         end
  267.