home *** CD-ROM | disk | FTP | other *** search
- ;**************************************************************************
- ;* *
- ;* RBkeyswap v2.0 6/22/91 *
- ;* (c) Copyright 1989, 1991 Ralf Brown *
- ;* *
- ;* Permission is granted to redistribute unmodified copies in their *
- ;* entirety. Modified copies may be distributed provided that they *
- ;* are clearly marked as modified and the original unmodified source *
- ;* code is distributed together with the modification. *
- ;* *
- ;* ------------------------------------------------------------------ *
- ;* *
- ;* RBkeyswap is a program to fix the IBM's enhanced keyboard, which *
- ;* places the Escape, Control, and CapsLock keys in the wrong places. *
- ;* After running RBkeyswap, Escape and `/~ will be exchanged, as will *
- ;* the left control key and the CapsLock key. The right control key *
- ;* will be unaffected. *
- ;* *
- ;* RBkeyswap loads itself high (no need for LOADHI or LH) into either *
- ;* an XMS upper memory block or a DOS 5.0 UMB. If neither is avail- *
- ;* able, RBkeyswap will go resident in low memory, using just 128 *
- ;* bytes (it needs a mere 64 bytes in high memory). Note that it will *
- ;* use 272 bytes under DOS 2.x, because those versions force all TSRs *
- ;* to leave at least that much resident. *
- ;* *
- ;* You need a BIOS which provides the keyboard intercept on INT 15h. *
- ;* If your BIOS does not support this, RBkeyswap will merely use up *
- ;* memory without doing anything. *
- ;* *
- ;* Usage: RBKEYSWP *
- ;* Note: the program does not check whether it is already installed, *
- ;* so a second run will re-swap the keys, negating the action and *
- ;* using up a small amount of extra memory. *
- ;* *
- ;* ------------------------------------------------------------------ *
- ;* *
- ;* Rebuilding RBkeyswap: *
- ;* TASM RBKEYSWP *
- ;* TLINK /T RBKEYSWP *
- ;* *
- ;**************************************************************************
-
- code segment 'code'
- assume cs:code
-
- org 2Ch
- envseg dw ? ; segment address of our environment
-
- org 100h
- RBkeyswap:
- jmp init
-
- banner db 13,"RBkeyswap 2.0",9,"(c) Copyright 1989, 1991 Ralf Brown",13,10
- db "Swaps Esc/tilde and CapsLock/LeftCtrl",13,10,"$"
- db 26 ; stop output here if TYPEing the .COM file
-
- ;--------------------------------------------------------------------------
-
- int15_handler:
- jnc not_ours ; has a previous handler said to ignore scan code?
- cmp ah,4Fh ; scan code translation?
- jne not_ours ; if not, chain immediately
- cmp al,0E1h ; is it a special key such as "Pause"?
- je int15_setbranch
- cmp al,0E0h ; or a right-{alt,ctrl}?
- _branch: ; (if prev scan was E0h or E1h, we will
- BRANCH equ (_branch-int15_handler) ; branch unconditionally)
- je int15_setbranch ; the opcode here gets toggled between
- ; JE and JMP SHORT as needed
- shl al,1 ; move break bit into CF
- pushf ; and remember it for later
- cmp al,1Dh*2 ; ctrl?
- je ctrl_or_capslock
- cmp al,3Ah*2 ; capslock?
- je ctrl_or_capslock
- cmp al,01h*2 ; ESC?
- je esc_or_tilde
- cmp al,29h*2 ; backquote/tilde key?
- jne int15_no_xlat
- esc_or_tilde:
- xor al,0Fh*2 ; (AL xor 0F) xor 27 == (AL xor 28h)
- ; 01h -> 29h, 29h -> 01h
- ; thus esc and tilde swapped
- ctrl_or_capslock:
- xor al,27h*2 ; 1Dh -> 3Ah, 3Ah -> 1Dh
- ; thus left-ctrl and capslock swapped
- int15_no_xlat:
- popf ; retrieve break bit in CF
- rcr al,1 ; and add to translated scan code
- jmp short int15_done
-
- int15_setbranch:
- xor byte ptr cs:BRANCH,(74h xor 0EBh) ; toggle between JE and JMP
- int15_done:
- stc ; use the scan code
- not_ours:
- db 0EAh ; FAR JMP chain to previous handler
- old_int15 dd ?
-
- end_resident label byte
- code_size equ $ - int15_handler
- resident_code equ (code_size + 15)/16
-
- ;--------------------------------------------------------------------------
-
- xms_entry dd 0
- resident_seg dw 0 ; location of interrupt handler after relocation
- resident_size dw 0 ; number of paras to keep on going TSR
- alloc_strat dw 0
- link_state db 0 ; are UMBs part of memory chain?
- exit_func db 4Ch ; will change to 31h if we must go resident
-
- assume ds:code
- init:
- mov dx,offset banner
- mov ah,9
- int 21h ; identify ourself
- mov ax,3515h
- int 21h ; get old vector
- mov word ptr old_int15,bx ; and store in new interrupt handler
- mov word ptr old_int15 + 2,es
- ; first, see if we can load into an XMS upper memory block
- mov ax,352Fh
- int 21h ; find out whether INT 2F is valid
- mov ax,es
- or ax,bx ; don't try XMS if INT 2F is NULL
- jz no_XMS ; (could be case under DOS 2.x)
- mov ax,4300h ; see if XMS is installed
- int 2Fh
- cmp al,80h ; did XMS respond?
- jnz no_XMS
- mov ax,4310h ; if XMS present, get its entry point
- int 2Fh
- mov word ptr xms_entry,bx
- mov word ptr xms_entry+2,es ; and store entry point for call
- mov ah,10h ; request UMB
- mov dx,resident_code ; this is how much we need
- call xms_entry ; ask XMS for the memory
- cmp ax,1 ; did we get it?
- jne no_XMS ; if not, try DOS 5 UMB
- mov resident_seg,bx ; remember where we'll relocate
- jmp relocate_handler ; and go install
- ; if no XMS, try a DOS5 UMB
- no_XMS:
- mov ax,3000h ; get DOS version
- int 21h
- cmp al,5 ; DOS 5.0 or higher?
- jb not_dos5
- cmp al,10 ; but make sure not OS/2 penalty box
- jae not_dos5
- mov ax,5802h ; get UMB link state
- int 21h
- mov link_state,al ; and remember it for later restore
- mov ax,5803h ; set link state
- mov bx,1 ; UMBs are part of memory chain
- int 21h
- mov ax,5800h ; get allocation strategy
- int 21h
- mov alloc_strat,ax ; and remember it for later restore
- mov ax,5801h ; set allocation strategy
- mov bx,40h ; alloc high memory only
- int 21h
- mov ah,48h ; allocate memory
- mov bx,resident_code ; this is how much we need
- int 21h ; try to allocate the UMB
- pushf ; remember whether we succeeded
- jc no_highmem ; did we succeed?
- mov resident_seg,ax ; yes, so remember where to relocate
- dec ax ; address the MCB for our new memory
- mov es,ax ; block
- mov word ptr es:[1],0Ah ; make DOS owner of UMB, so it won't be
- mov word ptr es:[8],"CS" ; released when we exit (details below)
- ;---------------------------
- ; Reasons for mucking with the MCB:
- ; DOS 5 will release any memory blocks owned by the program when
- ; it exits without going TSR, even if the blocks are in high memory
- ; and high memory has been disconnected from the memory chain. So,
- ; we need to change the owner field such that DOS thinks it belongs to
- ; somebody else and doesn't release it when we exit. Both 08h and
- ; 0Ah are used by DOS itself, so we know they won't be messed with.
- ; However, the DOS 5 MEM program gets confused by 08h, because it
- ; thinks the block should have subblocks, which it doesn't. 0Ah is
- ; normally a locked-out portion of high memory, so there aren't any
- ; problems there. I put "SC" in the name field to make DOS think
- ; this is "system code".
- ;---------------------------
- no_highmem:
- mov ax,5801h
- mov bx,alloc_strat ; restore allocation strategy
- int 21h
- mov ax,5803h ; restore link state
- mov bh,0
- mov bl,link_state
- int 21h
- popf ; get back whether we were successful
- jnc relocate_handler ; if successful, go install
- ; as a last resort, use our own PSP to store the code, and go resident
- not_dos5:
- mov ax,cs
- add ax,4 ; copy to offset 40h in PSP
- mov resident_seg,ax
- mov exit_func,31h ; TSR rather than normal exit
- mov ah,49h ; since we will be going resident,
- mov es,envseg ; discard our environment
- int 21h
- mov envseg,0 ; and zero the ptr in the PSP
- mov resident_size,resident_code + 4
- relocate_handler:
- ; relocate interrupt handler into the PSP or UMB
- mov si,offset int15_handler
- mov es,resident_seg ; get back destination segment
- xor di,di
- mov cx,code_size ; number of bytes to copy
- cld
- rep movsb ; copy the interrupt handler
- ; install the new interrupt handler
- push ds
- mov ds,resident_seg
- ASSUME DS:NOTHING
- mov dx,0
- mov ax,2515h ; set INT 15h
- int 21h
- pop ds
- ASSUME DS:CODE
- ; finally, exit (going resident if necessary)
- mov dx,resident_size
- mov ah,exit_func ; 4Ch or 31h
- mov al,0
- int 21h
-
- code ends
- end RBkeyswap
-