From 65fe7f2f9c1dcc6f602b5c9d53e62263951c4fcb Mon Sep 17 00:00:00 2001 From: Maximilian Mader Date: Mon, 4 May 2020 03:30:10 +0200 Subject: [PATCH] [GTK3] Add analog speed controls --- gtk3/main.c | 52 +++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 45 insertions(+), 7 deletions(-) diff --git a/gtk3/main.c b/gtk3/main.c index 5ca2cde..f4c69ce 100644 --- a/gtk3/main.c +++ b/gtk3/main.c @@ -118,6 +118,7 @@ typedef struct GuiData { bool rewind_paused; bool turbo_down; double clock_mutliplier; + double analog_clock_multiplier; // Input uint8_t pressed_buttons; @@ -1179,7 +1180,10 @@ static void vblank(GB_gameboy_t *gb) { GB_set_pixels_output(gb, get_pixels()); - if (gui_data.underclock_down && gui_data.clock_mutliplier > 0.5) { + if (config.analog_speed_controls && gui_data.analog_clock_multiplier != 0.0) { + GB_set_clock_multiplier(gb, gui_data.analog_clock_multiplier); + } + else if (gui_data.underclock_down && gui_data.clock_mutliplier > 0.5) { gui_data.clock_mutliplier -= 1.0/16; GB_set_clock_multiplier(gb, gui_data.clock_mutliplier); } @@ -1252,31 +1256,63 @@ static void vblank(GB_gameboy_t *gb) { g_idle_add((GSourceFunc) on_vblank, NULL); } +static double clamp_double(double min, double max, double value) { + if (value < min) return min; + if (value > max) return max; + return value; +} + +static double max_double(double a, double b) { + if (a > b) return a; + return b; +} + +static double min_double(double a, double b) { + if (a < b) return a; + return b; +} + static void handle_events(GB_gameboy_t *gb) { SDL_GameControllerUpdate(); uint8_t controller_state = 0; + double analog_clock_multiplier = 1.0; for (unsigned i = 0; i < gui_data.controller_count; i++) { struct Controller_t *s = &gui_data.controllers[i]; - int16_t x_axis = SDL_GameControllerGetAxis(s->controller, SDL_CONTROLLER_AXIS_LEFTX); - int16_t y_axis = SDL_GameControllerGetAxis(s->controller, SDL_CONTROLLER_AXIS_LEFTY); + int16_t left_x_axis = SDL_GameControllerGetAxis(s->controller, SDL_CONTROLLER_AXIS_LEFTX); + int16_t left_y_axis = SDL_GameControllerGetAxis(s->controller, SDL_CONTROLLER_AXIS_LEFTY); - if (x_axis >= JOYSTICK_HIGH) { + int16_t right_x_axis = SDL_GameControllerGetAxis(s->controller, SDL_CONTROLLER_AXIS_RIGHTX); + int16_t right_y_axis = SDL_GameControllerGetAxis(s->controller, SDL_CONTROLLER_AXIS_RIGHTY); + + if (config.analog_speed_controls) { + double left_trigger = (double) SDL_GameControllerGetAxis(s->controller, SDL_CONTROLLER_AXIS_TRIGGERLEFT) / (double) 32767; + double right_trigger = (double) SDL_GameControllerGetAxis(s->controller, SDL_CONTROLLER_AXIS_TRIGGERRIGHT) / (double) 32767; + + if (left_trigger > 0.0) { + analog_clock_multiplier = min_double(analog_clock_multiplier, clamp_double(1.0 / 3, 1.0, 1 - left_trigger + 0.2)); + } + else if (right_trigger > 0.0) { + analog_clock_multiplier = max_double(analog_clock_multiplier, clamp_double(1.0, 3.0, right_trigger * 3 + 0.8)); + } + } + + if (left_x_axis >= JOYSTICK_HIGH || right_x_axis >= JOYSTICK_HIGH) { gui_data.last_used_controller = s; controller_state |= BUTTON_MASK_RIGHT; } - else if (x_axis <= -JOYSTICK_HIGH) { + else if (left_x_axis <= -JOYSTICK_HIGH || right_x_axis <= -JOYSTICK_HIGH) { gui_data.last_used_controller = s; controller_state |= BUTTON_MASK_LEFT; } - if (y_axis >= JOYSTICK_HIGH) { + if (left_y_axis >= JOYSTICK_HIGH || right_y_axis >= JOYSTICK_HIGH) { gui_data.last_used_controller = s; controller_state |= BUTTON_MASK_DOWN; } - else if (y_axis <= -JOYSTICK_HIGH) { + else if (left_y_axis <= -JOYSTICK_HIGH || right_y_axis <= -JOYSTICK_HIGH) { gui_data.last_used_controller = s; controller_state |= BUTTON_MASK_UP; } @@ -1322,6 +1358,8 @@ static void handle_events(GB_gameboy_t *gb) { } } + gui_data.analog_clock_multiplier = analog_clock_multiplier; + GB_set_key_state(gb, GB_KEY_RIGHT, (gui_data.pressed_buttons & BUTTON_MASK_RIGHT) | (controller_state & BUTTON_MASK_RIGHT)); GB_set_key_state(gb, GB_KEY_LEFT, (gui_data.pressed_buttons & BUTTON_MASK_LEFT) | (controller_state & BUTTON_MASK_LEFT)); GB_set_key_state(gb, GB_KEY_UP, (gui_data.pressed_buttons & BUTTON_MASK_UP) | (controller_state & BUTTON_MASK_UP));