summaryrefslogtreecommitdiffhomepage
path: root/dinput/win32-joystick.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'dinput/win32-joystick.cpp')
-rw-r--r--dinput/win32-joystick.cpp113
1 files changed, 77 insertions, 36 deletions
diff --git a/dinput/win32-joystick.cpp b/dinput/win32-joystick.cpp
index f954a44e..4adf512d 100644
--- a/dinput/win32-joystick.cpp
+++ b/dinput/win32-joystick.cpp
@@ -11,6 +11,10 @@
#include <QDebug>
+// XXX how many axis update events can we reasonably get in a short time frame?
+enum { num_buffers = 256 };
+DIDEVICEOBJECTDATA win32_joy_ctx::joy::keystate_buffers[num_buffers];
+
QMutex win32_joy_ctx::enum_state::mtx;
win32_joy_ctx::enum_state win32_joy_ctx::enumerator;
@@ -163,59 +167,80 @@ bool win32_joy_ctx::joy::poll(fn f)
return false;
}
- DIJOYSTATE2 js;
- std::memset(&js, 0, sizeof(js));
-
- if (FAILED(hr = joy_handle->GetDeviceState(sizeof(js), &js)))
+ DWORD sz = num_buffers;
+ if (FAILED(hr = joy_handle->GetDeviceData(sizeof(DIDEVICEOBJECTDATA), keystate_buffers, &sz, 0)))
{
//qDebug() << "joy get state failed" << guid << hr;
return false;
}
- for (unsigned i = 0; i < 4; i++)
+ for (unsigned k = 0; k < sz; k++)
{
- using std::round;
-
- unsigned char pos;
- unsigned pos_ = js.rgdwPOV[i];
- if ((pos_ & 0xffff) == 0xffff)
- pos = 0;
- else if (pos_ == ~0u)
- pos = 0;
- else
+ const DIDEVICEOBJECTDATA& event = keystate_buffers[k];
+
+ bool is_pov = false;
+ int i = -1;
+
+ switch (event.dwOfs)
{
- using uc = unsigned char;
- pos = uc(((pos_ / 9000u) % 4u) + 1u);
+ case DIJOFS_POV(0): i = 0, is_pov = true; break;
+ case DIJOFS_POV(2): i = 1, is_pov = true; break;
+ case DIJOFS_POV(3): i = 2, is_pov = true; break;
+ case DIJOFS_POV(4): i = 3, is_pov = true; break;
+ default:
+ if (event.dwOfs >= DIJOFS_BUTTON0 && event.dwOfs <= DIJOFS_BUTTON(127))
+ {
+ unsigned tmp = event.dwOfs;
+ tmp -= DIJOFS_BUTTON0;
+ tmp /= DIJOFS_BUTTON1 - DIJOFS_BUTTON0;
+ tmp &= 127;
+ i = tmp;
+ }
+ break;
}
- const bool state[] =
+ if (is_pov)
{
- pos == 1,
- pos == 2,
- pos == 3,
- pos == 4
- };
+ //qDebug() << "DBG: pov" << i << event.dwData;
- unsigned idx = 128u + i * 4u;
+ using std::round;
- for (unsigned j = 0; j < 4; j++, idx++)
- {
- if (state[j] != pressed[idx])
+ unsigned char pos;
+ unsigned pos_ = event.dwData;
+ if ((pos_ & 0xffff) == 0xffff)
+ pos = 0;
+ else if (pos_ == ~0u)
+ pos = 0;
+ else
{
- f(guid, int(idx), state[j]);
- pressed[idx] = state[j];
+ using uc = unsigned char;
+ pos = uc(((pos_ / 9000u) % 4u) + 1u);
}
- }
- }
- for (int i = 0; i < 128; i++)
- {
- const bool state = !!(js.rgbButtons[i] & 0x80);
- if (state != pressed[i])
+ const bool state[] =
+ {
+ pos == 1,
+ pos == 2,
+ pos == 3,
+ pos == 4
+ };
+
+ i = 128u + i * 4u;
+
+ for (unsigned j = 0; j < 4; j++)
+ {
+ //pressed[i] = state[j];
+ f(guid, i, state[j]);
+ }
+ }
+ else if (i != -1)
{
+ const bool state = !!(event.dwData & 0x80);
+ //qDebug() << "DBG: btn" << i << state;
+ //pressed[i] = state;
f(guid, i, state);
}
- pressed[i] = state;
+
}
return true;
@@ -305,6 +330,23 @@ BOOL CALLBACK win32_joy_ctx::enum_state::EnumJoysticksCallback(const DIDEVICEINS
h->Release();
goto end;
}
+
+ {
+ DIPROPDWORD dipdw;
+ dipdw.dwData = 128;
+ dipdw.diph.dwHeaderSize = sizeof(dipdw.diph);
+ dipdw.diph.dwHow = DIPH_DEVICE;
+ dipdw.diph.dwObj = 0;
+ dipdw.diph.dwSize = sizeof(dipdw);
+
+ if (h->SetProperty(DIPROP_BUFFERSIZE, &dipdw.diph) != DI_OK)
+ {
+ qDebug() << "setup joystick buffer mode failed!";
+ h->Release();
+ goto end;
+ }
+ }
+
if (FAILED(hr = h->EnumObjects(EnumObjectsCallback, h, DIDFT_ALL)))
{
qDebug() << "enum-objects";
@@ -347,7 +389,6 @@ win32_joy_ctx::joy::joy(LPDIRECTINPUTDEVICE8 handle, const QString &guid, const
: joy_handle(handle), guid(guid), name(name)
{
//qDebug() << "make joy" << guid << name << joy_handle;
- std::memset(pressed, 0, sizeof(pressed));
}
win32_joy_ctx::joy::~joy()