X-Git-Url: https://git.artsoft.org/?p=rocksndiamonds.git;a=blobdiff_plain;f=src%2Finit.c;h=abef35e1a92821bb291d387ccc9bafde0dfe30eb;hp=ae1ada3a53b39b2488baf49d300e846436e7c24d;hb=18863a5655e9e07d548e2d673e7f82336703c8fb;hpb=04575ef0d5f1551715fca1d1def889fd63b5c3ad diff --git a/src/init.c b/src/init.c index ae1ada3a..abef35e1 100644 --- a/src/init.c +++ b/src/init.c @@ -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(); @@ -111,6 +271,12 @@ void InitGadgets() 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); } @@ -163,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_TITLE && 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]; @@ -180,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; @@ -190,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; } @@ -232,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; @@ -262,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; @@ -270,6 +481,45 @@ 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!) */ @@ -367,7 +617,8 @@ void InitFontGraphicInfo() } } - InitFontInfo(font_bitmap_info, num_font_bitmaps, getFontBitmapID); + InitFontInfo(font_bitmap_info, num_font_bitmaps, + getFontBitmapID, getFontFromToken); } void InitElementGraphicInfo() @@ -395,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++) { @@ -453,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; @@ -569,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++) @@ -628,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++) { @@ -779,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 */ @@ -815,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 @@ -846,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 @@ -859,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; } @@ -880,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)) @@ -909,6 +1250,7 @@ static int get_graphic_parameter_value(char *value_raw, char *suffix, int type) x++; } +#endif return -1; } @@ -929,8 +1271,266 @@ static int get_scaled_graphic_height(int graphic) return original_height * scale_up_factor; } +static void set_graphic_parameters_ext(int graphic, int *parameter, + Bitmap *src_bitmap) +{ + struct GraphicInfo *g = &graphic_info[graphic]; + int anim_frames_per_row = 1, anim_frames_per_col = 1; + int anim_frames_per_line = 1; + + /* 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->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 + +#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) + g->src_x = parameter[GFX_ARG_XPOS] * TILEX; + if (parameter[GFX_ARG_YPOS] != ARG_UNDEFINED_VALUE) + 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) + g->src_x = parameter[GFX_ARG_X]; + if (parameter[GFX_ARG_Y] != ARG_UNDEFINED_VALUE) + g->src_y = parameter[GFX_ARG_Y]; + + /* optional width and height of each animation frame */ + if (parameter[GFX_ARG_WIDTH] != ARG_UNDEFINED_VALUE) + g->width = parameter[GFX_ARG_WIDTH]; + if (parameter[GFX_ARG_HEIGHT] != ARG_UNDEFINED_VALUE) + 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) + 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]; +} + 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); @@ -972,10 +1572,12 @@ static void set_graphic_parameters(int graphic) 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 @@ -1162,7 +1764,9 @@ static void set_graphic_parameters(int graphic) 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 */ + /* 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) @@ -1171,8 +1775,13 @@ static void set_graphic_parameters(int graphic) 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) @@ -1192,18 +1801,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]; } @@ -1240,8 +1849,8 @@ static void InitGraphicInfo() IMG_BACKGROUND_ENVELOPE_4, IMG_BACKGROUND, + IMG_BACKGROUND_TITLE_INITIAL, IMG_BACKGROUND_TITLE, - IMG_BACKGROUND_MESSAGE, IMG_BACKGROUND_MAIN, IMG_BACKGROUND_LEVELS, IMG_BACKGROUND_SCORES, @@ -1344,21 +1953,21 @@ static void InitGraphicInfo() 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]; } @@ -1372,21 +1981,21 @@ static void InitGraphicInfo() 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]; } @@ -1590,7 +2199,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() @@ -1803,21 +2412,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() @@ -1965,7 +2589,7 @@ boolean getBitfieldProperty(int *bitfield, int property_bit_nr, int element) return FALSE; } -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; @@ -1989,10 +2613,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++) @@ -2003,7 +2630,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; @@ -2012,8 +2639,15 @@ static void resolve_group_element(int group_element, int recursion_depth) } } +void ResolveGroupElement(int group_element) +{ + ResolveGroupElementExt(group_element, 0); +} + void InitElementPropertiesStatic() { + static boolean clipboard_elements_initialized = FALSE; + static int ep_diggable[] = { EL_SAND, @@ -2203,8 +2837,12 @@ void InitElementPropertiesStatic() 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, @@ -2527,10 +3165,16 @@ void InitElementPropertiesStatic() 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, @@ -3457,6 +4101,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, @@ -3531,6 +4186,7 @@ void InitElementPropertiesStatic() EL_PLAYER_2, EL_PLAYER_3, EL_PLAYER_4, + EL_SOKOBAN_FIELD_PLAYER, EL_SP_MURPHY, EL_YAMYAM, EL_YAMYAM_LEFT, @@ -3926,6 +4582,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 }, @@ -3950,9 +4607,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++) @@ -3970,6 +4630,8 @@ void InitElementPropertiesStatic() /* 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) @@ -4011,18 +4673,17 @@ void InitElementPropertiesEngine(int engine_version) property (which means that conditional property changes must be set to a reliable default value before) */ - /* ---------- 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); + 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) || @@ -4216,6 +4877,14 @@ void InitElementPropertiesEngine(int engine_version) -1 }; + static int ep_em_explodes_by_fire[] = + { + EL_EM_DYNAMITE, + EL_EM_DYNAMITE_ACTIVE, + EL_MOLE, + -1 + }; + /* special EM style gems behaviour */ for (i = 0; ep_em_slippery_wall[i] != -1; i++) SET_PROPERTY(ep_em_slippery_wall[i], EP_EM_SLIPPERY_WALL, @@ -4225,6 +4894,11 @@ 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))); + + /* 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); } /* this is needed because some graphics depend on element properties */ @@ -4251,8 +4925,21 @@ void InitElementPropertiesAfterLoading(int engine_version) } } +void InitElementPropertiesGfxElement() +{ + int i; + + for (i = 0; i < MAX_NUM_ELEMENTS; i++) + { + struct ElementInfo *ei = &element_info[i]; + + ei->gfx_element = (ei->use_gfx_element ? ei->gfx_element_initial : i); + } +} + static void InitGlobal() { + int graphic; int i; for (i = 0; i < MAX_NUM_ELEMENTS + 1; i++) @@ -4263,19 +4950,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) @@ -4373,7 +5137,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]; @@ -4385,7 +5149,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]; @@ -4397,7 +5161,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 */ @@ -4433,9 +5197,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; @@ -4447,6 +5211,18 @@ 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) @@ -4674,12 +5450,15 @@ 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; @@ -4706,7 +5485,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); } } @@ -4726,6 +5505,7 @@ void InitGfx() 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, @@ -4733,7 +5513,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); @@ -4753,6 +5535,100 @@ void InitGfx() DrawInitText(PROGRAM_WEBSITE_STRING, WIN_YSIZE - 20 - font_height, FC_RED); DrawInitText("Loading graphics", 120, FC_GREEN); + +#if 1 +#if 1 + /* initialize busy animation with default values */ + int parameter[NUM_GFX_ARGS]; + for (i = 0; i < NUM_GFX_ARGS; i++) + parameter[i] = get_graphic_parameter_value(image_config_suffix[i].value, + image_config_suffix[i].token, + image_config_suffix[i].type); +#if 0 + for (i = 0; i < NUM_GFX_ARGS; i++) + printf("::: '%s' => %d\n", image_config_suffix[i].token, parameter[i]); +#endif +#endif + + /* determine settings for busy animation (when displaying startup messages) */ + for (i = 0; image_config[i].token != NULL; i++) + { + char *anim_token = CONFIG_TOKEN_GLOBAL_BUSY; + int len_anim_token = strlen(anim_token); + + if (strEqual(image_config[i].token, anim_token)) + filename_anim_initial = image_config[i].value; + else if (strlen(image_config[i].token) > len_anim_token && + strncmp(image_config[i].token, anim_token, len_anim_token) == 0) + { +#if 1 + for (j = 0; image_config_suffix[j].token != NULL; j++) + { + if (strEqual(&image_config[i].token[len_anim_token], + image_config_suffix[j].token)) + parameter[j] = + get_graphic_parameter_value(image_config[i].value, + image_config_suffix[j].token, + image_config_suffix[j].type); + } +#else + if (strEqual(&image_config[i].token[len_anim_token], ".x")) + anim_initial.src_x = atoi(image_config[i].value); + else if (strEqual(&image_config[i].token[len_anim_token], ".y")) + anim_initial.src_y = atoi(image_config[i].value); + else if (strEqual(&image_config[i].token[len_anim_token], ".width")) + anim_initial.width = atoi(image_config[i].value); + else if (strEqual(&image_config[i].token[len_anim_token], ".height")) + anim_initial.height = atoi(image_config[i].value); + else if (strEqual(&image_config[i].token[len_anim_token], ".frames")) + anim_initial.anim_frames = atoi(image_config[i].value); + else if (strEqual(&image_config[i].token[len_anim_token], + ".frames_per_line")) + anim_initial.anim_frames_per_line = atoi(image_config[i].value); + else if (strEqual(&image_config[i].token[len_anim_token], ".delay")) + anim_initial.anim_delay = atoi(image_config[i].value); +#endif + } + } + +#if defined(CREATE_SPECIAL_EDITION_RND_JUE) + filename_anim_initial = "loading.pcx"; + + parameter[GFX_ARG_X] = 0; + parameter[GFX_ARG_Y] = 0; + parameter[GFX_ARG_WIDTH] = 128; + parameter[GFX_ARG_HEIGHT] = 40; + parameter[GFX_ARG_FRAMES] = 32; + parameter[GFX_ARG_DELAY] = 4; + parameter[GFX_ARG_FRAMES_PER_LINE] = ARG_UNDEFINED_VALUE; +#endif + + if (filename_anim_initial == NULL) /* should not happen */ + Error(ERR_EXIT, "cannot get filename for '%s'", CONFIG_TOKEN_GLOBAL_BUSY); + + anim_initial.bitmap = LoadCustomImage(filename_anim_initial); + + graphic_info = &anim_initial; /* graphic == 0 => anim_initial */ + + set_graphic_parameters_ext(0, parameter, anim_initial.bitmap); + +#if 0 + printf("::: INIT_GFX: anim_frames_per_line == %d [%d / %d] [%d, %d]\n", + graphic_info[0].anim_frames_per_line, + get_scaled_graphic_width(0), + graphic_info[0].width, + getOriginalImageWidthFromImageID(0), + graphic_info[0].scale_up_factor); +#endif + + graphic_info = graphic_info_last; + + init.busy.width = anim_initial.width; + init.busy.height = anim_initial.height; + + InitMenuDesignSettings_Static(); + InitGfxDrawBusyAnimFunction(DrawInitAnim); +#endif } void RedrawBackground() @@ -4770,10 +5646,14 @@ void InitGfxBackground() 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++) @@ -4789,15 +5669,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, @@ -4807,16 +5711,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; @@ -4824,11 +5747,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; @@ -4836,7 +5766,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() @@ -4862,6 +5797,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 }; @@ -4869,7 +5922,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 @@ -4977,13 +6034,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(); @@ -4991,6 +6051,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 @@ -5001,39 +6089,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) - { - RedrawBackground(); + game_status = last_game_status; /* restore current game status */ - /* force redraw of (open or closed) door graphics */ - SetDoorState(DOOR_OPEN_ALL); - CloseDoor(DOOR_CLOSE_ALL | DOOR_NO_DELAY); - } +#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 +#if 1 + FadeSetEnterScreen(); + FadeSkipNextFadeOut(); + // FadeSetDisabled(); +#else + FadeSkipNext(); +#endif +#else + fading = fading_none; +#endif +#endif + +#if 0 + redraw_mask = REDRAW_ALL; +#endif + + print_timestamp_done("ReloadCustomArtwork"); } void KeyboardAutoRepeatOffUnlessAutoplay() @@ -5049,6 +6160,10 @@ void KeyboardAutoRepeatOffUnlessAutoplay() void OpenAll() { + print_timestamp_init("OpenAll"); + + game_status = GAME_MODE_LOADING; + InitGlobal(); /* initialize some global variables */ if (options.execute_command) @@ -5080,6 +6195,8 @@ void OpenAll() InitJoysticks(); + print_timestamp_time("[pre-video]"); + InitVideoDisplay(); InitVideoBuffer(WIN_XSIZE, WIN_YSIZE, DEFAULT_DEPTH, setup.fullscreen); @@ -5087,18 +6204,31 @@ void OpenAll() InitElementPropertiesStatic(); InitElementPropertiesEngine(GAME_VERSION_ACTUAL); + InitElementPropertiesGfxElement(); + + print_timestamp_time("[post-video]"); InitGfx(); - // debug_print_timestamp(0, "INIT"); + print_timestamp_time("InitGfx"); + InitLevelInfo(); - // debug_print_timestamp(0, "TIME InitLevelInfo: "); + print_timestamp_time("InitLevelInfo"); + InitLevelArtworkInfo(); - // debug_print_timestamp(0, "TIME 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(); @@ -5106,6 +6236,10 @@ void OpenAll() em_open_all(); #endif +#if 1 + sp_open_all(); +#endif + if (global.autoplay_leveldir) { AutoPlayTape(); @@ -5116,9 +6250,27 @@ void OpenAll() ConvertLevels(); return; } + else if (global.create_images_dir) + { + CreateLevelSketchImages(); + return; + } game_status = GAME_MODE_MAIN; +#if 1 + 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(); @@ -5135,6 +6287,10 @@ void CloseAllAndExit(int exit_value) em_close_all(); #endif +#if 1 + sp_close_all(); +#endif + FreeAllImages(); #if defined(TARGET_SDL)