UNIT KeyIntr ; { support for INT 09 16 routines } { Turbo Pascal 5.5+ } INTERFACE Type InterruptProcedure = Procedure ; Const BiosDataSegment = $40 ; Procedure DisableInterrupts ; Inline( $FA ) ; { CLI } Procedure EnableInterrupts ; Inline( $FB ) ; { STI } Procedure CallInterrupt( P : Pointer ) ; Function AltPressed : Boolean ; Function ControlPressed : Boolean ; Function ShiftPressed : Boolean ; Procedure EOI ; { end of interrupt to 8259 } Function ReadScanCode : Byte ; { read keyboard } Procedure ResetKeyboard ; { prepare for next key } { put key in buffer for INT 16 } Function StoreKey( Scan, Key : Byte ) : Boolean ; IMPLEMENTATION Type TwoBytesPtr = ^TwoBytes ; TwoBytes = { one key in the keyboard buffer } Record KeyCode, ScanCode : Byte ; End ; Var KeyState : Word Absolute BiosDataSegment:$17 ; KeyBufferHead : Word Absolute BiosDataSegment:$1A ; KeyBufferTail : Word Absolute BiosDataSegment:$1C ; KeyBufferStart : Word Absolute BiosDataSegment:$80 ; KeyBufferEnd : Word Absolute BiosDataSegment:$82 ; Procedure CallInterrupt( P : Pointer ) ; Begin Inline( $9C ) ; { PUSHF } InterruptProcedure(P) ; End ; Function AltPressed : Boolean ; Begin AltPressed := (KeyState and 8) <> 0 ; End ; Function ControlPressed : Boolean ; Begin ControlPressed := (KeyState and 4) <> 0 ; End ; Function ShiftPressed : Boolean ; Begin ShiftPressed := (KeyState and 3) <> 0 ; End ; Procedure EOI ; { end of interrupt to 8259 interrupt controller } Begin Port[$20] := $20 ; End ; Function ReadScanCode : Byte ; Var N : Byte ; Begin N := Port[$60] ; { $FF means keyboard overrun } ReadScanCode := N ; End ; Procedure ResetKeyboard ; { prepare for next key } Var N : Byte ; Begin N := Port[$61] ; Port[$61] := (N or $80) ; Port[$61] := N ; End ; Function StoreKey( Scan, Key : Byte ) : Boolean ; Var { put key in buffer that INT 16 reads } P : TwoBytesPtr ; N : Word ; Begin DisableInterrupts ; N := KeyBufferTail ; P := Ptr( BiosDataSegment, N ) ; Inc( N, 2 ) ; If( N = KeyBufferEnd ) then { end of the circular buffer } N := KeyBufferStart ; If( N = KeyBufferHead ) then { buffer full } Begin EnableInterrupts ; StoreKey := False ; End Else Begin P^.KeyCode := Key ; P^.ScanCode := Scan ; { store key in circular buffer } KeyBufferTail := N ; { advance tail pointer } EnableInterrupts ; StoreKey := True ; End ; End ; END.