#define CONFIG_TOKEN_FONT_INITIAL "font.initial"
#define CONFIG_TOKEN_GLOBAL_BUSY "global.busy"
+#define CONFIG_TOKEN_BACKGROUND_LOADING "background.LOADING"
+
+#define INITIAL_IMG_GLOBAL_BUSY 0
+#define INITIAL_IMG_BACKGROUND_LOADING 1
+
+#define NUM_INITIAL_IMAGES 2
static struct FontBitmapInfo font_initial[NUM_INITIAL_FONTS];
-static struct GraphicInfo anim_initial;
+static struct GraphicInfo image_initial[NUM_INITIAL_IMAGES];
static int copy_properties[][5] =
{
static int get_graphic_parameter_value(char *, char *, int);
+static void SetLoadingBackgroundImage(void)
+{
+ struct GraphicInfo *graphic_info_last = graphic_info;
+
+ graphic_info = image_initial;
+
+ SetDrawDeactivationMask(REDRAW_NONE);
+ SetDrawBackgroundMask(REDRAW_ALL);
+
+ SetWindowBackgroundImage(INITIAL_IMG_BACKGROUND_LOADING);
+
+ graphic_info = graphic_info_last;
+}
+
static void DrawInitAnim(void)
{
struct GraphicInfo *graphic_info_last = graphic_info;
if (game_status != GAME_MODE_LOADING)
return;
- if (anim_initial.bitmap == NULL || window == NULL)
+ if (image_initial[INITIAL_IMG_GLOBAL_BUSY].bitmap == NULL || window == NULL)
return;
if (!DelayReached(&action_delay, action_delay_value))
x = ALIGNED_TEXT_XPOS(&init_last.busy);
y = ALIGNED_TEXT_YPOS(&init_last.busy);
- graphic_info = &anim_initial; // graphic == 0 => anim_initial
+ graphic_info = image_initial; // graphic == 0 => image_initial
- if (sync_frame % anim_initial.anim_delay == 0)
+ if (sync_frame % image_initial[INITIAL_IMG_GLOBAL_BUSY].anim_delay == 0)
{
Bitmap *src_bitmap;
int src_x, src_y;
int height = graphic_info[graphic].height;
int frame = getGraphicAnimationFrame(graphic, sync_frame);
+ ClearRectangleOnBackground(drawto, x, y, width, height);
+
getFixedGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
- BlitBitmap(src_bitmap, window, src_x, src_y, width, height, x, y);
+ BlitBitmapMasked(src_bitmap, drawto, src_x, src_y, width, height, x, y);
+
+ BlitBitmap(drawto, window, x, y, width, height, x, y);
}
graphic_info = graphic_info_last;
}
}
+
+static void InitGameInfoFromArtworkInfo(void)
+{
+ // special case: store initial value of custom artwork setting
+ game.use_masked_elements_initial = game.use_masked_elements;
+}
+
static void ReinitializeGraphics(void)
{
print_timestamp_init("ReinitializeGraphics");
InitGraphicCompatibilityInfo();
print_timestamp_time("InitGraphicCompatibilityInfo");
- SetMainBackgroundImage(IMG_BACKGROUND);
- print_timestamp_time("SetMainBackgroundImage");
- SetDoorBackgroundImage(IMG_BACKGROUND_DOOR);
- print_timestamp_time("SetDoorBackgroundImage");
-
InitGadgets();
print_timestamp_time("InitGadgets");
InitDoors();
print_timestamp_time("InitDoors");
+ InitGameInfoFromArtworkInfo();
+
print_timestamp_done("ReinitializeGraphics");
}
static int ep_walkable_over[] =
{
EL_EMPTY_SPACE,
+ EL_EMPTY_SPACE_1,
+ EL_EMPTY_SPACE_2,
+ EL_EMPTY_SPACE_3,
+ EL_EMPTY_SPACE_4,
+ EL_EMPTY_SPACE_5,
+ EL_EMPTY_SPACE_6,
+ EL_EMPTY_SPACE_7,
+ EL_EMPTY_SPACE_8,
+ EL_EMPTY_SPACE_9,
+ EL_EMPTY_SPACE_10,
+ EL_EMPTY_SPACE_11,
+ EL_EMPTY_SPACE_12,
+ EL_EMPTY_SPACE_13,
+ EL_EMPTY_SPACE_14,
+ EL_EMPTY_SPACE_15,
+ EL_EMPTY_SPACE_16,
EL_SP_EMPTY_SPACE,
EL_SOKOBAN_FIELD_EMPTY,
EL_EXIT_OPEN,
-1
};
+ static int ep_empty_space[] =
+ {
+ EL_EMPTY_SPACE,
+ EL_EMPTY_SPACE_1,
+ EL_EMPTY_SPACE_2,
+ EL_EMPTY_SPACE_3,
+ EL_EMPTY_SPACE_4,
+ EL_EMPTY_SPACE_5,
+ EL_EMPTY_SPACE_6,
+ EL_EMPTY_SPACE_7,
+ EL_EMPTY_SPACE_8,
+ EL_EMPTY_SPACE_9,
+ EL_EMPTY_SPACE_10,
+ EL_EMPTY_SPACE_11,
+ EL_EMPTY_SPACE_12,
+ EL_EMPTY_SPACE_13,
+ EL_EMPTY_SPACE_14,
+ EL_EMPTY_SPACE_15,
+ EL_EMPTY_SPACE_16,
+
+ -1
+ };
+
static int ep_player[] =
{
EL_PLAYER_1,
static int ep_inactive[] =
{
EL_EMPTY,
+ EL_EMPTY_SPACE_1,
+ EL_EMPTY_SPACE_2,
+ EL_EMPTY_SPACE_3,
+ EL_EMPTY_SPACE_4,
+ EL_EMPTY_SPACE_5,
+ EL_EMPTY_SPACE_6,
+ EL_EMPTY_SPACE_7,
+ EL_EMPTY_SPACE_8,
+ EL_EMPTY_SPACE_9,
+ EL_EMPTY_SPACE_10,
+ EL_EMPTY_SPACE_11,
+ EL_EMPTY_SPACE_12,
+ EL_EMPTY_SPACE_13,
+ EL_EMPTY_SPACE_14,
+ EL_EMPTY_SPACE_15,
+ EL_EMPTY_SPACE_16,
EL_SAND,
EL_WALL,
EL_BD_WALL,
EL_INTERNAL_CASCADE_STEEL_CHARS_ACTIVE,
EL_INTERNAL_CASCADE_CE_ACTIVE,
EL_INTERNAL_CASCADE_GE_ACTIVE,
+ EL_INTERNAL_CASCADE_ES_ACTIVE,
EL_INTERNAL_CASCADE_REF_ACTIVE,
EL_INTERNAL_CASCADE_USER_ACTIVE,
EL_INTERNAL_CASCADE_DYNAMIC_ACTIVE,
EL_INTERNAL_CASCADE_STEEL_CHARS,
EL_INTERNAL_CASCADE_CE,
EL_INTERNAL_CASCADE_GE,
+ EL_INTERNAL_CASCADE_ES,
EL_INTERNAL_CASCADE_REF,
EL_INTERNAL_CASCADE_USER,
EL_INTERNAL_CASCADE_DYNAMIC,
{ ep_can_explode, EP_CAN_EXPLODE },
{ ep_gravity_reachable, EP_GRAVITY_REACHABLE },
+ { ep_empty_space, EP_EMPTY_SPACE },
{ ep_player, EP_PLAYER },
{ ep_can_pass_magic_wall, EP_CAN_PASS_MAGIC_WALL },
{ ep_can_pass_dc_magic_wall, EP_CAN_PASS_DC_MAGIC_WALL },
// ---------- CAN_BE_CLONED_BY_ANDROID ------------------------------------
for (j = 0; j < level.num_android_clone_elements; j++)
SET_PROPERTY(i, EP_CAN_BE_CLONED_BY_ANDROID,
- (i != EL_EMPTY &&
+ (!IS_EMPTY(i) &&
IS_EQUAL_OR_IN_GROUP(i, level.android_clone_element[j])));
// ---------- CAN_CHANGE --------------------------------------------------
LoadUserSetup(); // global user number
LoadSetup(); // global setup info
- LoadSetup_AutoSetup(); // global auto setup info
// set some options from setup file
game.request_active = FALSE;
game.request_active_or_moving = FALSE;
+
+ game.use_masked_elements_initial = FALSE;
}
static void InitPlayerInfo(void)
{
struct GraphicInfo *graphic_info_last = graphic_info;
char *filename_font_initial = NULL;
- char *filename_anim_initial = NULL;
+ char *filename_image_initial[NUM_INITIAL_IMAGES] = { NULL };
+ char *image_token[NUM_INITIAL_IMAGES] =
+ {
+ CONFIG_TOKEN_GLOBAL_BUSY,
+ CONFIG_TOKEN_BACKGROUND_LOADING
+ };
Bitmap *bitmap_font_initial = NULL;
- int i, j;
+ int parameter[NUM_INITIAL_IMAGES][NUM_GFX_ARGS];
+ int i, j, k;
// determine settings for initial font (for displaying startup messages)
for (i = 0; image_config[i].token != NULL; i++)
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)
{
InitGfxCustomArtworkInfo();
InitGfxOtherSettings();
+ InitGfxTileSizeInfo(TILESIZE, TILESIZE);
+
bitmap_font_initial = LoadCustomImage(filename_font_initial);
for (j = 0; j < NUM_INITIAL_FONTS; j++)
DrawProgramInfo();
- DrawInitText("Loading graphics", 120, FC_GREEN);
+ DrawInitTextHead("Loading graphics");
- // initialize settings for 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);
+ InitMenuDesignSettings_Static();
- char *anim_token = CONFIG_TOKEN_GLOBAL_BUSY;
- int len_anim_token = strlen(anim_token);
+ // initialize settings for initial images with default values
+ for (i = 0; i < NUM_INITIAL_IMAGES; i++)
+ for (j = 0; j < NUM_GFX_ARGS; j++)
+ parameter[i][j] =
+ get_graphic_parameter_value(image_config_suffix[j].value,
+ image_config_suffix[j].token,
+ image_config_suffix[j].type);
- // read settings for busy animation from default custom artwork config
+ // read settings for initial images from default custom artwork config
char *gfx_config_filename = getPath3(options.graphics_directory,
GFX_DEFAULT_SUBDIR,
GRAPHICSINFO_FILENAME);
if (setup_file_hash)
{
- char *filename = getHashEntry(setup_file_hash, anim_token);
-
- if (filename)
+ for (i = 0; i < NUM_INITIAL_IMAGES; i++)
{
- filename_anim_initial = getStringCopy(filename);
+ char *filename = getHashEntry(setup_file_hash, image_token[i]);
- for (j = 0; image_config_suffix[j].token != NULL; j++)
+ if (filename)
{
- int type = image_config_suffix[j].type;
- char *suffix = image_config_suffix[j].token;
- char *token = getStringCat2(anim_token, suffix);
- char *value = getHashEntry(setup_file_hash, token);
+ filename_image_initial[i] = getStringCopy(filename);
- checked_free(token);
+ for (j = 0; image_config_suffix[j].token != NULL; j++)
+ {
+ int type = image_config_suffix[j].type;
+ char *suffix = image_config_suffix[j].token;
+ char *token = getStringCat2(image_token[i], suffix);
+ char *value = getHashEntry(setup_file_hash, token);
- if (value)
- parameter[j] = get_graphic_parameter_value(value, suffix, type);
+ checked_free(token);
+
+ if (value)
+ parameter[i][j] =
+ get_graphic_parameter_value(value, suffix, type);
+ }
}
}
+ // read values from custom graphics config file
+ InitMenuDesignSettings_FromHash(setup_file_hash, FALSE);
+
freeSetupFileHash(setup_file_hash);
}
}
- if (filename_anim_initial == NULL)
+ for (i = 0; i < NUM_INITIAL_IMAGES; i++)
{
- // read settings for busy animation from static default artwork config
- for (i = 0; image_config[i].token != NULL; i++)
+ if (filename_image_initial[i] == NULL)
{
- if (strEqual(image_config[i].token, anim_token))
- filename_anim_initial = getStringCopy(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)
+ int len_token = strlen(image_token[i]);
+
+ // read settings for initial images from static default artwork config
+ for (j = 0; image_config[j].token != NULL; j++)
{
- for (j = 0; image_config_suffix[j].token != NULL; j++)
+ if (strEqual(image_config[j].token, image_token[i]))
{
- 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);
+ filename_image_initial[i] = getStringCopy(image_config[j].value);
+ }
+ else if (strlen(image_config[j].token) > len_token &&
+ strncmp(image_config[j].token, image_token[i], len_token) == 0)
+ {
+ for (k = 0; image_config_suffix[k].token != NULL; k++)
+ {
+ if (strEqual(&image_config[j].token[len_token],
+ image_config_suffix[k].token))
+ parameter[i][k] =
+ get_graphic_parameter_value(image_config[j].value,
+ image_config_suffix[k].token,
+ image_config_suffix[k].type);
+ }
}
}
}
}
- if (filename_anim_initial == NULL) // should not happen
- Fail("cannot get filename for '%s'", CONFIG_TOKEN_GLOBAL_BUSY);
+ for (i = 0; i < NUM_INITIAL_IMAGES; i++)
+ {
+ if (filename_image_initial[i] == NULL) // should not happen
+ Fail("cannot get filename for '%s'", image_token[i]);
- anim_initial.bitmaps =
- checked_calloc(sizeof(Bitmap *) * NUM_IMG_BITMAP_POINTERS);
+ image_initial[i].bitmaps =
+ checked_calloc(sizeof(Bitmap *) * NUM_IMG_BITMAP_POINTERS);
- anim_initial.bitmaps[IMG_BITMAP_STANDARD] =
- LoadCustomImage(filename_anim_initial);
+ if (!strEqual(filename_image_initial[i], UNDEFINED_FILENAME))
+ image_initial[i].bitmaps[IMG_BITMAP_STANDARD] =
+ LoadCustomImage(filename_image_initial[i]);
- checked_free(filename_anim_initial);
+ checked_free(filename_image_initial[i]);
+ }
- graphic_info = &anim_initial; // graphic == 0 => anim_initial
+ graphic_info = image_initial; // graphic == 0 => image_initial
- set_graphic_parameters_ext(0, parameter, anim_initial.bitmaps);
+ for (i = 0; i < NUM_INITIAL_IMAGES; i++)
+ set_graphic_parameters_ext(i, parameter[i], image_initial[i].bitmaps);
graphic_info = graphic_info_last;
- init.busy.width = anim_initial.width;
- init.busy.height = anim_initial.height;
+ SetLoadingBackgroundImage();
- InitMenuDesignSettings_Static();
+ ClearRectangleOnBackground(window, 0, 0, WIN_XSIZE, WIN_YSIZE);
InitGfxDrawBusyAnimFunction(DrawInitAnim);
InitGfxDrawGlobalAnimFunction(DrawGlobalAnimations);
static char *last_leveldir_identifier[3] = { NULL, NULL, NULL };
static char *last_artwork_identifier[3] = { NULL, NULL, NULL };
static boolean last_override_level_artwork[3] = { FALSE, FALSE, FALSE };
- static boolean last_has_level_artwork_set[3] = { FALSE, FALSE, FALSE };
+ static boolean last_has_custom_artwork_set[3] = { FALSE, FALSE, FALSE };
static boolean initialized[3] = { FALSE, FALSE, FALSE };
TreeInfo *artwork_first_node = ARTWORK_FIRST_NODE(artwork, type);
boolean setup_override_artwork = GFX_OVERRIDE_ARTWORK(type);
// !!! setLevelArtworkDir() should be moved to an earlier stage !!!
char *leveldir_artwork_set = setLevelArtworkDir(artwork_first_node);
boolean has_level_artwork_set = (leveldir_artwork_set != NULL);
+ TreeInfo *custom_artwork_set =
+ getTreeInfoFromIdentifier(artwork_first_node, leveldir_identifier);
+ boolean has_custom_artwork_set = (custom_artwork_set != NULL);
char *artwork_current_identifier;
char *artwork_new_identifier = NULL; // default: nothing has changed
if (setup_override_artwork)
artwork_current_identifier = setup_artwork_set;
- else if (leveldir_artwork_set != NULL)
+ else if (has_level_artwork_set)
artwork_current_identifier = leveldir_artwork_set;
- else if (getTreeInfoFromIdentifier(artwork_first_node, leveldir_identifier))
+ else if (has_custom_artwork_set)
artwork_current_identifier = leveldir_identifier;
else
artwork_current_identifier = setup_artwork_set;
// ---------- reload if level set and also artwork set has changed ----------
if (last_leveldir_identifier[type] != leveldir_identifier &&
- (last_has_level_artwork_set[type] || has_level_artwork_set))
+ (last_has_custom_artwork_set[type] || has_custom_artwork_set))
artwork_new_identifier = artwork_current_identifier;
last_leveldir_identifier[type] = leveldir_identifier;
- last_has_level_artwork_set[type] = has_level_artwork_set;
+ last_has_custom_artwork_set[type] = has_custom_artwork_set;
// ---------- reload if "override artwork" setting has changed --------------
if (last_override_level_artwork[type] != setup_override_artwork)
FadeOut(REDRAW_ALL);
- ClearRectangle(drawto, 0, 0, WIN_XSIZE, WIN_YSIZE);
- print_timestamp_time("ClearRectangle");
+ SetLoadingBackgroundImage();
+
+ ClearRectangleOnBackground(drawto, 0, 0, WIN_XSIZE, WIN_YSIZE);
+ print_timestamp_time("ClearRectangleOnBackground");
FadeIn(REDRAW_ALL);
+ UPDATE_BUSY_STATE();
+
if (gfx_new_identifier != NULL || force_reload_gfx)
{
#if 0
SetGameStatus(last_game_status); // restore current game status
- init_last = init; // switch to new busy animation
-
FadeOut(REDRAW_ALL);
RedrawGlobalBorder();
InitRND(NEW_RANDOMIZE);
InitSimpleRandom(NEW_RANDOMIZE);
+ InitBetterRandom(NEW_RANDOMIZE);
print_timestamp_time("[init global stuff]");
print_timestamp_done("OpenAll");
+ if (setup.ask_for_remaining_tapes)
+ setup.ask_for_uploading_tapes = TRUE;
+
DrawMainMenu();
#if 0
#endif
}
+static boolean WaitForApiThreads(void)
+{
+ unsigned int thread_delay = 0;
+ unsigned int thread_delay_value = 10000;
+
+ if (program.api_thread_count == 0)
+ return TRUE;
+
+ // deactivate global animations (not accessible in game state "loading")
+ setup.toons = FALSE;
+
+ // set game state to "loading" to be able to show busy animation
+ SetGameStatus(GAME_MODE_LOADING);
+
+ ResetDelayCounter(&thread_delay);
+
+ // wait for threads to finish (and fail on timeout)
+ while (program.api_thread_count > 0)
+ {
+ if (DelayReached(&thread_delay, thread_delay_value))
+ {
+ Error("failed waiting for threads - TIMEOUT");
+
+ return FALSE;
+ }
+
+ UPDATE_BUSY_STATE();
+
+ Delay(20);
+ }
+
+ return TRUE;
+}
+
void CloseAllAndExit(int exit_value)
{
+ WaitForApiThreads();
+
StopSounds();
FreeAllSounds();
FreeAllMusic();