mc.mitm: add support for 8bitdo ultimate 2.4g wireless controller

This commit is contained in:
ndeadly 2023-05-17 13:10:49 +02:00
parent d83763d38b
commit 6c1c8306ef
2 changed files with 109 additions and 62 deletions

View file

@ -15,12 +15,14 @@
*/
#include "8bitdo_controller.hpp"
#include <stratosphere.hpp>
#include "controller_utils.hpp"
namespace ams::controller {
namespace {
constexpr float stick_scale_factor = float(UINT12_MAX) / UINT16_MAX;
constexpr float stick_scale_factor_16bit = float(UINT12_MAX) / UINT16_MAX;
constexpr float stick_scale_factor_8bit = float(UINT12_MAX) / UINT8_MAX;
}
@ -53,26 +55,26 @@ namespace ams::controller {
(src->input0x01_v1.dpad == EightBitDoDPadV1_SW);
} else {
m_left_stick.SetData(
static_cast<u16>(stick_scale_factor * src->input0x01_v2.left_stick.x) & UINT12_MAX,
static_cast<u16>(stick_scale_factor * (UINT16_MAX - src->input0x01_v2.left_stick.y)) & UINT12_MAX
static_cast<u16>(stick_scale_factor_16bit * src->input0x01_v2.left_stick.x) & UINT12_MAX,
static_cast<u16>(stick_scale_factor_16bit * (UINT16_MAX - src->input0x01_v2.left_stick.y)) & UINT12_MAX
);
m_right_stick.SetData(
static_cast<u16>(stick_scale_factor * src->input0x01_v2.right_stick.x) & UINT12_MAX,
static_cast<u16>(stick_scale_factor * (UINT16_MAX - src->input0x01_v2.right_stick.y)) & UINT12_MAX
static_cast<u16>(stick_scale_factor_16bit * src->input0x01_v2.right_stick.x) & UINT12_MAX,
static_cast<u16>(stick_scale_factor_16bit * (UINT16_MAX - src->input0x01_v2.right_stick.y)) & UINT12_MAX
);
m_buttons.dpad_down = (src->input0x01_v2.buttons.dpad == EightBitDoDPadV2_S) ||
(src->input0x01_v2.buttons.dpad == EightBitDoDPadV2_SE) ||
(src->input0x01_v2.buttons.dpad == EightBitDoDPadV2_SW);
m_buttons.dpad_up = (src->input0x01_v2.buttons.dpad == EightBitDoDPadV2_N) ||
(src->input0x01_v2.buttons.dpad == EightBitDoDPadV2_NE) ||
(src->input0x01_v2.buttons.dpad == EightBitDoDPadV2_NW);
m_buttons.dpad_right = (src->input0x01_v2.buttons.dpad == EightBitDoDPadV2_E) ||
(src->input0x01_v2.buttons.dpad == EightBitDoDPadV2_NE) ||
(src->input0x01_v2.buttons.dpad == EightBitDoDPadV2_SE);
m_buttons.dpad_left = (src->input0x01_v2.buttons.dpad == EightBitDoDPadV2_W) ||
(src->input0x01_v2.buttons.dpad == EightBitDoDPadV2_NW) ||
(src->input0x01_v2.buttons.dpad == EightBitDoDPadV2_SW);
m_buttons.dpad_down = (src->input0x01_v2.dpad == EightBitDoDPadV2_S) ||
(src->input0x01_v2.dpad == EightBitDoDPadV2_SE) ||
(src->input0x01_v2.dpad == EightBitDoDPadV2_SW);
m_buttons.dpad_up = (src->input0x01_v2.dpad == EightBitDoDPadV2_N) ||
(src->input0x01_v2.dpad == EightBitDoDPadV2_NE) ||
(src->input0x01_v2.dpad == EightBitDoDPadV2_NW);
m_buttons.dpad_right = (src->input0x01_v2.dpad == EightBitDoDPadV2_E) ||
(src->input0x01_v2.dpad == EightBitDoDPadV2_NE) ||
(src->input0x01_v2.dpad == EightBitDoDPadV2_SE);
m_buttons.dpad_left = (src->input0x01_v2.dpad == EightBitDoDPadV2_W) ||
(src->input0x01_v2.dpad == EightBitDoDPadV2_NW) ||
(src->input0x01_v2.dpad == EightBitDoDPadV2_SW);
m_buttons.A = src->input0x01_v2.buttons.B;
m_buttons.B = src->input0x01_v2.buttons.A;
@ -106,34 +108,80 @@ namespace ams::controller {
}
void EightBitDoController::MapInputReport0x03(const EightBitDoReportData *src, EightBitDoReportFormat fmt) {
if (fmt == EightBitDoReportFormat_ZeroV1) {
m_buttons.A = src->input0x03_v1.buttons.B;
m_buttons.B = src->input0x03_v1.buttons.A;
m_buttons.X = src->input0x03_v1.buttons.Y;
m_buttons.Y = src->input0x03_v1.buttons.X;
if (m_controller_type == EightBitDoControllerType_Zero) {
if (fmt == EightBitDoReportFormat_ZeroV1) {
m_buttons.A = src->input0x03_v1.buttons.B;
m_buttons.B = src->input0x03_v1.buttons.A;
m_buttons.X = src->input0x03_v1.buttons.Y;
m_buttons.Y = src->input0x03_v1.buttons.X;
m_buttons.R = src->input0x03_v1.buttons.R1;
m_buttons.L = src->input0x03_v1.buttons.L1;
m_buttons.R = src->input0x03_v1.buttons.R1;
m_buttons.L = src->input0x03_v1.buttons.L1;
m_buttons.minus = src->input0x03_v1.buttons.select;
m_buttons.plus = src->input0x03_v1.buttons.start;
} else if (fmt == EightBitDoReportFormat_ZeroV2) {
m_buttons.dpad_down = src->input0x03_v2.left_stick.y == 0xff;
m_buttons.dpad_up = src->input0x03_v2.left_stick.y == 0x00;
m_buttons.dpad_right = src->input0x03_v2.left_stick.x == 0xff;
m_buttons.dpad_left = src->input0x03_v2.left_stick.x == 0x00;
m_buttons.minus = src->input0x03_v1.buttons.v2.select;
m_buttons.plus = src->input0x03_v1.buttons.v2.start;
} else if (fmt == EightBitDoReportFormat_ZeroV2) {
m_buttons.dpad_down = src->input0x03_v2.left_stick.y == 0xff;
m_buttons.dpad_up = src->input0x03_v2.left_stick.y == 0x00;
m_buttons.dpad_right = src->input0x03_v2.left_stick.x == 0xff;
m_buttons.dpad_left = src->input0x03_v2.left_stick.x == 0x00;
m_buttons.A = src->input0x03_v2.buttons.B;
m_buttons.B = src->input0x03_v2.buttons.A;
m_buttons.X = src->input0x03_v2.buttons.Y;
m_buttons.Y = src->input0x03_v2.buttons.X;
m_buttons.A = src->input0x03_v2.buttons.B;
m_buttons.B = src->input0x03_v2.buttons.A;
m_buttons.X = src->input0x03_v2.buttons.Y;
m_buttons.Y = src->input0x03_v2.buttons.X;
m_buttons.R = src->input0x03_v2.buttons.R1;
m_buttons.L = src->input0x03_v2.buttons.L1;
m_buttons.R = src->input0x03_v2.buttons.R1;
m_buttons.L = src->input0x03_v2.buttons.L1;
m_buttons.minus = src->input0x03_v2.buttons.select;
m_buttons.plus = src->input0x03_v2.buttons.start;
m_buttons.minus = src->input0x03_v2.buttons.v2.select;
m_buttons.plus = src->input0x03_v2.buttons.v2.start;
}
} else {
m_left_stick.SetData(
static_cast<u16>(stick_scale_factor_8bit * src->input0x03_v3.left_stick.x) & UINT12_MAX,
static_cast<u16>(stick_scale_factor_8bit * (UINT8_MAX - src->input0x03_v3.left_stick.y)) & UINT12_MAX
);
m_right_stick.SetData(
static_cast<u16>(stick_scale_factor_8bit * src->input0x03_v3.right_stick.x) & UINT12_MAX,
static_cast<u16>(stick_scale_factor_8bit * (UINT8_MAX - src->input0x03_v3.right_stick.y)) & UINT12_MAX
);
m_buttons.dpad_down = (src->input0x03_v3.dpad == EightBitDoDPadV2_S) ||
(src->input0x03_v3.dpad == EightBitDoDPadV2_SE) ||
(src->input0x03_v3.dpad == EightBitDoDPadV2_SW);
m_buttons.dpad_up = (src->input0x03_v3.dpad == EightBitDoDPadV2_N) ||
(src->input0x03_v3.dpad == EightBitDoDPadV2_NE) ||
(src->input0x03_v3.dpad == EightBitDoDPadV2_NW);
m_buttons.dpad_right = (src->input0x03_v3.dpad == EightBitDoDPadV2_E) ||
(src->input0x03_v3.dpad == EightBitDoDPadV2_NE) ||
(src->input0x03_v3.dpad == EightBitDoDPadV2_SE);
m_buttons.dpad_left = (src->input0x03_v3.dpad == EightBitDoDPadV2_W) ||
(src->input0x03_v3.dpad == EightBitDoDPadV2_NW) ||
(src->input0x03_v3.dpad == EightBitDoDPadV2_SW);
m_buttons.A = src->input0x03_v3.buttons.B;
m_buttons.B = src->input0x03_v3.buttons.A;
m_buttons.X = src->input0x03_v3.buttons.Y;
m_buttons.Y = src->input0x03_v3.buttons.X;
m_buttons.L = src->input0x03_v3.buttons.L1;
m_buttons.R = src->input0x03_v3.buttons.R1;
m_buttons.ZL = src->input0x03_v3.left_trigger > (m_trigger_threshold * UINT8_MAX);
m_buttons.ZR = src->input0x03_v3.right_trigger > (m_trigger_threshold * UINT8_MAX);
m_buttons.minus = src->input0x03_v3.buttons.v2.select;
m_buttons.plus = src->input0x03_v3.buttons.v2.start;
m_buttons.lstick_press = src->input0x03_v3.buttons.v2.L3;
m_buttons.rstick_press = src->input0x03_v3.buttons.v2.R3;
m_buttons.home = src->input0x03_v3.buttons.v2.home;
m_battery = convert_battery_100(src->input0x03_v3.battery);
}
}
}

View file

@ -22,6 +22,7 @@ namespace ams::controller {
EightBitDoControllerType_Zero,
EightBitDoControllerType_Sn30ProXboxCloud,
EightBitDoControllerType_Sn30ProXboxCloudFwV2,
EightBitDoControllerType_Ultimate24gWireless,
EightBitDoControllerType_Other
};
@ -65,23 +66,7 @@ namespace ams::controller {
u16 y;
} PACKED;
struct EightBitDoButtonDataV1 {
u8 A : 1;
u8 B : 1;
u8 : 1;
u8 X : 1;
u8 Y : 1;
u8 : 1;
u8 L1 : 1;
u8 R1 : 1;
u8 : 2;
u8 select : 1;
u8 start : 1;
u8 : 0;
} PACKED;
struct EightBitDoButtonDataV2 {
struct EightBitDoButtonData {
u8 A : 1;
u8 B : 1;
u8 : 1;
@ -113,8 +98,6 @@ namespace ams::controller {
u8 : 1;
} v2;
};
u8 dpad;
} PACKED;
struct EightBitDoInputReport0x01V1 {
@ -124,7 +107,8 @@ namespace ams::controller {
} PACKED;
struct EightBitDoInputReport0x01V2 {
EightBitDoButtonDataV2 buttons;
EightBitDoButtonData buttons;
u8 dpad;
EightBitDoStickData16 left_stick;
EightBitDoStickData16 right_stick;
u8 left_trigger;
@ -137,7 +121,7 @@ namespace ams::controller {
EightBitDoStickData8 left_stick;
EightBitDoStickData8 right_stick;
u8 _unk[3];
EightBitDoButtonDataV1 buttons;
EightBitDoButtonData buttons;
} PACKED;
struct EightBitDoInputReport0x03V2 {
@ -145,7 +129,18 @@ namespace ams::controller {
EightBitDoStickData8 left_stick;
EightBitDoStickData8 right_stick;
u8 _unk[2];
EightBitDoButtonDataV1 buttons;
EightBitDoButtonData buttons;
} PACKED;
struct EightBitDoInputReport0x03V3 {
u8 dpad;
EightBitDoStickData8 left_stick;
EightBitDoStickData8 right_stick;
u8 right_trigger;
u8 left_trigger;
EightBitDoButtonData buttons;
u8 battery;
u8 _unk0;
} PACKED;
struct EightBitDoReportData {
@ -155,6 +150,7 @@ namespace ams::controller {
EightBitDoInputReport0x01V2 input0x01_v2;
EightBitDoInputReport0x03V1 input0x03_v1;
EightBitDoInputReport0x03V2 input0x03_v2;
EightBitDoInputReport0x03V3 input0x03_v3;
};
} PACKED;
@ -164,7 +160,8 @@ namespace ams::controller {
static constexpr const HardwareID hardware_ids[] = {
{0x05a0, 0x3232}, // 8BitDo Zero
{0x2dc8, 0x2100}, // 8BitDo SN30 Pro for Xbox Cloud Gaming
{0x2dc8, 0x2101} // 8BitDo SN30 Pro for Xbox Cloud Gaming (fw 2.00)
{0x2dc8, 0x2101}, // 8BitDo SN30 Pro for Xbox Cloud Gaming (fw 2.00)
{0x2dc8, 0x3012} // 8BitDo Ultimate 2.4g Wireless
};
EightBitDoController(const bluetooth::Address *address, HardwareID id)
@ -175,6 +172,8 @@ namespace ams::controller {
m_controller_type = EightBitDoControllerType_Sn30ProXboxCloud;
else if ((id.vid == hardware_ids[2].vid) && (id.pid == hardware_ids[2].pid))
m_controller_type = EightBitDoControllerType_Sn30ProXboxCloudFwV2;
else if ((id.vid == hardware_ids[3].vid) && (id.pid == hardware_ids[3].pid))
m_controller_type = EightBitDoControllerType_Ultimate24gWireless;
else
m_controller_type = EightBitDoControllerType_Other;
}