From 59c99da458941bff05a3eb8aa3611cbcad244655 Mon Sep 17 00:00:00 2001 From: cathery Date: Thu, 7 Nov 2019 01:20:58 +0300 Subject: [PATCH] Added config files (no remapping yet) --- .gitignore | 3 +- ControllerUSB/include/ControllerConfig.h | 36 +++ ControllerUSB/include/ControllerHelpers.h | 17 ++ ControllerUSB/include/Controllers.h | 116 +------ .../Controllers/Dualshock3Controller.h | 4 + .../Controllers/Dualshock4Controller.h | 4 + .../include/Controllers/Xbox360Controller.h | 4 + .../include/Controllers/XboxOneController.h | 8 +- ControllerUSB/include/IController.h | 1 + ControllerUSB/source/ControllerHelpers.cpp | 114 +++++++ .../Controllers/Dualshock3Controller.cpp | 19 +- .../Controllers/Dualshock4Controller.cpp | 17 +- .../source/Controllers/Xbox360Controller.cpp | 17 +- .../source/Controllers/XboxOneController.cpp | 17 +- MakefileSysmodule | 4 +- inih/ini.c | 284 ++++++++++++++++++ inih/ini.h | 148 +++++++++ libnx | 2 +- source/configFile.cpp | 177 +++++++++++ source/configFile.h | 5 + source/log.h | 3 +- source/mainLoop.cpp | 4 +- 22 files changed, 861 insertions(+), 143 deletions(-) create mode 100644 ControllerUSB/include/ControllerConfig.h create mode 100644 ControllerUSB/include/ControllerHelpers.h create mode 100644 ControllerUSB/source/ControllerHelpers.cpp create mode 100644 inih/ini.c create mode 100644 inih/ini.h create mode 100644 source/configFile.cpp create mode 100644 source/configFile.h diff --git a/.gitignore b/.gitignore index 8e136bf..0e8cf8c 100644 --- a/.gitignore +++ b/.gitignore @@ -11,4 +11,5 @@ buildSysmodule/* *.flag *.rar *.xml -*.png \ No newline at end of file +*.png +*.ini diff --git a/ControllerUSB/include/ControllerConfig.h b/ControllerUSB/include/ControllerConfig.h new file mode 100644 index 0000000..914c9d0 --- /dev/null +++ b/ControllerUSB/include/ControllerConfig.h @@ -0,0 +1,36 @@ +#pragma once +#include +enum ControllerButton +{ + NOT_SET = -1, + FACE_UP, + FACE_RIGHT, + FACE_DOWN, + FACE_LEFT, + LSTICK, + RSTICK, + LSTICK_CLICK, + RSTICK_CLICK, + LEFT_BUMPER, + RIGHT_BUMPER, + LEFT_TRIGGER, + RIGHT_TRIGGER, + BACK, + START, + DPAD_UP, + DPAD_RIGHT, + DPAD_DOWN, + DPAD_LEFT, + SYNC, + GUIDE, +}; + +struct ControllerConfig +{ + uint16_t leftStickDeadzone; + uint16_t rightStickDeadzone; + uint16_t leftStickRotation; + uint16_t rightStickRotation; + uint16_t triggerDeadzone; + ControllerButton buttons[20]; +}; \ No newline at end of file diff --git a/ControllerUSB/include/ControllerHelpers.h b/ControllerUSB/include/ControllerHelpers.h new file mode 100644 index 0000000..510adb9 --- /dev/null +++ b/ControllerUSB/include/ControllerHelpers.h @@ -0,0 +1,17 @@ +#pragma once +#include "Controllers.h" + +//Returns a vector with all vendor IDs +std::vector GetVendors(); + +//Returns all product IDs for specified vendor +std::vector GetVendorProducts(uint16_t vendor_id); + +//Returns a constructed controller derived from IController based on the type +std::unique_ptr ConstructControllerFromType(ControllerType type, std::unique_ptr &&device); + +//Gets the controller type based on vendor + product combo +ControllerType GetControllerTypeFromIds(uint16_t vendor_id, uint16_t product_id); + +//Returns true if said controller supports said feature +bool DoesControllerSupport(ControllerType type, ControllerSupport supportType); \ No newline at end of file diff --git a/ControllerUSB/include/Controllers.h b/ControllerUSB/include/Controllers.h index d0210ea..3e02438 100644 --- a/ControllerUSB/include/Controllers.h +++ b/ControllerUSB/include/Controllers.h @@ -1,120 +1,6 @@ #pragma once -#include -//Catch-all header to include all the controllers + #include "Controllers/Xbox360Controller.h" #include "Controllers/XboxOneController.h" #include "Controllers/Dualshock3Controller.h" #include "Controllers/Dualshock4Controller.h" - -std::vector GetVendors() -{ - return {VENDOR_MICROSOFT, VENDOR_SONY}; -} - -std::vector GetVendorProducts(uint16_t vendor_id) -{ - switch (vendor_id) - { - case VENDOR_MICROSOFT: - return {PRODUCT_XBOX360, - PRODUCT_XBOXONE2013, - PRODUCT_XBOXONE2015, - PRODUCT_XBOXONEELITE, - PRODUCT_XBOXONES, - PRODUCT_XBOXADAPTIVE}; - case VENDOR_SONY: - return {PRODUCT_DUALSHOCK3, - PRODUCT_DUALSHOCK4}; - } - return {}; -} - -std::unique_ptr ConstructControllerFromType(ControllerType type, std::unique_ptr &&device) -{ - - //surely there must be a better way to pass a class type from a function - switch (type) - { - case CONTROLLER_XBOX360: - return std::make_unique(std::move(device)); - case CONTROLLER_XBOXONE: - return std::make_unique(std::move(device)); - case CONTROLLER_DUALSHOCK3: - return std::make_unique(std::move(device)); - case CONTROLLER_DUALSHOCK4: - return std::make_unique(std::move(device)); - default: - break; - } - return std::unique_ptr{}; -} - -ControllerType GetControllerTypeFromIds(uint16_t vendor_id, uint16_t product_id) -{ - switch (vendor_id) - { - case VENDOR_MICROSOFT: - switch (product_id) - { - case PRODUCT_XBOX360: - return CONTROLLER_XBOX360; - case PRODUCT_XBOXONE2013: - case PRODUCT_XBOXONE2015: - case PRODUCT_XBOXONEELITE: - case PRODUCT_XBOXONES: - case PRODUCT_XBOXADAPTIVE: - return CONTROLLER_XBOXONE; - } - break; - case VENDOR_SONY: - switch (product_id) - { - case PRODUCT_DUALSHOCK3: - return CONTROLLER_DUALSHOCK3; - case PRODUCT_DUALSHOCK4: - return CONTROLLER_DUALSHOCK4; - } - break; - default: - break; - } - return CONTROLLER_UNDEFINED; -} - -bool DoesControllerSupport(ControllerType type, ControllerSupport supportType) -{ - switch (type) - { - case CONTROLLER_XBOX360: - if (supportType == SUPPORTS_RUMBLE) - return true; - return false; - case CONTROLLER_XBOXONE: - switch (supportType) - { - case SUPPORTS_RUMBLE: - return true; - case SUPPORTS_BLUETOOTH: - return true; - default: - return false; - } - case CONTROLLER_DUALSHOCK3: - switch (supportType) - { - case SUPPORTS_RUMBLE: - return true; - case SUPPORTS_BLUETOOTH: - return true; - case SUPPORTS_PRESSUREBUTTONS: - return true; - case SUPPORTS_SIXAXIS: - return true; - default: - return false; - } - default: - return false; - } - return false; -} \ No newline at end of file diff --git a/ControllerUSB/include/Controllers/Dualshock3Controller.h b/ControllerUSB/include/Controllers/Dualshock3Controller.h index 619bfc6..55408a2 100644 --- a/ControllerUSB/include/Controllers/Dualshock3Controller.h +++ b/ControllerUSB/include/Controllers/Dualshock3Controller.h @@ -155,10 +155,12 @@ private: Dualshock3ButtonData m_buttonData; + /* int8_t kLeftThumbDeadzone = 10; int8_t kRightThumbDeadzone = 10; int8_t kTriggerMax = 0; int8_t kTriggerDeadzone = 0; + */ public: Dualshock3Controller(std::unique_ptr &&interface); @@ -183,4 +185,6 @@ public: Status SendInitBytes(); Status SetRumble(uint8_t strong_magnitude, uint8_t weak_magnitude); + + static void LoadConfig(const ControllerConfig *config); }; \ No newline at end of file diff --git a/ControllerUSB/include/Controllers/Dualshock4Controller.h b/ControllerUSB/include/Controllers/Dualshock4Controller.h index e68a35d..05479f4 100644 --- a/ControllerUSB/include/Controllers/Dualshock4Controller.h +++ b/ControllerUSB/include/Controllers/Dualshock4Controller.h @@ -51,10 +51,12 @@ private: Dualshock4ButtonData m_buttonData; + /* int16_t kLeftThumbDeadzone = 2000; //7849; int16_t kRightThumbDeadzone = 2000; //8689; uint16_t kTriggerMax = 0; //1023; uint16_t kTriggerDeadzone = 0; //120; + */ public: Dualshock4Controller(std::unique_ptr &&interface); @@ -79,4 +81,6 @@ public: Status SendInitBytes(); Status SetRumble(uint8_t strong_magnitude, uint8_t weak_magnitude); + + static void LoadConfig(const ControllerConfig *config); }; \ No newline at end of file diff --git a/ControllerUSB/include/Controllers/Xbox360Controller.h b/ControllerUSB/include/Controllers/Xbox360Controller.h index 3fce217..0c52fe0 100644 --- a/ControllerUSB/include/Controllers/Xbox360Controller.h +++ b/ControllerUSB/include/Controllers/Xbox360Controller.h @@ -67,11 +67,13 @@ private: IUSBEndpoint *m_outPipe = nullptr; Xbox360ButtonData m_buttonData; + /* int16_t kLeftThumbDeadzone = 8000; //7849; int16_t kRightThumbDeadzone = 8000; //8689; uint16_t kTriggerMax = 0; //1023; uint16_t kTriggerDeadzone = 0; //120; + */ public: Xbox360Controller(std::unique_ptr &&interface); @@ -96,4 +98,6 @@ public: Status SendInitBytes(); Status SetRumble(uint8_t strong_magnitude, uint8_t weak_magnitude); + + static void LoadConfig(const ControllerConfig *config); }; \ No newline at end of file diff --git a/ControllerUSB/include/Controllers/XboxOneController.h b/ControllerUSB/include/Controllers/XboxOneController.h index ae3f80e..ca7a939 100644 --- a/ControllerUSB/include/Controllers/XboxOneController.h +++ b/ControllerUSB/include/Controllers/XboxOneController.h @@ -81,11 +81,15 @@ private: XboxOneButtonData m_buttonData; bool m_GuidePressed{false}; + uint8_t m_rumbleDataCounter = 0; + /* + int16_t kLeftThumbDeadzone = 2500; //7849; int16_t kRightThumbDeadzone = 3500; //8689; uint16_t kTriggerMax = 0; //1023; uint16_t kTriggerDeadzone = 0; //120; - uint8_t m_rumbleDataCounter = 0; + + */ public: XboxOneController(std::unique_ptr &&interface); @@ -111,4 +115,6 @@ public: Status SendInitBytes(); Status WriteAckGuideReport(uint8_t sequence); Status SetRumble(uint8_t strong_magnitude, uint8_t weak_magnitude); + + static void LoadConfig(const ControllerConfig *config); }; \ No newline at end of file diff --git a/ControllerUSB/include/IController.h b/ControllerUSB/include/IController.h index a101a08..34f3c3e 100644 --- a/ControllerUSB/include/IController.h +++ b/ControllerUSB/include/IController.h @@ -1,6 +1,7 @@ #pragma once #include "IUSBDevice.h" #include "ControllerTypes.h" +#include "ControllerConfig.h" #include struct NormalizedButtonData diff --git a/ControllerUSB/source/ControllerHelpers.cpp b/ControllerUSB/source/ControllerHelpers.cpp new file mode 100644 index 0000000..a979438 --- /dev/null +++ b/ControllerUSB/source/ControllerHelpers.cpp @@ -0,0 +1,114 @@ +#include "ControllerHelpers.h" + +std::vector GetVendors() +{ + return {VENDOR_MICROSOFT, VENDOR_SONY}; +} + +std::vector GetVendorProducts(uint16_t vendor_id) +{ + switch (vendor_id) + { + case VENDOR_MICROSOFT: + return {PRODUCT_XBOX360, + PRODUCT_XBOXONE2013, + PRODUCT_XBOXONE2015, + PRODUCT_XBOXONEELITE, + PRODUCT_XBOXONES, + PRODUCT_XBOXADAPTIVE}; + case VENDOR_SONY: + return {PRODUCT_DUALSHOCK3, + PRODUCT_DUALSHOCK4}; + } + return {}; +} + +std::unique_ptr ConstructControllerFromType(ControllerType type, std::unique_ptr &&device) +{ + + //surely there must be a better way to pass a class type from a function + switch (type) + { + case CONTROLLER_XBOX360: + return std::make_unique(std::move(device)); + case CONTROLLER_XBOXONE: + return std::make_unique(std::move(device)); + case CONTROLLER_DUALSHOCK3: + return std::make_unique(std::move(device)); + case CONTROLLER_DUALSHOCK4: + return std::make_unique(std::move(device)); + default: + break; + } + return std::unique_ptr{}; +} + +ControllerType GetControllerTypeFromIds(uint16_t vendor_id, uint16_t product_id) +{ + switch (vendor_id) + { + case VENDOR_MICROSOFT: + switch (product_id) + { + case PRODUCT_XBOX360: + return CONTROLLER_XBOX360; + case PRODUCT_XBOXONE2013: + case PRODUCT_XBOXONE2015: + case PRODUCT_XBOXONEELITE: + case PRODUCT_XBOXONES: + case PRODUCT_XBOXADAPTIVE: + return CONTROLLER_XBOXONE; + } + break; + case VENDOR_SONY: + switch (product_id) + { + case PRODUCT_DUALSHOCK3: + return CONTROLLER_DUALSHOCK3; + case PRODUCT_DUALSHOCK4: + return CONTROLLER_DUALSHOCK4; + } + break; + default: + break; + } + return CONTROLLER_UNDEFINED; +} + +bool DoesControllerSupport(ControllerType type, ControllerSupport supportType) +{ + switch (type) + { + case CONTROLLER_XBOX360: + if (supportType == SUPPORTS_RUMBLE) + return true; + return false; + case CONTROLLER_XBOXONE: + switch (supportType) + { + case SUPPORTS_RUMBLE: + return true; + case SUPPORTS_BLUETOOTH: + return true; + default: + return false; + } + case CONTROLLER_DUALSHOCK3: + switch (supportType) + { + case SUPPORTS_RUMBLE: + return true; + case SUPPORTS_BLUETOOTH: + return true; + case SUPPORTS_PRESSUREBUTTONS: + return true; + case SUPPORTS_SIXAXIS: + return true; + default: + return false; + } + default: + return false; + } + return false; +} \ No newline at end of file diff --git a/ControllerUSB/source/Controllers/Dualshock3Controller.cpp b/ControllerUSB/source/Controllers/Dualshock3Controller.cpp index 6953417..84fecea 100644 --- a/ControllerUSB/source/Controllers/Dualshock3Controller.cpp +++ b/ControllerUSB/source/Controllers/Dualshock3Controller.cpp @@ -1,6 +1,8 @@ #include "Controllers/Dualshock3Controller.h" #include +static ControllerConfig _dualshock3ControllerConfig{}; + Dualshock3Controller::Dualshock3Controller(std::unique_ptr &&interface) : IController(std::move(interface)) { @@ -76,7 +78,7 @@ Status Dualshock3Controller::OpenInterfaces() } void Dualshock3Controller::CloseInterfaces() { - //m_device->Reset(); + m_device->Reset(); m_device->Close(); } @@ -99,10 +101,10 @@ Status Dualshock3Controller::GetInput() float Dualshock3Controller::NormalizeTrigger(uint8_t value) { //If the given value is below the trigger zone, save the calc and return 0, otherwise adjust the value to the deadzone - return value < kTriggerDeadzone + return value < _dualshock3ControllerConfig.triggerDeadzone ? 0 - : static_cast(value - kTriggerDeadzone) / - (kTriggerMax - kTriggerDeadzone); + : static_cast(value - _dualshock3ControllerConfig.triggerDeadzone) / + (UINT8_MAX - _dualshock3ControllerConfig.triggerDeadzone); } void Dualshock3Controller::NormalizeAxis(uint8_t x, @@ -170,9 +172,9 @@ NormalizedButtonData Dualshock3Controller::GetNormalizedButtonData() normalData.left_trigger = m_buttonData.trigger_left; normalData.right_trigger = m_buttonData.trigger_right; - NormalizeAxis(m_buttonData.stick_left_x, m_buttonData.stick_left_y, kLeftThumbDeadzone, + NormalizeAxis(m_buttonData.stick_left_x, m_buttonData.stick_left_y, _dualshock3ControllerConfig.leftStickDeadzone, &normalData.left_stick_x, &normalData.left_stick_y); - NormalizeAxis(m_buttonData.stick_right_x, m_buttonData.stick_right_y, kRightThumbDeadzone, + NormalizeAxis(m_buttonData.stick_right_x, m_buttonData.stick_right_y, _dualshock3ControllerConfig.rightStickDeadzone, &normalData.right_stick_x, &normalData.right_stick_y); return normalData; @@ -182,4 +184,9 @@ Status Dualshock3Controller::SetRumble(uint8_t strong_magnitude, uint8_t weak_ma { //Not implemented yet return 9; +} + +void Dualshock3Controller::LoadConfig(const ControllerConfig *config) +{ + _dualshock3ControllerConfig = *config; } \ No newline at end of file diff --git a/ControllerUSB/source/Controllers/Dualshock4Controller.cpp b/ControllerUSB/source/Controllers/Dualshock4Controller.cpp index ffde658..1b13ebc 100644 --- a/ControllerUSB/source/Controllers/Dualshock4Controller.cpp +++ b/ControllerUSB/source/Controllers/Dualshock4Controller.cpp @@ -1,6 +1,8 @@ #include "Controllers/Dualshock4Controller.h" #include +static ControllerConfig _dualshock4ControllerConfig{}; + Dualshock4Controller::Dualshock4Controller(std::unique_ptr &&interface) : IController(std::move(interface)) { @@ -143,10 +145,10 @@ Status Dualshock4Controller::SendInitBytes() float Dualshock4Controller::NormalizeTrigger(uint16_t value) { //If the given value is below the trigger zone, save the calc and return 0, otherwise adjust the value to the deadzone - return value < kTriggerDeadzone + return value < _dualshock4ControllerConfig.triggerDeadzone ? 0 - : static_cast(value - kTriggerDeadzone) / - (kTriggerMax - kTriggerDeadzone); + : static_cast(value - _dualshock4ControllerConfig.triggerDeadzone) / + (UINT16_MAX - _dualshock4ControllerConfig.triggerDeadzone); } void Dualshock4Controller::NormalizeAxis(int16_t x, @@ -216,9 +218,9 @@ NormalizedButtonData Dualshock4Controller::GetNormalizedButtonData() normalData.left_trigger = NormalizeTrigger(m_buttonData.trigger_left); normalData.right_trigger = NormalizeTrigger(m_buttonData.trigger_right); - NormalizeAxis(m_buttonData.stick_left_x, m_buttonData.stick_left_y, kLeftThumbDeadzone, + NormalizeAxis(m_buttonData.stick_left_x, m_buttonData.stick_left_y, _dualshock4ControllerConfig.leftStickDeadzone, &normalData.left_stick_x, &normalData.left_stick_y); - NormalizeAxis(m_buttonData.stick_right_x, m_buttonData.stick_right_y, kRightThumbDeadzone, + NormalizeAxis(m_buttonData.stick_right_x, m_buttonData.stick_right_y, _dualshock4ControllerConfig.rightStickDeadzone, &normalData.right_stick_x, &normalData.right_stick_y); return normalData; @@ -237,4 +239,9 @@ Status Dualshock4Controller::SetRumble(uint8_t strong_magnitude, uint8_t weak_ma 0xff, 0x00, 0x00}; return m_outPipe->Write(rumble_data, sizeof(rumble_data)); */ +} + +void Dualshock4Controller::LoadConfig(const ControllerConfig *config) +{ + _dualshock4ControllerConfig = *config; } \ No newline at end of file diff --git a/ControllerUSB/source/Controllers/Xbox360Controller.cpp b/ControllerUSB/source/Controllers/Xbox360Controller.cpp index 01b796e..adc0458 100644 --- a/ControllerUSB/source/Controllers/Xbox360Controller.cpp +++ b/ControllerUSB/source/Controllers/Xbox360Controller.cpp @@ -1,6 +1,8 @@ #include "Controllers/Xbox360Controller.h" #include +static ControllerConfig _xbox360ControllerConfig{}; + Xbox360Controller::Xbox360Controller(std::unique_ptr &&interface) : IController(std::move(interface)) { @@ -110,10 +112,10 @@ Status Xbox360Controller::SendInitBytes() float Xbox360Controller::NormalizeTrigger(uint16_t value) { //If the given value is below the trigger zone, save the calc and return 0, otherwise adjust the value to the deadzone - return value < kTriggerDeadzone + return value < _xbox360ControllerConfig.triggerDeadzone ? 0 - : static_cast(value - kTriggerDeadzone) / - (kTriggerMax - kTriggerDeadzone); + : static_cast(value - _xbox360ControllerConfig.triggerDeadzone) / + (UINT16_MAX - _xbox360ControllerConfig.triggerDeadzone); } void Xbox360Controller::NormalizeAxis(int16_t x, @@ -183,9 +185,9 @@ NormalizedButtonData Xbox360Controller::GetNormalizedButtonData() normalData.left_trigger = NormalizeTrigger(m_buttonData.trigger_left); normalData.right_trigger = NormalizeTrigger(m_buttonData.trigger_right); - NormalizeAxis(m_buttonData.stick_left_x, m_buttonData.stick_left_y, kLeftThumbDeadzone, + NormalizeAxis(m_buttonData.stick_left_x, m_buttonData.stick_left_y, _xbox360ControllerConfig.leftStickDeadzone, &normalData.left_stick_x, &normalData.left_stick_y); - NormalizeAxis(m_buttonData.stick_right_x, m_buttonData.stick_right_y, kRightThumbDeadzone, + NormalizeAxis(m_buttonData.stick_right_x, m_buttonData.stick_right_y, _xbox360ControllerConfig.rightStickDeadzone, &normalData.right_stick_x, &normalData.right_stick_y); return normalData; @@ -195,4 +197,9 @@ Status Xbox360Controller::SetRumble(uint8_t strong_magnitude, uint8_t weak_magni { uint8_t rumbleData[]{0x00, sizeof(Xbox360RumbleData), 0x00, strong_magnitude, weak_magnitude, 0x00, 0x00, 0x00}; return m_outPipe->Write(rumbleData, sizeof(rumbleData)); +} + +void Xbox360Controller::LoadConfig(const ControllerConfig *config) +{ + _xbox360ControllerConfig = *config; } \ No newline at end of file diff --git a/ControllerUSB/source/Controllers/XboxOneController.cpp b/ControllerUSB/source/Controllers/XboxOneController.cpp index 7505236..90ba0ab 100644 --- a/ControllerUSB/source/Controllers/XboxOneController.cpp +++ b/ControllerUSB/source/Controllers/XboxOneController.cpp @@ -1,6 +1,8 @@ #include "Controllers/XboxOneController.h" #include +static ControllerConfig _xboxoneControllerConfig{}; + XboxOneController::XboxOneController(std::unique_ptr &&interface) : IController(std::move(interface)) { @@ -130,10 +132,10 @@ Status XboxOneController::SendInitBytes() float XboxOneController::NormalizeTrigger(uint16_t value) { //If the given value is below the trigger zone, save the calc and return 0, otherwise adjust the value to the deadzone - return value < kTriggerDeadzone + return value < _xboxoneControllerConfig.triggerDeadzone ? 0 - : static_cast(value - kTriggerDeadzone) / - (kTriggerMax - kTriggerDeadzone); + : static_cast(value - _xboxoneControllerConfig.triggerDeadzone) / + (UINT16_MAX - _xboxoneControllerConfig.triggerDeadzone); } void XboxOneController::NormalizeAxis(int16_t x, @@ -203,9 +205,9 @@ NormalizedButtonData XboxOneController::GetNormalizedButtonData() normalData.left_trigger = NormalizeTrigger(m_buttonData.trigger_left); normalData.right_trigger = NormalizeTrigger(m_buttonData.trigger_right); - NormalizeAxis(m_buttonData.stick_left_x, m_buttonData.stick_left_y, kLeftThumbDeadzone, + NormalizeAxis(m_buttonData.stick_left_x, m_buttonData.stick_left_y, _xboxoneControllerConfig.leftStickDeadzone, &normalData.left_stick_x, &normalData.left_stick_y); - NormalizeAxis(m_buttonData.stick_right_x, m_buttonData.stick_right_y, kRightThumbDeadzone, + NormalizeAxis(m_buttonData.stick_right_x, m_buttonData.stick_right_y, _xboxoneControllerConfig.rightStickDeadzone, &normalData.right_stick_x, &normalData.right_stick_y); return normalData; @@ -233,4 +235,9 @@ Status XboxOneController::SetRumble(uint8_t strong_magnitude, uint8_t weak_magni weak_magnitude, 0xff, 0x00, 0x00}; return m_outPipe->Write(rumble_data, sizeof(rumble_data)); +} + +void XboxOneController::LoadConfig(const ControllerConfig *config) +{ + _xboxoneControllerConfig = *config; } \ No newline at end of file diff --git a/MakefileSysmodule b/MakefileSysmodule index f9b2dc8..9665842 100644 --- a/MakefileSysmodule +++ b/MakefileSysmodule @@ -39,9 +39,9 @@ include $(DEVKITPRO)/libnx/switch_rules #--------------------------------------------------------------------------------- TARGET := sys-con BUILD := buildSysmodule -SOURCES := source SwitchUSB/source ControllerUSB/source ControllerUSB/source/Controllers +SOURCES := source SwitchUSB/source ControllerUSB/source ControllerUSB/source/Controllers inih DATA := data -INCLUDES := include SwitchUSB/include ControllerUSB/include +INCLUDES := include SwitchUSB/include ControllerUSB/include inih #ROMFS := romfs #--------------------------------------------------------------------------------- diff --git a/inih/ini.c b/inih/ini.c new file mode 100644 index 0000000..71fed68 --- /dev/null +++ b/inih/ini.c @@ -0,0 +1,284 @@ +/* inih -- simple .INI file parser + +SPDX-License-Identifier: BSD-3-Clause + +Copyright (C) 2009-2019, Ben Hoyt + +inih is released under the New BSD license (see LICENSE.txt). Go to the project +home page for more info: + +https://github.com/benhoyt/inih + +*/ + +#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_WARNINGS) +#define _CRT_SECURE_NO_WARNINGS +#endif + +#include +#include +#include + +#include "ini.h" + +#if !INI_USE_STACK +#include +#endif + +#define MAX_SECTION 50 +#define MAX_NAME 50 + +/* Used by ini_parse_string() to keep track of string parsing state. */ +typedef struct { + const char* ptr; + size_t num_left; +} ini_parse_string_ctx; + +/* Strip whitespace chars off end of given string, in place. Return s. */ +static char* rstrip(char* s) +{ + char* p = s + strlen(s); + while (p > s && isspace((unsigned char)(*--p))) + *p = '\0'; + return s; +} + +/* Return pointer to first non-whitespace char in given string. */ +static char* lskip(const char* s) +{ + while (*s && isspace((unsigned char)(*s))) + s++; + return (char*)s; +} + +/* Return pointer to first char (of chars) or inline comment in given string, + or pointer to null at end of string if neither found. Inline comment must + be prefixed by a whitespace character to register as a comment. */ +static char* find_chars_or_comment(const char* s, const char* chars) +{ +#if INI_ALLOW_INLINE_COMMENTS + int was_space = 0; + while (*s && (!chars || !strchr(chars, *s)) && + !(was_space && strchr(INI_INLINE_COMMENT_PREFIXES, *s))) { + was_space = isspace((unsigned char)(*s)); + s++; + } +#else + while (*s && (!chars || !strchr(chars, *s))) { + s++; + } +#endif + return (char*)s; +} + +/* Version of strncpy that ensures dest (size bytes) is null-terminated. */ +static char* strncpy0(char* dest, const char* src, size_t size) +{ + strncpy(dest, src, size - 1); + dest[size - 1] = '\0'; + return dest; +} + +/* See documentation in header file. */ +int ini_parse_stream(ini_reader reader, void* stream, ini_handler handler, + void* user) +{ + /* Uses a fair bit of stack (use heap instead if you need to) */ +#if INI_USE_STACK + char line[INI_MAX_LINE]; + int max_line = INI_MAX_LINE; +#else + char* line; + int max_line = INI_INITIAL_ALLOC; +#endif +#if INI_ALLOW_REALLOC && !INI_USE_STACK + char* new_line; + int offset; +#endif + char section[MAX_SECTION] = ""; + char prev_name[MAX_NAME] = ""; + + char* start; + char* end; + char* name; + char* value; + int lineno = 0; + int error = 0; + +#if !INI_USE_STACK + line = (char*)malloc(INI_INITIAL_ALLOC); + if (!line) { + return -2; + } +#endif + +#if INI_HANDLER_LINENO +#define HANDLER(u, s, n, v) handler(u, s, n, v, lineno) +#else +#define HANDLER(u, s, n, v) handler(u, s, n, v) +#endif + + /* Scan through stream line by line */ + while (reader(line, max_line, stream) != NULL) { +#if INI_ALLOW_REALLOC && !INI_USE_STACK + offset = strlen(line); + while (offset == max_line - 1 && line[offset - 1] != '\n') { + max_line *= 2; + if (max_line > INI_MAX_LINE) + max_line = INI_MAX_LINE; + new_line = realloc(line, max_line); + if (!new_line) { + free(line); + return -2; + } + line = new_line; + if (reader(line + offset, max_line - offset, stream) == NULL) + break; + if (max_line >= INI_MAX_LINE) + break; + offset += strlen(line + offset); + } +#endif + + lineno++; + + start = line; +#if INI_ALLOW_BOM + if (lineno == 1 && (unsigned char)start[0] == 0xEF && + (unsigned char)start[1] == 0xBB && + (unsigned char)start[2] == 0xBF) { + start += 3; + } +#endif + start = lskip(rstrip(start)); + + if (strchr(INI_START_COMMENT_PREFIXES, *start)) { + /* Start-of-line comment */ + } +#if INI_ALLOW_MULTILINE + else if (*prev_name && *start && start > line) { + /* Non-blank line with leading whitespace, treat as continuation + of previous name's value (as per Python configparser). */ + if (!HANDLER(user, section, prev_name, start) && !error) + error = lineno; + } +#endif + else if (*start == '[') { + /* A "[section]" line */ + end = find_chars_or_comment(start + 1, "]"); + if (*end == ']') { + *end = '\0'; + strncpy0(section, start + 1, sizeof(section)); + *prev_name = '\0'; +#if INI_CALL_HANDLER_ON_NEW_SECTION + if (!HANDLER(user, section, NULL, NULL) && !error) + error = lineno; +#endif + } + else if (!error) { + /* No ']' found on section line */ + error = lineno; + } + } + else if (*start) { + /* Not a comment, must be a name[=:]value pair */ + end = find_chars_or_comment(start, "=:"); + if (*end == '=' || *end == ':') { + *end = '\0'; + name = rstrip(start); + value = end + 1; +#if INI_ALLOW_INLINE_COMMENTS + end = find_chars_or_comment(value, NULL); + if (*end) + *end = '\0'; +#endif + value = lskip(value); + rstrip(value); + + /* Valid name[=:]value pair found, call handler */ + strncpy0(prev_name, name, sizeof(prev_name)); + if (!HANDLER(user, section, name, value) && !error) + error = lineno; + } + else if (!error) { + /* No '=' or ':' found on name[=:]value line */ +#if INI_ALLOW_NO_VALUE + *end = '\0'; + name = rstrip(start); + if (!HANDLER(user, section, name, NULL) && !error) + error = lineno; +#else + error = lineno; +#endif + } + } + +#if INI_STOP_ON_FIRST_ERROR + if (error) + break; +#endif + } + +#if !INI_USE_STACK + free(line); +#endif + + return error; +} + +/* See documentation in header file. */ +int ini_parse_file(FILE* file, ini_handler handler, void* user) +{ + return ini_parse_stream((ini_reader)fgets, file, handler, user); +} + +/* See documentation in header file. */ +int ini_parse(const char* filename, ini_handler handler, void* user) +{ + FILE* file; + int error; + + file = fopen(filename, "r"); + if (!file) + return -1; + error = ini_parse_file(file, handler, user); + fclose(file); + return error; +} + +/* An ini_reader function to read the next line from a string buffer. This + is the fgets() equivalent used by ini_parse_string(). */ +static char* ini_reader_string(char* str, int num, void* stream) { + ini_parse_string_ctx* ctx = (ini_parse_string_ctx*)stream; + const char* ctx_ptr = ctx->ptr; + size_t ctx_num_left = ctx->num_left; + char* strp = str; + char c; + + if (ctx_num_left == 0 || num < 2) + return NULL; + + while (num > 1 && ctx_num_left != 0) { + c = *ctx_ptr++; + ctx_num_left--; + *strp++ = c; + if (c == '\n') + break; + num--; + } + + *strp = '\0'; + ctx->ptr = ctx_ptr; + ctx->num_left = ctx_num_left; + return str; +} + +/* See documentation in header file. */ +int ini_parse_string(const char* string, ini_handler handler, void* user) { + ini_parse_string_ctx ctx; + + ctx.ptr = string; + ctx.num_left = strlen(string); + return ini_parse_stream((ini_reader)ini_reader_string, &ctx, handler, + user); +} diff --git a/inih/ini.h b/inih/ini.h new file mode 100644 index 0000000..d2e07e6 --- /dev/null +++ b/inih/ini.h @@ -0,0 +1,148 @@ +/* inih -- simple .INI file parser + +SPDX-License-Identifier: BSD-3-Clause + +Copyright (C) 2009-2019, Ben Hoyt + +inih is released under the New BSD license (see LICENSE.txt). Go to the project +home page for more info: + +https://github.com/benhoyt/inih + +*/ + +#ifndef __INI_H__ +#define __INI_H__ + +/* Make this header file easier to include in C++ code */ +#ifdef __cplusplus +extern "C" { +#endif + +#include + +/* Nonzero if ini_handler callback should accept lineno parameter. */ +#ifndef INI_HANDLER_LINENO +#define INI_HANDLER_LINENO 0 +#endif + +/* Typedef for prototype of handler function. */ +#if INI_HANDLER_LINENO +typedef int (*ini_handler)(void* user, const char* section, + const char* name, const char* value, + int lineno); +#else +typedef int (*ini_handler)(void* user, const char* section, + const char* name, const char* value); +#endif + +/* Typedef for prototype of fgets-style reader function. */ +typedef char* (*ini_reader)(char* str, int num, void* stream); + +/* Parse given INI-style file. May have [section]s, name=value pairs + (whitespace stripped), and comments starting with ';' (semicolon). Section + is "" if name=value pair parsed before any section heading. name:value + pairs are also supported as a concession to Python's configparser. + + For each name=value pair parsed, call handler function with given user + pointer as well as section, name, and value (data only valid for duration + of handler call). Handler should return nonzero on success, zero on error. + + Returns 0 on success, line number of first error on parse error (doesn't + stop on first error), -1 on file open error, or -2 on memory allocation + error (only when INI_USE_STACK is zero). +*/ +int ini_parse(const char* filename, ini_handler handler, void* user); + +/* Same as ini_parse(), but takes a FILE* instead of filename. This doesn't + close the file when it's finished -- the caller must do that. */ +int ini_parse_file(FILE* file, ini_handler handler, void* user); + +/* Same as ini_parse(), but takes an ini_reader function pointer instead of + filename. Used for implementing custom or string-based I/O (see also + ini_parse_string). */ +int ini_parse_stream(ini_reader reader, void* stream, ini_handler handler, + void* user); + +/* Same as ini_parse(), but takes a zero-terminated string with the INI data +instead of a file. Useful for parsing INI data from a network socket or +already in memory. */ +int ini_parse_string(const char* string, ini_handler handler, void* user); + +/* Nonzero to allow multi-line value parsing, in the style of Python's + configparser. If allowed, ini_parse() will call the handler with the same + name for each subsequent line parsed. */ +#ifndef INI_ALLOW_MULTILINE +#define INI_ALLOW_MULTILINE 1 +#endif + +/* Nonzero to allow a UTF-8 BOM sequence (0xEF 0xBB 0xBF) at the start of + the file. See https://github.com/benhoyt/inih/issues/21 */ +#ifndef INI_ALLOW_BOM +#define INI_ALLOW_BOM 1 +#endif + +/* Chars that begin a start-of-line comment. Per Python configparser, allow + both ; and # comments at the start of a line by default. */ +#ifndef INI_START_COMMENT_PREFIXES +#define INI_START_COMMENT_PREFIXES ";#" +#endif + +/* Nonzero to allow inline comments (with valid inline comment characters + specified by INI_INLINE_COMMENT_PREFIXES). Set to 0 to turn off and match + Python 3.2+ configparser behaviour. */ +#ifndef INI_ALLOW_INLINE_COMMENTS +#define INI_ALLOW_INLINE_COMMENTS 1 +#endif +#ifndef INI_INLINE_COMMENT_PREFIXES +#define INI_INLINE_COMMENT_PREFIXES ";" +#endif + +/* Nonzero to use stack for line buffer, zero to use heap (malloc/free). */ +#ifndef INI_USE_STACK +#define INI_USE_STACK 1 +#endif + +/* Maximum line length for any line in INI file (stack or heap). Note that + this must be 3 more than the longest line (due to '\r', '\n', and '\0'). */ +#ifndef INI_MAX_LINE +#define INI_MAX_LINE 200 +#endif + +/* Nonzero to allow heap line buffer to grow via realloc(), zero for a + fixed-size buffer of INI_MAX_LINE bytes. Only applies if INI_USE_STACK is + zero. */ +#ifndef INI_ALLOW_REALLOC +#define INI_ALLOW_REALLOC 0 +#endif + +/* Initial size in bytes for heap line buffer. Only applies if INI_USE_STACK + is zero. */ +#ifndef INI_INITIAL_ALLOC +#define INI_INITIAL_ALLOC 200 +#endif + +/* Stop parsing on first error (default is to keep parsing). */ +#ifndef INI_STOP_ON_FIRST_ERROR +#define INI_STOP_ON_FIRST_ERROR 0 +#endif + +/* Nonzero to call the handler at the start of each new section (with + name and value NULL). Default is to only call the handler on + each name=value pair. */ +#ifndef INI_CALL_HANDLER_ON_NEW_SECTION +#define INI_CALL_HANDLER_ON_NEW_SECTION 0 +#endif + +/* Nonzero to allow a name without a value (no '=' or ':' on the line) and + call the handler with value NULL in this case. Default is to treat + no-value lines as an error. */ +#ifndef INI_ALLOW_NO_VALUE +#define INI_ALLOW_NO_VALUE 0 +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* __INI_H__ */ diff --git a/libnx b/libnx index 3204e55..767cb9a 160000 --- a/libnx +++ b/libnx @@ -1 +1 @@ -Subproject commit 3204e5581f7fac3d7b9872d08a37ea5f93c756b7 +Subproject commit 767cb9a1d1b8f25d1b209065a9c3ae5762ae577b diff --git a/source/configFile.cpp b/source/configFile.cpp new file mode 100644 index 0000000..3453416 --- /dev/null +++ b/source/configFile.cpp @@ -0,0 +1,177 @@ +#include "configFile.h" +#include "Controllers.h" +#include "ControllerConfig.h" + +#include "switch/result.h" +#include +#include +#include "ini.h" +#include "log.h" + +#define GLOBALCONFIG "config_global.ini" + +#define XBOX360CONFIG "config_xbox360.ini" +#define XBOXONECONFIG "config_xboxone.ini" +#define DUALSHOCK3CONFIG "config_dualshock3.ini" +#define DUALSHOCK4CONFIG "config_dualshock4.ini" + +std::array keyNames{ + "FACE_UP", + "FACE_RIGHT", + "FACE_DOWN", + "FACE_LEFT", + "LSTICK", + "RSTICK", + "LSTICK_CLICK", + "RSTICK_CLICK", + "LEFT_BUMPER", + "RIGHT_BUMPER", + "LEFT_TRIGGER", + "RIGHT_TRIGGER", + "BACK", + "START", + "DPAD_UP", + "DPAD_RIGHT", + "DPAD_DOWN", + "DPAD_LEFT", + "SYNC", + "GUIDE", +}; + +static ControllerButton _StringToKey(const char *text) +{ + for (int i = 0; i != keyNames.size(); ++i) + { + if (keyNames[i] == text) + { + return static_cast(i); + } + } + return NOT_SET; +} + +static ControllerConfig temp_config; + +static int _ParseConfigLine(void *dummy, const char *section, const char *name, const char *value) +{ + if (strncmp(name, "key_", 4) == 0) + { + ControllerButton button = _StringToKey(name + 4); + ControllerButton buttonValue = _StringToKey(value); + temp_config.buttons[button] = buttonValue; + return 1; + } + else if (strcmp(name, "left_stick_deadzone") == 0) + { + temp_config.leftStickDeadzone = atoi(value); + return 1; + } + else if (strcmp(name, "right_stick_deadzone") == 0) + { + temp_config.rightStickDeadzone = atoi(value); + return 1; + } + else if (strcmp(name, "left_stick_rotation") == 0) + { + temp_config.leftStickRotation = atoi(value); + return 1; + } + else if (strcmp(name, "right_stick_rotation") == 0) + { + temp_config.rightStickRotation = atoi(value); + return 1; + } + else if (strcmp(name, "trigger_deadzone") == 0) + { + temp_config.triggerDeadzone = atoi(value); + return 1; + } + + return 0; +} + +static Result _ReadFromConfig(const char *path) +{ + temp_config = {}; + return ini_parse(path, _ParseConfigLine, NULL); +} + +void LoadAllConfigs() +{ + if (R_SUCCEEDED(_ReadFromConfig(CONFIG_PATH XBOXONECONFIG))) + XboxOneController::LoadConfig(&temp_config); + else + WriteToLog("Failed to read from xbox one config!"); + + if (R_SUCCEEDED(_ReadFromConfig(CONFIG_PATH XBOX360CONFIG))) + Xbox360Controller::LoadConfig(&temp_config); + else + WriteToLog("Failed to read from xbox 360 config!"); + + if (R_SUCCEEDED(_ReadFromConfig(CONFIG_PATH DUALSHOCK3CONFIG))) + Dualshock3Controller::LoadConfig(&temp_config); + else + WriteToLog("Failed to read from dualshock 3 config!"); + + if (R_SUCCEEDED(_ReadFromConfig(CONFIG_PATH DUALSHOCK4CONFIG))) + Dualshock4Controller::LoadConfig(&temp_config); + else + WriteToLog("Failed to read from dualshock 4 config!"); +} + +/* +//Config example +[config_global.ini] +left_stick_deadzone = 0 +right_stick_deadzone = 0 +left_stick_rotation = 0 +right_stick_rotation = 0 +trigger_deadzone = 0 +key_FACE_UP = FACE_UP +key_FACE_RIGHT = FACE_RIGHT +key_FACE_DOWN = FACE_DOWN +key_FACE_LEFT = FACE_LEFT +key_LSTICK = LSTICK +key_RSTICK = RSTICK +key_LSTICK_CLICK = LSTICK_CLICK +key_RSTICK_CLICK = RSTICK_CLICK +key_LEFT_BUMPER = LEFT_BUMPER +key_RIGHT_BUMPER = RIGHT_BUMPER +key_LEFT_TRIGGER = LEFT_TRIGGER +key_RIGHT_TRIGGER = RIGHT_TRIGGER +key_BACK = BACK +key_START = START +key_DPAD_UP = DPAD_UP +key_DPAD_RIGHT = DPAD_RIGHT +key_DPAD_DOWN = DPAD_DOWN; +key_DPAD_LEFT = DPAD_LEFT +key_SYNC = SYNC +key_GUIDE = GUIDE + +[config_xboxone.ini] +left_stick_deadzone = 2500 +right_stick_deadzone = 3500 +left_stick_rotation = 0 +right_stick_rotation = 0 +trigger_deadzone = 0 +key_FACE_UP = FACE_UP +key_FACE_RIGHT = FACE_RIGHT +key_FACE_DOWN = FACE_DOWN +key_FACE_LEFT = FACE_LEFT +key_LSTICK = LSTICK +key_RSTICK = RSTICK +key_LSTICK_CLICK = LSTICK_CLICK +key_RSTICK_CLICK = RSTICK_CLICK +key_LEFT_BUMPER = LEFT_BUMPER +key_RIGHT_BUMPER = RIGHT_BUMPER +key_LEFT_TRIGGER = LEFT_TRIGGER +key_RIGHT_TRIGGER = RIGHT_TRIGGER +key_BACK = BACK +key_START = START +key_DPAD_UP = DPAD_UP +key_DPAD_RIGHT = DPAD_RIGHT +key_DPAD_DOWN = DPAD_DOWN; +key_DPAD_LEFT = DPAD_LEFT +key_SYNC = SYNC +key_GUIDE = GUIDE +*/ diff --git a/source/configFile.h b/source/configFile.h new file mode 100644 index 0000000..90dd1ab --- /dev/null +++ b/source/configFile.h @@ -0,0 +1,5 @@ +#pragma once + +#define CONFIG_PATH "/config/sys-con/" + +void LoadAllConfigs(); \ No newline at end of file diff --git a/source/log.h b/source/log.h index 77409b2..51124a2 100644 --- a/source/log.h +++ b/source/log.h @@ -2,6 +2,7 @@ #include #include #include +#include "configFile.h" template void WriteToLog(T &&... text) @@ -21,7 +22,7 @@ void WriteToLog(T &&... text) struct tm *time = localtime((const time_t *)&unixTime); fstream fs; - fs.open("/atmosphere/titles/690000000000000D/log.txt", fstream::app); + fs.open(CONFIG_PATH "log.txt", fstream::app); //Print time fs << setfill('0'); diff --git a/source/mainLoop.cpp b/source/mainLoop.cpp index 6a6e4e5..acf5b7a 100644 --- a/source/mainLoop.cpp +++ b/source/mainLoop.cpp @@ -3,9 +3,10 @@ #include "log.h" #include "SwitchUSBDevice.h" -#include "Controllers.h" +#include "ControllerHelpers.h" #include "SwitchHDLHandler.h" #include "SwitchAbstractedPadHandler.h" +#include "configFile.h" struct VendorEvent { @@ -48,6 +49,7 @@ Result mainLoop() } controllerInterfaces.reserve(8); + LoadAllConfigs(); while (appletMainLoop()) {