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

    ==============================================================================
     BBS: ®® The Information and Technology Exchan
      To: MATT CRILL                   Date: 01-05Ä92 (23:03)
    From: DANIEL CHURCHMAN           Number: 4144   [101] PASCAL
    Subj: JOYSTICK 1                 Status: Public
    ------------------------------------------------------------------------------
    Program Joy;  { Read Joystick positions and button states }

    Uses DOS, Crt;

    Const
      Buttons          : Byte = 0;
      Joystick         : Byte = 1;

      JoyIntr          : Byte = $15;
      JoyFunc          : Byte = $84;

      CStart           : Byte = 0; { To hold cursor start line }
      CEnd             : Byte = 0; { To hold cursor end line }

      kX               : Real = 6.25; { constant for horizontal conversion }
      kY               : Real = 20.0; { constant for vertical conversion }

      LastKey          : Char = ' ';

    Var
      { Variables for Joystick 1 }
      Joy1Vert         : Word; { Vertical Position }
      Joy1Hori         : Word; { Horizontal Position }
      Joy1But1         : Boolean; { Button 1 }
      Joy1But2         : Boolean; { Button 2 }

      { Variables for Joystick 2 }
      Joy2Vert         : Word; { Vertical Position }
      Joy2Hori         : Word; { Horizontal Position }
      Joy2But1         : Boolean; { Button 1 }
      Joy2But2         : Boolean; { Button 2 }

      Error            : Boolean; { We'll set this if the joystick isn't found }

      Regs             : Registers;
      NewX, NewY       : Byte;
      OldX, OldY       : Byte;
      MinX, MinY,
      MaxX, MaxY       : Word;

    { Checkjoy and CheckBut are really the only two procedures of real }
    { interest to you; the rest is just support code to do something   }
    { with the samples.                                                }

    Procedure CheckJoy;
        begin   { Prepare and make Int 15h, subfunction 84h call }
          With Regs do
          begin
            AH := JoyFunc;
            DX := Joystick;  { Subfunction 1 = joystick }
            Intr(JoyIntr, Regs);
            Joy1Hori := AX;
            Joy1Vert := BX;
            Joy2Hori := CX;
            Joy2Vert := DX;
            Error := ((Flags AND FCarry) <> 0)
          end;
        end;

    Procedure CheckBut;
        Const
          MaskJ1B1     = $10;
          MaskJ1B2     = $20;
          MaskJ2B1     = $40;
          MaskJ2B2     = $80;
        begin   { Prepare and make Int 15h, subfunction 84h call }
          With Regs do
          begin
            AH := JoyFunc;
            DX := Buttons;  { Subfunction 0 = buttons }
            Intr(JoyIntr, Regs);
            Joy1But1 := (AL AND MaskJ1B1) <> MaskJ1B1;
            Joy1But2 := (AL AND MaskJ1B2) <> MaskJ1B2;
            Joy2But1 := (AL AND MaskJ2B1) <> MaskJ2B1;
            Joy2But2 := (AL AND MaskJ2B2) <> MaskJ2B2;
            Error := ((Flags AND FCarry) <> 0)
          end;
        end;

    Procedure Calibrate;
        Var
          n            : Byte;
        begin
          { Calibrate joystick 1 }
          CheckJoy;
          If Error then
          begin
            Write('No Joystick(s) found - terminating program');
            Halt(1)
          end;

          If (Joy1Vert + Joy1Hori) = 0 then
            Writeln('Joystick 1 Absent')
          else
            Writeln('Joystick 1 Present');
          If (Joy2Vert + Joy2Hori) = 0 then
            Writeln('Joystick 2 Absent')
          else
            Writeln('Joystick 2 Present');

    (*      { Get centre joystick values for X and Y }
          Write('Hold joystick in centre position and press a button');
          Repeat
            CheckBut
          Until (Joy1But1 OR Joy1But2);
          CentreX := 0;
          CentreY := 0;
          For n := 1 to 10 do
          begin
            CheckJoy;
            CentreX := CentreX + Joy1Hori;
            CentreY := CentreY + Joy1Vert;
          end;
          CentreX := CentreX DIV 10;
          CentreY := CentreY DIV 10;
          While (Joy1But1 OR Joy1But2) do  { Wait till button released }
          begin
            CheckBut
          end;
          Writeln('  -  ',CentreX,':',CentreY);
    *)

          { Get minimum joystick values for X and Y }
          Write('Hold joystick in upper-left position and press a button');
          Repeat
            CheckBut
          Until (Joy1But1 OR Joy1But2);
          MinX := 0;
          MinY := 0;
          For n := 1 to 10 do  { Sample over time for accuracy }
          begin
            CheckJoy;
            { Bias the reading slightly to ensure }
            { we can always reach coord 1,1 }
            MinX := MinX + Word(Round(Joy1Hori * 1.1));
            MinY := MinY + Word(Round(Joy1Vert * 1.1))
          end;
          MinX := MinX DIV 10;
          MinY := MinY DIV 10;
          While (Joy1But1 OR Joy1But2) do  { Wait till button released }
          begin
            CheckBut
          end;
          Writeln('  -  ',MinX,':',MinY);

          { Get maximum joystick values for X and Y }
          Write('Hold joystick in bottom-right position and press a button');
          Repeat
            CheckBut
          Until (Joy1But1 OR Joy1But2);
          MaxX := 0;
          MaxY := 0;
          For n := 1 to 10 do   { Sample over time for accuracy }
          begin
            CheckJoy;
            { Bias the reading slightly to ensure }
            { we can always reach coord 80,25 }
            MaxX := MaxX + Word(Round(Joy1Hori * 0.95));
            MaxY := MaxY + Word(Round(Joy1Vert * 0.95))
          end;
          MaxX := MaxX DIV 10;
          MaxY := MaxY DIV 10;
          While (Joy1But1 OR Joy1But2) do  { Wait till button released }
          begin
            CheckBut
          end;
          Writeln('  -  ',MaxX,':',MaxY);

          { Important to note that the following calculations of kX and   }
          { kY is done linearly.  This is not really correct, as you'll   }
          { see by the fact that when centred, your screen coords are     }
          { NOT 40,13.  The reason is that the resistors in joysticks     }
          { work on a logarithmic scale.  My knowledge of logs is too     }
          { rusty to build this in properly, so I've skipped it.  What    }
          { you should do is derive the log that correctly passes through }
          { minimum, maximum AND centre.  This way, the joystick, centred }
          { will correctly position your screen coord dead centre, and    }
          { you can still reach the extremes as well.                     }

          kX := (MaxX - MinX) / 80;
          kY := (MaxY - MinY) / 25;
          Writeln('kX = ', kX:0:2,'     kY = ',kY:0:2);

        end;

    [Continued]

    --- Msged/sq
     * Origin: C&O Systems, Brisbane, AUSTRALIA (3:640/777)
    ==============================================================================
     BBS: ®® The Information and Technology Exchan
      To: MATT CRILL                   Date: 01-05Ä92 (23:04)
    From: DANIEL CHURCHMAN           Number: 4145   [101] PASCAL
    Subj: JOYSTICK 2                 Status: Public
    ------------------------------------------------------------------------------
    Procedure SetCoord;
        begin
          If Joy1Hori < MinX then NewX := 1 else
            NewX := Byte(Round((Joy1Hori - MinX) / kX));
          If Joy1Vert < MinY then NewY := 1 else
            NewY := Byte(Round((Joy1Vert - MinY) / kY));

          If NewX = 0 then NewX := 1;
          If NewX > 80 then NewX := 80;
          If NewY = 0 then NewY := 1;
          If NewY > 25 then NewY := 25;

        end;

    Procedure MoveIndicator;
        begin

          { If the position has changed, clean up old indicator }
          If NOT ((OldX = NewX) AND (OldY = NewY)) then
          begin

            { Turn off indicator at old position }
            With Regs do
            begin
              { First, move cursor to old position }
              AH := 2;   { Set cursor position                }
              BH := 0;   { Assume page 0                      }
              DH := OldY - 1; { This value must be zero-based }
              DL := OldX - 1; { This one too                  }
              Intr($10,Regs);

              { Now change the attribute }
              AH := 8;   { Read what character is there now                  }
              BH := 0;   { I'm assuming page 0                               }
              Intr($10,Regs);  {AH now holds the attribute, AL the character }
              AH := 9;   { Write Character and Attribute, AL is ok, so...    }
              BL := 31;  { ...only change the attribute                      }
              BH := 0;   { Again, assume page 0                              }
              CX := 1;   { Number of characters to write                     }
              Intr($10,Regs)
            end
          end;
          { Always refresh the current position }

          With Regs do
          begin
            { Next, move cursor to new position }
            AH := 2;   { Set cursor position                }
            BH := 0;   { Assume page 0                      }
            DH := NewY - 1; { This value must be zero-based }
            DL := NewX - 1; { This one too                  }
            Intr($10,Regs);

            { Then, turn on indicator at NEW position }
            AH := 8;   { Read what character is there now                  }
            BH := 0;   { I'm assuming page 0                               }
            Intr($10,Regs);  {AH now holds the attribute, AL the character }
            AH := 9;   { Write Character and Attribute, AL is ok, so...    }
            BL := 112; { ...change the attribute to black on grey          }
            BH := 0;   { Again, assume page 0                              }
            CX := 1;   { Number of characters to write                     }
            Intr($10,Regs)

          end;

        end;

    Procedure InitScreen;
        begin
          GotoXY(26,10);
          Write('Joystick 1        Joystick 2');
          GotoXY(20,12);
          Write('X :');
          GotoXY(20,13);
          Write('Y :');
          GotoXY(14,14);
          Write('Buttons :');
          GotoXY(16,16);
          Write('Error =');
          GotoXY(20,23);
          Write('Press "C" to reCalibrate your joystick');

          With Regs do
          begin      { First, save present cursor configuration }

            AH := 3; { Read cursor pos and config }
            BH := 0; { Assuming we are using page 0 }
            Intr($10,Regs);
            CStart := CH; { Starting line of cursor }
            CEnd   := CL; { Ending line of cursor }
            { DH holds cursor row }
            { DL holds cursor column }

            { Now turn the cursor off - we hope! }

            AH := 1;  { Set cursor type }
            CH := $20; { Should cause the cursor to disappear }
            Intr($10,Regs);

          end
        end;

    Procedure GetKey;
        begin
          If KeyPressed then
          begin
            LastKey := ReadKey;  { Read the key in the buffer       }
            If LastKey = #0 then { The key is an extended character }
              LastKey := ReadKey { Read the extended value          }
          end else
            LastKey := #0
        end;

    [Continued]

    --- Msged/sq
     * Origin: C&O Systems, Brisbane, AUSTRALIA (3:640/777)
    ==============================================================================
     BBS: ®® The Information and Technology Exchan
      To: MATT CRILL                   Date: 01-05Ä92 (23:05)
    From: DANIEL CHURCHMAN           Number: 4146   [101] PASCAL
    Subj: JOYSTICK 3                 Status: Public
    ------------------------------------------------------------------------------
    begin
      TextAttr := 31;  { White on Blue - my favourite :-) }
      ClrScr;

      Calibrate;
      SetCoord;

      InitScreen;

      Repeat
        GetKey;  { Simply load the variable LastKey with }
                 { a keystroke if one is available       }
        CheckJoy;
        CheckBut;
        OldX := NewX;
        OldY := NewY;
        SetCoord;
        GotoXY(24,12);
        Write(Joy1Hori:10);
        GotoXY(24,13);
        Write(Joy1Vert:10);
        GotoXY(31,14);
        Write((Joy1But1):5,':',(Joy1But2):5);

        GotoXY(44,12);
        Write(Joy2Hori:10);
        GotoXY(44,13);
        Write(Joy2Vert:10);
        GotoXY(51,14);
        Write(Byte(Joy2But1),':',Byte(Joy2But2));

        GotoXY(37,15);
        Write(NewX:2,':',NewY:2);

        GotoXY(24,16);
        Write(Error:5);

        Writeln;
        MoveIndicator;

        If UpCase(LastKey) = 'C' then
        begin
          ClrScr;
          Calibrate;
          InitScreen
        end;

      Until LastKey = #27;

      With Regs do
      begin      { Restore original cursor configuration }

        AH := 1;  { Set cursor type }
        CH := CStart; { Original cursor start line }
        CL := CEnd;   { Original cursor end line }
        Intr($10,Regs);
        GotoXY(1,24)
      end;

    end.

    [End of code]
    --- Msged/sq
     * Origin: C&O Systems, Brisbane, AUSTRALIA (3:640/777)

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