Skip to content

Commit

Permalink
#157 split game controller related functions to a separate file
Browse files Browse the repository at this point in the history
  • Loading branch information
laamaa committed Aug 19, 2024
1 parent 7bf257a commit 96574b7
Show file tree
Hide file tree
Showing 6 changed files with 192 additions and 160 deletions.
4 changes: 2 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
@@ -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//')
Expand Down
150 changes: 150 additions & 0 deletions src/gamecontrollers.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
//
// Created by jonne on 8/19/24.
//

#include "gamecontrollers.h"
#include "config.h"
#include "input.h"

#include <SDL.h>

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;
}
19 changes: 19 additions & 0 deletions src/gamecontrollers.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
//
// Created by jonne on 8/19/24.
//

#ifndef GAMECONTROLLERS_H_
#define GAMECONTROLLERS_H_

#include "config.h"
#include "input.h"
#include <SDL_gamecontroller.h>

#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_
158 changes: 5 additions & 153 deletions src/input.c
Original file line number Diff line number Diff line change
Expand Up @@ -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};

Expand All @@ -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) {
Expand Down Expand Up @@ -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) {

Expand All @@ -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)) {

Expand All @@ -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)
Expand Down
Loading

0 comments on commit 96574b7

Please sign in to comment.