From 459b051b589e2cca19d0d9af50f2b42d62d523d3 Mon Sep 17 00:00:00 2001
From: Naxdy <naxdy@naxdy.org>
Date: Wed, 3 Apr 2024 21:38:14 +0200
Subject: [PATCH] feat: implement input filters

---
 src/config.rs       |   7 ++-
 src/input.rs        |   5 ++
 src/input_filter.rs | 109 ++++++++++++++++++++++++++++++++++++++++++++
 src/main.rs         |   1 +
 4 files changed, 120 insertions(+), 2 deletions(-)
 create mode 100644 src/input_filter.rs

diff --git a/src/config.rs b/src/config.rs
index b1514b6..f087179 100644
--- a/src/config.rs
+++ b/src/config.rs
@@ -445,7 +445,7 @@ pub struct OverrideStickState {
 
 #[allow(dead_code)]
 #[derive(Clone, Copy, Debug, Format)]
-enum AwaitableButtons {
+pub enum AwaitableButtons {
     A,
     B,
     X,
@@ -731,7 +731,10 @@ impl<'a, T: RawMutex, const I: usize, const J: usize, const K: usize> WaitForBut
     }
 }
 
-fn is_awaitable_button_pressed(report: &GcReport, button_to_wait_for: &AwaitableButtons) -> bool {
+pub fn is_awaitable_button_pressed(
+    report: &GcReport,
+    button_to_wait_for: &AwaitableButtons,
+) -> bool {
     match button_to_wait_for {
         AwaitableButtons::A => report.buttons_1.button_a,
         AwaitableButtons::B => report.buttons_1.button_b,
diff --git a/src/input.rs b/src/input.rs
index 2e2a759..1d7cfd2 100644
--- a/src/input.rs
+++ b/src/input.rs
@@ -22,6 +22,7 @@ use crate::{
     filter::{run_waveshaping, FilterGains, KalmanState, WaveshapingValues, FILTER_GAINS},
     gcc_hid::GcReport,
     helpers::XyValuePair,
+    input_filter::{DummyFilter, InputFilter},
     stick::{linearize, notch_remap, StickParams},
 };
 
@@ -444,6 +445,9 @@ pub async fn update_button_state_task(
 
     let mut override_stick_state: Option<OverrideStickState> = None;
 
+    // replace this with the input filter of your choice, if you so desire.
+    let mut input_filter = DummyFilter::default();
+
     loop {
         update_button_states(
             &mut gcc_state,
@@ -498,6 +502,7 @@ pub async fn update_button_state_task(
             }
             gcc_publisher.publish_immediate(overriden_gcc_state);
         } else {
+            input_filter.apply_filter(&mut gcc_state);
             gcc_publisher.publish_immediate(gcc_state);
         }
 
diff --git a/src/input_filter.rs b/src/input_filter.rs
new file mode 100644
index 0000000..8074d7f
--- /dev/null
+++ b/src/input_filter.rs
@@ -0,0 +1,109 @@
+use defmt::warn;
+
+use crate::{
+    config::{is_awaitable_button_pressed, AwaitableButtons},
+    gcc_hid::GcReport,
+};
+
+/**
+ * Houses functionality for modifying GCC state before it is sent to the console.
+ */
+
+pub trait InputFilter: Sized {
+    fn apply_filter(&mut self, gcc_state: &mut GcReport);
+}
+
+/// Presses a single button if another button is pressed.
+pub struct SingleButtonMacroFilter {
+    /// The button that will trigger the macro.
+    pub btn_instigator: AwaitableButtons,
+    /// The button that will be pressed alongside the instigator.
+    pub btn_to_press: AwaitableButtons,
+}
+
+impl InputFilter for SingleButtonMacroFilter {
+    fn apply_filter(&mut self, gcc_state: &mut GcReport) {
+        if is_awaitable_button_pressed(gcc_state, &self.btn_instigator) {
+            match self.btn_to_press {
+                AwaitableButtons::A => {
+                    gcc_state.buttons_1.button_a = true;
+                }
+                AwaitableButtons::B => {
+                    gcc_state.buttons_1.button_b = true;
+                }
+                AwaitableButtons::X => {
+                    gcc_state.buttons_1.button_x = true;
+                }
+                AwaitableButtons::Y => {
+                    gcc_state.buttons_1.button_y = true;
+                }
+                AwaitableButtons::L => {
+                    gcc_state.trigger_l = 255;
+                    gcc_state.buttons_2.button_l = true;
+                }
+                AwaitableButtons::R => {
+                    gcc_state.trigger_r = 255;
+                    gcc_state.buttons_2.button_r = true;
+                }
+                AwaitableButtons::Z => {
+                    gcc_state.buttons_2.button_z = true;
+                }
+                AwaitableButtons::Start => {
+                    gcc_state.buttons_2.button_start = true;
+                }
+                AwaitableButtons::Up => {
+                    gcc_state.buttons_1.dpad_up = true;
+                }
+                AwaitableButtons::Down => {
+                    gcc_state.buttons_1.dpad_down = true;
+                }
+                AwaitableButtons::Left => {
+                    gcc_state.buttons_1.dpad_left = true;
+                }
+                AwaitableButtons::Right => {
+                    gcc_state.buttons_1.dpad_right = true;
+                }
+                b => {
+                    warn!(
+                        "Awaitable button {} is not supported by SingleButtonMacroFilter",
+                        b
+                    );
+                }
+            }
+        }
+    }
+}
+
+/// Improves hitting turnaround up & down tilt at the cost
+/// of making it harder to hit down angled forward tilt.
+pub struct CStickUpTiltFilter;
+
+impl InputFilter for CStickUpTiltFilter {
+    fn apply_filter(&mut self, gcc_state: &mut GcReport) {
+        if gcc_state.cstick_y > 157 {
+            if (137..=201).contains(&gcc_state.cstick_x) {
+                gcc_state.cstick_x = 201;
+                gcc_state.cstick_y = 255;
+            } else if (53..=117).contains(&gcc_state.cstick_x) {
+                gcc_state.cstick_x = 53;
+                gcc_state.cstick_y = 255;
+            }
+        } else if gcc_state.cstick_y < 97 {
+            if (137..=221).contains(&gcc_state.cstick_x) {
+                gcc_state.cstick_x = 221;
+                gcc_state.cstick_y = 0;
+            } else if (53..=117).contains(&gcc_state.cstick_x) {
+                gcc_state.cstick_x = 33;
+                gcc_state.cstick_y = 0;
+            }
+        }
+    }
+}
+
+/// Does nothing.
+#[derive(Default)]
+pub struct DummyFilter;
+
+impl InputFilter for DummyFilter {
+    fn apply_filter(&mut self, _gcc_state: &mut GcReport) {}
+}
diff --git a/src/main.rs b/src/main.rs
index 9ccf733..719cf41 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -9,6 +9,7 @@ mod filter;
 mod gcc_hid;
 mod helpers;
 mod input;
+mod input_filter;
 mod stick;
 
 use config::config_task;