home *** CD-ROM | disk | FTP | other *** search
/ Simtel MSDOS 1992 September / Simtel20_Sept92.cdr / msdos / at / swpkeyat.arc / SWPKEYAT.ASM < prev    next >
Assembly Source File  |  1989-01-18  |  8KB  |  237 lines

  1.     TITLE    SWPKEYAT -- Swap IBM-PC/AT Keys
  2.     SUBTTL    History
  3.  
  4. ;    This program intercepts the IBM-PC/AT's keyboard hardware interrupt
  5. ; and messes around with the keyboard scan codes, specifically to swap the
  6. ; "Esc" and "~" keys.  It then returns to the ROM BIOS for the remainder
  7. ; of the keyboard interrupt processing.
  8.  
  9. ;    Note that the only way that I can return to the ROM BIOS for the
  10. ; remainder of the keyboard processing is to jump to a nonstandard known
  11. ; location in ROM.  This is an unfortunate practice.  The only other
  12. ; option I can see is for SWPKEYAT to contain it's own copy of the entire
  13. ; keyboard interrupt code.  However, I don't have time to do this yet.
  14.  
  15. ;    Because of the way that SWPKEYAT interacts with the keyboard
  16. ; hardware interrupt vector and the BIOS ROM, you must load this program
  17. ; BEFORE you load other keyboard processing programs, such as ScrollMate
  18. ; and BUF160.  Perhaps with more effort I could devise a cleaner interface.
  19.  
  20. ;    Another problem is that some programs, such as Lugaru Epsilon,
  21. ; substitute their own keyboard scan interrupt routines while they are
  22. ; active.  In order to easily patch such programs I have defined a special
  23. ; interrupt number, INT 3FH, which acts like an IN from the keyboard data
  24. ; port with the appropriate scan codes swapped.  (INT 3FH is the last
  25. ; "Reserved for DOS" interrupt.  DOS 3.10 doesn't use it, but that's no
  26. ; guarantee about future availability.)
  27.  
  28. ;    This version is set up for the IBM-PC/AT ROM BIOS as documented in the
  29. ; March 1984 edition of the Technical Reference for the IBM Personal Computer
  30. ; AT, keyboard BIOS module dated 01/04/84.  Warning!  Ignore the IBM PC/AT
  31. ; Technical Reference section "Key Scan Codes", starting on p. 4-10.  It's
  32. ; completely bogus.  Also, ignore the "break code prefix".  Instead, relay on
  33. ; the BIOS ROM listing (p. 5-28, p. 5-115 and on) in earlier editions of
  34. ; the Technical Reference (like the Aug 1981 edition).  The only new key on
  35. ; the AT, Sys Req, has scan code 84 (dec).
  36. ;
  37. ;    For a newer AT with a ROM BIOS which implements the "keyboard 
  38. ; intercept" feature, see the companion program SWAPKEY.
  39. ;
  40. ; swpkeyat.asm  5 Jul 88   Jim Van Zandt
  41. ;    Changed interrupt from 3FH to 3CH due to conflicts with QuickC
  42. ;    and QuickBasic.  QuickBasic programs use interrupts 3D, 3E, and
  43. ;    3F and don't restore them.  The code for KB_INT was also
  44. ;    changed to jump directly to SCAN_INT rather than using the
  45. ;    interrupt.  That way, it continues to work even within programs
  46. ;    that change the interrupt but fix it afterwards.
  47. ;
  48. ; swpkeyat.asm  10 Jul 85  Craig Milo Rogers at USC/ISI
  49. ;    Improved some of the comments.
  50. ; swpkeyat.asm  27 Jun 85  Craig Milo Rogers at USC/ISI
  51. ;    Created this program to swap the ESC key on the IBM-PC/AT with the
  52. ;    tilde/grave key.
  53.  
  54.     PAGE
  55.     SUBTTL    Declarations
  56.  
  57. KB_DATA        EQU    060H        ; Keyboard data port.
  58. BREAK_BIT    EQU    080H        ; Break-contact scan modifier.
  59. ESC_SCAN    EQU    001H        ; Scan code for the ESC key.
  60. TILDE_SCAN    EQU    029H        ; Scan code for tilde/grave key.
  61.  
  62. STATUS_PORT     EQU    064H        ; Keyboard status port.
  63. INPT_BUF_FULL    EQU    002H        ; Input-buffer-full bit.
  64. DIS_KBD        EQU    0ADH        ; Disable-keyboard command.
  65.  
  66. KB_INUM        EQU    009H        ; Keyboard hardware interrupt number.
  67.  
  68. SCAN_INUM    EQU    03CH        ; Keyboard scan request interrupt
  69.                     ; number.
  70.  
  71.  
  72. ;    The following two segments are used to interface this code to the
  73. ; ROM BIOS.
  74.  
  75. BIOSDATA SEGMENT AT 40H            ; BIOS data area in RAM.
  76.  
  77. BIOSDATA ENDS
  78.  
  79.  
  80. BIOSROM    SEGMENT    AT 0F000H        ; Known BIOS locations in ROM.
  81.  
  82.     ORG    03054H+0ABH-08CH    ; Place to reenter the keyboard
  83. KB_INT_1A LABEL FAR            ; hardware interrupt.
  84.  
  85. BIOSROM    ENDS                ; End of BIOS ROM segment.
  86.  
  87.  
  88.  
  89. CODESEG    SEGMENT                ; The code segment for this module.
  90.     ASSUME    CS:CODESEG        ; Always in CS.
  91.                     ; Configure for a .COM file:  start
  92.                     ; with the Program Segment Prefix.
  93.  
  94.     ORG    02CH            ; The PSP environment pointer.
  95. ENV_SEG    LABEL    WORD
  96.  
  97.     ORG    100H            ; Start of .COM execution.
  98. BEGIN:    JMP    INIT            ; Goto to code which initializes
  99.                     ; everything.
  100.  
  101.     PAGE
  102.     SUBTTL    KB_INT -- Keyboard Interrupt
  103.  
  104. ;    Control passes here when a message is ready from the keyboard.
  105.  
  106. KB_INT    PROC    FAR
  107.     STI                ; Enable interrupts.
  108.     PUSH    BP            ; Save the registers just like
  109.     PUSH    AX            ; the ROM.
  110.     PUSH    BX
  111.     PUSH    CX
  112.     PUSH    DX
  113.     PUSH    SI
  114.     PUSH    DI
  115.     PUSH    DS
  116.     PUSH    ES
  117.     CLD                ; Forward direction.
  118.  
  119.     MOV    AX,BIOSDATA        ; Establish pointer to BIOS data.
  120.     MOV    DS,AX
  121.  
  122.                     ; Disable the keyboard:
  123.     SUB    CX,CX            ; Clear counter for max cycles.
  124.     CLI                ;;; Disable interrupts.
  125. LOOP1:    IN    AL,STATUS_PORT        ;;; Read the keyboard status port.
  126.     TEST    AL,INPT_BUF_FULL    ;;; Is the command buffer still full?
  127.      LOOPNZ    LOOP1            ;;;   (yes, continue spinning)
  128.     MOV    AL,DIS_KBD        ;;; Get command to disable keyboard.
  129.     OUT    STATUS_PORT,AL        ;;; Send it out.
  130.     STI                ;;; Reenable interrupts.
  131.  
  132.     NOP                ; Window for interrupts.
  133.  
  134.                     ; Wait for the keyboard to pick up
  135.                     ; the command:
  136.     SUB    CX,CX            ; Clear counter for max cycles.
  137.     CLI                ;;; Disable interrupts.
  138. LOOP2:    IN    AL,STATUS_PORT        ;;; Read the keyboard status port.
  139.     TEST    AL,INPT_BUF_FULL    ;;; Is the command buffer still full?
  140.      LOOPNZ    LOOP2            ;;;   (yes, continue spinning)
  141.     STI                ;;; Reenable interrupts.
  142.  
  143. ;    INT    SCAN_INUM        ; Read the scan code.
  144.  
  145.     pushf
  146.     mov    ax,seg KB_INT_1A
  147.     push    ax
  148.     mov    ax,offset KB_INT_1A
  149.     push    ax
  150.     jmp    scan_int
  151.  
  152.  
  153. ;    JMP    KB_INT_1A        ; Go enter the mainline ROM code.
  154.  
  155. KB_INT    ENDP
  156.  
  157.     PAGE
  158.     SUBTTL    SCAN_INT -- Get a Keyboard Scan Code
  159.  
  160. SCAN_INT PROC    FAR            ; Get a keyboard scan code.
  161.     STI                ; Enable interrupts.
  162.  
  163.     IN    AL,KB_DATA        ; Pick up the waiting scan code.
  164.  
  165.     PUSH    AX            ; Save the full scan.
  166.     AND    AL,NOT BREAK_BIT    ; Eliminate the break bit.
  167.     CMP    AL,ESC_SCAN        ; Is this an ESC?
  168.      JE    SAW_ESC            ;   (yes)
  169.     CMP    AL,TILDE_SCAN        ; Is this a tilde?
  170.      JE    SAW_TILDE        ;   (yes)
  171.  
  172.     POP    AX            ; Restore the full code.
  173.     IRET                ; Return to caller.
  174.  
  175.  
  176. SAW_ESC:POP    AX            ; Restore the full scan code.
  177.     AND    AL,BREAK_BIT        ; Retain the break bit.
  178.     OR    AL,TILDE_SCAN        ; Remap into a tilde.
  179.     IRET                ; Return to the caller.
  180.  
  181. SAW_TILDE:
  182.     POP    AX            ; Restore the full scan code.
  183.     AND    AL,BREAK_BIT        ; Retain the break bit.
  184.     OR    AL,ESC_SCAN        ; Remap into an escape.
  185.     IRET                ; Return to the caller.
  186.  
  187. SCAN_INT ENDP
  188.  
  189.  
  190.     PAGE
  191.     SUBTTL    INIT -- Initialize and Exit-staying-resident
  192.  
  193. INIT    PROC    NEAR            ; Initialize and exit.
  194.     ASSUME    DS:CODESEG        ; Entered with CS and DS pointing to
  195.                     ; the Program Segment Prefix, which
  196.                     ; the first 100H locations of CODESEG.
  197.  
  198.                     ; Grab the keyboard hardware int.:
  199.     MOV    DX,OFFSET KB_INT    ; Address of int. routine in DS:DX.
  200.     MOV    AL,KB_INUM        ; Keyboard hardware interrupt.
  201.     MOV    AH,025H            ; Set interrupt vector function.
  202.     INT    21H            ; Call DOS to take over the interrupt.
  203.  
  204.                     ; Grab our special keyboard scan int.:
  205.     MOV    DX,OFFSET SCAN_INT    ; Address of int. routine in DS:DX.
  206.     MOV    AL,SCAN_INUM        ; Keyboard scan input request.
  207.     MOV    AH,025H            ; Set interrupt vector function.
  208.     INT    21H            ; Call DOS to take over the interrupt.
  209.  
  210.                     ; Return our environment block to
  211.                     ;   free storage:
  212.     MOV    AX,ENV_SEG        ; Get our environment block's segment.
  213.     MOV    ES,AX
  214.     MOV    AH,049H            ; Free allocated memory.
  215.     INT    21H            ; Call DOS.
  216.                     ; Ignore possible error return.
  217.  
  218.                     ; Terminate and stay resident.  Start
  219.                     ; By calculating how much memory to
  220.                     ; leave allocated to this program:
  221.     MOV    DX,OFFSET INIT        ; Don't need to retain init routine.
  222.     ADD    DX,0FH            ; Round up to a paragraph.
  223.     MOV    CL,4
  224.     SHR    DX,CL
  225.     MOV    AL,0            ; Successful return.
  226.     MOV    AH,031H            ; Terminate process & remain resident.
  227.     INT    21H            ; Call DOS.
  228.  
  229.     XOR    AH,AH            ; Emergency exit in case of DOS 1.
  230.     INT    21H
  231.  
  232. INIT    ENDP
  233.  
  234. CODESEG    ENDS
  235.  
  236.     END    BEGIN
  237.