home *** CD-ROM | disk | FTP | other *** search
/ Stars of Shareware: Raytrace & Morphing / SOS-RAYTRACE.ISO / programm / source / devel5 / joystick.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-07-12  |  8.8 KB  |  450 lines

  1. /* Read the joystick */
  2.  
  3. /* Written by Bernie Roehl, January 1992 (broehl@sunee.waterloo.edu)
  4.      Adapted from code written by ajmyrvold@violet.waterloo.edu (Alan J. Myrvold)
  5.      who got technical assistance from : uunet!netxcom!jallen (John Allen)
  6.  
  7.      ATTRIBUTION:  If you use any part of this source code or the libraries
  8.      in your projects, you must give attribution to REND386, Dave Stampe,
  9.      and Bernie Roehl in your documentation, source code, and at startup
  10.      of your program.  Let's keep the freeware ball rolling!
  11.  */
  12.  
  13. /* DSmods: - rotate calibration - switch debounce */
  14. /* joystick interaction mods, timer read by Dave Stampe */
  15.  
  16. #pragma inline
  17.  
  18. #define TIMERJOYREAD 1
  19.  
  20. #include <stdio.h>
  21. #include <stdlib.h>
  22. #include <dos.h>
  23. #include <bios.h>
  24. #include <conio.h>
  25. #include "userint.h"   /* for joystick struct */
  26. #include "rend386.h"   /* for interrupts_occurred */
  27.  
  28. extern void hookints(void);
  29.  
  30. /* This routine returns two bits; bit 0 on => joystick 1 found, bit 1 => joystick 2 */
  31.  
  32. int joystick_check(void)
  33. {
  34.     int c, result;
  35.     disable();
  36.     outportb(0x201,0xff); /* Trigger joystick */
  37.     c = inportb(0x201);
  38.     c = inportb(0x201);
  39.     c = inportb(0x201);
  40.     delay(2); /* wait a few milliseconds */
  41.     c ^= inportb(0x201); /* any bits that changed state are now set */
  42.     enable();
  43.     result = 0;
  44.     if (c & 0x03) result |= 1;
  45.     if (c & 0x0C) result |= 2;
  46.     return result;
  47. }
  48.  
  49. int joystick_j1 = 0;     /* raw joystick results */
  50. int joystick_j2 = 0;
  51. int joystick_j3 = 0;
  52. int joystick_j4 = 0;
  53.  
  54.  
  55. #ifdef TIMERJOYREAD
  56.  
  57. void raw_joystick_read(int mask,
  58.     int *j1, int *j2, int *j3, int *j4, int *buttons)
  59. {                    /* timer peek version */
  60.  int c;                    /* much more stable   */
  61.  int vj1,vj2,vj3,vj4;            /* by Dave STampe, 8/5/93 */
  62.  extern unsigned clock_rate;
  63.  unsigned last_time;
  64.  unsigned char raw = 0;
  65.  int abort = 0;
  66.  
  67.  int k;
  68.  
  69.  if(!mask) return;
  70.  
  71.  interrupts_occurred = 0;     /* repeat if timer interrupt! */
  72.  do
  73.   {
  74.    if (interrupts_occurred) for (c = 0; c < 1000; c++); /* let it reset */
  75.    interrupts_occurred = 0; /* repeat if timer interrupt! */
  76.      k = kbhit();
  77.  
  78.    vj1 = vj2 = vj3 = vj4 = 0;
  79.  
  80.    asm {
  81.     push    dx
  82.  
  83.     cli
  84.     mov    dx,0201h          /* start port timers */
  85.     mov    al,0ffh
  86.     out    dx,al
  87.  
  88.     mov    al,00h            /* read timer */
  89.     out    043h,al
  90.     nop
  91.     nop
  92.     nop
  93.     nop
  94.     in    al,040h
  95.     mov    ah,al
  96.     nop
  97.     nop
  98.     in    al,040h
  99.     xchg    al,ah
  100.     mov    last_time,ax
  101.  
  102.     in    al,dx            /* record port value */
  103.     mov    raw,al
  104.     and    al,mask
  105.     mov    bl,al
  106.     je      timeout        /* very short time */
  107.     mov    cx,4000    /* safety timer */
  108.     sti
  109.        }
  110. wloop:
  111.      asm {
  112.     sti                      /* allow ints */
  113.     cli
  114.     in    al,dx
  115.     mov    raw,al           /* port change? */
  116.     and    al,mask
  117.     xor    al,bl
  118.     and     al,mask
  119.     jne    timeout
  120.     loop    wloop            /* safety timer */
  121.     mov    al,mask
  122.     not    al
  123.     mov    raw,al
  124.     mov    abort,ax
  125.        }
  126. timeout:
  127.    asm {
  128.     mov    bl,raw           /* record change */
  129.     mov    bh,al
  130.  
  131.     mov    al,00h         /* read new timer value */
  132.     out    043h,al
  133.     nop
  134.     nop
  135.     nop
  136.     nop
  137.     in    al,040h
  138.     mov    ah,al
  139.     nop
  140.     nop
  141.     in    al,040h
  142.     xchg    al,ah
  143.     sti
  144.  
  145.     sub    ax,last_time     /* compute delay */
  146.     neg    ax
  147.     jge    posj
  148.     add    ax,clock_rate     /* fixup for timeout */
  149.        }
  150. posj:
  151.    asm {
  152.     test    bh,8        /* update proper values */
  153.     je    ns4
  154.     mov    vj4,ax
  155.        }
  156. ns4:
  157.    asm {
  158.     test    bh,4
  159.     je    ns3
  160.     mov    vj3,ax
  161.        }
  162. ns3:
  163.    asm {
  164.     test    bh,2
  165.     je    ns2
  166.     mov    vj2,ax
  167.        }
  168. ns2:
  169.    asm {
  170.     test    bh,1
  171.     je    ns1
  172.     mov    vj1,ax
  173.        }
  174. ns1:
  175.    asm {
  176.     mov    al,raw        /* check if all done */
  177.     not    al
  178.     and    al,mask
  179.     cmp    al,mask
  180.     jne    wloop
  181.              }
  182. shorttime:
  183.    asm {
  184.     pop    dx
  185.        }
  186.   if(interrupts_occurred == 0 && k == kbhit() || abort) break;
  187.  }
  188.   while (1);
  189.  *j1 = vj1;
  190.  *j2 = vj2;
  191.  *j3 = vj3;
  192.  *j4 = vj4;
  193.  *buttons = ((~raw) >> 4) & 0x0F;
  194.  joystick_j1 = vj1;
  195.  joystick_j2 = vj2;
  196.  joystick_j3 = vj3;
  197.  joystick_j4 = vj4;
  198. }
  199.  
  200. #else
  201.  
  202. void raw_joystick_read(int mask,
  203.     int *j1, int *j2, int *j3, int *j4, int *buttons)
  204. {
  205.  int vj1,vj2,vj3,vj4;
  206.  int c, k, kb;
  207.  int savemask;
  208.  
  209.  if(!mask) return;
  210.  
  211. #ifdef JOY_INTS
  212.  /* mask all but timer IRQ : cannot use with some serial devices */
  213.  disable();
  214.  outportb(PIC_MASK,((savemask=inportb(PIC_MASK))|IRQ0_MASK));
  215.  outportb(PIC_CMD, NONSPEC_EOI);
  216.  enable();
  217. #endif
  218.  
  219.  interrupts_occurred = 0; /* repeat if timer interrupt! */
  220.  while(1)
  221.   {
  222.    kb = kbhit();
  223.    if (interrupts_occurred) for (c = 0; c < 1000; c++); /* let it reset */
  224.    interrupts_occurred = 0; /* repeat if timer interrupt! */
  225.    outportb(0x201, 0xff); /* Trigger joystick */
  226.    c = inportb(0x201);
  227.    if (mask==0x0C) c >>= 2;
  228.    *buttons = ((~c) >> 4) & 0x0F;
  229.  
  230.    for (k = 0; c & 3; k++) /* Get X and Y positions */
  231.     {
  232.      if (c & 1) vj1 = k;
  233.      if (c & 2) vj2 = k;
  234.      if (c & 4) vj3 = k;
  235.      if (c & 8) vj4 = k;
  236.      c = inportb(0x201);
  237.     }
  238.   if(interrupts_occurred == 0 && kb == kbhit()) break;
  239.  }
  240.  
  241.  *j1 = vj1;
  242.  *j2 = vj2;
  243.  *j3 = vj3;
  244.  *j4 = vj4;
  245.  joystick_j1 = vj1;
  246.  joystick_j2 = vj2;
  247.  joystick_j3 = vj3;
  248.  joystick_j4 = vj4;
  249. #ifdef JOY_INTS
  250.   disable();
  251.     outportb(PIC_MASK,savemask); /* re-enable */
  252.   enable();
  253. #endif
  254. }
  255.  
  256.  
  257.  
  258. #endif
  259.  
  260. /* This routine reads the joystick, setting x y and buttons */
  261.  
  262. int joystick_bt = 0;      /* used by pot head tracker */
  263. int use_pothead = 0;
  264.  
  265. int joystick_read(joystick_data *joy)
  266. {
  267.  int c, k, jx, jy;
  268.  int j;
  269.  if (joy->port == -1) return 0;
  270.  c = (joy->port) ? 0x0C : 0x03;
  271.  if(use_pothead) c |= 0x0C;
  272.  
  273.  raw_joystick_read(c, &jx, &jy, &j, &j, &joystick_bt);
  274.  joy->buttons = joystick_bt;
  275.  if(joy->port) joy->buttons >>= 2;
  276.  
  277.  joy->x = jx - joy->cenx;
  278.  joy->y = jy - joy->ceny;
  279.  if (joy->scale)
  280.   {
  281.    joy->x = (joy->x * joy->scale) /joy->xrange;
  282.    joy->y = (joy->y * joy->scale) /joy->yrange;
  283.   }
  284.  return 1;
  285. }
  286.  
  287.  
  288. /* This routine assumes the joystick is centered; sets the port and the
  289.    maximum range for the joystick (i.e. minx to maxx) */
  290.  
  291. void joystick_init(joystick_data *joy, int port)
  292. {
  293.  joy->cenx = joy->ceny = 0;
  294.  joy->port = port;
  295.  joy->scale = 0;
  296.  joystick_read(joy);
  297.  joy->cenx = joy->x;
  298.  joy->ceny = joy->y;
  299.  joy->xrange = 2*joy->x;
  300.  joy->yrange = 2*joy->y;
  301.  if(joy->xrange==0) joy->xrange = 1;
  302.  if(joy->yrange==0) joy->yrange = 1;
  303. }
  304.  
  305. void joystick_setscale(joystick_data *joy, int value)
  306. {
  307.  joy->scale = value;
  308. }
  309.  
  310. void joystick_quit(void)
  311. {
  312. }
  313.  
  314. /* If dir == 0, we're at top left; else, we're at bottom right */
  315. /* NO LONGER USED */
  316. void joystick_scale(joystick_data *joy, int dir)
  317. {
  318.     long t;
  319.     long maxx, maxy, minx, miny;
  320.  
  321.     maxx = maxy = 0;
  322.     minx = miny = 10000;
  323.  
  324.     t = joy->scale;
  325.     joy->scale = 0;
  326.     do {
  327.         joystick_read(joy);
  328.         if (joy->x > maxx) maxx = joy->x;
  329.         if (joy->y > maxy) maxy = joy->y;
  330.         if (joy->x < minx) minx = joy->x;
  331.         if (joy->y < miny) miny = joy->y;
  332.     }
  333.     while (joy->buttons == 0);
  334.  
  335.     joy->xrange = maxx - minx;
  336.     joy->yrange = maxy - miny;
  337.     delay(10);
  338.     do {
  339.         joystick_read(joy);
  340.     }
  341.     while (joy->buttons);
  342.     delay(10);
  343.  
  344.     joy->scale = t;
  345. }
  346.  
  347.  
  348. static int oldalt = 0;
  349. static mjx = 0;
  350. static mjy = 0;
  351.  
  352. static int old_mjx = 0;
  353. static int old_mjy = 0;
  354.  
  355. extern int mouse_nav;
  356. extern flymode;
  357.  
  358.  
  359. mouse_joy(joystick_data *joy)
  360. {
  361.     union REGS r;
  362.     int x,y,b;
  363.     int alt;
  364.  
  365.     if (!mouse_nav) {
  366.  
  367.         r.h.ah = 2;
  368.         int86(0x16, &r, &r);
  369.         alt = r.h.al & 8;
  370.         if (alt == 0)
  371.         {
  372.             joy->x = 0;
  373.             joy->y = 0;
  374.             joy->buttons = 0;
  375.             oldalt = 0;
  376.             return 0;
  377.         }
  378.         else
  379.             if (oldalt == 0)
  380.         {
  381.             mjx = 0;
  382.             mjy = 0;
  383.             oldalt = alt;
  384.         }
  385.     }
  386.     r.x.ax = 3; /* read button status */
  387.     int86(0x33, &r, &r);
  388.     {
  389.         int b=0;
  390.         if (r.x.bx & 1) b |= 2;
  391.         if (r.x.bx & 2) b |= 1;
  392.         joy->buttons = b;
  393.     }
  394.  
  395.     r.x.ax = 11; /* read motion counters */
  396.     int86(0x33, &r, &r);
  397.     if(!flymode) old_mjx = old_mjy = 0;
  398.     if ((!flymode) || (r.x.bx&2))
  399.     {
  400.         mjx = ((int) r.x.cx); /* MOUSE STEP: remove hysteresis */
  401.         mjy = ((int) r.x.dx);
  402.  
  403.         if (mjx<0) mjx += -11;
  404.         if (mjy<0) mjy += -11;
  405.         if (mjx>0) mjx += 11;
  406.         if (mjy>0) mjy += 11;
  407.     }
  408.     else
  409.     {
  410.         mjx = old_mjx;     /* save for reversion */
  411.         mjy = old_mjy;
  412.         mjx += ((int) r.x.cx)>>2; /*  SPEED STEP */
  413.         mjy += ((int) r.x.dx)>>2;
  414.         if (mjx < -joy->scale) mjx = -joy->scale;
  415.         if (mjy < -joy->scale) mjy = -joy->scale;
  416.         if (mjx > joy->scale) mjx = joy->scale;
  417.         if (mjy > joy->scale) mjy = joy->scale;
  418.         old_mjx = mjx;
  419.         old_mjy = mjy;
  420.     }
  421.     joy->x = mjx>>1;
  422.     joy->y = mjy>>1;
  423.     return 1;
  424. }
  425.  
  426.  
  427. #ifdef TEST
  428. void main(void)
  429. {
  430.     joystick_data joy;
  431.     if (joystick_check())
  432.         printf("We found a joystick!\n");
  433.     else {
  434.         printf("No joy.\n");
  435.         exit(0);
  436.     }
  437.     joystick_init(&joy, 0);
  438.     joystick_setscale(&joy, 100);
  439.     printf("Move joystick to upper left:\n");
  440.     joystick_scale(&joy, 0);
  441.     printf("Move joystick to lower right:\n");
  442.     joystick_scale(&joy, 1);
  443.     do {
  444.         joystick_read(&joy);
  445.         printf("%d,%d        \r", joy.x, joy.y);
  446.     }
  447.     while (joy.buttons == 0);
  448. }
  449. #endif
  450.