Esempio n. 1
0
static void dinput_poll(void *data)
{
   struct dinput_input *di = (struct dinput_input*)data;

   memset(di->state, 0, sizeof(di->state));
   if (di->keyboard)
   {
      if (FAILED(IDirectInputDevice8_GetDeviceState(
                  di->keyboard, sizeof(di->state), di->state)))
      {
         IDirectInputDevice8_Acquire(di->keyboard);
         if (FAILED(IDirectInputDevice8_GetDeviceState(
                     di->keyboard, sizeof(di->state), di->state)))
            memset(di->state, 0, sizeof(di->state));
      }
   }

   if (di->mouse)
   {
      DIMOUSESTATE2 mouse_state;
      memset(&mouse_state, 0, sizeof(mouse_state));

      if (FAILED(IDirectInputDevice8_GetDeviceState(
                  di->mouse, sizeof(mouse_state), &mouse_state)))
      {
         IDirectInputDevice8_Acquire(di->mouse);
         if (FAILED(IDirectInputDevice8_GetDeviceState(
                     di->mouse, sizeof(mouse_state), &mouse_state)))
            memset(&mouse_state, 0, sizeof(mouse_state));
      }

      di->mouse_last_x = di->mouse_x;
      di->mouse_last_y = di->mouse_y;

      di->mouse_x = di->window_pos_x;
      di->mouse_y = di->window_pos_y;


	  if (!mouse_state.rgbButtons[0])
		  unset_doubleclick_on_titlebar();
      if (doubleclick_on_titlebar_pressed())
         di->mouse_l  = 0;
      else
         di->mouse_l  = mouse_state.rgbButtons[0];
      di->mouse_r     = mouse_state.rgbButtons[1];
      di->mouse_m     = mouse_state.rgbButtons[2];

      /* No simple way to get absolute coordinates
       * for RETRO_DEVICE_POINTER. Just use Win32 APIs. */
      POINT point = {0};
      GetCursorPos(&point);
      ScreenToClient((HWND)video_driver_window_get(), &point);
      di->mouse_x = point.x;
      di->mouse_y = point.y;
   }

   if (di->joypad)
      di->joypad->poll();
}
Esempio n. 2
0
static void dinput_poll(void *data)
{
   struct dinput_input *di = (struct dinput_input*)data;

   memset(di->state, 0, sizeof(di->state));
   if (di->keyboard)
   {
      if (FAILED(IDirectInputDevice8_GetDeviceState(
                  di->keyboard, sizeof(di->state), di->state)))
      {
         IDirectInputDevice8_Acquire(di->keyboard);
         if (FAILED(IDirectInputDevice8_GetDeviceState(
                     di->keyboard, sizeof(di->state), di->state)))
            memset(di->state, 0, sizeof(di->state));
      }
   }

   if (di->mouse)
   {
      DIMOUSESTATE2 mouse_state;
      memset(&mouse_state, 0, sizeof(mouse_state));

      if (FAILED(IDirectInputDevice8_GetDeviceState(
                  di->mouse, sizeof(mouse_state), &mouse_state)))
      {
         IDirectInputDevice8_Acquire(di->mouse);
         if (FAILED(IDirectInputDevice8_GetDeviceState(
                     di->mouse, sizeof(mouse_state), &mouse_state)))
            memset(&mouse_state, 0, sizeof(mouse_state));
      }

      di->mouse_rel_x = mouse_state.lX;
      di->mouse_rel_y = mouse_state.lY;
      di->mouse_l  = mouse_state.rgbButtons[0];
      di->mouse_r  = mouse_state.rgbButtons[1];
      di->mouse_m  = mouse_state.rgbButtons[2];
      di->mouse_wu = mouse_state.rgbButtons[3];
      di->mouse_wd = mouse_state.rgbButtons[4];

      /* No simple way to get absolute coordinates 
       * for RETRO_DEVICE_POINTER. Just use Win32 APIs. */
      POINT point = {0};
      GetCursorPos(&point);
      ScreenToClient((HWND)driver.video_window, &point);
      di->mouse_x = point.x;
      di->mouse_y = point.y;
   }

   if (di->joypad)
      di->joypad->poll();
}
Esempio n. 3
0
static void dinput_joypad_poll(void)
{
    unsigned i;
    for (i = 0; i < MAX_USERS; i++)
    {
        struct dinput_joypad *pad = &g_pads[i];
        bool polled = g_xinput_pad_indexes[i] < 0;

        if (!pad || !pad->joypad || !polled)
            continue;

        memset(&pad->joy_state, 0, sizeof(pad->joy_state));

        if (FAILED(IDirectInputDevice8_Poll(pad->joypad)))
        {
            if (FAILED(IDirectInputDevice8_Acquire(pad->joypad)))
            {
                memset(&pad->joy_state, 0, sizeof(DIJOYSTATE2));
                continue;
            }

            /* If this fails, something *really* bad must have happened. */
            if (FAILED(IDirectInputDevice8_Poll(pad->joypad)))
            {
                memset(&pad->joy_state, 0, sizeof(DIJOYSTATE2));
                continue;
            }
        }

        IDirectInputDevice8_GetDeviceState(pad->joypad,
                                           sizeof(DIJOYSTATE2), &pad->joy_state);
    }
}
Esempio n. 4
0
static void dinput_joypad_poll(void)
{
   for (unsigned i = 0; i < MAX_PLAYERS; i++)
   {
      struct dinput_joypad *pad = &g_pads[i];

      if ((pad->joypad) && (g_xbox_pad_indexes[i] == -1))
      {
         memset(&pad->joy_state, 0, sizeof(pad->joy_state));

         if (FAILED(IDirectInputDevice8_Poll(pad->joypad)))
         {
            if (FAILED(IDirectInputDevice8_Acquire(pad->joypad)))
            {
               memset(&pad->joy_state, 0, sizeof(DIJOYSTATE2));
               continue;
            }

            // If this fails, something *really* bad must have happened.
            if (FAILED(IDirectInputDevice8_Poll(pad->joypad)))
            {
               memset(&pad->joy_state, 0, sizeof(DIJOYSTATE2));
               continue;
            }
         }

         IDirectInputDevice8_GetDeviceState(pad->joypad,
               sizeof(DIJOYSTATE2), &pad->joy_state);
      }
   }
}
Esempio n. 5
0
static HRESULT Poll(IDirectInputDevice8A * joystick, DIJOYSTATE * state)
{
    HRESULT hr;

    hr = IDirectInputDevice8_Poll(joystick);

    /* Try to acquire the joystick */
    if (FAILED(hr)) {

        hr = IDirectInputDevice8_Acquire(joystick);

        while (hr == DIERR_INPUTLOST)
            hr = IDirectInputDevice8_Acquire(joystick);

        if (hr == DIERR_INVALIDPARAM || hr == DIERR_NOTINITIALIZED)
            return E_FAIL;

        if (hr == DIERR_OTHERAPPHASPRIO)
            return S_OK;
    }

    hr = IDirectInputDevice8_GetDeviceState(joystick, sizeof(DIJOYSTATE),
                                            state);

    /* Should not fail, the device has just been acquired */
    if (FAILED(hr))
        return hr;

    return S_OK;
}
JNIEXPORT jint JNICALL Java_net_java_games_input_IDirectInputDevice_nGetDeviceState(JNIEnv *env, jclass unused, jlong address, jintArray device_state_array) {
    LPDIRECTINPUTDEVICE8 lpDevice = (LPDIRECTINPUTDEVICE8)(INT_PTR)address;
	jsize state_length = (*env)->GetArrayLength(env, device_state_array);
	DWORD state_size = state_length*sizeof(jint);
	HRESULT res;
	jint *device_state = (*env)->GetIntArrayElements(env, device_state_array, NULL);
	if (device_state == NULL)
		return -1;

	res = IDirectInputDevice8_GetDeviceState(lpDevice, state_size, device_state);
	(*env)->ReleaseIntArrayElements(env, device_state_array, device_state, 0);
	return res;
}
Esempio n. 7
0
static void poll_input(const struct Joystick *joy, DIJOYSTATE *state)
{
    HRESULT  hr;

    hr = IDirectInputDevice8_Poll(joy->device);

    /* If it failed, try to acquire the joystick */
    if (FAILED(hr))
    {
        hr = IDirectInputDevice8_Acquire(joy->device);
        while (hr == DIERR_INPUTLOST) hr = IDirectInputDevice8_Acquire(joy->device);
    }

    if (hr == DIERR_OTHERAPPHASPRIO) return;

    IDirectInputDevice8_GetDeviceState(joy->device, sizeof(DIJOYSTATE), state);
}
Esempio n. 8
0
/* Function to update the state of a joystick - called as a device poll.
 * This function shouldn't update the joystick structure directly,
 * but instead should call SDL_PrivateJoystick*() to deliver events
 * and update joystick device state.
 */
static void
UpdateDINPUTJoystickState_Polled(SDL_Joystick * joystick)
{
    DIJOYSTATE2 state;
    HRESULT result;
    int i;

    result =
        IDirectInputDevice8_GetDeviceState(joystick->hwdata->InputDevice,
        sizeof(DIJOYSTATE2), &state);
    if (result == DIERR_INPUTLOST || result == DIERR_NOTACQUIRED) {
        IDirectInputDevice8_Acquire(joystick->hwdata->InputDevice);
        result =
            IDirectInputDevice8_GetDeviceState(joystick->hwdata->InputDevice,
            sizeof(DIJOYSTATE2), &state);
    }

    if (result != DI_OK) {
        joystick->hwdata->send_remove_event = SDL_TRUE;
        joystick->hwdata->removed = SDL_TRUE;
        return;
    }

    /* Set each known axis, button and POV. */
    for (i = 0; i < joystick->hwdata->NumInputs; ++i) {
        const input_t *in = &joystick->hwdata->Inputs[i];

        switch (in->type) {
        case AXIS:
            switch (in->ofs) {
            case DIJOFS_X:
                SDL_PrivateJoystickAxis(joystick, in->num, (Sint16)state.lX);
                break;
            case DIJOFS_Y:
                SDL_PrivateJoystickAxis(joystick, in->num, (Sint16)state.lY);
                break;
            case DIJOFS_Z:
                SDL_PrivateJoystickAxis(joystick, in->num, (Sint16)state.lZ);
                break;
            case DIJOFS_RX:
                SDL_PrivateJoystickAxis(joystick, in->num, (Sint16)state.lRx);
                break;
            case DIJOFS_RY:
                SDL_PrivateJoystickAxis(joystick, in->num, (Sint16)state.lRy);
                break;
            case DIJOFS_RZ:
                SDL_PrivateJoystickAxis(joystick, in->num, (Sint16)state.lRz);
                break;
            case DIJOFS_SLIDER(0):
                SDL_PrivateJoystickAxis(joystick, in->num, (Sint16)state.rglSlider[0]);
                break;
            case DIJOFS_SLIDER(1):
                SDL_PrivateJoystickAxis(joystick, in->num, (Sint16)state.rglSlider[1]);
                break;
            }
            break;

        case BUTTON:
            SDL_PrivateJoystickButton(joystick, in->num,
                (Uint8)(state.rgbButtons[in->ofs - DIJOFS_BUTTON0] ? SDL_PRESSED : SDL_RELEASED));
            break;
        case HAT:
        {
            Uint8 pos = TranslatePOV(state.rgdwPOV[in->ofs - DIJOFS_POV(0)]);
            SDL_PrivateJoystickHat(joystick, in->num, pos);
            break;
        }
        }
    }
}
Esempio n. 9
0
static gboolean
dx_dinput_setup_events (ControllerDXDInput *controller,
                        GError            **error)
{
  HRESULT         hresult;
  DIPROPDWORD     dword;
  gint            i, k;
  DXDInputSource *source;

  if ((controller->event = CreateEvent (NULL, TRUE, FALSE, NULL)) == NULL)
    {
      g_set_error (error, GIMP_MODULE_ERROR, GIMP_MODULE_FAILED,
                   "CreateEvent failed: %s",
                   g_win32_error_message (GetLastError ()));
      return FALSE;
    }

  controller->format = g_new (DIDATAFORMAT, 1);
  controller->format->dwSize = sizeof (DIDATAFORMAT);
  controller->format->dwObjSize = sizeof (DIOBJECTDATAFORMAT);

  dword.diph.dwSize = sizeof (DIPROPDWORD);
  dword.diph.dwHeaderSize = sizeof (DIPROPHEADER);
  dword.diph.dwObj = 0;
  dword.diph.dwHow = DIPH_DEVICE;

  /* Get the axis mode so we can use the same in the format */
  if (FAILED ((hresult = IDirectInputDevice8_GetProperty (controller->didevice8,
                                                          DIPROP_AXISMODE,
                                                          &dword.diph))))
    {
      g_set_error (error, GIMP_MODULE_ERROR, GIMP_MODULE_FAILED,
                   "IDirectInputDevice8::GetParameters failed: %s",
                   g_win32_error_message (hresult));
      goto fail0;
    }

  controller->format->dwFlags = dword.dwData + 1;

  controller->format->dwNumObjs =
    controller->num_buttons +
    controller->num_axes +
    controller->num_sliders +
    controller->num_povs;

  controller->format->rgodf = g_new (DIOBJECTDATAFORMAT, controller->format->dwNumObjs);

  k = 0;
  controller->format->dwDataSize = 0;

  for (i = 0; i < controller->num_buttons; i++)
    {
      controller->format->rgodf[k].pguid = NULL;
      controller->format->rgodf[k].dwOfs = controller->format->dwDataSize;
      controller->format->rgodf[k].dwType = DIDFT_BUTTON | DIDFT_MAKEINSTANCE (i);
      controller->format->rgodf[k].dwFlags = 0;
      controller->format->dwDataSize += 1;
      k++;
    }

  controller->format->dwDataSize = 4*((controller->format->dwDataSize + 3)/4);

  for (i = 0; i < controller->num_axes; i++)
    {
      controller->format->rgodf[k].pguid = NULL;
      controller->format->rgodf[k].dwOfs = controller->format->dwDataSize;
      controller->format->rgodf[k].dwType = DIDFT_AXIS | DIDFT_MAKEINSTANCE (i);
      controller->format->rgodf[k].dwFlags = DIDOI_ASPECTPOSITION;
      controller->format->dwDataSize += 4;
      k++;
    }

  for (i = 0; i < controller->num_sliders; i++)
    {
      controller->format->rgodf[k].pguid = NULL;
      controller->format->rgodf[k].dwOfs = controller->format->dwDataSize;
      controller->format->rgodf[k].dwType = DIDFT_AXIS | DIDFT_MAKEINSTANCE (i);
      controller->format->rgodf[k].dwFlags = DIDOI_ASPECTPOSITION;
      controller->format->dwDataSize += 4;
      k++;
    }

  for (i = 0; i < controller->num_povs; i++)
    {
      controller->format->rgodf[k].pguid = NULL;
      controller->format->rgodf[k].dwOfs = controller->format->dwDataSize;
      controller->format->rgodf[k].dwType = DIDFT_POV | DIDFT_MAKEINSTANCE (i);
      controller->format->rgodf[k].dwFlags = 0;
      controller->format->dwDataSize += 4;
      k++;
    }

  g_assert (k == controller->format->dwNumObjs);

  controller->format->dwDataSize = 4*((controller->format->dwDataSize + 3)/4);
  controller->prevdata = g_malloc (controller->format->dwDataSize);

  dump_data_format (controller->format);

  if (FAILED ((hresult = IDirectInputDevice8_SetDataFormat (controller->didevice8,
                                                            controller->format))))
    {
      g_set_error (error, GIMP_MODULE_ERROR, GIMP_MODULE_FAILED,
                   "IDirectInputDevice8::SetDataFormat failed: %s",
                   g_win32_error_message (hresult));
      goto fail1;
    }

  if (FAILED ((hresult = IDirectInputDevice8_SetEventNotification (controller->didevice8,
                                                                   controller->event))))
    {
      g_set_error (error, GIMP_MODULE_ERROR, GIMP_MODULE_FAILED,
                   "IDirectInputDevice8::SetEventNotification failed: %s",
                   g_win32_error_message (hresult));
      goto fail2;
    }

  if (FAILED ((hresult = IDirectInputDevice8_Acquire (controller->didevice8))))
    {
      g_set_error (error, GIMP_MODULE_ERROR, GIMP_MODULE_FAILED,
                   "IDirectInputDevice8::Acquire failed: %s",
                   g_win32_error_message (hresult));
      goto fail2;
    }

  if (FAILED ((hresult = IDirectInputDevice8_GetDeviceState (controller->didevice8,
                                                             controller->format->dwDataSize,
                                                             controller->prevdata))))
    {
      g_set_error (error, GIMP_MODULE_ERROR, GIMP_MODULE_FAILED,
                   "IDirectInputDevice8::GetDeviceState failed: %s",
                   g_win32_error_message (hresult));
      goto fail2;
    }

  source = (DXDInputSource *) g_source_new (&dx_dinput_event_funcs,
                                            sizeof (DXDInputSource));
  source->controller = controller;
  controller->source = (GSource *) source;

  controller->pollfd = g_new (GPollFD, 1);

  controller->pollfd->fd = (int) controller->event;
  controller->pollfd->events = G_IO_IN;

  g_source_add_poll (&source->source, controller->pollfd);
  g_source_attach (&source->source, NULL);

  return TRUE;

 fail2:
  IDirectInputDevice8_SetEventNotification (controller->didevice8, NULL);
 fail1:
  g_free (controller->format->rgodf);
  g_free (controller->format);
  controller->format = NULL;
  g_free (controller->prevdata);
  controller->prevdata = NULL;
 fail0:
  CloseHandle (controller->event);
  controller->event = 0;

  return FALSE;
}
Esempio n. 10
0
static gboolean
dx_dinput_event_dispatch (GSource     *source,
                          GSourceFunc  callback,
                          gpointer     user_data)
{
  ControllerDXDInput * const       input = ((DXDInputSource *) source)->controller;
  GimpController                  *controller = &input->parent_instance;
  const DIDATAFORMAT * const       format = input->format;
  const DIOBJECTDATAFORMAT        *rgodf = format->rgodf;
  guchar                          *data;
  gint                             i;
  GimpControllerEvent              cevent = { 0, };

  data = g_alloca (format->dwDataSize);

  if (FAILED (IDirectInputDevice8_GetDeviceState (input->didevice8,
                                                  format->dwDataSize,
                                                  data)))
    {
      return TRUE;
    }

  g_object_ref (controller);

  for (i = 0; i < input->num_buttons; i++)
    {
      if (input->prevdata[rgodf->dwOfs] != data[rgodf->dwOfs])
        {
          if (data[rgodf->dwOfs] & 0x80)
            {
              /* Click event, compatibility with Linux Input */
              cevent.any.type = GIMP_CONTROLLER_EVENT_TRIGGER;
              cevent.any.source = controller;
              cevent.any.event_id = i*NUM_EVENTS_PER_BUTTON;
              gimp_controller_event (controller, &cevent);

              /* Press event */
              cevent.any.event_id = i*NUM_EVENTS_PER_BUTTON + 1;
              gimp_controller_event (controller, &cevent);
            }
          else
            {
              /* Release event */
              cevent.any.type = GIMP_CONTROLLER_EVENT_TRIGGER;
              cevent.any.source = controller;
              cevent.any.event_id = i*NUM_EVENTS_PER_BUTTON + 2;
              gimp_controller_event (controller, &cevent);
            }
        }
      rgodf++;
    }

  for (i = 0; i < input->num_axes; i++)
    {
      LONG *prev = (LONG *)(input->prevdata+rgodf->dwOfs);
      LONG *curr = (LONG *)(data+rgodf->dwOfs);

      if (ABS (*prev - *curr) > 1)
        {
          cevent.any.type = GIMP_CONTROLLER_EVENT_VALUE;
          cevent.any.source = controller;
          cevent.any.event_id =
            input->num_button_events +
            i*NUM_EVENTS_PER_AXIS;
          g_value_init (&cevent.value.value, G_TYPE_DOUBLE);
          if (*curr - *prev < 0)
            {
              g_value_set_double (&cevent.value.value, *prev - *curr);
            }
          else
            {
              cevent.any.event_id++;
              g_value_set_double (&cevent.value.value, *curr - *prev);
            }
          gimp_controller_event (controller, &cevent);
          g_value_unset (&cevent.value.value);
        }
      else
        *curr = *prev;
      rgodf++;
    }

  for (i = 0; i < input->num_sliders; i++)
    {
      LONG *prev = (LONG *)(input->prevdata+rgodf->dwOfs);
      LONG *curr = (LONG *)(data+rgodf->dwOfs);

      if (ABS (*prev - *curr) > 1)
        {
          cevent.any.type = GIMP_CONTROLLER_EVENT_VALUE;
          cevent.any.source = controller;
          cevent.any.event_id =
            input->num_button_events +
            input->num_axis_events +
            i*NUM_EVENTS_PER_SLIDER;
          g_value_init (&cevent.value.value, G_TYPE_DOUBLE);
          if (*curr - *prev < 0)
            {
              g_value_set_double (&cevent.value.value, *prev - *curr);
            }
          else
            {
              cevent.any.event_id++;
              g_value_set_double (&cevent.value.value, *curr - *prev);
            }
          gimp_controller_event (controller, &cevent);
          g_value_unset (&cevent.value.value);
        }
      else
        *curr = *prev;
      rgodf++;
    }

  for (i = 0; i < input->num_povs; i++)
    {
      LONG prev = *((LONG *)(input->prevdata+rgodf->dwOfs));
      LONG curr = *((LONG *)(data+rgodf->dwOfs));
      double prevx, prevy;
      double currx, curry;

      if (prev != curr)
        {
          if (prev == -1)
            {
              prevx = 0.;
              prevy = 0.;
            }
          else
            {
              prevx = sin (prev/36000.*2.*G_PI);
              prevy = cos (prev/36000.*2.*G_PI);
            }
          if (curr == -1)
            {
              currx = 0.;
              curry = 0.;
            }
          else
            {
              currx = sin (curr/36000.*2.*G_PI);
              curry = cos (curr/36000.*2.*G_PI);
            }

          cevent.any.type = GIMP_CONTROLLER_EVENT_VALUE;
          cevent.any.source = controller;
          cevent.any.event_id =
            input->num_button_events +
            input->num_axis_events +
            input->num_slider_events +
            i*NUM_EVENTS_PER_POV;
          g_value_init (&cevent.value.value, G_TYPE_DOUBLE);
          g_value_set_double (&cevent.value.value, currx - prevx);
          gimp_controller_event (controller, &cevent);
          cevent.any.event_id++;
          g_value_set_double (&cevent.value.value, curry - prevy);
          gimp_controller_event (controller, &cevent);
          g_value_unset (&cevent.value.value);
          if (curr == -1)
            {
              cevent.any.type = GIMP_CONTROLLER_EVENT_TRIGGER;
              cevent.any.event_id++;
              gimp_controller_event (controller, &cevent);
            }
        }
      rgodf++;
    }

  g_assert (rgodf == format->rgodf + format->dwNumObjs);

  memmove (input->prevdata, data, format->dwDataSize);

  g_object_unref (controller);

  return TRUE;
}
Esempio n. 11
0
void I_GetJoystickState(joystate_t *state)
{
    static BOOL     oldButtons[IJOY_MAXBUTTONS]; // Thats a lot of buttons.

    DWORD           tries, i;
    DIJOYSTATE      dijoy;
    BOOL            acquired;
    HRESULT         hr;

    memset(state, 0, sizeof(*state));

    // Initialization has not been done.
    if(!didJoy || !usejoystick || !initIOk)
        return;

    // Some joysticks need to be polled.
    IDirectInputDevice8_Poll(didJoy);

    tries = 1;
    acquired = FALSE;
    while(!acquired && tries > 0)
    {
        hr = IDirectInputDevice8_GetDeviceState(didJoy, sizeof(dijoy), &dijoy);

        if(SUCCEEDED(hr))
        {
            acquired = TRUE;
        }
        else if(tries > 0)
        {
            // Try to reacquire.
            IDirectInputDevice8_Acquire(didJoy);
            tries--;
        }
    }

    if(!acquired)
        return; // The operation is a failure.

    state->numAxes = 8;
    state->axis[0] = (int) dijoy.lX;
    state->axis[1] = (int) dijoy.lY;
    state->axis[2] = (int) dijoy.lZ;
    state->axis[3] = (int) dijoy.lRx;
    state->axis[4] = (int) dijoy.lRy;
    state->axis[5] = (int) dijoy.lRz;
    state->axis[6] = (int) dijoy.rglSlider[0];
    state->axis[7] = (int) dijoy.rglSlider[1];

    state->numButtons = 32;
    for(i = 0; i < IJOY_MAXBUTTONS; ++i)
    {
        BOOL            isDown = (dijoy.rgbButtons[i] & 0x80? TRUE : FALSE);

        state->buttonDowns[i] =
            state->buttonUps[i] = 0;
        if(isDown && !oldButtons[i])
            state->buttonDowns[i] = 1;
        else if(!isDown && oldButtons[i])
            state->buttonUps[i] = 1;

        oldButtons[i] = isDown;
    }

    state->numHats = 4;
    for(i = 0; i < IJOY_MAXHATS; ++i)
    {
        DWORD           pov = dijoy.rgdwPOV[i];

        if((pov & 0xffff) == 0xffff)
            state->hatAngle[i] = IJOY_POV_CENTER;
        else
            state->hatAngle[i] = pov / 100.0f;
    }
}