;---------------------------------------------------------- ; Key128, Keyboard buffer enhancer - Tenie Remmel ;---------------------------------------------------------- Ideal ESIZE = 128 ;Buffer size (can be changed) KEY_HEAD = 01Ah ;BIOS key info positions KEY_TAIL = 01Ch KEY_BUF = 01Eh KEY_END = 03Eh Model Tiny P186 CodeSeg Org 100h Start: jmp Main ;**************************** Resident data EBuf dw ESIZE dup (?) ;Extended buffer EOut dw EBuf ;Keys go out here EIn dw EBuf ;Keys go in here EFree dw ESIZE ;Number of keys free TBusy db 0 ;Transfer proc. 'Busy' flag ;**************************** NewInt9 -- New INT9 (key-press) proc. Proc NewInt9 call TransferKeys ;Transfer keys sti ;Set interrupt flag pushf ;Simulated interrupt call cli ;to old BIOS INT9 handler db 09Ah ;CALL FAR opcode OldInt9 dw 0,0 ;Old INT9 address cli ;Clear interrupt flag call TransferKeys ;Transfer keys iret ;Interrupt return EndP NewInt9 ;**************************** NewInt16 -- New INT16 (BIOS key func) proc. Proc NewInt16 call TransferKeys ;Transfer keys sti ;Set interrupt flag cld ;Clear direction flag push ax ;Save AX and ah,0EFh ;If it's a Get Key/Status (0/1/10/11), cmp ah,1 ;then jump ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ pop ax ;Restore AX ³ jbe i16_Main ;Jump to main handler <ÄÄÄÙ cli ;Finish with old handler db 0EAh ;JMP FAR opcode OldInt16 dw 0,0 ;Old INT16 address ;****************** INT16 Main Handler i16_Main: push bx cx si ds es ;Save registers push cs ;DS = CS pop ds mov bx,ax ;BX = function code i16_Key: mov si,[EOut] ;SI = key read pointer mov cx,ESIZE ;CX = key count sub cx,[EFree] jz $+3 ;Skip if no keys lodsw ;Load a key cmp al,0E0h ;Jump if it's not jne i16_Func ;an extended key code test bh,10h ;Jump if ext. function jnz i16_Func sub al,al ;Make it an ordinary key i16_Func: test bh,1 ;Jump if it's a 'Get Key' function jz i16_GetKey ;which is INT 16/0 or 16/10... test cx,cx ;otherwise just return status ;and possibly the key code. i16_Exit: pop es ds si cx bx ;Restore registers retf 2 ;Simulated IRET i16_GetKey: test cx,cx ;If the buffer isn't empty, jnz i16_GotKey ;then return the key code. i16_Wait: call TransferKeys ;Transfer keys cmp [EFree],ESIZE ;Loop if empty je i16_Wait jmp i16_Key ;Get key, and return i16_GotKey: inc [EFree] ;One more key free cmp si,offset EOut ;Check for wrap jb $+5 ;Jump if no wrap mov si,offset EBuf mov [EOut],si ;Set new buffer position jmp i16_Exit ;Return from interrupt EndP NewInt16 ;**************************** TransferKeys -- Put keys into buffer Proc TransferKeys cmp [byte cs:TBusy],0 ;Exit if it's busy jne tk_ret inc [byte cs:TBusy] ;Set busy flag sti ;Set interrupt flag cld ;Clear direction flag pusha ;Save registers push ds es push cs 40h ;DS = 40h, ES = CS pop ds es mov si,[KEY_HEAD] ;SI = key read pointer mov cx,[KEY_TAIL] ;CX = key end pointer mov di,[cs:EIn] ;DI = key write pointer mov bx,[cs:EFree] ;BX = key free count test bx,bx ;No keys free? tk_Loop: jz tk_Exit ;Then exit... cmp si,cx ;No keys to transfer? jnz tk_DoKey tk_Exit: mov [cs:EIn],di ;Save key write pointer mov [cs:EFree],bx ;Save key free count mov [KEY_HEAD],si ;Save BIOS buffer head pop es ds ;Restore registers popa cli ;Clear interrupt flag dec [byte cs:TBusy] ;Turn off busy flag tk_ret: ret ;Return tk_DoKey: lodsw ;Load key cmp al,0F0h ;Change key code jne tk_KeyOK ;to key code , test ah,ah ;except if it's <00,F0>. jz tk_KeyOK sub al,al ;Zero ASCII value tk_KeyOK: cmp si,KEY_END ;Check for wrap on SI jb $+5 ;Jump if no wrap mov si,KEY_BUF stosw ;Store key cmp di,offset EOut ;Check for wrap on DI jb $+5 ;Jump if no wrap mov di,offset EBuf dec bx ;Decrease keys free jmp tk_Loop ;Loop back EndP TransferKeys ;/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/ Transient Section ;**************************** Transient data Header db 'Key128 v1.13 Key Buffer Enhancer',13,10,10,'$' Uninstalled db 'Un' Installed db 'Installed Successfully',13,10,'$' Syntax db 'Syntax: KEY128 [/U]',13,10,'$' NoMemory db 'Out of memory',13,10,'$' AlreadyIn db 'Already installed',13,10,'$' NotFound db 'Resident copy not found',13,10,'$' CantUnload db 'Can''t uninstall',13,10,'$' ResName db 'Key128 ' ResSeg dw 0 ;**************************** Main -- Main procedure Proc Main mov ah,9 ;Print "Key128 v1.13..." string mov dx,offset Header int 21h call FindRes ;Find resident copy mov al,'/' ;Search for slash xor cx,cx ;in command line mov cl,[byte 80h] mov di,81h repne scasb jne NoUnload ;No slash, don't unload mov dx,offset Syntax ;DX = 'Syntax:' string cmp [byte di],'U' ;/U or /u, unload je Unload cmp [byte di],'u' je Unload cmp [byte di],'?' ;/?, print syntax je Error NoUnload: mov dx,offset AlreadyIn ;Point DX to error string cmp [ResSeg],0 ;Already installed? jne Error cld ;Clear direction flag mov ax,offset LastByte ;AX = last byte + 256 inc ah cmp ax,sp ;Check for too little memory jbe MemOK mov dx,offset NoMemory ;Print 'Out of memory' string Error: mov ah,9 int 21h mov ax,4C01h ;Exit with error int 21h MemOK: mov sp,ax ;Shrink stack jmp Load ;Jump to Load procedure EndP Main ;**************************** Load -- TSR loader procedure Proc Load mov ah,49h ;Free environment segment mov es,[2Ch] int 21h mov ax,3509h ;Get and store old INT9 address int 21h mov [OldInt9],bx mov [OldInt9+2],es mov al,16h ;Get and store old INT16 address int 21h mov [OldInt16],bx mov [OldInt16+2],es mov ax,2509h ;Set new INT16 handler mov dx,offset NewInt9 int 21h mov al,16h ;Set new INT9 handler mov dx,offset NewInt16 int 21h mov ax,cs ;ES = MCB segment (CS - 1) dec ax mov es,ax mov si,offset ResName ;Change resident name mov di,8 mov cx,di rep movsb mov ah,9 ;Print 'Installed' string mov dx,offset Installed int 21h mov dx,offset Header-1 ;Last byte of program LastByte: int 27h ;DOS TSR service EndP Load ;**************************** Unload -- Uninstall procedure Proc Unload mov cx,[ResSeg] ;CX = resident segment mov dx,offset NotFound ;Point DX to error string test cx,cx ;Make sure it's in memory je Error mov dx,offset CantUnload ;Point DX to error string mov ax,3509h ;Check to make sure that the int 21h ;interrupts still point to cmp bx,offset NewInt9 ;the resident copy... jne Error mov al,16h int 21h cmp bx,offset NewInt16 jne Error mov es,[ResSeg] ;ES = resident segment mov ax,2509h ;Reset INT9 vector mov dx,[es:OldInt9] mov ds,[es:OldInt9+2] int 21h mov al,16h ;Reset INT9 vector mov dx,[es:OldInt16] mov ds,[es:OldInt16+2] int 21h mov ah,49h ;Release memory segment int 21h push cs ;DS = CS pop ds mov [byte Installed],'i';Fix 'Uninstalled' string mov ah,9 ;Print 'Uninstalled' string mov dx,offset Uninstalled int 21h mov ax,4C00h ;Quit program int 21h EndP Unload ;**************************** FindRes -- Find resident copy Proc FindRes pusha ;Save registers push es mov ax,5802h ;Save UMB link status int 21h push ax mov ax,5803h ;Link UMBs mov bx,1 int 21h mov ah,52h ;Get Internal Config Table int 21h sub bx,2 ;BX = first MCB mov bx,[es:bx] fr_Loop: mov es,bx ;ES = MCB segment cmp [word es:9],7965h ;Check for signature je fr_Found add bx,[es:3] ;Step to next one inc bx cmp [byte es:0],'Z' ;Last one in chain? jne fr_Loop ;Loop back mov bx,-1 ;Return 0 (-1 + 1 = 0) fr_Found: inc bx mov [ResSeg],bx ;Return resident segment mov ax,5803h ;Restore UMB link status pop bx int 21h pop es ;Restore registers popa ret ;Return EndP FindRes End Start