Skip to content

Commit e3431a0

Browse files
ivyljulliard
authored andcommitted
winebus.sys: Use 4 bits for hat switches.
Declaring them as 8 bits crashes game due to how Unity's native hid support parses the data.
1 parent 94a7b32 commit e3431a0

File tree

1 file changed

+50
-24
lines changed

1 file changed

+50
-24
lines changed

dlls/winebus.sys/hid.c

+50-24
Original file line numberDiff line numberDiff line change
@@ -209,13 +209,14 @@ static BOOL hid_device_add_hatswitch_count(struct unix_device *iface, BYTE count
209209
ERR("hatswitches should be added before buttons!\n");
210210
else if ((iface->hid_device_state.bit_size % 8))
211211
ERR("hatswitches should be byte aligned, missing padding!\n");
212-
else if (iface->hid_device_state.bit_size + 8 * count > 0x80000)
212+
else if (iface->hid_device_state.bit_size + 4 * (count + 1) > 0x80000)
213213
ERR("report size overflow, too many elements!\n");
214214
else
215215
{
216216
if (!iface->hid_device_state.hatswitch_count) iface->hid_device_state.hatswitch_start = offset;
217217
iface->hid_device_state.hatswitch_count += count;
218-
iface->hid_device_state.bit_size += 8 * count;
218+
iface->hid_device_state.bit_size += 4 * count;
219+
if (count % 2) iface->hid_device_state.bit_size += 4;
219220
return TRUE;
220221
}
221222

@@ -231,16 +232,28 @@ BOOL hid_device_add_hatswitch(struct unix_device *iface, INT count)
231232
USAGE(1, HID_USAGE_GENERIC_HATSWITCH),
232233
LOGICAL_MINIMUM(1, 1),
233234
LOGICAL_MAXIMUM(1, 8),
234-
REPORT_SIZE(1, 8),
235+
REPORT_SIZE(1, 4),
235236
REPORT_COUNT(4, count),
236237
UNIT(1, 0x0), /* None */
237238
INPUT(1, Data|Var|Abs|Null),
238239
};
240+
const BYTE template_pad[] =
241+
{
242+
REPORT_COUNT(1, 4),
243+
REPORT_SIZE(1, 1),
244+
INPUT(1, Cnst|Ary|Abs),
245+
};
239246

240247
if (!hid_device_add_hatswitch_count(iface, count))
241248
return FALSE;
242249

243-
return hid_report_descriptor_append(desc, template, sizeof(template));
250+
if (!hid_report_descriptor_append(desc, template, sizeof(template)))
251+
return FALSE;
252+
253+
if ((count % 2) && !hid_report_descriptor_append(desc, template_pad, sizeof(template_pad)))
254+
return FALSE;
255+
256+
return TRUE;
244257
}
245258

246259
static BOOL hid_device_add_axis_count(struct unix_device *iface, BOOL rel, BYTE count,
@@ -1409,58 +1422,71 @@ BOOL hid_device_set_button(struct unix_device *iface, ULONG index, BOOL is_set)
14091422
* +1 | 6 5 4
14101423
* v
14111424
*/
1412-
static void hatswitch_decompose(BYTE value, LONG *x, LONG *y)
1425+
static void hatswitch_decompose(BYTE value, ULONG index, LONG *x, LONG *y)
14131426
{
1427+
value = (index % 2) ? (value >> 4) : (value & 0x0f);
14141428
*x = *y = 0;
14151429
if (value == 8 || value == 1 || value == 2) *y = -1;
14161430
if (value == 6 || value == 5 || value == 4) *y = +1;
14171431
if (value == 8 || value == 7 || value == 6) *x = -1;
14181432
if (value == 2 || value == 3 || value == 4) *x = +1;
14191433
}
14201434

1421-
static void hatswitch_compose(LONG x, LONG y, BYTE *value)
1435+
static void hatswitch_compose(LONG x, LONG y, BYTE *value, ULONG index)
14221436
{
1423-
if (x == 0 && y == 0) *value = 0;
1424-
else if (x == 0 && y < 0) *value = 1;
1425-
else if (x > 0 && y < 0) *value = 2;
1426-
else if (x > 0 && y == 0) *value = 3;
1427-
else if (x > 0 && y > 0) *value = 4;
1428-
else if (x == 0 && y > 0) *value = 5;
1429-
else if (x < 0 && y > 0) *value = 6;
1430-
else if (x < 0 && y == 0) *value = 7;
1431-
else if (x < 0 && y < 0) *value = 8;
1437+
BYTE new_value = 0;
1438+
if (x == 0 && y == 0) new_value = 0;
1439+
else if (x == 0 && y < 0) new_value = 1;
1440+
else if (x > 0 && y < 0) new_value = 2;
1441+
else if (x > 0 && y == 0) new_value = 3;
1442+
else if (x > 0 && y > 0) new_value = 4;
1443+
else if (x == 0 && y > 0) new_value = 5;
1444+
else if (x < 0 && y > 0) new_value = 6;
1445+
else if (x < 0 && y == 0) new_value = 7;
1446+
else if (x < 0 && y < 0) new_value = 8;
1447+
1448+
if (index % 2)
1449+
{
1450+
*value &= 0xf;
1451+
*value |= new_value << 4;
1452+
}
1453+
else
1454+
{
1455+
*value &= 0xf0;
1456+
*value |= new_value;
1457+
}
14321458
}
14331459

14341460
BOOL hid_device_set_hatswitch_x(struct unix_device *iface, ULONG index, LONG new_x)
14351461
{
14361462
struct hid_device_state *state = &iface->hid_device_state;
1437-
ULONG offset = state->hatswitch_start + index;
1463+
ULONG offset = state->hatswitch_start + index / 2;
14381464
LONG x, y;
14391465
if (index > state->hatswitch_count) return FALSE;
1440-
hatswitch_decompose(state->report_buf[offset], &x, &y);
1441-
hatswitch_compose(new_x, y, &state->report_buf[offset]);
1466+
hatswitch_decompose(state->report_buf[offset], index, &x, &y);
1467+
hatswitch_compose(new_x, y, &state->report_buf[offset], index);
14421468
return TRUE;
14431469
}
14441470

14451471
BOOL hid_device_set_hatswitch_y(struct unix_device *iface, ULONG index, LONG new_y)
14461472
{
14471473
struct hid_device_state *state = &iface->hid_device_state;
1448-
ULONG offset = state->hatswitch_start + index;
1474+
ULONG offset = state->hatswitch_start + index / 2;
14491475
LONG x, y;
14501476
if (index > state->hatswitch_count) return FALSE;
1451-
hatswitch_decompose(state->report_buf[offset], &x, &y);
1452-
hatswitch_compose(x, new_y, &state->report_buf[offset]);
1477+
hatswitch_decompose(state->report_buf[offset], index, &x, &y);
1478+
hatswitch_compose(x, new_y, &state->report_buf[offset], index);
14531479
return TRUE;
14541480
}
14551481

14561482
BOOL hid_device_move_hatswitch(struct unix_device *iface, ULONG index, LONG x, LONG y)
14571483
{
14581484
struct hid_device_state *state = &iface->hid_device_state;
1459-
ULONG offset = state->hatswitch_start + index;
1485+
ULONG offset = state->hatswitch_start + index / 2;
14601486
LONG old_x, old_y;
14611487
if (index > state->hatswitch_count) return FALSE;
1462-
hatswitch_decompose(state->report_buf[offset], &old_x, &old_y);
1463-
hatswitch_compose(old_x + x, old_y + y, &state->report_buf[offset]);
1488+
hatswitch_decompose(state->report_buf[offset], index, &old_x, &old_y);
1489+
hatswitch_compose(old_x + x, old_y + y, &state->report_buf[offset], index);
14641490
return TRUE;
14651491
}
14661492

0 commit comments

Comments
 (0)