Skip to content

Commit a73b453

Browse files
committed
Apply special remapping to the NSO N64 controller when reported as Pro Controller.
1 parent 4ba0a00 commit a73b453

File tree

2 files changed

+60
-1
lines changed

2 files changed

+60
-1
lines changed

mc_mitm/source/controllers/forced_pro_controller.cpp

Lines changed: 56 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,30 @@
1818

1919
namespace ams::controller {
2020

21+
namespace {
22+
23+
bool ApplyN64Remapping(SwitchButtonData *buttons) {
24+
bool alternatescheme = buttons->Y; //C-Up
25+
buttons->Y = buttons->ZR; //C-Down -> Y
26+
buttons->ZR = buttons->lstick_press; //ZR -> ZR
27+
buttons->lstick_press = 0;
28+
if (alternatescheme) {
29+
buttons->lstick_press = buttons->L; //L -> LEFT STICK PRESS
30+
buttons->rstick_press = buttons->R; //R -> RIGHT STICK PRESS
31+
buttons->L = 0;
32+
buttons->R = 0;
33+
}
34+
return alternatescheme;
35+
}
36+
37+
}
38+
2139
ForcedProController::ForcedProController(const bluetooth::Address *address, HardwareID id)
22-
: SwitchController(address, id) {}
40+
: SwitchController(address, id)
41+
, m_is_n64_controller(false) {
42+
if (m_id.pid == 0x2019)
43+
m_is_n64_controller = true;
44+
}
2345

2446

2547
Result ForcedProController::HandleDataReportEvent(const bluetooth::HidReportEventInfo *event_info) {
@@ -57,6 +79,31 @@ namespace ams::controller {
5779
std::memcpy(response->data.serial_flash_read.data, data, sizeof(data));
5880
}
5981
}
82+
else if (m_is_n64_controller) {
83+
switch (response->data.serial_flash_read.address) {
84+
case 0x603d: //Factory stick calibration
85+
memcpy(&response->data.serial_flash_read.data[9], &response->data.serial_flash_read.data[3], 3); //Swap calibration triplets for the right stick (https://github.com/dekuNukem/Nintendo_Switch_Reverse_Engineering/blob/master/spi_flash_notes.md)
86+
memcpy(&m_n64_calibrated_stick_zero, &response->data.serial_flash_read.data[3], 3);
87+
memcpy(&response->data.serial_flash_read.data[12], &response->data.serial_flash_read.data[6], 3);
88+
memcpy(&response->data.serial_flash_read.data[15], &response->data.serial_flash_read.data[0], 3);
89+
break;
90+
case 0x8010: //User stick calibration
91+
if (response->data.serial_flash_read.data[0] != 0xFF && response->data.serial_flash_read.data[1] != 0xFF) {
92+
memcpy(&response->data.serial_flash_read.data[11], &response->data.serial_flash_read.data[0], 2); //Copy magic numbers that signal the presence of a user calibration
93+
memcpy(&response->data.serial_flash_read.data[13], &response->data.serial_flash_read.data[5], 3); //Swap calibration triplets for the right stick
94+
memcpy(&m_n64_calibrated_stick_zero, &response->data.serial_flash_read.data[5], 3);
95+
memcpy(&response->data.serial_flash_read.data[16], &response->data.serial_flash_read.data[8], 3);
96+
memcpy(&response->data.serial_flash_read.data[19], &response->data.serial_flash_read.data[2], 3);
97+
}
98+
break;
99+
case 0x6080: //Left stick parameters (always read first) (first 6 bytes are 6-Axis Horizontal Offsets which we don't need)
100+
memcpy(&m_n64_left_stick_param, &response->data.serial_flash_read.data[6],sizeof(SwitchAnalogStickParameters));
101+
break;
102+
case 0x6098: //Right stick parameters (always read after the left ones)
103+
memcpy(&response->data.serial_flash_read.data, &m_n64_left_stick_param, sizeof(SwitchAnalogStickParameters));
104+
break;
105+
}
106+
}
60107
break;
61108
case HidCommand_GetDeviceInfo:
62109
response->data.get_device_info.type = 0x03;
@@ -65,6 +112,14 @@ namespace ams::controller {
65112
}
66113
}
67114

115+
if (m_is_n64_controller) {
116+
if (ApplyN64Remapping(&input_report->buttons)) {
117+
input_report->right_stick.SetData(input_report->left_stick.GetX(), input_report->left_stick.GetY());
118+
memcpy(&input_report->left_stick.m_xy, &m_n64_calibrated_stick_zero, 3);
119+
}
120+
else memcpy(&input_report->right_stick.m_xy, &m_n64_calibrated_stick_zero, 3);
121+
}
122+
68123
this->ApplyButtonCombos(&input_report->buttons);
69124

70125
return bluetooth::hid::report::WriteHidDataReport(m_address, &m_input_report);

mc_mitm/source/controllers/forced_pro_controller.hpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,10 @@ namespace ams::controller {
2626

2727
Result HandleDataReportEvent(const bluetooth::HidReportEventInfo *event_info);
2828
Result HandleOutputDataReport(const bluetooth::HidReport *report);
29+
private:
30+
bool m_is_n64_controller;
31+
SwitchAnalogStickParameters m_n64_left_stick_param;
32+
uint8_t m_n64_calibrated_stick_zero[3];
2933

3034
};
3135

0 commit comments

Comments
 (0)