+ /* calculated after (possible) reload of custom artwork */
+ name_width = getTextWidth(name_text, FONT_MENU_1);
+ level_width = 9 * 32;
+
+ DrawText(mSX + 32 + name_width, mSY + 2 * 32, setup.player_name,
+ FONT_INPUT_1);
+
+ DrawText(mSX + getCurrentLevelTextPos() * 32, mSY + 3 * 32,
+ int2str(level_nr, 3), FONT_VALUE_1);
+
+ {
+ int text_height = getFontHeight(FONT_TEXT_3);
+ int xpos = getLevelRangeTextPos() * 32 + 8;
+ int ypos2 = 3 * 32 + 16;
+ int ypos1 = ypos2 - text_height;
+
+ DrawTextF(mSX - SX + xpos, mSY - SY + ypos1, FONT_TEXT_3,
+ "%03d", leveldir_current->first_level);
+ DrawTextF(mSX - SX + xpos, mSY - SY + ypos2, FONT_TEXT_3,
+ "%03d", leveldir_current->last_level);
+ }
+
+ for (i = 0; i < 8; i++)
+ initCursor(i, (i == 1 || i == 4 || i == 6 ? IMG_MENU_BUTTON_ENTER_MENU :
+ IMG_MENU_BUTTON));
+
+ DrawTextSCentered(326, FONT_TITLE_2, PROGRAM_GAME_BY_STRING);
+#endif
+
+ DrawPreviewLevel(TRUE);
+
+ HandleMainMenu(0, 0, 0, 0, MB_MENU_INITIALIZE);
+
+ TapeStop();
+ if (TAPE_IS_EMPTY(tape))
+ LoadTape(level_nr);
+ DrawCompleteVideoDisplay();
+
+ PlayMenuSound();
+ PlayMenuMusic();
+
+ /* create gadgets for main menu screen */
+ FreeScreenGadgets();
+ CreateScreenGadgets();
+
+ /* map gadgets for main menu screen */
+ MapTapeButtons();
+ MapScreenMenuGadgets(SCREEN_MASK_MAIN);
+
+ DrawMaskedBorder(REDRAW_ALL);
+
+ if (do_fading)
+ FadeIn(redraw_mask);
+ else
+ BackToFront();
+
+ InitAnimation();
+
+ OpenDoor(DOOR_CLOSE_1 | DOOR_OPEN_2);
+}
+
+void DrawAndFadeInMainMenu(int redraw_mask)
+{
+ DrawMainMenuExt(redraw_mask, TRUE);
+}
+
+void DrawMainMenu()
+{
+ DrawMainMenuExt(REDRAW_ALL, FALSE);
+}
+
+#if 0
+static void gotoTopLevelDir()
+{
+ /* move upwards to top level directory */
+ while (leveldir_current->node_parent)
+ {
+ /* write a "path" into level tree for easy navigation to last level */
+ if (leveldir_current->node_parent->node_group->cl_first == -1)
+ {
+ int num_leveldirs = numTreeInfoInGroup(leveldir_current);
+ int leveldir_pos = posTreeInfo(leveldir_current);
+ int num_page_entries;
+ int cl_first, cl_cursor;
+
+ if (num_leveldirs <= NUM_MENU_ENTRIES_ON_SCREEN)
+ num_page_entries = num_leveldirs;
+ else
+ num_page_entries = NUM_MENU_ENTRIES_ON_SCREEN;
+
+ cl_first = MAX(0, leveldir_pos - num_page_entries + 1);
+ cl_cursor = leveldir_pos - cl_first;
+
+ leveldir_current->node_parent->node_group->cl_first = cl_first;
+ leveldir_current->node_parent->node_group->cl_cursor = cl_cursor;
+ }
+
+ leveldir_current = leveldir_current->node_parent;
+ }
+}
+#endif
+
+void HandleTitleScreen(int mx, int my, int dx, int dy, int button)
+{
+ static unsigned long title_delay = 0;
+ static int title_nr = 0;
+ boolean return_to_main_menu = FALSE;
+ boolean use_fading_main_menu = TRUE;
+ boolean use_cross_fading = !show_titlescreen_initial; /* default */
+
+ if (button == MB_MENU_INITIALIZE)
+ {
+ int last_game_status = game_status; /* save current game status */
+
+ title_delay = 0;
+ title_nr = 0;
+
+ if (show_titlescreen_initial &&
+ graphic_info[IMG_TITLESCREEN_INITIAL_1].bitmap == NULL)
+ show_titlescreen_initial = FALSE;
+
+ if (game_status == GAME_MODE_INFO)
+ {
+ if (graphic_info[IMG_TITLESCREEN_1].bitmap == NULL)
+ {
+ DrawInfoScreen_NotAvailable("Title screen information:",
+ "No title screen for this level set.");
+
+ return;
+ }
+
+ FadeSoundsAndMusic();
+
+ FadeOut(REDRAW_ALL);
+ }
+
+ /* force TITLE music on title info screen */
+ game_status = GAME_MODE_TITLE;
+
+ PlayMenuSound();
+ PlayMenuMusic();
+
+ game_status = last_game_status; /* restore current game status */
+
+ DrawTitleScreenImage(title_nr);
+
+ FadeIn(REDRAW_ALL);
+
+ DelayReached(&title_delay, 0); /* reset delay counter */
+
+ return;
+ }
+
+ if (title.auto_delay_final > -1 &&
+ DelayReached(&title_delay, title.auto_delay_final))
+ button = MB_MENU_CHOICE;
+
+ if (button == MB_MENU_LEAVE)
+ {
+ return_to_main_menu = TRUE;
+ use_fading_main_menu = FALSE;
+ }
+ else if (button == MB_MENU_CHOICE)
+ {
+ int anim_mode;
+
+ if (game_status == GAME_MODE_INFO &&
+ graphic_info[IMG_TITLESCREEN_1].bitmap == NULL)
+ {
+ info_mode = INFO_MODE_MAIN;
+ DrawInfoScreen();
+
+ return;
+ }
+
+ title_nr++;
+
+ if (show_titlescreen_initial &&
+ (title_nr >= MAX_NUM_TITLE_SCREENS ||
+ graphic_info[IMG_TITLESCREEN_INITIAL_1 + title_nr].bitmap == NULL))
+ {
+ show_titlescreen_initial = FALSE;
+
+ title_nr = 0; /* restart with title screens for current level set */
+ }
+
+ anim_mode = graphic_info[getTitleScreenGraphic() + title_nr].anim_mode;
+
+ use_cross_fading = (anim_mode == ANIM_FADE ? FALSE :
+ anim_mode == ANIM_CROSSFADE ? TRUE :
+ use_cross_fading);
+
+ if (!use_cross_fading)
+ FadeOut(REDRAW_ALL);
+
+ if (title_nr < MAX_NUM_TITLE_SCREENS &&
+ graphic_info[getTitleScreenGraphic() + title_nr].bitmap != NULL)
+ {
+ if (use_cross_fading)
+ FadeCrossSaveBackbuffer();
+
+ DrawTitleScreenImage(title_nr);
+
+ if (use_cross_fading)
+ FadeCross(REDRAW_ALL);
+ else
+ FadeIn(REDRAW_ALL);
+
+ DelayReached(&title_delay, 0); /* reset delay counter */
+ }
+ else
+ {
+ FadeSoundsAndMusic();
+
+ FadeOut(REDRAW_ALL);
+
+ return_to_main_menu = TRUE;
+ }
+ }
+
+ if (return_to_main_menu)
+ {
+ show_titlescreen_initial = FALSE;
+
+ RedrawBackground();
+
+ if (game_status == GAME_MODE_INFO)
+ {
+ OpenDoor(DOOR_CLOSE_1 | DOOR_CLOSE_2 | DOOR_NO_DELAY | DOOR_FORCE_REDRAW);
+
+ info_mode = INFO_MODE_MAIN;
+ DrawInfoScreenExt(REDRAW_ALL, use_fading_main_menu);
+ }
+ else /* default: return to main menu */
+ {
+ OpenDoor(DOOR_CLOSE_1 | DOOR_OPEN_2 | DOOR_NO_DELAY | DOOR_FORCE_REDRAW);
+
+ game_status = GAME_MODE_MAIN;
+ DrawMainMenuExt(REDRAW_ALL, use_fading_main_menu);
+ }
+ }
+}
+
+void HandleMainMenu_SelectLevel(int step, int direction)
+{
+ int old_level_nr = level_nr;
+ int new_level_nr;
+
+ new_level_nr = old_level_nr + step * direction;
+ if (new_level_nr < leveldir_current->first_level)
+ new_level_nr = leveldir_current->first_level;
+ if (new_level_nr > leveldir_current->last_level)
+ new_level_nr = leveldir_current->last_level;
+
+ if (setup.handicap && new_level_nr > leveldir_current->handicap_level)
+ {
+ /* skipping levels is only allowed when trying to skip single level */
+ if (setup.skip_levels && step == 1 &&
+ Request("Level still unsolved ! Skip despite handicap ?", REQ_ASK))
+ {
+ leveldir_current->handicap_level++;
+ SaveLevelSetup_SeriesInfo();
+ }
+
+ new_level_nr = leveldir_current->handicap_level;
+ }
+
+ if (new_level_nr != old_level_nr)
+ {
+ struct MainControlInfo *mci= getMainControlInfo(MAIN_CONTROL_CURRENT_LEVEL);
+
+ level_nr = new_level_nr;
+
+#if 1
+ DrawText(mSX + mci->pos_text->x, mSY + mci->pos_text->y,
+ int2str(level_nr, 3), mci->font_text);
+#else
+ DrawText(mSX + 11 * 32, mSY + 3 * 32, int2str(level_nr, 3), FONT_VALUE_1);
+#endif
+
+ LoadLevel(level_nr);
+ DrawPreviewLevel(TRUE);
+
+ TapeErase();
+ LoadTape(level_nr);
+ DrawCompleteVideoDisplay();
+
+ /* needed because DrawPreviewLevel() takes some time */
+ BackToFront();
+ SyncDisplay();
+ }
+}
+
+#if 1
+
+void HandleMainMenu(int mx, int my, int dx, int dy, int button)
+{
+ static int choice = MAIN_CONTROL_GAME;
+ int pos = choice;
+ int i;
+
+ if (button == MB_MENU_INITIALIZE)
+ {
+ DrawCursorAndText_Main(choice, TRUE);
+
+ return;
+ }
+
+ if (mx || my) /* mouse input */
+ {
+ pos = -1;
+
+ for (i = 0; main_controls[i].nr != -1; i++)
+ {
+ if (insideMenuPosRect(main_controls[i].pos_button, mx - mSX, my - mSY) ||
+ insideMenuPosRect(main_controls[i].pos_text, mx - mSX, my - mSY) ||
+ insideMenuPosRect(main_controls[i].pos_input, mx - mSX, my - mSY))
+ {
+ pos = main_controls[i].nr;
+
+ break;
+ }
+ }
+ }
+ else if (dx || dy) /* keyboard input */
+ {
+ if (dx > 0 && (choice == MAIN_CONTROL_INFO ||
+ choice == MAIN_CONTROL_SETUP))
+ button = MB_MENU_CHOICE;
+ else if (dy)
+ pos = choice + dy;
+ }
+
+ if (pos == MAIN_CONTROL_LEVELS && dx != 0 && button)
+ {
+ HandleMainMenu_SelectLevel(1, dx < 0 ? -1 : +1);
+ }
+ else if (pos >= MAIN_CONTROL_NAME && pos <= MAIN_CONTROL_QUIT)
+ {
+ if (button)
+ {
+ if (pos != choice)
+ {
+ DrawCursorAndText_Main(choice, FALSE);
+ DrawCursorAndText_Main(pos, TRUE);
+
+ choice = pos;
+ }
+ }
+ else
+ {
+ if (pos == MAIN_CONTROL_NAME)
+ {
+ game_status = GAME_MODE_PSEUDO_TYPENAME;
+
+ HandleTypeName(strlen(setup.player_name), 0);
+ }
+ else if (pos == MAIN_CONTROL_LEVELS)
+ {
+ if (leveldir_first)
+ {
+ game_status = GAME_MODE_LEVELS;
+
+ SaveLevelSetup_LastSeries();
+ SaveLevelSetup_SeriesInfo();
+
+#if 0
+ gotoTopLevelDir();
+#endif
+
+ DrawChooseLevel();
+ }
+ }
+ else if (pos == MAIN_CONTROL_SCORES)
+ {
+ game_status = GAME_MODE_SCORES;
+
+ DrawHallOfFame(-1);
+ }
+ else if (pos == MAIN_CONTROL_EDITOR)
+ {
+ if (leveldir_current->readonly &&
+ !strEqual(setup.player_name, "Artsoft"))
+ Request("This level is read only !", REQ_CONFIRM);
+
+ game_status = GAME_MODE_EDITOR;
+
+ DrawLevelEd();
+ }
+ else if (pos == MAIN_CONTROL_INFO)
+ {
+ game_status = GAME_MODE_INFO;
+ info_mode = INFO_MODE_MAIN;
+
+ DrawInfoScreen();
+ }
+ else if (pos == MAIN_CONTROL_GAME)
+ {
+ StartGameActions(options.network, setup.autorecord, NEW_RANDOMIZE);
+ }
+ else if (pos == MAIN_CONTROL_SETUP)
+ {
+ game_status = GAME_MODE_SETUP;
+ setup_mode = SETUP_MODE_MAIN;
+
+ DrawSetupScreen();
+ }
+ else if (pos == MAIN_CONTROL_QUIT)
+ {
+ SaveLevelSetup_LastSeries();
+ SaveLevelSetup_SeriesInfo();
+
+ if (Request("Do you really want to quit ?", REQ_ASK | REQ_STAY_CLOSED))
+ game_status = GAME_MODE_QUIT;
+ }
+ }
+ }
+
+ if (game_status == GAME_MODE_MAIN)
+ {
+ DrawPreviewLevel(FALSE);
+ DoAnimation();
+ }
+}
+
+#else
+
+void HandleMainMenu(int mx, int my, int dx, int dy, int button)
+{
+ static int choice = 5;
+ int x = 0;
+ int y = choice;
+
+ if (button == MB_MENU_INITIALIZE)
+ {
+ drawCursor(choice, TRUE);
+
+ return;
+ }
+
+ if (mx || my) /* mouse input */
+ {
+ x = (mx - mSX) / 32;
+ y = (my - mSY) / 32 - MENU_SCREEN_START_YPOS;
+ }
+ else if (dx || dy) /* keyboard input */
+ {
+ if (dx && choice == 1)
+ x = (dx < 0 ? 10 : 14);
+ else if (dx > 0)
+ {
+ if (choice == 4 || choice == 6)
+ button = MB_MENU_CHOICE;
+ }
+ else if (dy)
+ y = choice + dy;
+ }
+
+ if (y == 1 && dx != 0 && button)
+ {
+ HandleMainMenu_SelectLevel(1, dx < 0 ? -1 : +1);
+ }
+ else if (IN_VIS_FIELD(x, y) &&
+ y >= 0 && y <= 7 && (y != 1 || x < 10))
+ {
+ if (button)
+ {
+ if (y != choice)
+ {
+ drawCursor(choice, FALSE);
+ drawCursor(y, TRUE);
+
+ choice = y;
+ }
+ }
+ else
+ {
+ if (y == 0)
+ {
+ game_status = GAME_MODE_PSEUDO_TYPENAME;
+ HandleTypeName(strlen(setup.player_name), 0);
+ }
+ else if (y == 1)
+ {
+ if (leveldir_first)
+ {
+ game_status = GAME_MODE_LEVELS;
+ SaveLevelSetup_LastSeries();
+ SaveLevelSetup_SeriesInfo();
+
+#if 0
+ gotoTopLevelDir();
+#endif
+
+ DrawChooseLevel();
+ }
+ }
+ else if (y == 2)
+ {
+ game_status = GAME_MODE_SCORES;
+ DrawHallOfFame(-1);
+ }
+ else if (y == 3)
+ {
+ if (leveldir_current->readonly &&
+ !strEqual(setup.player_name, "Artsoft"))
+ Request("This level is read only !", REQ_CONFIRM);
+ game_status = GAME_MODE_EDITOR;
+ DrawLevelEd();
+ }
+ else if (y == 4)
+ {
+ game_status = GAME_MODE_INFO;
+ info_mode = INFO_MODE_MAIN;
+ DrawInfoScreen();
+ }
+ else if (y == 5)
+ {
+ StartGameActions(options.network, setup.autorecord, NEW_RANDOMIZE);
+ }
+ else if (y == 6)
+ {
+ game_status = GAME_MODE_SETUP;
+ setup_mode = SETUP_MODE_MAIN;
+
+ DrawSetupScreen();
+ }
+ else if (y == 7)
+ {
+ SaveLevelSetup_LastSeries();
+ SaveLevelSetup_SeriesInfo();
+
+ if (Request("Do you really want to quit ?", REQ_ASK | REQ_STAY_CLOSED))
+ game_status = GAME_MODE_QUIT;
+ }
+ }
+ }
+
+ if (game_status == GAME_MODE_MAIN)
+ {
+ DrawPreviewLevel(FALSE);
+ DoAnimation();
+ }
+}
+
+#endif
+
+
+/* ========================================================================= */
+/* info screen functions */
+/* ========================================================================= */
+
+static struct TokenInfo *info_info;
+static int num_info_info;
+
+static void execInfoTitleScreen()
+{
+ info_mode = INFO_MODE_TITLE;
+ DrawInfoScreen();
+}
+
+static void execInfoElements()
+{
+ info_mode = INFO_MODE_ELEMENTS;
+ DrawInfoScreen();
+}
+
+static void execInfoMusic()
+{
+ info_mode = INFO_MODE_MUSIC;
+ DrawInfoScreen();
+}
+
+static void execInfoCredits()
+{
+ info_mode = INFO_MODE_CREDITS;
+ DrawInfoScreen();
+}
+
+static void execInfoProgram()
+{
+ info_mode = INFO_MODE_PROGRAM;
+ DrawInfoScreen();
+}
+
+static void execInfoLevelSet()
+{
+ info_mode = INFO_MODE_LEVELSET;
+ DrawInfoScreen();
+}
+
+static void execExitInfo()
+{
+ game_status = GAME_MODE_MAIN;
+ DrawMainMenu();
+}
+
+static struct TokenInfo info_info_main[] =
+{
+ { TYPE_ENTER_SCREEN, execInfoTitleScreen, "Title Screen" },
+ { TYPE_ENTER_SCREEN, execInfoElements, "Elements Info" },
+ { TYPE_ENTER_SCREEN, execInfoMusic, "Music Info" },
+ { TYPE_ENTER_SCREEN, execInfoCredits, "Credits" },
+ { TYPE_ENTER_SCREEN, execInfoProgram, "Program Info" },
+ { TYPE_ENTER_SCREEN, execInfoLevelSet, "Level Set Info" },
+ { TYPE_EMPTY, NULL, "" },
+ { TYPE_LEAVE_MENU, execExitInfo, "Exit" },
+
+ { 0, NULL, NULL }
+};
+
+static void DrawCursorAndText_Info(int pos, boolean active)
+{
+ int xpos = MENU_SCREEN_START_XPOS;
+ int ypos = MENU_SCREEN_START_YPOS + pos;
+ int font_nr = FONT_MENU_1;
+
+ if (active)
+ font_nr = FONT_ACTIVE(font_nr);
+
+ DrawText(mSX + xpos * 32, mSY + ypos * 32, info_info[pos].text, font_nr);
+
+ if (info_info[pos].type & ~TYPE_SKIP_ENTRY)
+ drawCursor(pos, active);
+}
+
+static void DrawInfoScreen_Main(int redraw_mask, boolean do_fading)
+{
+ int i;
+
+ UnmapAllGadgets();
+ CloseDoor(DOOR_CLOSE_2);
+
+ ClearWindow();
+
+ DrawTextSCentered(mSY - SY + 16, FONT_TITLE_1, "Info Screen");
+
+ info_info = info_info_main;
+ num_info_info = 0;
+
+ for (i = 0; info_info[i].type != 0 && i < NUM_MENU_ENTRIES_ON_SCREEN; i++)
+ {
+#if 0
+ int xpos = MENU_SCREEN_START_XPOS;
+ int ypos = MENU_SCREEN_START_YPOS + i;
+ int font_nr = FONT_MENU_1;
+#endif
+
+ if (info_info[i].type & (TYPE_ENTER_MENU|TYPE_ENTER_LIST))
+ initCursor(i, IMG_MENU_BUTTON_ENTER_MENU);
+ else if (info_info[i].type & (TYPE_LEAVE_MENU|TYPE_LEAVE_LIST))
+ initCursor(i, IMG_MENU_BUTTON_LEAVE_MENU);
+ else if (info_info[i].type & ~TYPE_SKIP_ENTRY)
+ initCursor(i, IMG_MENU_BUTTON);
+
+#if 1
+ DrawCursorAndText_Info(i, FALSE);
+#else
+ DrawText(mSX + xpos * 32, mSY + ypos * 32, info_info[i].text, font_nr);
+#endif
+
+ num_info_info++;
+ }
+
+ HandleInfoScreen_Main(0, 0, 0, 0, MB_MENU_INITIALIZE);
+
+ PlayMenuSound();
+ PlayMenuMusic();
+
+ DrawMaskedBorder(REDRAW_ALL);
+
+ if (do_fading)
+ FadeIn(redraw_mask);
+ else
+ BackToFront();
+
+ InitAnimation();
+}
+
+void HandleInfoScreen_Main(int mx, int my, int dx, int dy, int button)
+{
+ static int choice_store[MAX_INFO_MODES];
+ int choice = choice_store[info_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_info_info &&
+ info_info[choice].type & TYPE_SKIP_ENTRY)
+ choice++;
+ choice_store[info_mode] = choice;
+
+#if 1
+ DrawCursorAndText_Info(choice, TRUE);
+#else
+ drawCursor(choice, TRUE);
+#endif
+
+ return;
+ }
+ else if (button == MB_MENU_LEAVE)
+ {
+ for (y = 0; y < num_info_info; y++)
+ {
+ if (info_info[y].type & TYPE_LEAVE_MENU)
+ {
+ void (*menu_callback_function)(void) = info_info[y].value;
+
+ menu_callback_function();
+
+ break; /* absolutely needed because function changes 'info_info'! */
+ }
+ }
+
+ return;
+ }
+
+ if (mx || my) /* mouse input */
+ {
+ x = (mx - mSX) / 32;
+ y = (my - mSY) / 32 - MENU_SCREEN_START_YPOS;
+ }
+ else if (dx || dy) /* keyboard input */
+ {
+ if (dx)
+ {
+ int menu_navigation_type = (dx < 0 ? TYPE_LEAVE : TYPE_ENTER);
+
+ if (info_info[choice].type & menu_navigation_type ||
+ info_info[choice].type & TYPE_ENTER_SCREEN ||
+ info_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_info_info - 1 &&
+ info_info[y].type & TYPE_SKIP_ENTRY)
+ y += dy;
+ }
+
+ if (IN_VIS_FIELD(x, y) &&
+ y >= 0 && y < num_info_info && info_info[y].type & ~TYPE_SKIP_ENTRY)
+ {
+ if (button)
+ {
+ if (y != choice)
+ {
+#if 1
+ DrawCursorAndText_Info(choice, FALSE);
+ DrawCursorAndText_Info(y, TRUE);
+#else
+ drawCursor(choice, FALSE);
+ drawCursor(y, TRUE);
+#endif
+
+ choice = choice_store[info_mode] = y;
+ }
+ }
+ else if (!(info_info[y].type & TYPE_GHOSTED))
+ {
+ if (info_info[y].type & TYPE_ENTER_OR_LEAVE)
+ {
+ void (*menu_callback_function)(void) = info_info[choice].value;
+
+ menu_callback_function();
+ }
+ }
+ }
+}
+
+void DrawInfoScreen_NotAvailable(char *text_title, char *text_error)
+{
+ int ystart = 150;
+ int ybottom = SYSIZE - 20;
+
+ SetMainBackgroundImageIfDefined(IMG_BACKGROUND_INFO_LEVELSET);
+
+ ClearWindow();
+ DrawHeadline();
+
+ DrawTextSCentered(100, FONT_TEXT_1, text_title);
+
+ DrawTextSCentered(ybottom, FONT_TEXT_4,
+ "Press any key or button for info menu");
+
+ DrawTextSCentered(ystart, FONT_TEXT_2, text_error);
+}
+
+void DrawInfoScreen_HelpAnim(int start, int max_anims, boolean init)
+{
+ static int infoscreen_step[MAX_INFO_ELEMENTS_ON_SCREEN];
+ static int infoscreen_frame[MAX_INFO_ELEMENTS_ON_SCREEN];
+ int xstart = mSX + 16;
+ int ystart = mSY + 64 + 2 * 32;
+ int ystep = TILEY + 4;
+ int element, action, direction;
+ int graphic;
+ int delay;
+ int sync_frame;
+ int i, j;
+
+ if (init)
+ {
+ for (i = 0; i < MAX_INFO_ELEMENTS_ON_SCREEN; i++)
+ infoscreen_step[i] = infoscreen_frame[i] = 0;
+
+ ClearWindow();
+ DrawHeadline();
+
+ DrawTextSCentered(100, FONT_TEXT_1, "The Game Elements:");
+
+ DrawTextSCentered(SYSIZE - 20, FONT_TEXT_4,
+ "Press any key or button for next page");
+
+ FrameCounter = 0;
+ }
+
+ i = j = 0;
+ while (helpanim_info[j].element != HELPANIM_LIST_END)
+ {
+ if (i >= start + MAX_INFO_ELEMENTS_ON_SCREEN ||
+ i >= max_anims)
+ break;
+ else if (i < start)
+ {
+ while (helpanim_info[j].element != HELPANIM_LIST_NEXT)
+ j++;
+
+ j++;
+ i++;
+
+ continue;
+ }
+
+ j += infoscreen_step[i - start];
+
+ element = helpanim_info[j].element;
+ action = helpanim_info[j].action;
+ direction = helpanim_info[j].direction;
+
+ if (element < 0)
+ element = EL_UNKNOWN;
+
+ if (action != -1 && direction != -1)
+ graphic = el_act_dir2img(element, action, direction);
+ else if (action != -1)
+ graphic = el_act2img(element, action);
+ else if (direction != -1)
+ graphic = el_dir2img(element, direction);
+ else
+ graphic = el2img(element);
+
+ delay = helpanim_info[j++].delay;
+
+ if (delay == -1)
+ delay = 1000000;
+
+ if (infoscreen_frame[i - start] == 0)
+ {
+ sync_frame = 0;
+ infoscreen_frame[i - start] = delay - 1;
+ }
+ else
+ {
+ sync_frame = delay - infoscreen_frame[i - start];
+ infoscreen_frame[i - start]--;
+ }
+
+ if (helpanim_info[j].element == HELPANIM_LIST_NEXT)
+ {
+ if (!infoscreen_frame[i - start])
+ infoscreen_step[i - start] = 0;
+ }
+ else
+ {
+ if (!infoscreen_frame[i - start])
+ infoscreen_step[i - start]++;
+ while (helpanim_info[j].element != HELPANIM_LIST_NEXT)
+ j++;
+ }
+
+ j++;
+
+ ClearRectangleOnBackground(drawto, xstart, ystart + (i - start) * ystep,
+ TILEX, TILEY);
+ DrawGraphicAnimationExt(drawto, xstart, ystart + (i - start) * ystep,
+ graphic, sync_frame, USE_MASKING);
+
+ if (init)
+ DrawInfoScreen_HelpText(element, action, direction, i - start);
+
+ i++;
+ }
+
+ redraw_mask |= REDRAW_FIELD;
+
+ FrameCounter++;
+}
+
+static char *getHelpText(int element, int action, int direction)
+{
+ char token[MAX_LINE_LEN];
+
+ strcpy(token, element_info[element].token_name);
+
+ if (action != -1)
+ strcat(token, element_action_info[action].suffix);
+
+ if (direction != -1)
+ strcat(token, element_direction_info[MV_DIR_TO_BIT(direction)].suffix);
+
+ return getHashEntry(helptext_info, token);
+}
+
+void DrawInfoScreen_HelpText(int element, int action, int direction, int ypos)
+{
+ int font_nr = FONT_LEVEL_NUMBER;
+ int font_width = getFontWidth(font_nr);
+ int sx = mSX + MINI_TILEX + TILEX + MINI_TILEX;
+ int sy = mSY + 65 + 2 * 32 + 1;
+ int ystep = TILEY + 4;
+ int pad_x = sx - SX;
+ int max_chars_per_line = (SXSIZE - pad_x - MINI_TILEX) / font_width;
+ int max_lines_per_text = 2;
+ char *text = NULL;
+
+ if (action != -1 && direction != -1) /* element.action.direction */
+ text = getHelpText(element, action, direction);
+
+ if (text == NULL && action != -1) /* element.action */
+ text = getHelpText(element, action, -1);
+
+ if (text == NULL && direction != -1) /* element.direction */
+ text = getHelpText(element, -1, direction);
+
+ if (text == NULL) /* base element */
+ text = getHelpText(element, -1, -1);
+
+ if (text == NULL) /* not found */
+ text = "No description available";
+
+ if (strlen(text) <= max_chars_per_line) /* only one line of text */
+ sy += getFontHeight(font_nr) / 2;
+
+ DrawTextWrapped(sx, sy + ypos * ystep, text, font_nr,
+ max_chars_per_line, max_lines_per_text);
+}
+
+void DrawInfoScreen_TitleScreen()
+{
+ DrawTitleScreen();
+}
+
+void HandleInfoScreen_TitleScreen(int button)
+{
+ HandleTitleScreen(0, 0, 0, 0, button);
+}
+
+void DrawInfoScreen_Elements()
+{
+ SetMainBackgroundImageIfDefined(IMG_BACKGROUND_INFO_ELEMENTS);
+
+ FadeOut(REDRAW_FIELD);
+
+ LoadHelpAnimInfo();
+ LoadHelpTextInfo();
+
+ HandleInfoScreen_Elements(MB_MENU_INITIALIZE);
+
+ FadeIn(REDRAW_FIELD);
+
+ InitAnimation();
+}
+
+void HandleInfoScreen_Elements(int button)
+{
+ static unsigned long info_delay = 0;
+ static int num_anims;
+ static int num_pages;
+ static int page;
+ int anims_per_page = MAX_INFO_ELEMENTS_ON_SCREEN;
+ int i;
+
+ if (button == MB_MENU_INITIALIZE)
+ {
+ boolean new_element = TRUE;
+
+ num_anims = 0;
+
+ for (i = 0; helpanim_info[i].element != HELPANIM_LIST_END; i++)
+ {
+ if (helpanim_info[i].element == HELPANIM_LIST_NEXT)
+ new_element = TRUE;
+ else if (new_element)
+ {
+ num_anims++;
+ new_element = FALSE;
+ }
+ }
+
+ num_pages = (num_anims + anims_per_page - 1) / anims_per_page;
+ page = 0;
+ }
+
+ if (button == MB_MENU_LEAVE)
+ {
+ info_mode = INFO_MODE_MAIN;
+ DrawInfoScreen();
+
+ return;
+ }
+ else if (button == MB_MENU_CHOICE || button == MB_MENU_INITIALIZE)
+ {
+ if (button != MB_MENU_INITIALIZE)
+ page++;
+
+ if (page >= num_pages)
+ {
+ FadeSoundsAndMusic();
+ FadeOut(REDRAW_FIELD);
+
+ info_mode = INFO_MODE_MAIN;
+ DrawAndFadeInInfoScreen(REDRAW_FIELD);
+
+ return;
+ }
+
+ if (button != MB_MENU_INITIALIZE)
+ FadeCrossSaveBackbuffer();
+
+ DrawInfoScreen_HelpAnim(page * anims_per_page, num_anims, TRUE);
+
+ if (button != MB_MENU_INITIALIZE)
+ FadeCross(REDRAW_FIELD);
+ }
+ else
+ {
+ if (DelayReached(&info_delay, GameFrameDelay))
+ if (page < num_pages)
+ DrawInfoScreen_HelpAnim(page * anims_per_page, num_anims, FALSE);
+
+ PlayMenuSoundIfLoop();
+ }
+}
+
+void DrawInfoScreen_Music()
+{
+ SetMainBackgroundImageIfDefined(IMG_BACKGROUND_INFO_MUSIC);
+
+ FadeOut(REDRAW_FIELD);
+
+ ClearWindow();
+ DrawHeadline();
+
+ LoadMusicInfo();
+
+ HandleInfoScreen_Music(MB_MENU_INITIALIZE);
+
+ FadeIn(REDRAW_FIELD);
+}
+
+void HandleInfoScreen_Music(int button)
+{
+ static struct MusicFileInfo *list = NULL;
+ int ystart = 150, dy = 30;
+ int ybottom = SYSIZE - 20;
+
+ if (button == MB_MENU_INITIALIZE)
+ {
+ list = music_file_info;
+
+ if (list == NULL)
+ {
+ FadeSoundsAndMusic();
+
+ ClearWindow();
+ DrawHeadline();
+
+ DrawTextSCentered(100, FONT_TEXT_1, "No music info for this level set.");
+
+ DrawTextSCentered(ybottom, FONT_TEXT_4,
+ "Press any key or button for info menu");
+
+ return;
+ }
+ }
+
+ if (button == MB_MENU_LEAVE)
+ {
+ info_mode = INFO_MODE_MAIN;
+ DrawInfoScreen();
+
+ return;
+ }
+ else if (button == MB_MENU_CHOICE || button == MB_MENU_INITIALIZE)
+ {
+ int y = 0;
+
+ if (button != MB_MENU_INITIALIZE)
+ if (list != NULL)
+ list = list->next;
+
+ if (list == NULL)
+ {
+ FadeSoundsAndMusic();
+ FadeOut(REDRAW_FIELD);
+
+ info_mode = INFO_MODE_MAIN;
+ DrawAndFadeInInfoScreen(REDRAW_FIELD);
+
+ return;
+ }
+
+ FadeSoundsAndMusic();
+
+ if (button != MB_MENU_INITIALIZE)
+ FadeCrossSaveBackbuffer();
+
+ ClearWindow();
+ DrawHeadline();
+
+ if (list->is_sound)
+ {
+ int sound = list->music;
+
+ if (sound_info[sound].loop)
+ PlaySoundLoop(sound);
+ else
+ PlaySound(sound);
+
+ DrawTextSCentered(100, FONT_TEXT_1, "The Game Background Sounds:");
+ }
+ else
+ {
+ PlayMusic(list->music);
+
+ DrawTextSCentered(100, FONT_TEXT_1, "The Game Background Music:");
+ }
+
+ if (!strEqual(list->title, UNKNOWN_NAME))
+ {
+ if (!strEqual(list->title_header, UNKNOWN_NAME))
+ DrawTextSCentered(ystart + y++ * dy, FONT_TEXT_2, list->title_header);
+
+ DrawTextFCentered(ystart + y++ * dy, FONT_TEXT_3, "\"%s\"", list->title);
+ }
+
+ if (!strEqual(list->artist, UNKNOWN_NAME))
+ {
+ if (!strEqual(list->artist_header, UNKNOWN_NAME))
+ DrawTextSCentered(ystart + y++ * dy, FONT_TEXT_2, list->artist_header);
+ else
+ DrawTextSCentered(ystart + y++ * dy, FONT_TEXT_2, "by");
+
+ DrawTextFCentered(ystart + y++ * dy, FONT_TEXT_3, "%s", list->artist);
+ }
+
+ if (!strEqual(list->album, UNKNOWN_NAME))
+ {
+ if (!strEqual(list->album_header, UNKNOWN_NAME))
+ DrawTextSCentered(ystart + y++ * dy, FONT_TEXT_2, list->album_header);
+ else
+ DrawTextSCentered(ystart + y++ * dy, FONT_TEXT_2, "from the album");
+
+ DrawTextFCentered(ystart + y++ * dy, FONT_TEXT_3, "\"%s\"", list->album);
+ }
+
+ if (!strEqual(list->year, UNKNOWN_NAME))
+ {
+ if (!strEqual(list->year_header, UNKNOWN_NAME))
+ DrawTextSCentered(ystart + y++ * dy, FONT_TEXT_2, list->year_header);
+ else
+ DrawTextSCentered(ystart + y++ * dy, FONT_TEXT_2, "from the year");
+
+ DrawTextFCentered(ystart + y++ * dy, FONT_TEXT_3, "%s", list->year);
+ }
+
+ DrawTextSCentered(ybottom, FONT_TEXT_4,
+ "Press any key or button for next page");
+
+ if (button != MB_MENU_INITIALIZE)
+ FadeCross(REDRAW_FIELD);
+ }
+
+ if (list != NULL && list->is_sound && sound_info[list->music].loop)
+ PlaySoundLoop(list->music);
+}
+
+static boolean DrawInfoScreen_CreditsScreen(int screen_nr)
+{
+ int ystart = 150, ystep = 30;
+ int ybottom = SYSIZE - 20;
+
+ if (screen_nr > 8)
+ return FALSE;
+
+ ClearWindow();
+ DrawHeadline();
+
+ DrawTextSCentered(100, FONT_TEXT_1, "Credits:");
+
+ if (screen_nr == 0)
+ {
+ DrawTextSCentered(ystart + 0 * ystep, FONT_TEXT_2,
+ "Special thanks to");
+ DrawTextSCentered(ystart + 1 * ystep, FONT_TEXT_3,
+ "Peter Liepa");
+ DrawTextSCentered(ystart + 2 * ystep, FONT_TEXT_2,
+ "for creating");
+ DrawTextSCentered(ystart + 3 * ystep, FONT_TEXT_3,
+ "\"Boulder Dash\"");
+ DrawTextSCentered(ystart + 4 * ystep, FONT_TEXT_2,
+ "in the year");
+ DrawTextSCentered(ystart + 5 * ystep, FONT_TEXT_3,
+ "1984");
+ DrawTextSCentered(ystart + 6 * ystep, FONT_TEXT_2,
+ "published by");
+ DrawTextSCentered(ystart + 7 * ystep, FONT_TEXT_3,
+ "First Star Software");
+ }
+ else if (screen_nr == 1)
+ {
+ DrawTextSCentered(ystart + 0 * ystep, FONT_TEXT_2,
+ "Special thanks to");
+ DrawTextSCentered(ystart + 1 * ystep, FONT_TEXT_3,
+ "Klaus Heinz & Volker Wertich");
+ DrawTextSCentered(ystart + 2 * ystep, FONT_TEXT_2,
+ "for creating");
+ DrawTextSCentered(ystart + 3 * ystep, FONT_TEXT_3,
+ "\"Emerald Mine\"");
+ DrawTextSCentered(ystart + 4 * ystep, FONT_TEXT_2,
+ "in the year");
+ DrawTextSCentered(ystart + 5 * ystep, FONT_TEXT_3,
+ "1987");
+ DrawTextSCentered(ystart + 6 * ystep, FONT_TEXT_2,
+ "published by");
+ DrawTextSCentered(ystart + 7 * ystep, FONT_TEXT_3,
+ "Kingsoft");
+ }
+ else if (screen_nr == 2)
+ {
+ DrawTextSCentered(ystart + 0 * ystep, FONT_TEXT_2,
+ "Special thanks to");
+ DrawTextSCentered(ystart + 1 * ystep, FONT_TEXT_3,
+ "Michael Stopp & Philip Jespersen");
+ DrawTextSCentered(ystart + 2 * ystep, FONT_TEXT_2,
+ "for creating");
+ DrawTextSCentered(ystart + 3 * ystep, FONT_TEXT_3,
+ "\"Supaplex\"");
+ DrawTextSCentered(ystart + 4 * ystep, FONT_TEXT_2,
+ "in the year");
+ DrawTextSCentered(ystart + 5 * ystep, FONT_TEXT_3,
+ "1991");
+ DrawTextSCentered(ystart + 6 * ystep, FONT_TEXT_2,
+ "published by");
+ DrawTextSCentered(ystart + 7 * ystep, FONT_TEXT_3,
+ "Digital Integration");
+ }
+ else if (screen_nr == 3)
+ {
+ DrawTextSCentered(ystart + 0 * ystep, FONT_TEXT_2,
+ "Special thanks to");
+ DrawTextSCentered(ystart + 1 * ystep, FONT_TEXT_3,
+ "Hiroyuki Imabayashi");
+ DrawTextSCentered(ystart + 2 * ystep, FONT_TEXT_2,
+ "for creating");
+ DrawTextSCentered(ystart + 3 * ystep, FONT_TEXT_3,
+ "\"Sokoban\"");
+ DrawTextSCentered(ystart + 4 * ystep, FONT_TEXT_2,
+ "in the year");
+ DrawTextSCentered(ystart + 5 * ystep, FONT_TEXT_3,
+ "1982");
+ DrawTextSCentered(ystart + 6 * ystep, FONT_TEXT_2,
+ "published by");
+ DrawTextSCentered(ystart + 7 * ystep, FONT_TEXT_3,
+ "Thinking Rabbit");
+ }
+ else if (screen_nr == 4)
+ {
+ DrawTextSCentered(ystart + 0 * ystep, FONT_TEXT_2,
+ "Special thanks to");
+ DrawTextSCentered(ystart + 1 * ystep, FONT_TEXT_3,
+ "Alan Bond");
+ DrawTextSCentered(ystart + 2 * ystep, FONT_TEXT_2,
+ "and");
+ DrawTextSCentered(ystart + 3 * ystep, FONT_TEXT_3,
+ "Jürgen Bonhagen");
+ DrawTextSCentered(ystart + 4 * ystep, FONT_TEXT_2,
+ "for the continuous creation");
+ DrawTextSCentered(ystart + 5 * ystep, FONT_TEXT_2,
+ "of outstanding level sets");
+ }
+ else if (screen_nr == 5)
+ {
+ DrawTextSCentered(ystart + 0 * ystep, FONT_TEXT_2,
+ "Thanks to");
+ DrawTextSCentered(ystart + 1 * ystep, FONT_TEXT_3,
+ "Peter Elzner");
+ DrawTextSCentered(ystart + 2 * ystep, FONT_TEXT_2,
+ "for ideas and inspiration by");
+ DrawTextSCentered(ystart + 3 * ystep, FONT_TEXT_3,
+ "Diamond Caves");
+
+ DrawTextSCentered(ystart + 5 * ystep, FONT_TEXT_2,
+ "Thanks to");
+ DrawTextSCentered(ystart + 6 * ystep, FONT_TEXT_3,
+ "Steffest");
+ DrawTextSCentered(ystart + 7 * ystep, FONT_TEXT_2,
+ "for ideas and inspiration by");
+ DrawTextSCentered(ystart + 8 * ystep, FONT_TEXT_3,
+ "DX-Boulderdash");
+ }
+ else if (screen_nr == 6)
+ {
+ DrawTextSCentered(ystart + 0 * ystep, FONT_TEXT_2,
+ "Thanks to");
+ DrawTextSCentered(ystart + 1 * ystep, FONT_TEXT_3,
+ "David Tritscher");
+ DrawTextSCentered(ystart + 2 * ystep, FONT_TEXT_2,
+ "for the new Emerald Mine engine");
+ }
+ else if (screen_nr == 7)
+ {
+ DrawTextSCentered(ystart + 0 * ystep, FONT_TEXT_2,
+ "Thanks to");
+ DrawTextSCentered(ystart + 1 * ystep, FONT_TEXT_3,
+ "Guido Schulz");
+ DrawTextSCentered(ystart + 2 * ystep, FONT_TEXT_2,
+ "for the initial DOS port");
+
+ DrawTextSCentered(ystart + 4 * ystep, FONT_TEXT_2,
+ "Thanks to");
+ DrawTextSCentered(ystart + 5 * ystep, FONT_TEXT_3,
+ "Karl Hörnell");
+ DrawTextSCentered(ystart + 6 * ystep, FONT_TEXT_2,
+ "for some additional toons");
+ }
+ else if (screen_nr == 8)
+ {
+ DrawTextSCentered(ystart + 0 * ystep, FONT_TEXT_2,
+ "And not to forget:");
+ DrawTextSCentered(ystart + 1 * ystep, FONT_TEXT_2,
+ "Many thanks to");
+ DrawTextSCentered(ystart + 2 * ystep, FONT_TEXT_3,
+ "All those who contributed");
+ DrawTextSCentered(ystart + 3 * ystep, FONT_TEXT_3,
+ "levels to this game");
+ DrawTextSCentered(ystart + 4 * ystep, FONT_TEXT_3,
+ "since 1995");
+ }
+#if 0
+ else
+ {
+ return FALSE;
+ }
+#endif
+
+ DrawTextSCentered(ybottom, FONT_TEXT_4,
+ "Press any key or button for next page");
+
+ return TRUE;
+}
+
+void DrawInfoScreen_Credits()
+{
+ SetMainBackgroundImageIfDefined(IMG_BACKGROUND_INFO_CREDITS);
+
+ FadeSoundsAndMusic();
+
+ FadeOut(REDRAW_FIELD);
+
+ HandleInfoScreen_Credits(MB_MENU_INITIALIZE);
+
+ FadeIn(REDRAW_FIELD);
+}
+
+void HandleInfoScreen_Credits(int button)
+{
+ static int screen_nr = 0;
+
+ if (button == MB_MENU_INITIALIZE)
+ {
+ screen_nr = 0;
+
+ DrawInfoScreen_CreditsScreen(screen_nr);
+ }
+ else if (button == MB_MENU_LEAVE)
+ {
+ info_mode = INFO_MODE_MAIN;
+ DrawInfoScreen();
+
+ return;
+ }
+ else if (button == MB_MENU_CHOICE)
+ {
+ boolean show_screen;
+
+ screen_nr++;
+
+ FadeCrossSaveBackbuffer();
+
+ show_screen = DrawInfoScreen_CreditsScreen(screen_nr);
+
+ if (show_screen)
+ {
+ FadeCross(REDRAW_FIELD);
+ }
+ else
+ {
+ FadeSoundsAndMusic();
+ FadeOut(REDRAW_FIELD);
+
+ info_mode = INFO_MODE_MAIN;
+ DrawAndFadeInInfoScreen(REDRAW_FIELD);
+ }
+ }
+ else
+ {
+ PlayMenuSoundIfLoop();
+ }
+}
+
+void DrawInfoScreen_Program()
+{
+ int ystart = 150, ystep = 30;
+ int ybottom = SYSIZE - 20;
+
+ SetMainBackgroundImageIfDefined(IMG_BACKGROUND_INFO_PROGRAM);
+
+ FadeOut(REDRAW_FIELD);
+
+ ClearWindow();
+ DrawHeadline();
+
+ DrawTextSCentered(100, FONT_TEXT_1, "Program Information:");
+
+ DrawTextSCentered(ystart + 0 * ystep, FONT_TEXT_2,
+ "This game is Freeware!");
+ DrawTextSCentered(ystart + 1 * ystep, FONT_TEXT_2,
+ "If you like it, send e-mail to:");
+ DrawTextSCentered(ystart + 2 * ystep, FONT_TEXT_3,
+ PROGRAM_EMAIL_STRING);
+ DrawTextSCentered(ystart + 3 * ystep, FONT_TEXT_2,
+ "or SnailMail to:");
+ DrawTextSCentered(ystart + 4 * ystep + 0, FONT_TEXT_3,
+ "Holger Schemel");
+ DrawTextSCentered(ystart + 4 * ystep + 20, FONT_TEXT_3,
+ "Detmolder Strasse 189");
+ DrawTextSCentered(ystart + 4 * ystep + 40, FONT_TEXT_3,
+ "33604 Bielefeld");
+ DrawTextSCentered(ystart + 4 * ystep + 60, FONT_TEXT_3,
+ "Germany");
+ DrawTextSCentered(ystart + 7 * ystep, FONT_TEXT_2,
+ "More information and levels:");
+ DrawTextSCentered(ystart + 8 * ystep, FONT_TEXT_3,
+ PROGRAM_WEBSITE_STRING);
+ DrawTextSCentered(ystart + 9 * ystep, FONT_TEXT_2,
+ "If you have created new levels,");
+ DrawTextSCentered(ystart + 10 * ystep, FONT_TEXT_2,
+ "send them to me to include them!");
+ DrawTextSCentered(ystart + 11 * ystep, FONT_TEXT_2,
+ ":-)");
+
+ DrawTextSCentered(ybottom, FONT_TEXT_4,
+ "Press any key or button for info menu");
+
+ FadeIn(REDRAW_FIELD);
+}
+
+void HandleInfoScreen_Program(int button)
+{
+ if (button == MB_MENU_LEAVE)
+ {
+ info_mode = INFO_MODE_MAIN;
+ DrawInfoScreen();
+
+ return;
+ }
+ else if (button == MB_MENU_CHOICE)
+ {
+ FadeSoundsAndMusic();
+ FadeOut(REDRAW_FIELD);
+
+ info_mode = INFO_MODE_MAIN;
+ DrawAndFadeInInfoScreen(REDRAW_FIELD);
+ }
+ else
+ {
+ PlayMenuSoundIfLoop();
+ }
+}
+
+void DrawInfoScreen_LevelSet()
+{
+ int ystart = 150;
+ int ybottom = SYSIZE - 20;
+ char *filename = getLevelSetInfoFilename();
+ int font_nr = FONT_LEVEL_NUMBER;
+ int font_width = getFontWidth(font_nr);
+ int font_height = getFontHeight(font_nr);
+ int pad_x = 32;
+ int pad_y = ystart;
+ int sx = SX + pad_x;
+ int sy = SY + pad_y;
+ int max_chars_per_line = (SXSIZE - 2 * pad_x) / font_width;
+ int max_lines_per_screen = (SYSIZE - pad_y) / font_height - 1;
+
+ SetMainBackgroundImageIfDefined(IMG_BACKGROUND_INFO_LEVELSET);
+
+ FadeOut(REDRAW_FIELD);
+
+ ClearWindow();
+ DrawHeadline();
+
+ DrawTextSCentered(100, FONT_TEXT_1, "Level Set Information:");
+
+ DrawTextSCentered(ybottom, FONT_TEXT_4,
+ "Press any key or button for info menu");
+
+ if (filename != NULL)
+ DrawTextFromFile(sx, sy, filename, font_nr, max_chars_per_line,
+ max_lines_per_screen);
+ else
+ DrawTextSCentered(ystart, FONT_TEXT_2,
+ "No information for this level set.");
+
+ FadeIn(REDRAW_FIELD);
+}
+
+void HandleInfoScreen_LevelSet(int button)
+{
+ if (button == MB_MENU_LEAVE)
+ {
+ info_mode = INFO_MODE_MAIN;
+ DrawInfoScreen();
+
+ return;
+ }
+ else if (button == MB_MENU_CHOICE)
+ {
+ FadeSoundsAndMusic();
+ FadeOut(REDRAW_FIELD);
+
+ info_mode = INFO_MODE_MAIN;
+ DrawAndFadeInInfoScreen(REDRAW_FIELD);
+ }
+ else
+ {
+ PlayMenuSoundIfLoop();
+ }
+}
+
+static void DrawInfoScreenExt(int redraw_mask, boolean do_fading)
+{
+ SetMainBackgroundImage(IMG_BACKGROUND_INFO);
+
+ if (info_mode == INFO_MODE_TITLE)
+ DrawInfoScreen_TitleScreen();
+ else if (info_mode == INFO_MODE_ELEMENTS)
+ DrawInfoScreen_Elements();
+ else if (info_mode == INFO_MODE_MUSIC)
+ DrawInfoScreen_Music();
+ else if (info_mode == INFO_MODE_CREDITS)
+ DrawInfoScreen_Credits();
+ else if (info_mode == INFO_MODE_PROGRAM)
+ DrawInfoScreen_Program();
+ else if (info_mode == INFO_MODE_LEVELSET)
+ DrawInfoScreen_LevelSet();
+ else
+ DrawInfoScreen_Main(redraw_mask, do_fading);
+
+ if (info_mode != INFO_MODE_MAIN &&
+ info_mode != INFO_MODE_TITLE &&
+ info_mode != INFO_MODE_MUSIC)
+ {
+ PlayMenuSound();
+ PlayMenuMusic();
+ }
+}
+
+void DrawAndFadeInInfoScreen(int redraw_mask)
+{
+ DrawInfoScreenExt(redraw_mask, TRUE);
+}
+
+void DrawInfoScreen()
+{
+ DrawInfoScreenExt(REDRAW_ALL, FALSE);
+}
+
+void HandleInfoScreen(int mx, int my, int dx, int dy, int button)
+{
+ if (info_mode == INFO_MODE_TITLE)
+ HandleInfoScreen_TitleScreen(button);
+ else if (info_mode == INFO_MODE_ELEMENTS)
+ HandleInfoScreen_Elements(button);
+ else if (info_mode == INFO_MODE_MUSIC)
+ HandleInfoScreen_Music(button);
+ else if (info_mode == INFO_MODE_CREDITS)
+ HandleInfoScreen_Credits(button);
+ else if (info_mode == INFO_MODE_PROGRAM)
+ HandleInfoScreen_Program(button);
+ else if (info_mode == INFO_MODE_LEVELSET)
+ HandleInfoScreen_LevelSet(button);
+ else
+ HandleInfoScreen_Main(mx, my, dx, dy, button);
+
+ DoAnimation();
+}
+
+
+/* ========================================================================= */
+/* type name functions */
+/* ========================================================================= */
+
+void HandleTypeName(int newxpos, Key key)
+{
+ struct MainControlInfo *mci = getMainControlInfo(MAIN_CONTROL_NAME);
+#if 1
+ static int xpos = 0;
+#else
+ static int xpos = 0, ypos = 2;
+#endif
+ int font_nr = mci->font_input;
+ int font_active_nr = FONT_ACTIVE(font_nr);
+ int font_width = getFontWidth(font_active_nr);
+#if 1
+ int startx = mSX + mci->pos_input->x;
+ int starty = mSY + mci->pos_input->y;
+#else
+ int name_width = getFontWidth(FONT_MENU_1) * strlen("Name:");
+ int startx = mSX + 32 + name_width;
+ int starty = mSY + ypos * 32;
+#endif
+
+ if (newxpos)
+ {
+ xpos = newxpos;
+
+ DrawText(startx, starty, setup.player_name, font_active_nr);
+ DrawText(startx + xpos * font_width, starty, "_", font_active_nr);
+
+ return;
+ }
+
+ if (((key >= KSYM_A && key <= KSYM_Z) ||
+ (key >= KSYM_a && key <= KSYM_z)) &&
+ xpos < MAX_PLAYER_NAME_LEN)
+ {
+ char ascii;
+
+ if (key >= KSYM_A && key <= KSYM_Z)
+ ascii = 'A' + (char)(key - KSYM_A);
+ else
+ ascii = 'a' + (char)(key - KSYM_a);
+
+ setup.player_name[xpos] = ascii;
+ setup.player_name[xpos + 1] = 0;
+
+ xpos++;
+
+ DrawText(startx, starty, setup.player_name, font_active_nr);
+ DrawText(startx + xpos * font_width, starty, "_", font_active_nr);
+ }
+ else if ((key == KSYM_Delete || key == KSYM_BackSpace) && xpos > 0)
+ {
+ xpos--;
+
+ setup.player_name[xpos] = 0;
+
+ DrawText(startx + xpos * font_width, starty, "_ ", font_active_nr);
+ }
+ else if (key == KSYM_Return && xpos > 0)
+ {
+ DrawText(startx, starty, setup.player_name, font_nr);
+ DrawText(startx + xpos * font_width, starty, " ", font_active_nr);
+
+ SaveSetup();
+
+ game_status = GAME_MODE_MAIN;
+ }
+}
+
+
+/* ========================================================================= */
+/* tree menu functions */
+/* ========================================================================= */
+
+static void DrawChooseTree(TreeInfo **ti_ptr)
+{
+ UnmapAllGadgets();
+
+ FreeScreenGadgets();
+ CreateScreenGadgets();
+
+ CloseDoor(DOOR_CLOSE_2);
+
+ ClearWindow();
+
+ HandleChooseTree(0, 0, 0, 0, MB_MENU_INITIALIZE, ti_ptr);
+ MapScreenTreeGadgets(*ti_ptr);
+
+ FadeToFront();
+ InitAnimation();
+}
+
+static void AdjustChooseTreeScrollbar(int id, int first_entry, TreeInfo *ti)
+{
+ struct GadgetInfo *gi = screen_gadget[id];
+ int items_max, items_visible, item_position;
+
+ items_max = numTreeInfoInGroup(ti);
+ items_visible = NUM_MENU_ENTRIES_ON_SCREEN;
+ item_position = first_entry;
+
+ if (item_position > items_max - items_visible)
+ item_position = items_max - items_visible;
+
+ ModifyGadget(gi, GDI_SCROLLBAR_ITEMS_MAX, items_max,
+ GDI_SCROLLBAR_ITEMS_VISIBLE, items_visible,
+ GDI_SCROLLBAR_ITEM_POSITION, item_position, GDI_END);
+}
+
+static void drawChooseTreeList(int first_entry, int num_page_entries,
+ TreeInfo *ti)
+{
+ int i;
+ char *title_string = NULL;
+ int yoffset_sets = MENU_TITLE1_YPOS;
+ int yoffset_setup = 16;
+ int yoffset = (ti->type == TREE_TYPE_LEVEL_DIR ? yoffset_sets :
+ yoffset_setup);
+ int last_game_status = game_status; /* save current game status */
+
+ title_string = ti->infotext;
+
+ DrawTextSCentered(mSY - SY + yoffset, FONT_TITLE_1, title_string);
+
+ /* force LEVELS font on artwork setup screen */
+ game_status = GAME_MODE_LEVELS;
+
+#if 1
+ /* clear tree list area, but not title or scrollbar */
+ DrawBackground(mSX, mSY + MENU_SCREEN_START_YPOS * 32,
+ SC_SCROLLBAR_XPOS + menu.scrollbar_xoffset,
+ NUM_MENU_ENTRIES_ON_SCREEN * 32);
+#else
+ /* clear tree list area, but not title or scrollbar */
+ DrawBackground(mSX, mSY + MENU_SCREEN_START_YPOS * 32,
+ SC_SCROLLBAR_XPOS + menu.scrollbar_xoffset,
+ MAX_MENU_ENTRIES_ON_SCREEN * 32);
+#endif
+
+ for (i = 0; i < num_page_entries; i++)
+ {
+ TreeInfo *node, *node_first;
+ int entry_pos = first_entry + i;
+ int xpos = MENU_SCREEN_START_XPOS;
+ int ypos = MENU_SCREEN_START_YPOS + i;
+ int startx = mSX + xpos * 32;
+ int starty = mSY + ypos * 32;
+ int font_nr = FONT_TEXT_1;
+ int font_xoffset = getFontBitmapInfo(font_nr)->draw_xoffset;
+ int startx_text = startx + font_xoffset;
+ int startx_scrollbar = mSX + SC_SCROLLBAR_XPOS + menu.scrollbar_xoffset;
+ int text_size = startx_scrollbar - startx_text;
+ int max_buffer_len = text_size / getFontWidth(font_nr);
+ char buffer[max_buffer_len + 1];
+
+ node_first = getTreeInfoFirstGroupEntry(ti);
+ node = getTreeInfoFromPos(node_first, entry_pos);
+
+ strncpy(buffer, node->name, max_buffer_len);
+ buffer[max_buffer_len] = '\0';
+
+ DrawText(startx, starty, buffer, font_nr + node->color);
+
+ if (node->parent_link)
+ initCursor(i, IMG_MENU_BUTTON_LEAVE_MENU);
+ else if (node->level_group)
+ initCursor(i, IMG_MENU_BUTTON_ENTER_MENU);
+ else
+ initCursor(i, IMG_MENU_BUTTON);
+ }
+
+ game_status = last_game_status; /* restore current game status */
+
+ redraw_mask |= REDRAW_FIELD;
+}
+
+static void drawChooseTreeInfo(int entry_pos, TreeInfo *ti)
+{
+ TreeInfo *node, *node_first;
+ int x, last_redraw_mask = redraw_mask;
+ int ypos = MENU_TITLE2_YPOS;
+ int font_nr = FONT_TITLE_2;
+
+ if (ti->type != TREE_TYPE_LEVEL_DIR)
+ return;
+
+ node_first = getTreeInfoFirstGroupEntry(ti);
+ node = getTreeInfoFromPos(node_first, entry_pos);
+
+ DrawBackgroundForFont(SX, SY + ypos, SXSIZE, getFontHeight(font_nr), font_nr);
+
+ if (node->parent_link)
+ DrawTextFCentered(ypos, font_nr, "leave group \"%s\"",
+ node->class_desc);
+ else if (node->level_group)
+ DrawTextFCentered(ypos, font_nr, "enter group \"%s\"",
+ node->class_desc);
+ else if (ti->type == TREE_TYPE_LEVEL_DIR)
+ DrawTextFCentered(ypos, font_nr, "%3d levels (%s)",
+ node->levels, node->class_desc);
+
+ /* let BackToFront() redraw only what is needed */
+ redraw_mask = last_redraw_mask | REDRAW_TILES;
+ for (x = 0; x < SCR_FIELDX; x++)
+ MarkTileDirty(x, 1);
+}
+
+static void HandleChooseTree(int mx, int my, int dx, int dy, int button,
+ TreeInfo **ti_ptr)
+{
+ TreeInfo *ti = *ti_ptr;
+ int x = 0;
+ int y = ti->cl_cursor;
+ int step = (button == 1 ? 1 : button == 2 ? 5 : 10);
+ int num_entries = numTreeInfoInGroup(ti);
+ int num_page_entries;
+ int last_game_status = game_status; /* save current game status */
+ boolean position_set_by_scrollbar = (dx == 999);
+
+ /* force LEVELS draw offset on choose level and artwork setup screen */
+ game_status = GAME_MODE_LEVELS;
+
+ if (num_entries <= NUM_MENU_ENTRIES_ON_SCREEN)
+ num_page_entries = num_entries;
+ else
+ num_page_entries = NUM_MENU_ENTRIES_ON_SCREEN;
+
+ game_status = last_game_status; /* restore current game status */
+
+ if (button == MB_MENU_INITIALIZE)
+ {
+ int num_entries = numTreeInfoInGroup(ti);
+ int entry_pos = posTreeInfo(ti);
+
+ if (ti->cl_first == -1)
+ {
+ /* only on initialization */
+ ti->cl_first = MAX(0, entry_pos - num_page_entries + 1);
+ ti->cl_cursor = entry_pos - ti->cl_first;
+ }
+ else if (ti->cl_cursor >= num_page_entries ||
+ (num_entries > num_page_entries &&
+ num_entries - ti->cl_first < num_page_entries))
+ {
+ /* only after change of list size (by custom graphic configuration) */
+ ti->cl_first = MAX(0, entry_pos - num_page_entries + 1);
+ ti->cl_cursor = entry_pos - ti->cl_first;
+ }
+
+ if (position_set_by_scrollbar)
+ ti->cl_first = dy;
+ else
+ AdjustChooseTreeScrollbar(SCREEN_CTRL_ID_SCROLL_VERTICAL,
+ ti->cl_first, ti);
+
+ drawChooseTreeList(ti->cl_first, num_page_entries, ti);
+ drawChooseTreeInfo(ti->cl_first + ti->cl_cursor, ti);
+ drawChooseTreeCursor(ti->cl_cursor, TRUE);
+
+ return;
+ }
+ else if (button == MB_MENU_LEAVE)
+ {
+ if (ti->node_parent)
+ {
+ *ti_ptr = ti->node_parent;
+ DrawChooseTree(ti_ptr);
+ }
+ else if (game_status == GAME_MODE_SETUP)
+ {
+ if (game_status == GAME_MODE_SETUP)
+ {
+ if (setup_mode == SETUP_MODE_CHOOSE_SCREEN_MODE)
+ execSetupGraphics();
+ else
+ execSetupArtwork();
+ }
+ }
+ else
+ {
+ game_status = GAME_MODE_MAIN;
+ DrawMainMenu();
+ }
+
+ return;
+ }
+
+ if (mx || my) /* mouse input */
+ {
+ int last_game_status = game_status; /* save current game status */
+
+ /* force LEVELS draw offset on artwork setup screen */
+ game_status = GAME_MODE_LEVELS;
+
+ x = (mx - mSX) / 32;
+ y = (my - mSY) / 32 - MENU_SCREEN_START_YPOS;
+
+ game_status = last_game_status; /* restore current game status */
+ }
+ else if (dx || dy) /* keyboard or scrollbar/scrollbutton input */
+ {
+ /* move cursor instead of scrolling when already at start/end of list */
+ if (dy == -1 * SCROLL_LINE && ti->cl_first == 0)
+ dy = -1;
+ else if (dy == +1 * SCROLL_LINE &&
+ ti->cl_first + num_page_entries == num_entries)
+ dy = 1;
+
+ /* handle scrolling screen one line or page */
+ if (ti->cl_cursor + dy < 0 ||
+ ti->cl_cursor + dy > num_page_entries - 1)
+ {
+ if (ABS(dy) == SCROLL_PAGE)
+ step = num_page_entries - 1;
+
+ if (dy < 0 && ti->cl_first > 0)
+ {
+ /* scroll page/line up */
+
+ ti->cl_first -= step;
+ if (ti->cl_first < 0)
+ ti->cl_first = 0;
+
+ drawChooseTreeList(ti->cl_first, num_page_entries, ti);
+ drawChooseTreeInfo(ti->cl_first + ti->cl_cursor, ti);
+ drawChooseTreeCursor(ti->cl_cursor, TRUE);
+
+ AdjustChooseTreeScrollbar(SCREEN_CTRL_ID_SCROLL_VERTICAL,
+ ti->cl_first, ti);
+ }
+ else if (dy > 0 && ti->cl_first + num_page_entries < num_entries)
+ {
+ /* scroll page/line down */
+
+ ti->cl_first += step;
+ if (ti->cl_first + num_page_entries > num_entries)
+ ti->cl_first = MAX(0, num_entries - num_page_entries);
+
+ drawChooseTreeList(ti->cl_first, num_page_entries, ti);
+ drawChooseTreeInfo(ti->cl_first + ti->cl_cursor, ti);
+ drawChooseTreeCursor(ti->cl_cursor, TRUE);
+
+ AdjustChooseTreeScrollbar(SCREEN_CTRL_ID_SCROLL_VERTICAL,
+ ti->cl_first, ti);
+ }
+
+ return;
+ }
+
+ /* handle moving cursor one line */
+ y = ti->cl_cursor + dy;
+ }
+
+ if (dx == 1)
+ {
+ TreeInfo *node_first, *node_cursor;
+ int entry_pos = ti->cl_first + y;
+
+ node_first = getTreeInfoFirstGroupEntry(ti);
+ node_cursor = getTreeInfoFromPos(node_first, entry_pos);
+
+ if (node_cursor->node_group)
+ {
+ node_cursor->cl_first = ti->cl_first;
+ node_cursor->cl_cursor = ti->cl_cursor;
+ *ti_ptr = node_cursor->node_group;
+ DrawChooseTree(ti_ptr);
+
+ return;
+ }
+ }
+ else if (dx == -1 && ti->node_parent)
+ {
+ *ti_ptr = ti->node_parent;
+ DrawChooseTree(ti_ptr);
+
+ return;
+ }
+
+ if (!anyScrollbarGadgetActive() &&
+ IN_VIS_FIELD(x, y) &&
+ mx < screen_gadget[SCREEN_CTRL_ID_SCROLL_VERTICAL]->x &&
+ y >= 0 && y < num_page_entries)
+ {
+ if (button)
+ {
+ if (y != ti->cl_cursor)
+ {
+ drawChooseTreeCursor(ti->cl_cursor, FALSE);
+ drawChooseTreeCursor(y, TRUE);
+ drawChooseTreeInfo(ti->cl_first + y, ti);
+
+ ti->cl_cursor = y;
+ }
+ }
+ else
+ {
+ TreeInfo *node_first, *node_cursor;
+ int entry_pos = ti->cl_first + y;
+
+ node_first = getTreeInfoFirstGroupEntry(ti);
+ node_cursor = getTreeInfoFromPos(node_first, entry_pos);
+
+ if (node_cursor->node_group)
+ {
+ node_cursor->cl_first = ti->cl_first;
+ node_cursor->cl_cursor = ti->cl_cursor;
+ *ti_ptr = node_cursor->node_group;
+ DrawChooseTree(ti_ptr);
+ }
+ else if (node_cursor->parent_link)
+ {
+ *ti_ptr = node_cursor->node_parent;
+ DrawChooseTree(ti_ptr);
+ }
+ else
+ {
+ node_cursor->cl_first = ti->cl_first;
+ node_cursor->cl_cursor = ti->cl_cursor;
+ *ti_ptr = node_cursor;
+
+ if (ti->type == TREE_TYPE_LEVEL_DIR)
+ {
+ LoadLevelSetup_SeriesInfo();
+
+ SaveLevelSetup_LastSeries();
+ SaveLevelSetup_SeriesInfo();
+ TapeErase();
+ }
+
+ if (game_status == GAME_MODE_SETUP)
+ {
+ if (setup_mode == SETUP_MODE_CHOOSE_SCREEN_MODE)
+ execSetupGraphics();
+ else
+ execSetupArtwork();
+ }
+ else
+ {
+ game_status = GAME_MODE_MAIN;
+ DrawMainMenu();
+ }
+ }
+ }
+ }
+}
+
+void DrawChooseLevel()
+{
+ SetMainBackgroundImage(IMG_BACKGROUND_LEVELS);
+
+ DrawChooseTree(&leveldir_current);
+
+ PlayMenuSound();
+ PlayMenuMusic();
+}
+
+void HandleChooseLevel(int mx, int my, int dx, int dy, int button)
+{
+ HandleChooseTree(mx, my, dx, dy, button, &leveldir_current);
+
+ DoAnimation();
+}
+
+void DrawHallOfFame(int highlight_position)
+{
+ UnmapAllGadgets();
+ FadeSoundsAndMusic();
+
+ /* (this is needed when called from GameEnd() after winning a game) */
+ KeyboardAutoRepeatOn();
+ ActivateJoystick();
+
+ /* (this is needed when called from GameEnd() after winning a game) */
+ SetDrawDeactivationMask(REDRAW_NONE);
+ SetDrawBackgroundMask(REDRAW_FIELD);
+
+ CloseDoor(DOOR_CLOSE_2);
+
+ if (highlight_position < 0)
+ LoadScore(level_nr);
+
+ FadeOut(REDRAW_FIELD);
+
+ InitAnimation();
+
+ PlayMenuSound();
+ PlayMenuMusic();
+
+ HandleHallOfFame(highlight_position, 0, 0, 0, MB_MENU_INITIALIZE);
+
+ FadeIn(REDRAW_FIELD);
+}
+
+static void drawHallOfFameList(int first_entry, int highlight_position)
+{
+ int i;
+
+ SetMainBackgroundImage(IMG_BACKGROUND_SCORES);
+ ClearWindow();
+
+ DrawTextSCentered(MENU_TITLE1_YPOS, FONT_TITLE_1, "Hall Of Fame");
+ DrawTextFCentered(MENU_TITLE2_YPOS, FONT_TITLE_2,
+ "HighScores of Level %d", level_nr);
+
+ for (i = 0; i < NUM_MENU_ENTRIES_ON_SCREEN; i++)
+ {
+ int entry = first_entry + i;
+ boolean active = (entry == highlight_position);
+ int font_nr1 = (active ? FONT_TEXT_1_ACTIVE : FONT_TEXT_1);
+ int font_nr2 = (active ? FONT_TEXT_2_ACTIVE : FONT_TEXT_2);
+ int font_nr3 = (active ? FONT_TEXT_3_ACTIVE : FONT_TEXT_3);
+ int font_nr4 = (active ? FONT_TEXT_4_ACTIVE : FONT_TEXT_4);
+ int dx1 = 3 * getFontWidth(font_nr1);
+ int dx2 = dx1 + getFontWidth(font_nr1);
+ int dx3 = dx2 + 25 * getFontWidth(font_nr3);
+ int sy = mSY + 64 + i * 32;
+
+ DrawText(mSX, sy, int2str(entry + 1, 3), font_nr1);
+ DrawText(mSX + dx1, sy, ".", font_nr1);
+ DrawText(mSX + dx2, sy, ".........................", font_nr3);
+
+ if (!strEqual(highscore[entry].Name, EMPTY_PLAYER_NAME))
+ DrawText(mSX + dx2, sy, highscore[entry].Name, font_nr2);
+
+ DrawText(mSX + dx3, sy, int2str(highscore[entry].Score, 5), font_nr4);
+ }
+
+ redraw_mask |= REDRAW_FIELD;
+}
+
+void HandleHallOfFame(int mx, int my, int dx, int dy, int button)
+{
+ static int first_entry = 0;
+ static int highlight_position = 0;
+ int step = (button == 1 ? 1 : button == 2 ? 5 : 10);
+
+ if (button == MB_MENU_INITIALIZE)
+ {
+ first_entry = 0;
+ highlight_position = mx;
+ drawHallOfFameList(first_entry, highlight_position);
+
+ return;
+ }
+
+ if (ABS(dy) == SCROLL_PAGE) /* handle scrolling one page */
+ step = NUM_MENU_ENTRIES_ON_SCREEN - 1;
+
+ if (dy < 0)
+ {
+ if (first_entry > 0)
+ {
+ first_entry -= step;
+ if (first_entry < 0)
+ first_entry = 0;
+
+ drawHallOfFameList(first_entry, highlight_position);
+ }
+ }
+ else if (dy > 0)
+ {
+ if (first_entry + NUM_MENU_ENTRIES_ON_SCREEN < MAX_SCORE_ENTRIES)
+ {
+ first_entry += step;
+ if (first_entry + NUM_MENU_ENTRIES_ON_SCREEN > MAX_SCORE_ENTRIES)
+ first_entry = MAX(0, MAX_SCORE_ENTRIES - NUM_MENU_ENTRIES_ON_SCREEN);
+
+ drawHallOfFameList(first_entry, highlight_position);
+ }
+ }
+ else if (button == MB_MENU_LEAVE)
+ {
+ FadeSound(SND_BACKGROUND_SCORES);
+
+ game_status = GAME_MODE_MAIN;
+
+ DrawMainMenu();
+ }
+ else if (button == MB_MENU_CHOICE)
+ {
+ FadeSound(SND_BACKGROUND_SCORES);
+ FadeOut(REDRAW_FIELD);
+
+ game_status = GAME_MODE_MAIN;
+
+ DrawAndFadeInMainMenu(REDRAW_FIELD);
+ }
+
+ if (game_status == GAME_MODE_SCORES)
+ PlayMenuSoundIfLoop();
+
+ DoAnimation();
+}
+
+
+/* ========================================================================= */
+/* setup screen functions */
+/* ========================================================================= */
+
+static struct TokenInfo *setup_info;
+static int num_setup_info;
+
+static char *screen_mode_text;
+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()
+{
+ if (video.fullscreen_available && screen_modes == NULL)
+ {
+ int i;
+
+ for (i = 0; video.fullscreen_modes[i].width != -1; i++)
+ {
+ TreeInfo *ti = newTreeInfo_setDefaults(TREE_TYPE_UNDEFINED);
+ char identifier[32], name[32];
+ int x = video.fullscreen_modes[i].width;
+ int y = video.fullscreen_modes[i].height;
+ int xx, yy;
+
+ get_aspect_ratio_from_screen_mode(&video.fullscreen_modes[i], &xx, &yy);
+
+ ti->node_top = &screen_modes;
+ ti->sort_priority = x * 10000 + y;
+
+ sprintf(identifier, "%dx%d", x, y);
+ sprintf(name, "%d x %d [%d:%d]", x, y, xx, yy);
+
+ setString(&ti->identifier, identifier);
+ setString(&ti->name, name);
+ setString(&ti->name_sorting, name);
+ setString(&ti->infotext, "Fullscreen Mode");
+
+ pushTreeInfo(&screen_modes, ti);
+ }
+
+ /* sort fullscreen modes to start with lowest available screen resolution */
+ sortTreeInfo(&screen_modes);
+
+ /* set current screen mode for fullscreen mode to configured setup value */
+ screen_mode_current = getTreeInfoFromIdentifier(screen_modes,
+ setup.fullscreen_mode);
+
+ /* if that fails, set current screen mode to reliable default value */
+ if (screen_mode_current == NULL)
+ screen_mode_current = getTreeInfoFromIdentifier(screen_modes,
+ DEFAULT_FULLSCREEN_MODE);
+
+ /* if that also fails, set current screen mode to first available mode */
+ if (screen_mode_current == NULL)
+ screen_mode_current = screen_modes;
+
+ if (screen_mode_current == NULL)
+ video.fullscreen_available = FALSE;
+ }
+
+ if (video.fullscreen_available)
+ {
+ setup.fullscreen_mode = screen_mode_current->identifier;
+
+ /* needed for displaying screen mode name instead of identifier */
+ screen_mode_text = screen_mode_current->name;
+ }
+
+ setup_mode = SETUP_MODE_GRAPHICS;
+ DrawSetupScreen();
+}
+
+static void execSetupChooseScreenMode()
+{
+ if (!video.fullscreen_available)
+ return;
+
+ setup_mode = SETUP_MODE_CHOOSE_SCREEN_MODE;
+ DrawSetupScreen();
+}
+
+static void execSetupSound()
+{
+ setup_mode = SETUP_MODE_SOUND;
+ DrawSetupScreen();
+}
+
+static void execSetupArtwork()
+{
+ setup.graphics_set = artwork.gfx_current->identifier;
+ setup.sounds_set = artwork.snd_current->identifier;
+ setup.music_set = artwork.mus_current->identifier;
+
+ /* needed if last screen (setup choice) changed graphics, sounds or music */
+ ReloadCustomArtwork(0);
+
+ /* 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 execSetupShortcut1()
+{
+ setup_mode = SETUP_MODE_SHORTCUT_1;
+ DrawSetupScreen();
+}
+
+static void execSetupShortcut2()
+{
+ setup_mode = SETUP_MODE_SHORTCUT_2;
+ DrawSetupScreen();
+}
+
+static void execExitSetup()
+{
+ game_status = GAME_MODE_MAIN;
+ DrawMainMenu();
+}
+
+static void execSaveAndExitSetup()
+{
+ SaveSetup();
+ execExitSetup();
+}
+
+static struct TokenInfo setup_info_main[] =
+{
+ { TYPE_ENTER_MENU, execSetupGame, "Game & Menu" },
+ { TYPE_ENTER_MENU, execSetupEditor, "Editor" },
+ { 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, execSetupShortcut1, "Key Shortcuts 1" },
+ { TYPE_ENTER_MENU, execSetupShortcut2, "Key Shortcuts 2" },
+ { 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 (Multi-Player):" },
+ { TYPE_YES_NO, &setup.input_on_focus, "Only Move Focussed Player:" },
+ { TYPE_SWITCH, &setup.handicap, "Handicap:" },
+ { TYPE_SWITCH, &setup.skip_levels, "Skip Unsolved Levels:" },
+ { TYPE_SWITCH, &setup.time_limit, "Time Limit:" },
+ { TYPE_SWITCH, &setup.autorecord, "Auto-Record Tapes:" },
+ { TYPE_EMPTY, NULL, "" },
+ { TYPE_LEAVE_MENU, execSetupMain, "Back" },
+
+ { 0, NULL, NULL }
+};
+
+static struct TokenInfo setup_info_editor[] =
+{
+#if 0
+ { TYPE_SWITCH, &setup.editor.el_boulderdash, "Boulder Dash:" },
+ { TYPE_SWITCH, &setup.editor.el_emerald_mine, "Emerald Mine:" },
+ { TYPE_SWITCH, &setup.editor.el_emerald_mine_club, "Emerald Mine Club:" },
+ { TYPE_SWITCH, &setup.editor.el_more, "Rocks'n'Diamonds:" },
+ { TYPE_SWITCH, &setup.editor.el_sokoban, "Sokoban:" },
+ { TYPE_SWITCH, &setup.editor.el_supaplex, "Supaplex:" },
+ { TYPE_SWITCH, &setup.editor.el_diamond_caves, "Diamond Caves II:" },
+ { TYPE_SWITCH, &setup.editor.el_dx_boulderdash,"DX-Boulderdash:" },
+#endif
+ { TYPE_SWITCH, &setup.editor.el_chars, "Text Characters:" },
+ { TYPE_SWITCH, &setup.editor.el_custom, "Custom & Group Elements:" },
+#if 0
+ { TYPE_SWITCH, &setup.editor.el_headlines, "Headlines:" },
+#endif
+ { TYPE_SWITCH, &setup.editor.el_user_defined, "User defined element list:" },
+ { TYPE_SWITCH, &setup.editor.el_dynamic, "Dynamic level elements:" },
+ { TYPE_EMPTY, NULL, "" },
+#if 0
+ { TYPE_SWITCH, &setup.editor.el_by_game, "Show elements by game:" },
+ { TYPE_SWITCH, &setup.editor.el_by_type, "Show elements by type:" },
+ { TYPE_EMPTY, NULL, "" },
+#endif
+ { TYPE_SWITCH, &setup.editor.show_element_token, "Show element token:" },
+ { TYPE_EMPTY, NULL, "" },
+ { TYPE_LEAVE_MENU, execSetupMain, "Back" },
+
+ { 0, NULL, NULL }
+};
+
+static struct TokenInfo setup_info_graphics[] =
+{
+ { TYPE_SWITCH, &setup.fullscreen, "Fullscreen:" },
+ { TYPE_ENTER_LIST, execSetupChooseScreenMode, "Fullscreen Mode:" },
+ { TYPE_STRING, &screen_mode_text, "" },
+ { TYPE_SWITCH, &setup.scroll_delay, "Delayed Scrolling:" },
+#if 0
+ { TYPE_SWITCH, &setup.soft_scrolling, "Soft Scrolling:" },
+ { TYPE_SWITCH, &setup.double_buffering,"Double-Buffering:" },
+#endif
+ { TYPE_SWITCH, &setup.fade_screens, "Fade Screens:" },
+ { TYPE_SWITCH, &setup.quick_switch, "Quick Player Focus Switch:" },
+ { TYPE_SWITCH, &setup.quick_doors, "Quick Menu Doors:" },
+ { TYPE_SWITCH, &setup.show_titlescreen,"Show Title Screens:" },
+ { TYPE_SWITCH, &setup.toons, "Show Toons:" },
+ { TYPE_ECS_AGA, &setup.prefer_aga_graphics,"EMC graphics preference:" },
+ { TYPE_EMPTY, NULL, "" },
+ { TYPE_LEAVE_MENU, execSetupMain, "Back" },
+
+ { 0, NULL, NULL }
+};
+
+static struct TokenInfo setup_info_sound[] =
+{
+ { TYPE_SWITCH, &setup.sound_simple, "Sound Effects (Normal):" },
+ { TYPE_SWITCH, &setup.sound_loops, "Sound Effects (Looping):" },
+ { TYPE_SWITCH, &setup.sound_music, "Music:" },
+ { TYPE_EMPTY, NULL, "" },
+ { TYPE_LEAVE_MENU, execSetupMain, "Back" },
+
+ { 0, NULL, NULL }
+};
+
+static struct TokenInfo setup_info_artwork[] =
+{
+ { TYPE_ENTER_LIST, execSetupChooseGraphics,"Custom Graphics:" },
+ { TYPE_STRING, &graphics_set_name, "" },
+ { TYPE_ENTER_LIST, execSetupChooseSounds, "Custom Sounds:" },
+ { TYPE_STRING, &sounds_set_name, "" },
+ { TYPE_ENTER_LIST, execSetupChooseMusic, "Custom Music:" },
+ { TYPE_STRING, &music_set_name, "" },
+ { TYPE_EMPTY, NULL, "" },
+#if 1
+ { TYPE_YES_NO, &setup.override_level_graphics,"Override Level Graphics:" },
+ { TYPE_YES_NO, &setup.override_level_sounds, "Override Level Sounds:" },
+ { TYPE_YES_NO, &setup.override_level_music, "Override Level Music:" },
+#else
+ { 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:" },
+#endif
+ { TYPE_EMPTY, NULL, "" },
+ { TYPE_LEAVE_MENU, execSetupMain, "Back" },
+
+ { 0, NULL, NULL }
+};
+
+static struct TokenInfo setup_info_input[] =
+{
+ { TYPE_SWITCH, NULL, "Player:" },
+ { TYPE_SWITCH, NULL, "Device:" },
+ { TYPE_ENTER_MENU, NULL, "" },
+ { TYPE_EMPTY, NULL, "" },
+ { TYPE_EMPTY, NULL, "" },
+ { TYPE_EMPTY, NULL, "" },
+ { TYPE_EMPTY, NULL, "" },
+ { TYPE_EMPTY, NULL, "" },
+ { TYPE_EMPTY, NULL, "" },
+ { TYPE_EMPTY, NULL, "" },
+ { TYPE_EMPTY, NULL, "" },
+ { TYPE_EMPTY, NULL, "" },
+ { TYPE_EMPTY, NULL, "" },
+ { TYPE_LEAVE_MENU, execSetupMain, "Back" },
+
+ { 0, NULL, NULL }
+};
+
+static struct TokenInfo setup_info_shortcut_1[] =
+{
+ { TYPE_KEYTEXT, NULL, "Quick Save Game to Tape:", },
+ { TYPE_KEY, &setup.shortcut.save_game, "" },
+ { TYPE_KEYTEXT, NULL, "Quick Load Game from Tape:", },
+ { TYPE_KEY, &setup.shortcut.load_game, "" },
+ { TYPE_KEYTEXT, NULL, "Start Game & Toggle Pause:", },
+ { TYPE_KEY, &setup.shortcut.toggle_pause, "" },
+ { TYPE_EMPTY, NULL, "" },
+ { TYPE_YES_NO, &setup.ask_on_escape, "Ask on 'Esc' Key:" },
+ { TYPE_YES_NO, &setup.ask_on_escape_editor, "Ask on 'Esc' Key (Editor):" },
+ { TYPE_EMPTY, NULL, "" },
+ { TYPE_LEAVE_MENU, execSetupMain, "Back" },
+
+ { 0, NULL, NULL }
+};
+
+static struct TokenInfo setup_info_shortcut_2[] =
+{
+ { TYPE_KEYTEXT, NULL, "Set Focus to Player 1:", },
+ { TYPE_KEY, &setup.shortcut.focus_player[0], "" },
+ { TYPE_KEYTEXT, NULL, "Set Focus to Player 2:", },
+ { TYPE_KEY, &setup.shortcut.focus_player[1], "" },
+ { TYPE_KEYTEXT, NULL, "Set Focus to Player 3:", },
+ { TYPE_KEY, &setup.shortcut.focus_player[2], "" },
+ { TYPE_KEYTEXT, NULL, "Set Focus to Player 4:", },
+ { TYPE_KEY, &setup.shortcut.focus_player[3], "" },
+ { TYPE_KEYTEXT, NULL, "Set Focus to All Players:", },
+ { TYPE_KEY, &setup.shortcut.focus_player_all, "" },
+ { 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;
+ }
+ }
+
+ DoAnimation();
+ BackToFront();
+
+ /* don't eat all CPU time */
+ Delay(10);
+ }
+
+ return key;
+}
+
+static int getSetupTextFont(int type)
+{
+ if (type & (TYPE_SWITCH |
+ TYPE_YES_NO |
+ TYPE_STRING |
+ TYPE_ECS_AGA |
+ TYPE_KEYTEXT |
+ TYPE_ENTER_LIST))
+ return FONT_MENU_2;
+ else
+ return FONT_MENU_1;
+}
+
+static int getSetupValueFont(int type, void *value)
+{
+ if (type & TYPE_KEY)
+ return (type & TYPE_QUERY ? FONT_INPUT_1_ACTIVE : FONT_VALUE_1);
+ else if (type & TYPE_STRING)
+ return FONT_VALUE_2;
+ else if (type & TYPE_ECS_AGA)
+ return FONT_VALUE_1;
+ else if (type & TYPE_BOOLEAN_STYLE)
+ return (*(boolean *)value ? FONT_OPTION_ON : FONT_OPTION_OFF);
+ else
+ return FONT_VALUE_1;
+}
+
+static void drawSetupValue(int pos)
+{
+ boolean font_draw_xoffset_modified = FALSE;
+ int font_draw_xoffset_old = -1;
+ int xpos = MENU_SCREEN_VALUE_XPOS;
+ int ypos = MENU_SCREEN_START_YPOS + pos;
+ int startx = mSX + xpos * 32;
+ int starty = mSY + ypos * 32;
+ int font_nr, font_width;
+ int type = setup_info[pos].type;
+ void *value = setup_info[pos].value;
+ char *value_string = getSetupValue(type, value);
+ int i;
+
+ if (value_string == NULL)
+ return;
+
+ if (type & TYPE_KEY)
+ {
+ xpos = MENU_SCREEN_START_XPOS;
+
+ if (type & TYPE_QUERY)
+ {
+ value_string = "<press key>";
+ }
+ }
+ else if (type & TYPE_STRING)
+ {
+ int max_value_len = (SCR_FIELDX - 2) * 2;
+
+ xpos = MENU_SCREEN_START_XPOS;
+
+ if (strlen(value_string) > max_value_len)
+ value_string[max_value_len] = '\0';
+ }
+
+ startx = mSX + xpos * 32;
+ starty = mSY + ypos * 32;
+ font_nr = getSetupValueFont(type, value);
+ font_width = getFontWidth(font_nr);
+
+ /* downward compatibility correction for Juergen Bonhagen's menu settings */
+ if (setup_mode != SETUP_MODE_INPUT)
+ {
+ int check_font_nr = FONT_OPTION_ON; /* known font that needs correction */
+ int font1_xoffset = getFontBitmapInfo(font_nr)->draw_xoffset;
+ int font2_xoffset = getFontBitmapInfo(check_font_nr)->draw_xoffset;
+ int text_startx = mSX + MENU_SCREEN_START_XPOS * 32;
+ int text_font_nr = getSetupTextFont(FONT_MENU_2);
+ int text_font_xoffset = getFontBitmapInfo(text_font_nr)->draw_xoffset;
+ int text_width = MAX_MENU_TEXT_LENGTH_MEDIUM * getFontWidth(text_font_nr);
+ boolean correct_font_draw_xoffset = FALSE;
+
+ if (xpos == MENU_SCREEN_START_XPOS &&
+ startx + font1_xoffset < text_startx + text_font_xoffset)
+ correct_font_draw_xoffset = TRUE;
+
+ if (xpos == MENU_SCREEN_VALUE_XPOS &&
+ startx + font2_xoffset < text_startx + text_width + text_font_xoffset)
+ correct_font_draw_xoffset = TRUE;
+
+ /* check if setup value would overlap with setup text when printed */
+ /* (this can happen for extreme/wrong values for font draw offset) */
+ if (correct_font_draw_xoffset)
+ {
+ font_draw_xoffset_old = getFontBitmapInfo(font_nr)->draw_xoffset;
+ font_draw_xoffset_modified = TRUE;
+
+ if (type & TYPE_KEY)
+ getFontBitmapInfo(font_nr)->draw_xoffset += 2 * getFontWidth(font_nr);
+ else if (!(type & TYPE_STRING))
+ getFontBitmapInfo(font_nr)->draw_xoffset = text_font_xoffset + 20 -
+ MAX_MENU_TEXT_LENGTH_MEDIUM * (16 - getFontWidth(text_font_nr));
+ }
+ }
+
+ for (i = 0; i <= MENU_SCREEN_MAX_XPOS - xpos; i++)
+ DrawText(startx + i * font_width, starty, " ", font_nr);