; ; keys.asm ; ; translate +- keys to keypad +- keys ; ; David lindauer, August 28,1995 ; .386 LEFTSHIFT = 02Ah RIGHTSHIFT = 036h KEYMINUS = 0ch KEYEQUAL = 0dh KEYPADMINUS = 4ah KEYPADPLUS = 4EH TSRHOOK = 082h TSRLOADED = 5 TSRUNLOAD = 6 absseg segment word use16 at 0 org 02ch env dw ? ; ENV is in PSP org 6ch timer dd ? ; TiMER is in bios data seg 40h org 015h*4 int15h dd ? ; Ints are in seg 0 org 80h*4 int80h dd ? absseg ends cseg segment word use16 'CODE' assume cs:cseg org 100h assume ds:nothing, es:nothing begin: jmp start ; Program start shift db 0 ; Tick counter. Update time every ; 18 ticks old15 dd 0 ; Old int 15 old80 dd 0 ; old int 80 handler15 PROC pushf cmp ah,4fh jnz chain cmp al,LEFTSHIFT JZ SHIFTON cmp al,RIGHTSHIFT jz SHIFTON cmp al, LEFTSHIFT + 80h jz SHIFTOFF cmp al, RIGHTSHIFT + 80h jz shiftoff cmp al,KEYEQUAL jz chgequal cmp al,KEYEQUAL + 80h jz chgbrequal cmp al,KEYMINUS jz chgminus cmp al,KEYMINUS + 80h jnz chain mov al,KEYPADMINUS + 80h jmp chain chgminus: mov al,KEYPADMINUS jmp chain chgbrequal: mov al,KEYPADPLUS + 80h jmp chain chgequal: mov al,KEYPADPLUS jmp chain shifton: mov [shift],1 jmp chain shiftoff: mov [shift],0 chain: popf jmp [old15] handler15 endp ; ; Hook handler ; handler80 proc pushf ; See if valid request cmp ah,TSRHOOK ; jz short hooked ; Yep, get it followint: push ax ; Else see if was an old handler mov ax,word ptr [old80] ; or ax,word ptr [old80+2] ; pop ax ; jz short noold ; return if not popf ; Else go to next handler jmp [old80] ; noold: popf iret hooked: cmp al,TSRLOADED ; See if is load test jnz short checkunload ; Nope, look for unload popf ; mov al,0ffh ; Return loaded status iret checkunload: cmp al,TSRUNLOAD ; See if is unload jnz short followint ; Nope, follow interrupt chain popf mov bx,80h ; Reset int vectors to original state mov si,offset old80 ; call unloadint ; mov bx,15h ; mov si,offset old15 ; call unloadint ; push cs pop es mov es,es:[env] ; Free environment mov ah,49h ; int 21h ; push cs pop es mov ah,49h ; Free prog seg int 21h ; sub ax,ax ; iret handler80 endp ; ; Routine to unload ints ; unloadint proc shl bx,2 ; Get int address push 0 ; pop es ; ES = 0 mov ax,cs:[si] ; Move lo word mov es:[bx],ax ; mov ax,cs:[si+2] ; mov es:[bx+2],ax ; ret unloadint endp endtsr label BYTE ; ; End of TSR. Init routines come next ; loadmsg db "Loading +- changer",10,13,'$' unloadmsg db "Unloading +- changer",10,13,'$' ; ; Routine to load an interrupt ; loadint proc shl bx,2 ; Get int address push 0 ; ES = 0 pop es mov di,es:[bx] ; Get old int mov cs:[si],di mov di,es:[bx+2] mov cs:[si+2],di cli mov es:[bx],ax ; Save new int mov es:[bx+2],cs ; sti ret loadint endp ; ; Main program ; start proc assume ds:cseg, es:absseg push 0 ; Check for int 80h pop es ; mov ax,word ptr [int80h] ; or ax,word ptr [int80h + 2]; jz short notloaded ; Not there, let's go load mov ah,TSRHOOK ; See if TSR is hooked mov al,TSRLOADED ; int 80h ; cmp al,0ffh ; jnz short notloaded ; Nope, go load mov dx,offset unloadmsg ; Unnloading mov ah,9 ; int 21h ; mov ah,TSRHOOK ; Tell TSR to unload mov al,TSRUNLOAD ; int 80h ; mov ah,4ch ; Get out int 21h notloaded: mov dx,offset loadmsg ; Loading mov ah,9 ; int 21h ; mov si,offset old80 ; Set int80h mov ax,offset handler80 mov bx,80h call loadint mov si,offset old15 ; Set int 15h mov ax,offset handler15 ; mov bx,15h ; call loadint ; mov dx,offset endtsr ; Set up keep space & exit add dx,15 ; shr dx,4 ; mov ah,31h ; int 21h ; start endp cseg ends end begin