Skip to content

Commit

Permalink
Merge branch 'develop' into profiles_branch
Browse files Browse the repository at this point in the history
  • Loading branch information
Banz99 committed Jul 12, 2021
2 parents 934fc87 + 4db612c commit 2bec6c2
Show file tree
Hide file tree
Showing 18 changed files with 95 additions and 34 deletions.
8 changes: 4 additions & 4 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,11 @@ dist: all

cp -r exefs_patches dist/atmosphere/

mkdir -p dist/atmosphere/config_templates
cp mc_mitm/config.ini dist/atmosphere/config_templates/missioncontrol.ini
mkdir -p dist/config/MissionControl
cp mc_mitm/config.ini dist/config/MissionControl/missioncontrol.ini.template

mkdir -p dist/switch/missioncontrol/profiles
cp mc_mitm/default.ini dist/switch/missioncontrol/profiles/default.ini
mkdir -p dist/config/MissionControl/profiles
cp mc_mitm/default.ini dist/config/MissionControl/profiles/default.ini

cd dist; zip -r $(PROJECT_NAME)-$(BUILD_VERSION).zip ./*; cd ../;

Expand Down
25 changes: 19 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ Use controllers from other consoles natively on your Nintendo Switch via Bluetoo
* Rumble support*
* Low input lag.
* Spoofing of host Bluetooth adapter name and address.
* `btdrv.mitm` module adds extension IPC commands that can be used to interact with the `bluetooth` process without interfering with the state of the system.
* `mc.mitm` module adds extension IPC commands that can be used to interact with the `bluetooth` process without interfering with the state of the system.

**Rumble not currently implemented for all compatible controllers*

Expand Down Expand Up @@ -75,7 +75,7 @@ Use controllers from other consoles natively on your Nintendo Switch via Bluetoo
Download the [latest release](https://github.com/ndeadly/MissionControl/releases) .zip and extract to the root of your SD card, allowing the folders to merge and overwriting any existing files. A console reboot is required in order for Mission Control to become active.

***IMPORTANT:
Atmosphère >= 0.19.3 is required to run the latest release of Mission Control. Using an older Atmosphère version will cause Mission Control to crash the system on boot.
Atmosphère >= 0.19.5 is required to run the latest release of Mission Control. Using an older Atmosphère version will cause Mission Control to crash the system on boot.
Users upgrading from version 0.1.0 of Mission Control are also advised to wipe their pairing database and re-pair controllers running the latest version. Failure to wipe the old entries may result in non-switch controllers being detected incorrectly.***

### Usage
Expand Down Expand Up @@ -104,6 +104,20 @@ You should also ensure your controller firmware is up to date, as old firmwares
***Other Controllers***
Please refer to your controller's user manual for information on how to put it in sync mode. Note that many generic Bluetooth controllers can be started in one of several modes. Usually you want to choose something like HID, PC or Android mode for it to work correctly.

### Module configuration

A template for the config .ini file will be installed to `/config/MissionControl/missioncontrol.ini.template`. To modify the default module settings, copy the template to `/config/MissionControl/missioncontrol.ini` and uncomment/modify any settings you want to change. The file is only parsed on startup, so any changes you make will require a reboot to take effect. Currently there is only a small set of configuration settings, but this will be expanded upon in future releases.

- `[general]`
These are general settings for mission control features.
- `enable_rumble` Enables/disables rumble support for unofficial controllers.
- `enable_motion` Enables/disables motion controls support. Not currently used

- `[bluetooth]`
These settings can be used to spoof your switch bluetooth to appear as another device. This may be useful (in conjunction with a link key) if you want to use your controller across multiple devices without having to re-pair every time you switch. Note that changing these settings will invalidate your console information stored in any previously paired controllers and will require re-pairing.
- `host_name` Override the bluetooth host adapter name
- `host_address` Override the bluetooth host adapter address

### Removal

To functionally uninstall Mission Control and its components, all that needs to be done is to delete the following directories from your SD card and reboot your console.
Expand All @@ -113,9 +127,8 @@ To functionally uninstall Mission Control and its components, all that needs to

If you wish to completely remove all traces of the software ever having been installed (telemetry excepted), you may also want to follow these additional steps

* Remove the following files from your SD card (if present)
* `/atmosphere/config_templates/missioncontrol.ini`
* `/atmosphere/config/missioncontrol.ini`
* Remove the following directory from your SD card
* `/config/MissionControl`

* Wipe the Bluetooth pairing database via `System Settings->Controllers and Sensors->Disconnect Controllers`

Expand Down Expand Up @@ -217,7 +230,7 @@ git clone --recurse-submodules https://github.com/ndeadly/MissionControl.git
cd MissionControl
```

~~Mission Control currently uses a custom fork of `libnx` that adds Bluetooth service wrappers and type definitions.~~ Official libnx master is now used to build Mission Control. This needs to be built and installed first.
~~Mission Control currently uses a custom fork of `libnx` that adds Bluetooth service wrappers and type definitions.~~ Official libnx master is now used to build Mission Control. At the time of writing, the libnx distributed by devkitPro can be used without the need to build it yourself. This may change if `Atmosphere-libs` updates to use bleeding edge `libnx` commits not present in the official release. In any case, you can build the included `libnx` submodule from source with the following commands.

```
cd lib/libnx
Expand Down
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
2 changes: 1 addition & 1 deletion lib/Atmosphere-libs
Submodule Atmosphere-libs updated 23 files
+1 −1 config/common.mk
+1 −1 config/templates/exosphere.mk
+1 −1 config/templates/mesosphere.mk
+12 −11 libexosphere/include/exosphere/pkg1/pkg1_key_generation.hpp
+1 −1 libexosphere/include/exosphere/pkg2.hpp
+3 −2 libmesosphere/include/mesosphere/arch/arm64/init/kern_k_init_arguments.hpp
+1 −1 libmesosphere/include/mesosphere/board/nintendo/nx/kern_k_device_page_table.hpp
+2 −0 libmesosphere/include/mesosphere/init/kern_init_arguments_select.hpp
+7 −1 libmesosphere/include/mesosphere/kern_k_dynamic_page_manager.hpp
+8 −1 libmesosphere/include/mesosphere/kern_k_dynamic_slab_heap.hpp
+5 −2 libmesosphere/include/mesosphere/kern_k_page_table_base.hpp
+4 −5 libmesosphere/include/mesosphere/kern_k_page_table_manager.hpp
+9 −3 libmesosphere/source/arch/arm64/kern_k_page_table.cpp
+2 −2 libmesosphere/source/board/nintendo/nx/kern_k_device_page_table.cpp
+1 −1 libmesosphere/source/kern_k_device_address_space.cpp
+1 −0 libmesosphere/source/kern_k_resource_limit.cpp
+1 −0 libstratosphere/include/stratosphere/fssrv.hpp
+159 −0 libstratosphere/include/stratosphere/fssrv/impl/fssrv_impl_program_index_map_info_manager.hpp
+1 −0 libstratosphere/include/stratosphere/hos/hos_types.hpp
+3 −0 libstratosphere/source/erpt/srv/erpt_srv_context_record.cpp
+1 −1 libstratosphere/source/erpt/srv/erpt_srv_reporter.cpp
+3 −3 libvapours/include/vapours/ams/ams_api_version.h
+3 −1 libvapours/include/vapours/ams/ams_target_firmware.h
2 changes: 1 addition & 1 deletion mc_mitm/source/bluetooth_mitm/btdrv_mitm_service.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ namespace ams::mitm::bluetooth {

Result BtdrvMitmService::SetTsi(ams::bluetooth::Address address, u8 tsi) {
auto device = controller::LocateHandler(&address);
if (!device || device->IsOfficialController())
if (!device || device->SupportsSetTsiCommand())
return sm::mitm::ResultShouldForwardToSession();

if (hos::GetVersion() < hos::Version_9_0_0) {
Expand Down
2 changes: 1 addition & 1 deletion mc_mitm/source/controllers/dualshock4_controller.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ namespace ams::controller {
}

Result Dualshock4Controller::PushRumbleLedState(void) {
Dualshock4OutputReport0x11 report = {0xa2, 0x11, 0xc0, 0x20, 0xf3, 0x04, 0x00,
Dualshock4OutputReport0x11 report = {0xa2, 0x11, static_cast<uint8_t>(0xc0 | (m_report_rate & 0xff)), 0x20, 0xf3, 0x04, 0x00,
m_rumble_state.amp_motor_right, m_rumble_state.amp_motor_left,
m_led_colour.r, m_led_colour.g, m_led_colour.b
};
Expand Down
26 changes: 24 additions & 2 deletions mc_mitm/source/controllers/dualshock4_controller.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,26 @@

namespace ams::controller {

enum Dualshock4ReportRate {
Dualshock4ReportRate_Max = 0,
Dualshock4ReportRate_1000Hz = 1,
Dualshock4ReportRate_500Hz = 2,
Dualshock4ReportRate_333Hz = 3,
Dualshock4ReportRate_250Hz = 4,
Dualshock4ReportRate_200Hz = 5,
Dualshock4ReportRate_166Hz = 6,
Dualshock4ReportRate_142Hz = 7,
Dualshock4ReportRate_125Hz = 8,
Dualshock4ReportRate_111Hz = 9,
Dualshock4ReportRate_100Hz = 10,
Dualshock4ReportRate_90Hz = 11,
Dualshock4ReportRate_83Hz = 12,
Dualshock4ReportRate_76Hz = 13,
Dualshock4ReportRate_71Hz = 14,
Dualshock4ReportRate_66Hz = 15,
Dualshock4ReportRate_62Hz = 16
};

enum Dualshock4ControllerVariant {
Dualshock4ControllerVariant_V1,
Dualshock4ControllerVariant_V2,
Expand Down Expand Up @@ -131,15 +151,16 @@ namespace ams::controller {

Dualshock4Controller(const bluetooth::Address *address)
: EmulatedSwitchController(address)
, m_report_rate(Dualshock4ReportRate_125Hz)
, m_led_colour({0, 0, 0})
, m_rumble_state({0, 0}) { };

Result Initialize(void);
Result SetVibration(const SwitchRumbleData *rumble_data);
Result CancelVibration(void);
Result SetPlayerLed(uint8_t led_mask);
Result SetLightbarColour(RGBColour colour);

void UpdateControllerState(const bluetooth::HidReport *report);

private:
Expand All @@ -150,6 +171,7 @@ namespace ams::controller {

Result PushRumbleLedState(void);

Dualshock4ReportRate m_report_rate;
RGBColour m_led_colour;
Dualshock4RumbleData m_rumble_state;
};
Expand Down
17 changes: 16 additions & 1 deletion mc_mitm/source/controllers/emulated_switch_controller.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@ namespace ams::controller {

namespace {

// Factory calibration data representing analog stick ranges that span the entire 12-bit data type in x and y
SwitchAnalogStickFactoryCalibration lstick_factory_calib = {0xff, 0xf7, 0x7f, 0x00, 0x08, 0x80, 0x00, 0x08, 0x80};
SwitchAnalogStickFactoryCalibration rstick_factory_calib = {0x00, 0x08, 0x80, 0x00, 0x08, 0x80, 0xff, 0xf7, 0x7f};

// Frequency in Hz rounded to nearest int
// https://github.com/dekuNukem/Nintendo_Switch_Reverse_Engineering/blob/master/rumble_data_table.md#frequency-table
const uint16_t rumble_freq_lut[] = {
Expand Down Expand Up @@ -283,7 +287,7 @@ namespace ams::controller {
// @ 0x00006080: 50 fd 00 00 c6 0f 0f 30 61 ae 90 d9 d4 14 54 41 15 54 c7 79 9c 33 36 63 <= Factory Sensor and Stick device parameters
// @ 0x00006098: 0f 30 61 ae 90 d9 d4 14 54 41 15 54 c7 79 9c 33 36 63 <= Stick device parameters 2. Normally the same with 1, even in Pro Contr.
// @ 0x00008010: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff <= User Analog sticks calibration
// @ 0x0000603d: e6 a5 67 1a 58 78 50 56 60 1a f8 7f 20 c6 63 d5 15 5e ff 32 32 32 ff ff ff <= Left analog stick calibration
// @ 0x0000603d: e6 a5 67 1a 58 78 50 56 60 1a f8 7f 20 c6 63 d5 15 5e ff 32 32 32 ff ff ff <= Analog stick factory calibration + face/button colours
// @ 0x00006020: 64 ff 33 00 b8 01 00 40 00 40 00 40 17 00 d7 ff bd ff 3b 34 3b 34 3b 34 <= 6-Axis motion sensor Factory calibration

auto switch_report = reinterpret_cast<const SwitchReportData *>(&report->data);
Expand All @@ -302,6 +306,17 @@ namespace ams::controller {
if (read_addr == 0x6050) {
std::memcpy(response.spi_flash_read.data, &m_colours, sizeof(m_colours)); // Set controller colours
}
else if (read_addr == 0x603d) {
const struct {
SwitchAnalogStickFactoryCalibration lstick_factory_calib;
SwitchAnalogStickFactoryCalibration rstick_factory_calib;
uint8_t unused;
RGBColour body;
RGBColour buttons;
} data = { lstick_factory_calib, rstick_factory_calib, 0xff, m_colours.body, m_colours.buttons };

std::memcpy(response.spi_flash_read.data, &data, sizeof(data));
}
else {
std::memset(response.spi_flash_read.data, 0xff, read_size); // Console doesn't seem to mind if response is uninitialised data (0xff)
}
Expand Down
2 changes: 2 additions & 0 deletions mc_mitm/source/controllers/gamesir_controller.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,8 @@ namespace ams::controller {
GamesirController(const bluetooth::Address *address)
: EmulatedSwitchController(address) { };

bool SupportsSetTsiCommand(void) { return false; }

void UpdateControllerState(const bluetooth::HidReport *report);

private:
Expand Down
4 changes: 4 additions & 0 deletions mc_mitm/source/controllers/switch_analog_stick.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,4 +33,8 @@ namespace ams::controller {
uint8_t m_xy[3];
};

struct SwitchAnalogStickFactoryCalibration {
uint8_t calib[9];
};

}
7 changes: 4 additions & 3 deletions mc_mitm/source/controllers/switch_controller.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -254,11 +254,12 @@ namespace ams::controller {
SwitchController(const bluetooth::Address *address)
: m_address(*address) { };

const bluetooth::Address& Address(void) const { return m_address; };
const bluetooth::Address& Address(void) const { return m_address; }

virtual bool IsOfficialController(void) { return true; };
virtual bool IsOfficialController(void) { return true; }
virtual bool SupportsSetTsiCommand(void) { return true; }

virtual Result Initialize(void) { return ams::ResultSuccess(); };
virtual Result Initialize(void) { return ams::ResultSuccess(); }
virtual Result HandleIncomingReport(const bluetooth::HidReport *report);
virtual Result HandleOutgoingReport(const bluetooth::HidReport *report);

Expand Down
24 changes: 13 additions & 11 deletions mc_mitm/source/controllers/wii_controller.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ namespace ams::controller {
constexpr uint8_t init_data2[] = {0x00};

constexpr float nunchuck_stick_scale_factor = float(UINT12_MAX) / 0xb8;
constexpr float wiiu_scale_factor = 1.5;
constexpr float wiiu_scale_factor = 2.0;
constexpr float left_stick_scale_factor = float(UINT12_MAX) / 0x3f;
constexpr float right_stick_scale_factor = float(UINT12_MAX) / 0x1f;

Expand Down Expand Up @@ -77,7 +77,9 @@ namespace ams::controller {
else if (src->input0x20.extension_connected && (m_extension == WiiExtensionController_None)) {
// Initialise extension
this->WriteMemory(0x04a400f0, init_data1, sizeof(init_data1));
svcSleepThread(20'000'000ULL);
this->WriteMemory(0x04a400fb, init_data2, sizeof(init_data2));
svcSleepThread(20'000'000ULL);

// Read extension type
this->ReadMemory(0x04a400fa, 6);
Expand All @@ -92,7 +94,7 @@ namespace ams::controller {
if (read_addr == 0x00fa) {
// Identify extension controller by ID
uint64_t extension_id = (util::SwapBytes(*reinterpret_cast<const uint64_t *>(&src->input0x21.data)) >> 16);

switch (extension_id) {
case 0x0000A4200000ULL:
case 0xFF00A4200000ULL:
Expand Down Expand Up @@ -140,7 +142,7 @@ namespace ams::controller {
}

void WiiController::HandleInputReport0x32(const WiiReportData *src) {
if ((m_extension == WiiExtensionController_Nunchuck)
if ((m_extension == WiiExtensionController_Nunchuck)
|| (m_extension == WiiExtensionController_Classic)
|| (m_extension == WiiExtensionController_ClassicPro)
|| (m_extension == WiiExtensionController_TaTaCon)) {
Expand All @@ -151,7 +153,7 @@ namespace ams::controller {
}

void WiiController::HandleInputReport0x34(const WiiReportData *src) {
if ((m_extension == WiiExtensionController_Nunchuck)
if ((m_extension == WiiExtensionController_Nunchuck)
|| (m_extension == WiiExtensionController_Classic)
|| (m_extension == WiiExtensionController_ClassicPro)) {
this->MapButtonsVerticalOrientation(&src->input0x34.buttons);
Expand Down Expand Up @@ -221,7 +223,7 @@ namespace ams::controller {
auto extension = reinterpret_cast<const WiiNunchuckExtensionData *>(ext);

m_left_stick.SetData(
std::clamp<uint16_t>(static_cast<uint16_t>(nunchuck_stick_scale_factor * (extension->stick_x - 0x80) + STICK_ZERO), 0, 0xfff),
std::clamp<uint16_t>(static_cast<uint16_t>(nunchuck_stick_scale_factor * (extension->stick_x - 0x80) + STICK_ZERO), 0, 0xfff),
std::clamp<uint16_t>(static_cast<uint16_t>(nunchuck_stick_scale_factor * (extension->stick_y - 0x80) + STICK_ZERO), 0, 0xfff)
);

Expand All @@ -231,11 +233,11 @@ namespace ams::controller {

void WiiController::MapClassicControllerExtension(const uint8_t ext[]) {
m_left_stick.SetData(
static_cast<uint16_t>(left_stick_scale_factor * ((ext[0] & 0x3f) - 0x20) + STICK_ZERO) & 0xfff,
static_cast<uint16_t>(left_stick_scale_factor * ((ext[0] & 0x3f) - 0x20) + STICK_ZERO) & 0xfff,
static_cast<uint16_t>(left_stick_scale_factor * ((ext[1] & 0x3f) - 0x20) + STICK_ZERO) & 0xfff
);
m_right_stick.SetData(
static_cast<uint16_t>(right_stick_scale_factor * ((((ext[0] >> 3) & 0x18) | ((ext[1] >> 5) & 0x06) | ((ext[2] >> 7) & 0x01)) - 0x10) + STICK_ZERO) & 0xfff,
static_cast<uint16_t>(right_stick_scale_factor * ((((ext[0] >> 3) & 0x18) | ((ext[1] >> 5) & 0x06) | ((ext[2] >> 7) & 0x01)) - 0x10) + STICK_ZERO) & 0xfff,
static_cast<uint16_t>(right_stick_scale_factor * ((ext[2] & 0x1f) - 0x10) + STICK_ZERO) & 0xfff
);

Expand Down Expand Up @@ -266,7 +268,7 @@ namespace ams::controller {
auto extension = reinterpret_cast<const WiiUProExtensionData *>(ext);

m_left_stick.SetData(
std::clamp<uint16_t>(((wiiu_scale_factor * (extension->left_stick_x - STICK_ZERO))) + STICK_ZERO, 0, 0xfff),
std::clamp<uint16_t>(((wiiu_scale_factor * (extension->left_stick_x - STICK_ZERO))) + STICK_ZERO, 0, 0xfff),
std::clamp<uint16_t>(((wiiu_scale_factor * (extension->left_stick_y - STICK_ZERO))) + STICK_ZERO, 0, 0xfff)
);
m_right_stick.SetData(
Expand Down Expand Up @@ -343,12 +345,12 @@ namespace ams::controller {
auto report_data = reinterpret_cast<WiiReportData *>(s_output_report.data);
report_data->id = 0x15;
report_data->output0x15.rumble = m_rumble_state;

return bluetooth::hid::report::SendHidReport(&m_address, &s_output_report);
}

Result WiiController::SetVibration(const SwitchRumbleData *rumble_data) {
m_rumble_state = rumble_data->low_band_amp > 0 || rumble_data->high_band_amp > 0;
m_rumble_state = rumble_data->high_band_amp > 0; //rumble_data->low_band_amp > 0 || rumble_data->high_band_amp > 0;

s_output_report.size = sizeof(WiiOutputReport0x10) + 1;
auto report_data = reinterpret_cast<WiiReportData *>(s_output_report.data);
Expand All @@ -369,7 +371,7 @@ namespace ams::controller {
return bluetooth::hid::report::SendHidReport(&m_address, &s_output_report);
}

Result WiiController::SetPlayerLed(uint8_t led_mask) {
Result WiiController::SetPlayerLed(uint8_t led_mask) {
s_output_report.size = sizeof(WiiOutputReport0x11) + 1;
auto report_data = reinterpret_cast<WiiReportData *>(s_output_report.data);
report_data->id = 0x11;
Expand Down
2 changes: 2 additions & 0 deletions mc_mitm/source/controllers/xbox_one_controller.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,8 @@ namespace ams::controller {
XboxOneController(const bluetooth::Address *address)
: EmulatedSwitchController(address) { };

bool SupportsSetTsiCommand(void) { return false; }

Result SetVibration(const SwitchRumbleData *rumble_data);
void UpdateControllerState(const bluetooth::HidReport *report);

Expand Down
6 changes: 3 additions & 3 deletions mc_mitm/source/mcmitm_config.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,9 @@ namespace ams::mitm {

namespace {

constexpr const char *config_file_location = "sdmc:/atmosphere/config/missioncontrol.ini";
constexpr const char *cp_default_location = "sdmc:/switch/missioncontrol/profiles/default.ini";
constexpr const char *custom_config_base = "sdmc:/switch/missioncontrol/profiles/config_";
constexpr const char *config_file_location = "sdmc:/config/MissionControl/missioncontrol.ini";
constexpr const char *cp_default_location = "sdmc:/config/MissionControl/profiles/default.ini";
constexpr const char *custom_config_base = "sdmc:/config/MissionControl/profiles/config_";

MissionControlConfig g_global_config = {
.general = {
Expand Down

0 comments on commit 2bec6c2

Please sign in to comment.