+ FadeSetEnterMenu();
+ FadeOut(REDRAW_FIELD);
+
+ ClearField();
+
+ DrawTextSCentered(mSY - SY + 16, FONT_TITLE_1, "Keyboard Input");
+
+ step_nr = 0;
+ DrawText(mSX, mSY + (2 + 2 * step_nr) * 32,
+ customize_step[step_nr].text, FONT_INPUT_1_ACTIVE);
+ DrawText(mSX, mSY + (2 + 2 * step_nr + 1) * 32,
+ "Key:", FONT_INPUT_1_ACTIVE);
+ DrawText(mSX + 4 * 32, mSY + (2 + 2 * step_nr + 1) * 32,
+ getKeyNameFromKey(*customize_step[step_nr].key), font_nr_old);
+
+ FadeIn(REDRAW_FIELD);
+
+ while (!finished)
+ {
+ Event event;
+
+ if (NextValidEvent(&event))
+ {
+ switch (event.type)
+ {
+ case EVENT_KEYPRESS:
+ {
+ Key key = GetEventKey((KeyEvent *)&event, FALSE);
+
+ /* press 'Escape' to abort and keep the old key bindings */
+ if (key == KSYM_Escape)
+ {
+ FadeSkipNextFadeIn();
+
+ finished = TRUE;
+
+ break;
+ }
+
+ /* press 'Enter' to keep the existing key binding */
+ if (key == KSYM_Return)
+ key = *customize_step[step_nr].key;
+
+ /* check if key already used */
+ for (i = 0; i < step_nr; i++)
+ if (*customize_step[i].key == key)
+ break;
+ if (i < step_nr)
+ break;
+
+ /* got new key binding */
+ *customize_step[step_nr].key = key;
+ DrawText(mSX + 4 * 32, mSY + (2 + 2 * step_nr + 1) * 32,
+ " ", font_nr_new);
+ DrawText(mSX + 4 * 32, mSY + (2 + 2 * step_nr + 1) * 32,
+ getKeyNameFromKey(key), font_nr_new);
+ step_nr++;
+
+ /* un-highlight last query */
+ DrawText(mSX, mSY + (2 + 2 * (step_nr - 1)) * 32,
+ customize_step[step_nr - 1].text, FONT_MENU_1);
+ DrawText(mSX, mSY + (2 + 2 * (step_nr - 1) + 1) * 32,
+ "Key:", FONT_MENU_1);
+
+ /* all keys configured */
+ if (step_nr == 6)
+ {
+ finished = TRUE;
+ success = TRUE;
+
+ break;
+ }
+
+ /* query next key binding */
+ DrawText(mSX, mSY + (2 + 2 * step_nr) * 32,
+ customize_step[step_nr].text, FONT_INPUT_1_ACTIVE);
+ DrawText(mSX, mSY + (2 + 2 * step_nr + 1) * 32,
+ "Key:", FONT_INPUT_1_ACTIVE);
+ DrawText(mSX + 4 * 32, mSY + (2 + 2 * step_nr + 1) * 32,
+ getKeyNameFromKey(*customize_step[step_nr].key),
+ font_nr_old);
+ }
+ break;
+
+ case EVENT_KEYRELEASE:
+ key_joystick_mapping = 0;
+ break;
+
+ default:
+ HandleOtherEvents(&event);
+ break;
+ }
+ }
+
+ BackToFront();
+ }
+
+ /* write new key bindings back to player setup, if successfully finished */
+ if (success)
+ setup.input[player_nr].key = custom_key;
+
+ return success;
+}
+
+void CustomizeKeyboard(int player_nr)
+{
+ boolean success = CustomizeKeyboardMain(player_nr);
+
+ if (success)
+ {
+ int font_nr = FONT_TITLE_1;
+ int font_height = getFontHeight(font_nr);
+ int ypos1 = SYSIZE / 2 - font_height * 2;
+ int ypos2 = SYSIZE / 2 - font_height * 1;
+ unsigned int wait_frame_delay = 0;
+ unsigned int wait_frame_delay_value = 2000;
+
+ ResetDelayCounter(&wait_frame_delay);
+
+ ClearField();
+
+ DrawTextSCentered(ypos1, font_nr, "Keyboard");
+ DrawTextSCentered(ypos2, font_nr, "configured!");
+
+ while (!DelayReached(&wait_frame_delay, wait_frame_delay_value))
+ BackToFront();
+
+ ClearEventQueue();
+ }
+
+ DrawSetupScreen_Input();
+}
+
+/* game controller mapping generator by Gabriel Jacobo <gabomdq@gmail.com> */
+
+#define MARKER_BUTTON 1
+#define MARKER_AXIS_X 2
+#define MARKER_AXIS_Y 3
+
+static boolean ConfigureJoystickMapButtonsAndAxes(SDL_Joystick *joystick)
+{
+#if defined(TARGET_SDL2)
+ static boolean bitmaps_initialized = FALSE;
+ boolean screen_initialized = FALSE;
+ static Bitmap *controller, *button, *axis_x, *axis_y;
+ char *name;
+ boolean success = TRUE;
+ boolean done = FALSE, next = FALSE;
+ Event event;
+ int alpha = 200, alpha_step = -1;
+ int alpha_ticks = 0;
+ char mapping[4096], temp[4096];
+ int font_name = MENU_SETUP_FONT_TITLE;
+ int font_info = MENU_SETUP_FONT_TEXT;
+ int spacing_name = menu.line_spacing_setup[SETUP_MODE_INPUT];
+ int spacing_line = menu.line_spacing_setup[SETUP_MODE_INPUT];
+ int spacing_para = menu.paragraph_spacing_setup[SETUP_MODE_INPUT];
+ int ystep_name = getMenuTextStep(spacing_name, font_name);
+ int ystep_line = getMenuTextStep(spacing_line, font_info);
+ int ystep_para = getMenuTextStep(spacing_para, font_info);
+ int i, j;
+
+ struct
+ {
+ int x, y;
+ int marker;
+ char *field;
+ int axis, button, hat, hat_value;
+ char mapping[4096];
+ }
+ *step, *prev_step, steps[] =
+ {
+ { 356, 155, MARKER_BUTTON, "a", },
+ { 396, 122, MARKER_BUTTON, "b", },
+ { 320, 125, MARKER_BUTTON, "x", },
+ { 358, 95, MARKER_BUTTON, "y", },
+ { 162, 125, MARKER_BUTTON, "back", },
+ { 216, 125, MARKER_BUTTON, "guide", },
+ { 271, 125, MARKER_BUTTON, "start", },
+ { 110, 200, MARKER_BUTTON, "dpleft", },
+ { 146, 228, MARKER_BUTTON, "dpdown", },
+ { 178, 200, MARKER_BUTTON, "dpright", },
+ { 146, 172, MARKER_BUTTON, "dpup", },
+ { 50, 40, MARKER_BUTTON, "leftshoulder", },
+ { 88, -10, MARKER_AXIS_Y, "lefttrigger", },
+ { 382, 40, MARKER_BUTTON, "rightshoulder", },
+ { 346, -10, MARKER_AXIS_Y, "righttrigger", },
+ { 73, 141, MARKER_BUTTON, "leftstick", },
+ { 282, 210, MARKER_BUTTON, "rightstick", },
+ { 73, 141, MARKER_AXIS_X, "leftx", },
+ { 73, 141, MARKER_AXIS_Y, "lefty", },
+ { 282, 210, MARKER_AXIS_X, "rightx", },
+ { 282, 210, MARKER_AXIS_Y, "righty", },
+ };
+
+ unsigned int event_frame_delay = 0;
+ unsigned int event_frame_delay_value = GAME_FRAME_DELAY;
+
+ ResetDelayCounter(&event_frame_delay);
+
+ if (!bitmaps_initialized)
+ {
+ controller = LoadCustomImage("joystick/controller.png");
+ button = LoadCustomImage("joystick/button.png");
+ axis_x = LoadCustomImage("joystick/axis_x.png");
+ axis_y = LoadCustomImage("joystick/axis_y.png");