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

📄 joystick.c

📁 二~六键游戏操纵杆(gamepad)控制程序
💻 C
📖 第 1 页 / 共 2 页
字号:
  }

  printf("\n");

  /* line BEFORE WHICH left is stuffed */
  calib[j][0] = centx[j] - ((centx[j] - minx[j]) / SEGMENTS);

  /* line AFTER WHICH right is stuffed */
  calib[j][1] = centx[j] + ((maxx[j] - centx[j]) / SEGMENTS);

  /* line BEFORE WHICH up is stuffed */
  calib[j][2] = centy[j] - ((centy[j] - miny[j]) / SEGMENTS);

  /* line AFTER WHICH down is stuffed */
  calib[j][3] = centy[j] + ((maxy[j] - centy[j]) / SEGMENTS);

  return 1;
}

static void _readjoy(void)
{
  /* Set flags for each joystick (directions and fire buttons) */

  register int  v;
  register unsigned char st, j;

  st = _readjport();

  for (j = 0; j < 2; j++)
    if (jready[j])
    {
      jstatus[j] = 0;

      if (!(st & fire1[j]))
        jstatus[j] |= JOY_AF;

      if (!(st & fire2[j]))
        jstatus[j] |= JOY_BF;

      jstatus[j] |= _manualdir(j);

      if (joymode) /* 4 buttons or 6 buttons */
      {
        v = j ? 0 : 1;

        if (!(st & fire1[v]))
          jstatus[j] |= JOY_CF;

        if (!(st & fire2[v]))
          jstatus[j] |= JOY_DF;

        /*
        ** Buttons 5 and 6 are connected to directions on second joystick.
        ** Only one 6-button joystick can be connected, so we use jstatus[0]
        ** instead of jstatus[j].
        */

        if (joymode == JOY_6BUTTONS)
        {
          v = _manualdir(1);
          if (v & (JOY_UP | JOY_DN))
            jstatus[0] |= JOY_EF;

          if (v & (JOY_LT | JOY_RT))
            jstatus[0] |= JOY_FF;

          j = 2;
        }
      }
    }
}

static unsigned char _joyready(const unsigned char j)
{
  /*
  ** Probe joystick, returning 1 if it is present, 0 otherwise.
  ** Presence is determined in this way:
  ** - if position (x and y) and both fire buttons read through bios are 0,
  **   joystick is absent;
  ** - otherwise, it is present.
  **
  ** If 'j' is 0, probes the first joystick; if 'j' is 1, probes the second.
  */

  union REGS regs;
  register int x, y, fa, fb;

  /* Read position */
  regs.h.ah = 0x84;
  regs.x.dx = 1;
  int86(0x15, &regs, &regs);
  if (regs.x.cflag)
    return 0; /* Error: joystick not found */

  if (j)
  {
    x = regs.x.cx;
    y = regs.x.dx;
  }
  else
  {
    x = regs.x.ax;
    y = regs.x.bx;
  }

  /* Read fire buttons */
  regs.h.ah = 0x84;
  regs.x.dx = 0;
  int86(0x15, &regs, &regs);
  if (regs.x.cflag)
    return 0; /* Error: joystick not found */

  if (j)
  {
    fa = !GetBit(regs.x.ax, 6);
    fb = !GetBit(regs.x.ax, 7);
  }
  else
  {
    fa = !GetBit(regs.x.ax, 4);
    fb = !GetBit(regs.x.ax, 5);
  }

  if (x + y + fa + fb == 0)
    return 0;
  else
    return 1;
}

static void _savecalib(const char *filename, const unsigned char njoy)
{
  /*
  ** Store number of joysticks connected, joystick mode and
  ** calibration informations into filename (which is created
  ** or overwritten). No errors are reported; if filename is NULL,
  ** calibration is not saved.
  */

  if (filename != NULL)
  {
    register int i, l;
    int h;
    struct calibrecord {
      unsigned char njoy;
      unsigned char joymode;
      int calib[2][4];
    } cr;

    cr.njoy = njoy;
    cr.joymode = joymode;
    for (i = 0; i < 2; i++)
      for (l = 0; l < 4; l++)
        cr.calib[i][l] = calib[i][l];

    h = open(filename, O_WRONLY | O_BINARY | O_CREAT | O_TRUNC, S_IWRITE);

    if (h != -1)
    {
      write(h, (void *) &cr, sizeof(cr));
      close(h);
    }
  }
}

static unsigned char _checkcalib(const unsigned char j)
{
  /*
  ** Check if joystick j is centered, according to current calibration;
  ** returns JOY_FIRST or JOY_SECOND (according to j) if it needs to
  ** be re-calibrated, JOY_NONE otherwise.
  ** This routine does two checks, at one-second interval each:
  ** if both return joystick off-centered, the program assumes that
  ** calibration is needed.
  */

  int try = 0;
  unsigned int jstat;

retry:

  _readjport();
  jstat = _manualdir(j);

  if (jstat)
    if (try)
      return j + 1;
    else
    {
      delay(1000);
      goto retry;
    }

  return JOY_NONE;
}

static unsigned char _loadcalib(const char *filename, const unsigned char njoy)
{
  /*
  ** Load calibration and returns:
  **
  ** JOY_NONE       if mode and joy # are correct and joys appear centered
  ** JOY_FIRST      if joy #1 must be re-calibrated
  ** JOY_SECOND     if joy #2 must be re-calibrated
  ** JOY_BOTH       if both joys need to be re-calibrated
  */

  if (filename != NULL)
  {
    int h, i, l;
    unsigned char oldnjoy;
    struct calibrecord {
      unsigned char njoy;
      unsigned char joymode;
      int calib[2][4];
    } cr;

    h = open(filename, O_RDONLY | O_BINARY, S_IREAD);

    /* File not found: re-calibration */
    if (h == -1)
      return njoy;

    /* Wrong size: remove file and force re-calibration */
    if (filelength(h) != sizeof(cr))
    {
      close(h);
      remove(filename);
      return njoy;
    }

    l = read(h, (void *) &cr, sizeof(cr)) != sizeof(cr);
    close(h);

    /* Error reading: re-calibration */
    if (l)
      return njoy;

    /* Mode incompatibility: re-calibration */
    if ((joymode == JOY_6BUTTONS && cr.joymode != JOY_6BUTTONS) ||
        (cr.joymode == JOY_6BUTTONS && joymode != JOY_6BUTTONS))
      return njoy;

    /* Different number of joysticks: re-calibration for only the new joystick */
    oldnjoy = njoy;
    for (i = 0; i < 2; i++)
      for (l = 0; l < 4; l++)
        calib[i][l] = cr.calib[i][l];

    if (oldnjoy != cr.njoy)
    {
      unsigned char t = 0;

      for (i = 1; i < 3; i++)
        if ((oldnjoy & i) && (cr.njoy & i))
          t |= _checkcalib(i - 1);
        else
          if (oldnjoy & i)
            t |= i;
      return t;
    }

    return JOY_NONE;
  }
  else
    return njoy;   /* NULL file specified: re-calibration */
}

/****************************************************************************/
/******************* External functions: joystick interface *****************/
/****************************************************************************/

unsigned char InstallJoystick(const unsigned char mode, const unsigned char skipjoy, const char *calibfile)
{
  /*
  ** This function checks and returns the number of installed joysticks.
  **
  ** 'mode' can be:
  **
  ** JOY_2BUTTONS   2-buttons joysticks (one or two)
  ** JOY_4BUTTONS   4-buttons joysticks (one or two)
  ** JOY_6BUTTONS   6-buttons joystick (only one)
  **
  ** 'skipjoy' can be:
  **
  ** JOY_NONE    all joysticks present are installed and calibrated
  ** JOY_FIRST   skip installation/calibration for first joystick
  ** JOY_SECOND  skip installation/calibration for second joystick
  **
  ** Most of the times, skipjoy will be JOY_NONE (all joysticks installed
  ** and calibrated) or JOY_SECOND (only first joystick is installed and
  ** calibrated, e.g. when your program uses just one joystick).
  **
  ** 'calibfile' is the name of the file from which calibration must be
  ** loaded (if exists) or to which it will be saved (if does NOT exist).
  ** If 'calibfile' is NULL, calibration won't be saved, i.e. the user will
  ** have to calibrate joystick(s) at each run.
  ** If 'mode' is JOY_2BUTTONS or JOY_4BUTTONS and mode determined from
  ** configuration file is JOY_6BUTTONS (or viceversa), calibration will be
  ** forced; the same will happen if number of joysticks connected is
  ** different or if the calibration appears incorrect.
  ** If calibration is aborted for one joystick, that joystick will be
  ** reported as not connected (it will be re-calibrated the next time you
  ** run the program).
  **
  ** Values returned
  ** JOY_NONE    if no joystick is installed
  ** JOY_FIRST   if only joystick 1 is installed
  ** JOY_SECOND  if only joystick 2 is installed
  ** JOY_BOTH    if both joysticks (or one 6-buttons joystick) are installed
  **
  ** Central values are set at current position.
  */

  register unsigned char retval = 0, j;
  unsigned char j2calib;

  joymode = mode;

  /* Determine joysticks attached */
  for (j = 0; j < 2; j++)
    if ((jready[j] = _joyready(j)) != 0)
      retval += j + 1;

  /* Revert to 4-buttons mode if 6-buttons joystick not found */
  if (joymode == JOY_6BUTTONS && retval < JOY_BOTH)
    joymode = JOY_4BUTTONS;

  /* Prompt the user to calibrate joystick(s) */
  j2calib = _loadcalib(calibfile, retval);
  for (j = 0; j < 2; j++)
  {
    if ((skipjoy & (j + 1)) || (jready[j] && (j2calib & (j + 1)) && !_usercalib(j)))
    {
      jready[j] = 0;
      retval -= j + 1;
    }

    /* No need to calibrate second (virtual) joystick when in 6-buttons mode */
    if (joymode == JOY_6BUTTONS)
      j = 2;
  }

  if (retval)
    _savecalib(calibfile, retval);

  return retval;
}

void ReadJoystick(unsigned int *first, unsigned int *second)
{
  /*
  ** Read both joysticks, returning into "first" and "second" an
  ** unsigned integer with the following flags set:
  **
  ** JOY_UP    Joystick moved up
  ** JOY_DN    Joystick moved down
  ** JOY_LT    Joystick moved to left
  ** JOY_RT    Joystick moved to right
  ** JOY_AF    Button 1 pressed
  ** JOY_BF    Button 2 pressed
  ** JOY_CF    Button 3 pressed (joymode = JOY_4BUTTONS or JOY_6BUTTONS)
  ** JOY_DF    Button 4 pressed (joymode = JOY_4BUTTONS or JOY_6BUTTONS)
  ** JOY_EF    Button 5 pressed (joymode = JOY_6BUTTONS)
  ** JOY_FF    Button 6 pressed (joymode = JOY_6BUTTONS)
  **
  ** If a NULL pointer is passed, no data is stored (useful if data
  ** for only one joystick are needed).
  */

  _readjoy();
  if (first)
    *first = jstatus[0];
  if (second)
    *second = jstatus[1];
}

⌨️ 快捷键说明

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