X-Git-Url: https://git.artsoft.org/?p=rocksndiamonds.git;a=blobdiff_plain;f=src%2Finit.c;h=4596e8395d4772a6b2bd282680435f20fa948b2e;hp=c975ec616a5d194cf485ef238d3027fd15c7f362;hb=328e3b0f53ca41e626fda33427f5c51325bc700b;hpb=bc76bd63993e350f699d1420ebd9ae3ac573f407 diff --git a/src/init.c b/src/init.c index c975ec61..4596e839 100644 --- a/src/init.c +++ b/src/init.c @@ -1,7 +1,7 @@ /*********************************************************** * Rocks'n'Diamonds -- McDuffin Strikes Back! * *----------------------------------------------------------* -* (c) 1995-2002 Artsoft Entertainment * +* (c) 1995-2006 Artsoft Entertainment * * Holger Schemel * * Detmolder Strasse 189 * * 33604 Bielefeld * @@ -32,12 +32,18 @@ #include "conf_fnt.c" /* include auto-generated data structure definitions */ #include "conf_g2s.c" /* include auto-generated data structure definitions */ #include "conf_g2m.c" /* include auto-generated data structure definitions */ +#include "conf_act.c" /* include auto-generated data structure definitions */ #define CONFIG_TOKEN_FONT_INITIAL "font.initial" +#define CONFIG_TOKEN_GLOBAL_BUSY "global.busy" + +#define DEBUG_PRINT_INIT_TIMESTAMPS TRUE +#define DEBUG_PRINT_INIT_TIMESTAMPS_DEPTH 1 static struct FontBitmapInfo font_initial[NUM_INITIAL_FONTS]; +static struct GraphicInfo anim_initial; static int copy_properties[][5] = { @@ -82,6 +88,160 @@ static int copy_properties[][5] = } }; + +static void print_timestamp_ext(char *message, char *mode) +{ +#if DEBUG +#if DEBUG_PRINT_INIT_TIMESTAMPS + static char *debug_message = NULL; + static char *last_message = NULL; + static int counter_nr = 0; + int max_depth = DEBUG_PRINT_INIT_TIMESTAMPS_DEPTH; + + checked_free(debug_message); + debug_message = getStringCat3(mode, " ", message); + + if (strEqual(mode, "INIT")) + { + debug_print_timestamp(counter_nr, NULL); + + if (counter_nr + 1 < max_depth) + debug_print_timestamp(counter_nr, debug_message); + + counter_nr++; + + debug_print_timestamp(counter_nr, NULL); + } + else if (strEqual(mode, "DONE")) + { + counter_nr--; + + if (counter_nr + 1 < max_depth || + (counter_nr == 0 && max_depth == 1)) + { + last_message = message; + + if (counter_nr == 0 && max_depth == 1) + { + checked_free(debug_message); + debug_message = getStringCat3("TIME", " ", message); + } + + debug_print_timestamp(counter_nr, debug_message); + } + } + else if (!strEqual(mode, "TIME") || + !strEqual(message, last_message)) + { + if (counter_nr < max_depth) + debug_print_timestamp(counter_nr, debug_message); + } +#endif +#endif +} + +static void print_timestamp_init(char *message) +{ + print_timestamp_ext(message, "INIT"); +} + +static void print_timestamp_time(char *message) +{ + print_timestamp_ext(message, "TIME"); +} + +static void print_timestamp_done(char *message) +{ + print_timestamp_ext(message, "DONE"); +} + +void DrawInitAnim() +{ + struct GraphicInfo *graphic_info_last = graphic_info; + int graphic = 0; + static unsigned long action_delay = 0; + unsigned long action_delay_value = GameFrameDelay; + int sync_frame = FrameCounter; + int x, y; + + if (game_status != GAME_MODE_LOADING) + return; + + if (anim_initial.bitmap == NULL || window == NULL) + return; + + if (!DelayReached(&action_delay, action_delay_value)) + return; + +#if 0 + { + static unsigned long last_counter = -1; + unsigned long current_counter = Counter(); + unsigned long delay = current_counter - last_counter; + + if (last_counter != -1 && delay > action_delay_value + 5) + printf("::: DrawInitAnim: DELAY TOO LONG: %ld\n", delay); + + last_counter = current_counter; + } +#endif + +#if 0 + anim_initial.anim_mode = ANIM_LOOP; + anim_initial.anim_start_frame = 0; + anim_initial.offset_x = anim_initial.width; + anim_initial.offset_y = 0; +#endif + +#if 1 + x = ALIGNED_TEXT_XPOS(&init.busy); + y = ALIGNED_TEXT_YPOS(&init.busy); +#else + x = WIN_XSIZE / 2 - TILESIZE / 2; + y = WIN_YSIZE / 2 - TILESIZE / 2; +#endif + + graphic_info = &anim_initial; /* graphic == 0 => anim_initial */ + +#if 0 + { + static boolean done = FALSE; + + // if (!done) + printf("::: %d, %d, %d, %d => %d, %d [%d, %d] [%d, %d]\n", + init.busy.x, init.busy.y, + init.busy.align, init.busy.valign, + x, y, + graphic_info[graphic].width, + graphic_info[graphic].height, + sync_frame, anim_initial.anim_delay); + + done = TRUE; + } +#endif + + if (sync_frame % anim_initial.anim_delay == 0) + { +#if 1 + Bitmap *src_bitmap; + int src_x, src_y; + int width = graphic_info[graphic].width; + int height = graphic_info[graphic].height; + int frame = getGraphicAnimationFrame(graphic, sync_frame); + + getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y); + BlitBitmap(src_bitmap, window, src_x, src_y, width, height, x, y); +#else + /* !!! this can only draw TILEX/TILEY size animations !!! */ + DrawGraphicAnimationExt(window, x, y, graphic, sync_frame, NO_MASKING); +#endif + } + + graphic_info = graphic_info_last; + + FrameCounter++; +} + void FreeGadgets() { FreeLevelEditorGadgets(); @@ -104,11 +264,19 @@ void InitGadgets() CreateToolButtons(); CreateScreenGadgets(); + InitGadgetsSoundCallback(PlaySoundActivating, PlaySoundSelecting); + gadgets_initialized = TRUE; } inline void InitElementSmallImagesScaledUp(int graphic) { +#if 0 + struct FileInfo *fi = getImageListEntryFromImageID(graphic); + + printf("::: '%s' -> '%s'\n", fi->token, fi->filename); +#endif + CreateImageWithSmallImages(graphic, graphic_info[graphic].scale_up_factor); } @@ -161,16 +329,37 @@ void SetBitmaps_EM(Bitmap **em_bitmap) } #endif +#if 0 +/* !!! FIX THIS (CHANGE TO USING NORMAL ELEMENT GRAPHIC DEFINITIONS) !!! */ +void SetBitmaps_SP(Bitmap **sp_bitmap) +{ + *sp_bitmap = graphic_info[IMG_SP_OBJECTS].bitmap; +} +#endif + static int getFontBitmapID(int font_nr) { int special = -1; - if (game_status >= GAME_MODE_MAIN && game_status <= GAME_MODE_PSEUDO_PREVIEW) + /* (special case: do not use special font for GAME_MODE_LOADING) */ + if (game_status >= GAME_MODE_TITLE_INITIAL && + game_status <= GAME_MODE_PSEUDO_PREVIEW) special = game_status; else if (game_status == GAME_MODE_PSEUDO_TYPENAME) special = GFX_SPECIAL_ARG_MAIN; +#if 0 else if (game_status == GAME_MODE_PLAYING) special = GFX_SPECIAL_ARG_DOOR; +#endif + +#if 0 + if (special != -1) + { + printf("%s%s\n", + font_info[font_nr].token_name, + special_suffix_info[special].suffix); + } +#endif if (special != -1) return font_info[font_nr].special_bitmap_id[special]; @@ -178,6 +367,26 @@ static int getFontBitmapID(int font_nr) return font_nr; } +static int getFontFromToken(char *token) +{ +#if 1 + char *value = getHashEntry(font_token_hash, token); + + if (value != NULL) + return atoi(value); +#else + int i; + + /* !!! OPTIMIZE THIS BY USING HASH !!! */ + for (i = 0; i < NUM_FONTS; i++) + if (strEqual(token, font_info[i].token_name)) + return i; +#endif + + /* if font not found, use reliable default value */ + return FONT_INITIAL_1; +} + void InitFontGraphicInfo() { static struct FontBitmapInfo *font_bitmap_info = NULL; @@ -188,7 +397,8 @@ void InitFontGraphicInfo() if (graphic_info == NULL) /* still at startup phase */ { - InitFontInfo(font_initial, NUM_INITIAL_FONTS, getFontBitmapID); + InitFontInfo(font_initial, NUM_INITIAL_FONTS, + getFontBitmapID, getFontFromToken); return; } @@ -230,18 +440,21 @@ void InitFontGraphicInfo() int graphic = font_to_graphic[i].graphic; int base_graphic = font2baseimg(font_nr); - if (special >= 0 && special < NUM_SPECIAL_GFX_ARGS) + if (IS_SPECIAL_GFX_ARG(special)) { boolean base_redefined = getImageListEntryFromImageID(base_graphic)->redefined; boolean special_redefined = getImageListEntryFromImageID(graphic)->redefined; + boolean special_cloned = (graphic_info[graphic].clone_from != -1); /* if the base font ("font.title_1", for example) has been redefined, but not the special font ("font.title_1.LEVELS", for example), do not use an existing (in this case considered obsolete) special font anymore, but use the automatically determined default font */ - if (base_redefined && !special_redefined) + /* special case: cloned special fonts must be explicitly redefined, + but are not automatically redefined by redefining base font */ + if (base_redefined && !special_redefined && !special_cloned) continue; font_info[font_nr].special_graphic[special] = graphic; @@ -250,7 +463,7 @@ void InitFontGraphicInfo() } } - /* initialize special element/graphic mapping from dynamic configuration */ + /* initialize special font/graphic mapping from dynamic configuration */ for (i = 0; i < num_property_mappings; i++) { int font_nr = property_mapping[i].base_index - MAX_NUM_ELEMENTS; @@ -260,7 +473,7 @@ void InitFontGraphicInfo() if (font_nr < 0) continue; - if (special >= 0 && special < NUM_SPECIAL_GFX_ARGS) + if (IS_SPECIAL_GFX_ARG(special)) { font_info[font_nr].special_graphic[special] = graphic; font_info[font_nr].special_bitmap_id[special] = num_font_bitmaps; @@ -268,6 +481,93 @@ void InitFontGraphicInfo() } } + /* correct special font/graphic mapping for cloned fonts for downwards + compatibility of PREVIEW fonts -- this is only needed for implicit + redefinition of special font by redefined base font, and only if other + fonts are cloned from this special font (like in the "Zelda" level set) */ + for (i = 0; font_to_graphic[i].font_nr > -1; i++) + { + int font_nr = font_to_graphic[i].font_nr; + int special = font_to_graphic[i].special; + int graphic = font_to_graphic[i].graphic; + + if (IS_SPECIAL_GFX_ARG(special)) + { + boolean special_redefined = + getImageListEntryFromImageID(graphic)->redefined; + boolean special_cloned = (graphic_info[graphic].clone_from != -1); + + if (special_cloned && !special_redefined) + { + int j; + + for (j = 0; font_to_graphic[j].font_nr > -1; j++) + { + int font_nr2 = font_to_graphic[j].font_nr; + int special2 = font_to_graphic[j].special; + int graphic2 = font_to_graphic[j].graphic; + + if (IS_SPECIAL_GFX_ARG(special2) && + graphic2 == graphic_info[graphic].clone_from) + { + font_info[font_nr].special_graphic[special] = + font_info[font_nr2].special_graphic[special2]; + font_info[font_nr].special_bitmap_id[special] = + font_info[font_nr2].special_bitmap_id[special2]; + } + } + } + } + } + + /* reset non-redefined ".active" font graphics if normal font is redefined */ + /* (this different treatment is needed because normal and active fonts are + independently defined ("active" is not a property of font definitions!) */ + for (i = 0; i < NUM_FONTS; i++) + { + int font_nr_base = i; + int font_nr_active = FONT_ACTIVE(font_nr_base); + + /* check only those fonts with exist as normal and ".active" variant */ + if (font_nr_base != font_nr_active) + { + int base_graphic = font_info[font_nr_base].graphic; + int active_graphic = font_info[font_nr_active].graphic; + boolean base_redefined = + getImageListEntryFromImageID(base_graphic)->redefined; + boolean active_redefined = + getImageListEntryFromImageID(active_graphic)->redefined; + + /* if the base font ("font.menu_1", for example) has been redefined, + but not the active font ("font.menu_1.active", for example), do not + use an existing (in this case considered obsolete) active font + anymore, but use the automatically determined default font */ + if (base_redefined && !active_redefined) + font_info[font_nr_active].graphic = base_graphic; + + /* now also check each "special" font (which may be the same as above) */ + for (j = 0; j < NUM_SPECIAL_GFX_ARGS; j++) + { + int base_graphic = font_info[font_nr_base].special_graphic[j]; + int active_graphic = font_info[font_nr_active].special_graphic[j]; + boolean base_redefined = + getImageListEntryFromImageID(base_graphic)->redefined; + boolean active_redefined = + getImageListEntryFromImageID(active_graphic)->redefined; + + /* same as above, but check special graphic definitions, for example: + redefined "font.menu_1.MAIN" invalidates "font.menu_1.active.MAIN" */ + if (base_redefined && !active_redefined) + { + font_info[font_nr_active].special_graphic[j] = + font_info[font_nr_base].special_graphic[j]; + font_info[font_nr_active].special_bitmap_id[j] = + font_info[font_nr_base].special_bitmap_id[j]; + } + } + } + } + /* ---------- initialize font bitmap array ---------- */ if (font_bitmap_info != NULL) @@ -295,7 +595,7 @@ void InitFontGraphicInfo() if (graphic_info[graphic].anim_frames < MIN_NUM_CHARS_PER_FONT) { graphic_info[graphic].anim_frames = DEFAULT_NUM_CHARS_PER_FONT; - graphic_info[graphic].anim_frames_per_line= DEFAULT_NUM_CHARS_PER_LINE; + graphic_info[graphic].anim_frames_per_line = DEFAULT_NUM_CHARS_PER_LINE; } /* copy font relevant information from graphics information */ @@ -317,7 +617,8 @@ void InitFontGraphicInfo() } } - InitFontInfo(font_bitmap_info, num_font_bitmaps, getFontBitmapID); + InitFontInfo(font_bitmap_info, num_font_bitmaps, + getFontBitmapID, getFontFromToken); } void InitElementGraphicInfo() @@ -345,6 +646,8 @@ void InitElementGraphicInfo() } } + UPDATE_BUSY_STATE(); + /* initialize normal element/graphic mapping from static configuration */ for (i = 0; element_to_graphic[i].element > -1; i++) { @@ -403,6 +706,16 @@ void InitElementGraphicInfo() int graphic = property_mapping[i].artwork_index; boolean crumbled = FALSE; +#if 0 + if ((element == EL_EM_DYNAMITE || + element == EL_EM_DYNAMITE_ACTIVE) && + action == ACTION_ACTIVE && + (special == GFX_SPECIAL_ARG_EDITOR || + special == GFX_SPECIAL_ARG_PANEL)) + printf("::: DYNAMIC: %d, %d, %d -> %d\n", + element, action, special, graphic); +#endif + if (special == GFX_SPECIAL_ARG_CRUMBLED) { special = -1; @@ -519,6 +832,8 @@ void InitElementGraphicInfo() } } + UPDATE_BUSY_STATE(); + /* adjust graphics with 2nd tile for movement according to direction (do this before correcting '-1' values to minimize calculations) */ for (i = 0; i < MAX_NUM_ELEMENTS; i++) @@ -578,6 +893,8 @@ void InitElementGraphicInfo() } } + UPDATE_BUSY_STATE(); + /* now set all '-1' values to element specific default values */ for (i = 0; i < MAX_NUM_ELEMENTS; i++) { @@ -729,6 +1046,8 @@ void InitElementGraphicInfo() } } + UPDATE_BUSY_STATE(); + #if 0 /* !!! THIS ALSO CLEARS SPECIAL FLAGS (AND IS NOT NEEDED ANYWAY) !!! */ /* set animation mode to "none" for each graphic with only 1 frame */ @@ -765,7 +1084,7 @@ void InitElementGraphicInfo() for (i = 0; i < MAX_NUM_ELEMENTS; i++) if (element_info[i].graphic[ACTION_DEFAULT] == IMG_UNKNOWN && i != EL_UNKNOWN) - Error(ERR_RETURN, "warning: no graphic for element '%s' (%d)", + Error(ERR_INFO, "warning: no graphic for element '%s' (%d)", element_info[i].token_name, i); } #endif @@ -796,6 +1115,15 @@ void InitElementSpecialGraphicInfo() boolean special_redefined = getImageListEntryFromImageID(graphic)->redefined; +#if 0 + if ((element == EL_EM_DYNAMITE || + element == EL_EM_DYNAMITE_ACTIVE) && + (special == GFX_SPECIAL_ARG_EDITOR || + special == GFX_SPECIAL_ARG_PANEL)) + printf("::: SPECIAL STATIC: %d, %d -> %d\n", + element, special, graphic); +#endif + /* if the base graphic ("emerald", for example) has been redefined, but not the special graphic ("emerald.EDITOR", for example), do not use an existing (in this case considered obsolete) special graphic @@ -809,14 +1137,58 @@ void InitElementSpecialGraphicInfo() /* initialize special element/graphic mapping from dynamic configuration */ for (i = 0; i < num_property_mappings; i++) { - int element = property_mapping[i].base_index; - int special = property_mapping[i].ext3_index; - int graphic = property_mapping[i].artwork_index; + int element = property_mapping[i].base_index; + int action = property_mapping[i].ext1_index; + int direction = property_mapping[i].ext2_index; + int special = property_mapping[i].ext3_index; + int graphic = property_mapping[i].artwork_index; + +#if 0 + if ((element == EL_EM_DYNAMITE || + element == EL_EM_DYNAMITE_ACTIVE || + element == EL_CONVEYOR_BELT_1_MIDDLE || + element == EL_CONVEYOR_BELT_1_MIDDLE_ACTIVE) && + (special == GFX_SPECIAL_ARG_EDITOR || + special == GFX_SPECIAL_ARG_PANEL)) + printf("::: SPECIAL DYNAMIC: %d, %d -> %d [%d]\n", + element, special, graphic, property_mapping[i].ext1_index); +#endif + +#if 0 + if (element == EL_CONVEYOR_BELT_1_MIDDLE && + action == ACTION_ACTIVE) + { + element = EL_CONVEYOR_BELT_1_MIDDLE_ACTIVE; + action = -1; + } +#endif + +#if 0 + if (element == EL_MAGIC_WALL && + action == ACTION_ACTIVE) + { + element = EL_MAGIC_WALL_ACTIVE; + action = -1; + } +#endif + +#if 1 + /* for action ".active", replace element with active element, if exists */ + if (action == ACTION_ACTIVE && element != ELEMENT_ACTIVE(element)) + { + element = ELEMENT_ACTIVE(element); + action = -1; + } +#endif if (element >= MAX_NUM_ELEMENTS) continue; - if (special >= 0 && special < NUM_SPECIAL_GFX_ARGS) + /* do not change special graphic if action or direction was specified */ + if (action != -1 || direction != -1) + continue; + + if (IS_SPECIAL_GFX_ARG(special)) element_info[element].special_graphic[special] = graphic; } @@ -830,15 +1202,34 @@ void InitElementSpecialGraphicInfo() static int get_graphic_parameter_value(char *value_raw, char *suffix, int type) { - int i; - int x = 0; - - if (type != TYPE_TOKEN) + if (type != TYPE_ELEMENT && type != TYPE_GRAPHIC) return get_parameter_value(value_raw, suffix, type); if (strEqual(value_raw, ARG_UNDEFINED)) return ARG_UNDEFINED_VALUE; +#if 1 + if (type == TYPE_ELEMENT) + { + char *value = getHashEntry(element_token_hash, value_raw); + + return (value != NULL ? atoi(value) : EL_UNDEFINED); + } + else if (type == TYPE_GRAPHIC) + { + char *value = getHashEntry(graphic_token_hash, value_raw); + + return (value != NULL ? atoi(value) : IMG_UNDEFINED); + } + +#else + + int i; + int x = 0; + + /* !!! THIS IS BUGGY !!! NOT SURE IF YOU GET ELEMENT ID OR GRAPHIC ID !!! */ + /* !!! (possible reason why ".clone_from" with elements doesn't work) !!! */ + /* !!! OPTIMIZE THIS BY USING HASH !!! */ for (i = 0; i < MAX_NUM_ELEMENTS; i++) if (strEqual(element_info[i].token_name, value_raw)) @@ -859,6 +1250,7 @@ static int get_graphic_parameter_value(char *value_raw, char *suffix, int type) x++; } +#endif return -1; } @@ -879,73 +1271,364 @@ static int get_scaled_graphic_height(int graphic) return original_height * scale_up_factor; } -static void set_graphic_parameters(int graphic) +static void set_graphic_parameters_ext(int graphic, int *parameter, + Bitmap *src_bitmap) { - struct FileInfo *image = getImageListEntryFromImageID(graphic); - char **parameter_raw = image->parameter; - Bitmap *src_bitmap = getBitmapFromImageID(graphic); - int parameter[NUM_GFX_ARGS]; + struct GraphicInfo *g = &graphic_info[graphic]; int anim_frames_per_row = 1, anim_frames_per_col = 1; int anim_frames_per_line = 1; - int i; - - /* if fallback to default artwork is done, also use the default parameters */ - if (image->fallback_to_default) - parameter_raw = image->default_parameter; - /* get integer values from string parameters */ - for (i = 0; i < NUM_GFX_ARGS; i++) - parameter[i] = get_graphic_parameter_value(parameter_raw[i], - image_config_suffix[i].token, - image_config_suffix[i].type); + /* always start with reliable default values */ + g->src_image_width = 0; + g->src_image_height = 0; + g->src_x = 0; + g->src_y = 0; + g->width = TILEX; /* default for element graphics */ + g->height = TILEY; /* default for element graphics */ + g->offset_x = 0; /* one or both of these values ... */ + g->offset_y = 0; /* ... will be corrected later */ + g->offset2_x = 0; /* one or both of these values ... */ + g->offset2_y = 0; /* ... will be corrected later */ + g->swap_double_tiles = -1; /* auto-detect tile swapping */ + g->crumbled_like = -1; /* do not use clone element */ + g->diggable_like = -1; /* do not use clone element */ + g->border_size = TILEX / 8; /* "CRUMBLED" border size */ + g->scale_up_factor = 1; /* default: no scaling up */ + g->clone_from = -1; /* do not use clone graphic */ + g->anim_delay_fixed = 0; + g->anim_delay_random = 0; + g->post_delay_fixed = 0; + g->post_delay_random = 0; + g->fade_mode = FADE_MODE_DEFAULT; + g->fade_delay = -1; + g->post_delay = -1; + g->auto_delay = -1; + g->align = ALIGN_CENTER; /* default for title screens */ + g->valign = VALIGN_MIDDLE; /* default for title screens */ + g->sort_priority = 0; /* default for title screens */ + g->class = 0; + g->style = STYLE_DEFAULT; + + g->bitmap = src_bitmap; - graphic_info[graphic].bitmap = src_bitmap; +#if 1 + /* optional zoom factor for scaling up the image to a larger size */ + if (parameter[GFX_ARG_SCALE_UP_FACTOR] != ARG_UNDEFINED_VALUE) + g->scale_up_factor = parameter[GFX_ARG_SCALE_UP_FACTOR]; + if (g->scale_up_factor < 1) + g->scale_up_factor = 1; /* no scaling */ +#endif - /* start with reliable default values */ - graphic_info[graphic].src_image_width = 0; - graphic_info[graphic].src_image_height = 0; - graphic_info[graphic].src_x = 0; - graphic_info[graphic].src_y = 0; - graphic_info[graphic].width = TILEX; - graphic_info[graphic].height = TILEY; - graphic_info[graphic].offset_x = 0; /* one or both of these values ... */ - graphic_info[graphic].offset_y = 0; /* ... will be corrected later */ - graphic_info[graphic].offset2_x = 0; /* one or both of these values ... */ - graphic_info[graphic].offset2_y = 0; /* ... will be corrected later */ - graphic_info[graphic].swap_double_tiles = -1; /* auto-detect tile swapping */ - graphic_info[graphic].crumbled_like = -1; /* do not use clone element */ - graphic_info[graphic].diggable_like = -1; /* do not use clone element */ - graphic_info[graphic].border_size = TILEX / 8; /* "CRUMBLED" border size */ - graphic_info[graphic].scale_up_factor = 1; /* default: no scaling up */ - graphic_info[graphic].clone_from = -1; /* do not use clone graphic */ - graphic_info[graphic].anim_delay_fixed = 0; - graphic_info[graphic].anim_delay_random = 0; - graphic_info[graphic].post_delay_fixed = 0; - graphic_info[graphic].post_delay_random = 0; +#if 1 + if (g->use_image_size) + { + /* set new default bitmap size (with scaling, but without small images) */ + g->width = get_scaled_graphic_width(graphic); + g->height = get_scaled_graphic_height(graphic); + } +#endif /* optional x and y tile position of animation frame sequence */ if (parameter[GFX_ARG_XPOS] != ARG_UNDEFINED_VALUE) - graphic_info[graphic].src_x = parameter[GFX_ARG_XPOS] * TILEX; + g->src_x = parameter[GFX_ARG_XPOS] * TILEX; if (parameter[GFX_ARG_YPOS] != ARG_UNDEFINED_VALUE) - graphic_info[graphic].src_y = parameter[GFX_ARG_YPOS] * TILEY; + g->src_y = parameter[GFX_ARG_YPOS] * TILEY; /* optional x and y pixel position of animation frame sequence */ if (parameter[GFX_ARG_X] != ARG_UNDEFINED_VALUE) - graphic_info[graphic].src_x = parameter[GFX_ARG_X]; + g->src_x = parameter[GFX_ARG_X]; if (parameter[GFX_ARG_Y] != ARG_UNDEFINED_VALUE) - graphic_info[graphic].src_y = parameter[GFX_ARG_Y]; + g->src_y = parameter[GFX_ARG_Y]; /* optional width and height of each animation frame */ if (parameter[GFX_ARG_WIDTH] != ARG_UNDEFINED_VALUE) - graphic_info[graphic].width = parameter[GFX_ARG_WIDTH]; + g->width = parameter[GFX_ARG_WIDTH]; if (parameter[GFX_ARG_HEIGHT] != ARG_UNDEFINED_VALUE) - graphic_info[graphic].height = parameter[GFX_ARG_HEIGHT]; + g->height = parameter[GFX_ARG_HEIGHT]; +#if 0 /* optional zoom factor for scaling up the image to a larger size */ if (parameter[GFX_ARG_SCALE_UP_FACTOR] != ARG_UNDEFINED_VALUE) - graphic_info[graphic].scale_up_factor = parameter[GFX_ARG_SCALE_UP_FACTOR]; - if (graphic_info[graphic].scale_up_factor < 1) + g->scale_up_factor = parameter[GFX_ARG_SCALE_UP_FACTOR]; + if (g->scale_up_factor < 1) + g->scale_up_factor = 1; /* no scaling */ +#endif + + if (src_bitmap) + { + /* get final bitmap size (with scaling, but without small images) */ + int src_image_width = get_scaled_graphic_width(graphic); + int src_image_height = get_scaled_graphic_height(graphic); + + if (src_image_width == 0 || src_image_height == 0) + { + /* only happens when loaded outside artwork system (like "global.busy") */ + src_image_width = src_bitmap->width; + src_image_height = src_bitmap->height; + } + + anim_frames_per_row = src_image_width / g->width; + anim_frames_per_col = src_image_height / g->height; + + g->src_image_width = src_image_width; + g->src_image_height = src_image_height; + } + + /* correct x or y offset dependent of vertical or horizontal frame order */ + if (parameter[GFX_ARG_VERTICAL]) /* frames are ordered vertically */ + { + g->offset_y = (parameter[GFX_ARG_OFFSET] != ARG_UNDEFINED_VALUE ? + parameter[GFX_ARG_OFFSET] : g->height); + anim_frames_per_line = anim_frames_per_col; + } + else /* frames are ordered horizontally */ + { + g->offset_x = (parameter[GFX_ARG_OFFSET] != ARG_UNDEFINED_VALUE ? + parameter[GFX_ARG_OFFSET] : g->width); + anim_frames_per_line = anim_frames_per_row; + } + + /* optionally, the x and y offset of frames can be specified directly */ + if (parameter[GFX_ARG_XOFFSET] != ARG_UNDEFINED_VALUE) + g->offset_x = parameter[GFX_ARG_XOFFSET]; + if (parameter[GFX_ARG_YOFFSET] != ARG_UNDEFINED_VALUE) + g->offset_y = parameter[GFX_ARG_YOFFSET]; + + /* optionally, moving animations may have separate start and end graphics */ + g->double_movement = parameter[GFX_ARG_2ND_MOVEMENT_TILE]; + + if (parameter[GFX_ARG_2ND_VERTICAL] == ARG_UNDEFINED_VALUE) + parameter[GFX_ARG_2ND_VERTICAL] = !parameter[GFX_ARG_VERTICAL]; + + /* correct x or y offset2 dependent of vertical or horizontal frame order */ + if (parameter[GFX_ARG_2ND_VERTICAL]) /* frames are ordered vertically */ + g->offset2_y = (parameter[GFX_ARG_2ND_OFFSET] != ARG_UNDEFINED_VALUE ? + parameter[GFX_ARG_2ND_OFFSET] : g->height); + else /* frames are ordered horizontally */ + g->offset2_x = (parameter[GFX_ARG_2ND_OFFSET] != ARG_UNDEFINED_VALUE ? + parameter[GFX_ARG_2ND_OFFSET] : g->width); + + /* optionally, the x and y offset of 2nd graphic can be specified directly */ + if (parameter[GFX_ARG_2ND_XOFFSET] != ARG_UNDEFINED_VALUE) + g->offset2_x = parameter[GFX_ARG_2ND_XOFFSET]; + if (parameter[GFX_ARG_2ND_YOFFSET] != ARG_UNDEFINED_VALUE) + g->offset2_y = parameter[GFX_ARG_2ND_YOFFSET]; + + /* optionally, the second movement tile can be specified as start tile */ + if (parameter[GFX_ARG_2ND_SWAP_TILES] != ARG_UNDEFINED_VALUE) + g->swap_double_tiles= parameter[GFX_ARG_2ND_SWAP_TILES]; + + /* automatically determine correct number of frames, if not defined */ + if (parameter[GFX_ARG_FRAMES] != ARG_UNDEFINED_VALUE) + g->anim_frames = parameter[GFX_ARG_FRAMES]; + else if (parameter[GFX_ARG_XPOS] == 0 && !parameter[GFX_ARG_VERTICAL]) + g->anim_frames = anim_frames_per_row; + else if (parameter[GFX_ARG_YPOS] == 0 && parameter[GFX_ARG_VERTICAL]) + g->anim_frames = anim_frames_per_col; + else + g->anim_frames = 1; + + if (g->anim_frames == 0) /* frames must be at least 1 */ + g->anim_frames = 1; + + g->anim_frames_per_line = + (parameter[GFX_ARG_FRAMES_PER_LINE] != ARG_UNDEFINED_VALUE ? + parameter[GFX_ARG_FRAMES_PER_LINE] : anim_frames_per_line); + + g->anim_delay = parameter[GFX_ARG_DELAY]; + if (g->anim_delay == 0) /* delay must be at least 1 */ + g->anim_delay = 1; + + g->anim_mode = parameter[GFX_ARG_ANIM_MODE]; +#if 0 + if (g->anim_frames == 1) + g->anim_mode = ANIM_NONE; +#endif + + /* automatically determine correct start frame, if not defined */ + if (parameter[GFX_ARG_START_FRAME] == ARG_UNDEFINED_VALUE) + g->anim_start_frame = 0; + else if (g->anim_mode & ANIM_REVERSE) + g->anim_start_frame = g->anim_frames - parameter[GFX_ARG_START_FRAME] - 1; + else + g->anim_start_frame = parameter[GFX_ARG_START_FRAME]; + + /* animation synchronized with global frame counter, not move position */ + g->anim_global_sync = parameter[GFX_ARG_GLOBAL_SYNC]; + + /* optional element for cloning crumble graphics */ + if (parameter[GFX_ARG_CRUMBLED_LIKE] != ARG_UNDEFINED_VALUE) + g->crumbled_like = parameter[GFX_ARG_CRUMBLED_LIKE]; + + /* optional element for cloning digging graphics */ + if (parameter[GFX_ARG_DIGGABLE_LIKE] != ARG_UNDEFINED_VALUE) + g->diggable_like = parameter[GFX_ARG_DIGGABLE_LIKE]; + + /* optional border size for "crumbling" diggable graphics */ + if (parameter[GFX_ARG_BORDER_SIZE] != ARG_UNDEFINED_VALUE) + g->border_size = parameter[GFX_ARG_BORDER_SIZE]; + + /* this is only used for player "boring" and "sleeping" actions */ + if (parameter[GFX_ARG_ANIM_DELAY_FIXED] != ARG_UNDEFINED_VALUE) + g->anim_delay_fixed = parameter[GFX_ARG_ANIM_DELAY_FIXED]; + if (parameter[GFX_ARG_ANIM_DELAY_RANDOM] != ARG_UNDEFINED_VALUE) + g->anim_delay_random = parameter[GFX_ARG_ANIM_DELAY_RANDOM]; + if (parameter[GFX_ARG_POST_DELAY_FIXED] != ARG_UNDEFINED_VALUE) + g->post_delay_fixed = parameter[GFX_ARG_POST_DELAY_FIXED]; + if (parameter[GFX_ARG_POST_DELAY_RANDOM] != ARG_UNDEFINED_VALUE) + g->post_delay_random = parameter[GFX_ARG_POST_DELAY_RANDOM]; + + /* this is only used for toon animations */ + g->step_offset = parameter[GFX_ARG_STEP_OFFSET]; + g->step_delay = parameter[GFX_ARG_STEP_DELAY]; + + /* this is only used for drawing font characters */ + g->draw_xoffset = parameter[GFX_ARG_DRAW_XOFFSET]; + g->draw_yoffset = parameter[GFX_ARG_DRAW_YOFFSET]; + + /* this is only used for drawing envelope graphics */ + g->draw_masked = parameter[GFX_ARG_DRAW_MASKED]; + + /* optional graphic for cloning all graphics settings */ + if (parameter[GFX_ARG_CLONE_FROM] != ARG_UNDEFINED_VALUE) + g->clone_from = parameter[GFX_ARG_CLONE_FROM]; + + /* optional settings for drawing title screens and title messages */ + if (parameter[GFX_ARG_FADE_MODE] != ARG_UNDEFINED_VALUE) + g->fade_mode = parameter[GFX_ARG_FADE_MODE]; + if (parameter[GFX_ARG_FADE_DELAY] != ARG_UNDEFINED_VALUE) + g->fade_delay = parameter[GFX_ARG_FADE_DELAY]; + if (parameter[GFX_ARG_POST_DELAY] != ARG_UNDEFINED_VALUE) + g->post_delay = parameter[GFX_ARG_POST_DELAY]; + if (parameter[GFX_ARG_AUTO_DELAY] != ARG_UNDEFINED_VALUE) + g->auto_delay = parameter[GFX_ARG_AUTO_DELAY]; + if (parameter[GFX_ARG_ALIGN] != ARG_UNDEFINED_VALUE) + g->align = parameter[GFX_ARG_ALIGN]; + if (parameter[GFX_ARG_VALIGN] != ARG_UNDEFINED_VALUE) + g->valign = parameter[GFX_ARG_VALIGN]; + if (parameter[GFX_ARG_SORT_PRIORITY] != ARG_UNDEFINED_VALUE) + g->sort_priority = parameter[GFX_ARG_SORT_PRIORITY]; + + if (parameter[GFX_ARG_CLASS] != ARG_UNDEFINED_VALUE) + g->class = parameter[GFX_ARG_CLASS]; + if (parameter[GFX_ARG_STYLE] != ARG_UNDEFINED_VALUE) + g->style = parameter[GFX_ARG_STYLE]; +} + +static void set_graphic_parameters(int graphic) +{ +#if 1 + struct FileInfo *image = getImageListEntryFromImageID(graphic); + char **parameter_raw = image->parameter; + Bitmap *src_bitmap = getBitmapFromImageID(graphic); + int parameter[NUM_GFX_ARGS]; + int i; + + /* if fallback to default artwork is done, also use the default parameters */ + if (image->fallback_to_default) + parameter_raw = image->default_parameter; + + /* get integer values from string parameters */ + for (i = 0; i < NUM_GFX_ARGS; i++) + parameter[i] = get_graphic_parameter_value(parameter_raw[i], + image_config_suffix[i].token, + image_config_suffix[i].type); + + set_graphic_parameters_ext(graphic, parameter, src_bitmap); + +#else + + struct FileInfo *image = getImageListEntryFromImageID(graphic); + char **parameter_raw = image->parameter; + Bitmap *src_bitmap = getBitmapFromImageID(graphic); + int parameter[NUM_GFX_ARGS]; + int anim_frames_per_row = 1, anim_frames_per_col = 1; + int anim_frames_per_line = 1; + int i; + + /* if fallback to default artwork is done, also use the default parameters */ + if (image->fallback_to_default) + parameter_raw = image->default_parameter; + + /* get integer values from string parameters */ + for (i = 0; i < NUM_GFX_ARGS; i++) + parameter[i] = get_graphic_parameter_value(parameter_raw[i], + image_config_suffix[i].token, + image_config_suffix[i].type); + + graphic_info[graphic].bitmap = src_bitmap; + + /* always start with reliable default values */ + graphic_info[graphic].src_image_width = 0; + graphic_info[graphic].src_image_height = 0; + graphic_info[graphic].src_x = 0; + graphic_info[graphic].src_y = 0; + graphic_info[graphic].width = TILEX; /* default for element graphics */ + graphic_info[graphic].height = TILEY; /* default for element graphics */ + graphic_info[graphic].offset_x = 0; /* one or both of these values ... */ + graphic_info[graphic].offset_y = 0; /* ... will be corrected later */ + graphic_info[graphic].offset2_x = 0; /* one or both of these values ... */ + graphic_info[graphic].offset2_y = 0; /* ... will be corrected later */ + graphic_info[graphic].swap_double_tiles = -1; /* auto-detect tile swapping */ + graphic_info[graphic].crumbled_like = -1; /* do not use clone element */ + graphic_info[graphic].diggable_like = -1; /* do not use clone element */ + graphic_info[graphic].border_size = TILEX / 8; /* "CRUMBLED" border size */ + graphic_info[graphic].scale_up_factor = 1; /* default: no scaling up */ + graphic_info[graphic].clone_from = -1; /* do not use clone graphic */ + graphic_info[graphic].anim_delay_fixed = 0; + graphic_info[graphic].anim_delay_random = 0; + graphic_info[graphic].post_delay_fixed = 0; + graphic_info[graphic].post_delay_random = 0; + graphic_info[graphic].fade_mode = FADE_MODE_DEFAULT; + graphic_info[graphic].fade_delay = -1; + graphic_info[graphic].post_delay = -1; + graphic_info[graphic].auto_delay = -1; + graphic_info[graphic].align = ALIGN_CENTER; /* default for title screens */ + graphic_info[graphic].valign = VALIGN_MIDDLE; /* default for title screens */ + graphic_info[graphic].sort_priority = 0; /* default for title screens */ + +#if 1 + /* optional zoom factor for scaling up the image to a larger size */ + if (parameter[GFX_ARG_SCALE_UP_FACTOR] != ARG_UNDEFINED_VALUE) + graphic_info[graphic].scale_up_factor = parameter[GFX_ARG_SCALE_UP_FACTOR]; + if (graphic_info[graphic].scale_up_factor < 1) + graphic_info[graphic].scale_up_factor = 1; /* no scaling */ +#endif + +#if 1 + if (graphic_info[graphic].use_image_size) + { + /* set new default bitmap size (with scaling, but without small images) */ + graphic_info[graphic].width = get_scaled_graphic_width(graphic); + graphic_info[graphic].height = get_scaled_graphic_height(graphic); + } +#endif + + /* optional x and y tile position of animation frame sequence */ + if (parameter[GFX_ARG_XPOS] != ARG_UNDEFINED_VALUE) + graphic_info[graphic].src_x = parameter[GFX_ARG_XPOS] * TILEX; + if (parameter[GFX_ARG_YPOS] != ARG_UNDEFINED_VALUE) + graphic_info[graphic].src_y = parameter[GFX_ARG_YPOS] * TILEY; + + /* optional x and y pixel position of animation frame sequence */ + if (parameter[GFX_ARG_X] != ARG_UNDEFINED_VALUE) + graphic_info[graphic].src_x = parameter[GFX_ARG_X]; + if (parameter[GFX_ARG_Y] != ARG_UNDEFINED_VALUE) + graphic_info[graphic].src_y = parameter[GFX_ARG_Y]; + + /* optional width and height of each animation frame */ + if (parameter[GFX_ARG_WIDTH] != ARG_UNDEFINED_VALUE) + graphic_info[graphic].width = parameter[GFX_ARG_WIDTH]; + if (parameter[GFX_ARG_HEIGHT] != ARG_UNDEFINED_VALUE) + graphic_info[graphic].height = parameter[GFX_ARG_HEIGHT]; + +#if 0 + /* optional zoom factor for scaling up the image to a larger size */ + if (parameter[GFX_ARG_SCALE_UP_FACTOR] != ARG_UNDEFINED_VALUE) + graphic_info[graphic].scale_up_factor = parameter[GFX_ARG_SCALE_UP_FACTOR]; + if (graphic_info[graphic].scale_up_factor < 1) graphic_info[graphic].scale_up_factor = 1; /* no scaling */ +#endif if (src_bitmap) { @@ -1087,6 +1770,25 @@ static void set_graphic_parameters(int graphic) /* optional graphic for cloning all graphics settings */ if (parameter[GFX_ARG_CLONE_FROM] != ARG_UNDEFINED_VALUE) graphic_info[graphic].clone_from = parameter[GFX_ARG_CLONE_FROM]; + + /* optional settings for drawing title screens and title messages */ + if (parameter[GFX_ARG_FADE_MODE] != ARG_UNDEFINED_VALUE) + graphic_info[graphic].fade_mode = parameter[GFX_ARG_FADE_MODE]; + if (parameter[GFX_ARG_FADE_DELAY] != ARG_UNDEFINED_VALUE) + graphic_info[graphic].fade_delay = parameter[GFX_ARG_FADE_DELAY]; + if (parameter[GFX_ARG_POST_DELAY] != ARG_UNDEFINED_VALUE) + graphic_info[graphic].post_delay = parameter[GFX_ARG_POST_DELAY]; + if (parameter[GFX_ARG_AUTO_DELAY] != ARG_UNDEFINED_VALUE) + graphic_info[graphic].auto_delay = parameter[GFX_ARG_AUTO_DELAY]; + if (parameter[GFX_ARG_ALIGN] != ARG_UNDEFINED_VALUE) + graphic_info[graphic].align = parameter[GFX_ARG_ALIGN]; + if (parameter[GFX_ARG_VALIGN] != ARG_UNDEFINED_VALUE) + graphic_info[graphic].valign = parameter[GFX_ARG_VALIGN]; + if (parameter[GFX_ARG_SORT_PRIORITY] != ARG_UNDEFINED_VALUE) + graphic_info[graphic].sort_priority = parameter[GFX_ARG_SORT_PRIORITY]; +#endif + + UPDATE_BUSY_STATE(); } static void set_cloned_graphic_parameters(int graphic) @@ -1106,18 +1808,18 @@ static void set_cloned_graphic_parameters(int graphic) if (num_references_followed >= max_num_images) { - Error(ERR_RETURN_LINE, "-"); - Error(ERR_RETURN, "warning: error found in config file:"); - Error(ERR_RETURN, "- config file: '%s'", getImageConfigFilename()); - Error(ERR_RETURN, "- config token: '%s'", getTokenFromImageID(graphic)); - Error(ERR_RETURN, "error: loop discovered when resolving cloned graphics"); - Error(ERR_RETURN, "custom graphic rejected for this element/action"); + Error(ERR_INFO_LINE, "-"); + Error(ERR_INFO, "warning: error found in config file:"); + Error(ERR_INFO, "- config file: '%s'", getImageConfigFilename()); + Error(ERR_INFO, "- config token: '%s'", getTokenFromImageID(graphic)); + Error(ERR_INFO, "error: loop discovered when resolving cloned graphics"); + Error(ERR_INFO, "custom graphic rejected for this element/action"); if (graphic == fallback_graphic) Error(ERR_EXIT, "fatal error: no fallback graphic available"); - Error(ERR_RETURN, "fallback done to 'char_exclam' for this graphic"); - Error(ERR_RETURN_LINE, "-"); + Error(ERR_INFO, "fallback done to 'char_exclam' for this graphic"); + Error(ERR_INFO_LINE, "-"); graphic_info[graphic] = graphic_info[fallback_graphic]; } @@ -1142,10 +1844,61 @@ static void InitGraphicInfo() GC copy_clipmask_gc = None; #endif + /* use image size as default values for width and height for these images */ + static int full_size_graphics[] = + { + IMG_GLOBAL_BORDER, + IMG_GLOBAL_DOOR, + + IMG_BACKGROUND_ENVELOPE_1, + IMG_BACKGROUND_ENVELOPE_2, + IMG_BACKGROUND_ENVELOPE_3, + IMG_BACKGROUND_ENVELOPE_4, + + IMG_BACKGROUND, + IMG_BACKGROUND_TITLE_INITIAL, + IMG_BACKGROUND_TITLE, + IMG_BACKGROUND_MAIN, + IMG_BACKGROUND_LEVELS, + IMG_BACKGROUND_SCORES, + IMG_BACKGROUND_EDITOR, + IMG_BACKGROUND_INFO, + IMG_BACKGROUND_INFO_ELEMENTS, + IMG_BACKGROUND_INFO_MUSIC, + IMG_BACKGROUND_INFO_CREDITS, + IMG_BACKGROUND_INFO_PROGRAM, + IMG_BACKGROUND_INFO_LEVELSET, + IMG_BACKGROUND_SETUP, + IMG_BACKGROUND_DOOR, + + IMG_TITLESCREEN_INITIAL_1, + IMG_TITLESCREEN_INITIAL_2, + IMG_TITLESCREEN_INITIAL_3, + IMG_TITLESCREEN_INITIAL_4, + IMG_TITLESCREEN_INITIAL_5, + IMG_TITLESCREEN_1, + IMG_TITLESCREEN_2, + IMG_TITLESCREEN_3, + IMG_TITLESCREEN_4, + IMG_TITLESCREEN_5, + + -1 + }; + checked_free(graphic_info); graphic_info = checked_calloc(num_images * sizeof(struct GraphicInfo)); +#if 1 + /* initialize "use_image_size" flag with default value */ + for (i = 0; i < num_images; i++) + graphic_info[i].use_image_size = FALSE; + + /* initialize "use_image_size" flag from static configuration above */ + for (i = 0; full_size_graphics[i] != -1; i++) + graphic_info[full_size_graphics[i]].use_image_size = TRUE; +#endif + #if defined(TARGET_X11_NATIVE_PERFORMANCE_WORKAROUND) if (clipmasks_initialized) { @@ -1175,6 +1928,7 @@ static void InitGraphicInfo() { Bitmap *src_bitmap; int src_x, src_y; + int width, height; int first_frame, last_frame; int src_bitmap_width, src_bitmap_height; @@ -1183,6 +1937,10 @@ static void InitGraphicInfo() if (graphic_info[i].bitmap == NULL) continue; /* skip check for optional images that are undefined */ + /* get image size (this can differ from the standard element tile size!) */ + width = graphic_info[i].width; + height = graphic_info[i].height; + /* get final bitmap size (with scaling, but without small images) */ src_bitmap_width = graphic_info[i].src_image_width; src_bitmap_height = graphic_info[i].src_image_height; @@ -1192,25 +1950,31 @@ static void InitGraphicInfo() first_frame = 0; getGraphicSource(i, first_frame, &src_bitmap, &src_x, &src_y); +#if 1 + /* this avoids calculating wrong start position for out-of-bounds frame */ + src_x = graphic_info[i].src_x; + src_y = graphic_info[i].src_y; +#endif + if (src_x < 0 || src_y < 0 || - src_x + TILEX > src_bitmap_width || - src_y + TILEY > src_bitmap_height) + src_x + width > src_bitmap_width || + src_y + height > src_bitmap_height) { - Error(ERR_RETURN_LINE, "-"); - Error(ERR_RETURN, "warning: error found in config file:"); - Error(ERR_RETURN, "- config file: '%s'", getImageConfigFilename()); - Error(ERR_RETURN, "- config token: '%s'", getTokenFromImageID(i)); - Error(ERR_RETURN, "- image file: '%s'", src_bitmap->source_filename); - Error(ERR_RETURN, + Error(ERR_INFO_LINE, "-"); + Error(ERR_INFO, "warning: error found in config file:"); + Error(ERR_INFO, "- config file: '%s'", getImageConfigFilename()); + Error(ERR_INFO, "- config token: '%s'", getTokenFromImageID(i)); + Error(ERR_INFO, "- image file: '%s'", src_bitmap->source_filename); + Error(ERR_INFO, "error: first animation frame out of bounds (%d, %d) [%d, %d]", src_x, src_y, src_bitmap_width, src_bitmap_height); - Error(ERR_RETURN, "custom graphic rejected for this element/action"); + Error(ERR_INFO, "custom graphic rejected for this element/action"); if (i == fallback_graphic) Error(ERR_EXIT, "fatal error: no fallback graphic available"); - Error(ERR_RETURN, "fallback done to 'char_exclam' for this graphic"); - Error(ERR_RETURN_LINE, "-"); + Error(ERR_INFO, "fallback done to 'char_exclam' for this graphic"); + Error(ERR_INFO_LINE, "-"); graphic_info[i] = graphic_info[fallback_graphic]; } @@ -1221,24 +1985,24 @@ static void InitGraphicInfo() getGraphicSource(i, last_frame, &src_bitmap, &src_x, &src_y); if (src_x < 0 || src_y < 0 || - src_x + TILEX > src_bitmap_width || - src_y + TILEY > src_bitmap_height) + src_x + width > src_bitmap_width || + src_y + height > src_bitmap_height) { - Error(ERR_RETURN_LINE, "-"); - Error(ERR_RETURN, "warning: error found in config file:"); - Error(ERR_RETURN, "- config file: '%s'", getImageConfigFilename()); - Error(ERR_RETURN, "- config token: '%s'", getTokenFromImageID(i)); - Error(ERR_RETURN, "- image file: '%s'", src_bitmap->source_filename); - Error(ERR_RETURN, + Error(ERR_INFO_LINE, "-"); + Error(ERR_INFO, "warning: error found in config file:"); + Error(ERR_INFO, "- config file: '%s'", getImageConfigFilename()); + Error(ERR_INFO, "- config token: '%s'", getTokenFromImageID(i)); + Error(ERR_INFO, "- image file: '%s'", src_bitmap->source_filename); + Error(ERR_INFO, "error: last animation frame (%d) out of bounds (%d, %d) [%d, %d]", last_frame, src_x, src_y, src_bitmap_width, src_bitmap_height); - Error(ERR_RETURN, "custom graphic rejected for this element/action"); + Error(ERR_INFO, "custom graphic rejected for this element/action"); if (i == fallback_graphic) Error(ERR_EXIT, "fatal error: no fallback graphic available"); - Error(ERR_RETURN, "fallback done to 'char_exclam' for this graphic"); - Error(ERR_RETURN_LINE, "-"); + Error(ERR_INFO, "fallback done to 'char_exclam' for this graphic"); + Error(ERR_INFO_LINE, "-"); graphic_info[i] = graphic_info[fallback_graphic]; } @@ -1442,7 +2206,7 @@ static void set_sound_parameters(int sound, char **parameter_raw) sound_info[sound].volume = parameter[SND_ARG_VOLUME]; /* sound priority to give certain sounds a higher or lower priority */ - sound_info[sound].volume = parameter[SND_ARG_VOLUME]; + sound_info[sound].priority = parameter[SND_ARG_PRIORITY]; } static void InitSoundInfo() @@ -1655,21 +2419,36 @@ static void InitMusicInfo() static void ReinitializeGraphics() { + print_timestamp_init("ReinitializeGraphics"); + InitGraphicInfo(); /* graphic properties mapping */ + print_timestamp_time("InitGraphicInfo"); InitElementGraphicInfo(); /* element game graphic mapping */ + print_timestamp_time("InitElementGraphicInfo"); InitElementSpecialGraphicInfo(); /* element special graphic mapping */ + print_timestamp_time("InitElementSpecialGraphicInfo"); InitElementSmallImages(); /* scale elements to all needed sizes */ + print_timestamp_time("InitElementSmallImages"); InitScaledImages(); /* scale all other images, if needed */ + print_timestamp_time("InitScaledImages"); InitFontGraphicInfo(); /* initialize text drawing functions */ + print_timestamp_time("InitFontGraphicInfo"); InitGraphicInfo_EM(); /* graphic mapping for EM engine */ + print_timestamp_time("InitGraphicInfo_EM"); SetMainBackgroundImage(IMG_BACKGROUND); + print_timestamp_time("SetMainBackgroundImage"); SetDoorBackgroundImage(IMG_BACKGROUND_DOOR); + print_timestamp_time("SetDoorBackgroundImage"); InitGadgets(); + print_timestamp_time("InitGadgets"); InitToons(); + print_timestamp_time("InitToons"); + + print_timestamp_done("ReinitializeGraphics"); } static void ReinitializeSounds() @@ -1817,8 +2596,7 @@ boolean getBitfieldProperty(int *bitfield, int property_bit_nr, int element) return FALSE; } -#if 1 -static void resolve_group_element(int group_element, int recursion_depth) +static void ResolveGroupElementExt(int group_element, int recursion_depth) { static int group_nr; static struct ElementGroupInfo *group; @@ -1842,10 +2620,13 @@ static void resolve_group_element(int group_element, int recursion_depth) if (recursion_depth == 0) /* initialization */ { group = actual_group; - group_nr = group_element - EL_GROUP_START; + group_nr = GROUP_NR(group_element); group->num_elements_resolved = 0; group->choice_pos = 0; + + for (i = 0; i < MAX_NUM_ELEMENTS; i++) + element_info[i].in_group[group_nr] = FALSE; } for (i = 0; i < actual_group->num_elements; i++) @@ -1856,7 +2637,7 @@ static void resolve_group_element(int group_element, int recursion_depth) break; if (IS_GROUP_ELEMENT(element)) - resolve_group_element(element, recursion_depth + 1); + ResolveGroupElementExt(element, recursion_depth + 1); else { group->element_resolved[group->num_elements_resolved++] = element; @@ -1864,10 +2645,16 @@ static void resolve_group_element(int group_element, int recursion_depth) } } } -#endif + +void ResolveGroupElement(int group_element) +{ + ResolveGroupElementExt(group_element, 0); +} void InitElementPropertiesStatic() { + static boolean clipboard_elements_initialized = FALSE; + static int ep_diggable[] = { EL_SAND, @@ -1883,6 +2670,7 @@ void InitElementPropertiesStatic() /* (if amoeba can grow into anything diggable, maybe keep these out) */ #if 0 EL_LANDMINE, + EL_DC_LANDMINE, EL_TRAP_ACTIVE, EL_SP_BUGGY_BASE_ACTIVE, EL_EMC_PLANT, @@ -1920,7 +2708,7 @@ void InitElementPropertiesStatic() EL_SP_DISK_RED, EL_PEARL, EL_CRYSTAL, - EL_KEY_WHITE, + EL_DC_KEY_WHITE, EL_SHIELD_NORMAL, EL_SHIELD_DEADLY, EL_EXTRA_TIME, @@ -1932,6 +2720,11 @@ void InitElementPropertiesStatic() EL_EMC_LENSES, EL_EMC_MAGNIFIER, +#if 0 + /* !!! handle separately !!! */ + EL_DC_LANDMINE, /* deadly when running into, but can be snapped */ +#endif + -1 }; @@ -1958,6 +2751,7 @@ void InitElementPropertiesStatic() /* !!! maybe this should better be handled by 'ep_diggable' !!! */ #if 1 EL_LANDMINE, + EL_DC_LANDMINE, EL_TRAP_ACTIVE, EL_SP_BUGGY_BASE_ACTIVE, EL_EMC_PLANT, @@ -2036,13 +2830,48 @@ void InitElementPropertiesStatic() EL_SIGN_STOP, EL_SIGN_WHEELCHAIR, EL_SIGN_PARKING, - EL_SIGN_ONEWAY, + EL_SIGN_NO_ENTRY, + EL_SIGN_UNUSED_1, + EL_SIGN_GIVE_WAY, + EL_SIGN_ENTRY_FORBIDDEN, + EL_SIGN_EMERGENCY_EXIT, + EL_SIGN_YIN_YANG, + EL_SIGN_UNUSED_2, + EL_SIGN_SPERMS, + EL_SIGN_BULLET, EL_SIGN_HEART, - EL_SIGN_TRIANGLE, - EL_SIGN_ROUND, - EL_SIGN_EXIT, - EL_SIGN_YINYANG, - EL_SIGN_OTHER, + EL_SIGN_CROSS, + EL_SIGN_FRANKIE, + EL_STEEL_EXIT_CLOSED, + EL_STEEL_EXIT_OPEN, + EL_STEEL_EXIT_OPENING, + EL_STEEL_EXIT_CLOSING, + EL_EM_STEEL_EXIT_CLOSED, + EL_EM_STEEL_EXIT_OPEN, + EL_EM_STEEL_EXIT_OPENING, + EL_EM_STEEL_EXIT_CLOSING, + EL_DC_STEELWALL_1_LEFT, + EL_DC_STEELWALL_1_RIGHT, + EL_DC_STEELWALL_1_TOP, + EL_DC_STEELWALL_1_BOTTOM, + EL_DC_STEELWALL_1_HORIZONTAL, + EL_DC_STEELWALL_1_VERTICAL, + EL_DC_STEELWALL_1_TOPLEFT, + EL_DC_STEELWALL_1_TOPRIGHT, + EL_DC_STEELWALL_1_BOTTOMLEFT, + EL_DC_STEELWALL_1_BOTTOMRIGHT, + EL_DC_STEELWALL_1_TOPLEFT_2, + EL_DC_STEELWALL_1_TOPRIGHT_2, + EL_DC_STEELWALL_1_BOTTOMLEFT_2, + EL_DC_STEELWALL_1_BOTTOMRIGHT_2, + EL_DC_STEELWALL_2_LEFT, + EL_DC_STEELWALL_2_RIGHT, + EL_DC_STEELWALL_2_TOP, + EL_DC_STEELWALL_2_BOTTOM, + EL_DC_STEELWALL_2_HORIZONTAL, + EL_DC_STEELWALL_2_VERTICAL, + EL_DC_STEELWALL_2_MIDDLE, + EL_DC_STEELWALL_2_SINGLE, EL_STEELWALL_SLIPPERY, EL_EMC_STEELWALL_1, EL_EMC_STEELWALL_2, @@ -2085,21 +2914,25 @@ void InitElementPropertiesStatic() EL_EMC_GATE_6_GRAY_ACTIVE, EL_EMC_GATE_7_GRAY_ACTIVE, EL_EMC_GATE_8_GRAY_ACTIVE, + EL_DC_GATE_WHITE, + EL_DC_GATE_WHITE_GRAY, + EL_DC_GATE_WHITE_GRAY_ACTIVE, + EL_DC_GATE_FAKE_GRAY, EL_SWITCHGATE_OPEN, EL_SWITCHGATE_OPENING, EL_SWITCHGATE_CLOSED, EL_SWITCHGATE_CLOSING, -#if 0 - EL_SWITCHGATE_SWITCH_UP, - EL_SWITCHGATE_SWITCH_DOWN, +#if 1 + EL_DC_SWITCHGATE_SWITCH_UP, + EL_DC_SWITCHGATE_SWITCH_DOWN, #endif EL_TIMEGATE_OPEN, EL_TIMEGATE_OPENING, EL_TIMEGATE_CLOSED, EL_TIMEGATE_CLOSING, -#if 0 - EL_TIMEGATE_SWITCH, - EL_TIMEGATE_SWITCH_ACTIVE, +#if 1 + EL_DC_TIMEGATE_SWITCH, + EL_DC_TIMEGATE_SWITCH_ACTIVE, #endif EL_TUBE_ANY, EL_TUBE_VERTICAL, @@ -2112,6 +2945,9 @@ void InitElementPropertiesStatic() EL_TUBE_LEFT_DOWN, EL_TUBE_RIGHT_UP, EL_TUBE_RIGHT_DOWN, + EL_EXPANDABLE_STEELWALL_HORIZONTAL, + EL_EXPANDABLE_STEELWALL_VERTICAL, + EL_EXPANDABLE_STEELWALL_ANY, -1 }; @@ -2204,8 +3040,10 @@ void InitElementPropertiesStatic() EL_NUT, EL_AMOEBA_DROP, EL_QUICKSAND_FULL, + EL_QUICKSAND_FAST_FULL, EL_MAGIC_WALL_FULL, EL_BD_MAGIC_WALL_FULL, + EL_DC_MAGIC_WALL_FULL, EL_TIME_ORB_FULL, EL_TIME_ORB_EMPTY, EL_SP_ZONK, @@ -2333,8 +3171,17 @@ void InitElementPropertiesStatic() EL_SP_EMPTY_SPACE, EL_SOKOBAN_FIELD_EMPTY, EL_EXIT_OPEN, + EL_EM_EXIT_OPEN, +#if 1 + EL_EM_EXIT_OPENING, +#endif EL_SP_EXIT_OPEN, EL_SP_EXIT_OPENING, + EL_STEEL_EXIT_OPEN, + EL_EM_STEEL_EXIT_OPEN, +#if 1 + EL_EM_STEEL_EXIT_OPENING, +#endif EL_GATE_1, EL_GATE_2, EL_GATE_3, @@ -2402,6 +3249,9 @@ void InitElementPropertiesStatic() EL_EMC_GATE_6_GRAY_ACTIVE, EL_EMC_GATE_7_GRAY_ACTIVE, EL_EMC_GATE_8_GRAY_ACTIVE, + EL_DC_GATE_WHITE, + EL_DC_GATE_WHITE_GRAY, + EL_DC_GATE_WHITE_GRAY_ACTIVE, EL_SWITCHGATE_OPEN, EL_TIMEGATE_OPEN, @@ -2514,6 +3364,9 @@ void InitElementPropertiesStatic() EL_EMC_GATE_6_GRAY_ACTIVE, EL_EMC_GATE_7_GRAY_ACTIVE, EL_EMC_GATE_8_GRAY_ACTIVE, + EL_DC_GATE_WHITE, + EL_DC_GATE_WHITE_GRAY, + EL_DC_GATE_WHITE_GRAY_ACTIVE, EL_SWITCHGATE_OPEN, EL_TIMEGATE_OPEN, @@ -2643,6 +3496,22 @@ void InitElementPropertiesStatic() -1 }; + static int ep_can_pass_dc_magic_wall[] = + { + EL_ROCK, + EL_BD_ROCK, + EL_EMERALD, + EL_BD_DIAMOND, + EL_EMERALD_YELLOW, + EL_EMERALD_RED, + EL_EMERALD_PURPLE, + EL_DIAMOND, + EL_PEARL, + EL_CRYSTAL, + + -1 + }; + static int ep_switchable[] = { EL_ROBOT_WHEEL, @@ -2661,9 +3530,12 @@ void InitElementPropertiesStatic() EL_CONVEYOR_BELT_4_SWITCH_RIGHT, EL_SWITCHGATE_SWITCH_UP, EL_SWITCHGATE_SWITCH_DOWN, + EL_DC_SWITCHGATE_SWITCH_UP, + EL_DC_SWITCHGATE_SWITCH_DOWN, EL_LIGHT_SWITCH, EL_LIGHT_SWITCH_ACTIVE, EL_TIMEGATE_SWITCH, + EL_DC_TIMEGATE_SWITCH, EL_BALLOON_SWITCH_LEFT, EL_BALLOON_SWITCH_RIGHT, EL_BALLOON_SWITCH_UP, @@ -2999,8 +3871,12 @@ void InitElementPropertiesStatic() EL_INVISIBLE_WALL_ACTIVE, EL_SWITCHGATE_SWITCH_UP, EL_SWITCHGATE_SWITCH_DOWN, + EL_DC_SWITCHGATE_SWITCH_UP, + EL_DC_SWITCHGATE_SWITCH_DOWN, EL_TIMEGATE_SWITCH, EL_TIMEGATE_SWITCH_ACTIVE, + EL_DC_TIMEGATE_SWITCH, + EL_DC_TIMEGATE_SWITCH_ACTIVE, EL_EMC_WALL_1, EL_EMC_WALL_2, EL_EMC_WALL_3, @@ -3055,13 +3931,42 @@ void InitElementPropertiesStatic() EL_SIGN_STOP, EL_SIGN_WHEELCHAIR, EL_SIGN_PARKING, - EL_SIGN_ONEWAY, + EL_SIGN_NO_ENTRY, + EL_SIGN_UNUSED_1, + EL_SIGN_GIVE_WAY, + EL_SIGN_ENTRY_FORBIDDEN, + EL_SIGN_EMERGENCY_EXIT, + EL_SIGN_YIN_YANG, + EL_SIGN_UNUSED_2, + EL_SIGN_SPERMS, + EL_SIGN_BULLET, EL_SIGN_HEART, - EL_SIGN_TRIANGLE, - EL_SIGN_ROUND, - EL_SIGN_EXIT, - EL_SIGN_YINYANG, - EL_SIGN_OTHER, + EL_SIGN_CROSS, + EL_SIGN_FRANKIE, + EL_STEEL_EXIT_CLOSED, + EL_STEEL_EXIT_OPEN, + EL_DC_STEELWALL_1_LEFT, + EL_DC_STEELWALL_1_RIGHT, + EL_DC_STEELWALL_1_TOP, + EL_DC_STEELWALL_1_BOTTOM, + EL_DC_STEELWALL_1_HORIZONTAL, + EL_DC_STEELWALL_1_VERTICAL, + EL_DC_STEELWALL_1_TOPLEFT, + EL_DC_STEELWALL_1_TOPRIGHT, + EL_DC_STEELWALL_1_BOTTOMLEFT, + EL_DC_STEELWALL_1_BOTTOMRIGHT, + EL_DC_STEELWALL_1_TOPLEFT_2, + EL_DC_STEELWALL_1_TOPRIGHT_2, + EL_DC_STEELWALL_1_BOTTOMLEFT_2, + EL_DC_STEELWALL_1_BOTTOMRIGHT_2, + EL_DC_STEELWALL_2_LEFT, + EL_DC_STEELWALL_2_RIGHT, + EL_DC_STEELWALL_2_TOP, + EL_DC_STEELWALL_2_BOTTOM, + EL_DC_STEELWALL_2_HORIZONTAL, + EL_DC_STEELWALL_2_VERTICAL, + EL_DC_STEELWALL_2_MIDDLE, + EL_DC_STEELWALL_2_SINGLE, EL_STEELWALL_SLIPPERY, EL_EMC_STEELWALL_1, EL_EMC_STEELWALL_2, @@ -3203,6 +4108,17 @@ void InitElementPropertiesStatic() -1 }; + static int ep_acid_pool[] = + { + EL_ACID_POOL_TOPLEFT, + EL_ACID_POOL_TOPRIGHT, + EL_ACID_POOL_BOTTOMLEFT, + EL_ACID_POOL_BOTTOM, + EL_ACID_POOL_BOTTOMRIGHT, + + -1 + }; + static int ep_keygate[] = { EL_GATE_1, @@ -3241,6 +4157,9 @@ void InitElementPropertiesStatic() EL_EMC_GATE_6_GRAY_ACTIVE, EL_EMC_GATE_7_GRAY_ACTIVE, EL_EMC_GATE_8_GRAY_ACTIVE, + EL_DC_GATE_WHITE, + EL_DC_GATE_WHITE_GRAY, + EL_DC_GATE_WHITE_GRAY_ACTIVE, -1 }; @@ -3274,6 +4193,7 @@ void InitElementPropertiesStatic() EL_PLAYER_2, EL_PLAYER_3, EL_PLAYER_4, + EL_SOKOBAN_FIELD_PLAYER, EL_SP_MURPHY, EL_YAMYAM, EL_YAMYAM_LEFT, @@ -3333,6 +4253,7 @@ void InitElementPropertiesStatic() EL_STEELWALL, EL_AMOEBA_DEAD, EL_QUICKSAND_EMPTY, + EL_QUICKSAND_FAST_EMPTY, EL_STONEBLOCK, EL_ROBOT_WHEEL, EL_KEY_1, @@ -3383,6 +4304,10 @@ void InitElementPropertiesStatic() EL_EMC_GATE_6_GRAY_ACTIVE, EL_EMC_GATE_7_GRAY_ACTIVE, EL_EMC_GATE_8_GRAY_ACTIVE, + EL_DC_GATE_WHITE, + EL_DC_GATE_WHITE_GRAY, + EL_DC_GATE_WHITE_GRAY_ACTIVE, + EL_DC_GATE_FAKE_GRAY, EL_DYNAMITE, EL_EM_DYNAMITE, EL_INVISIBLE_STEELWALL, @@ -3413,6 +4338,8 @@ void InitElementPropertiesStatic() EL_MAGIC_WALL_DEAD, EL_BD_MAGIC_WALL, EL_BD_MAGIC_WALL_DEAD, + EL_DC_MAGIC_WALL, + EL_DC_MAGIC_WALL_DEAD, EL_AMOEBA_TO_DIAMOND, EL_BLOCKED, EL_SP_EMPTY, @@ -3473,13 +4400,40 @@ void InitElementPropertiesStatic() EL_SIGN_STOP, EL_SIGN_WHEELCHAIR, EL_SIGN_PARKING, - EL_SIGN_ONEWAY, + EL_SIGN_NO_ENTRY, + EL_SIGN_UNUSED_1, + EL_SIGN_GIVE_WAY, + EL_SIGN_ENTRY_FORBIDDEN, + EL_SIGN_EMERGENCY_EXIT, + EL_SIGN_YIN_YANG, + EL_SIGN_UNUSED_2, + EL_SIGN_SPERMS, + EL_SIGN_BULLET, EL_SIGN_HEART, - EL_SIGN_TRIANGLE, - EL_SIGN_ROUND, - EL_SIGN_EXIT, - EL_SIGN_YINYANG, - EL_SIGN_OTHER, + EL_SIGN_CROSS, + EL_SIGN_FRANKIE, + EL_DC_STEELWALL_1_LEFT, + EL_DC_STEELWALL_1_RIGHT, + EL_DC_STEELWALL_1_TOP, + EL_DC_STEELWALL_1_BOTTOM, + EL_DC_STEELWALL_1_HORIZONTAL, + EL_DC_STEELWALL_1_VERTICAL, + EL_DC_STEELWALL_1_TOPLEFT, + EL_DC_STEELWALL_1_TOPRIGHT, + EL_DC_STEELWALL_1_BOTTOMLEFT, + EL_DC_STEELWALL_1_BOTTOMRIGHT, + EL_DC_STEELWALL_1_TOPLEFT_2, + EL_DC_STEELWALL_1_TOPRIGHT_2, + EL_DC_STEELWALL_1_BOTTOMLEFT_2, + EL_DC_STEELWALL_1_BOTTOMRIGHT_2, + EL_DC_STEELWALL_2_LEFT, + EL_DC_STEELWALL_2_RIGHT, + EL_DC_STEELWALL_2_TOP, + EL_DC_STEELWALL_2_BOTTOM, + EL_DC_STEELWALL_2_HORIZONTAL, + EL_DC_STEELWALL_2_VERTICAL, + EL_DC_STEELWALL_2_MIDDLE, + EL_DC_STEELWALL_2_SINGLE, EL_STEELWALL_SLIPPERY, EL_EMC_STEELWALL_1, EL_EMC_STEELWALL_2, @@ -3518,6 +4472,7 @@ void InitElementPropertiesStatic() { EL_SAND, EL_LANDMINE, + EL_DC_LANDMINE, EL_TRAP, EL_TRAP_ACTIVE, @@ -3535,6 +4490,7 @@ void InitElementPropertiesStatic() EL_INTERNAL_CASCADE_DC_ACTIVE, EL_INTERNAL_CASCADE_DX_ACTIVE, EL_INTERNAL_CASCADE_CHARS_ACTIVE, + EL_INTERNAL_CASCADE_STEEL_CHARS_ACTIVE, EL_INTERNAL_CASCADE_CE_ACTIVE, EL_INTERNAL_CASCADE_GE_ACTIVE, EL_INTERNAL_CASCADE_REF_ACTIVE, @@ -3555,6 +4511,7 @@ void InitElementPropertiesStatic() EL_INTERNAL_CASCADE_DC, EL_INTERNAL_CASCADE_DX, EL_INTERNAL_CASCADE_CHARS, + EL_INTERNAL_CASCADE_STEEL_CHARS, EL_INTERNAL_CASCADE_CE, EL_INTERNAL_CASCADE_GE, EL_INTERNAL_CASCADE_REF, @@ -3616,6 +4573,7 @@ void InitElementPropertiesStatic() { 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 }, { ep_switchable, EP_SWITCHABLE }, { ep_bd_element, EP_BD_ELEMENT }, { ep_sp_element, EP_SP_ELEMENT }, @@ -3631,6 +4589,7 @@ void InitElementPropertiesStatic() { ep_belt_active, EP_BELT_ACTIVE }, { ep_belt_switch, EP_BELT_SWITCH }, { ep_tube, EP_TUBE }, + { ep_acid_pool, EP_ACID_POOL }, { ep_keygate, EP_KEYGATE }, { ep_amoeboid, EP_AMOEBOID }, { ep_amoebalive, EP_AMOEBALIVE }, @@ -3655,9 +4614,12 @@ void InitElementPropertiesStatic() int i, j, k; /* always start with reliable default values (element has no properties) */ + /* (but never initialize clipboard elements after the very first time) */ + /* (to be able to use clipboard elements between several levels) */ for (i = 0; i < MAX_NUM_ELEMENTS; i++) - for (j = 0; j < NUM_ELEMENT_PROPERTIES; j++) - SET_PROPERTY(i, j, FALSE); + if (!IS_CLIPBOARD_ELEMENT(i) || !clipboard_elements_initialized) + for (j = 0; j < NUM_ELEMENT_PROPERTIES; j++) + SET_PROPERTY(i, j, FALSE); /* set all base element properties from above array definitions */ for (i = 0; element_properties[i].elements != NULL; i++) @@ -3671,6 +4633,12 @@ void InitElementPropertiesStatic() if (HAS_PROPERTY(copy_properties[j][0], i)) for (k = 1; k <= 4; k++) SET_PROPERTY(copy_properties[j][k], i, TRUE); + + /* set static element properties that are not listed in array definitions */ + for (i = EL_STEEL_CHAR_START; i <= EL_STEEL_CHAR_END; i++) + SET_PROPERTY(i, EP_INDESTRUCTIBLE, TRUE); + + clipboard_elements_initialized = TRUE; } void InitElementPropertiesEngine(int engine_version) @@ -3712,22 +4680,22 @@ void InitElementPropertiesEngine(int engine_version) property (which means that conditional property changes must be set to a reliable default value before) */ -#if 1 - /* ---------- recursively resolve group elements ------------------------- */ - - for (i = 0; i < MAX_NUM_ELEMENTS; i++) - for (j = 0; j < NUM_GROUP_ELEMENTS; j++) - element_info[i].in_group[j] = FALSE; - + /* resolve group elements */ for (i = 0; i < NUM_GROUP_ELEMENTS; i++) - resolve_group_element(EL_GROUP_START + i, 0); -#endif + ResolveGroupElement(EL_GROUP_START + i); /* set all special, combined or engine dependent element properties */ for (i = 0; i < MAX_NUM_ELEMENTS; i++) { + /* do not change (already initialized) clipboard elements here */ + if (IS_CLIPBOARD_ELEMENT(i)) + continue; + /* ---------- INACTIVE ------------------------------------------------- */ - SET_PROPERTY(i, EP_INACTIVE, (i >= EL_CHAR_START && i <= EL_CHAR_END)); + SET_PROPERTY(i, EP_INACTIVE, ((i >= EL_CHAR_START && + i <= EL_CHAR_END) || + (i >= EL_STEEL_CHAR_START && + i <= EL_STEEL_CHAR_END))); /* ---------- WALKABLE, PASSABLE, ACCESSIBLE --------------------------- */ SET_PROPERTY(i, EP_WALKABLE, (IS_WALKABLE_OVER(i) || @@ -3781,7 +4749,6 @@ void InitElementPropertiesEngine(int engine_version) !IS_COLLECTIBLE(i))); /* ---------- DRAGONFIRE_PROOF ----------------------------------------- */ - if (IS_HISTORIC_SOLID(i) || i == EL_EXPLOSION) SET_PROPERTY(i, EP_DRAGONFIRE_PROOF, TRUE); else @@ -3904,12 +4871,24 @@ void InitElementPropertiesEngine(int engine_version) { static int ep_em_slippery_wall[] = { - EL_STEELWALL, EL_WALL, + EL_STEELWALL, EL_EXPANDABLE_WALL, EL_EXPANDABLE_WALL_HORIZONTAL, EL_EXPANDABLE_WALL_VERTICAL, EL_EXPANDABLE_WALL_ANY, + EL_EXPANDABLE_STEELWALL_HORIZONTAL, + EL_EXPANDABLE_STEELWALL_VERTICAL, + EL_EXPANDABLE_STEELWALL_ANY, + EL_EXPANDABLE_STEELWALL_GROWING, + -1 + }; + + static int ep_em_explodes_by_fire[] = + { + EL_EM_DYNAMITE, + EL_EM_DYNAMITE_ACTIVE, + EL_MOLE, -1 }; @@ -3922,36 +4901,22 @@ void InitElementPropertiesEngine(int engine_version) SET_PROPERTY(EL_EXPANDABLE_WALL_GROWING, EP_EM_SLIPPERY_WALL, (level.em_slippery_gems && engine_version > VERSION_IDENT(2,0,1,0))); - } -#if 0 - /* set default push delay values (corrected since version 3.0.7-1) */ - if (engine_version < VERSION_IDENT(3,0,7,1)) - { - game.default_push_delay_fixed = 2; - game.default_push_delay_random = 8; - } - else - { - game.default_push_delay_fixed = 8; - game.default_push_delay_random = 8; + /* special EM style explosion behaviour regarding chain reactions */ + for (i = 0; ep_em_explodes_by_fire[i] != -1; i++) + SET_PROPERTY(ep_em_explodes_by_fire[i], EP_EXPLODES_BY_FIRE, + level.em_explodes_by_fire); } -#endif -#if 0 - /* set uninitialized push delay values of custom elements in older levels */ - for (i = 0; i < NUM_CUSTOM_ELEMENTS; i++) - { - int element = EL_CUSTOM_START + i; + /* this is needed because some graphics depend on element properties */ + if (game_status == GAME_MODE_PLAYING) + InitElementGraphicInfo(); +} - if (element_info[element].push_delay_fixed == -1) - element_info[element].push_delay_fixed = game.default_push_delay_fixed; - if (element_info[element].push_delay_random == -1) - element_info[element].push_delay_random = game.default_push_delay_random; - } -#endif +void InitElementPropertiesAfterLoading(int engine_version) +{ + int i; -#if 0 /* set some other uninitialized values of custom elements in older levels */ if (engine_version < VERSION_IDENT(3,1,0,0)) { @@ -3965,72 +4930,23 @@ void InitElementPropertiesEngine(int engine_version) element_info[element].ignition_delay = 8; } } -#endif - -#if 0 - /* set element properties that were handled incorrectly in older levels */ - if (engine_version < VERSION_IDENT(3,1,0,0)) - { - SET_PROPERTY(EL_SP_SNIKSNAK, EP_DONT_COLLIDE_WITH, FALSE); - SET_PROPERTY(EL_SP_ELECTRON, EP_DONT_COLLIDE_WITH, FALSE); - } -#endif - - /* this is needed because some graphics depend on element properties */ - if (game_status == GAME_MODE_PLAYING) - InitElementGraphicInfo(); } -void InitElementPropertiesAfterLoading(int engine_version) +void InitElementPropertiesGfxElement() { int i; -#if 0 - /* set default push delay values (corrected since version 3.0.7-1) */ - if (engine_version < VERSION_IDENT(3,0,7,1)) - { - game.default_push_delay_fixed = 2; - game.default_push_delay_random = 8; - } - else - { - game.default_push_delay_fixed = 8; - game.default_push_delay_random = 8; - } -#endif - -#if 0 - /* set uninitialized push delay values of custom elements in older levels */ - for (i = 0; i < NUM_CUSTOM_ELEMENTS; i++) - { - int element = EL_CUSTOM_START + i; - - if (element_info[element].push_delay_fixed == -1) - element_info[element].push_delay_fixed = game.default_push_delay_fixed; - if (element_info[element].push_delay_random == -1) - element_info[element].push_delay_random = game.default_push_delay_random; - } -#endif - -#if 1 - /* set some other uninitialized values of custom elements in older levels */ - if (engine_version < VERSION_IDENT(3,1,0,0)) + for (i = 0; i < MAX_NUM_ELEMENTS; i++) { - for (i = 0; i < NUM_CUSTOM_ELEMENTS; i++) - { - int element = EL_CUSTOM_START + i; - - element_info[element].access_direction = MV_ALL_DIRECTIONS; + struct ElementInfo *ei = &element_info[i]; - element_info[element].explosion_delay = 17; - element_info[element].ignition_delay = 8; - } + ei->gfx_element = (ei->use_gfx_element ? ei->gfx_element_initial : i); } -#endif } static void InitGlobal() { + int graphic; int i; for (i = 0; i < MAX_NUM_ELEMENTS + 1; i++) @@ -4041,15 +4957,96 @@ static void InitGlobal() element_info[i].token_name = element_name_info[i].token_name; element_info[i].class_name = element_name_info[i].class_name; - element_info[i].editor_description=element_name_info[i].editor_description; + element_info[i].editor_description= element_name_info[i].editor_description; + +#if 0 + printf("%04d: %s\n", i, element_name_info[i].token_name); +#endif + } + + /* create hash from image config list */ + image_config_hash = newSetupFileHash(); + for (i = 0; image_config[i].token != NULL; i++) + setHashEntry(image_config_hash, + image_config[i].token, + image_config[i].value); + + /* create hash from element token list */ + element_token_hash = newSetupFileHash(); + for (i = 0; element_name_info[i].token_name != NULL; i++) + setHashEntry(element_token_hash, + element_name_info[i].token_name, + int2str(i, 0)); + + /* create hash from graphic token list */ + graphic_token_hash = newSetupFileHash(); + for (graphic = 0, i = 0; image_config[i].token != NULL; i++) + if (strSuffix(image_config[i].value, ".pcx") || + strSuffix(image_config[i].value, ".wav") || + strEqual(image_config[i].value, UNDEFINED_FILENAME)) + setHashEntry(graphic_token_hash, + image_config[i].token, + int2str(graphic++, 0)); + + /* create hash from font token list */ + font_token_hash = newSetupFileHash(); + for (i = 0; font_info[i].token_name != NULL; i++) + setHashEntry(font_token_hash, + font_info[i].token_name, + int2str(i, 0)); + + /* always start with reliable default values (all elements) */ + for (i = 0; i < MAX_NUM_ELEMENTS; i++) + ActiveElement[i] = i; + + /* now add all entries that have an active state (active elements) */ + for (i = 0; element_with_active_state[i].element != -1; i++) + { + int element = element_with_active_state[i].element; + int element_active = element_with_active_state[i].element_active; + + ActiveElement[element] = element_active; + } + + /* always start with reliable default values (all buttons) */ + for (i = 0; i < NUM_IMAGE_FILES; i++) + ActiveButton[i] = i; + + /* now add all entries that have an active state (active buttons) */ + for (i = 0; button_with_active_state[i].button != -1; i++) + { + int button = button_with_active_state[i].button; + int button_active = button_with_active_state[i].button_active; + + ActiveButton[button] = button_active; + } + + /* always start with reliable default values (all fonts) */ + for (i = 0; i < NUM_FONTS; i++) + ActiveFont[i] = i; + + /* now add all entries that have an active state (active fonts) */ + for (i = 0; font_with_active_state[i].font_nr != -1; i++) + { + int font = font_with_active_state[i].font_nr; + int font_active = font_with_active_state[i].font_nr_active; + + ActiveFont[font] = font_active; } global.autoplay_leveldir = NULL; global.convert_leveldir = NULL; + global.create_images_dir = NULL; global.frames_per_second = 0; global.fps_slowdown = FALSE; global.fps_slowdown_factor = 1; + + global.border_status = GAME_MODE_MAIN; +#if 0 + global.fading_status = GAME_MODE_MAIN; + global.fading_type = TYPE_ENTER_MENU; +#endif } void Execute_Command(char *command) @@ -4147,7 +5144,7 @@ void Execute_Command(char *command) exit(0); } - else if (strncmp(command, "dump level ", 11) == 0) + else if (strPrefix(command, "dump level ")) { char *filename = &command[11]; @@ -4159,7 +5156,7 @@ void Execute_Command(char *command) exit(0); } - else if (strncmp(command, "dump tape ", 10) == 0) + else if (strPrefix(command, "dump tape ")) { char *filename = &command[10]; @@ -4171,7 +5168,7 @@ void Execute_Command(char *command) exit(0); } - else if (strncmp(command, "autoplay ", 9) == 0) + else if (strPrefix(command, "autoplay ")) { char *str_ptr = getStringCopy(&command[9]); /* read command parameters */ @@ -4207,9 +5204,9 @@ void Execute_Command(char *command) str_ptr++; } } - else if (strncmp(command, "convert ", 8) == 0) + else if (strPrefix(command, "convert ")) { - char *str_copy = getStringCopy(&command[8]); + char *str_copy = getStringCopy(strchr(command, ' ') + 1); char *str_ptr = strchr(str_copy, ' '); global.convert_leveldir = str_copy; @@ -4221,6 +5218,57 @@ void Execute_Command(char *command) global.convert_level_nr = atoi(str_ptr); /* get level_nr value */ } } + else if (strPrefix(command, "create images ")) + { +#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); @@ -4409,13 +5457,17 @@ static void InitArtworkConfig() 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) */ @@ -4440,7 +5492,7 @@ void InitGfx() 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")) + else if (strEqual(&image_config[i].token[len_font_token], ".height")) font_initial[j].height = atoi(image_config[i].value); } } @@ -4456,9 +5508,11 @@ void InitGfx() Error(ERR_EXIT, "cannot get filename for '%s'", CONFIG_TOKEN_FONT_INITIAL); /* create additional image buffers for double-buffering and cross-fading */ - bitmap_db_title = CreateBitmap(WIN_XSIZE, WIN_YSIZE, DEFAULT_DEPTH); + 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, @@ -4466,7 +5520,9 @@ void InitGfx() bitmap_db_field); InitGfxDoor1Info(DX, DY, DXSIZE, DYSIZE); InitGfxDoor2Info(VX, VY, VXSIZE, VYSIZE); + InitGfxWindowInfo(WIN_XSIZE, WIN_YSIZE); InitGfxScrollbufferInfo(FXSIZE, FYSIZE); + InitGfxCustomArtworkInfo(); bitmap_font_initial = LoadCustomImage(filename_font_initial); @@ -4475,10 +5531,111 @@ void InitGfx() 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); - DrawInitText("Loading graphics:", 120, FC_GREEN); + 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() @@ -4493,14 +5650,17 @@ void InitGfxBackground() { int x, y; - drawto = backbuffer; 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++) @@ -4516,15 +5676,39 @@ static void InitLevelInfo() LoadLevelSetup_SeriesInfo(); /* last played level info */ } -void InitLevelArtworkInfo() +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, @@ -4534,16 +5718,35 @@ static void InitImages() leveldir_current->graphics_path); #endif + UPDATE_BUSY_STATE(); + ReloadCustomImages(); + print_timestamp_time("ReloadCustomImages"); + + UPDATE_BUSY_STATE(); LoadCustomElementDescriptions(); - LoadSpecialMenuDesignSettings(); + 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; @@ -4551,11 +5754,18 @@ static void InitSound(char *identifier) 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; @@ -4563,7 +5773,12 @@ static void InitMusic(char *identifier) setLevelArtworkDir(artwork.mus_first); InitReloadCustomMusic(identifier); + print_timestamp_time("InitReloadCustomMusic"); + ReinitializeMusic(); + print_timestamp_time("ReinitializeMusic"); + + print_timestamp_done("InitMusic"); } void InitNetworkServer() @@ -4589,6 +5804,124 @@ void InitNetworkServer() #endif } +static boolean CheckArtworkConfigForCustomElements(char *filename) +{ + SetupFileHash *setup_file_hash; + boolean redefined_ce_found = FALSE; + + /* !!! CACHE THIS BY USING HASH 'filename' => 'true/false' !!! */ + + if ((setup_file_hash = loadSetupFileHash(filename)) != NULL) + { + BEGIN_HASH_ITERATION(setup_file_hash, itr) + { + char *token = HASH_ITERATION_TOKEN(itr); + + if (strPrefix(token, "custom_")) + { + redefined_ce_found = TRUE; + + break; + } + } + END_HASH_ITERATION(setup_file_hash, itr) + + freeSetupFileHash(setup_file_hash); + } + + return redefined_ce_found; +} + +static boolean CheckArtworkTypeForRedefinedCustomElements(int type) +{ + char *filename_base, *filename_local; + boolean redefined_ce_found = FALSE; + + setLevelArtworkDir(ARTWORK_FIRST_NODE(artwork, type)); + +#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, type)); +#endif + + /* first look for special artwork configured in level series config */ + filename_base = getCustomArtworkLevelConfigFilename(type); + +#if 0 + printf("::: filename_base == '%s'\n", filename_base); +#endif + + if (fileExists(filename_base)) + redefined_ce_found |= CheckArtworkConfigForCustomElements(filename_base); + + filename_local = getCustomArtworkConfigFilename(type); + +#if 0 + printf("::: filename_local == '%s'\n", filename_local); +#endif + + if (filename_local != NULL && !strEqual(filename_base, filename_local)) + redefined_ce_found |= CheckArtworkConfigForCustomElements(filename_local); + +#if 0 + printf("::: redefined_ce_found == %d\n", redefined_ce_found); +#endif + + return redefined_ce_found; +} + +static void InitOverrideArtwork() +{ + boolean redefined_ce_found = FALSE; + + /* to check if this level set redefines any CEs, do not use overriding */ + gfx.override_level_graphics = FALSE; + gfx.override_level_sounds = FALSE; + gfx.override_level_music = FALSE; + + /* now check if this level set has definitions for custom elements */ + if (setup.override_level_graphics == AUTO || + setup.override_level_sounds == AUTO || + setup.override_level_music == AUTO) + redefined_ce_found = + (CheckArtworkTypeForRedefinedCustomElements(ARTWORK_TYPE_GRAPHICS) | + CheckArtworkTypeForRedefinedCustomElements(ARTWORK_TYPE_SOUNDS) | + CheckArtworkTypeForRedefinedCustomElements(ARTWORK_TYPE_MUSIC)); + +#if 0 + printf("::: redefined_ce_found == %d\n", redefined_ce_found); +#endif + + if (redefined_ce_found) + { + /* this level set has CE definitions: change "AUTO" to "FALSE" */ + gfx.override_level_graphics = (setup.override_level_graphics == TRUE); + gfx.override_level_sounds = (setup.override_level_sounds == TRUE); + gfx.override_level_music = (setup.override_level_music == TRUE); + } + else + { + /* this level set has no CE definitions: change "AUTO" to "TRUE" */ + gfx.override_level_graphics = (setup.override_level_graphics != FALSE); + gfx.override_level_sounds = (setup.override_level_sounds != FALSE); + gfx.override_level_music = (setup.override_level_music != FALSE); + } + +#if 0 + printf("::: => %d, %d, %d\n", + gfx.override_level_graphics, + gfx.override_level_sounds, + gfx.override_level_music); +#endif +} + static char *getNewArtworkIdentifier(int type) { static char *leveldir_current_identifier[3] = { NULL, NULL, NULL }; @@ -4596,7 +5929,11 @@ static char *getNewArtworkIdentifier(int type) static boolean last_has_level_artwork_set[3] = { FALSE, FALSE, FALSE }; static boolean initialized[3] = { FALSE, FALSE, FALSE }; TreeInfo *artwork_first_node = ARTWORK_FIRST_NODE(artwork, type); +#if 1 + boolean setup_override_artwork = GFX_OVERRIDE_ARTWORK(type); +#else boolean setup_override_artwork = SETUP_OVERRIDE_ARTWORK(setup, type); +#endif char *setup_artwork_set = SETUP_ARTWORK_SET(setup, type); char *leveldir_identifier = leveldir_current->identifier; #if 1 @@ -4704,13 +6041,16 @@ static char *getNewArtworkIdentifier(int type) void ReloadCustomArtwork(int force_reload) { + int last_game_status = game_status; /* save current game status */ char *gfx_new_identifier; char *snd_new_identifier; char *mus_new_identifier; boolean force_reload_gfx = (force_reload & (1 << ARTWORK_TYPE_GRAPHICS)); boolean force_reload_snd = (force_reload & (1 << ARTWORK_TYPE_SOUNDS)); boolean force_reload_mus = (force_reload & (1 << ARTWORK_TYPE_MUSIC)); - boolean redraw_screen = FALSE; + boolean reload_needed; + + InitOverrideArtwork(); force_reload_gfx |= AdjustGraphicsForEMC(); @@ -4718,6 +6058,34 @@ void ReloadCustomArtwork(int force_reload) snd_new_identifier = getNewArtworkIdentifier(ARTWORK_TYPE_SOUNDS); mus_new_identifier = getNewArtworkIdentifier(ARTWORK_TYPE_MUSIC); + reload_needed = (gfx_new_identifier != NULL || force_reload_gfx || + snd_new_identifier != NULL || force_reload_snd || + mus_new_identifier != NULL || force_reload_mus); + + if (!reload_needed) + return; + + print_timestamp_init("ReloadCustomArtwork"); + + game_status = GAME_MODE_LOADING; + + FadeOut(REDRAW_ALL); + +#if 1 + ClearRectangle(drawto, 0, 0, WIN_XSIZE, WIN_YSIZE); +#else + ClearRectangle(window, 0, 0, WIN_XSIZE, WIN_YSIZE); +#endif + print_timestamp_time("ClearRectangle"); + +#if 0 + printf("::: fading in ... %d\n", fading.fade_mode); +#endif + FadeIn(REDRAW_ALL); +#if 0 + printf("::: done\n"); +#endif + if (gfx_new_identifier != NULL || force_reload_gfx) { #if 0 @@ -4728,43 +6096,62 @@ void ReloadCustomArtwork(int force_reload) leveldir_current->graphics_set); #endif - ClearRectangle(window, 0, 0, WIN_XSIZE, WIN_YSIZE); - InitImages(); - - redraw_screen = TRUE; + print_timestamp_time("InitImages"); } if (snd_new_identifier != NULL || force_reload_snd) { - ClearRectangle(window, 0, 0, WIN_XSIZE, WIN_YSIZE); - InitSound(snd_new_identifier); - - redraw_screen = TRUE; + print_timestamp_time("InitSound"); } if (mus_new_identifier != NULL || force_reload_mus) { - ClearRectangle(window, 0, 0, WIN_XSIZE, WIN_YSIZE); - InitMusic(mus_new_identifier); - - redraw_screen = TRUE; + print_timestamp_time("InitMusic"); } - if (redraw_screen) - { + game_status = last_game_status; /* restore current game status */ + +#if 0 + printf("::: ----------------DELAY 1 ...\n"); + Delay(3000); +#endif + +#if 0 + printf("::: FadeOut @ ReloadCustomArtwork ...\n"); +#endif + FadeOut(REDRAW_ALL); +#if 0 + printf("::: FadeOut @ ReloadCustomArtwork done\n"); +#endif + + RedrawBackground(); + + /* force redraw of (open or closed) door graphics */ + SetDoorState(DOOR_OPEN_ALL); + CloseDoor(DOOR_CLOSE_ALL | DOOR_NO_DELAY); + +#if 1 #if 1 - RedrawBackground(); +#if 1 + FadeSetEnterScreen(); + FadeSkipNextFadeOut(); + // FadeSetDisabled(); +#else + FadeSkipNext(); +#endif #else - InitGfxBackground(); + fading = fading_none; +#endif #endif - /* force redraw of (open or closed) door graphics */ - SetDoorState(DOOR_OPEN_ALL); - CloseDoor(DOOR_CLOSE_ALL | DOOR_NO_DELAY); - } +#if 0 + redraw_mask = REDRAW_ALL; +#endif + + print_timestamp_done("ReloadCustomArtwork"); } void KeyboardAutoRepeatOffUnlessAutoplay() @@ -4780,6 +6167,10 @@ void KeyboardAutoRepeatOffUnlessAutoplay() void OpenAll() { + print_timestamp_init("OpenAll"); + + game_status = GAME_MODE_LOADING; + InitGlobal(); /* initialize some global variables */ if (options.execute_command) @@ -4807,30 +6198,55 @@ void OpenAll() InitCounter(); InitRND(NEW_RANDOMIZE); - InitSimpleRND(NEW_RANDOMIZE); + InitSimpleRandom(NEW_RANDOMIZE); InitJoysticks(); + print_timestamp_time("[pre-video]"); + InitVideoDisplay(); - InitVideoBuffer(&backbuffer, &window, WIN_XSIZE, WIN_YSIZE, DEFAULT_DEPTH, - setup.fullscreen); + InitVideoBuffer(WIN_XSIZE, WIN_YSIZE, DEFAULT_DEPTH, setup.fullscreen); InitEventFilter(FilterMouseMotionEvents); InitElementPropertiesStatic(); InitElementPropertiesEngine(GAME_VERSION_ACTUAL); + InitElementPropertiesGfxElement(); + + print_timestamp_time("[post-video]"); InitGfx(); + print_timestamp_time("InitGfx"); + InitLevelInfo(); + print_timestamp_time("InitLevelInfo"); + InitLevelArtworkInfo(); + print_timestamp_time("InitLevelArtworkInfo"); + + InitOverrideArtwork(); /* needs to know current level directory */ + print_timestamp_time("InitOverrideArtwork"); InitImages(); /* needs to know current level directory */ + print_timestamp_time("InitImages"); + InitSound(NULL); /* needs to know current level directory */ + print_timestamp_time("InitSound"); + InitMusic(NULL); /* needs to know current level directory */ + print_timestamp_time("InitMusic"); InitGfxBackground(); +#if 1 + em_open_all(); +#endif + +#if 1 + sp_open_all(); +#endif + if (global.autoplay_leveldir) { AutoPlayTape(); @@ -4841,13 +6257,27 @@ void OpenAll() ConvertLevels(); return; } + else if (global.create_images_dir) + { + CreateLevelSketchImages(); + return; + } game_status = GAME_MODE_MAIN; #if 1 - em_open_all(); + FadeSetEnterScreen(); + if (!(fading.fade_mode & FADE_TYPE_TRANSFORM)) + FadeSkipNextFadeOut(); + // FadeSetDisabled(); +#else + fading = fading_none; #endif + print_timestamp_time("[post-artwork]"); + + print_timestamp_done("OpenAll"); + DrawMainMenu(); InitNetworkServer(); @@ -4864,6 +6294,10 @@ void CloseAllAndExit(int exit_value) em_close_all(); #endif +#if 1 + sp_close_all(); +#endif + FreeAllImages(); #if defined(TARGET_SDL) @@ -4874,5 +6308,8 @@ void CloseAllAndExit(int exit_value) CloseVideoDisplay(); ClosePlatformDependentStuff(); + if (exit_value != 0) + NotifyUserAboutErrorFile(); + exit(exit_value); }