2021-02-20 23:16:23 +00:00
|
|
|
/*
|
2023-02-23 20:57:56 +00:00
|
|
|
* Copyright (c) 2020-2023 ndeadly
|
2021-02-20 23:16:23 +00:00
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or modify it
|
|
|
|
* under the terms and conditions of the GNU General Public License,
|
|
|
|
* version 2, as published by the Free Software Foundation.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope it will be useful, but WITHOUT
|
|
|
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
|
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
|
|
|
* more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
*/
|
|
|
|
#include <stratosphere.hpp>
|
|
|
|
#include "mcmitm_config.hpp"
|
|
|
|
|
|
|
|
namespace ams::mitm {
|
|
|
|
|
|
|
|
namespace {
|
|
|
|
|
2021-07-11 17:40:24 +00:00
|
|
|
constexpr const char *config_file_location = "sdmc:/config/MissionControl/missioncontrol.ini";
|
2021-02-20 23:16:23 +00:00
|
|
|
|
2022-03-24 08:04:58 +00:00
|
|
|
SetLanguage g_system_language;
|
|
|
|
|
2021-02-20 23:16:23 +00:00
|
|
|
MissionControlConfig g_global_config = {
|
|
|
|
.general = {
|
|
|
|
.enable_rumble = true,
|
|
|
|
.enable_motion = true
|
2021-05-31 21:56:03 +00:00
|
|
|
},
|
|
|
|
.misc = {
|
2023-05-16 21:17:58 +00:00
|
|
|
.analog_trigger_activation_threshold = 50,
|
2023-04-11 13:56:48 +00:00
|
|
|
.dualshock3_led_mode = 0,
|
2023-03-07 11:22:30 +00:00
|
|
|
.dualshock4_polling_rate = 8,
|
2023-03-07 10:53:10 +00:00
|
|
|
.dualshock4_lightbar_brightness = 5,
|
|
|
|
.dualsense_lightbar_brightness = 5,
|
2023-03-07 10:56:32 +00:00
|
|
|
.dualsense_enable_player_leds = true,
|
2022-09-14 17:37:09 +00:00
|
|
|
.dualsense_vibration_intensity = 4
|
2021-02-20 23:16:23 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
void ParseBoolean(const char *value, bool *out) {
|
|
|
|
if (strcasecmp(value, "true") == 0)
|
|
|
|
*out = true;
|
|
|
|
else if (strcasecmp(value, "false") == 0)
|
|
|
|
*out = false;
|
|
|
|
}
|
|
|
|
|
2022-09-14 17:37:09 +00:00
|
|
|
void ParseInt(const char *value, int *out, int min=INT_MIN, int max=INT_MAX) {
|
2022-09-14 21:24:03 +00:00
|
|
|
int tmp = std::strtol(value, nullptr, 10);
|
2023-02-22 21:25:51 +00:00
|
|
|
if ((tmp >= min) && (tmp <= max)) {
|
2022-09-14 17:37:09 +00:00
|
|
|
*out = tmp;
|
2023-02-22 21:25:51 +00:00
|
|
|
}
|
2022-09-14 17:37:09 +00:00
|
|
|
}
|
|
|
|
|
2021-02-20 23:16:23 +00:00
|
|
|
void ParseBluetoothAddress(const char *value, bluetooth::Address *out) {
|
|
|
|
// Check length of address string is correct
|
2023-02-22 21:25:51 +00:00
|
|
|
if (std::strlen(value) != 3*sizeof(bluetooth::Address) - 1) {
|
|
|
|
return;
|
|
|
|
}
|
2021-02-20 23:16:23 +00:00
|
|
|
|
|
|
|
// Parse bluetooth mac address
|
|
|
|
char buf[2 + 1];
|
|
|
|
bluetooth::Address address = {};
|
2023-02-22 21:25:51 +00:00
|
|
|
for (u32 i = 0; i < sizeof(bluetooth::Address); ++i) {
|
2021-02-20 23:16:23 +00:00
|
|
|
// Convert hex pair to number
|
|
|
|
std::memcpy(buf, &value[i*3], 2);
|
2023-02-22 21:25:51 +00:00
|
|
|
address.address[i] = static_cast<u8>(std::strtoul(buf, nullptr, 16));
|
2021-02-20 23:16:23 +00:00
|
|
|
|
|
|
|
// Check for colon separator
|
2023-02-22 21:25:51 +00:00
|
|
|
if ((i < sizeof(bluetooth::Address) - 1) && (value[i*3 + 2] != ':')) {
|
2021-02-20 23:16:23 +00:00
|
|
|
return;
|
2023-02-22 21:25:51 +00:00
|
|
|
}
|
2021-02-20 23:16:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
*out = address;
|
|
|
|
}
|
|
|
|
|
|
|
|
int ConfigIniHandler(void *user, const char *section, const char *name, const char *value) {
|
|
|
|
auto config = reinterpret_cast<MissionControlConfig *>(user);
|
|
|
|
|
|
|
|
if (strcasecmp(section, "general") == 0) {
|
2023-02-22 21:25:51 +00:00
|
|
|
if (strcasecmp(name, "enable_rumble") == 0) {
|
|
|
|
ParseBoolean(value, &config->general.enable_rumble);
|
|
|
|
} else if (strcasecmp(name, "enable_motion") == 0) {
|
|
|
|
ParseBoolean(value, &config->general.enable_motion);
|
|
|
|
}
|
|
|
|
} else if (strcasecmp(section, "bluetooth") == 0) {
|
|
|
|
if (strcasecmp(name, "host_name") == 0) {
|
2021-02-20 23:16:23 +00:00
|
|
|
std::strncpy(config->bluetooth.host_name, value, sizeof(config->bluetooth.host_name));
|
2023-02-22 21:25:51 +00:00
|
|
|
} else if (strcasecmp(name, "host_address") == 0) {
|
2021-02-20 23:16:23 +00:00
|
|
|
ParseBluetoothAddress(value, &config->bluetooth.host_address);
|
2023-02-22 21:25:51 +00:00
|
|
|
}
|
|
|
|
} else if (strcasecmp(section, "misc") == 0) {
|
2023-05-16 21:17:58 +00:00
|
|
|
if (strcasecmp(name, "analog_trigger_activation_threshold") == 0) {
|
|
|
|
ParseInt(value, &config->misc.analog_trigger_activation_threshold, 0, 100);
|
|
|
|
} else if (strcasecmp(name, "dualshock3_led_mode") == 0) {
|
2023-05-10 20:20:36 +00:00
|
|
|
ParseInt(value, &config->misc.dualshock3_led_mode, 0, 2);
|
2023-04-11 13:56:48 +00:00
|
|
|
} else if (strcasecmp(name, "dualshock4_polling_rate") == 0) {
|
2023-03-07 11:22:30 +00:00
|
|
|
ParseInt(value, &config->misc.dualshock4_polling_rate, 0, 16);
|
|
|
|
} else if (strcasecmp(name, "dualshock4_lightbar_brightness") == 0) {
|
2023-03-07 10:53:10 +00:00
|
|
|
ParseInt(value, &config->misc.dualshock4_lightbar_brightness, 0, 9);
|
|
|
|
} else if (strcasecmp(name, "dualsense_lightbar_brightness") == 0) {
|
|
|
|
ParseInt(value, &config->misc.dualsense_lightbar_brightness, 0, 9);
|
2023-03-07 10:56:32 +00:00
|
|
|
} else if (strcasecmp(name, "dualsense_enable_player_leds") == 0) {
|
|
|
|
ParseBoolean(value, &config->misc.dualsense_enable_player_leds);
|
2023-02-22 21:25:51 +00:00
|
|
|
} else if (strcasecmp(name, "dualsense_vibration_intensity") == 0) {
|
2022-09-14 22:00:30 +00:00
|
|
|
ParseInt(value, &config->misc.dualsense_vibration_intensity, 1, 8);
|
2023-02-22 21:25:51 +00:00
|
|
|
}
|
|
|
|
} else {
|
2021-02-20 23:16:23 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2023-07-26 19:55:28 +00:00
|
|
|
void ParseIniConfiguration() {
|
|
|
|
fs::FileHandle file;
|
|
|
|
{
|
|
|
|
if (R_FAILED(fs::OpenFile(std::addressof(file), config_file_location, fs::OpenMode_Read))) {
|
|
|
|
return;
|
|
|
|
}
|
2021-02-20 23:16:23 +00:00
|
|
|
}
|
2023-07-26 19:55:28 +00:00
|
|
|
ON_SCOPE_EXIT { fs::CloseFile(file); };
|
|
|
|
|
|
|
|
util::ini::ParseFile(file, &g_global_config, ConfigIniHandler);
|
2021-02-20 23:16:23 +00:00
|
|
|
}
|
|
|
|
|
2023-07-26 19:55:28 +00:00
|
|
|
void ReadSystemLanguage() {
|
|
|
|
R_ABORT_UNLESS(setInitialize());
|
|
|
|
ON_SCOPE_EXIT { setExit(); };
|
|
|
|
u64 language_code = 0;
|
|
|
|
R_ABORT_UNLESS(setGetSystemLanguage(&language_code));
|
|
|
|
R_ABORT_UNLESS(setMakeLanguage(language_code, &g_system_language));
|
|
|
|
}
|
2021-02-20 23:16:23 +00:00
|
|
|
|
2023-07-26 19:55:28 +00:00
|
|
|
}
|
2022-03-24 08:04:58 +00:00
|
|
|
|
2023-07-26 19:55:28 +00:00
|
|
|
void LoadConfiguration() {
|
|
|
|
ParseIniConfiguration();
|
|
|
|
ReadSystemLanguage();
|
2022-03-24 08:04:58 +00:00
|
|
|
}
|
|
|
|
|
2022-04-08 15:12:59 +00:00
|
|
|
MissionControlConfig *GetGlobalConfig() {
|
2022-03-24 08:04:58 +00:00
|
|
|
return &g_global_config;
|
|
|
|
}
|
|
|
|
|
|
|
|
SetLanguage GetSystemLanguage() {
|
|
|
|
return g_system_language;
|
|
|
|
}
|
|
|
|
|
2021-02-20 23:16:23 +00:00
|
|
|
}
|