[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]