[alt.hackers] PC joysticks

dweingar@csserv1.ic.sunysb.edu (David Weingart) (12/08/90)

     One of the more annoying things about dealing with the PC is the
almost total and complete lack of _good_ interface documentation.  Oh,
sure, there's stuff around, but it's well hidden in obscure references
and doesn't always work as advertised.

     To wit:  This past week I had an application at work that required
a joystick.  So we popped out and bought a game card and a cheap
joystick.  According to the PC's interface manuals, the game adapter is
at address 201h, and a read from that address should yield the switch
positions, and the resistance values in one swell foop.

     WRONG!  The switches _are_ read that way, but not the values.  I
eventually found something in a PS/2 BIOS manual which proved to be a
help, and figured I'd share it with you folks.

     In order to read the game adapter for a joystick, you have to
generate DOS interrupt 15h.  AH should be set to 84h.  The read then
depends on the value of DX.  If DX is 0, then the switches are read.
If DX is 1, then you're dealing with the resistance values.  Note that
DX is set _before_ you generate the interrupt.

     Switch values are stored in the AX register, bits 4-7 (AH) upon
return.  When the following bits are high, the following switched are
pressed:  Bit 4: Stick A, button 1; Bit 5: Stick A, button 2,  Bit 6:
Stick B, button 1; Bit 7: Stick B, button 2.

     When the resistive inputs are being read, the following registers
contain the values:  AX:  Stick A, x-coordinate;  BX:  Stick B,
y-coordinate; CX:  Stick B, x-coordinate;  DX:  Stick C, y-coordinate.

     The example below is in MicroSoft C, because that's what our
application was in, but it should be transportable to 80x86 assembly
with no problems.  It only bothers to read stick 1, but could easily be
converted to stick 2.  When run, the '+' will be moved around the
screen with the joystick.  The buttons' status will be displayed in the
upper left of the screen, and the current (x,y) in the upper right.

/*----------example begins here---------------------------------------*/

#include <stdio.h>
#include <conio.h>
#include <graph.h>
#include <dos.h>

void main(void){

   union REGS inregs;
   union REGS outregs;
   int x=10,y=10;

   inregs.h.ah=0x84;


   system("cls");
   _settextposition(24,1);
   printf("Hit any keyboard key to exit back to DOS");
   while(!kbhit()){
      inregs.x.dx=0;                 /*  set for reading the buttons  */
      int86(0x15,&inregs,&outregs);  /*  generate int 15h  */
      _settextposition(1,1);
      if(!(outregs.x.ax & 16))            /*  check button 1  */
          printf("Button 1 pressed    ");
      else
          printf("Button 1 not pressed");
      _settextposition(1,30);
      if(!(outregs.x.ax & 32))             /*  check button 2  */
          printf("Button 2 pressed    ");
      else
          printf("Button 2 not pressed");
      inregs.x.dx=1;                       /*  set for reading pos.  */
      int86(0x15,&inregs,&outregs);
      _settextposition(y,x);
      printf(" ");
      x=outregs.x.ax;
      y=outregs.x.bx/4;  /*  to prevent illegal screen locations  */
      if(x>79)x=79;
      if(x<2)x=2;
      if(y>23)x=23;
      if(y<2)y=2;
      _settextposition(y,x);
      printf("+");
      _settextposition(1,72);
      printf("(%d,%d)   ",x,y);
   }  
}

/*----------example ends here-----------------------------------------*/
-- 
David Weingart                    dweingar@ic.sunysb.edu
The opinions expressed here aren't even mine...
Come down off the perch.  Achieve concensus.  Zooooon!