[Back to KEYBOARD SWAG index]  [Back to Main SWAG index]  [Original]

{
>     I need help on reading the keyboard in a specific way, I need to
> read it as a whole not a key at a time. I need to do this for
> the games I make, I have to ba able to hold down one key to
> perform a Function and then hold down another key and scan both
> keys at the same time but to perform 2 different Functions. For
> instance, if I hold down the left arrow key to make a Character
> run I should be able to hold down the space bar to make him
> fire a gun at the same time.
>     I would Really appreciate any help anyone could give me With this.

Grab this (TWOKEYS.PAS) and the next 2 messages (KEYINTR.PAS and POLL.PAS).
}

Program TwoKeys;

Uses
  Crt, Poll ;  { polled keyboard handler }

{ ----- this Program will probably hang a debugger ----- }

Var
  X, Y : Byte ;

begin
  ClrScr ;
  X := 40 ;
  Y := 12 ;

  WriteLn( 'Hit keys A S  and  1 2 on the keypad' ) ;
  WriteLn( ' -- Esc to stop' ) ;

  While not KeyTable[ EscKey ] do
  begin
    GotoXY( X, Y ) ;
    Write( ' ' ) ;

    { poll the KeyTable }
    If KeyTable[ endKey ] and ( X > 1 ) then  Dec( X ) ;
    If KeyTable[ DownKey ] and ( X < 80 ) then  Inc( X ) ;
    If KeyTable[ aKey ] and ( Y > 4 ) then  Dec( Y ) ;
    If KeyTable[ sKey ] and ( Y < 24 ) then  Inc( Y ) ;

    GotoXY( X, Y ) ;
    Write( chr( 1 ) ) ;
    Delay( 10 ) ;
  end ;
end.




Unit KeyIntr ;  { support For INT 09 routines }

Interface

Procedure CLI ; Inline( $FA ) ; { disable interrupts }
Procedure STI ; Inline( $FB ) ; { enable interrupts }

{ cannot be used outside an interrupt Procedure }
Procedure JumpInterrupt( p : Pointer ) ;
Inline(
  $5B/$58/                         { POP  BX, AX   AX:BX = p }
  $89/$EC/                         { MOV  SP, BP             }
  $87/$46/$10/                     { XCHG AX, [BP+10H]       }
  $87/$5E/$0E/                     { XCHG BX, [BP+0EH]       }
  $5D/$07/$1F/$5F/$5E/             { POP  BP, ES, DS, DI, SI }
  $5A/$59/                         { POP  DX, CX             }
  $FA/                             { CLI                     }
  $CB ) ;                          { RETF          jmp far p }


Function Control_Pressed : Boolean ;

Procedure EOI ;
{ end of interrupt to 8259 }

Function ReadScanCode : Byte ;
{ read keyboard }

Procedure ResetKeyboard ;
{ prepare For next key }

Procedure StoreKey( Scan, Key : Byte );
{ put key in buffer For INT 16 }


Implementation

Uses
  Crt ;  { Sound, NoSound }

Type
  Address = Record                  { used in Pointer manipulation }
    Offset : Word ;
    Segment : Word ;
  end ;
Const
  BiosDataSegment = $40 ;

Var
  KeyState       : Word Absolute BiosDataSegment:$0017 ;
  KeyBufferHead  : Word Absolute BiosDataSegment:$001A ;
  KeyBufferTail  : Word Absolute BiosDataSegment:$001C ;
  KeyBufferStart : Word Absolute BiosDataSegment:$0080 ;
  KeyBufferend   : Word Absolute BiosDataSegment:$0082 ;


Function Control_Pressed : Boolean ;
begin
  Control_Pressed := ( KeyState and  4 ) = 4 ;
end;

Procedure EOI ;
{ end of interrupt to 8259 interrupt controller }
begin
  CLI ;
  Port[$20] := $20 ;
end ;

Function ReadScanCode : Byte ;
begin
  ReadScanCode := Port[$60] ;
end ;

Procedure ResetKeyboard ;
{ prepare For next key }
Var
  N : Byte ;
begin
  N := Port[$61] ;
  Port[$61] := ( N or $80 ) ;
  Port[$61] := N ;
end ;

Procedure StoreKey( Scan, Key : Byte ) ;
Var
{ put key in buffer that INT 16 reads }
  P : ^Word ;
  N : Word ;
begin
  address(P).segment := BiosDataSegment ;
  N := KeyBufferTail ;
  address(P).offset := N ;
  Inc( N, 2 ) ;                      { advance Pointer two Bytes }
  If( N = KeyBufferend ) then        { end of the circular buffer }
     N := KeyBufferStart ;
  If( N = KeyBufferHead ) then       { buffer full }
  begin
    EOI ;               { EOI must be done before Exit            }
    Sound( 2200 ) ;     {    but before anything that takes a lot }
    Delay( 80 ) ;       {     of time and can be interrupted      }
    NoSound ;
  end
  Else
  begin          { high Byte is scan code, low is ASCII }
    P^ := Scan * $100 + Key ;       { store key in circular buffer }
    KeyBufferTail := N ;            { advance tail Pointer }
    EOI ;
  end ;
end ;

end.




Unit POLL ;         { polled keyboard handler }
                    { does not support F11 or F12 keys } Interface

Const
  EscKey = 1 ;    { key codes }
  aKey = 30 ;
  sKey = 31 ;
  endKey = 79 ;
  DownKey = 80 ;

Var
  KeyTable : Array[ 1..127 ] of Boolean ;

{ KeyTable[ x ] is True when key x is pressed and stays True Until key
  x is released }


Implementation

Uses
  Dos, KeyIntr ;  { keyboard interrupt support }

Var
  OldInt09 : Pointer ;
  ExitSave : Pointer ;

Procedure RestoreInt09 ; Far;
begin
  ExitProc := ExitSave ;
  SetIntVec( $09, OldInt09 ) ;
end ;

Procedure NewInt09 ; interrupt ; Far;
Var
  ScanCode : Byte ;
  KeyCode : Byte ;
begin
  STI ;
  ScanCode := ReadScanCode ;
  KeyCode := ScanCode and $7F ;        { strip make/break bit }
  KeyTable[ KeyCode ] := ( ScanCode and $80 ) = 0 ;
  ResetKeyboard ;
  EOI ;
end ;

Var
  N : Byte ;

begin
  ExitSave := ExitProc ;
  ExitProc := addr( RestoreInt09 ) ;

  For N := 1 to 127 do   { no key pressed }
    KeyTable[ N ] := False ;

  GetIntVec( $09, OldInt09 ) ;
  SetIntVec( $09, addr( NewInt09 ) ) ;
end.

[Back to KEYBOARD SWAG index]  [Back to Main SWAG index]  [Original]