diff --git a/Makefile b/Makefile index e571d72..75b93fe 100644 --- a/Makefile +++ b/Makefile @@ -126,13 +126,6 @@ ifeq ($(SDL_AUDIO_DRIVER),sdl) GTK_OPTIONS += -DUSE_SDL_AUDIO endif -# Use SDL’s haptic feedback subsystem by default, although -# some controllers only work with the simpler SDL_GameControllerRumble / SDL_JoystickRumble, -# but SDL’s WUP-028 (Wii U GameCube Controller Adapter) driver rumble handling seems to make the adapter lock up after a while. -ifneq ($(USE_SDL_HAPTIC),0) - GTK_OPTIONS += -DUSE_SDL_HAPTIC -endif - GTK3_CFLAGS := $(shell $(PKG_CONFIG) --cflags gio-2.0 gtk+-3.0 epoxy) $(GTK_OPTIONS) GTK3_LDFLAGS := $(shell $(PKG_CONFIG) --libs gio-2.0 gtk+-3.0 epoxy) diff --git a/gtk3/main.c b/gtk3/main.c index 145e408..782bc61 100644 --- a/gtk3/main.c +++ b/gtk3/main.c @@ -455,12 +455,10 @@ static gboolean init_controllers(void) { return false; } - #ifdef USE_SDL_HAPTIC - g_debug("Initializing haptic feedback"); - if (SDL_InitSubSystem(SDL_INIT_HAPTIC) < 0) { - g_warning("Failed to initialize haptic feedback support: %s", SDL_GetError()); - } - #endif + g_debug("Initializing haptic feedback"); + if (SDL_InitSubSystem(SDL_INIT_HAPTIC) < 0) { + g_warning("Failed to initialize haptic feedback support: %s", SDL_GetError()); + } g_debug("Loading custom game controller database"); GError *error = NULL; @@ -494,23 +492,21 @@ static gboolean init_controllers(void) { SDL_Joystick *joystick = SDL_GameControllerGetJoystick(s->controller); SDL_JoystickPowerLevel power_level = SDL_JoystickCurrentPowerLevel(joystick); - #ifdef USE_SDL_HAPTIC - if (SDL_JoystickIsHaptic(joystick)) { - s->haptic = SDL_HapticOpenFromJoystick(joystick); + if (SDL_JoystickIsHaptic(joystick)) { + s->haptic = SDL_HapticOpenFromJoystick(joystick); - if (s->haptic && SDL_HapticRumbleSupported(s->haptic)) { - SDL_HapticRumbleInit(s->haptic); - } - else { - if (s->haptic == NULL) { - g_warning("%s", SDL_GetError()); - } - - SDL_HapticClose(s->haptic); - s->haptic = NULL; - } + if (s->haptic && SDL_HapticRumbleSupported(s->haptic)) { + SDL_HapticRumbleInit(s->haptic); } - #endif + else { + if (s->haptic == NULL) { + g_warning("%s", SDL_GetError()); + } + + SDL_HapticClose(s->haptic); + s->haptic = NULL; + } + } char guid_str[33]; SDL_JoystickGUID guid = SDL_JoystickGetGUID(joystick); @@ -600,16 +596,15 @@ static void rumble_callback(GB_gameboy_t *gb, double amp) { struct Controller_t *s = gui_data.last_used_controller; - #ifdef USE_SDL_HAPTIC - if (s->haptic) { - if (amp > 0.0) { - SDL_HapticRumblePlay(s->haptic, amp, 100.0); - } - else { - SDL_HapticRumbleStop(s->haptic); - } + if (s->haptic) { + if (amp > 0.0) { + SDL_HapticRumblePlay(s->haptic, amp, 100.0); } - #else + else { + SDL_HapticRumbleStop(s->haptic); + } + } + else { if (amp == 0.0) { SDL_GameControllerRumble(s->controller, 0, 0, 0); } @@ -617,7 +612,7 @@ static void rumble_callback(GB_gameboy_t *gb, double amp) { Uint16 intensity = (float) 0xFFFF * amp; SDL_GameControllerRumble(s->controller, intensity, intensity, 100); } - #endif + } } static void clear_sidebar(void) { @@ -1408,7 +1403,7 @@ static void init(void) { GB_set_boot_rom_load_callback(&gb, load_boot_rom); GB_set_rumble_callback(&gb, rumble_callback); - GB_set_rumble_mode(&gb, GB_RUMBLE_CARTRIDGE_ONLY); // TODO + GB_set_rumble_mode(&gb, get_rumble_mode()); if (get_display_border_mode() <= GB_BORDER_ALWAYS) { GB_set_border_mode(&gb, get_display_border_mode()); @@ -1572,10 +1567,7 @@ static void quit(void) { for (unsigned i = 0; i < gui_data.controller_count; i++) { struct Controller_t *s = &gui_data.controllers[i]; - #ifdef USE_SDL_HAPTIC - SDL_HapticClose(s->haptic); - #endif - + SDL_HapticClose(s->haptic); SDL_GameControllerClose(s->controller); } @@ -2604,6 +2596,19 @@ G_MODULE_EXPORT void console_on_enter(GtkWidget *w, gpointer user_data_ptr) { gtk_entry_set_text(input, ""); } +G_MODULE_EXPORT void on_rumble_mode_changed(GtkWidget *w, gpointer user_data_ptr) { + GtkComboBox *box = GTK_COMBO_BOX(w); + config.rumble_mode = (gchar *)gtk_combo_box_get_active_id(box); + + GB_set_rumble_mode(&gb, get_rumble_mode()); +} + +G_MODULE_EXPORT void on_analog_speed_controls_changed(GtkWidget *w, gpointer user_data_ptr) { + GtkCheckButton *button = GTK_CHECK_BUTTON(w); + gboolean value = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(button)); + config.analog_speed_controls = value; +} + int main(int argc, char *argv[]) { gui_data.main_thread = g_thread_self(); diff --git a/gtk3/resources/ui/window.ui b/gtk3/resources/ui/window.ui index cb258c5..c38ef00 100644 --- a/gtk3/resources/ui/window.ui +++ b/gtk3/resources/ui/window.ui @@ -730,6 +730,7 @@ Maximilian Mader https://github.com/max-m True True False + start 5 10 True @@ -747,6 +748,7 @@ Maximilian Mader https://github.com/max-m True True False + start 5 10 True @@ -1064,10 +1066,63 @@ Maximilian Mader https://github.com/max-m 4 + + + Analog turbo and slow-motion controls + True + True + False + start + 5 + 10 + True + + + + False + False + 5 + + + + + True + False + 8 + Enable Rumble: + + + False + True + 6 + + + + + True + False + 5 + 10 + 0 + + Never + For rumble-enabled cartridges + Always + + + + + False + True + 7 + + True False + 5 + 10 Configure Joypad @@ -1102,7 +1157,7 @@ Maximilian Mader https://github.com/max-m False True - 5 + 8 diff --git a/gtk3/settings.c b/gtk3/settings.c index 267ec41..5609ddd 100644 --- a/gtk3/settings.c +++ b/gtk3/settings.c @@ -118,6 +118,8 @@ void on_preferences_realize(GtkWidget *w, gpointer builder_ptr) { gtk_toggle_button_set_active(builder_get(GTK_TOGGLE_BUTTON, "aspect_ratio_toggle"), config.keep_aspect_ratio); gtk_combo_box_set_active_id(builder_get(GTK_COMBO_BOX, "highpass_filter_selector"), config.high_pass_filter_id); gtk_combo_box_set_active_id(builder_get(GTK_COMBO_BOX, "sample_rate_selector"), g_strdup_printf("%i", config.sample_rate)); + gtk_toggle_button_set_active(builder_get(GTK_TOGGLE_BUTTON, "analog_speed_controls_toggle"), config.analog_speed_controls); + gtk_combo_box_set_active_id(builder_get(GTK_COMBO_BOX, "rumble_mode_selector"), config.rumble_mode); #if ! NDEBUG gtk_combo_box_set_active_id(builder_get(GTK_COMBO_BOX, "menubar_override_selector"), config.menubar_override); @@ -420,6 +422,38 @@ void set_highpass_mode(GB_highpass_mode_t mode) { } } +const GB_rumble_mode_t get_rumble_mode(void) { + if (config.rumble_mode == NULL) goto default_value; + + if (g_strcmp0(config.rumble_mode, "never") == 0) { + return GB_RUMBLE_DISABLED; + } + else if (g_strcmp0(config.rumble_mode, "rumble_cartridges") == 0) { + return GB_RUMBLE_CARTRIDGE_ONLY; + } + else if (g_strcmp0(config.rumble_mode, "always") == 0) { + return GB_RUMBLE_ALL_GAMES; + } + + // This should not happen + g_warning("Unknown highpass mode: %s\nFalling back to “Never”", config.rumble_mode); + default_value: return GB_RUMBLE_DISABLED; +} + +void set_rumble_mode(GB_rumble_mode_t mode) { + switch (mode) { + case GB_RUMBLE_DISABLED: + config.rumble_mode = "never"; + break; + case GB_RUMBLE_CARTRIDGE_ONLY: + config.rumble_mode = "rumble_cartridges"; + break; + case GB_RUMBLE_ALL_GAMES: + config.rumble_mode = "always"; + break; + } +} + GB_model_t get_dmg_model(void) { if (config.dmg_revision_name == NULL) goto default_value; diff --git a/gtk3/settings.h b/gtk3/settings.h index 00264cd..47dd44f 100644 --- a/gtk3/settings.h +++ b/gtk3/settings.h @@ -51,7 +51,8 @@ EXPAND_GROUP_MEMBER(sample_rate, integer, -1) \ ) \ EXPAND_GROUP(Controls, \ - \ + EXPAND_GROUP_MEMBER(analog_speed_controls, boolean, false) \ + EXPAND_GROUP_MEMBER(rumble_mode, string, "Never") \ ) typedef struct config_t { @@ -103,6 +104,9 @@ void set_highpass_mode(GB_highpass_mode_t); const GB_palette_t* get_monochrome_palette(void); void set_monochrome_palette(const GB_palette_t*); +const GB_rumble_mode_t get_rumble_mode(void); +void set_rumble_mode(const GB_rumble_mode_t); + GB_model_t get_dmg_model(void); GB_model_t get_sgb_model(void); GB_model_t get_cgb_model(void);