+ global.convert_leveldir = str_copy;
+ global.convert_level_nr = -1;
+
+ if (str_ptr != NULL) /* level number follows */
+ {
+ *str_ptr++ = '\0'; /* terminate leveldir string */
+ global.convert_level_nr = atoi(str_ptr); /* get level_nr value */
+ }
+ }
+ else if (strncmp(command, "create images ", 14) == 0)
+ {
+#if defined(TARGET_SDL)
+ global.create_images_dir = getStringCopy(&command[14]);
+
+ if (access(global.create_images_dir, W_OK) != 0)
+ Error(ERR_EXIT, "image target directory '%s' not found or not writable",
+ global.create_images_dir);
+#else
+ Error(ERR_EXIT, "command only available for SDL target");
+#endif
+ }
+
+#if DEBUG
+#if defined(TARGET_SDL)
+ else if (strEqual(command, "SDL_ListModes"))
+ {
+ SDL_Rect **modes;
+ int i;
+
+ SDL_Init(SDL_INIT_VIDEO);
+
+ /* get available fullscreen/hardware modes */
+ modes = SDL_ListModes(NULL, SDL_FULLSCREEN | SDL_HWSURFACE);
+
+ /* check if there are any modes available */
+ if (modes == NULL)
+ {
+ printf("No modes available!\n");
+
+ exit(-1);
+ }
+
+ /* check if our resolution is restricted */
+ if (modes == (SDL_Rect **)-1)
+ {
+ printf("All resolutions available.\n");
+ }
+ else
+ {
+ printf("Available Modes:\n");
+
+ for(i = 0; modes[i]; i++)
+ printf(" %d x %d\n", modes[i]->w, modes[i]->h);
+ }
+
+ exit(0);
+ }
+#endif
+#endif
+
+ else
+ {
+ Error(ERR_EXIT_HELP, "unrecognized command '%s'", command);
+ }
+}
+
+static void InitSetup()
+{
+ LoadSetup(); /* global setup info */
+
+ /* set some options from setup file */
+
+ if (setup.options.verbose)
+ options.verbose = TRUE;
+}
+
+static void InitGameInfo()
+{
+ game.restart_level = FALSE;
+}
+
+static void InitPlayerInfo()
+{
+ int i;
+
+ /* choose default local player */
+ local_player = &stored_player[0];
+
+ for (i = 0; i < MAX_PLAYERS; i++)
+ stored_player[i].connected = FALSE;
+
+ local_player->connected = TRUE;
+}
+
+static void InitArtworkInfo()
+{
+ LoadArtworkInfo();
+}
+
+static char *get_string_in_brackets(char *string)
+{
+ char *string_in_brackets = checked_malloc(strlen(string) + 3);
+
+ sprintf(string_in_brackets, "[%s]", string);
+
+ return string_in_brackets;
+}
+
+static char *get_level_id_suffix(int id_nr)
+{
+ char *id_suffix = checked_malloc(1 + 3 + 1);
+
+ if (id_nr < 0 || id_nr > 999)
+ id_nr = 0;
+
+ sprintf(id_suffix, ".%03d", id_nr);
+
+ return id_suffix;
+}
+
+#if 0
+static char *get_element_class_token(int element)
+{
+ char *element_class_name = element_info[element].class_name;
+ char *element_class_token = checked_malloc(strlen(element_class_name) + 3);
+
+ sprintf(element_class_token, "[%s]", element_class_name);
+
+ return element_class_token;
+}
+
+static char *get_action_class_token(int action)
+{
+ char *action_class_name = &element_action_info[action].suffix[1];
+ char *action_class_token = checked_malloc(strlen(action_class_name) + 3);
+
+ sprintf(action_class_token, "[%s]", action_class_name);
+
+ return action_class_token;
+}
+#endif
+
+static void InitArtworkConfig()
+{
+ static char *image_id_prefix[MAX_NUM_ELEMENTS + NUM_FONTS + 1];
+ static char *sound_id_prefix[2 * MAX_NUM_ELEMENTS + 1];
+ static char *music_id_prefix[NUM_MUSIC_PREFIXES + 1];
+ static char *action_id_suffix[NUM_ACTIONS + 1];
+ static char *direction_id_suffix[NUM_DIRECTIONS_FULL + 1];
+ static char *special_id_suffix[NUM_SPECIAL_GFX_ARGS + 1];
+ static char *level_id_suffix[MAX_LEVELS + 1];
+ static char *dummy[1] = { NULL };
+ static char *ignore_generic_tokens[] =
+ {
+ "name",
+ "sort_priority",
+ NULL
+ };
+ static char **ignore_image_tokens;
+ static char **ignore_sound_tokens;
+ static char **ignore_music_tokens;
+ int num_ignore_generic_tokens;
+ int num_ignore_image_tokens;
+ int num_ignore_sound_tokens;
+ int num_ignore_music_tokens;
+ int i;
+
+ /* dynamically determine list of generic tokens to be ignored */
+ num_ignore_generic_tokens = 0;
+ for (i = 0; ignore_generic_tokens[i] != NULL; i++)
+ num_ignore_generic_tokens++;
+
+ /* dynamically determine list of image tokens to be ignored */
+ num_ignore_image_tokens = num_ignore_generic_tokens;
+ for (i = 0; image_config_vars[i].token != NULL; i++)
+ num_ignore_image_tokens++;
+ ignore_image_tokens =
+ checked_malloc((num_ignore_image_tokens + 1) * sizeof(char *));
+ for (i = 0; i < num_ignore_generic_tokens; i++)
+ ignore_image_tokens[i] = ignore_generic_tokens[i];
+ for (i = 0; i < num_ignore_image_tokens - num_ignore_generic_tokens; i++)
+ ignore_image_tokens[num_ignore_generic_tokens + i] =
+ image_config_vars[i].token;
+ ignore_image_tokens[num_ignore_image_tokens] = NULL;
+
+ /* dynamically determine list of sound tokens to be ignored */
+ num_ignore_sound_tokens = num_ignore_generic_tokens;
+ ignore_sound_tokens =
+ checked_malloc((num_ignore_sound_tokens + 1) * sizeof(char *));
+ for (i = 0; i < num_ignore_generic_tokens; i++)
+ ignore_sound_tokens[i] = ignore_generic_tokens[i];
+ ignore_sound_tokens[num_ignore_sound_tokens] = NULL;
+
+ /* dynamically determine list of music tokens to be ignored */
+ num_ignore_music_tokens = num_ignore_generic_tokens;
+ ignore_music_tokens =
+ checked_malloc((num_ignore_music_tokens + 1) * sizeof(char *));
+ for (i = 0; i < num_ignore_generic_tokens; i++)
+ ignore_music_tokens[i] = ignore_generic_tokens[i];
+ ignore_music_tokens[num_ignore_music_tokens] = NULL;
+
+ for (i = 0; i < MAX_NUM_ELEMENTS; i++)
+ image_id_prefix[i] = element_info[i].token_name;
+ for (i = 0; i < NUM_FONTS; i++)
+ image_id_prefix[MAX_NUM_ELEMENTS + i] = font_info[i].token_name;
+ image_id_prefix[MAX_NUM_ELEMENTS + NUM_FONTS] = NULL;
+
+ for (i = 0; i < MAX_NUM_ELEMENTS; i++)
+ sound_id_prefix[i] = element_info[i].token_name;
+ for (i = 0; i < MAX_NUM_ELEMENTS; i++)
+ sound_id_prefix[MAX_NUM_ELEMENTS + i] =
+ get_string_in_brackets(element_info[i].class_name);
+ sound_id_prefix[2 * MAX_NUM_ELEMENTS] = NULL;
+
+ for (i = 0; i < NUM_MUSIC_PREFIXES; i++)
+ music_id_prefix[i] = music_prefix_info[i].prefix;
+ music_id_prefix[NUM_MUSIC_PREFIXES] = NULL;
+
+ for (i = 0; i < NUM_ACTIONS; i++)
+ action_id_suffix[i] = element_action_info[i].suffix;
+ action_id_suffix[NUM_ACTIONS] = NULL;
+
+ for (i = 0; i < NUM_DIRECTIONS_FULL; i++)
+ direction_id_suffix[i] = element_direction_info[i].suffix;
+ direction_id_suffix[NUM_DIRECTIONS_FULL] = NULL;
+
+ for (i = 0; i < NUM_SPECIAL_GFX_ARGS; i++)
+ special_id_suffix[i] = special_suffix_info[i].suffix;
+ special_id_suffix[NUM_SPECIAL_GFX_ARGS] = NULL;
+
+ for (i = 0; i < MAX_LEVELS; i++)
+ level_id_suffix[i] = get_level_id_suffix(i);
+ level_id_suffix[MAX_LEVELS] = NULL;
+
+ InitImageList(image_config, NUM_IMAGE_FILES, image_config_suffix,
+ image_id_prefix, action_id_suffix, direction_id_suffix,
+ special_id_suffix, ignore_image_tokens);
+ InitSoundList(sound_config, NUM_SOUND_FILES, sound_config_suffix,
+ sound_id_prefix, action_id_suffix, dummy,
+ special_id_suffix, ignore_sound_tokens);
+ InitMusicList(music_config, NUM_MUSIC_FILES, music_config_suffix,
+ music_id_prefix, special_id_suffix, level_id_suffix,
+ dummy, ignore_music_tokens);
+}
+
+static void InitMixer()
+{
+ OpenAudio();
+
+ StartMixer();
+}
+
+void InitGfx()
+{
+ struct GraphicInfo *graphic_info_last = graphic_info;
+ char *filename_font_initial = NULL;
+ char *filename_anim_initial = NULL;
+ Bitmap *bitmap_font_initial = NULL;
+ int font_height;
+ int i, j;
+
+ /* determine settings for initial font (for displaying startup messages) */
+ for (i = 0; image_config[i].token != NULL; i++)
+ {
+ for (j = 0; j < NUM_INITIAL_FONTS; j++)
+ {
+ char font_token[128];
+ int len_font_token;
+
+ sprintf(font_token, "%s_%d", CONFIG_TOKEN_FONT_INITIAL, j + 1);
+ len_font_token = strlen(font_token);
+
+ if (strEqual(image_config[i].token, font_token))
+ filename_font_initial = image_config[i].value;
+ else if (strlen(image_config[i].token) > len_font_token &&
+ strncmp(image_config[i].token, font_token, len_font_token) == 0)
+ {
+ if (strEqual(&image_config[i].token[len_font_token], ".x"))
+ font_initial[j].src_x = atoi(image_config[i].value);
+ else if (strEqual(&image_config[i].token[len_font_token], ".y"))
+ font_initial[j].src_y = atoi(image_config[i].value);
+ else if (strEqual(&image_config[i].token[len_font_token], ".width"))
+ font_initial[j].width = atoi(image_config[i].value);
+ else if (strEqual(&image_config[i].token[len_font_token], ".height"))
+ font_initial[j].height = atoi(image_config[i].value);
+ }
+ }
+ }
+
+ for (j = 0; j < NUM_INITIAL_FONTS; j++)
+ {
+ font_initial[j].num_chars = DEFAULT_NUM_CHARS_PER_FONT;
+ font_initial[j].num_chars_per_line = DEFAULT_NUM_CHARS_PER_LINE;
+ }
+
+ if (filename_font_initial == NULL) /* should not happen */
+ Error(ERR_EXIT, "cannot get filename for '%s'", CONFIG_TOKEN_FONT_INITIAL);
+
+ /* create additional image buffers for double-buffering and cross-fading */
+ bitmap_db_cross = CreateBitmap(WIN_XSIZE, WIN_YSIZE, DEFAULT_DEPTH);
+ bitmap_db_field = CreateBitmap(FXSIZE, FYSIZE, DEFAULT_DEPTH);
+ bitmap_db_panel = CreateBitmap(DXSIZE, DYSIZE, DEFAULT_DEPTH);
+ bitmap_db_door = CreateBitmap(3 * DXSIZE, DYSIZE + VYSIZE, DEFAULT_DEPTH);
+ bitmap_db_toons = CreateBitmap(FULL_SXSIZE, FULL_SYSIZE, DEFAULT_DEPTH);
+
+ /* initialize screen properties */
+ InitGfxFieldInfo(SX, SY, SXSIZE, SYSIZE,
+ REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE,
+ bitmap_db_field);
+ InitGfxDoor1Info(DX, DY, DXSIZE, DYSIZE);
+ InitGfxDoor2Info(VX, VY, VXSIZE, VYSIZE);
+ InitGfxScrollbufferInfo(FXSIZE, FYSIZE);
+ InitGfxCustomArtworkInfo();
+
+ bitmap_font_initial = LoadCustomImage(filename_font_initial);
+
+ for (j = 0; j < NUM_INITIAL_FONTS; j++)
+ font_initial[j].bitmap = bitmap_font_initial;
+
+ InitFontGraphicInfo();
+
+ font_height = getFontHeight(FC_RED);
+
+#if 1
+ DrawInitText(getWindowTitleString(), 20, FC_YELLOW);
+#else
+ DrawInitText(getProgramInitString(), 20, FC_YELLOW);
+#endif
+ DrawInitText(PROGRAM_COPYRIGHT_STRING, 50, FC_RED);
+ DrawInitText(PROGRAM_WEBSITE_STRING, WIN_YSIZE - 20 - font_height, FC_RED);
+
+ DrawInitText("Loading graphics", 120, FC_GREEN);
+
+#if 1
+#if 1
+ /* initialize busy animation with default values */
+ int parameter[NUM_GFX_ARGS];
+ for (i = 0; i < NUM_GFX_ARGS; i++)
+ parameter[i] = get_graphic_parameter_value(image_config_suffix[i].value,
+ image_config_suffix[i].token,
+ image_config_suffix[i].type);
+#if 0
+ for (i = 0; i < NUM_GFX_ARGS; i++)
+ printf("::: '%s' => %d\n", image_config_suffix[i].token, parameter[i]);
+#endif
+#endif
+
+ /* determine settings for busy animation (when displaying startup messages) */
+ for (i = 0; image_config[i].token != NULL; i++)
+ {
+ char *anim_token = CONFIG_TOKEN_GLOBAL_BUSY;
+ int len_anim_token = strlen(anim_token);
+
+ if (strEqual(image_config[i].token, anim_token))
+ filename_anim_initial = image_config[i].value;
+ else if (strlen(image_config[i].token) > len_anim_token &&
+ strncmp(image_config[i].token, anim_token, len_anim_token) == 0)
+ {
+#if 1
+ for (j = 0; image_config_suffix[j].token != NULL; j++)
+ {
+ if (strEqual(&image_config[i].token[len_anim_token],
+ image_config_suffix[j].token))
+ parameter[j] =
+ get_graphic_parameter_value(image_config[i].value,
+ image_config_suffix[j].token,
+ image_config_suffix[j].type);
+ }
+#else
+ if (strEqual(&image_config[i].token[len_anim_token], ".x"))
+ anim_initial.src_x = atoi(image_config[i].value);
+ else if (strEqual(&image_config[i].token[len_anim_token], ".y"))
+ anim_initial.src_y = atoi(image_config[i].value);
+ else if (strEqual(&image_config[i].token[len_anim_token], ".width"))
+ anim_initial.width = atoi(image_config[i].value);
+ else if (strEqual(&image_config[i].token[len_anim_token], ".height"))
+ anim_initial.height = atoi(image_config[i].value);
+ else if (strEqual(&image_config[i].token[len_anim_token], ".frames"))
+ anim_initial.anim_frames = atoi(image_config[i].value);
+ else if (strEqual(&image_config[i].token[len_anim_token],
+ ".frames_per_line"))
+ anim_initial.anim_frames_per_line = atoi(image_config[i].value);
+ else if (strEqual(&image_config[i].token[len_anim_token], ".delay"))
+ anim_initial.anim_delay = atoi(image_config[i].value);
+#endif
+ }
+ }
+
+#if defined(CREATE_SPECIAL_EDITION_RND_JUE)
+ filename_anim_initial = "loading.pcx";
+
+ parameter[GFX_ARG_X] = 0;
+ parameter[GFX_ARG_Y] = 0;
+ parameter[GFX_ARG_WIDTH] = 128;
+ parameter[GFX_ARG_HEIGHT] = 40;
+ parameter[GFX_ARG_FRAMES] = 32;
+ parameter[GFX_ARG_DELAY] = 4;
+ parameter[GFX_ARG_FRAMES_PER_LINE] = ARG_UNDEFINED_VALUE;
+#endif
+
+ if (filename_anim_initial == NULL) /* should not happen */
+ Error(ERR_EXIT, "cannot get filename for '%s'", CONFIG_TOKEN_GLOBAL_BUSY);
+
+ anim_initial.bitmap = LoadCustomImage(filename_anim_initial);
+
+ graphic_info = &anim_initial; /* graphic == 0 => anim_initial */
+
+ set_graphic_parameters_ext(0, parameter, anim_initial.bitmap);
+
+#if 0
+ printf("::: INIT_GFX: anim_frames_per_line == %d [%d / %d] [%d, %d]\n",
+ graphic_info[0].anim_frames_per_line,
+ get_scaled_graphic_width(0),
+ graphic_info[0].width,
+ getOriginalImageWidthFromImageID(0),
+ graphic_info[0].scale_up_factor);
+#endif
+
+ graphic_info = graphic_info_last;
+
+ init.busy.width = anim_initial.width;
+ init.busy.height = anim_initial.height;
+
+ InitMenuDesignSettings_Static();
+ InitGfxDrawBusyAnimFunction(DrawInitAnim);
+#endif
+}
+
+void RedrawBackground()
+{
+ BlitBitmap(graphic_info[IMG_GLOBAL_BORDER].bitmap, backbuffer,
+ 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
+
+ redraw_mask = REDRAW_ALL;
+}
+
+void InitGfxBackground()
+{
+ int x, y;
+
+ fieldbuffer = bitmap_db_field;
+ SetDrawtoField(DRAW_BACKBUFFER);
+
+#if 1
+ ClearRectangle(backbuffer, 0, 0, WIN_XSIZE, WIN_YSIZE);
+#else
+ RedrawBackground();
+
+ ClearRectangle(backbuffer, REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE);
+ ClearRectangle(bitmap_db_door, 0, 0, 3 * DXSIZE, DYSIZE + VYSIZE);
+#endif
+
+ for (x = 0; x < MAX_BUF_XSIZE; x++)
+ for (y = 0; y < MAX_BUF_YSIZE; y++)
+ redraw[x][y] = 0;
+ redraw_tiles = 0;
+ redraw_mask = REDRAW_ALL;
+}
+
+static void InitLevelInfo()
+{
+ LoadLevelInfo(); /* global level info */
+ LoadLevelSetup_LastSeries(); /* last played series info */
+ LoadLevelSetup_SeriesInfo(); /* last played level info */
+}
+
+static void InitLevelArtworkInfo()
+{
+ LoadLevelArtworkInfo();
+}
+
+static void InitImages()
+{
+ print_timestamp_init("InitImages");
+
+#if 0
+ printf("::: leveldir_current->identifier == '%s'\n",
+ leveldir_current == NULL ? "[NULL]" : leveldir_current->identifier);
+ printf("::: leveldir_current->graphics_path == '%s'\n",
+ leveldir_current == NULL ? "[NULL]" : leveldir_current->graphics_path);
+ printf("::: leveldir_current->graphics_set == '%s'\n",
+ leveldir_current == NULL ? "[NULL]" : leveldir_current->graphics_set);
+ printf("::: getLevelArtworkSet(ARTWORK_TYPE_GRAPHICS) == '%s'\n",
+ leveldir_current == NULL ? "[NULL]" : LEVELDIR_ARTWORK_SET(leveldir_current, ARTWORK_TYPE_GRAPHICS));
+#endif
+
+ setLevelArtworkDir(artwork.gfx_first);
+
+#if 0
+ printf("::: leveldir_current->identifier == '%s'\n",
+ leveldir_current == NULL ? "[NULL]" : leveldir_current->identifier);
+ printf("::: leveldir_current->graphics_path == '%s'\n",
+ leveldir_current == NULL ? "[NULL]" : leveldir_current->graphics_path);
+ printf("::: leveldir_current->graphics_set == '%s'\n",
+ leveldir_current == NULL ? "[NULL]" : leveldir_current->graphics_set);
+ printf("::: getLevelArtworkSet(ARTWORK_TYPE_GRAPHICS) == '%s'\n",
+ leveldir_current == NULL ? "[NULL]" : LEVELDIR_ARTWORK_SET(leveldir_current, ARTWORK_TYPE_GRAPHICS));
+#endif
+
+#if 0
+ printf("::: InitImages for '%s' ['%s', '%s'] ['%s', '%s']\n",
+ leveldir_current->identifier,
+ artwork.gfx_current_identifier,
+ artwork.gfx_current->identifier,
+ leveldir_current->graphics_set,
+ leveldir_current->graphics_path);
+#endif
+
+ UPDATE_BUSY_STATE();
+
+ ReloadCustomImages();
+ print_timestamp_time("ReloadCustomImages");
+
+ UPDATE_BUSY_STATE();
+
+ LoadCustomElementDescriptions();
+ print_timestamp_time("LoadCustomElementDescriptions");
+
+ UPDATE_BUSY_STATE();
+
+ LoadMenuDesignSettings();
+ print_timestamp_time("LoadMenuDesignSettings");
+
+ UPDATE_BUSY_STATE();
+
+ ReinitializeGraphics();
+ print_timestamp_time("ReinitializeGraphics");
+
+ UPDATE_BUSY_STATE();
+
+ print_timestamp_done("InitImages");
+}
+
+static void InitSound(char *identifier)
+{
+ print_timestamp_init("InitSound");
+
+ if (identifier == NULL)
+ identifier = artwork.snd_current->identifier;
+
+ /* set artwork path to send it to the sound server process */
+ setLevelArtworkDir(artwork.snd_first);
+
+ InitReloadCustomSounds(identifier);
+ print_timestamp_time("InitReloadCustomSounds");
+
+ ReinitializeSounds();
+ print_timestamp_time("ReinitializeSounds");
+
+ print_timestamp_done("InitSound");
+}
+
+static void InitMusic(char *identifier)
+{
+ print_timestamp_init("InitMusic");
+
+ if (identifier == NULL)
+ identifier = artwork.mus_current->identifier;
+
+ /* set artwork path to send it to the sound server process */
+ setLevelArtworkDir(artwork.mus_first);
+
+ InitReloadCustomMusic(identifier);
+ print_timestamp_time("InitReloadCustomMusic");
+
+ ReinitializeMusic();
+ print_timestamp_time("ReinitializeMusic");
+
+ print_timestamp_done("InitMusic");
+}
+
+void InitNetworkServer()
+{
+#if defined(NETWORK_AVALIABLE)
+ int nr_wanted;
+#endif
+
+ if (!options.network)
+ return;
+
+#if defined(NETWORK_AVALIABLE)
+ nr_wanted = Request("Choose player", REQ_PLAYER | REQ_STAY_CLOSED);
+
+ if (!ConnectToServer(options.server_host, options.server_port))
+ Error(ERR_EXIT, "cannot connect to network game server");
+
+ SendToServer_PlayerName(setup.player_name);
+ SendToServer_ProtocolVersion();
+
+ if (nr_wanted)
+ SendToServer_NrWanted(nr_wanted);
+#endif
+}
+
+static boolean CheckArtworkConfigForCustomElements(char *filename)
+{
+ SetupFileHash *setup_file_hash;
+ boolean redefined_ce_found = FALSE;
+
+ /* !!! CACHE THIS BY USING HASH 'filename' => 'true/false' !!! */