+ drawHallOfFameList(first_entry, highlight_position);
+ return;
+ }
+ }
+
+ if (button_released)
+ {
+ FadeSound(SND_BACKGROUND_SCORES);
+ game_status = MAINMENU;
+ DrawMainMenu();
+ }
+
+ BackToFront();
+
+ if (game_status == HALLOFFAME)
+ {
+ DoAnimation();
+#if 1
+ PlaySound_Menu_Continue(SND_BACKGROUND_SCORES);
+#endif
+ }
+}
+
+
+/* ========================================================================= */
+/* setup screen functions */
+/* ========================================================================= */
+
+static struct TokenInfo *setup_info;
+static int num_setup_info;
+
+static char *graphics_set_name;
+static char *sounds_set_name;
+static char *music_set_name;
+
+static void execSetupMain()
+{
+ setup_mode = SETUP_MODE_MAIN;
+ DrawSetupScreen();
+}
+
+static void execSetupGame()
+{
+ setup_mode = SETUP_MODE_GAME;
+ DrawSetupScreen();
+}
+
+static void execSetupEditor()
+{
+ setup_mode = SETUP_MODE_EDITOR;
+ DrawSetupScreen();
+}
+
+static void execSetupGraphics()
+{
+ setup_mode = SETUP_MODE_GRAPHICS;
+ DrawSetupScreen();
+}
+
+static void execSetupSound()
+{
+ setup_mode = SETUP_MODE_SOUND;
+ DrawSetupScreen();
+}
+
+static void execSetupArtwork()
+{
+ /* needed if last screen (setup choice) changed graphics, sounds or music */
+ ReloadCustomArtwork();
+
+ setup.graphics_set = artwork.gfx_current->identifier;
+ setup.sounds_set = artwork.snd_current->identifier;
+ setup.music_set = artwork.mus_current->identifier;
+
+ /* needed for displaying artwork name instead of artwork identifier */
+ graphics_set_name = artwork.gfx_current->name;
+ sounds_set_name = artwork.snd_current->name;
+ music_set_name = artwork.mus_current->name;
+
+ setup_mode = SETUP_MODE_ARTWORK;
+ DrawSetupScreen();
+}
+
+static void execSetupChooseGraphics()
+{
+ setup_mode = SETUP_MODE_CHOOSE_GRAPHICS;
+ DrawSetupScreen();
+}
+
+static void execSetupChooseSounds()
+{
+ setup_mode = SETUP_MODE_CHOOSE_SOUNDS;
+ DrawSetupScreen();
+}
+
+static void execSetupChooseMusic()
+{
+ setup_mode = SETUP_MODE_CHOOSE_MUSIC;
+ DrawSetupScreen();
+}
+
+static void execSetupInput()
+{
+ setup_mode = SETUP_MODE_INPUT;
+ DrawSetupScreen();
+}
+
+static void execSetupShortcut()
+{
+ setup_mode = SETUP_MODE_SHORTCUT;
+ DrawSetupScreen();
+}
+
+static void execExitSetup()
+{
+ game_status = MAINMENU;
+ DrawMainMenu();
+}
+
+static void execSaveAndExitSetup()
+{
+ SaveSetup();
+ execExitSetup();
+}
+
+static struct TokenInfo setup_info_main[] =
+{
+ { TYPE_ENTER_MENU, execSetupGame, "Game Settings" },
+ { TYPE_ENTER_MENU, execSetupEditor, "Editor Settings" },
+ { TYPE_ENTER_MENU, execSetupGraphics, "Graphics" },
+ { TYPE_ENTER_MENU, execSetupSound, "Sound & Music" },
+ { TYPE_ENTER_MENU, execSetupArtwork, "Custom Artwork" },
+ { TYPE_ENTER_MENU, execSetupInput, "Input Devices" },
+ { TYPE_ENTER_MENU, execSetupShortcut, "Key Shortcuts" },
+ { TYPE_EMPTY, NULL, "" },
+ { TYPE_LEAVE_MENU, execExitSetup, "Exit" },
+ { TYPE_LEAVE_MENU, execSaveAndExitSetup, "Save and Exit" },
+ { 0, NULL, NULL }
+};
+
+static struct TokenInfo setup_info_game[] =
+{
+ { TYPE_SWITCH, &setup.team_mode, "Team-Mode:" },
+ { TYPE_SWITCH, &setup.handicap, "Handicap:" },
+ { TYPE_SWITCH, &setup.time_limit, "Timelimit:" },
+ { TYPE_SWITCH, &setup.autorecord, "Auto-Record:" },
+ { TYPE_EMPTY, NULL, "" },
+ { TYPE_LEAVE_MENU, execSetupMain, "Back" },
+ { 0, NULL, NULL }
+};
+
+static struct TokenInfo setup_info_editor[] =
+{
+ { TYPE_STRING, NULL, "Offer Special Elements:"},
+ { TYPE_SWITCH, &setup.editor.el_boulderdash, "BoulderDash:" },
+ { TYPE_SWITCH, &setup.editor.el_emerald_mine, "Emerald Mine:" },
+ { TYPE_SWITCH, &setup.editor.el_more, "More:" },
+ { TYPE_SWITCH, &setup.editor.el_sokoban, "Sokoban:" },
+ { TYPE_SWITCH, &setup.editor.el_supaplex, "Supaplex:" },
+ { TYPE_SWITCH, &setup.editor.el_diamond_caves, "Diamd. Caves:" },
+ { TYPE_SWITCH, &setup.editor.el_dx_boulderdash,"DX Boulderd.:" },
+ { TYPE_SWITCH, &setup.editor.el_chars, "Characters:" },
+ { TYPE_SWITCH, &setup.editor.el_custom, "Custom:" },
+ { TYPE_EMPTY, NULL, "" },
+ { TYPE_LEAVE_MENU, execSetupMain, "Back" },
+ { 0, NULL, NULL }
+};
+
+static struct TokenInfo setup_info_graphics[] =
+{
+ { TYPE_SWITCH, &setup.fullscreen, "Fullscreen:" },
+ { TYPE_SWITCH, &setup.scroll_delay, "Scroll Delay:" },
+ { TYPE_SWITCH, &setup.soft_scrolling, "Soft Scroll.:" },
+#if 0
+ { TYPE_SWITCH, &setup.double_buffering,"Buffered gfx:" },
+ { TYPE_SWITCH, &setup.fading, "Fading:" },
+#endif
+ { TYPE_SWITCH, &setup.quick_doors, "Quick Doors:" },
+ { TYPE_SWITCH, &setup.toons, "Toons:" },
+ { TYPE_EMPTY, NULL, "" },
+ { TYPE_LEAVE_MENU, execSetupMain, "Back" },
+ { 0, NULL, NULL }
+};
+
+static struct TokenInfo setup_info_sound[] =
+{
+ { TYPE_SWITCH, &setup.sound, "Sound:", },
+ { TYPE_EMPTY, NULL, "" },
+ { TYPE_SWITCH, &setup.sound_simple, "Simple Sound:" },
+ { TYPE_SWITCH, &setup.sound_loops, "Sound Loops:" },
+ { TYPE_SWITCH, &setup.sound_music, "Game Music:" },
+ { TYPE_EMPTY, NULL, "" },
+ { TYPE_LEAVE_MENU, execSetupMain, "Back" },
+ { 0, NULL, NULL }
+};
+
+static struct TokenInfo setup_info_artwork[] =
+{
+ { TYPE_ENTER_MENU, execSetupChooseGraphics,"Custom Graphics" },
+ { TYPE_STRING, &graphics_set_name, "" },
+ { TYPE_ENTER_MENU, execSetupChooseSounds, "Custom Sounds" },
+ { TYPE_STRING, &sounds_set_name, "" },
+ { TYPE_ENTER_MENU, execSetupChooseMusic, "Custom Music" },
+ { TYPE_STRING, &music_set_name, "" },
+ { TYPE_EMPTY, NULL, "" },
+ { TYPE_STRING, NULL, "Override Level Artwork:"},
+ { TYPE_YES_NO, &setup.override_level_graphics, "Graphics:" },
+ { TYPE_YES_NO, &setup.override_level_sounds, "Sounds:" },
+ { TYPE_YES_NO, &setup.override_level_music, "Music:" },
+ { TYPE_EMPTY, NULL, "" },
+ { TYPE_LEAVE_MENU, execSetupMain, "Back" },
+ { 0, NULL, NULL }
+};
+
+static struct TokenInfo setup_info_shortcut[] =
+{
+ { TYPE_KEYTEXT, NULL, "Quick Save Game:", },
+ { TYPE_KEY, &setup.shortcut.save_game, "" },
+ { TYPE_KEYTEXT, NULL, "Quick Load Game:", },
+ { TYPE_KEY, &setup.shortcut.load_game, "" },
+ { TYPE_KEYTEXT, NULL, "Toggle Pause:", },
+ { TYPE_KEY, &setup.shortcut.toggle_pause, "" },
+ { TYPE_EMPTY, NULL, "" },
+ { TYPE_YES_NO, &setup.ask_on_escape, "Ask on Esc:" },
+ { TYPE_EMPTY, NULL, "" },
+ { TYPE_LEAVE_MENU, execSetupMain, "Back" },
+ { 0, NULL, NULL }
+};
+
+static Key getSetupKey()
+{
+ Key key = KSYM_UNDEFINED;
+ boolean got_key_event = FALSE;
+
+ while (!got_key_event)
+ {
+ if (PendingEvent()) /* got event */
+ {
+ Event event;
+
+ NextEvent(&event);
+
+ switch(event.type)
+ {
+ case EVENT_KEYPRESS:
+ {
+ key = GetEventKey((KeyEvent *)&event, TRUE);
+
+ /* press 'Escape' or 'Enter' to keep the existing key binding */
+ if (key == KSYM_Escape || key == KSYM_Return)
+ key = KSYM_UNDEFINED; /* keep old value */
+
+ got_key_event = TRUE;
+ }
+ break;
+
+ case EVENT_KEYRELEASE:
+ key_joystick_mapping = 0;
+ break;
+
+ default:
+ HandleOtherEvents(&event);
+ break;
+ }
+ }
+
+ BackToFront();
+ DoAnimation();
+
+ /* don't eat all CPU time */
+ Delay(10);
+ }
+
+ return key;
+}
+
+static void drawSetupValue(int pos)
+{
+ int xpos = MENU_SCREEN_VALUE_XPOS;
+ int ypos = MENU_SCREEN_START_YPOS + pos;
+ int font_nr = FONT_VALUE_1;
+ char *value_string = getSetupValue(setup_info[pos].type & ~TYPE_GHOSTED,
+ setup_info[pos].value);
+
+ if (value_string == NULL)
+ return;
+
+ if (setup_info[pos].type & TYPE_KEY)
+ {
+ xpos = 3;
+
+ if (setup_info[pos].type & TYPE_QUERY)
+ {
+ value_string = "<press key>";
+ font_nr = FONT_INPUT_ACTIVE;
+ }
+ }
+ else if (setup_info[pos].type & TYPE_STRING)
+ {
+ int max_value_len = (SCR_FIELDX - 2) * 2;
+
+ xpos = 1;
+ font_nr = FONT_VALUE_2;
+
+ if (strlen(value_string) > max_value_len)
+ value_string[max_value_len] = '\0';
+ }
+ else if (setup_info[pos].type & TYPE_BOOLEAN_STYLE &&
+ !*(boolean *)(setup_info[pos].value))
+ font_nr = FONT_OPTION_OFF;
+
+ DrawText(mSX + xpos * 32, mSY + ypos * 32,
+ (xpos == 3 ? " " : " "), font_nr);
+ DrawText(mSX + xpos * 32, mSY + ypos * 32, value_string, font_nr);
+}
+
+static void changeSetupValue(int pos)
+{
+ if (setup_info[pos].type & TYPE_BOOLEAN_STYLE)
+ {
+ *(boolean *)setup_info[pos].value ^= TRUE;
+ }
+ else if (setup_info[pos].type & TYPE_KEY)
+ {
+ Key key;
+
+ setup_info[pos].type |= TYPE_QUERY;
+ drawSetupValue(pos);
+ setup_info[pos].type &= ~TYPE_QUERY;
+
+ key = getSetupKey();
+ if (key != KSYM_UNDEFINED)
+ *(Key *)setup_info[pos].value = key;
+ }
+
+ drawSetupValue(pos);
+}
+
+static void DrawSetupScreen_Generic()
+{
+ char *title_string = NULL;
+ int i;
+
+ UnmapAllGadgets();
+ CloseDoor(DOOR_CLOSE_2);
+
+ ClearWindow();
+
+ if (setup_mode == SETUP_MODE_MAIN)
+ {
+ setup_info = setup_info_main;
+ title_string = "Setup";
+ }
+ else if (setup_mode == SETUP_MODE_GAME)
+ {
+ setup_info = setup_info_game;
+ title_string = "Setup Game";
+ }
+ else if (setup_mode == SETUP_MODE_EDITOR)
+ {
+ setup_info = setup_info_editor;
+ title_string = "Setup Editor";
+ }
+ else if (setup_mode == SETUP_MODE_GRAPHICS)
+ {
+ setup_info = setup_info_graphics;
+ title_string = "Setup Graphics";
+ }
+ else if (setup_mode == SETUP_MODE_SOUND)
+ {
+ setup_info = setup_info_sound;
+ title_string = "Setup Sound";
+ }
+ else if (setup_mode == SETUP_MODE_ARTWORK)
+ {
+ setup_info = setup_info_artwork;
+ title_string = "Custom Artwork";
+ }
+ else if (setup_mode == SETUP_MODE_SHORTCUT)
+ {
+ setup_info = setup_info_shortcut;
+ title_string = "Setup Shortcuts";
+ }
+
+ DrawText(mSX + 16, mSY + 16, title_string, FONT_TITLE_1);
+
+ num_setup_info = 0;
+ for(i=0; setup_info[i].type != 0 && i < MAX_MENU_ENTRIES_ON_SCREEN; i++)
+ {
+ void *value_ptr = setup_info[i].value;
+ int ypos = MENU_SCREEN_START_YPOS + i;
+ int font_nr = FONT_MENU_1;
+
+ /* set some entries to "unchangeable" according to other variables */
+ if ((value_ptr == &setup.sound && !audio.sound_available) ||
+ (value_ptr == &setup.sound_loops && !audio.loops_available) ||
+ (value_ptr == &setup.sound_music && !audio.music_available) ||
+ (value_ptr == &setup.fullscreen && !video.fullscreen_available))
+ setup_info[i].type |= TYPE_GHOSTED;
+
+ if (setup_info[i].type & TYPE_STRING)
+ font_nr = FONT_MENU_2;
+
+ DrawText(mSX + 32, mSY + ypos * 32, setup_info[i].text, font_nr);
+
+ if (setup_info[i].type & TYPE_ENTER_MENU)
+ initCursor(i, IMG_MENU_BUTTON_RIGHT);
+ else if (setup_info[i].type & TYPE_LEAVE_MENU)
+ initCursor(i, IMG_MENU_BUTTON_LEFT);
+ else if (setup_info[i].type & ~TYPE_SKIP_ENTRY)
+ initCursor(i, IMG_MENU_BUTTON);
+
+ if (setup_info[i].type & TYPE_VALUE)
+ drawSetupValue(i);
+
+ num_setup_info++;
+ }
+
+ FadeToFront();
+ InitAnimation();
+ HandleSetupScreen_Generic(0,0,0,0,MB_MENU_INITIALIZE);
+}
+
+void HandleSetupScreen_Generic(int mx, int my, int dx, int dy, int button)
+{
+ static int choice_store[MAX_SETUP_MODES];
+ int choice = choice_store[setup_mode]; /* always starts with 0 */
+ int x = 0;
+ int y = choice;
+
+ if (button == MB_MENU_INITIALIZE)
+ {
+ /* advance to first valid menu entry */
+ while (choice < num_setup_info &&
+ (setup_info[choice].type & TYPE_SKIP_ENTRY))
+ choice++;
+ choice_store[setup_mode] = choice;
+
+ drawCursor(choice, FC_RED);
+ return;
+ }
+ else if (button == MB_MENU_LEAVE)
+ {
+ for (y=0; y<num_setup_info; y++)
+ {
+ if (setup_info[y].type & TYPE_LEAVE_MENU)
+ {
+ void (*menu_callback_function)(void) = setup_info[y].value;
+
+ menu_callback_function();
+ break; /* absolutely needed because function changes 'setup_info'! */
+ }
+ }
+
+ return;
+ }
+
+ if (mx || my) /* mouse input */
+ {
+ x = (mx - SX) / 32;
+ y = (my - SY) / 32 - MENU_SCREEN_START_YPOS;
+ }
+ else if (dx || dy) /* keyboard input */
+ {
+ if (dx)
+ {
+ int menu_navigation_type = (dx < 0 ? TYPE_LEAVE_MENU : TYPE_ENTER_MENU);
+
+ if ((setup_info[choice].type & menu_navigation_type) ||
+ (setup_info[choice].type & TYPE_BOOLEAN_STYLE))
+ button = MB_MENU_CHOICE;
+ }
+ else if (dy)
+ y = choice + dy;
+
+ /* jump to next non-empty menu entry (up or down) */
+ while (y > 0 && y < num_setup_info - 1 &&
+ (setup_info[y].type & TYPE_SKIP_ENTRY))
+ y += dy;
+ }
+
+ if (x == 0 && y >= 0 && y < num_setup_info &&
+ (setup_info[y].type & ~TYPE_SKIP_ENTRY))
+ {
+ if (button)
+ {
+ if (y != choice)
+ {
+ drawCursor(y, FC_RED);
+ drawCursor(choice, FC_BLUE);
+ choice = choice_store[setup_mode] = y;
+ }
+ }
+ else if (!(setup_info[y].type & TYPE_GHOSTED))
+ {
+ if (setup_info[y].type & TYPE_ENTER_OR_LEAVE_MENU)
+ {
+ void (*menu_callback_function)(void) = setup_info[choice].value;
+
+ menu_callback_function();
+ }
+ else
+ {
+ if ((setup_info[y].type & TYPE_KEYTEXT) &&
+ (setup_info[y + 1].type & TYPE_KEY))
+ y++;
+
+ if (setup_info[y].type & TYPE_VALUE)
+ changeSetupValue(y);
+ }
+ }
+ }
+
+ BackToFront();
+
+ if (game_status == SETUP)
+ DoAnimation();
+}
+
+void DrawSetupScreen_Input()
+{
+ ClearWindow();
+
+ DrawText(mSX+16, mSY+16, "Setup Input", FONT_TITLE_1);
+
+ initCursor(0, IMG_MENU_BUTTON);
+ initCursor(1, IMG_MENU_BUTTON);
+ initCursor(2, IMG_MENU_BUTTON_RIGHT);
+ initCursor(13, IMG_MENU_BUTTON_LEFT);
+
+ drawCursorXY(10, 0, IMG_MENU_BUTTON_LEFT);
+ drawCursorXY(12, 0, IMG_MENU_BUTTON_RIGHT);
+
+ DrawText(mSX+32, mSY+2*32, "Player:", FONT_MENU_1);
+ DrawText(mSX+32, mSY+3*32, "Device:", FONT_MENU_1);
+ DrawText(mSX+32, mSY+15*32, "Back", FONT_MENU_1);
+
+#if 0
+ DeactivateJoystickForCalibration();
+ DrawTextFCentered(SYSIZE - 20, FONT_TEXT_4,
+ "Joysticks deactivated on this screen");
+#endif
+
+ HandleSetupScreen_Input(0,0, 0,0, MB_MENU_INITIALIZE);
+ FadeToFront();
+ InitAnimation();
+}
+
+static void setJoystickDeviceToNr(char *device_name, int device_nr)
+{
+ if (device_name == NULL)
+ return;
+
+ if (device_nr < 0 || device_nr >= MAX_PLAYERS)
+ device_nr = 0;
+
+ if (strlen(device_name) > 1)
+ {
+ char c1 = device_name[strlen(device_name) - 1];
+ char c2 = device_name[strlen(device_name) - 2];
+
+ if (c1 >= '0' && c1 <= '9' && !(c2 >= '0' && c2 <= '9'))
+ device_name[strlen(device_name) - 1] = '0' + (char)(device_nr % 10);
+ }
+ else
+ strncpy(device_name, getDeviceNameFromJoystickNr(device_nr),
+ strlen(device_name));
+}
+
+static void drawPlayerSetupInputInfo(int player_nr)
+{
+ int i;
+ static struct SetupKeyboardInfo custom_key;
+ static struct
+ {
+ Key *key;
+ char *text;
+ } custom[] =
+ {
+ { &custom_key.left, "Joystick Left" },
+ { &custom_key.right, "Joystick Right" },
+ { &custom_key.up, "Joystick Up" },
+ { &custom_key.down, "Joystick Down" },
+ { &custom_key.snap, "Button 1" },
+ { &custom_key.bomb, "Button 2" }
+ };
+ static char *joystick_name[MAX_PLAYERS] =
+ {
+ "Joystick1",
+ "Joystick2",
+ "Joystick3",
+ "Joystick4"
+ };
+
+ custom_key = setup.input[player_nr].key;
+
+ DrawText(mSX+11*32, mSY+2*32, int2str(player_nr + 1, 1), FONT_INPUT_ACTIVE);
+#if 1
+ DrawGraphicThruMaskExt(drawto, mSX + 8 * TILEX, mSY + 2 * TILEY,
+ PLAYER_NR_GFX(IMG_PLAYER_1, player_nr), 0);
+#else
+ DrawGraphicThruMask(8, 2, PLAYER_NR_GFX(IMG_PLAYER_1, player_nr), 0);
+#endif
+
+ if (setup.input[player_nr].use_joystick)
+ {
+ char *device_name = setup.input[player_nr].joy.device_name;
+
+ DrawText(mSX+8*32, mSY+3*32,
+ joystick_name[getJoystickNrFromDeviceName(device_name)],
+ FONT_VALUE_1);
+ DrawText(mSX+32, mSY+4*32, "Calibrate", FONT_MENU_1);
+ }
+ else
+ {
+ DrawText(mSX+8*32, mSY+3*32, "Keyboard ", FONT_VALUE_1);
+ DrawText(mSX+32, mSY+4*32, "Customize", FONT_MENU_1);
+ }
+
+ DrawText(mSX+32, mSY+5*32, "Actual Settings:", FONT_MENU_1);
+ drawCursorXY(1, 4, IMG_MENU_BUTTON_LEFT);
+ drawCursorXY(1, 5, IMG_MENU_BUTTON_RIGHT);
+ drawCursorXY(1, 6, IMG_MENU_BUTTON_UP);
+ drawCursorXY(1, 7, IMG_MENU_BUTTON_DOWN);
+ DrawText(mSX+2*32, mSY+6*32, ":", FONT_VALUE_OLD);
+ DrawText(mSX+2*32, mSY+7*32, ":", FONT_VALUE_OLD);
+ DrawText(mSX+2*32, mSY+8*32, ":", FONT_VALUE_OLD);
+ DrawText(mSX+2*32, mSY+9*32, ":", FONT_VALUE_OLD);
+ DrawText(mSX+32, mSY+10*32, "Snap Field:", FONT_VALUE_OLD);
+ DrawText(mSX+32, mSY+12*32, "Place Bomb:", FONT_VALUE_OLD);
+
+ for (i=0; i<6; i++)
+ {
+ int ypos = 6 + i + (i > 3 ? i-3 : 0);
+
+ DrawText(mSX + 3*32, mSY + ypos*32,
+ " ", FONT_VALUE_1);
+ DrawText(mSX + 3*32, mSY + ypos*32,
+ (setup.input[player_nr].use_joystick ?
+ custom[i].text :
+ getKeyNameFromKey(*custom[i].key)), FONT_VALUE_1);
+ }
+}
+
+void HandleSetupScreen_Input(int mx, int my, int dx, int dy, int button)
+{
+ static int choice = 0;
+ static int player_nr = 0;
+ int x = 0;
+ int y = choice;
+ int pos_start = SETUPINPUT_SCREEN_POS_START;
+ int pos_empty1 = SETUPINPUT_SCREEN_POS_EMPTY1;
+ int pos_empty2 = SETUPINPUT_SCREEN_POS_EMPTY2;
+ int pos_end = SETUPINPUT_SCREEN_POS_END;
+
+ if (button == MB_MENU_INITIALIZE)
+ {
+ drawPlayerSetupInputInfo(player_nr);
+ drawCursor(choice, FC_RED);
+ return;
+ }
+ else if (button == MB_MENU_LEAVE)
+ {
+ setup_mode = SETUP_MODE_MAIN;
+ DrawSetupScreen();
+ InitJoysticks();
+ }
+
+ if (mx || my) /* mouse input */
+ {
+ x = (mx - SX) / 32;
+ y = (my - SY) / 32 - MENU_SCREEN_START_YPOS;
+ }
+ else if (dx || dy) /* keyboard input */
+ {
+ if (dx && choice == 0)
+ x = (dx < 0 ? 10 : 12);
+ else if ((dx && choice == 1) ||
+ (dx == +1 && choice == 2) ||
+ (dx == -1 && choice == pos_end))
+ button = MB_MENU_CHOICE;
+ else if (dy)
+ y = choice + dy;
+
+ if (y >= pos_empty1 && y <= pos_empty2)
+ y = (dy > 0 ? pos_empty2 + 1 : pos_empty1 - 1);
+ }
+
+ if (y == 0 && ((x == 0 && !button) || ((x == 10 || x == 12) && button)))
+ {
+ static unsigned long delay = 0;
+
+ if (!DelayReached(&delay, GADGET_FRAME_DELAY))
+ goto out;
+
+ player_nr = (player_nr + (x == 10 ? -1 : +1) + MAX_PLAYERS) % MAX_PLAYERS;
+
+ drawPlayerSetupInputInfo(player_nr);
+ }
+ else if (x == 0 && y >= pos_start && y <= pos_end &&
+ !(y >= pos_empty1 && y <= pos_empty2))
+ {
+ if (button)
+ {
+ if (y != choice)
+ {
+ drawCursor(y, FC_RED);
+ drawCursor(choice, FC_BLUE);
+ choice = y;
+ }
+ }
+ else
+ {
+ if (y == 1)
+ {
+ char *device_name = setup.input[player_nr].joy.device_name;
+
+ if (!setup.input[player_nr].use_joystick)
+ {
+ int new_device_nr = (dx >= 0 ? 0 : MAX_PLAYERS - 1);
+
+ setJoystickDeviceToNr(device_name, new_device_nr);
+ setup.input[player_nr].use_joystick = TRUE;
+ }
+ else
+ {
+ int device_nr = getJoystickNrFromDeviceName(device_name);
+ int new_device_nr = device_nr + (dx >= 0 ? +1 : -1);
+
+ if (new_device_nr < 0 || new_device_nr >= MAX_PLAYERS)
+ setup.input[player_nr].use_joystick = FALSE;
+ else
+ setJoystickDeviceToNr(device_name, new_device_nr);
+ }
+
+ drawPlayerSetupInputInfo(player_nr);
+ }
+ else if (y == 2)
+ {
+ if (setup.input[player_nr].use_joystick)
+ {
+ InitJoysticks();
+ CalibrateJoystick(player_nr);
+ }
+ else
+ CustomizeKeyboard(player_nr);
+ }
+ else if (y == pos_end)
+ {
+ InitJoysticks();
+
+ setup_mode = SETUP_MODE_MAIN;
+ DrawSetupScreen();
+ }
+ }
+ }
+
+ BackToFront();
+
+ out:
+
+ if (game_status == SETUP)
+ DoAnimation();
+}
+
+void CustomizeKeyboard(int player_nr)
+{
+ int i;
+ int step_nr;
+ boolean finished = FALSE;
+ static struct SetupKeyboardInfo custom_key;
+ static struct
+ {
+ Key *key;
+ char *text;
+ } customize_step[] =
+ {
+ { &custom_key.left, "Move Left" },
+ { &custom_key.right, "Move Right" },
+ { &custom_key.up, "Move Up" },
+ { &custom_key.down, "Move Down" },
+ { &custom_key.snap, "Snap Field" },
+ { &custom_key.bomb, "Place Bomb" }
+ };
+
+ /* read existing key bindings from player setup */
+ custom_key = setup.input[player_nr].key;
+
+ ClearWindow();
+ DrawText(mSX + 16, mSY + 16, "Keyboard Input", FONT_TITLE_1);
+
+ BackToFront();
+ InitAnimation();
+
+ step_nr = 0;
+ DrawText(mSX, mSY + (2+2*step_nr)*32,
+ customize_step[step_nr].text, FONT_INPUT_ACTIVE);
+ DrawText(mSX, mSY + (2+2*step_nr+1)*32,
+ "Key:", FONT_INPUT_ACTIVE);
+ DrawText(mSX + 4*32, mSY + (2+2*step_nr+1)*32,
+ getKeyNameFromKey(*customize_step[step_nr].key), FONT_VALUE_OLD);
+
+ while(!finished)
+ {
+ if (PendingEvent()) /* got event */
+ {
+ Event event;
+
+ NextEvent(&event);
+
+ switch(event.type)
+ {
+ case EVENT_KEYPRESS:
+ {
+ Key key = GetEventKey((KeyEvent *)&event, FALSE);
+
+ if (key == KSYM_Escape || (key == KSYM_Return && step_nr == 6))
+ {
+ finished = TRUE;
+ break;
+ }
+
+ /* all keys configured -- wait for "Escape" or "Return" key */
+ if (step_nr == 6)
+ 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_VALUE_1);
+ DrawText(mSX + 4*32, mSY + (2+2*step_nr+1)*32,
+ getKeyNameFromKey(key), FONT_VALUE_1);
+ 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);
+
+ /* press 'Enter' to leave */
+ if (step_nr == 6)
+ {
+ DrawText(mSX + 16, mSY + 15*32+16,
+ "Press Enter", FONT_TITLE_1);
+ break;
+ }
+
+ /* query next key binding */
+ DrawText(mSX, mSY+(2+2*step_nr)*32,
+ customize_step[step_nr].text, FONT_INPUT_ACTIVE);
+ DrawText(mSX, mSY+(2+2*step_nr+1)*32,
+ "Key:", FONT_INPUT_ACTIVE);
+ DrawText(mSX + 4*32, mSY+(2+2*step_nr+1)*32,
+ getKeyNameFromKey(*customize_step[step_nr].key),
+ FONT_VALUE_OLD);
+ }
+ break;
+
+ case EVENT_KEYRELEASE:
+ key_joystick_mapping = 0;
+ break;
+
+ default:
+ HandleOtherEvents(&event);
+ break;
+ }
+ }
+
+ BackToFront();
+ DoAnimation();
+
+ /* don't eat all CPU time */
+ Delay(10);
+ }
+
+ /* write new key bindings back to player setup */
+ setup.input[player_nr].key = custom_key;
+
+ StopAnimation();
+ DrawSetupScreen_Input();
+}
+
+static boolean CalibrateJoystickMain(int player_nr)
+{
+ int new_joystick_xleft = JOYSTICK_XMIDDLE;
+ int new_joystick_xright = JOYSTICK_XMIDDLE;
+ int new_joystick_yupper = JOYSTICK_YMIDDLE;
+ int new_joystick_ylower = JOYSTICK_YMIDDLE;
+ int new_joystick_xmiddle, new_joystick_ymiddle;
+
+ int joystick_fd = joystick.fd[player_nr];
+ int x, y, last_x, last_y, xpos = 8, ypos = 3;
+ boolean check[3][3];
+ int check_remaining = 3 * 3;
+ int joy_x, joy_y;
+ int joy_value;
+ int result = -1;
+
+ if (joystick.status == JOYSTICK_NOT_AVAILABLE)
+ return FALSE;
+
+ if (joystick_fd < 0 || !setup.input[player_nr].use_joystick)
+ return FALSE;