.386P
.model flat

        public NewKeyb_,OldKeyb_
        public KillKeyb_,RaiseKeyb_
        public IsKey_,WasKey_,RelKey_
        public InitKey_,ClearKey_,ClearWasKey_
        public KeyPressed_

.data
    Key             db  256 dup(0)      ; Keyboard buffer 
    KeyboardInst    db  0               ; Keyboard ISR Installed Flag
    ISR_OldS        dw  ?               ; Old Vector Segment
    ISR_OldO        dd  ?               ; Old Vector Offset
    e0Flag          db  0               ; flag a-la-con !!!

    .code

Keyboard_PM PROC
       push ax
       push bx
       pushfd                           ; sauve les EFlags
        cli
        in   al, 60h                    ; get scan code from keyboard port }
        cmp  al, 0E0h                   ; al = $E0 key ? }
        jne  @@SetScanCode                 
        mov  [e0Flag], 128
        jmp  @exit
@@SetScanCode:
        mov  bl, al                     ; Save scancode in BL }
        and  bl, 01111111b
        add  bl, [e0Flag]
        xor  bh, bh
        test al,10000000b
        jnz  @KBIReleased                
        mov al,[offset Key + bx]
        or   al,00000011b                ; was pressed (!!) & pressed
        mov [offset Key + bx],al
        mov  [e0Flag], 0                 ; reinit e0Flag
        jmp  @exit                       ; bye!

@KBIReleased:
        mov al,[offset Key + bx]
        and  al,00000010b                ; was pressed but !pressed
        or   al,00000100b
        mov [offset Key + bx],al
        mov  [e0Flag], 0
@exit:
        mov  al, 20h                    ; send EOI to PIC }
        out  20h, al
        sti
       popfd                    ; restaure les EFlags
       pop  bx
       pop  ax
        iretd                           ; Let's get the freak outa here.
Keyboard_PM     ENDP


NewKeyb_  PROC
        cmp  KeyboardInst,0
        jz   @NotInstalled
	ret

@NotInstalled:
        mov  KeyboardInst,1

	;; *********************************************
        ;; Get OLD INT 09h Vectors
	;; *********************************************
        mov  ax,0204h                   ; get PM vector
        mov  bl,09h
        int  31h
        mov  ISR_OldO,edx               ; save it . . .
        mov  ISR_OldS,cx        

	;; *********************************************
	;; Set NEW INT 09h Vector
	;; *********************************************
        mov  ax,0205h
        mov  bl,09h
        mov  cx,cs
        mov  edx,offset Keyboard_PM
        int   31h  

        ret                            ; Return to caller
NewKeyb_   ENDP



OldKeyb_ PROC   
        cmp  KeyboardInst,1
        jz   @AlReadyInstalled
	ret

@AlReadyInstalled:
        mov  KeyboardInst,0
        
        ;; *********************************************
        ;; Restore OLD INT 09h Vector
	;; *********************************************
        mov  ax,0205h
        mov  bl,09h
        mov  cx, ISR_OldS         
        mov  edx,ISR_OldO               ; to original Keyboard Interrupt
        int  31h          
        ret                             ; Return to caller
OldKeyb_  ENDP

IsKey_ PROC
        mov  bx,ax
        mov  al,[offset Key + bx]
        test al,00000001b
        jnz @IsKeyb
        xor eax,eax
        ret
@IsKeyb:
        mov eax,1
        ret
IsKey_ endp

WasKey_ PROC
        mov  bx,ax
        mov  al,[offset Key + bx]
        test al,00000010b
        jnz @WasKeyb
        xor eax,eax
        ret
@WasKeyb:
        and  al,11111101b
        mov  [offset Key + bx],al
        mov eax,1
        ret
WasKey_ endp

RelKey_ PROC
        mov  bx,ax
        mov  al,[offset Key + bx]
        test al,00000100b
        jnz @RelKeyb
        xor eax,eax
        ret
@RelKeyb:
        and  al,11111011b
        mov  [offset Key + bx],al
        mov eax,1
        ret
RelKey_ endp

InitKey_ proc
        mov cl,64
        xor bx,bx
        xor eax,eax
@OBC01:
        mov  [offset Key + bx],eax
        add bx,4
        dec cl
        jnz @OBC01
        ret
InitKey_ endp

ClearKey_ proc
        mov bx,ax
        xor eax,eax
        mov  [offset Key + bx],al
        ret
ClearKey_ endp

ClearWasKey_ proc
        mov bx,ax
        mov al,[offset Key + bx]
        and  al,11111101b
        mov [offset Key + bx],al
        ret
ClearWasKey_ endp

KillKeyb_ proc
        in al,21h
        or al,00000010b
        out 21h,al
        ret
KillKeyb_ endp

RaiseKeyb_ proc
        in al,21h
        and al,11111101b
        out 21h,al
        ret
RaiseKeyb_ endp

KeyPressed_ PROC
        mov  bx,255
@TstKey:
        mov  al,[offset Key + bx]
        test al,00000001b
        jnz @Keybpressed
        dec bx
        jnz @TstKey
        xor eax,eax
        ret
@Keybpressed:
        mov eax,1
        ret
KeyPressed_ endp


end

; 0 = Faux; Le reste = Vrai;
