diff --git a/SDL/gui.c b/SDL/gui.c index 365f059..be075e4 100644 --- a/SDL/gui.c +++ b/SDL/gui.c @@ -66,6 +66,24 @@ configuration_t configuration = SDL_SCANCODE_TAB, SDL_SCANCODE_LSHIFT, }, + .joypad_configuration = { + 13, + 14, + 11, + 12, + 0, + 1, + 9, + 8, + 10, + 4, + -1, + 5, + }, + .joypad_axises = { + 0, + 1, + }, .color_correction_mode = GB_COLOR_CORRECTION_EMULATE_HARDWARE, .highpass_mode = GB_HIGHPASS_ACCURATE, .scaling_mode = GB_SDL_SCALING_INTEGER_FACTOR, @@ -221,8 +239,8 @@ static enum { WAITING_FOR_JBUTTON, } gui_state; -unsigned auto_detect_progress = 0; -unsigned auto_detect_inputs[3]; +static unsigned joypad_configuration_progress = 0; +static uint8_t joypad_axis_temp; static void item_exit(unsigned index) { @@ -593,8 +611,9 @@ static void enter_controls_menu_2(unsigned index) } static unsigned joypad_index = 0; -SDL_Joystick *joystick = NULL; -SDL_GameController *controller = NULL; +static SDL_Joystick *joystick = NULL; +static SDL_GameController *controller = NULL; + const char *current_joypad_name(unsigned index) { static char name[23] = {0,}; @@ -661,80 +680,16 @@ static void cycle_joypads_backwards(unsigned index) } } -unsigned fix_joypad_axis(unsigned axis) -{ - if (controller) { - /* Convert to the mapping used by generic Xbox-style controllers */ - for (SDL_GameControllerAxis i = 0; i < SDL_CONTROLLER_AXIS_MAX; i++) { - if (SDL_GameControllerGetBindForAxis(controller, i).value.axis == axis) { - if (i == SDL_CONTROLLER_AXIS_LEFTX || i == SDL_CONTROLLER_AXIS_RIGHTX) return 0; - if (i == SDL_CONTROLLER_AXIS_LEFTY || i == SDL_CONTROLLER_AXIS_RIGHTY) return 1; - return i; - } - } - return -1; - } - - - if (configuration.div_joystick) { - axis >>= 1; - } - - return axis & 1; -} - -unsigned fix_joypad_button(unsigned button) -{ - if (controller) { - /* Convert to the mapping used by generic Xbox-style controllers */ - for (SDL_GameControllerButton i = 0; i < SDL_CONTROLLER_BUTTON_MAX; i++) { - if (SDL_GameControllerGetBindForButton(controller, i).value.button == button) { - if (i == SDL_CONTROLLER_BUTTON_START) { - return 9; - } - if (i == 9) { - return SDL_CONTROLLER_BUTTON_START; - } - - if (i == SDL_CONTROLLER_BUTTON_BACK) { - return 8; - } - if (i == 8) { - return SDL_CONTROLLER_BUTTON_BACK; - } - return i; - } - } - return -1; - } - - - if (configuration.div_joystick) { - button >>= 1; - } - - if (button < 4) { - if (configuration.swap_joysticks_bits_1_and_2) { - button = (int[]){0, 2, 1, 3}[button]; - } - - if (configuration.flip_joystick_bit_1) { - button ^= 1; - } - } - - return button; -} - static void detect_joypad_layout(unsigned index) { gui_state = WAITING_FOR_JBUTTON; - auto_detect_progress = 0; + joypad_configuration_progress = 0; + joypad_axis_temp = -1; } static const struct menu_item joypad_menu[] = { {"Joypad:", cycle_joypads, current_joypad_name, cycle_joypads_backwards}, - {"Detect layout", detect_joypad_layout}, + {"Configure layout", detect_joypad_layout}, {"Back", return_to_root_menu}, {NULL,} }; @@ -745,6 +700,27 @@ static void enter_joypad_menu(unsigned index) current_selection = 0; } +joypad_button_t get_joypad_button(uint8_t physical_button) +{ + for (unsigned i = 0; i < JOYPAD_BUTTONS_MAX; i++) { + if (configuration.joypad_configuration[i] == physical_button) { + return i; + } + } + return JOYPAD_BUTTONS_MAX; +} + +joypad_axis_t get_joypad_axis(uint8_t physical_axis) +{ + for (unsigned i = 0; i < JOYPAD_AXISES_MAX; i++) { + if (configuration.joypad_axises[i] == physical_axis) { + return i; + } + } + return JOYPAD_AXISES_MAX; +} + + extern void set_filename(const char *new_filename, bool new_should_free); void run_gui(bool is_running) { @@ -793,17 +769,17 @@ void run_gui(bool is_running) switch (event.type) { case SDL_JOYBUTTONDOWN: event.type = SDL_KEYDOWN; - event.jbutton.button = fix_joypad_button(event.jbutton.button); - if (event.jbutton.button < 4) { - event.key.keysym.scancode = (event.jbutton.button & 1) ? SDL_SCANCODE_RETURN : SDL_SCANCODE_ESCAPE; + joypad_button_t button = get_joypad_button(event.jbutton.button); + if (button == JOYPAD_BUTTON_A) { + event.key.keysym.scancode = SDL_SCANCODE_RETURN; } - else if (event.jbutton.button == 8 || event.jbutton.button == 9) { + else if (button == JOYPAD_BUTTON_START || button == JOYPAD_BUTTON_B || button == JOYPAD_BUTTON_MENU) { event.key.keysym.scancode = SDL_SCANCODE_ESCAPE; } - else if (event.jbutton.button == SDL_CONTROLLER_BUTTON_DPAD_UP) event.key.keysym.scancode = SDL_SCANCODE_UP; - else if (event.jbutton.button == SDL_CONTROLLER_BUTTON_DPAD_DOWN) event.key.keysym.scancode = SDL_SCANCODE_DOWN; - else if (event.jbutton.button == SDL_CONTROLLER_BUTTON_DPAD_LEFT) event.key.keysym.scancode = SDL_SCANCODE_LEFT; - else if (event.jbutton.button == SDL_CONTROLLER_BUTTON_DPAD_RIGHT) event.key.keysym.scancode = SDL_SCANCODE_RIGHT; + else if (button == JOYPAD_BUTTON_UP) event.key.keysym.scancode = SDL_SCANCODE_UP; + else if (button == JOYPAD_BUTTON_DOWN) event.key.keysym.scancode = SDL_SCANCODE_DOWN; + else if (button == JOYPAD_BUTTON_LEFT) event.key.keysym.scancode = SDL_SCANCODE_LEFT; + else if (button == JOYPAD_BUTTON_RIGHT) event.key.keysym.scancode = SDL_SCANCODE_RIGHT; break; case SDL_JOYHATMOTION: { @@ -825,8 +801,9 @@ void run_gui(bool is_running) case SDL_JOYAXISMOTION: { static bool axis_active[2] = {false, false}; - event.jaxis.axis = fix_joypad_axis(event.jaxis.axis); - if (event.jaxis.axis == 1) { + + joypad_axis_t axis = get_joypad_axis(event.jaxis.axis); + if (axis == JOYPAD_AXISES_Y) { if (event.jaxis.value > 0x4000) { if (!axis_active[1]) { event.type = SDL_KEYDOWN; @@ -845,7 +822,7 @@ void run_gui(bool is_running) axis_active[1] = false; } } - else if (event.jaxis.axis == 0) { + else if (axis == JOYPAD_AXISES_X) { if (event.jaxis.value > 0x4000) { if (!axis_active[0]) { event.type = SDL_KEYDOWN; @@ -892,36 +869,54 @@ void run_gui(bool is_running) } case SDL_JOYBUTTONDOWN: { - if (gui_state == WAITING_FOR_JBUTTON) { + if (gui_state == WAITING_FOR_JBUTTON && joypad_configuration_progress != JOYPAD_BUTTONS_MAX) { should_render = true; - auto_detect_inputs[auto_detect_progress++] = event.jbutton.button; - if (auto_detect_progress == 3) { + configuration.joypad_configuration[joypad_configuration_progress++] = event.jbutton.button; + } + break; + } + + case SDL_JOYAXISMOTION: { + if (gui_state == WAITING_FOR_JBUTTON && + joypad_configuration_progress == JOYPAD_BUTTONS_MAX && + abs(event.jaxis.value) >= 0x4000) { + if (joypad_axis_temp == (uint8_t)-1) { + joypad_axis_temp = event.jaxis.axis; + } + else if (joypad_axis_temp != event.jaxis.axis) { + if (joypad_axis_temp < event.jaxis.axis) { + configuration.joypad_axises[JOYPAD_AXISES_X] = joypad_axis_temp; + configuration.joypad_axises[JOYPAD_AXISES_Y] = event.jaxis.axis; + } + else { + configuration.joypad_axises[JOYPAD_AXISES_Y] = joypad_axis_temp; + configuration.joypad_axises[JOYPAD_AXISES_X] = event.jaxis.axis; + } + gui_state = SHOWING_MENU; - - configuration.div_joystick = - ((auto_detect_inputs[0] | auto_detect_inputs[1] | auto_detect_inputs[2]) & 1) == 0 && - auto_detect_inputs[0] > 9; - - if (configuration.div_joystick) { - auto_detect_inputs[0] >>= 1; - auto_detect_inputs[1] >>= 1; - auto_detect_inputs[2] >>= 1; - } - - configuration.swap_joysticks_bits_1_and_2 = - (auto_detect_inputs[1] & 1) == (auto_detect_inputs[2] & 1); - - if (configuration.swap_joysticks_bits_1_and_2) { - auto_detect_inputs[1] = (int[]){0, 2, 1, 3}[auto_detect_inputs[1]]; - auto_detect_inputs[2] = (int[]){0, 2, 1, 3}[auto_detect_inputs[2]]; - } - - configuration.flip_joystick_bit_1 = auto_detect_inputs[2] & 1; + should_render = true; } } + break; } + case SDL_KEYDOWN: - if (event.key.keysym.scancode == SDL_SCANCODE_ESCAPE) { + if (event.key.keysym.scancode == SDL_SCANCODE_RETURN && gui_state == WAITING_FOR_JBUTTON) { + should_render = true; + if (joypad_configuration_progress != JOYPAD_BUTTONS_MAX) { + configuration.joypad_configuration[joypad_configuration_progress] = -1; + } + else { + configuration.joypad_axises[0] = -1; + configuration.joypad_axises[1] = -1; + } + joypad_configuration_progress++; + + if (joypad_configuration_progress > JOYPAD_BUTTONS_MAX) { + gui_state = SHOWING_MENU; + } + } + else if (event.key.keysym.scancode == SDL_SCANCODE_ESCAPE) { if (is_running) { return; } @@ -937,8 +932,7 @@ void run_gui(bool is_running) should_render = true; } } - - if (gui_state == SHOWING_MENU) { + else if (gui_state == SHOWING_MENU) { if (event.key.keysym.scancode == SDL_SCANCODE_DOWN && current_menu[current_selection + 1].string) { current_selection++; should_render = true; @@ -1040,13 +1034,28 @@ void run_gui(bool is_running) draw_text_centered(pixels, 68, "Press a Key", gui_palette_native[3], gui_palette_native[0], DECORATION_NONE); break; case WAITING_FOR_JBUTTON: - draw_text_centered(pixels, 68, (const char *[]) - { - "Press button for Start", - "Press button for A", - "Press button for B", - } [auto_detect_progress], + draw_text_centered(pixels, 68, + joypad_configuration_progress != JOYPAD_BUTTONS_MAX ? "Press button for" : "Move the Analog Stick", gui_palette_native[3], gui_palette_native[0], DECORATION_NONE); + draw_text_centered(pixels, 80, + (const char *[]) + { + "Right", + "Left", + "Up", + "Down", + "A", + "B", + "Select", + "Start", + "Open Menu", + "Turbo", + "Rewind", + "Slow-Motion", + "", + } [joypad_configuration_progress], + gui_palette_native[3], gui_palette_native[0], DECORATION_NONE); + draw_text_centered(pixels, 104, "Press Enter to skip", gui_palette_native[3], gui_palette_native[0], DECORATION_NONE); break; } diff --git a/SDL/gui.h b/SDL/gui.h index e3f53c9..7042357 100644 --- a/SDL/gui.h +++ b/SDL/gui.h @@ -31,8 +31,32 @@ enum pending_command { GB_SDL_QUIT_COMMAND, }; + extern enum pending_command pending_command; extern unsigned command_parameter; + +typedef enum { + JOYPAD_BUTTON_LEFT, + JOYPAD_BUTTON_RIGHT, + JOYPAD_BUTTON_UP, + JOYPAD_BUTTON_DOWN, + JOYPAD_BUTTON_A, + JOYPAD_BUTTON_B, + JOYPAD_BUTTON_SELECT, + JOYPAD_BUTTON_START, + JOYPAD_BUTTON_MENU, + JOYPAD_BUTTON_TURBO, + JOYPAD_BUTTON_REWIND, + JOYPAD_BUTTON_SLOW_MOTION, + JOYPAD_BUTTONS_MAX +} joypad_button_t; + +typedef enum { + JOYPAD_AXISES_X, + JOYPAD_AXISES_Y, + JOYPAD_AXISES_MAX +} joypad_axis_t; + typedef struct { SDL_Scancode keys[9]; GB_color_correction_mode_t color_correction_mode; @@ -41,9 +65,9 @@ typedef struct { GB_highpass_mode_t highpass_mode; - bool div_joystick; - bool flip_joystick_bit_1; - bool swap_joysticks_bits_1_and_2; + bool _deprecated_div_joystick; + bool _deprecated_flip_joystick_bit_1; + bool _deprecated_swap_joysticks_bits_1_and_2; char filter[32]; enum { @@ -55,15 +79,18 @@ typedef struct { /* v0.11 */ uint32_t rewind_length; - SDL_Scancode keys_2[2]; /* Rewind and underclock */ + SDL_Scancode keys_2[32]; /* Rewind and underclock, + padding for the future */ + uint8_t joypad_configuration[32]; /* 12 Keys + padding for the future*/; + uint8_t joypad_axises[JOYPAD_AXISES_MAX]; } configuration_t; extern configuration_t configuration; void update_viewport(void); void run_gui(bool is_running); -unsigned fix_joypad_button(unsigned button); -unsigned fix_joypad_axis(unsigned axis); void render_texture(void *pixels, void *previous); +joypad_button_t get_joypad_button(uint8_t physical_button); +joypad_axis_t get_joypad_axis(uint8_t physical_axis); + #endif diff --git a/SDL/main.c b/SDL/main.c index ff279f4..5aabfe8 100755 --- a/SDL/main.c +++ b/SDL/main.c @@ -92,6 +92,20 @@ static const char *end_capturing_logs(bool show_popup, bool should_exit) return captured_log; } +static void open_menu(void) +{ + bool audio_playing = SDL_GetAudioDeviceStatus(device_id) == SDL_AUDIO_PLAYING; + if (audio_playing) { + SDL_PauseAudioDevice(device_id, 1); + } + run_gui(true); + if (audio_playing) { + SDL_PauseAudioDevice(device_id, 0); + } + GB_set_color_correction_mode(&gb, configuration.color_correction_mode); + GB_set_highpass_filter_mode(&gb, configuration.highpass_mode); +} + static void handle_events(GB_gameboy_t *gb) { #ifdef __APPLE__ @@ -121,56 +135,42 @@ static void handle_events(GB_gameboy_t *gb) } case SDL_JOYBUTTONUP: - case SDL_JOYBUTTONDOWN: - event.jbutton.button = fix_joypad_button(event.jbutton.button); - if (event.jbutton.button < 4) { - GB_set_key_state(gb, (event.jbutton.button & 1) ? GB_KEY_A : GB_KEY_B, - event.type == SDL_JOYBUTTONDOWN); + case SDL_JOYBUTTONDOWN: { + joypad_button_t button = get_joypad_button(event.jbutton.button); + if ((GB_key_t) button < GB_KEY_MAX) { + GB_set_key_state(gb, (GB_key_t) button, event.type == SDL_JOYBUTTONDOWN); } - else if (event.jbutton.button == 8) { - GB_set_key_state(gb, GB_KEY_SELECT, event.type == SDL_JOYBUTTONDOWN); - } - else if (event.jbutton.button == 9) { - GB_set_key_state(gb, GB_KEY_START, event.type == SDL_JOYBUTTONDOWN); - } - else if (event.jbutton.button == SDL_CONTROLLER_BUTTON_DPAD_UP) { - GB_set_key_state(gb, GB_KEY_UP, event.type == SDL_JOYBUTTONDOWN); - } - else if (event.jbutton.button == SDL_CONTROLLER_BUTTON_DPAD_DOWN) { - GB_set_key_state(gb, GB_KEY_DOWN, event.type == SDL_JOYBUTTONDOWN); - } - else if (event.jbutton.button == SDL_CONTROLLER_BUTTON_DPAD_LEFT) { - GB_set_key_state(gb, GB_KEY_LEFT, event.type == SDL_JOYBUTTONDOWN); - } - else if (event.jbutton.button == SDL_CONTROLLER_BUTTON_DPAD_RIGHT) { - GB_set_key_state(gb, GB_KEY_RIGHT, event.type == SDL_JOYBUTTONDOWN); - } - else if (event.jbutton.button & 1) { + else if (button == JOYPAD_BUTTON_TURBO) { turbo_down = event.type == SDL_JOYBUTTONDOWN; GB_set_turbo_mode(gb, turbo_down, turbo_down && rewind_down); } - - else { - bool audio_playing = SDL_GetAudioDeviceStatus(device_id) == SDL_AUDIO_PLAYING; - if (audio_playing) { - SDL_PauseAudioDevice(device_id, 1); - } - run_gui(true); - GB_set_color_correction_mode(gb, configuration.color_correction_mode); - GB_set_highpass_filter_mode(gb, configuration.highpass_mode); + else if (button == JOYPAD_BUTTON_SLOW_MOTION) { + underclock_down = event.type == SDL_JOYBUTTONDOWN; } + else if (button == JOYPAD_BUTTON_REWIND) { + rewind_down = event.type == SDL_JOYBUTTONDOWN; + if (event.type == SDL_JOYBUTTONUP) { + rewind_paused = false; + } + GB_set_turbo_mode(gb, turbo_down, turbo_down && rewind_down); + } + else if (button == JOYPAD_BUTTON_MENU && event.type == SDL_JOYBUTTONDOWN) { + open_menu(); + } + } break; - case SDL_JOYAXISMOTION: - event.jaxis.axis = fix_joypad_axis(event.jaxis.axis); - if (event.jaxis.axis == 1) { + case SDL_JOYAXISMOTION: { + joypad_axis_t axis = get_joypad_axis(event.jaxis.axis); + if (axis == JOYPAD_AXISES_Y) { GB_set_key_state(gb, GB_KEY_DOWN, event.jaxis.value > 0x4000); GB_set_key_state(gb, GB_KEY_UP, event.jaxis.value < -0x4000); } - else if (event.jaxis.axis == 0) { + else if (axis == JOYPAD_AXISES_X) { GB_set_key_state(gb, GB_KEY_RIGHT, event.jaxis.value > 0x4000); GB_set_key_state(gb, GB_KEY_LEFT, event.jaxis.value < -0x4000); } + } break; case SDL_JOYHATMOTION: @@ -191,16 +191,7 @@ static void handle_events(GB_gameboy_t *gb) case SDL_KEYDOWN: switch (event.key.keysym.scancode) { case SDL_SCANCODE_ESCAPE: { - bool audio_playing = SDL_GetAudioDeviceStatus(device_id) == SDL_AUDIO_PLAYING; - if (audio_playing) { - SDL_PauseAudioDevice(device_id, 1); - } - run_gui(true); - if (!audio_playing) { - SDL_PauseAudioDevice(device_id, 0); - } - GB_set_color_correction_mode(gb, configuration.color_correction_mode); - GB_set_highpass_filter_mode(gb, configuration.highpass_mode); + open_menu(); break; } case SDL_SCANCODE_C: