shithub: m8c

Download patch

ref: a6a0098d0d37998ace5b3df4b57cd842d4c3922f
parent: 7f4526eeeb658bdcf04d7c8428c91c3286810f82
author: Jonne Kokkonen <jonne.kokkonen@gmail.com>
date: Tue Nov 30 18:25:44 EST 2021

rewrite gamepad input code

--- a/config.c
+++ b/config.c
@@ -25,15 +25,25 @@
   c.key_delete      = SDL_SCANCODE_DELETE;
   c.key_reset       = SDL_SCANCODE_R;
 
-  c.gamepad_up                = SDL_CONTROLLER_BUTTON_DPAD_UP;
-  c.gamepad_left              = SDL_CONTROLLER_BUTTON_DPAD_LEFT;
-  c.gamepad_down              = SDL_CONTROLLER_BUTTON_DPAD_DOWN;
-  c.gamepad_right             = SDL_CONTROLLER_BUTTON_DPAD_RIGHT;
-  c.gamepad_select            = SDL_CONTROLLER_BUTTON_BACK;
-  c.gamepad_start             = SDL_CONTROLLER_BUTTON_START;
-  c.gamepad_opt               = SDL_CONTROLLER_BUTTON_B;
-  c.gamepad_edit              = SDL_CONTROLLER_BUTTON_A;
-  c.gamepad_analog_threshold  = 32767;
+  c.gamepad_up                    = SDL_CONTROLLER_BUTTON_DPAD_UP;
+  c.gamepad_left                  = SDL_CONTROLLER_BUTTON_DPAD_LEFT;
+  c.gamepad_down                  = SDL_CONTROLLER_BUTTON_DPAD_DOWN;
+  c.gamepad_right                 = SDL_CONTROLLER_BUTTON_DPAD_RIGHT;
+  c.gamepad_select                = SDL_CONTROLLER_BUTTON_BACK;
+  c.gamepad_start                 = SDL_CONTROLLER_BUTTON_START;
+  c.gamepad_opt                   = SDL_CONTROLLER_BUTTON_B;
+  c.gamepad_edit                  = SDL_CONTROLLER_BUTTON_A;
+
+  c.gamepad_analog_threshold      = 32767;
+  c.gamepad_analog_invert         = 0;
+  c.gamepad_analog_axis_updown    = SDL_CONTROLLER_AXIS_LEFTY;
+  c.gamepad_analog_axis_leftright = SDL_CONTROLLER_AXIS_LEFTX;
+  c.gamepad_analog_axis_start     = SDL_CONTROLLER_AXIS_TRIGGERRIGHT;
+  c.gamepad_analog_axis_select    = SDL_CONTROLLER_AXIS_TRIGGERLEFT;
+  c.gamepad_analog_axis_opt       = SDL_CONTROLLER_AXIS_INVALID;
+  c.gamepad_analog_axis_edit      = SDL_CONTROLLER_AXIS_INVALID;
+
+
   return c;
 }
 
@@ -99,23 +109,43 @@
 void read_gamepad_config(ini_t *ini, config_params_s *conf) {
   // TODO: Some form of validation
 
-  const char *gamepad_up                = ini_get(ini, "gamepad", "gamepad_up");
-  const char *gamepad_left              = ini_get(ini, "gamepad", "gamepad_left");
-  const char *gamepad_down              = ini_get(ini, "gamepad", "gamepad_down");
-  const char *gamepad_right             = ini_get(ini, "gamepad", "gamepad_right");
-  const char *gamepad_select            = ini_get(ini, "gamepad", "gamepad_select");
-  const char *gamepad_start             = ini_get(ini, "gamepad", "gamepad_start");
-  const char *gamepad_opt               = ini_get(ini, "gamepad", "gamepad_opt");
-  const char *gamepad_edit              = ini_get(ini, "gamepad", "gamepad_edit");
-  const char *gamepad_analog_threshold  = ini_get(ini, "gamepad", "gamepad_analog_threshold");
+  const char *gamepad_up                    = ini_get(ini, "gamepad", "gamepad_up");
+  const char *gamepad_left                  = ini_get(ini, "gamepad", "gamepad_left");
+  const char *gamepad_down                  = ini_get(ini, "gamepad", "gamepad_down");
+  const char *gamepad_right                 = ini_get(ini, "gamepad", "gamepad_right");
+  const char *gamepad_select                = ini_get(ini, "gamepad", "gamepad_select");
+  const char *gamepad_start                 = ini_get(ini, "gamepad", "gamepad_start");
+  const char *gamepad_opt                   = ini_get(ini, "gamepad", "gamepad_opt");
+  const char *gamepad_edit                  = ini_get(ini, "gamepad", "gamepad_edit");
+  const char *gamepad_analog_threshold      = ini_get(ini, "gamepad", "gamepad_analog_threshold");
+  const char *gamepad_analog_invert         = ini_get(ini, "gamepad", "gamepad_analog_invert");
+  const char *gamepad_analog_axis_updown    = ini_get(ini, "gamepad", "gamepad_analog_axis_updown");
+  const char *gamepad_analog_axis_leftright = ini_get(ini, "gamepad", "gamepad_analog_axis_leftright");
+  const char *gamepad_analog_axis_select    = ini_get(ini, "gamepad", "gamepad_analog_axis_select");
+  const char *gamepad_analog_axis_start     = ini_get(ini, "gamepad", "gamepad_analog_axis_start");
+  const char *gamepad_analog_axis_opt       = ini_get(ini, "gamepad", "gamepad_analog_axis_opt");
+  const char *gamepad_analog_axis_edit      = ini_get(ini, "gamepad", "gamepad_analog_axis_edit");
 
-  conf->gamepad_up                = atoi(gamepad_up);
-  conf->gamepad_left              = atoi(gamepad_left);
-  conf->gamepad_down              = atoi(gamepad_down);
-  conf->gamepad_right             = atoi(gamepad_right);
-  conf->gamepad_select            = atoi(gamepad_select);
-  conf->gamepad_start             = atoi(gamepad_start);
-  conf->gamepad_opt               = atoi(gamepad_opt);
-  conf->gamepad_edit              = atoi(gamepad_edit);
-  conf->gamepad_analog_threshold  = atoi(gamepad_analog_threshold);
+  conf->gamepad_up                    = atoi(gamepad_up);
+  conf->gamepad_left                  = atoi(gamepad_left);
+  conf->gamepad_down                  = atoi(gamepad_down);
+  conf->gamepad_right                 = atoi(gamepad_right);
+  conf->gamepad_select                = atoi(gamepad_select);
+  conf->gamepad_start                 = atoi(gamepad_start);
+  conf->gamepad_opt                   = atoi(gamepad_opt);
+  conf->gamepad_edit                  = atoi(gamepad_edit);
+  conf->gamepad_analog_threshold      = atoi(gamepad_analog_threshold);
+
+  // This obviously requires the parameter to be a lowercase true to enable fullscreen
+  if ( strcmp(gamepad_analog_invert, "true") == 0 ) {
+    conf->gamepad_analog_invert = 1;
+  }
+  else conf->gamepad_analog_invert = 0;
+
+  conf->gamepad_analog_axis_updown    = atoi(gamepad_analog_axis_updown);
+  conf->gamepad_analog_axis_leftright = atoi(gamepad_analog_axis_leftright);
+  conf->gamepad_analog_axis_select    = atoi(gamepad_analog_axis_select);
+  conf->gamepad_analog_axis_start     = atoi(gamepad_analog_axis_start);
+  conf->gamepad_analog_axis_opt       = atoi(gamepad_analog_axis_opt);
+  conf->gamepad_analog_axis_edit      = atoi(gamepad_analog_axis_edit);  
 }
\ No newline at end of file
--- a/config.h
+++ b/config.h
@@ -35,6 +35,14 @@
   int gamepad_edit;
 
   int gamepad_analog_threshold;
+  int gamepad_analog_invert;
+  int gamepad_analog_axis_updown;
+  int gamepad_analog_axis_leftright;
+  int gamepad_analog_axis_start;
+  int gamepad_analog_axis_select;
+  int gamepad_analog_axis_opt;
+  int gamepad_analog_axis_edit;
+
 } config_params_s;
 
 
--- a/config.ini
+++ b/config.ini
@@ -31,4 +31,15 @@
 gamepad_start=6
 gamepad_opt=1
 gamepad_edit=0
-gamepad_analog_threshold=32767 ;the threshold for analog sticks to trigger cursor movement (range: 1-32767)
\ No newline at end of file
+
+gamepad_analog_threshold=32766 ;the threshold for analog sticks to trigger cursor movement (range: 1-32767)
+gamepad_analog_invert=false ;invert up/down and left/right axis (true/false)
+
+; these need to be the decimal value of the controller axis
+; you can use -1 if you do not wish to map the function to an analog axis
+gamepad_analog_axis_updown=1
+gamepad_analog_axis_leftright=0
+gamepad_analog_axis_start=5
+gamepad_analog_axis_select=4
+gamepad_analog_axis_opt=-1
+gamepad_analog_axis_edit=-1
--- a/input.c
+++ b/input.c
@@ -2,6 +2,10 @@
 // Released under the MIT licence, https://opensource.org/licenses/MIT
 
 #include <SDL2/SDL.h>
+#include <SDL2/SDL_events.h>
+#include <SDL2/SDL_gamecontroller.h>
+#include <SDL2/SDL_joystick.h>
+#include <SDL2/SDL_stdinc.h>
 #include <stdio.h>
 
 #include "config.h"
@@ -28,8 +32,8 @@
 uint8_t keyjazz_enabled = 0;
 uint8_t keyjazz_base_octave = 2;
 
-uint8_t keycode = 0;                     // value of the pressed key
-static int controller_axis_released = 1; // is analog axis released
+static uint8_t keycode = 0; // value of the pressed key
+
 input_msg_s key = {normal, 0};
 
 uint8_t toggle_input_keyjazz() {
@@ -219,107 +223,114 @@
   return key;
 }
 
-static input_msg_s handle_game_controller_buttons(SDL_Event *event,
+/*static input_msg_s handle_game_controller_buttons(SDL_Event *event,
                                                   config_params_s *conf,
                                                   uint8_t keyvalue) {
   input_msg_s key = {normal, keyvalue};
 
   if (event->cbutton.button == conf->gamepad_up) {
-    key.value = key_up;
+    key.value |= key_up;
   } else if (event->cbutton.button == conf->gamepad_left) {
-    key.value = key_left;
+    key.value |= key_left;
   } else if (event->cbutton.button == conf->gamepad_down) {
-    key.value = key_down;
+    key.value |= key_down;
   } else if (event->cbutton.button == conf->gamepad_right) {
-    key.value = key_right;
+    key.value |= key_right;
   } else if (event->cbutton.button == conf->gamepad_select) {
-    key.value = key_select;
+    key.value |= key_select;
   } else if (event->cbutton.button == conf->gamepad_start) {
-    key.value = key_start;
+    key.value |= key_start;
   } else if (event->cbutton.button == conf->gamepad_opt) {
-    key.value = key_opt;
+    key.value |= key_opt;
   } else if (event->cbutton.button == conf->gamepad_edit) {
-    key.value = key_edit;
+    key.value |= key_edit;
   } else {
     key.value = 0;
   }
   return key;
+} */
+
+int axis_in_threshold(int axis_value, int threshold) {
+  if (axis_value <= 0 - threshold || axis_value >= threshold) {
+    return 1;
+  } else {
+    return 0;
+  }
 }
 
-// Handle analog sticks and digital pads that emulate analog behavior.
-static input_msg_s handle_game_controller_axis(SDL_Event *event,
-                                               config_params_s *conf,
-                                               uint8_t keyvalue) {
+static int get_game_controller_button(config_params_s *conf,
+                                      SDL_GameController *controller,
+                                      int button) {
 
-  input_msg_s key = {normal, keyvalue};
-  static int active_keys;
+  const int button_mappings[8] = {conf->gamepad_up,     conf->gamepad_down,
+                                  conf->gamepad_left,   conf->gamepad_right,
+                                  conf->gamepad_opt,    conf->gamepad_edit,
+                                  conf->gamepad_select, conf->gamepad_start};
 
-  // If the controller returns to zero position, clear all active directions
-  if (controller_axis_released == 0 &&
-      event->caxis.value > 0 - conf->gamepad_analog_threshold &&
-      event->caxis.value < conf->gamepad_analog_threshold) {
-
-    SDL_LogDebug(
-        SDL_LOG_CATEGORY_INPUT,
-        "Analog controller axis at zero, axis: %d, value: %d, active keys: %d",
-        event->caxis.axis, event->caxis.value, active_keys);
-
-    key.value = active_keys;
-    controller_axis_released = 1;
-    active_keys = 0;
+  if (SDL_GameControllerGetButton(controller, button_mappings[button])) {
+    return 1;
+  } else {
+    switch (button) {
+    case INPUT_UP:
+      return SDL_GameControllerGetAxis(controller,
+                                       conf->gamepad_analog_axis_updown) <
+             -conf->gamepad_analog_threshold;
+    case INPUT_DOWN:
+      return SDL_GameControllerGetAxis(controller,
+                                       conf->gamepad_analog_axis_updown) >
+             conf->gamepad_analog_threshold;
+    case INPUT_LEFT:
+      return SDL_GameControllerGetAxis(controller,
+                                       conf->gamepad_analog_axis_leftright) <
+             -conf->gamepad_analog_threshold;
+    case INPUT_RIGHT:
+      return SDL_GameControllerGetAxis(controller,
+                                       conf->gamepad_analog_axis_leftright) >
+             conf->gamepad_analog_threshold;
+    case INPUT_OPT:
+      return SDL_GameControllerGetAxis(controller,
+                                       conf->gamepad_analog_axis_opt) >
+             conf->gamepad_analog_threshold;
+    case INPUT_EDIT:
+      return SDL_GameControllerGetAxis(controller,
+                                       conf->gamepad_analog_axis_edit) >
+             conf->gamepad_analog_threshold;
+    case INPUT_SELECT:
+      return SDL_GameControllerGetAxis(controller,
+                                       conf->gamepad_analog_axis_select) >
+             conf->gamepad_analog_threshold;
+    case INPUT_START:
+      return SDL_GameControllerGetAxis(controller,
+                                       conf->gamepad_analog_axis_start) >
+             conf->gamepad_analog_threshold;
+    default:
+      return 0;
+    }
   }
+  return 0;
+}
 
-  // Handle up-down movement
-  if (event->caxis.axis == SDL_CONTROLLER_AXIS_LEFTY ||
-      event->caxis.axis == SDL_CONTROLLER_AXIS_RIGHTY) {
+// Handle game controllers, simply check all buttons and analog axis on every
+// cycle
+static int handle_game_controller_buttons(config_params_s *conf) {
 
-    if (event->caxis.value >= conf->gamepad_analog_threshold) {
+  const int keycodes[8] = {key_up,  key_down, key_left,   key_right,
+                           key_opt, key_edit, key_select, key_start};
 
-      active_keys |= key_down;
-      key.value = active_keys;
-      controller_axis_released = 0;
+  int key = 0;
 
-      SDL_LogDebug(
-          SDL_LOG_CATEGORY_INPUT,
-          "Analog controller axis down, axis: %d, value: %d, active keys: %d",
-          event->caxis.axis, event->caxis.value, active_keys);
-
-    } else if (event->caxis.value <= 0 - conf->gamepad_analog_threshold) {
-
-      active_keys |= key_up;
-      key.value = active_keys;
-      controller_axis_released = 0;
-
-      SDL_LogDebug(
-          SDL_LOG_CATEGORY_INPUT,
-          "Analog controller axis up, axis: %d, value: %d, active keys: %d",
-          event->caxis.axis, event->caxis.value, active_keys);
+  // Cycle through every active game controller
+  for (int gc = 0; gc < SDL_NumJoysticks(); gc++) {
+    // Cycle through all M8 buttons
+    for (int button = 0; button < (input_buttons_t)INPUT_MAX; button++) {
+      // If the button is active, add the keycode to the variable containing
+      // active keys
+      if (get_game_controller_button(conf, game_controllers[gc], button)) {
+        key |= keycodes[button];
+      }
     }
   }
 
-  // Handle left-right movement
-  else if (event->caxis.axis == SDL_CONTROLLER_AXIS_LEFTX ||
-           event->caxis.axis == SDL_CONTROLLER_AXIS_RIGHTX) {
-    if (event->caxis.value >= conf->gamepad_analog_threshold) {
-
-      active_keys |= key_right;
-      key.value = active_keys;
-      controller_axis_released = 0;
-      SDL_LogDebug(
-          SDL_LOG_CATEGORY_INPUT,
-          "Analog controller axis right, axis: %d, value: %d, active keys: %d",
-          event->caxis.axis, event->caxis.value, active_keys);
-    } else if (event->caxis.value <= 0 - conf->gamepad_analog_threshold) {
-      active_keys |= key_left;
-      key.value = active_keys;
-      controller_axis_released = 0;
-      SDL_LogDebug(
-          SDL_LOG_CATEGORY_INPUT,
-          "Analog controller axis left, axis: %d, value: %d, active keys: %d",
-          event->caxis.axis, event->caxis.value, active_keys);
-    }
-  }
-
   return key;
 }
 
@@ -326,8 +337,17 @@
 // Handles SDL input events
 void handle_sdl_events(config_params_s *conf) {
 
+  static int prev_key_analog = 0;
+
   SDL_Event event;
 
+  // Read joysticks
+  int key_analog = handle_game_controller_buttons(conf);
+  if (prev_key_analog != key_analog) {
+    keycode = key_analog;
+    prev_key_analog = key_analog;
+  }
+
   SDL_PollEvent(&event);
 
   switch (event.type) {
@@ -372,35 +392,29 @@
       key = handle_keyjazz(&event, key.value);
     break;
 
-  // Game controller events
-  case SDL_CONTROLLERBUTTONDOWN:
-  case SDL_CONTROLLERBUTTONUP:
-    key = handle_game_controller_buttons(&event, conf, 0);
-    break;
-
-  case SDL_CONTROLLERAXISMOTION:
-    key = handle_game_controller_axis(&event, conf, 0);
-    break;
-
   default:
     break;
   }
 
-  // Do not allow pressing multiple keys with keyjazz
-  if (key.type == normal) {
-
-    if (event.type == SDL_KEYDOWN || event.type == SDL_CONTROLLERBUTTONDOWN ||
-        controller_axis_released == 0) {
+  switch (key.type) {
+  case normal:
+    if (event.type == SDL_KEYDOWN) {
       keycode |= key.value;
     } else {
       keycode &= ~key.value;
     }
-
-  } else {
-    if (event.type == SDL_KEYDOWN)
+    break;
+  case keyjazz:
+    // Do not allow pressing multiple keys with keyjazz
+  case special:
+    if (event.type == SDL_KEYDOWN) {
       keycode = key.value;
-    else
+    } else {
       keycode = 0;
+    }
+    break;
+  default:
+    break;
   }
 }
 
--- a/input.h
+++ b/input.h
@@ -6,6 +6,18 @@
 
 #include <stdint.h>
 
+typedef enum input_buttons_t {
+    INPUT_UP,
+    INPUT_DOWN,
+    INPUT_LEFT,
+    INPUT_RIGHT,
+    INPUT_OPT,
+    INPUT_EDIT,
+    INPUT_SELECT,
+    INPUT_START,
+    INPUT_MAX
+} input_buttons_t;
+
 typedef enum input_type_t {
   normal,
   keyjazz,
--- a/render.c
+++ b/render.c
@@ -4,9 +4,6 @@
 #include "render.h"
 
 #include <SDL2/SDL.h>
-#include <SDL2/SDL_log.h>
-#include <SDL2/SDL_pixels.h>
-#include <SDL2/SDL_render.h>
 #include <stdio.h>
 
 #include "SDL2_inprint.h"
@@ -59,7 +56,7 @@
   prepare_inline_font();
 
   // Uncomment this for debug level logging
-  //  SDL_LogSetAllPriority(SDL_LOG_PRIORITY_DEBUG);
+  //SDL_LogSetAllPriority(SDL_LOG_PRIORITY_DEBUG);
 
   return 1;
 }
--