+ /* create additional image buffers for double-buffering */
+ bitmap_db_field = CreateBitmap(FXSIZE, FYSIZE, DEFAULT_DEPTH);
+ bitmap_db_door = CreateBitmap(3 * DXSIZE, DYSIZE + VYSIZE, 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);
+
+ bitmap_font_initial = LoadCustomImage(filename_font_initial);
+
+ for (j=0; j < NUM_INITIAL_FONTS; j++)
+ font_initial[j].bitmap = bitmap_font_initial;
+
+ InitFontGraphicInfo();
+
+ DrawInitText(WINDOW_TITLE_STRING, 20, FC_YELLOW);
+ DrawInitText(WINDOW_SUBTITLE_STRING, 50, FC_RED);
+
+ DrawInitText("Loading graphics:", 120, FC_GREEN);
+
+ InitTileClipmasks();
+}
+
+void InitGfxBackground()
+{
+ int x, y;
+
+ drawto = backbuffer;
+ fieldbuffer = bitmap_db_field;
+ SetDrawtoField(DRAW_BACKBUFFER);
+
+ BlitBitmap(graphic_info[IMG_GLOBAL_BORDER].bitmap, backbuffer,
+ 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
+ ClearRectangle(backbuffer, REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE);
+ ClearRectangle(bitmap_db_door, 0, 0, 3 * DXSIZE, DYSIZE + VYSIZE);
+
+ 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 */
+}
+
+void InitLevelArtworkInfo()
+{
+ LoadLevelArtworkInfo();
+}
+
+static void InitImages()
+{
+#if 1
+ setLevelArtworkDir(artwork.gfx_first);
+#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
+
+ ReloadCustomImages();
+
+ LoadCustomElementDescriptions();
+ LoadSpecialMenuDesignSettings();
+
+ ReinitializeGraphics();
+}
+
+static void InitSound()
+{
+ setLevelArtworkDir(artwork.snd_first);
+
+ InitReloadCustomSounds(artwork.snd_current->identifier);
+ ReinitializeSounds();
+}
+
+static void InitMusic()
+{
+ setLevelArtworkDir(artwork.mus_first);
+
+ InitReloadCustomMusic(artwork.mus_current->identifier);
+ ReinitializeMusic();
+}
+
+void InitNetworkServer()
+{
+#if defined(PLATFORM_UNIX)
+ int nr_wanted;
+#endif
+
+ if (!options.network)
+ return;
+
+#if defined(PLATFORM_UNIX)
+ 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
+}
+
+void ReloadCustomArtwork()
+{
+ static char *leveldir_current_identifier = NULL;
+ static boolean last_override_level_graphics = FALSE;
+ static boolean last_override_level_sounds = FALSE;
+ static boolean last_override_level_music = FALSE;
+ static boolean last_own_level_graphics_set = FALSE;
+ static boolean last_own_level_sounds_set = FALSE;
+ static boolean last_own_level_music_set = FALSE;
+ boolean level_graphics_set_changed = FALSE;
+ boolean level_sounds_set_changed = FALSE;
+ boolean level_music_set_changed = FALSE;
+ /* identifier for new artwork; default: artwork configured in setup */
+#if 0
+ char *gfx_new_identifier = artwork.gfx_current->identifier;
+ char *snd_new_identifier = artwork.snd_current->identifier;
+ char *mus_new_identifier = artwork.mus_current->identifier;
+#else
+ char *gfx_new_identifier = artwork.gfx_current_identifier;
+ char *snd_new_identifier = artwork.snd_current_identifier;
+ char *mus_new_identifier = artwork.mus_current_identifier;
+#endif
+ boolean redraw_screen = FALSE;
+
+#if 0
+ if (leveldir_current_identifier == NULL)
+ leveldir_current_identifier = leveldir_current->identifier;
+#endif
+
+#if 0
+ printf("CURRENT GFX: '%s' ['%s']\n", artwork.gfx_current->identifier,
+ leveldir_current->graphics_set);
+ printf("CURRENT LEV: '%s' / '%s'\n", leveldir_current_identifier,
+ leveldir_current->identifier);
+#endif
+
+#if 0
+ printf("graphics --> '%s' ('%s')\n",
+ artwork.gfx_current_identifier, artwork.gfx_current->filename);
+ printf("sounds --> '%s' ('%s')\n",
+ artwork.snd_current_identifier, artwork.snd_current->filename);
+ printf("music --> '%s' ('%s')\n",
+ artwork.mus_current_identifier, artwork.mus_current->filename);
+#endif
+
+ /* leveldir_current may be invalid (level group, parent link) */
+ if (!validLevelSeries(leveldir_current))
+ return;
+
+ /* when a new level series was selected, check if there was a change
+ in custom artwork stored in level series directory */
+ if (1 || leveldir_current_identifier != leveldir_current->identifier)
+ {
+#if 0
+ char *identifier_old = leveldir_current_identifier;
+#endif
+ char *identifier_new = leveldir_current->identifier;
+
+#if 0
+ printf("::: 1: ['%s'] '%s', '%s' [%lx, %lx]\n",
+ gfx_new_identifier, identifier_old, identifier_new,
+ getTreeInfoFromIdentifier(artwork.gfx_first, identifier_old),
+ getTreeInfoFromIdentifier(artwork.gfx_first, identifier_new));
+#endif
+
+#if 0
+ if (getTreeInfoFromIdentifier(artwork.gfx_first, identifier_new) == NULL)
+ gfx_new_identifier = GRAPHICS_SUBDIR;
+ else if (getTreeInfoFromIdentifier(artwork.gfx_first, identifier_old) !=
+ getTreeInfoFromIdentifier(artwork.gfx_first, identifier_new))
+ gfx_new_identifier = identifier_new;
+#else
+ if (getTreeInfoFromIdentifier(artwork.gfx_first, identifier_new))
+ gfx_new_identifier = identifier_new;
+ else
+ gfx_new_identifier = setup.graphics_set;
+#endif
+
+#if 0
+ if (getTreeInfoFromIdentifier(artwork.snd_first, identifier_new) == NULL)
+ snd_new_identifier = SOUNDS_SUBDIR;
+ else if (getTreeInfoFromIdentifier(artwork.snd_first, identifier_old) !=
+ getTreeInfoFromIdentifier(artwork.snd_first, identifier_new))
+ snd_new_identifier = identifier_new;
+#else
+ if (getTreeInfoFromIdentifier(artwork.snd_first, identifier_new))
+ snd_new_identifier = identifier_new;
+ else
+ snd_new_identifier = setup.sounds_set;
+#endif
+
+#if 0
+ if (getTreeInfoFromIdentifier(artwork.mus_first, identifier_new) == NULL)
+ mus_new_identifier = MUSIC_SUBDIR;
+ else if (getTreeInfoFromIdentifier(artwork.mus_first, identifier_new) !=
+ getTreeInfoFromIdentifier(artwork.mus_first, identifier_new))
+ mus_new_identifier = identifier_new;
+#else
+ if (getTreeInfoFromIdentifier(artwork.mus_first, identifier_new))
+ mus_new_identifier = identifier_new;
+ else
+ mus_new_identifier = setup.music_set;
+#endif
+
+#if 0
+ printf("::: 2: ['%s'] '%s', '%s'\n",
+ gfx_new_identifier, identifier_old, identifier_new);
+#endif
+
+#if 0
+ leveldir_current_identifier = leveldir_current->identifier;
+#endif
+ }
+
+ /* custom level artwork configured in level series configuration file
+ always overrides custom level artwork stored in level series directory
+ and (level independent) custom artwork configured in setup menu */
+ if (leveldir_current->graphics_set != NULL)
+ gfx_new_identifier = leveldir_current->graphics_set;
+ if (leveldir_current->sounds_set != NULL)
+ snd_new_identifier = leveldir_current->sounds_set;
+ if (leveldir_current->music_set != NULL)
+ mus_new_identifier = leveldir_current->music_set;
+
+ if (leveldir_current_identifier != leveldir_current->identifier)
+ {
+ if (last_own_level_graphics_set || leveldir_current->graphics_set != NULL)
+ level_graphics_set_changed = TRUE;
+
+ if (last_own_level_sounds_set || leveldir_current->sounds_set != NULL)
+ level_sounds_set_changed = TRUE;
+
+ if (last_own_level_music_set || leveldir_current->music_set != NULL)
+ level_music_set_changed = TRUE;
+
+ last_own_level_graphics_set = (leveldir_current->graphics_set != NULL);
+ last_own_level_sounds_set = (leveldir_current->sounds_set != NULL);
+ last_own_level_music_set = (leveldir_current->music_set != NULL);
+ }
+
+#if 1
+ leveldir_current_identifier = leveldir_current->identifier;
+#endif
+
+ if (setup.override_level_graphics)
+ gfx_new_identifier = artwork.gfx_current->identifier;
+ if (setup.override_level_sounds)
+ snd_new_identifier = artwork.snd_current->identifier;
+ if (setup.override_level_music)
+ mus_new_identifier = artwork.mus_current->identifier;
+
+
+#if 0
+ printf("CHECKING OLD/NEW GFX:\n OLD: '%s'\n NEW: '%s' ['%s', '%s'] [%d]\n",
+ artwork.gfx_current_identifier, gfx_new_identifier,
+ artwork.gfx_current->identifier, leveldir_current->graphics_set,
+ level_graphics_set_changed);
+#endif
+
+ if (strcmp(artwork.gfx_current_identifier, gfx_new_identifier) != 0 ||
+ last_override_level_graphics != setup.override_level_graphics ||
+ level_graphics_set_changed)
+ {
+#if 0
+ printf("RELOADING GRAPHICS '%s' -> '%s' ['%s']\n",
+ artwork.gfx_current_identifier,
+ gfx_new_identifier,
+ artwork.gfx_current->identifier);
+#endif
+
+#if 0
+ artwork.gfx_current =
+ getTreeInfoFromIdentifier(artwork.gfx_first, gfx_new_identifier);
+#endif
+#if 0
+ artwork.gfx_current_identifier = gfx_new_identifier;
+#endif
+
+#if 0
+ setLevelArtworkDir(artwork.gfx_first);
+#endif
+
+ ClearRectangle(window, 0, 0, WIN_XSIZE, WIN_YSIZE);
+
+ InitImages();
+
+#if 0
+ printf("::: %d\n", menu.list_size[GAME_MODE_LEVELS]);
+#endif
+
+ FreeTileClipmasks();
+ InitTileClipmasks();
+#if 0
+ artwork.gfx_current =
+ getTreeInfoFromIdentifier(artwork.gfx_first, gfx_new_identifier);
+#endif
+#if 0
+ printf("::: '%s', %lx\n", gfx_new_identifier, artwork.gfx_current);
+#endif
+
+#if 0
+ artwork.gfx_current_identifier = artwork.gfx_current->identifier;
+#endif
+ artwork.gfx_current_identifier = gfx_new_identifier;
+ last_override_level_graphics = setup.override_level_graphics;
+
+#if 0
+ printf("DONE RELOADING GFX: '%s' ['%s']\n",
+ artwork.gfx_current_identifier, artwork.gfx_current->identifier);
+#endif
+
+ redraw_screen = TRUE;
+ }
+
+ if (strcmp(artwork.snd_current_identifier, snd_new_identifier) != 0 ||
+ last_override_level_sounds != setup.override_level_sounds ||
+ level_sounds_set_changed)
+ {
+#if 0
+ printf("RELOADING SOUNDS '%s' -> '%s' ('%s')\n",
+ artwork.snd_current_identifier,
+ artwork.snd_current->identifier,
+ snd_new_identifier);
+#endif
+
+ /* set artwork path to send it to the sound server process */
+ setLevelArtworkDir(artwork.snd_first);
+
+ ClearRectangle(window, 0, 0, WIN_XSIZE, WIN_YSIZE);
+
+ InitReloadCustomSounds(snd_new_identifier);
+ ReinitializeSounds();
+
+#if 0
+ artwork.snd_current =
+ getTreeInfoFromIdentifier(artwork.snd_first, setup.sounds_set);
+ artwork.snd_current_identifier = artwork.snd_current->identifier;
+#endif
+ artwork.snd_current_identifier = snd_new_identifier;
+ last_override_level_sounds = setup.override_level_sounds;
+
+ redraw_screen = TRUE;
+ }
+
+ if (strcmp(artwork.mus_current_identifier, mus_new_identifier) != 0 ||
+ last_override_level_music != setup.override_level_music ||
+ level_music_set_changed)
+ {
+ /* set artwork path to send it to the sound server process */
+ setLevelArtworkDir(artwork.mus_first);
+
+ ClearRectangle(window, 0, 0, WIN_XSIZE, WIN_YSIZE);
+
+ InitReloadCustomMusic(mus_new_identifier);
+ ReinitializeMusic();
+
+#if 0
+ artwork.mus_current =
+ getTreeInfoFromIdentifier(artwork.mus_first, setup.music_set);
+ artwork.mus_current_identifier = artwork.mus_current->identifier;
+#endif
+ artwork.mus_current_identifier = mus_new_identifier;
+ last_override_level_music = setup.override_level_music;
+
+ redraw_screen = TRUE;
+ }
+
+ if (redraw_screen)
+ {
+ InitGfxBackground();
+
+ /* force redraw of (open or closed) door graphics */
+ SetDoorState(DOOR_OPEN_ALL);
+ CloseDoor(DOOR_CLOSE_ALL | DOOR_NO_DELAY);
+ }
+}
+
+void KeyboardAutoRepeatOffUnlessAutoplay()
+{
+ if (global.autoplay_leveldir == NULL)
+ KeyboardAutoRepeatOff();
+}
+
+
+/* ========================================================================= */
+/* OpenAll() */
+/* ========================================================================= */
+
+void OpenAll()
+{
+ InitGlobal(); /* initialize some global variables */
+
+ if (options.execute_command)
+ Execute_Command(options.execute_command);
+
+ if (options.serveronly)
+ {
+#if defined(PLATFORM_UNIX)
+ NetworkServer(options.server_port, options.serveronly);
+#else
+ Error(ERR_WARN, "networking only supported in Unix version");
+#endif
+ exit(0); /* never reached */
+ }
+
+ InitSetup();
+
+ InitPlayerInfo();
+ InitArtworkInfo(); /* needed before loading gfx, sound & music */
+ InitArtworkConfig(); /* needed before forking sound child process */
+ InitMixer();
+
+ InitCounter();
+
+ InitRND(NEW_RANDOMIZE);
+ InitSimpleRND(NEW_RANDOMIZE);
+
+ InitJoysticks();
+
+ InitVideoDisplay();
+ InitVideoBuffer(&backbuffer, &window, WIN_XSIZE, WIN_YSIZE, DEFAULT_DEPTH,
+ setup.fullscreen);
+
+ InitEventFilter(FilterMouseMotionEvents);
+
+ InitElementPropertiesStatic();
+
+ InitGfx();
+
+ InitLevelInfo();
+ InitLevelArtworkInfo();
+
+ InitImages(); /* needs to know current level directory */
+ InitSound(); /* needs to know current level directory */
+ InitMusic(); /* needs to know current level directory */
+
+ InitGfxBackground();
+
+ if (global.autoplay_leveldir)
+ {
+ AutoPlayTape();
+ return;
+ }
+
+ game_status = GAME_MODE_MAIN;
+
+ DrawMainMenu();
+
+ InitNetworkServer();
+}
+
+void CloseAllAndExit(int exit_value)
+{
+ StopSounds();
+ FreeAllSounds();
+ FreeAllMusic();
+ CloseAudio(); /* called after freeing sounds (needed for SDL) */
+
+ FreeAllImages();
+ FreeTileClipmasks();