diff --git a/assets/config_menu/general.rml b/assets/config_menu/general.rml
index 241dab3..93c8e74 100644
--- a/assets/config_menu/general.rml
+++ b/assets/config_menu/general.rml
@@ -92,6 +92,24 @@
/>
+
+
+
+
+
+
+
+
diff --git a/include/recomp_input.h b/include/recomp_input.h
index 0b1600e..44946e9 100644
--- a/include/recomp_input.h
+++ b/include/recomp_input.h
@@ -129,8 +129,10 @@ namespace recomp {
// Gyro and mouse sensitivities range from 0 to 100.
int get_gyro_sensitivity();
int get_mouse_sensitivity();
+ float get_joystick_deadzone();
void set_gyro_sensitivity(int strength);
void set_mouse_sensitivity(int strength);
+ void set_joystick_deadzone(float value);
enum class TargetingMode {
Switch,
diff --git a/src/game/config.cpp b/src/game/config.cpp
index 72b8de7..b6d5a07 100644
--- a/src/game/config.cpp
+++ b/src/game/config.cpp
@@ -163,6 +163,7 @@ void save_general_config(const std::filesystem::path& path) {
config_json["rumble_strength"] = recomp::get_rumble_strength();
config_json["gyro_sensitivity"] = recomp::get_gyro_sensitivity();
config_json["mouse_sensitivity"] = recomp::get_mouse_sensitivity();
+ config_json["joystick_deadzone"] = recomp::get_joystick_deadzone();
config_json["autosave_mode"] = recomp::get_autosave_mode();
config_json["debug_mode"] = recomp::get_debug_mode_enabled();
config_file << std::setw(4) << config_json;
@@ -174,6 +175,7 @@ void set_general_settings_from_json(const nlohmann::json& config_json) {
recomp::set_rumble_strength(from_or_default(config_json, "rumble_strength", 25));
recomp::set_gyro_sensitivity(from_or_default(config_json, "gyro_sensitivity", 50));
recomp::set_mouse_sensitivity(from_or_default(config_json, "mouse_sensitivity", is_steam_deck ? 50 : 0));
+ recomp::set_joystick_deadzone(from_or_default(config_json, "joystick_deadzone", 0.0f));
recomp::set_autosave_mode(from_or_default(config_json, "autosave_mode", recomp::AutosaveMode::On));
recomp::set_debug_mode_enabled(from_or_default(config_json, "debug_mode", false));
}
diff --git a/src/game/controls.cpp b/src/game/controls.cpp
index 278f5da..726e674 100644
--- a/src/game/controls.cpp
+++ b/src/game/controls.cpp
@@ -87,14 +87,47 @@ void recomp::get_n64_input(uint16_t* buttons_out, float* x_out, float* y_out) {
cur_buttons |= recomp::get_input_digital(controller_input_mappings[input_index]) ? n64_button_values[i] : 0;
}
+ float joystick_deadzone = recomp::get_joystick_deadzone() / 100.0f;
+
+ float joystick_x = recomp::get_input_analog(controller_input_mappings[(size_t)GameInput::X_AXIS_POS])
+ - recomp::get_input_analog(controller_input_mappings[(size_t)GameInput::X_AXIS_NEG]);
+
+ float joystick_y = recomp::get_input_analog(controller_input_mappings[(size_t)GameInput::Y_AXIS_POS])
+ - recomp::get_input_analog(controller_input_mappings[(size_t)GameInput::Y_AXIS_NEG]);
+
+ if(fabsf(joystick_x) < joystick_deadzone) {
+ joystick_x = 0.0f;
+ }
+ else {
+ if(joystick_x > 0.0f) {
+ joystick_x -= joystick_deadzone;
+ }
+ else {
+ joystick_x += joystick_deadzone;
+ }
+
+ joystick_x /= (1.0f - joystick_deadzone);
+ }
+
+ if(fabsf(joystick_y) < joystick_deadzone) {
+ joystick_y = 0.0f;
+ }
+ else {
+ if(joystick_y > 0.0f) {
+ joystick_y -= joystick_deadzone;
+ }
+ else {
+ joystick_y += joystick_deadzone;
+ }
+
+ joystick_y /= (1.0f - joystick_deadzone);
+ }
+
cur_x = recomp::get_input_analog(keyboard_input_mappings[(size_t)GameInput::X_AXIS_POS])
- - recomp::get_input_analog(keyboard_input_mappings[(size_t)GameInput::X_AXIS_NEG])
- + recomp::get_input_analog(controller_input_mappings[(size_t)GameInput::X_AXIS_POS])
- - recomp::get_input_analog(controller_input_mappings[(size_t)GameInput::X_AXIS_NEG]);
+ - recomp::get_input_analog(keyboard_input_mappings[(size_t)GameInput::X_AXIS_NEG]) + joystick_x;
+
cur_y = recomp::get_input_analog(keyboard_input_mappings[(size_t)GameInput::Y_AXIS_POS])
- - recomp::get_input_analog(keyboard_input_mappings[(size_t)GameInput::Y_AXIS_NEG])
- + recomp::get_input_analog(controller_input_mappings[(size_t)GameInput::Y_AXIS_POS])
- - recomp::get_input_analog(controller_input_mappings[(size_t)GameInput::Y_AXIS_NEG]);
+ - recomp::get_input_analog(keyboard_input_mappings[(size_t)GameInput::Y_AXIS_NEG]) + joystick_y;
}
*buttons_out = cur_buttons;
diff --git a/src/ui/ui_config.cpp b/src/ui/ui_config.cpp
index a436120..35eff4c 100644
--- a/src/ui/ui_config.cpp
+++ b/src/ui/ui_config.cpp
@@ -274,6 +274,7 @@ struct ControlOptionsContext {
int rumble_strength; // 0 to 100
int gyro_sensitivity; // 0 to 100
int mouse_sensitivity; // 0 to 100
+ float joystick_deadzone;
recomp::TargetingMode targeting_mode;
recomp::BackgroundInputMode background_input_mode;
recomp::AutosaveMode autosave_mode;
@@ -300,6 +301,10 @@ int recomp::get_mouse_sensitivity() {
return control_options_context.mouse_sensitivity;
}
+float recomp::get_joystick_deadzone() {
+ return control_options_context.joystick_deadzone;
+}
+
void recomp::set_gyro_sensitivity(int sensitivity) {
control_options_context.gyro_sensitivity = sensitivity;
if (general_model_handle) {
@@ -314,6 +319,13 @@ void recomp::set_mouse_sensitivity(int sensitivity) {
}
}
+void recomp::set_joystick_deadzone(float value) {
+ control_options_context.joystick_deadzone = value;
+ if(general_model_handle) {
+ general_model_handle.DirtyVariable("joystick_deadzone");
+ }
+}
+
recomp::TargetingMode recomp::get_targeting_mode() {
return control_options_context.targeting_mode;
}
@@ -848,6 +860,7 @@ public:
constructor.Bind("rumble_strength", &control_options_context.rumble_strength);
constructor.Bind("gyro_sensitivity", &control_options_context.gyro_sensitivity);
constructor.Bind("mouse_sensitivity", &control_options_context.mouse_sensitivity);
+ constructor.Bind("joystick_deadzone", &control_options_context.joystick_deadzone);
bind_option(constructor, "targeting_mode", &control_options_context.targeting_mode);
bind_option(constructor, "background_input_mode", &control_options_context.background_input_mode);
bind_option(constructor, "autosave_mode", &control_options_context.autosave_mode);