Files
NX2navi/runtime/input_ds3.c
FemOrWhat 844940c6fb Add DualShock 3 support on Windows, read straight from the controller when no driver presents it, off by default.
runtime/input_ds3_win.c finds a DualShock 3 through hid.dll and setupapi (loaded at run time), sends it the command
that makes it report, sets its first player light and decodes its reports (runtime/input_ds3.c, tested by
tests/ds3_check) into the pad state, with rumble through its light motor. input.c follows whichever pad was pressed
last when an SDL pad is connected too. ds3 = 1 in nx2navi.ini turns it on: it starts a scan for the controller every
three seconds and opens it read-write, so it stays off unless a player asks for it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-09 08:21:07 -05:00

43 lines
2.0 KiB
C

// The DualShock 3's report formats, free of any operating system (input_ds3.h): the input report to inputs by position
// and the output report that drives the motors and the player light. tests/ds3_check.c checks both; input_ds3_win.c
// moves the reports.
#include <string.h>
#include "input_ds3.h"
int ds3_decode(const uint8_t *r, unsigned n, uint8_t pd[PAD_COUNT], int32_t raw[4]) {
if (n < 10 || r[0] != 0x01) return 0;
uint8_t b1 = r[2], b2 = r[3];
memset(pd, 0, PAD_COUNT);
pd[PAD_BACK] = (b1 & 0x01) != 0, pd[PAD_LSTICK] = (b1 & 0x02) != 0, pd[PAD_RSTICK] = (b1 & 0x04) != 0;
pd[PAD_START] = (b1 & 0x08) != 0;
pd[PAD_DPAD_UP] = (b1 & 0x10) != 0, pd[PAD_DPAD_RIGHT] = (b1 & 0x20) != 0;
pd[PAD_DPAD_DOWN] = (b1 & 0x40) != 0, pd[PAD_DPAD_LEFT] = (b1 & 0x80) != 0;
pd[PAD_L] = (b2 & 0x04) != 0, pd[PAD_R] = (b2 & 0x08) != 0;
pd[PAD_NORTH] = (b2 & 0x10) != 0, pd[PAD_EAST] = (b2 & 0x20) != 0; // triangle, circle
pd[PAD_SOUTH] = (b2 & 0x40) != 0, pd[PAD_WEST] = (b2 & 0x80) != 0; // cross, square
// The triggers go by pressure, as an XInput trigger does; a report without it (n < 20) has the switch only
unsigned l2 = n > 19 ? r[18] : 0, r2 = n > 19 ? r[19] : 0;
pd[PAD_ZL] = l2 ? l2 > DS3_TRIGGER_ON : (b2 & 0x01) != 0;
pd[PAD_ZR] = r2 ? r2 > DS3_TRIGGER_ON : (b2 & 0x02) != 0;
for (int i = 0; i < 4; i++) {
int d = (int)r[6 + i] - 128;
int v = d >= 0 ? d * 32767 / 127 : d * 32767 / 128;
raw[i] = i & 1 ? -v : v; // y: the controller's grows downwards, the game's upwards
}
return 1;
}
void ds3_output_report(uint8_t *o, unsigned n, int left, int right, unsigned dur, int led) {
memset(o, 0, n);
if (n < 36) return;
o[0] = 0x01;
o[2] = (uint8_t)dur, o[3] = (uint8_t)(right != 0);
o[4] = (uint8_t)dur, o[5] = (uint8_t)left;
o[10] = (uint8_t)(led << 1);
for (int i = 0; i < 4; i++) { // the four lights' blink timing: steady
uint8_t *l = o + 11 + 5 * i;
l[0] = 0xFF, l[1] = 0x27, l[2] = 0x10, l[3] = 0x00, l[4] = 0x32;
}
}