⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 joystick.c

📁 二~六键游戏操纵杆(gamepad)控制程序
💻 C
📖 第 1 页 / 共 2 页
字号:
/*
** Joystick routines.
**
** This file is part of:
**
** Joystick Library for Dos.
** Version: 1.1
**
** Last modified: June 15th, 1997
**
** (C) 1997 Simone Zanella Productions.
**
** E-mail: szanella@dsi.unive.it
**         zanella@prometeo.it
**
** Web:    http://www.dsi.unive.it/~szanella/index.htm
**         http://members.tripod.com/~szanella/index.htm
**
** Changes from version 1.0:
**
** - changed calibration to manual, to avoid incompatibilities and
**   to get a faster reading;
** - added support for 4 and 6 buttons joysticks;
** - added parameter mode to function InstallJoystick, to set
**   the number of buttons for joysticks;
** - added parameter skipjoy to function InstallJoystick, to skip
**   installation/calibration of one joystick;
** - added parameter calibfile to function InstallJoystick, to
**   allow calibration saving/reloading;
** - changed to integer parameters 'first' and 'second' in function
**   ReadJoystick, to keep flags for fire buttons 5 and 6;
** - removed tolerances from function InstallJoystick.
**
** --------------------------------------------------------
**
** This is freeware: use it as you like, but ALWAYS include
** the original author's name in the docs of your program.
**
** --------------------------------------------------------
**
** Usage:
**
** - include "joystick.h" at the beginning of your program and
**   compile and link the module "joystick.c"
**
** - at program startup, use:
**
**   unsigned char j, mode;
**
**   // Set mode to the kind of joystick requested:
**   // JOY_2BUTTONS    standard 2-buttons joysticks
**   // JOY_4BUTTONS    4-buttons joysticks (fire 3 and 4 are other joystick's
**   //                 fire buttons)
**   // JOY_6BUTTONS    6-buttons joystick (fire 3 & 4 as above, fire 5 and 6
**   //                 connected to joystick #2 directions)
**   //
**   // Set calibfile to the name of a file to be used for saving/reloading
**   // calibration (NULL to force re-calibration at each run).
**   //
**   // Set skipjoy to:
**   // JOY_NONE    if all joysticks connected should be detected and calibrated;
**   // JOY_SECOND  if only first joystick is used and thus should be calibrated.
**
**   j = InstallJoystick(mode, skipjoy, calibfile);
**
** - use the value j to determine number of joysticks connected:
**
**   j & JOY_FIRST    first joystick is present
**   j & JOY_SECOND   second joystick is present
**   j & JOY_BOTH     both joysticks present (or one 6-buttons joystick)
**
** - when you want to read the joystick(s), use:
**
**   unsigned int fj, sj;
**
**   ReadJoystick(&fj, &sj);
**
**   Then, you can determine if a direction is activated by:
**
**   fj & JOY_xx
**
**   where "xx" can be: UP, DN (down), LT (left), RT (right)
**
**   You can test the fire buttons in a similar way:
**
**   fj & JOY_AF    first button
**   fj & JOY_BF    second button
**   fj & JOY_CF    third button (only when mode = JOY_4BUTTONS)
**   fj & JOY_DF    fourth button (only when mode = JOY_4BUTTONS)
**   fj & JOY_EF    fifth button (only joystick 1, when mode = JOY_6BUTTONS)
**   fj & JOY_FF    sixth button (only joystick 1, when mode = JOY_6BUTTONS)
**
**   Of course, replace "fj" above with "sj" to test second joystick.
**
** If you want to poll joystick at regular intervals, you can chain the
** system timer (int 8).
*/

#include "joystick.h"

#include <stdlib.h>
#include <dos.h>
#include <limits.h>
#include <conio.h>
#include <io.h>
#include <fcntl.h>
#include <stat.h>
#include <stdio.h>

/*
#ifndef __BORLANDC__
#include <pc.h>
#endif
*/

#define JOYPORT              0x201

/* Number of divisions, for determining thresholds */

#define SEGMENTS             2

/* Tolerance, to determine direction on 6-buttons joysticks */

#define JOY_TOL              100

 /* Constant for timed joy reading */

#define JOYCOUNTER           60000

/* Pseudo-functions */

#define GetBit(c, n)         ( c & ( 1 << (n) ) )

/* Static variables used for storing:
** - x and y coordinates;
** - threshold values;
** - status (ready/not ready);
** - mode (2, 4 or 6 buttons);
** - flags.
*/

static int x[2], y[2], calib[2][4];
static unsigned char jready[2], joymode = JOY_2BUTTONS;
static unsigned int jstatus[2];

/* Maps for fire buttons (internal) */

static unsigned char fire1[2] = {16, 64};
static unsigned char fire2[2] = {32, 128};

/****************************************************************************/
/************** Internal functions: should NOT be called by user ************/
/****************************************************************************/

static unsigned char _readjport(void)
{
  /*
  ** Read joystick port, setting x and y coordinates for each joystick;
  ** the status of the 4 buttons is returned.
  */

  register long count;
  register unsigned char st, mask;

  mask = 0;
  if (jready[0])
    mask |= 3;

  if (jready[1])
    mask |= 12;

  count = x[0] = y[0] = x[1] = y[1] = 0;
  disable();

  /* Read port for JOYCOUNTER cycles */

  /* Don't count previous reading (VERY FAST machines) */
  do st = inportb(JOYPORT);
  while (st & mask);
  outportb(JOYPORT, 0xFF);
  do
  {
    st = inportb(JOYPORT);
    if (st & 1)
      x[0]++;
    if (st & 2)
      y[0]++;
    if (st & 4)
      x[1]++;
    if (st & 8)
      y[1]++;

    count++;
  } while ((st & mask) && count <= JOYCOUNTER);
  enable();

  return st;
}

static unsigned char _readjbutton(const unsigned char j)
{
  /*
  ** Read joystick, returning 0 if no fire button is pressed.
  */

  register unsigned char st, mask, pressed;

  if (j)
    mask = 12;
  else
    mask = 3;
  outportb(JOYPORT, 0xFF);
  st = inportb(JOYPORT);
  pressed = (j) ? (!(st & 64) || !(st & 128)) : (!(st & 16) || !(st & 32));
  while (st & mask)
    st = inportb(JOYPORT);
  return pressed;
}

static unsigned char _readjpos(const unsigned char j)
{
  /*
  ** Wait for the user to press a joystick button, then read joystick
  ** port; return 0 if user aborted calibration.
  */

  delay(1000);

  /* Wait for button pressed */
  while (!_readjbutton(j))
    if (kbhit())
      if (getch() == 0x1B)
        return 0;

  _readjport();

  /* Wait for button released */
  while (_readjbutton(j));

  return 1;
}

static unsigned int _manualdir(const unsigned char j)
{
  /*
  ** Direction check for manual calibration.
  */

  register unsigned int jstat = 0;

  if (x[j] < calib[j][0])
    jstat |= JOY_LT; /* Left */
  else
    jstat |= (x[j] > calib[j][1]) ? JOY_RT : 0; /* Right or center */

  if (y[j] < calib[j][2])
    jstat |= JOY_UP; /* Up */
  else
    jstat |= (y[j] > calib[j][3]) ? JOY_DN : 0; /* Down or center */

  return jstat;
}

unsigned char _usercalib(const unsigned char j)
{
  /*
  ** Print out messages for performing manual calibration for joystick j;
  ** set calibration values and return 1 if successfull, 0 if user aborted.
  */

  unsigned char i, l;
  int centx[2], centy[2], minx[2], maxx[2], miny[2], maxy[2];
  int ocentx, ocenty;

  char *msg[]={"Center stick and press a button (Esc abort)...",
               "Move stick to upper left and press a button (Esc abort)...",
               "Move stick to lower right and press a button (Esc abort)...",
               "While pressing button 5, press button 1 or 2 (Esc abort)...",
               "While pressing button 6, press button 1 or 2 (Esc abort)..."};

  printf("Calibration of joystick %d..\n", j + 1);
  for (i = 0; i < 3; i++)
  {
    printf(msg[i]);
#ifndef __BORLANDC__
    fflush(stdout);
#endif
    l = _readjpos(j);
    printf("\n");
    if (!l)
      return 0;

    /* Insert values for center, maximum, minimum variables */
    switch (i)
    {
      case 0:
        centx[j] = x[j];
        centy[j] = y[j];
        ocentx = x[1];
        ocenty = y[1];
        break;
      case 1:
        minx[j] = x[j];
        miny[j] = y[j];
        break;
      default:
        maxx[j] = x[j];
        maxy[j] = y[j];
        break;
    }
  }
  if (joymode == JOY_6BUTTONS)
  {
    unsigned int jstat;

    for (i = 0; i < 2; i++)
    {
      /* We must calibrate pseudo-directions corresponding to buttons 5 and 6 */
      printf(msg[3 + i]);
#ifndef __BORLANDC__
      fflush(stdout);
#endif
      delay(1000);

  retry:

      /* Wait for button pressed */
      while (!_readjbutton(j))
        if (kbhit())
          if (getch() == 0x1B)
            return 0;

      _readjport();

      jstat = 0;

      if (x[1] < ocentx - JOY_TOL)
        jstat |= JOY_LT; /* Left */
      else
        jstat |= (x[1] > ocentx + JOY_TOL) ? JOY_RT : 0; /* Right or center */

      if (y[1] < ocenty - JOY_TOL)
        jstat |= JOY_UP; /* Up */
      else
        jstat |= (y[1] > ocenty + JOY_TOL) ? JOY_DN : 0; /* Down or center */

      /* Wait for button released */
      while (_readjbutton(j));

      if (jstat & (i ? (JOY_LT | JOY_RT) : (JOY_UP | JOY_DN)))
        if (i) /* Button 6: can be LEFT or RIGHT */
          if (x[1] > ocentx) /* Button corresponds to RIGHT */
          {
            calib[1][1] = ocentx + ((x[1] - ocentx) / SEGMENTS);
            calib[1][0] = INT_MIN;
          }
          else /* Button corresponds to LEFT */
          {
            calib[1][1] = INT_MAX;
            calib[1][0] = ocentx - ((ocentx - x[1]) / SEGMENTS);
          }
        else /* Button 5: can be UP or DOWN */
          if (y[1] > ocenty) /* Button corresponds to DOWN */
          {
            calib[1][3] = ocenty + ((y[1] - ocenty) / SEGMENTS);
            calib[1][2] = INT_MIN;
          }
          else /* Button corresponds to UP */
          {
            calib[1][3] = INT_MAX;
            calib[1][2] = ocenty - ((ocenty - y[1]) / SEGMENTS);
          }
      else
        goto retry;
      printf("\n");
    }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -