Keyboard.pas

{$O-,V-}
UNIT KeyBoard;
 
(**) INTERFACE (**)
 
USES
  Dos;
 
TYPE
  String15 = String[15];
 
FUNCTION IsEnhanced : Boolean;
FUNCTION ReadKeyEnh : Word;
FUNCTION KeyPressedEnh : Boolean;
PROCEDURE ClearBuffer;
PROCEDURE StuffBuffer(S : String15);
FUNCTION FastKeyPressed : Boolean;
FUNCTION FasterKeyPressed : Boolean;
PROCEDURE DisableKeyboard;
PROCEDURE EnableKeyboard;
PROCEDURE MaskOutKbd;
PROCEDURE UnMaskKbd;
 
(**) IMPLEMENTATION (**)
 
CONST
  KbStart = $1E;
 
VAR
  ShiftState : Byte ABSOLUTE $40:$17;
  KbHead     : Word ABSOLUTE $40:$1A;
  KbTail     : Word ABSOLUTE $40:$1C;
  KbBuff     : ARRAY[0..15] OF Word ABSOLUTE $40:KbStart;
  OldKeyVec  : Pointer;
 
FUNCTION IsEnhanced : Boolean;
VAR StateFrom16 : Byte;
BEGIN
  IsEnhanced := FALSE;
  ASM
    MOV AH, 12h
    INT 16h
    MOV StateFrom16, AL
  END;
  IF StateFrom16 <> ShiftState THEN Exit;
  ShiftState := ShiftState XOR $20;
  ASM
    MOV AH, 12h
    INT 16h
    MOV StateFrom16, AL
  END;
  IsEnhanced := StateFrom16 = ShiftState;
  ShiftState := ShiftState XOR $20;
END;
 
FUNCTION ReadKeyEnh : Word; Assembler;
ASM
  MOV AH, 10h
  INT 16h
END;
 
FUNCTION KeyPressedEnh : Boolean; Assembler;
ASM
  MOV AH, 11h
  INT 16h
  MOV AX, 0
  JZ @NoKey
  INC AX
  @NoKey:
END;
 
PROCEDURE ClearBuffer;
BEGIN
  ASM CLI END;
  KbHead := KbStart;
  KbTail := KbStart;
  ASM STI END;
END;
 
FUNCTION FastKeyPressed : Boolean;
BEGIN
  FastKeyPressed := KbHead <> KbTail;
END;
 
FUNCTION FasterKeyPressed : Boolean; Assembler;
ASM
  PUSH DS
  MOV AX, 40h
  MOV DS, AX
  CLI
  MOV AX, [1Ah]
  CMP AX, [1Ch]
  STI
  MOV AX, 0
  JZ @NoPress
  INC AX
  @NoPress:
  POP DS
END;
 
PROCEDURE StuffBuffer(S : String15);
VAR
  N,
  max : Byte;
BEGIN
  max := 15;
  IF length(S) < max THEN max := length(S);
  ASM CLI END;
  KbHead := KbStart;
  KbTail := KbStart + 2*max;
  FOR N := 1 to max DO KbBuff[pred(N)] := Word(S[N]);
  ASM
    STI
  END;
END;
 
PROCEDURE MaskOutKbd; Assembler;
ASM
  IN AL, 21h
  OR AL, 00000010b
  OUT 21h, AL
END;
 
PROCEDURE UnMaskKbd; Assembler;
ASM
  IN AL, 21h
  AND AL,11111101b
  OUT 21h, AL
END;
 
PROCEDURE EatAllKeys; Assembler;
ASM
  PUSH AX      {sauvegarde AX, car on va l'employer}
  PUSHF        {sauvegarde des drapeaux}
  IN AL,60h    {lecture du port clavier}
  IN AL,61h    {lecture du contrôleur clavier}
  MOV AH,AL
  OR AL,80h    {positionne le bit de "reset"}
  OUT 61h,AL   {protŠge la valeur}
  XCHG AH,AL   {reprend la valeur originale}
  OUT 61h,AL   {et la protŠge également}
  POPF
  CLI          {pas d'interruptions pour l'instant}
  MOV AL,20h   {End-Of-Interrupt signal}
  OUT 20h,AL   {envoi de EOI dans PIC}
  POP AX
  IRET
END;
 
PROCEDURE DisableKeyboard;
BEGIN
  GetIntVec(9, OldKeyVec);
  SetIntVec(9, @EatAllKeys);
END;
 
PROCEDURE EnableKeyboard;
BEGIN
  SetIntVec(9, OldKeyVec);
END;
 
BEGIN
  {$IFOPT O+}
  CRASH HERE -- on ne doit pas employer la directive O+
  {$ENDIF}
  IF NOT IsEnhanced THEN
    BEGIN
      MEM[CSeg : Ofs(ReadKeyEnh)+1] := $00;
      MEM[CSeg : Ofs(KeyPressedEnh)+1] := $01;
    END;
END.