Revision: 45557
http://sourceforge.net/p/vice-emu/code/45557
Author: compyx
Date: 2025-03-22 08:53:03 +0000 (Sat, 22 Mar 2025)
Log Message:
-----------
Joystick: Windows: implement `poll()` driver method
Implement polling for the DirectInput driver. Might require having the driver
keep a private 'prev' value to avoid unnecessary callbacks to `joy_*_event()`
in the common joystick system, DirectInput isn't event driven, so we get a lot
of (unchanged) data when polling each scanline.
Modified Paths:
--------------
branches/compyx/joymap-001/vice/src/arch/gtk3/joystickdrv/joystick_win32_directinput.c
branches/compyx/joymap-001/vice/src/joyport/joystick.h
Modified: branches/compyx/joymap-001/vice/src/arch/gtk3/joystickdrv/joystick_win32_directinput.c
===================================================================
--- branches/compyx/joymap-001/vice/src/arch/gtk3/joystickdrv/joystick_win32_directinput.c 2025-03-22 04:39:53 UTC (rev 45556)
+++ branches/compyx/joymap-001/vice/src/arch/gtk3/joystickdrv/joystick_win32_directinput.c 2025-03-22 08:53:03 UTC (rev 45557)
@@ -440,7 +440,109 @@
static void win32_joy_poll(joystick_device_t *joydev)
{
- /* TODO */
+ joy_priv_t *priv;
+ DIJOYSTATE2 jstate;
+ /* map axis instance (dwType & 0xff) IDs to their position in the joystick
+ * state DIJOYSTATE2 struct: */
+ LONG *axis_map[] = {
+ &jstate.lX, &jstate.lY, &jstate.lZ,
+ &jstate.lRx, &jstate.lRy, &jstate.lRz,
+ &jstate.lVX, &jstate.lVY, &jstate.lVZ,
+ &jstate.lVRx, &jstate.lVRy, &jstate.lVRz,
+ &jstate.lAX, &jstate.lAY, &jstate.lAZ,
+ &jstate.lARx, &jstate.lARy, &jstate.lARz,
+ &jstate.lFX, &jstate.lFY, &jstate.lFZ,
+ &jstate.lFRx, &jstate.lFRy, &jstate.lFRz
+ };
+ int i;
+ HRESULT result;
+
+ /* poll device */
+ priv = joydev->priv;
+ result = IDirectInputDevice8_Poll(priv->didev);
+ if (result != DI_OK && result != DI_NOEFFECT) {
+ return;
+ }
+
+ /* get device state */
+ result = IDirectInputDevice8_GetDeviceState(priv->didev, sizeof(jstate), &jstate);
+ if (result != DI_OK) {
+ return;
+ }
+
+ /* handle buttons */
+ for (i = 0; i < joydev->num_buttons; i++) {
+ /* buttons are simply listed in sequence, starting at 0 */
+ joystick_button_t *button = joydev->buttons[i];
+ int32_t value = jstate.rgbButtons[i] & 0x80;
+
+ joy_button_event(joydev, button, value);
+ }
+
+ /* handle axes */
+ for (i = 0; i < joydev->num_axes; i++) {
+ joystick_axis_t *axis = joydev->axes[i];
+ uint32_t code = axis->code;
+
+ if (code < sizeof axis_map / sizeof axis_map[0]) {
+ int32_t minimum = axis->minimum;
+ int32_t maximum = axis->maximum;
+ int32_t range = maximum - minimum;
+ int32_t value = *(axis_map[code]);
+
+ //printf("axis %d raw value = %d\n", i, value);
+
+ if (value <= minimum + (range / 4)) {
+ joy_axis_event(joydev, axis, JOY_AXIS_NEGATIVE);
+ } else if (value >= maximum - (range / 4)) {
+ joy_axis_event(joydev, axis, JOY_AXIS_POSITIVE);
+ } else {
+ joy_axis_event(joydev, axis, JOY_AXIS_MIDDLE);
+ }
+ }
+ }
+
+ /* handle POVs */
+ for (i = 0; i < joydev->num_hats; i++) {
+ /* POVs are simply reported sequentially, so hat index is POV value index */
+ joystick_hat_t *hat = joydev->hats[i];
+ int32_t value = LOWORD(jstate.rgdwPOV[i]);
+ int32_t direction = JOYSTICK_DIRECTION_NONE; /* neutral */
+
+ /* POVs map to 360 degrees, in units of 1/100th of a degree, neutral
+ * is reported as -1 / 0xffffffff.
+ * Translate position on a circle to joystick directions, clockwise
+ * from North through to Northwest */
+ if (value < 0 || value >= 36000) {
+ /* invalid: report neutral position */
+ direction = JOYSTICK_DIRECTION_NONE;
+ } else if (value >= 33750 || value < 2250) {
+ /* North */
+ direction = JOYSTICK_DIRECTION_UP;
+ } else if (value >= 2250 && value < 6750) {
+ /* Northeast */
+ direction = JOYSTICK_DIRECTION_UP|JOYSTICK_DIRECTION_RIGHT;
+ } else if (value >= 6750 && value < 11250) {
+ /* East */
+ direction = JOYSTICK_DIRECTION_RIGHT;
+ } else if (value >= 11250 && value < 15750) {
+ /* Southeast */
+ direction = JOYSTICK_DIRECTION_DOWN|JOYSTICK_DIRECTION_RIGHT;
+ } else if (value >= 15750 && value < 20250) {
+ /* South */
+ direction = JOYSTICK_DIRECTION_DOWN;
+ } else if (value >= 20250 && value < 24750) {
+ /* Southwest */
+ direction = JOYSTICK_DIRECTION_DOWN|JOYSTICK_DIRECTION_LEFT;
+ } else if (value >= 24750 && value < 29250) {
+ /* West */
+ direction = JOYSTICK_DIRECTION_LEFT;
+ } else if (value >= 29250 && value < 33750) {
+ /* Northwest */
+ direction = JOYSTICK_DIRECTION_UP|JOYSTICK_DIRECTION_LEFT;
+ }
+ joy_hat_event(joydev, hat, direction);
+ }
}
/** \brief Close joystick device
@@ -521,13 +623,13 @@
axis = joystick_axis_new(lpddoi->tszName);
axis->code = DIDFT_GETINSTANCE(lpddoi->dwType);
- /* obtain logical range of axis */
+ /* obtain raw range of axis */
range.diph.dwSize = sizeof(DIPROPRANGE);
range.diph.dwHeaderSize = sizeof(DIPROPHEADER);
range.diph.dwObj = lpddoi->dwType;
range.diph.dwHow = DIPH_BYID;
result = IDirectInputDevice8_GetProperty(priv->didev,
- DIPROP_LOGICALRANGE,
+ DIPROP_RANGE,
&range.diph);
if (SUCCEEDED(result)) {
axis->minimum = range.lMin;
Modified: branches/compyx/joymap-001/vice/src/joyport/joystick.h
===================================================================
--- branches/compyx/joymap-001/vice/src/joyport/joystick.h 2025-03-22 04:39:53 UTC (rev 45556)
+++ branches/compyx/joymap-001/vice/src/joyport/joystick.h 2025-03-22 08:53:03 UTC (rev 45557)
@@ -36,6 +36,7 @@
#include "lib.h"
+#define JOYSTICK_DIRECTION_NONE 0
#define JOYSTICK_DIRECTION_UP 1
#define JOYSTICK_DIRECTION_DOWN 2
#define JOYSTICK_DIRECTION_LEFT 4
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|