From 96574b7204a58cf4f50bb2774b89ab9fcb7bf6cd Mon Sep 17 00:00:00 2001 From: Jonne Kokkonen Date: Mon, 19 Aug 2024 14:18:13 +0300 Subject: [PATCH] #157 split game controller related functions to a separate file --- Makefile | 4 +- src/gamecontrollers.c | 150 +++++++++++++++++++++++++++++++++++++++ src/gamecontrollers.h | 19 +++++ src/input.c | 158 ++---------------------------------------- src/input.h | 14 +++- src/main.c | 7 +- 6 files changed, 192 insertions(+), 160 deletions(-) create mode 100644 src/gamecontrollers.c create mode 100644 src/gamecontrollers.h diff --git a/Makefile b/Makefile index 6514c05..f9c44e3 100644 --- a/Makefile +++ b/Makefile @@ -1,8 +1,8 @@ #Set all your object files (the object files of all the .c files in your project, e.g. main.o my_sub_functions.o ) -OBJ = src/main.o src/serial.o src/slip.o src/command.o src/render.o src/ini.o src/config.o src/input.o src/fx_cube.o src/usb.o src/audio.o src/usb_audio.o src/ringbuffer.o src/inprint2.o +OBJ = src/main.o src/serial.o src/slip.o src/command.o src/render.o src/ini.o src/config.o src/input.o src/gamecontrollers.o src/fx_cube.o src/usb.o src/audio.o src/usb_audio.o src/ringbuffer.o src/inprint2.o #Set any dependant header files so that if they are edited they cause a complete re-compile (e.g. main.h some_subfunctions.h some_definitions_file.h ), or leave blank -DEPS = src/serial.h src/slip.h src/command.h src/render.h src/ini.h src/config.h src/input.h src/fx_cube.h src/audio.h src/ringbuffer.h src/inline_font.h +DEPS = src/serial.h src/slip.h src/command.h src/render.h src/ini.h src/config.h src/input.h src/gamecontrollers.h src/fx_cube.h src/audio.h src/ringbuffer.h src/inline_font.h #Any special libraries you are using in your project (e.g. -lbcm2835 -lrt `pkg-config --libs gtk+-3.0` ), or leave blank INCLUDES = $(shell pkg-config --libs sdl2 libserialport | sed 's/-mwindows//') diff --git a/src/gamecontrollers.c b/src/gamecontrollers.c new file mode 100644 index 0000000..400aefb --- /dev/null +++ b/src/gamecontrollers.c @@ -0,0 +1,150 @@ +// +// Created by jonne on 8/19/24. +// + +#include "gamecontrollers.h" +#include "config.h" +#include "input.h" + +#include + +static int num_joysticks = 0; +SDL_GameController *game_controllers[MAX_CONTROLLERS]; + +// Opens available game controllers and returns the amount of opened controllers +int gamecontrollers_initialize() { + + num_joysticks = SDL_NumJoysticks(); + int controller_index = 0; + + SDL_Log("Looking for game controllers"); + SDL_Delay(10); // Some controllers like XBone wired need a little while to get ready + + // Try to load the game controller database file + char db_filename[1024] = {0}; + snprintf(db_filename, sizeof(db_filename), "%sgamecontrollerdb.txt", SDL_GetPrefPath("", "m8c")); + SDL_Log("Trying to open game controller database from %s", db_filename); + SDL_RWops *db_rw = SDL_RWFromFile(db_filename, "rb"); + if (db_rw == NULL) { + snprintf(db_filename, sizeof(db_filename), "%sgamecontrollerdb.txt", SDL_GetBasePath()); + SDL_Log("Trying to open game controller database from %s", db_filename); + db_rw = SDL_RWFromFile(db_filename, "rb"); + } + + if (db_rw != NULL) { + int mappings = SDL_GameControllerAddMappingsFromRW(db_rw, 1); + if (mappings != -1) + SDL_Log("Found %d game controller mappings", mappings); + else + SDL_LogError(SDL_LOG_CATEGORY_INPUT, "Error loading game controller mappings."); + } else { + SDL_LogError(SDL_LOG_CATEGORY_INPUT, "Unable to open game controller database file."); + } + + // Open all available game controllers + for (int i = 0; i < num_joysticks; i++) { + if (!SDL_IsGameController(i)) + continue; + if (controller_index >= MAX_CONTROLLERS) + break; + game_controllers[controller_index] = SDL_GameControllerOpen(i); + SDL_Log("Controller %d: %s", controller_index + 1, + SDL_GameControllerName(game_controllers[controller_index])); + controller_index++; + } + + return controller_index; +} + +// Closes all open game controllers +void gamecontrollers_close() { + + for (int i = 0; i < MAX_CONTROLLERS; i++) { + if (game_controllers[i]) + SDL_GameControllerClose(game_controllers[i]); + } +} + +// Check whether a button is pressed on a gamepad and return 1 if pressed. +static int get_game_controller_button(config_params_s *conf, SDL_GameController *controller, + int button) { + + 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}; + + // Check digital buttons + if (SDL_GameControllerGetButton(controller, button_mappings[button])) { + return 1; + } + + // If digital button isn't pressed, check the corresponding analog control + 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; + } +} + +// Handle game controllers, simply check all buttons and analog axis on every +// cycle +int gamecontrollers_handle_buttons(config_params_s *conf) { + + const int keycodes[8] = {key_up, key_down, key_left, key_right, + key_opt, key_edit, key_select, key_start}; + + int key = 0; + + // Cycle through every active game controller + for (int gc = 0; gc < num_joysticks; gc++) { + // Cycle through all M8 buttons + for (int button = 0; button < 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]; + } + } + } + + return key; +} + +input_msg_s gamecontrollers_handle_special_messages(config_params_s *conf) { + input_msg_s msg = {0}; + // Read special case game controller buttons quit and reset + for (int gc = 0; gc < num_joysticks; gc++) { + if (SDL_GameControllerGetButton(game_controllers[gc], conf->gamepad_quit) && + (SDL_GameControllerGetButton(game_controllers[gc], conf->gamepad_select) || + SDL_GameControllerGetAxis(game_controllers[gc], conf->gamepad_analog_axis_select))) + msg = (input_msg_s){special, msg_quit}; + else if (SDL_GameControllerGetButton(game_controllers[gc], conf->gamepad_reset) && + (SDL_GameControllerGetButton(game_controllers[gc], conf->gamepad_select) || + SDL_GameControllerGetAxis(game_controllers[gc], conf->gamepad_analog_axis_select))) + msg = (input_msg_s){special, msg_reset_display}; + } + return msg; +} \ No newline at end of file diff --git a/src/gamecontrollers.h b/src/gamecontrollers.h new file mode 100644 index 0000000..30d5182 --- /dev/null +++ b/src/gamecontrollers.h @@ -0,0 +1,19 @@ +// +// Created by jonne on 8/19/24. +// + +#ifndef GAMECONTROLLERS_H_ +#define GAMECONTROLLERS_H_ + +#include "config.h" +#include "input.h" +#include + +#define MAX_CONTROLLERS 4 + +int gamecontrollers_initialize(); +void gamecontrollers_close(); +int gamecontrollers_handle_buttons(config_params_s *conf); +input_msg_s gamecontrollers_handle_special_messages(config_params_s *conf); + +#endif //GAMECONTROLLERS_H_ diff --git a/src/input.c b/src/input.c index 0488a70..e739614 100644 --- a/src/input.c +++ b/src/input.c @@ -7,29 +7,13 @@ #include "config.h" #include "input.h" #include "render.h" - -#define MAX_CONTROLLERS 4 - -SDL_GameController *game_controllers[MAX_CONTROLLERS]; - -// Bits for M8 input messages -enum keycodes { - key_left = 1 << 7, - key_up = 1 << 6, - key_down = 1 << 5, - key_select = 1 << 4, - key_start = 1 << 3, - key_right = 1 << 2, - key_opt = 1 << 1, - key_edit = 1 -}; +#include "gamecontrollers.h" uint8_t keyjazz_enabled = 0; uint8_t keyjazz_base_octave = 2; uint8_t keyjazz_velocity = 0x64; static uint8_t keycode = 0; // value of the pressed key -static int num_joysticks = 0; static input_msg_s key = {normal, 0}; @@ -39,60 +23,6 @@ uint8_t toggle_input_keyjazz() { return keyjazz_enabled; } -// Opens available game controllers and returns the amount of opened controllers -int initialize_game_controllers() { - - num_joysticks = SDL_NumJoysticks(); - int controller_index = 0; - - SDL_Log("Looking for game controllers\n"); - SDL_Delay(10); // Some controllers like XBone wired need a little while to get ready - - // Try to load the game controller database file - char db_filename[1024] = {0}; - snprintf(db_filename, sizeof(db_filename), "%sgamecontrollerdb.txt", SDL_GetPrefPath("", "m8c")); - SDL_Log("Trying to open game controller database from %s", db_filename); - SDL_RWops *db_rw = SDL_RWFromFile(db_filename, "rb"); - if (db_rw == NULL) { - snprintf(db_filename, sizeof(db_filename), "%sgamecontrollerdb.txt", SDL_GetBasePath()); - SDL_Log("Trying to open game controller database from %s", db_filename); - db_rw = SDL_RWFromFile(db_filename, "rb"); - } - - if (db_rw != NULL) { - int mappings = SDL_GameControllerAddMappingsFromRW(db_rw, 1); - if (mappings != -1) - SDL_Log("Found %d game controller mappings", mappings); - else - SDL_LogError(SDL_LOG_CATEGORY_INPUT, "Error loading game controller mappings."); - } else { - SDL_LogError(SDL_LOG_CATEGORY_INPUT, "Unable to open game controller database file."); - } - - // Open all available game controllers - for (int i = 0; i < num_joysticks; i++) { - if (!SDL_IsGameController(i)) - continue; - if (controller_index >= MAX_CONTROLLERS) - break; - game_controllers[controller_index] = SDL_GameControllerOpen(i); - SDL_Log("Controller %d: %s", controller_index + 1, - SDL_GameControllerName(game_controllers[controller_index])); - controller_index++; - } - - return controller_index; -} - -// Closes all open game controllers -void close_game_controllers() { - - for (int i = 0; i < MAX_CONTROLLERS; i++) { - if (game_controllers[i]) - SDL_GameControllerClose(game_controllers[i]); - } -} - static input_msg_s handle_keyjazz(SDL_Event *event, uint8_t keyvalue, config_params_s *conf) { input_msg_s key = {keyjazz, keyvalue, keyjazz_velocity, event->type}; switch (event->key.keysym.scancode) { @@ -259,75 +189,6 @@ static input_msg_s handle_normal_keys(SDL_Event *event, config_params_s *conf, u return key; } -// Check whether a button is pressed on a gamepad and return 1 if pressed. -static int get_game_controller_button(config_params_s *conf, SDL_GameController *controller, - int button) { - - 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}; - - // Check digital buttons - if (SDL_GameControllerGetButton(controller, button_mappings[button])) { - return 1; - } - - // If digital button isn't pressed, check the corresponding analog control - 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 game controllers, simply check all buttons and analog axis on every -// cycle -static int handle_game_controller_buttons(config_params_s *conf) { - - const int keycodes[8] = {key_up, key_down, key_left, key_right, - key_opt, key_edit, key_select, key_start}; - - int key = 0; - - // Cycle through every active game controller - for (int gc = 0; gc < num_joysticks; gc++) { - // Cycle through all M8 buttons - for (int button = 0; button < 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]; - } - } - } - - return key; -} - // Handles SDL input events void handle_sdl_events(config_params_s *conf) { @@ -336,23 +197,14 @@ void handle_sdl_events(config_params_s *conf) { SDL_Event event; // Read joysticks - int key_analog = handle_game_controller_buttons(conf); + int key_analog = gamecontrollers_handle_buttons(conf); if (prev_key_analog != key_analog) { keycode = key_analog; prev_key_analog = key_analog; } - // Read special case game controller buttons quit and reset - for (int gc = 0; gc < num_joysticks; gc++) { - if (SDL_GameControllerGetButton(game_controllers[gc], conf->gamepad_quit) && - (SDL_GameControllerGetButton(game_controllers[gc], conf->gamepad_select) || - SDL_GameControllerGetAxis(game_controllers[gc], conf->gamepad_analog_axis_select))) - key = (input_msg_s){special, msg_quit}; - else if (SDL_GameControllerGetButton(game_controllers[gc], conf->gamepad_reset) && - (SDL_GameControllerGetButton(game_controllers[gc], conf->gamepad_select) || - SDL_GameControllerGetAxis(game_controllers[gc], conf->gamepad_analog_axis_select))) - key = (input_msg_s){special, msg_reset_display}; - } + input_msg_s gcmsg = gamecontrollers_handle_special_messages(conf); + if (gcmsg.type == special) { key = gcmsg; } while (SDL_PollEvent(&event)) { @@ -361,7 +213,7 @@ void handle_sdl_events(config_params_s *conf) { // Reinitialize game controllers on controller add/remove/remap case SDL_CONTROLLERDEVICEADDED: case SDL_CONTROLLERDEVICEREMOVED: - initialize_game_controllers(); + gamecontrollers_initialize(); break; // Handle SDL quit events (for example, window close) diff --git a/src/input.h b/src/input.h index 72de886..ad1bf2c 100644 --- a/src/input.h +++ b/src/input.h @@ -19,6 +19,18 @@ typedef enum input_buttons_t { INPUT_MAX } input_buttons_t; +// Bits for M8 input messages +typedef enum keycodes_t { + key_left = 1 << 7, + key_up = 1 << 6, + key_down = 1 << 5, + key_select = 1 << 4, + key_start = 1 << 3, + key_right = 1 << 2, + key_opt = 1 << 1, + key_edit = 1 +} keycodes_t; + typedef enum input_type_t { normal, keyjazz, special } input_type_t; typedef enum special_messages_t { @@ -34,8 +46,6 @@ typedef struct input_msg_s { uint32_t eventType; } input_msg_s; -int initialize_game_controllers(); -void close_game_controllers(); input_msg_s get_input_msg(config_params_s *conf); #endif diff --git a/src/main.c b/src/main.c index 9dfe12b..b4a2193 100644 --- a/src/main.c +++ b/src/main.c @@ -13,6 +13,7 @@ #include "command.h" #include "config.h" #include "input.h" +#include "gamecontrollers.h" #include "render.h" #include "serial.h" #include "slip.h" @@ -88,7 +89,7 @@ int main(int argc, char *argv[]) { run = QUIT; // initial scan for (existing) game controllers - initialize_game_controllers(); + gamecontrollers_initialize(); #ifdef DEBUG_MSG SDL_LogSetAllPriority(SDL_LOG_PRIORITY_DEBUG); @@ -172,7 +173,7 @@ int main(int argc, char *argv[]) { if (conf.audio_enabled == 1) { audio_destroy(); } - close_game_controllers(); + gamecontrollers_close(); close_renderer(); kill_inline_font(); SDL_free(serial_buf); @@ -286,7 +287,7 @@ int main(int argc, char *argv[]) { if (conf.audio_enabled == 1) { audio_destroy(); } - close_game_controllers(); + gamecontrollers_close(); close_renderer(); close_serial_port(); SDL_free(serial_buf);