home *** CD-ROM | disk | FTP | other *** search
/ Simtel MSDOS - Coast to Coast / simteldosarchivecoasttocoast.iso / keyboard / swpkeyat.asm < prev    next >
Assembly Source File  |  1994-03-04  |  7KB  |  219 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.  
  38. ; swpkeyat.asm  10 Jul 85  Craig Milo Rogers at USC/ISI
  39. ;    Improved some of the comments.
  40. ; swpkeyat.asm  27 Jun 85  Craig Milo Rogers at USC/ISI
  41. ;    Created this program to swap the ESC key on the IBM-PC/AT with the
  42. ; tilde/grave key.
  43.  
  44.     PAGE
  45.     SUBTTL    Declarations
  46.  
  47. KB_DATA        EQU    060H        ; Keyboard data port.
  48. BREAK_BIT    EQU        080H    ; Break-contact scan modifier.
  49. ESC_SCAN    EQU        001H    ; Scan code for the ESC key.
  50. TILDE_SCAN    EQU        029H    ; Scan code for tilde/grave key.
  51.  
  52. STATUS_PORT     EQU    064H        ; Keyboard status port.
  53. INPT_BUF_FULL    EQU        002H    ; Input-buffer-full bit.
  54. DIS_KBD        EQU        0ADH    ; Disable-keyboard command.
  55.  
  56. KB_INUM        EQU    009H        ; Keyboard hardware interrupt number.
  57.  
  58. SCAN_INUM    EQU    03FH        ; Keyboard scan request interrupt
  59.                     ; number.
  60.  
  61.  
  62. ;    The following two segments are used to interface this code to the
  63. ; ROM BIOS.
  64.  
  65. BIOSDATA SEGMENT AT 40H            ; BIOS data area in RAM.
  66.  
  67. BIOSDATA ENDS
  68.  
  69.  
  70. BIOSROM    SEGMENT    AT 0F000H        ; Known BIOS locations in ROM.
  71.  
  72.     ORG    03054H+0ABH-08CH    ; Place to reenter the keyboard
  73. KB_INT_1A LABEL FAR            ; hardware interrupt.
  74.  
  75. BIOSROM    ENDS                ; End of BIOS ROM segment.
  76.  
  77.  
  78.  
  79. CODESEG    SEGMENT                ; The code segment for this module.
  80.     ASSUME    CS:CODESEG        ; Always in CS.
  81.                     ; Configure for a .COM file:  start
  82.                     ; with the Program Segment Prefix.
  83.  
  84.     ORG    02CH            ; The PSP environment pointer.
  85. ENV_SEG    LABEL    WORD
  86.  
  87.     ORG    100H            ; Start of .COM execution.
  88. BEGIN:    JMP    INIT            ; Goto to code which initializes
  89.                     ; everything.
  90.  
  91.     PAGE
  92.     SUBTTL    KB_INT -- Keyboard Interrupt
  93.  
  94. ;    Control passes here when a message is ready from the keyboard.
  95.  
  96. KB_INT    PROC    FAR
  97.     STI                ; Enable interrupts.
  98.     PUSH    BP            ; Save the registers just like
  99.     PUSH    AX            ; the ROM.
  100.     PUSH    BX
  101.     PUSH    CX
  102.     PUSH    DX
  103.     PUSH    SI
  104.     PUSH    DI
  105.     PUSH    DS
  106.     PUSH    ES
  107.     CLD                ; Forward direction.
  108.  
  109.     MOV    AX,BIOSDATA        ; Establish pointer to BIOS data.
  110.     MOV    DS,AX
  111.  
  112.                     ; Disable the keyboard:
  113.     SUB    CX,CX            ; Clear counter for max cycles.
  114.     CLI                ;;; Disable interrupts.
  115. LOOP1:    IN    AL,STATUS_PORT        ;;; Read the keyboard status port.
  116.     TEST    AL,INPT_BUF_FULL    ;;; Is the command buffer still full?
  117.      LOOPNZ    LOOP1            ;;;   (yes, continue spinning)
  118.     MOV    AL,DIS_KBD        ;;; Get command to disable keyboard.
  119.     OUT    STATUS_PORT,AL        ;;; Send it out.
  120.     STI                ;;; Reenable interrupts.
  121.  
  122.     NOP                ; Window for interrupts.
  123.  
  124.                     ; Wait for the keyboard to pick up
  125.                     ; the command:
  126.     SUB    CX,CX            ; Clear counter for max cycles.
  127.     CLI                ;;; Disable interrupts.
  128. LOOP2:    IN    AL,STATUS_PORT        ;;; Read the keyboard status port.
  129.     TEST    AL,INPT_BUF_FULL    ;;; Is the command buffer still full?
  130.      LOOPNZ    LOOP2            ;;;   (yes, continue spinning)
  131.     STI                ;;; Reenable interrupts.
  132.  
  133.     INT    SCAN_INUM        ; Read the scan code.
  134.  
  135.     JMP    KB_INT_1A        ; Go enter the mainline ROM code.
  136.  
  137. KB_INT    ENDP
  138.  
  139.     PAGE
  140.     SUBTTL    SCAN_INT -- Get a Keyboard Scan Code
  141.  
  142. SCAN_INT PROC    FAR            ; Get a keyboard scan code.
  143.     STI                ; Enable interrupts.
  144.  
  145.     IN    AL,KB_DATA        ; Pick up the waiting scan code.
  146.  
  147.     PUSH    AX            ; Save the full scan.
  148.     AND    AL,NOT BREAK_BIT    ; Eliminate the break bit.
  149.     CMP    AL,ESC_SCAN        ; Is this an ESC?
  150.      JE    SAW_ESC            ;   (yes)
  151.     CMP    AL,TILDE_SCAN        ; Is this a tilde?
  152.      JE    SAW_TILDE        ;   (yes)
  153.  
  154.     POP    AX            ; Restore the full code.
  155.     IRET                ; Return to caller.
  156.  
  157.  
  158. SAW_ESC:POP    AX            ; Restore the full scan code.
  159.     AND    AL,BREAK_BIT        ; Retain the break bit.
  160.     OR    AL,TILDE_SCAN        ; Remap into a tilde.
  161.     IRET                ; Return to the caller.
  162.  
  163. SAW_TILDE:
  164.     POP    AX            ; Restore the full scan code.
  165.     AND    AL,BREAK_BIT        ; Retain the break bit.
  166.     OR    AL,ESC_SCAN        ; Remap into an escape.
  167.     IRET                ; Return to the caller.
  168.  
  169. SCAN_INT ENDP
  170.  
  171.  
  172.     PAGE
  173.     SUBTTL    INIT -- Initialize and Exit-staying-resident
  174.  
  175. INIT    PROC    NEAR            ; Initialize and exit.
  176.     ASSUME    DS:CODESEG        ; Entered with CS and DS pointing to
  177.                     ; the Program Segment Prefix, which
  178.                     ; the first 100H locations of CODESEG.
  179.  
  180.                     ; Grab the keyboard hardware int.:
  181.     MOV    DX,OFFSET KB_INT    ; Address of int. routine in DS:DX.
  182.     MOV    AL,KB_INUM        ; Keyboard hardware interrupt.
  183.     MOV    AH,025H            ; Set interrupt vector function.
  184.     INT    21H            ; Call DOS to take over the interrupt.
  185.  
  186.                     ; Grab our special keyboard scan int.:
  187.     MOV    DX,OFFSET SCAN_INT    ; Address of int. routine in DS:DX.
  188.     MOV    AL,SCAN_INUM        ; Keyboard scan input request.
  189.     MOV    AH,025H            ; Set interrupt vector function.
  190.     INT    21H            ; Call DOS to take over the interrupt.
  191.  
  192.                     ; Return our environment block to
  193.                     ;   free storage:
  194.     MOV    AX,ENV_SEG        ; Get our environment block's segment.
  195.     MOV    ES,AX
  196.     MOV    AH,049H            ; Free allocated memory.
  197.     INT    21H            ; Call DOS.
  198.                     ; Ignore possible error return.
  199.  
  200.                     ; Terminate and stay resident.  Start
  201.                     ; By calculating how much memory to
  202.                     ; leave allocated to this program:
  203.     MOV    DX,OFFSET INIT        ; Don't need to retain init routine.
  204.     ADD    DX,0FH            ; Round up to a paragraph.
  205.     MOV    CL,4
  206.     SHR    DX,CL
  207.     MOV    AL,0            ; Successful return.
  208.     MOV    AH,031H            ; Terminate process & remain resident.
  209.     INT    21H            ; Call DOS.
  210.  
  211.     XOR    AH,AH            ; Emergency exit in case of DOS 1.
  212.     INT    21H
  213.  
  214. INIT    ENDP
  215.  
  216. CODESEG    ENDS
  217.  
  218.     END    BEGIN
  219.