-/***********************************************************
-* Rocks'n'Diamonds -- McDuffin Strikes Back! *
-*----------------------------------------------------------*
-* (c) 1995-2006 Artsoft Entertainment *
-* Holger Schemel *
-* Detmolder Strasse 189 *
-* 33604 Bielefeld *
-* Germany *
-* e-mail: info@artsoft.org *
-*----------------------------------------------------------*
-* init.c *
-***********************************************************/
+// ============================================================================
+// Rocks'n'Diamonds - McDuffin Strikes Back!
+// ----------------------------------------------------------------------------
+// (c) 1995-2014 by Artsoft Entertainment
+// Holger Schemel
+// info@artsoft.org
+// http://www.artsoft.org/
+// ----------------------------------------------------------------------------
+// init.c
+// ============================================================================
#include "libgame/libgame.h"
#include "files.h"
#include "network.h"
#include "netserv.h"
-#include "cartoons.h"
+#include "anim.h"
#include "config.h"
#include "conf_e2g.c" /* include auto-generated data structure definitions */
#define CONFIG_TOKEN_FONT_INITIAL "font.initial"
+#define CONFIG_TOKEN_GLOBAL_BUSY "global.busy"
static struct FontBitmapInfo font_initial[NUM_INITIAL_FONTS];
+static struct GraphicInfo anim_initial;
static int copy_properties[][5] =
{
}
};
-void FreeGadgets()
+
+/* forward declaration for internal use */
+static int get_graphic_parameter_value(char *, char *, int);
+
+
+static void DrawInitAnim(void)
+{
+ struct GraphicInfo *graphic_info_last = graphic_info;
+ int graphic = 0;
+ static unsigned int action_delay = 0;
+ unsigned int action_delay_value = GameFrameDelay;
+ int sync_frame = FrameCounter;
+ int x, y;
+
+ /* prevent OS (Windows) from complaining about program not responding */
+ CheckQuitEvent();
+
+ if (game_status != GAME_MODE_LOADING)
+ return;
+
+ if (anim_initial.bitmap == NULL || window == NULL)
+ return;
+
+ if (!DelayReached(&action_delay, action_delay_value))
+ return;
+
+ if (init_last.busy.x == -1)
+ init_last.busy.x = WIN_XSIZE / 2;
+ if (init_last.busy.y == -1)
+ init_last.busy.y = WIN_YSIZE / 2;
+
+ x = ALIGNED_TEXT_XPOS(&init_last.busy);
+ y = ALIGNED_TEXT_YPOS(&init_last.busy);
+
+ graphic_info = &anim_initial; /* graphic == 0 => anim_initial */
+
+ if (sync_frame % anim_initial.anim_delay == 0)
+ {
+ 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);
+
+ getFixedGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
+ BlitBitmap(src_bitmap, window, src_x, src_y, width, height, x, y);
+ }
+
+ graphic_info = graphic_info_last;
+
+ FrameCounter++;
+}
+
+static void DrawProgramInfo(void)
+{
+ int font1_nr = FC_YELLOW;
+ int font2_nr = FC_RED;
+ int font2_height = getFontHeight(font2_nr);
+ int ypos1 = 20;
+ int ypos2 = 50;
+ int ypos3 = WIN_YSIZE - 20 - font2_height;
+
+ DrawInitText(getProgramInitString(), ypos1, font1_nr);
+ DrawInitText(setup.internal.program_copyright, ypos2, font2_nr);
+ DrawInitText(setup.internal.program_website, ypos3, font2_nr);
+}
+
+static void FreeGadgets(void)
{
FreeLevelEditorGadgets();
FreeGameButtons();
FreeScreenGadgets();
}
-void InitGadgets()
+void InitGadgets(void)
{
static boolean gadgets_initialized = FALSE;
gadgets_initialized = TRUE;
}
-inline void InitElementSmallImagesScaledUp(int graphic)
+inline static void InitElementSmallImagesScaledUp(int graphic)
{
- CreateImageWithSmallImages(graphic, graphic_info[graphic].scale_up_factor);
+ struct GraphicInfo *g = &graphic_info[graphic];
+
+ // create small and game tile sized bitmaps (and scale up, if needed)
+ CreateImageWithSmallImages(graphic, g->scale_up_factor, g->tile_size);
}
-void InitElementSmallImages()
+static void InitElementSmallImages(void)
{
+ print_timestamp_init("InitElementSmallImages");
+
static int special_graphics[] =
{
+ IMG_FLAMES_1_LEFT,
+ IMG_FLAMES_2_LEFT,
+ IMG_FLAMES_3_LEFT,
+ IMG_FLAMES_1_RIGHT,
+ IMG_FLAMES_2_RIGHT,
+ IMG_FLAMES_3_RIGHT,
+ IMG_FLAMES_1_UP,
+ IMG_FLAMES_2_UP,
+ IMG_FLAMES_3_UP,
+ IMG_FLAMES_1_DOWN,
+ IMG_FLAMES_2_DOWN,
+ IMG_FLAMES_3_DOWN,
IMG_EDITOR_ELEMENT_BORDER,
IMG_EDITOR_ELEMENT_BORDER_INPUT,
IMG_EDITOR_CASCADE_LIST,
int num_property_mappings = getImageListPropertyMappingSize();
int i;
- /* initialize normal images from static configuration */
+ print_timestamp_time("getImageListPropertyMapping/Size");
+
+ print_timestamp_init("InitElementSmallImagesScaledUp (1)");
+ /* initialize normal element images from static configuration */
for (i = 0; element_to_graphic[i].element > -1; i++)
InitElementSmallImagesScaledUp(element_to_graphic[i].graphic);
+ print_timestamp_done("InitElementSmallImagesScaledUp (1)");
- /* initialize special images from static configuration */
+ /* initialize special element images from static configuration */
for (i = 0; element_to_special_graphic[i].element > -1; i++)
InitElementSmallImagesScaledUp(element_to_special_graphic[i].graphic);
+ print_timestamp_time("InitElementSmallImagesScaledUp (2)");
- /* initialize images from dynamic configuration (may be elements or other) */
+ /* initialize element images from dynamic configuration */
for (i = 0; i < num_property_mappings; i++)
- InitElementSmallImagesScaledUp(property_mapping[i].artwork_index);
+ if (property_mapping[i].base_index < MAX_NUM_ELEMENTS)
+ InitElementSmallImagesScaledUp(property_mapping[i].artwork_index);
+ print_timestamp_time("InitElementSmallImagesScaledUp (3)");
- /* initialize special images from above list (non-element images) */
+ /* initialize special non-element images from above list */
for (i = 0; special_graphics[i] > -1; i++)
InitElementSmallImagesScaledUp(special_graphics[i]);
+ print_timestamp_time("InitElementSmallImagesScaledUp (4)");
+
+ print_timestamp_done("InitElementSmallImages");
}
-void InitScaledImages()
+inline static void InitScaledImagesScaledUp(int graphic)
{
+ struct GraphicInfo *g = &graphic_info[graphic];
+
+ ScaleImage(graphic, g->scale_up_factor);
+}
+
+static void InitScaledImages(void)
+{
+ struct PropertyMapping *property_mapping = getImageListPropertyMapping();
+ int num_property_mappings = getImageListPropertyMappingSize();
int i;
/* scale normal images from static configuration, if not already scaled */
for (i = 0; i < NUM_IMAGE_FILES; i++)
- ScaleImage(i, graphic_info[i].scale_up_factor);
+ InitScaledImagesScaledUp(i);
+
+ /* scale images from dynamic configuration, if not already scaled */
+ for (i = 0; i < num_property_mappings; i++)
+ InitScaledImagesScaledUp(property_mapping[i].artwork_index);
+}
+
+static void InitBitmapPointers(void)
+{
+ int num_images = getImageListSize();
+ int i;
+
+ // standard size bitmap may have changed -- update default bitmap pointer
+ for (i = 0; i < num_images; i++)
+ if (graphic_info[i].bitmaps)
+ graphic_info[i].bitmap = graphic_info[i].bitmaps[IMG_BITMAP_STANDARD];
+}
+
+void InitImageTextures(void)
+{
+ int i, j, k;
+
+ FreeAllImageTextures();
+
+ for (i = IMG_GLOBAL_BORDER_FIRST; i <= IMG_GLOBAL_BORDER_LAST; i++)
+ CreateImageTextures(i);
+
+ for (i = 0; i < MAX_NUM_TOONS; i++)
+ CreateImageTextures(IMG_TOON_1 + i);
+
+ for (i = 0; i < NUM_GLOBAL_ANIMS; i++)
+ {
+ for (j = 0; j < NUM_GLOBAL_ANIM_PARTS_ALL; j++)
+ {
+ for (k = 0; k < NUM_SPECIAL_GFX_ARGS; k++)
+ {
+ int graphic = global_anim_info[i].graphic[j][k];
+
+ if (graphic == IMG_UNDEFINED)
+ continue;
+
+ CreateImageTextures(graphic);
+ }
+ }
+ }
}
#if 1
}
#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;
+ /* (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 (special != -1)
return font_info[font_nr].special_bitmap_id[special];
static int getFontFromToken(char *token)
{
- int i;
+ char *value = getHashEntry(font_token_hash, token);
- /* !!! OPTIMIZE THIS BY USING HASH !!! */
- for (i = 0; i < NUM_FONTS; i++)
- if (strEqual(token, font_info[i].token_name))
- return i;
+ if (value != NULL)
+ return atoi(value);
/* if font not found, use reliable default value */
return FONT_INITIAL_1;
}
-void InitFontGraphicInfo()
+static void InitFontGraphicInfo(void)
{
static struct FontBitmapInfo *font_bitmap_info = NULL;
struct PropertyMapping *property_mapping = getImageListPropertyMapping();
int special = property_mapping[i].ext3_index;
int graphic = property_mapping[i].artwork_index;
- if (font_nr < 0)
+ if (font_nr < 0 || font_nr >= NUM_FONTS)
continue;
if (IS_SPECIAL_GFX_ARG(special))
font_bitmap_info[font_bitmap_id].width = graphic_info[graphic].width;
font_bitmap_info[font_bitmap_id].height = graphic_info[graphic].height;
+ font_bitmap_info[font_bitmap_id].offset_x =
+ graphic_info[graphic].offset_x;
+ font_bitmap_info[font_bitmap_id].offset_y =
+ graphic_info[graphic].offset_y;
+
font_bitmap_info[font_bitmap_id].draw_xoffset =
graphic_info[graphic].draw_xoffset;
font_bitmap_info[font_bitmap_id].draw_yoffset =
getFontBitmapID, getFontFromToken);
}
-void InitElementGraphicInfo()
+static void InitGlobalAnimGraphicInfo(void)
+{
+ struct PropertyMapping *property_mapping = getImageListPropertyMapping();
+ int num_property_mappings = getImageListPropertyMappingSize();
+ int i, j, k;
+
+ if (graphic_info == NULL) /* still at startup phase */
+ return;
+
+ /* always start with reliable default values (no global animations) */
+ for (i = 0; i < NUM_GLOBAL_ANIM_TOKENS; i++)
+ for (j = 0; j < NUM_GLOBAL_ANIM_PARTS_ALL; j++)
+ for (k = 0; k < NUM_SPECIAL_GFX_ARGS; k++)
+ global_anim_info[i].graphic[j][k] = IMG_UNDEFINED;
+
+ /* initialize global animation definitions from static configuration */
+ for (i = 0; i < NUM_GLOBAL_ANIM_TOKENS; i++)
+ {
+ int j = GLOBAL_ANIM_ID_PART_BASE;
+ int k = GFX_SPECIAL_ARG_DEFAULT;
+
+ global_anim_info[i].graphic[j][k] = IMG_GFX_GLOBAL_ANIM_1 + i;
+ }
+
+ /* initialize global animation definitions from dynamic configuration */
+ for (i = 0; i < num_property_mappings; i++)
+ {
+ int anim_nr = property_mapping[i].base_index - MAX_NUM_ELEMENTS - NUM_FONTS;
+ int part_nr = property_mapping[i].ext1_index - ACTION_PART_1;
+ int special = property_mapping[i].ext3_index;
+ int graphic = property_mapping[i].artwork_index;
+
+ if (anim_nr < 0 || anim_nr >= NUM_GLOBAL_ANIM_TOKENS)
+ continue;
+
+ /* set animation part to base part, if not specified */
+ if (!IS_GLOBAL_ANIM_PART(part_nr))
+ part_nr = GLOBAL_ANIM_ID_PART_BASE;
+
+ /* set animation screen to default, if not specified */
+ if (!IS_SPECIAL_GFX_ARG(special))
+ special = GFX_SPECIAL_ARG_DEFAULT;
+
+ global_anim_info[anim_nr].graphic[part_nr][special] = graphic;
+
+ /* fix default value for ".draw_masked" (for backward compatibility) */
+ struct GraphicInfo *g = &graphic_info[graphic];
+ struct FileInfo *image = getImageListEntryFromImageID(graphic);
+ char **parameter_raw = image->parameter;
+ int p = GFX_ARG_DRAW_MASKED;
+ int draw_masked = get_graphic_parameter_value(parameter_raw[p],
+ image_config_suffix[p].token,
+ image_config_suffix[p].type);
+
+ /* if ".draw_masked" parameter is undefined, use default value "TRUE" */
+ if (draw_masked == ARG_UNDEFINED_VALUE)
+ g->draw_masked = TRUE;
+ }
+
+#if 0
+ printf("::: InitGlobalAnimGraphicInfo\n");
+
+ for (i = 0; i < NUM_GLOBAL_ANIMS; i++)
+ for (j = 0; j < NUM_GLOBAL_ANIM_PARTS_ALL; j++)
+ for (k = 0; k < NUM_SPECIAL_GFX_ARGS; k++)
+ if (global_anim_info[i].graphic[j][k] != IMG_UNDEFINED &&
+ graphic_info[global_anim_info[i].graphic[j][k]].bitmap != NULL)
+ printf("::: - anim %d, part %d, mode %d => %d\n",
+ i, j, k, global_anim_info[i].graphic[j][k]);
+#endif
+}
+
+static void InitGlobalAnimSoundInfo(void)
+{
+ struct PropertyMapping *property_mapping = getSoundListPropertyMapping();
+ int num_property_mappings = getSoundListPropertyMappingSize();
+ int i, j, k;
+
+ /* always start with reliable default values (no global animation sounds) */
+ for (i = 0; i < NUM_GLOBAL_ANIM_TOKENS; i++)
+ for (j = 0; j < NUM_GLOBAL_ANIM_PARTS_ALL; j++)
+ for (k = 0; k < NUM_SPECIAL_GFX_ARGS; k++)
+ global_anim_info[i].sound[j][k] = SND_UNDEFINED;
+
+ /* initialize global animation sound definitions from dynamic configuration */
+ for (i = 0; i < num_property_mappings; i++)
+ {
+ int anim_nr = property_mapping[i].base_index - 2 * MAX_NUM_ELEMENTS;
+ int part_nr = property_mapping[i].ext1_index - ACTION_PART_1;
+ int special = property_mapping[i].ext3_index;
+ int sound = property_mapping[i].artwork_index;
+
+ // sound uses control definition; map it to position of graphic (artwork)
+ anim_nr -= GLOBAL_ANIM_ID_CONTROL_FIRST;
+
+ if (anim_nr < 0 || anim_nr >= NUM_GLOBAL_ANIM_TOKENS)
+ continue;
+
+ /* set animation part to base part, if not specified */
+ if (!IS_GLOBAL_ANIM_PART(part_nr))
+ part_nr = GLOBAL_ANIM_ID_PART_BASE;
+
+ /* set animation screen to default, if not specified */
+ if (!IS_SPECIAL_GFX_ARG(special))
+ special = GFX_SPECIAL_ARG_DEFAULT;
+
+ global_anim_info[anim_nr].sound[part_nr][special] = sound;
+ }
+
+#if 0
+ printf("::: InitGlobalAnimSoundInfo\n");
+
+ for (i = 0; i < NUM_GLOBAL_ANIMS; i++)
+ for (j = 0; j < NUM_GLOBAL_ANIM_PARTS_ALL; j++)
+ for (k = 0; k < NUM_SPECIAL_GFX_ARGS; k++)
+ if (global_anim_info[i].sound[j][k] != SND_UNDEFINED)
+ printf("::: - anim %d, part %d, mode %d => %d\n",
+ i, j, k, global_anim_info[i].sound[j][k]);
+#endif
+}
+
+static void InitGlobalAnimMusicInfo(void)
+{
+ struct PropertyMapping *property_mapping = getMusicListPropertyMapping();
+ int num_property_mappings = getMusicListPropertyMappingSize();
+ int i, j, k;
+
+ /* always start with reliable default values (no global animation music) */
+ for (i = 0; i < NUM_GLOBAL_ANIM_TOKENS; i++)
+ for (j = 0; j < NUM_GLOBAL_ANIM_PARTS_ALL; j++)
+ for (k = 0; k < NUM_SPECIAL_GFX_ARGS; k++)
+ global_anim_info[i].music[j][k] = MUS_UNDEFINED;
+
+ /* initialize global animation music definitions from dynamic configuration */
+ for (i = 0; i < num_property_mappings; i++)
+ {
+ int anim_nr = property_mapping[i].base_index - NUM_MUSIC_PREFIXES;
+ int part_nr = property_mapping[i].ext1_index - ACTION_PART_1;
+ int special = property_mapping[i].ext2_index;
+ int music = property_mapping[i].artwork_index;
+
+ // music uses control definition; map it to position of graphic (artwork)
+ anim_nr -= GLOBAL_ANIM_ID_CONTROL_FIRST;
+
+ if (anim_nr < 0 || anim_nr >= NUM_GLOBAL_ANIM_TOKENS)
+ continue;
+
+ /* set animation part to base part, if not specified */
+ if (!IS_GLOBAL_ANIM_PART(part_nr))
+ part_nr = GLOBAL_ANIM_ID_PART_BASE;
+
+ /* set animation screen to default, if not specified */
+ if (!IS_SPECIAL_GFX_ARG(special))
+ special = GFX_SPECIAL_ARG_DEFAULT;
+
+ global_anim_info[anim_nr].music[part_nr][special] = music;
+ }
+
+#if 0
+ printf("::: InitGlobalAnimMusicInfo\n");
+
+ for (i = 0; i < NUM_GLOBAL_ANIMS; i++)
+ for (j = 0; j < NUM_GLOBAL_ANIM_PARTS_ALL; j++)
+ for (k = 0; k < NUM_SPECIAL_GFX_ARGS; k++)
+ if (global_anim_info[i].music[j][k] != MUS_UNDEFINED)
+ printf("::: - anim %d, part %d, mode %d => %d\n",
+ i, j, k, global_anim_info[i].music[j][k]);
+#endif
+}
+
+static void InitElementGraphicInfo(void)
{
struct PropertyMapping *property_mapping = getImageListPropertyMapping();
int num_property_mappings = getImageListPropertyMappingSize();
}
}
+ UPDATE_BUSY_STATE();
+
/* initialize normal element/graphic mapping from static configuration */
for (i = 0; element_to_graphic[i].element > -1; i++)
{
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;
}
}
-#if 1
/* set hardcoded definitions for some runtime elements without graphic */
element_info[EL_AMOEBA_TO_DIAMOND].graphic[ACTION_DEFAULT] = IMG_AMOEBA_DEAD;
-#endif
-#if 1
/* set hardcoded definitions for some internal elements without graphic */
for (i = 0; i < MAX_NUM_ELEMENTS; i++)
{
else if (IS_EDITOR_CASCADE_ACTIVE(i))
element_info[i].graphic[ACTION_DEFAULT] = IMG_EDITOR_CASCADE_LIST_ACTIVE;
}
-#endif
/* now set all undefined/invalid graphics to -1 to set to default after it */
for (i = 0; i < MAX_NUM_ELEMENTS; i++)
}
}
+ 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++)
(move_dir == MV_BIT_UP && !front_is_left_or_upper) ||
(move_dir == MV_BIT_RIGHT && front_is_left_or_upper) ||
(move_dir == MV_BIT_DOWN && front_is_left_or_upper)));
- Bitmap *dummy;
/* swap frontside and backside graphic tile coordinates, if needed */
if (swap_movement_tiles_always || swap_movement_tiles_autodetected)
{
/* get current (wrong) backside tile coordinates */
- getGraphicSourceExt(graphic, 0, &dummy, &src_x_back, &src_y_back,
- TRUE);
+ getGraphicSourceXY(graphic, 0, &src_x_back, &src_y_back, TRUE);
/* set frontside tile coordinates to backside tile coordinates */
g->src_x = src_x_back;
}
}
+ UPDATE_BUSY_STATE();
+
/* now set all '-1' values to element specific default values */
for (i = 0; i < MAX_NUM_ELEMENTS; i++)
{
if (default_graphic == -1)
default_graphic = IMG_UNKNOWN;
-#if 1
+
if (default_crumbled == -1)
default_crumbled = default_graphic;
-#else
- /* !!! THIS LOOKS CRAPPY FOR SAND ETC. WITHOUT CRUMBLED GRAPHICS !!! */
- if (default_crumbled == -1)
- default_crumbled = IMG_EMPTY;
-#endif
for (dir = 0; dir < NUM_DIRECTIONS_FULL; dir++)
{
if (default_direction_graphic[dir] == -1)
default_direction_graphic[dir] = default_graphic;
-#if 1
+
if (default_direction_crumbled[dir] == -1)
default_direction_crumbled[dir] = default_direction_graphic[dir];
-#else
- /* !!! THIS LOOKS CRAPPY FOR SAND ETC. WITHOUT CRUMBLED GRAPHICS !!! */
- if (default_direction_crumbled[dir] == -1)
- default_direction_crumbled[dir] = default_crumbled;
-#endif
}
for (act = 0; act < NUM_ACTIONS; act++)
default_action_graphic = element_info[EL_SP_DEFAULT].graphic[act];
if (IS_SB_ELEMENT(i) && element_info[EL_SB_DEFAULT].graphic[act] != -1)
default_action_graphic = element_info[EL_SB_DEFAULT].graphic[act];
+ if (IS_MM_ELEMENT(i) && element_info[EL_MM_DEFAULT].graphic[act] != -1)
+ default_action_graphic = element_info[EL_MM_DEFAULT].graphic[act];
if (IS_BD_ELEMENT(i) && element_info[EL_BD_DEFAULT].crumbled[act] != -1)
default_action_crumbled = element_info[EL_BD_DEFAULT].crumbled[act];
default_action_crumbled = element_info[EL_SP_DEFAULT].crumbled[act];
if (IS_SB_ELEMENT(i) && element_info[EL_SB_DEFAULT].crumbled[act] != -1)
default_action_crumbled = element_info[EL_SB_DEFAULT].crumbled[act];
+ if (IS_MM_ELEMENT(i) && element_info[EL_MM_DEFAULT].crumbled[act] != -1)
+ default_action_crumbled = element_info[EL_MM_DEFAULT].crumbled[act];
-#if 1
/* !!! needed because EL_EMPTY_SPACE treated as IS_SP_ELEMENT !!! */
/* !!! make this better !!! */
if (i == EL_EMPTY_SPACE)
default_action_graphic = element_info[EL_DEFAULT].graphic[act];
default_action_crumbled = element_info[EL_DEFAULT].crumbled[act];
}
-#endif
if (default_action_graphic == -1)
default_action_graphic = default_graphic;
-#if 1
+
if (default_action_crumbled == -1)
default_action_crumbled = default_action_graphic;
-#else
- /* !!! THIS LOOKS CRAPPY FOR SAND ETC. WITHOUT CRUMBLED GRAPHICS !!! */
- if (default_action_crumbled == -1)
- default_action_crumbled = default_crumbled;
-#endif
for (dir = 0; dir < NUM_DIRECTIONS_FULL; dir++)
{
element_info[i].direction_graphic[act][dir] =
default_action_direction_graphic;
-#if 1
if (default_action_direction_crumbled == -1)
default_action_direction_crumbled =
element_info[i].direction_graphic[act][dir];
-#else
- if (default_action_direction_crumbled == -1)
- default_action_direction_crumbled =
- (act_remove ? default_remove_graphic :
- act_turning ?
- element_info[i].direction_crumbled[ACTION_TURNING][dir] :
- default_action_crumbled != default_crumbled ?
- default_action_crumbled :
- default_direction_crumbled[dir]);
-#endif
if (element_info[i].direction_crumbled[act][dir] == -1)
element_info[i].direction_crumbled[act][dir] =
(act_remove ? default_remove_graphic :
act_turning ? element_info[i].graphic[ACTION_TURNING] :
default_action_graphic);
-#if 1
+
if (element_info[i].crumbled[act] == -1)
element_info[i].crumbled[act] = element_info[i].graphic[act];
-#else
- if (element_info[i].crumbled[act] == -1)
- element_info[i].crumbled[act] =
- (act_remove ? default_remove_graphic :
- act_turning ? element_info[i].crumbled[ACTION_TURNING] :
- default_action_crumbled);
-#endif
- }
- }
-
-#if 0
- /* !!! THIS ALSO CLEARS SPECIAL FLAGS (AND IS NOT NEEDED ANYWAY) !!! */
- /* set animation mode to "none" for each graphic with only 1 frame */
- for (i = 0; i < MAX_NUM_ELEMENTS; i++)
- {
- for (act = 0; act < NUM_ACTIONS; act++)
- {
- int graphic = element_info[i].graphic[act];
- int crumbled = element_info[i].crumbled[act];
-
- if (graphic_info[graphic].anim_frames == 1)
- graphic_info[graphic].anim_mode = ANIM_NONE;
- if (graphic_info[crumbled].anim_frames == 1)
- graphic_info[crumbled].anim_mode = ANIM_NONE;
-
- for (dir = 0; dir < NUM_DIRECTIONS_FULL; dir++)
- {
- graphic = element_info[i].direction_graphic[act][dir];
- crumbled = element_info[i].direction_crumbled[act][dir];
-
- if (graphic_info[graphic].anim_frames == 1)
- graphic_info[graphic].anim_mode = ANIM_NONE;
- if (graphic_info[crumbled].anim_frames == 1)
- graphic_info[crumbled].anim_mode = ANIM_NONE;
- }
}
}
-#endif
-#if 0
-#if DEBUG
- if (options.verbose)
- {
- for (i = 0; i < MAX_NUM_ELEMENTS; i++)
- if (element_info[i].graphic[ACTION_DEFAULT] == IMG_UNKNOWN &&
- i != EL_UNKNOWN)
- Error(ERR_INFO, "warning: no graphic for element '%s' (%d)",
- element_info[i].token_name, i);
- }
-#endif
-#endif
+ UPDATE_BUSY_STATE();
}
-void InitElementSpecialGraphicInfo()
+static void InitElementSpecialGraphicInfo(void)
{
struct PropertyMapping *property_mapping = getImageListPropertyMapping();
int num_property_mappings = getImageListPropertyMappingSize();
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
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;
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;
- /* !!! OPTIMIZE THIS BY USING HASH !!! */
- for (i = 0; i < MAX_NUM_ELEMENTS; i++)
- if (strEqual(element_info[i].token_name, value_raw))
- return i;
-
- /* !!! OPTIMIZE THIS BY USING HASH !!! */
- for (i = 0; image_config[i].token != NULL; i++)
+ if (type == TYPE_ELEMENT)
{
- int len_config_value = strlen(image_config[i].value);
+ char *value = getHashEntry(element_token_hash, value_raw);
- if (!strEqual(&image_config[i].value[len_config_value - 4], ".pcx") &&
- !strEqual(&image_config[i].value[len_config_value - 4], ".wav") &&
- !strEqual(image_config[i].value, UNDEFINED_FILENAME))
- continue;
+ if (value == NULL)
+ {
+ Error(ERR_INFO_LINE, "-");
+ Error(ERR_INFO, "warning: error found in config file:");
+ Error(ERR_INFO, "- config file: '%s'", getImageConfigFilename());
+ Error(ERR_INFO, "error: invalid element token '%s'", value_raw);
+ Error(ERR_INFO, "custom graphic rejected for this element/action");
+ Error(ERR_INFO, "fallback done to undefined element for this graphic");
+ Error(ERR_INFO_LINE, "-");
+ }
+
+ return (value != NULL ? atoi(value) : EL_UNDEFINED);
+ }
+ else if (type == TYPE_GRAPHIC)
+ {
+ char *value = getHashEntry(graphic_token_hash, value_raw);
+ int fallback_graphic = IMG_CHAR_EXCLAM;
- if (strEqual(image_config[i].token, value_raw))
- return x;
+ if (value == NULL)
+ {
+ Error(ERR_INFO_LINE, "-");
+ Error(ERR_INFO, "warning: error found in config file:");
+ Error(ERR_INFO, "- config file: '%s'", getImageConfigFilename());
+ Error(ERR_INFO, "error: invalid graphic token '%s'", value_raw);
+ Error(ERR_INFO, "custom graphic rejected for this element/action");
+ Error(ERR_INFO, "fallback done to 'char_exclam' for this graphic");
+ Error(ERR_INFO_LINE, "-");
+ }
- x++;
+ return (value != NULL ? atoi(value) : fallback_graphic);
}
return -1;
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_bitmaps)
{
- 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];
+ Bitmap *src_bitmap = (src_bitmaps ? src_bitmaps[IMG_BITMAP_STANDARD] : NULL);
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 */
+ 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->tile_size = TILESIZE; /* default: standard tile size */
+ g->clone_from = -1; /* do not use clone graphic */
+ g->init_delay_fixed = 0;
+ g->init_delay_random = 0;
+ g->anim_delay_fixed = 0;
+ g->anim_delay_random = 0;
+ g->post_delay_fixed = 0;
+ g->post_delay_random = 0;
+ g->init_event = ANIM_EVENT_DEFAULT;
+ g->anim_event = ANIM_EVENT_DEFAULT;
+ g->init_event_action = -1;
+ g->anim_event_action = -1;
+ g->draw_masked = FALSE;
+ g->draw_order = 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->bitmaps = src_bitmaps;
+ 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)
- 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 */
+ g->scale_up_factor = parameter[GFX_ARG_SCALE_UP_FACTOR];
+ if (g->scale_up_factor < 1)
+ g->scale_up_factor = 1; /* no scaling */
+
+ /* optional tile size for using non-standard image size */
+ if (parameter[GFX_ARG_TILE_SIZE] != ARG_UNDEFINED_VALUE)
+ {
+ g->tile_size = parameter[GFX_ARG_TILE_SIZE];
+
+#if 0
+ // CHECK: should tile sizes less than standard tile size be allowed?
+ if (g->tile_size < TILESIZE)
+ g->tile_size = TILESIZE; /* standard tile size */
#endif
-#if 1
- if (graphic_info[graphic].use_image_size)
+ // when setting tile size, also set width and height accordingly
+ g->width = g->tile_size;
+ g->height = g->tile_size;
+ }
+
+ if (g->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);
+ g->width = get_scaled_graphic_width(graphic);
+ g->height = get_scaled_graphic_height(graphic);
}
-#endif
+
+ /* 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];
/* 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] * g->width;
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] * g->height;
/* 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];
- if (parameter[GFX_ARG_HEIGHT] != ARG_UNDEFINED_VALUE)
- graphic_info[graphic].height = parameter[GFX_ARG_HEIGHT];
+ if (src_bitmap)
+ {
+ if (g->width <= 0)
+ {
+ Error(ERR_INFO_LINE, "-");
+ Error(ERR_WARN, "invalid value %d for '%s.width' (fallback done to %d)",
+ g->width, getTokenFromImageID(graphic), TILEX);
+ Error(ERR_INFO_LINE, "-");
-#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
+ g->width = TILEX; /* will be checked to be inside bitmap later */
+ }
+
+ if (g->height <= 0)
+ {
+ Error(ERR_INFO_LINE, "-");
+ Error(ERR_WARN, "invalid value %d for '%s.height' (fallback done to %d)",
+ g->height, getTokenFromImageID(graphic), TILEY);
+ Error(ERR_INFO_LINE, "-");
+
+ g->height = TILEY; /* will be checked to be inside bitmap later */
+ }
+ }
if (src_bitmap)
{
int src_image_width = get_scaled_graphic_width(graphic);
int src_image_height = get_scaled_graphic_height(graphic);
- anim_frames_per_row = src_image_width / graphic_info[graphic].width;
- anim_frames_per_col = src_image_height / graphic_info[graphic].height;
+ 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;
+ }
+
+ if (parameter[GFX_ARG_TILE_SIZE] != ARG_UNDEFINED_VALUE)
+ {
+ anim_frames_per_row = MAX(1, src_image_width / g->tile_size);
+ anim_frames_per_col = MAX(1, src_image_height / g->tile_size);
+ }
+ else
+ {
+ anim_frames_per_row = MAX(1, src_image_width / g->width);
+ anim_frames_per_col = MAX(1, src_image_height / g->height);
+ }
- graphic_info[graphic].src_image_width = src_image_width;
- graphic_info[graphic].src_image_height = src_image_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 */
{
- graphic_info[graphic].offset_y =
- (parameter[GFX_ARG_OFFSET] != ARG_UNDEFINED_VALUE ?
- parameter[GFX_ARG_OFFSET] : graphic_info[graphic].height);
+ 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 */
{
- graphic_info[graphic].offset_x =
- (parameter[GFX_ARG_OFFSET] != ARG_UNDEFINED_VALUE ?
- parameter[GFX_ARG_OFFSET] : graphic_info[graphic].width);
+ 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)
- graphic_info[graphic].offset_x = parameter[GFX_ARG_XOFFSET];
+ g->offset_x = parameter[GFX_ARG_XOFFSET];
if (parameter[GFX_ARG_YOFFSET] != ARG_UNDEFINED_VALUE)
- graphic_info[graphic].offset_y = parameter[GFX_ARG_YOFFSET];
+ g->offset_y = parameter[GFX_ARG_YOFFSET];
/* optionally, moving animations may have separate start and end graphics */
- graphic_info[graphic].double_movement = parameter[GFX_ARG_2ND_MOVEMENT_TILE];
+ 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 */
- graphic_info[graphic].offset2_y =
- (parameter[GFX_ARG_2ND_OFFSET] != ARG_UNDEFINED_VALUE ?
- parameter[GFX_ARG_2ND_OFFSET] : graphic_info[graphic].height);
+ g->offset2_y = (parameter[GFX_ARG_2ND_OFFSET] != ARG_UNDEFINED_VALUE ?
+ parameter[GFX_ARG_2ND_OFFSET] : g->height);
else /* frames are ordered horizontally */
- graphic_info[graphic].offset2_x =
- (parameter[GFX_ARG_2ND_OFFSET] != ARG_UNDEFINED_VALUE ?
- parameter[GFX_ARG_2ND_OFFSET] : graphic_info[graphic].width);
+ 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)
- graphic_info[graphic].offset2_x = parameter[GFX_ARG_2ND_XOFFSET];
+ g->offset2_x = parameter[GFX_ARG_2ND_XOFFSET];
if (parameter[GFX_ARG_2ND_YOFFSET] != ARG_UNDEFINED_VALUE)
- graphic_info[graphic].offset2_y = parameter[GFX_ARG_2ND_YOFFSET];
+ 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)
- graphic_info[graphic].swap_double_tiles= parameter[GFX_ARG_2ND_SWAP_TILES];
+ 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)
- graphic_info[graphic].anim_frames = parameter[GFX_ARG_FRAMES];
+ g->anim_frames = parameter[GFX_ARG_FRAMES];
else if (parameter[GFX_ARG_XPOS] == 0 && !parameter[GFX_ARG_VERTICAL])
- graphic_info[graphic].anim_frames = anim_frames_per_row;
+ g->anim_frames = anim_frames_per_row;
else if (parameter[GFX_ARG_YPOS] == 0 && parameter[GFX_ARG_VERTICAL])
- graphic_info[graphic].anim_frames = anim_frames_per_col;
+ g->anim_frames = anim_frames_per_col;
else
- graphic_info[graphic].anim_frames = 1;
+ g->anim_frames = 1;
- if (graphic_info[graphic].anim_frames == 0) /* frames must be at least 1 */
- graphic_info[graphic].anim_frames = 1;
+ if (g->anim_frames == 0) /* frames must be at least 1 */
+ g->anim_frames = 1;
- graphic_info[graphic].anim_frames_per_line =
+ g->anim_frames_per_line =
(parameter[GFX_ARG_FRAMES_PER_LINE] != ARG_UNDEFINED_VALUE ?
parameter[GFX_ARG_FRAMES_PER_LINE] : anim_frames_per_line);
- graphic_info[graphic].anim_delay = parameter[GFX_ARG_DELAY];
- if (graphic_info[graphic].anim_delay == 0) /* delay must be at least 1 */
- graphic_info[graphic].anim_delay = 1;
+ g->anim_delay = parameter[GFX_ARG_DELAY];
+ if (g->anim_delay == 0) /* delay must be at least 1 */
+ g->anim_delay = 1;
- graphic_info[graphic].anim_mode = parameter[GFX_ARG_ANIM_MODE];
-#if 0
- if (graphic_info[graphic].anim_frames == 1)
- graphic_info[graphic].anim_mode = ANIM_NONE;
-#endif
+ g->anim_mode = parameter[GFX_ARG_ANIM_MODE];
/* automatically determine correct start frame, if not defined */
if (parameter[GFX_ARG_START_FRAME] == ARG_UNDEFINED_VALUE)
- graphic_info[graphic].anim_start_frame = 0;
- else if (graphic_info[graphic].anim_mode & ANIM_REVERSE)
- graphic_info[graphic].anim_start_frame =
- graphic_info[graphic].anim_frames - parameter[GFX_ARG_START_FRAME] - 1;
+ 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
- graphic_info[graphic].anim_start_frame = parameter[GFX_ARG_START_FRAME];
+ g->anim_start_frame = parameter[GFX_ARG_START_FRAME];
/* animation synchronized with global frame counter, not move position */
- graphic_info[graphic].anim_global_sync = parameter[GFX_ARG_GLOBAL_SYNC];
+ g->anim_global_sync = parameter[GFX_ARG_GLOBAL_SYNC];
/* optional element for cloning crumble graphics */
if (parameter[GFX_ARG_CRUMBLED_LIKE] != ARG_UNDEFINED_VALUE)
- graphic_info[graphic].crumbled_like = parameter[GFX_ARG_CRUMBLED_LIKE];
+ g->crumbled_like = parameter[GFX_ARG_CRUMBLED_LIKE];
/* optional element for cloning digging graphics */
if (parameter[GFX_ARG_DIGGABLE_LIKE] != ARG_UNDEFINED_VALUE)
- graphic_info[graphic].diggable_like = parameter[GFX_ARG_DIGGABLE_LIKE];
+ g->diggable_like = parameter[GFX_ARG_DIGGABLE_LIKE];
/* optional border size for "crumbling" diggable graphics */
if (parameter[GFX_ARG_BORDER_SIZE] != ARG_UNDEFINED_VALUE)
- graphic_info[graphic].border_size = parameter[GFX_ARG_BORDER_SIZE];
+ g->border_size = parameter[GFX_ARG_BORDER_SIZE];
- /* this is only used for player "boring" and "sleeping" actions */
+ /* used for global animations and player "boring" and "sleeping" actions */
+ if (parameter[GFX_ARG_INIT_DELAY_FIXED] != ARG_UNDEFINED_VALUE)
+ g->init_delay_fixed = parameter[GFX_ARG_INIT_DELAY_FIXED];
+ if (parameter[GFX_ARG_INIT_DELAY_RANDOM] != ARG_UNDEFINED_VALUE)
+ g->init_delay_random = parameter[GFX_ARG_INIT_DELAY_RANDOM];
if (parameter[GFX_ARG_ANIM_DELAY_FIXED] != ARG_UNDEFINED_VALUE)
- graphic_info[graphic].anim_delay_fixed =
- parameter[GFX_ARG_ANIM_DELAY_FIXED];
+ g->anim_delay_fixed = parameter[GFX_ARG_ANIM_DELAY_FIXED];
if (parameter[GFX_ARG_ANIM_DELAY_RANDOM] != ARG_UNDEFINED_VALUE)
- graphic_info[graphic].anim_delay_random =
- parameter[GFX_ARG_ANIM_DELAY_RANDOM];
+ g->anim_delay_random = parameter[GFX_ARG_ANIM_DELAY_RANDOM];
if (parameter[GFX_ARG_POST_DELAY_FIXED] != ARG_UNDEFINED_VALUE)
- graphic_info[graphic].post_delay_fixed =
- parameter[GFX_ARG_POST_DELAY_FIXED];
+ g->post_delay_fixed = parameter[GFX_ARG_POST_DELAY_FIXED];
if (parameter[GFX_ARG_POST_DELAY_RANDOM] != ARG_UNDEFINED_VALUE)
- graphic_info[graphic].post_delay_random =
- parameter[GFX_ARG_POST_DELAY_RANDOM];
-
- /* this is only used for toon animations */
- graphic_info[graphic].step_offset = parameter[GFX_ARG_STEP_OFFSET];
- graphic_info[graphic].step_delay = parameter[GFX_ARG_STEP_DELAY];
+ g->post_delay_random = parameter[GFX_ARG_POST_DELAY_RANDOM];
+
+ /* used for global animations */
+ if (parameter[GFX_ARG_INIT_EVENT] != ARG_UNDEFINED_VALUE)
+ g->init_event = parameter[GFX_ARG_INIT_EVENT];
+ if (parameter[GFX_ARG_ANIM_EVENT] != ARG_UNDEFINED_VALUE)
+ g->anim_event = parameter[GFX_ARG_ANIM_EVENT];
+ if (parameter[GFX_ARG_INIT_EVENT_ACTION] != ARG_UNDEFINED_VALUE)
+ g->init_event_action = parameter[GFX_ARG_INIT_EVENT_ACTION];
+ if (parameter[GFX_ARG_ANIM_EVENT_ACTION] != ARG_UNDEFINED_VALUE)
+ g->anim_event_action = parameter[GFX_ARG_ANIM_EVENT_ACTION];
+
+ /* used for toon animations and global animations */
+ g->step_offset = parameter[GFX_ARG_STEP_OFFSET];
+ g->step_xoffset = parameter[GFX_ARG_STEP_XOFFSET];
+ g->step_yoffset = parameter[GFX_ARG_STEP_YOFFSET];
+ g->step_delay = parameter[GFX_ARG_STEP_DELAY];
+ g->direction = parameter[GFX_ARG_DIRECTION];
+ g->position = parameter[GFX_ARG_POSITION];
+ g->x = parameter[GFX_ARG_X]; // (may be uninitialized,
+ g->y = parameter[GFX_ARG_Y]; // unlike src_x and src_y)
/* this is only used for drawing font characters */
- graphic_info[graphic].draw_xoffset = parameter[GFX_ARG_DRAW_XOFFSET];
- graphic_info[graphic].draw_yoffset = parameter[GFX_ARG_DRAW_YOFFSET];
+ g->draw_xoffset = parameter[GFX_ARG_DRAW_XOFFSET];
+ g->draw_yoffset = parameter[GFX_ARG_DRAW_YOFFSET];
+
+ /* use a different default value for global animations and toons */
+ if ((graphic >= IMG_GFX_GLOBAL_ANIM_1 && graphic <= IMG_GFX_GLOBAL_ANIM_8) ||
+ (graphic >= IMG_TOON_1 && graphic <= IMG_TOON_20))
+ g->draw_masked = TRUE;
- /* this is only used for drawing envelope graphics */
- graphic_info[graphic].draw_masked = parameter[GFX_ARG_DRAW_MASKED];
+ /* this is used for drawing envelopes, global animations and toons */
+ if (parameter[GFX_ARG_DRAW_MASKED] != ARG_UNDEFINED_VALUE)
+ g->draw_masked = parameter[GFX_ARG_DRAW_MASKED];
+
+ /* used for toon animations and global animations */
+ if (parameter[GFX_ARG_DRAW_ORDER] != ARG_UNDEFINED_VALUE)
+ g->draw_order = parameter[GFX_ARG_DRAW_ORDER];
/* 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];
+ 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)
- graphic_info[graphic].fade_mode = parameter[GFX_ARG_FADE_MODE];
+ g->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];
+ g->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];
+ g->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];
+ g->auto_delay = parameter[GFX_ARG_AUTO_DELAY];
if (parameter[GFX_ARG_ALIGN] != ARG_UNDEFINED_VALUE)
- graphic_info[graphic].align = parameter[GFX_ARG_ALIGN];
+ g->align = parameter[GFX_ARG_ALIGN];
if (parameter[GFX_ARG_VALIGN] != ARG_UNDEFINED_VALUE)
- graphic_info[graphic].valign = parameter[GFX_ARG_VALIGN];
+ g->valign = parameter[GFX_ARG_VALIGN];
if (parameter[GFX_ARG_SORT_PRIORITY] != ARG_UNDEFINED_VALUE)
- graphic_info[graphic].sort_priority = parameter[GFX_ARG_SORT_PRIORITY];
+ 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];
+
+ /* this is only used for drawing menu buttons and text */
+ g->active_xoffset = parameter[GFX_ARG_ACTIVE_XOFFSET];
+ g->active_yoffset = parameter[GFX_ARG_ACTIVE_YOFFSET];
+ g->pressed_xoffset = parameter[GFX_ARG_PRESSED_XOFFSET];
+ g->pressed_yoffset = parameter[GFX_ARG_PRESSED_YOFFSET];
+}
+
+static void set_graphic_parameters(int graphic)
+{
+ struct FileInfo *image = getImageListEntryFromImageID(graphic);
+ char **parameter_raw = image->parameter;
+ Bitmap **src_bitmaps = getBitmapsFromImageID(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_bitmaps);
+
+ UPDATE_BUSY_STATE();
}
static void set_cloned_graphic_parameters(int graphic)
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_EXIT, "no fallback graphic available");
Error(ERR_INFO, "fallback done to 'char_exclam' for this graphic");
Error(ERR_INFO_LINE, "-");
}
}
-static void InitGraphicInfo()
+static void InitGraphicInfo(void)
{
int fallback_graphic = IMG_CHAR_EXCLAM;
int num_images = getImageListSize();
int i;
-#if defined(TARGET_X11_NATIVE_PERFORMANCE_WORKAROUND)
- static boolean clipmasks_initialized = FALSE;
- Pixmap src_pixmap;
- XGCValues clip_gc_values;
- unsigned long clip_gc_valuemask;
- 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_BORDER_MAIN,
+ IMG_GLOBAL_BORDER_SCORES,
+ IMG_GLOBAL_BORDER_EDITOR,
+ IMG_GLOBAL_BORDER_PLAYING,
IMG_GLOBAL_DOOR,
IMG_BACKGROUND_ENVELOPE_1,
IMG_BACKGROUND_ENVELOPE_2,
IMG_BACKGROUND_ENVELOPE_3,
IMG_BACKGROUND_ENVELOPE_4,
+ IMG_BACKGROUND_REQUEST,
IMG_BACKGROUND,
IMG_BACKGROUND_TITLE_INITIAL,
IMG_BACKGROUND_TITLE,
IMG_BACKGROUND_MAIN,
IMG_BACKGROUND_LEVELS,
+ IMG_BACKGROUND_LEVELNR,
IMG_BACKGROUND_SCORES,
IMG_BACKGROUND_EDITOR,
IMG_BACKGROUND_INFO,
IMG_BACKGROUND_INFO_MUSIC,
IMG_BACKGROUND_INFO_CREDITS,
IMG_BACKGROUND_INFO_PROGRAM,
+ IMG_BACKGROUND_INFO_VERSION,
IMG_BACKGROUND_INFO_LEVELSET,
IMG_BACKGROUND_SETUP,
+ IMG_BACKGROUND_PLAYING,
IMG_BACKGROUND_DOOR,
+ IMG_BACKGROUND_TAPE,
+ IMG_BACKGROUND_PANEL,
+ IMG_BACKGROUND_PALETTE,
+ IMG_BACKGROUND_TOOLBOX,
IMG_TITLESCREEN_INITIAL_1,
IMG_TITLESCREEN_INITIAL_2,
IMG_TITLESCREEN_4,
IMG_TITLESCREEN_5,
+ IMG_BACKGROUND_TITLEMESSAGE_INITIAL_1,
+ IMG_BACKGROUND_TITLEMESSAGE_INITIAL_2,
+ IMG_BACKGROUND_TITLEMESSAGE_INITIAL_3,
+ IMG_BACKGROUND_TITLEMESSAGE_INITIAL_4,
+ IMG_BACKGROUND_TITLEMESSAGE_INITIAL_5,
+ IMG_BACKGROUND_TITLEMESSAGE_1,
+ IMG_BACKGROUND_TITLEMESSAGE_2,
+ IMG_BACKGROUND_TITLEMESSAGE_3,
+ IMG_BACKGROUND_TITLEMESSAGE_4,
+ IMG_BACKGROUND_TITLEMESSAGE_5,
+
-1
};
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)
- {
- for (i = 0; i < num_images; i++)
- {
- if (graphic_info[i].clip_mask)
- XFreePixmap(display, graphic_info[i].clip_mask);
- if (graphic_info[i].clip_gc)
- XFreeGC(display, graphic_info[i].clip_gc);
-
- graphic_info[i].clip_mask = None;
- graphic_info[i].clip_gc = None;
- }
- }
-#endif
/* first set all graphic paramaters ... */
for (i = 0; i < num_images; i++)
for (i = 0; i < num_images; i++)
{
- Bitmap *src_bitmap;
+ Bitmap *src_bitmap = graphic_info[i].bitmap;
int src_x, src_y;
int width, height;
- int first_frame, last_frame;
+ int last_frame;
int src_bitmap_width, src_bitmap_height;
/* now check if no animation frames are outside of the loaded image */
/* check if first animation frame is inside specified bitmap */
- first_frame = 0;
- getGraphicSource(i, first_frame, &src_bitmap, &src_x, &src_y);
-
-#if 1
+ /* do not use getGraphicSourceXY() here to get position of first frame; */
/* 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 (program.headless)
+ continue;
if (src_x < 0 || src_y < 0 ||
src_x + width > src_bitmap_width ||
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, "- frame size: %d, %d", width, height);
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_INFO, "custom graphic rejected for this element/action");
if (i == fallback_graphic)
- Error(ERR_EXIT, "fatal error: no fallback graphic available");
+ Error(ERR_EXIT, "no fallback graphic available");
Error(ERR_INFO, "fallback done to 'char_exclam' for this graphic");
Error(ERR_INFO_LINE, "-");
graphic_info[i] = graphic_info[fallback_graphic];
+
+ /* if first frame out of bounds, do not check last frame anymore */
+ continue;
}
/* check if last animation frame is inside specified bitmap */
last_frame = graphic_info[i].anim_frames - 1;
- getGraphicSource(i, last_frame, &src_bitmap, &src_x, &src_y);
+ getGraphicSourceXY(i, last_frame, &src_x, &src_y, FALSE);
if (src_x < 0 || src_y < 0 ||
src_x + width > src_bitmap_width ||
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, "- frame size: %d, %d", width, height);
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_INFO, "custom graphic rejected for this element/action");
if (i == fallback_graphic)
- Error(ERR_EXIT, "fatal error: no fallback graphic available");
+ Error(ERR_EXIT, "no fallback graphic available");
Error(ERR_INFO, "fallback done to 'char_exclam' for this graphic");
Error(ERR_INFO_LINE, "-");
graphic_info[i] = graphic_info[fallback_graphic];
}
+ }
+}
-#if defined(TARGET_X11_NATIVE_PERFORMANCE_WORKAROUND)
- /* currently we only need a tile clip mask from the first frame */
- getGraphicSource(i, first_frame, &src_bitmap, &src_x, &src_y);
-
- if (copy_clipmask_gc == None)
- {
- clip_gc_values.graphics_exposures = False;
- clip_gc_valuemask = GCGraphicsExposures;
- copy_clipmask_gc = XCreateGC(display, src_bitmap->clip_mask,
- clip_gc_valuemask, &clip_gc_values);
- }
+static void InitGraphicCompatibilityInfo(void)
+{
+ struct FileInfo *fi_global_door =
+ getImageListEntryFromImageID(IMG_GLOBAL_DOOR);
+ int num_images = getImageListSize();
+ int i;
- graphic_info[i].clip_mask =
- XCreatePixmap(display, window->drawable, TILEX, TILEY, 1);
+ /* the following compatibility handling is needed for the following case:
+ versions up to 3.3.0.0 used one large bitmap "global.door" for various
+ graphics mainly used for door and panel graphics, like editor, tape and
+ in-game buttons with hard-coded bitmap positions and button sizes; as
+ these graphics now have individual definitions, redefining "global.door"
+ to change all these graphics at once like before does not work anymore
+ (because all those individual definitions still have their default values);
+ to solve this, remap all those individual definitions that are not
+ redefined to the new bitmap of "global.door" if it was redefined */
- src_pixmap = src_bitmap->clip_mask;
- XCopyArea(display, src_pixmap, graphic_info[i].clip_mask,
- copy_clipmask_gc, src_x, src_y, TILEX, TILEY, 0, 0);
+ /* special compatibility handling if image "global.door" was redefined */
+ if (fi_global_door->redefined)
+ {
+ for (i = 0; i < num_images; i++)
+ {
+ struct FileInfo *fi = getImageListEntryFromImageID(i);
- clip_gc_values.graphics_exposures = False;
- clip_gc_values.clip_mask = graphic_info[i].clip_mask;
- clip_gc_valuemask = GCGraphicsExposures | GCClipMask;
+ /* process only those images that still use the default settings */
+ if (!fi->redefined)
+ {
+ /* process all images which default to same image as "global.door" */
+ if (strEqual(fi->default_filename, fi_global_door->default_filename))
+ {
+ // printf("::: special treatment needed for token '%s'\n", fi->token);
- graphic_info[i].clip_gc =
- XCreateGC(display, window->drawable, clip_gc_valuemask, &clip_gc_values);
-#endif
+ graphic_info[i].bitmaps = graphic_info[IMG_GLOBAL_DOOR].bitmaps;
+ graphic_info[i].bitmap = graphic_info[IMG_GLOBAL_DOOR].bitmap;
+ }
+ }
+ }
}
-#if defined(TARGET_X11_NATIVE_PERFORMANCE_WORKAROUND)
- if (copy_clipmask_gc)
- XFreeGC(display, copy_clipmask_gc);
-
- clipmasks_initialized = TRUE;
-#endif
+ InitGraphicCompatibilityInfo_Doors();
}
-static void InitElementSoundInfo()
+static void InitElementSoundInfo(void)
{
struct PropertyMapping *property_mapping = getSoundListPropertyMapping();
int num_property_mappings = getSoundListPropertyMappingSize();
default_action_sound = element_info[EL_SP_DEFAULT].sound[act];
if (IS_SB_ELEMENT(i) && element_info[EL_SB_DEFAULT].sound[act] != -1)
default_action_sound = element_info[EL_SB_DEFAULT].sound[act];
+ if (IS_MM_ELEMENT(i) && element_info[EL_MM_DEFAULT].sound[act] != -1)
+ default_action_sound = element_info[EL_MM_DEFAULT].sound[act];
- /* !!! there's no such thing as a "default action sound" !!! */
-#if 0
- /* look for element specific default sound (independent from action) */
- if (element_info[i].sound[ACTION_DEFAULT] != -1)
- default_action_sound = element_info[i].sound[ACTION_DEFAULT];
-#endif
-
-#if 1
/* !!! needed because EL_EMPTY_SPACE treated as IS_SP_ELEMENT !!! */
/* !!! make this better !!! */
if (i == EL_EMPTY_SPACE)
default_action_sound = element_info[EL_DEFAULT].sound[act];
-#endif
/* no sound for this specific action -- use default action sound */
if (element_info[i].sound[act] == -1)
element_info[copy_properties[i][0]].sound[act];
}
-static void InitGameModeSoundInfo()
+static void InitGameModeSoundInfo(void)
{
int i;
for (i = 0; i < NUM_SPECIAL_GFX_ARGS; i++)
if (menu.sound[i] == -1)
menu.sound[i] = menu.sound[GAME_MODE_DEFAULT];
-
-#if 0
- for (i = 0; i < NUM_SPECIAL_GFX_ARGS; i++)
- if (menu.sound[i] != -1)
- printf("::: menu.sound[%d] == %d\n", i, menu.sound[i]);
-#endif
}
static void set_sound_parameters(int sound, char **parameter_raw)
sound_info[sound].priority = parameter[SND_ARG_PRIORITY];
}
-static void InitSoundInfo()
+static void InitSoundInfo(void)
{
int *sound_effect_properties;
int num_sounds = getSoundListSize();
sound_effect_properties[i] = ACTION_OTHER;
sound_info[i].loop = FALSE; /* default: play sound only once */
-#if 0
- printf("::: sound %d: '%s'\n", i, sound->token);
-#endif
-
/* determine all loop sounds and identify certain sound classes */
for (j = 0; element_action_info[j].suffix; j++)
free(sound_effect_properties);
}
-static void InitGameModeMusicInfo()
+static void InitGameModeMusicInfo(void)
{
struct PropertyMapping *property_mapping = getMusicListPropertyMapping();
int num_property_mappings = getMusicListPropertyMappingSize();
int gamemode = gamemode_to_music[i].gamemode;
int music = gamemode_to_music[i].music;
-#if 0
- printf("::: gamemode == %d, music == %d\n", gamemode, music);
-#endif
-
if (gamemode < 0)
gamemode = GAME_MODE_DEFAULT;
for (i = 0; i < num_property_mappings; i++)
{
int prefix = property_mapping[i].base_index;
- int gamemode = property_mapping[i].ext1_index;
- int level = property_mapping[i].ext2_index;
+ int gamemode = property_mapping[i].ext2_index;
+ int level = property_mapping[i].ext3_index;
int music = property_mapping[i].artwork_index;
-#if 0
- printf("::: prefix == %d, gamemode == %d, level == %d, music == %d\n",
- prefix, gamemode, level, music);
-#endif
-
if (prefix < 0 || prefix >= NUM_MUSIC_PREFIXES)
continue;
for (i = 0; i < NUM_SPECIAL_GFX_ARGS; i++)
if (menu.music[i] == -1)
menu.music[i] = menu.music[GAME_MODE_DEFAULT];
-
-#if 0
- for (i = 0; i < MAX_LEVELS; i++)
- if (levelset.music[i] != -1)
- printf("::: levelset.music[%d] == %d\n", i, levelset.music[i]);
- for (i = 0; i < NUM_SPECIAL_GFX_ARGS; i++)
- if (menu.music[i] != -1)
- printf("::: menu.music[%d] == %d\n", i, menu.music[i]);
-#endif
}
static void set_music_parameters(int music, char **parameter_raw)
music_info[music].loop = parameter[MUS_ARG_MODE_LOOP];
}
-static void InitMusicInfo()
+static void InitMusicInfo(void)
{
int num_music = getMusicListSize();
int i, j;
}
}
-static void ReinitializeGraphics()
+static void ReinitializeGraphics(void)
{
+ print_timestamp_init("ReinitializeGraphics");
+
+ InitGfxTileSizeInfo(game.tile_size, TILESIZE);
+
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");
+ InitBitmapPointers(); /* set standard size bitmap pointers */
+ print_timestamp_time("InitBitmapPointers");
InitFontGraphicInfo(); /* initialize text drawing functions */
+ print_timestamp_time("InitFontGraphicInfo");
+ InitGlobalAnimGraphicInfo(); /* initialize global animation config */
+ print_timestamp_time("InitGlobalAnimGraphicInfo");
+
+ InitImageTextures(); /* create textures for certain images */
+ print_timestamp_time("InitImageTextures");
InitGraphicInfo_EM(); /* graphic mapping for EM engine */
+ print_timestamp_time("InitGraphicInfo_EM");
+
+ InitGraphicCompatibilityInfo();
+ print_timestamp_time("InitGraphicCompatibilityInfo");
SetMainBackgroundImage(IMG_BACKGROUND);
+ print_timestamp_time("SetMainBackgroundImage");
SetDoorBackgroundImage(IMG_BACKGROUND_DOOR);
+ print_timestamp_time("SetDoorBackgroundImage");
InitGadgets();
- InitToons();
+ print_timestamp_time("InitGadgets");
+ InitDoors();
+ print_timestamp_time("InitDoors");
+
+ print_timestamp_done("ReinitializeGraphics");
}
-static void ReinitializeSounds()
+static void ReinitializeSounds(void)
{
InitSoundInfo(); /* sound properties mapping */
InitElementSoundInfo(); /* element game sound mapping */
InitGameModeSoundInfo(); /* game mode sound mapping */
+ InitGlobalAnimSoundInfo(); /* global animation sound settings */
InitPlayLevelSound(); /* internal game sound settings */
}
-static void ReinitializeMusic()
+static void ReinitializeMusic(void)
{
InitMusicInfo(); /* music properties mapping */
InitGameModeMusicInfo(); /* game mode music mapping */
+ InitGlobalAnimMusicInfo(); /* global animation music settings */
}
static int get_special_property_bit(int element, int property_bit_nr)
ResolveGroupElementExt(group_element, 0);
}
-void InitElementPropertiesStatic()
+void InitElementPropertiesStatic(void)
{
+ static boolean clipboard_elements_initialized = FALSE;
+
static int ep_diggable[] =
{
EL_SAND,
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_SWITCHGATE_OPENING,
EL_SWITCHGATE_CLOSED,
EL_SWITCHGATE_CLOSING,
-#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 1
EL_DC_TIMEGATE_SWITCH,
EL_DC_TIMEGATE_SWITCH_ACTIVE,
-#endif
EL_TUBE_ANY,
EL_TUBE_VERTICAL,
EL_TUBE_HORIZONTAL,
EL_SOKOBAN_FIELD_EMPTY,
EL_EXIT_OPEN,
EL_EM_EXIT_OPEN,
+ EL_EM_EXIT_OPENING,
EL_SP_EXIT_OPEN,
EL_SP_EXIT_OPENING,
EL_STEEL_EXIT_OPEN,
EL_EM_STEEL_EXIT_OPEN,
+ EL_EM_STEEL_EXIT_OPENING,
EL_GATE_1,
EL_GATE_2,
EL_GATE_3,
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,
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_EM_GATE_2_GRAY_ACTIVE,
EL_EM_GATE_3_GRAY_ACTIVE,
EL_EM_GATE_4_GRAY_ACTIVE,
+ EL_EMC_GATE_5,
+ EL_EMC_GATE_6,
+ EL_EMC_GATE_7,
+ EL_EMC_GATE_8,
+ EL_EMC_GATE_5_GRAY,
+ EL_EMC_GATE_6_GRAY,
+ EL_EMC_GATE_7_GRAY,
+ EL_EMC_GATE_8_GRAY,
+ EL_EMC_GATE_5_GRAY_ACTIVE,
+ 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,
+ EL_DC_SWITCHGATE_SWITCH_UP,
+ EL_DC_SWITCHGATE_SWITCH_DOWN,
EL_TIMEGATE_OPEN,
EL_TIMEGATE_OPENING,
EL_TIMEGATE_CLOSED,
EL_TIMEGATE_CLOSING,
+ EL_DC_TIMEGATE_SWITCH,
+ EL_DC_TIMEGATE_SWITCH_ACTIVE,
EL_TUBE_ANY,
EL_TUBE_VERTICAL,
EL_TUBE_HORIZONTAL,
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
};
EL_PLAYER_2,
EL_PLAYER_3,
EL_PLAYER_4,
+ EL_SOKOBAN_FIELD_PLAYER,
EL_SP_MURPHY,
EL_YAMYAM,
EL_YAMYAM_LEFT,
EL_INTERNAL_CASCADE_SP_ACTIVE,
EL_INTERNAL_CASCADE_DC_ACTIVE,
EL_INTERNAL_CASCADE_DX_ACTIVE,
+ EL_INTERNAL_CASCADE_MM_ACTIVE,
+ EL_INTERNAL_CASCADE_DF_ACTIVE,
EL_INTERNAL_CASCADE_CHARS_ACTIVE,
EL_INTERNAL_CASCADE_STEEL_CHARS_ACTIVE,
EL_INTERNAL_CASCADE_CE_ACTIVE,
EL_INTERNAL_CASCADE_SP,
EL_INTERNAL_CASCADE_DC,
EL_INTERNAL_CASCADE_DX,
+ EL_INTERNAL_CASCADE_MM,
+ EL_INTERNAL_CASCADE_DF,
EL_INTERNAL_CASCADE_CHARS,
EL_INTERNAL_CASCADE_STEEL_CHARS,
EL_INTERNAL_CASCADE_CE,
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++)
/* 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)
/* 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) ||
if (IS_HISTORIC_SOLID(i) || i == EL_EXPLOSION)
SET_PROPERTY(i, EP_DRAGONFIRE_PROOF, TRUE);
else
- SET_PROPERTY(i, EP_DRAGONFIRE_PROOF, (IS_CUSTOM_ELEMENT(i) &&
- IS_INDESTRUCTIBLE(i)));
+ SET_PROPERTY(i, EP_DRAGONFIRE_PROOF, (IS_INDESTRUCTIBLE(i) &&
+ i != EL_ACID));
/* ---------- EXPLOSION_PROOF ------------------------------------------ */
if (i == EL_FLAMES)
HAS_ACTION(i)));
/* ---------- GFX_CRUMBLED --------------------------------------------- */
-#if 1
SET_PROPERTY(i, EP_GFX_CRUMBLED,
element_info[i].crumbled[ACTION_DEFAULT] !=
element_info[i].graphic[ACTION_DEFAULT]);
-#else
- /* !!! THIS LOOKS CRAPPY FOR SAND ETC. WITHOUT CRUMBLED GRAPHICS !!! */
- SET_PROPERTY(i, EP_GFX_CRUMBLED,
- element_info[i].crumbled[ACTION_DEFAULT] != IMG_EMPTY);
-#endif
/* ---------- EDITOR_CASCADE ------------------------------------------- */
SET_PROPERTY(i, EP_EDITOR_CASCADE, (IS_EDITOR_CASCADE_ACTIVE(i) ||
-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,
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 */
InitElementGraphicInfo();
}
-void InitElementPropertiesAfterLoading(int engine_version)
+void InitElementPropertiesGfxElement(void)
{
int i;
- /* 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;
+ struct ElementInfo *ei = &element_info[i];
- element_info[element].access_direction = MV_ALL_DIRECTIONS;
-
- element_info[element].explosion_delay = 17;
- element_info[element].ignition_delay = 8;
- }
+ ei->gfx_element = (ei->use_gfx_element ? ei->gfx_element_initial : i);
}
}
-static void InitGlobal()
+static void InitGlobal(void)
{
+ int graphic;
int i;
for (i = 0; i < MAX_NUM_ELEMENTS + 1; i++)
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;
+ }
-#if 0
- printf("%04d: %s\n", i, element_name_info[i].token_name);
-#endif
+ for (i = 0; i < NUM_GLOBAL_ANIM_TOKENS + 1; i++)
+ {
+ /* check if global_anim_name_info defined for each entry in "main.h" */
+ if (i < NUM_GLOBAL_ANIM_TOKENS &&
+ global_anim_name_info[i].token_name == NULL)
+ Error(ERR_EXIT, "undefined 'global_anim_name_info' entry for anim %d", i);
+
+ global_anim_info[i].token_name = global_anim_name_info[i].token_name;
+ }
+
+ /* 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, ".png") ||
+ 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));
+
+ /* set default filenames for all cloned graphics in static configuration */
+ for (i = 0; image_config[i].token != NULL; i++)
+ {
+ if (strEqual(image_config[i].value, UNDEFINED_FILENAME))
+ {
+ char *token = image_config[i].token;
+ char *token_clone_from = getStringCat2(token, ".clone_from");
+ char *token_cloned = getHashEntry(image_config_hash, token_clone_from);
+
+ if (token_cloned != NULL)
+ {
+ char *value_cloned = getHashEntry(image_config_hash, token_cloned);
+
+ if (value_cloned != NULL)
+ {
+ /* set default filename in static configuration */
+ image_config[i].value = value_cloned;
+
+ /* set default filename in image config hash */
+ setHashEntry(image_config_hash, token, value_cloned);
+ }
+ }
+
+ free(token_clone_from);
+ }
}
/* always start with reliable default values (all elements) */
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.show_frames_per_second = FALSE;
+
+ global.border_status = GAME_MODE_LOADING;
+ global.anim_status = global.anim_status_next = GAME_MODE_LOADING;
+
+ global.use_envelope_request = FALSE;
}
-void Execute_Command(char *command)
+static void Execute_Command(char *command)
{
int i;
if (strEqual(command, "print graphicsinfo.conf"))
{
- printf("# You can configure additional/alternative image files here.\n");
- printf("# (The entries below are default and therefore commented out.)\n");
- printf("\n");
- printf("%s\n", getFormattedSetupEntry("name", "Classic Graphics"));
- printf("\n");
- printf("%s\n", getFormattedSetupEntry("sort_priority", "100"));
- printf("\n");
+ Print("# You can configure additional/alternative image files here.\n");
+ Print("# (The entries below are default and therefore commented out.)\n");
+ Print("\n");
+ Print("%s\n", getFormattedSetupEntry("name", "Classic Graphics"));
+ Print("\n");
+ Print("%s\n", getFormattedSetupEntry("sort_priority", "100"));
+ Print("\n");
for (i = 0; image_config[i].token != NULL; i++)
- printf("# %s\n", getFormattedSetupEntry(image_config[i].token,
- image_config[i].value));
+ Print("# %s\n", getFormattedSetupEntry(image_config[i].token,
+ image_config[i].value));
exit(0);
}
else if (strEqual(command, "print soundsinfo.conf"))
{
- printf("# You can configure additional/alternative sound files here.\n");
- printf("# (The entries below are default and therefore commented out.)\n");
- printf("\n");
- printf("%s\n", getFormattedSetupEntry("name", "Classic Sounds"));
- printf("\n");
- printf("%s\n", getFormattedSetupEntry("sort_priority", "100"));
- printf("\n");
+ Print("# You can configure additional/alternative sound files here.\n");
+ Print("# (The entries below are default and therefore commented out.)\n");
+ Print("\n");
+ Print("%s\n", getFormattedSetupEntry("name", "Classic Sounds"));
+ Print("\n");
+ Print("%s\n", getFormattedSetupEntry("sort_priority", "100"));
+ Print("\n");
for (i = 0; sound_config[i].token != NULL; i++)
- printf("# %s\n", getFormattedSetupEntry(sound_config[i].token,
- sound_config[i].value));
+ Print("# %s\n", getFormattedSetupEntry(sound_config[i].token,
+ sound_config[i].value));
exit(0);
}
else if (strEqual(command, "print musicinfo.conf"))
{
- printf("# You can configure additional/alternative music files here.\n");
- printf("# (The entries below are default and therefore commented out.)\n");
- printf("\n");
- printf("%s\n", getFormattedSetupEntry("name", "Classic Music"));
- printf("\n");
- printf("%s\n", getFormattedSetupEntry("sort_priority", "100"));
- printf("\n");
+ Print("# You can configure additional/alternative music files here.\n");
+ Print("# (The entries below are default and therefore commented out.)\n");
+ Print("\n");
+ Print("%s\n", getFormattedSetupEntry("name", "Classic Music"));
+ Print("\n");
+ Print("%s\n", getFormattedSetupEntry("sort_priority", "100"));
+ Print("\n");
for (i = 0; music_config[i].token != NULL; i++)
- printf("# %s\n", getFormattedSetupEntry(music_config[i].token,
- music_config[i].value));
+ Print("# %s\n", getFormattedSetupEntry(music_config[i].token,
+ music_config[i].value));
exit(0);
}
else if (strEqual(command, "print editorsetup.conf"))
{
- printf("# You can configure your personal editor element list here.\n");
- printf("# (The entries below are default and therefore commented out.)\n");
- printf("\n");
+ Print("# You can configure your personal editor element list here.\n");
+ Print("# (The entries below are default and therefore commented out.)\n");
+ Print("\n");
/* this is needed to be able to check element list for cascade elements */
InitElementPropertiesStatic();
}
else if (strEqual(command, "print helpanim.conf"))
{
- printf("# You can configure different element help animations here.\n");
- printf("# (The entries below are default and therefore commented out.)\n");
- printf("\n");
+ Print("# You can configure different element help animations here.\n");
+ Print("# (The entries below are default and therefore commented out.)\n");
+ Print("\n");
for (i = 0; helpanim_config[i].token != NULL; i++)
{
- printf("# %s\n", getFormattedSetupEntry(helpanim_config[i].token,
- helpanim_config[i].value));
+ Print("# %s\n", getFormattedSetupEntry(helpanim_config[i].token,
+ helpanim_config[i].value));
if (strEqual(helpanim_config[i].token, "end"))
- printf("#\n");
+ Print("#\n");
}
exit(0);
}
else if (strEqual(command, "print helptext.conf"))
{
- printf("# You can configure different element help text here.\n");
- printf("# (The entries below are default and therefore commented out.)\n");
- printf("\n");
+ Print("# You can configure different element help text here.\n");
+ Print("# (The entries below are default and therefore commented out.)\n");
+ Print("\n");
for (i = 0; helptext_config[i].token != NULL; i++)
- printf("# %s\n", getFormattedSetupEntry(helptext_config[i].token,
- helptext_config[i].value));
+ Print("# %s\n", getFormattedSetupEntry(helptext_config[i].token,
+ helptext_config[i].value));
exit(0);
}
- else if (strncmp(command, "dump level ", 11) == 0)
+ else if (strPrefix(command, "dump level "))
{
char *filename = &command[11];
exit(0);
}
- else if (strncmp(command, "dump tape ", 10) == 0)
+ else if (strPrefix(command, "dump tape "))
{
char *filename = &command[10];
exit(0);
}
- else if (strncmp(command, "autoplay ", 9) == 0)
+ else if (strPrefix(command, "autotest ") ||
+ strPrefix(command, "autoplay ") ||
+ strPrefix(command, "autoffwd ") ||
+ strPrefix(command, "autowarp "))
{
char *str_ptr = getStringCopy(&command[9]); /* read command parameters */
+ global.autoplay_mode =
+ (strPrefix(command, "autotest") ? AUTOPLAY_MODE_TEST :
+ strPrefix(command, "autoplay") ? AUTOPLAY_MODE_PLAY :
+ strPrefix(command, "autoffwd") ? AUTOPLAY_MODE_FFWD :
+ strPrefix(command, "autowarp") ? AUTOPLAY_MODE_WARP :
+ AUTOPLAY_MODE_NONE);
+
while (*str_ptr != '\0') /* continue parsing string */
{
/* cut leading whitespace from string, replace it by string terminator */
while (*str_ptr != ' ' && *str_ptr != '\t' && *str_ptr != '\0')
str_ptr++;
}
+
+ if (global.autoplay_mode == AUTOPLAY_MODE_TEST)
+ program.headless = TRUE;
}
- 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;
*str_ptr++ = '\0'; /* terminate leveldir string */
global.convert_level_nr = atoi(str_ptr); /* get level_nr value */
}
- }
-#if DEBUG
-#if defined(TARGET_SDL)
- else if (strEqual(command, "SDL_ListModes"))
+ program.headless = TRUE;
+ }
+ else if (strPrefix(command, "create images "))
{
- 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");
+ global.create_images_dir = getStringCopy(&command[14]);
- for(i = 0; modes[i]; i++)
- printf(" %d x %d\n", modes[i]->w, modes[i]->h);
- }
+ 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 if (strPrefix(command, "create CE image "))
+ {
+ CreateCustomElementImages(&command[16]);
exit(0);
}
-#endif
-#endif
-
else
{
Error(ERR_EXIT_HELP, "unrecognized command '%s'", command);
}
+
+ /* disable networking if any valid command was recognized */
+ options.network = setup.network_mode = FALSE;
}
-static void InitSetup()
+static void InitSetup(void)
{
LoadSetup(); /* global setup info */
+ LoadSetup_AutoSetup(); /* global auto setup info */
/* set some options from setup file */
if (setup.options.verbose)
options.verbose = TRUE;
+
+ if (setup.debug.show_frames_per_second)
+ global.show_frames_per_second = TRUE;
}
-static void InitGameInfo()
+static void InitGameInfo(void)
{
game.restart_level = FALSE;
+ game.restart_game_message = NULL;
}
-static void InitPlayerInfo()
+static void InitPlayerInfo(void)
{
int i;
local_player = &stored_player[0];
for (i = 0; i < MAX_PLAYERS; i++)
- stored_player[i].connected = FALSE;
+ {
+ stored_player[i].connected_locally = FALSE;
+ stored_player[i].connected_network = FALSE;
+ }
- local_player->connected = TRUE;
+ local_player->connected_locally = TRUE;
}
-static void InitArtworkInfo()
+static void InitArtworkInfo(void)
{
LoadArtworkInfo();
}
return id_suffix;
}
-#if 0
-static char *get_element_class_token(int element)
+static void InitArtworkConfig(void)
{
- char *element_class_name = element_info[element].class_name;
- char *element_class_token = checked_malloc(strlen(element_class_name) + 3);
+ static char *image_id_prefix[MAX_NUM_ELEMENTS +
+ NUM_FONTS +
+ NUM_GLOBAL_ANIM_TOKENS + 1];
+ static char *sound_id_prefix[2 * MAX_NUM_ELEMENTS +
+ NUM_GLOBAL_ANIM_TOKENS + 1];
+ static char *music_id_prefix[NUM_MUSIC_PREFIXES +
+ NUM_GLOBAL_ANIM_TOKENS + 1];
+ static char *action_id_suffix[NUM_ACTIONS + 1];
+ static char *direction_id_suffix[NUM_DIRECTIONS_FULL + 1];
+ static char *special_id_suffix[NUM_SPECIAL_GFX_ARGS + 1];
+ static char *level_id_suffix[MAX_LEVELS + 1];
+ static char *dummy[1] = { NULL };
+ static char *ignore_generic_tokens[] =
+ {
+ "name",
+ "sort_priority",
+ "program_title",
+ "program_copyright",
+ "program_company",
- sprintf(element_class_token, "[%s]", element_class_name);
-
- return element_class_token;
-}
-
-static char *get_action_class_token(int action)
-{
- char *action_class_name = &element_action_info[action].suffix[1];
- char *action_class_token = checked_malloc(strlen(action_class_name) + 3);
-
- sprintf(action_class_token, "[%s]", action_class_name);
-
- return action_class_token;
-}
-#endif
-
-static void InitArtworkConfig()
-{
- static char *image_id_prefix[MAX_NUM_ELEMENTS + NUM_FONTS + 1];
- static char *sound_id_prefix[2 * MAX_NUM_ELEMENTS + 1];
- static char *music_id_prefix[NUM_MUSIC_PREFIXES + 1];
- static char *action_id_suffix[NUM_ACTIONS + 1];
- static char *direction_id_suffix[NUM_DIRECTIONS_FULL + 1];
- static char *special_id_suffix[NUM_SPECIAL_GFX_ARGS + 1];
- static char *level_id_suffix[MAX_LEVELS + 1];
- static char *dummy[1] = { NULL };
- static char *ignore_generic_tokens[] =
- {
- "name",
- "sort_priority",
NULL
};
static char **ignore_image_tokens;
image_id_prefix[i] = element_info[i].token_name;
for (i = 0; i < NUM_FONTS; i++)
image_id_prefix[MAX_NUM_ELEMENTS + i] = font_info[i].token_name;
- image_id_prefix[MAX_NUM_ELEMENTS + NUM_FONTS] = NULL;
+ for (i = 0; i < NUM_GLOBAL_ANIM_TOKENS; i++)
+ image_id_prefix[MAX_NUM_ELEMENTS + NUM_FONTS + i] =
+ global_anim_info[i].token_name;
+ image_id_prefix[MAX_NUM_ELEMENTS + NUM_FONTS + NUM_GLOBAL_ANIM_TOKENS] = NULL;
for (i = 0; i < MAX_NUM_ELEMENTS; i++)
sound_id_prefix[i] = element_info[i].token_name;
for (i = 0; i < MAX_NUM_ELEMENTS; i++)
sound_id_prefix[MAX_NUM_ELEMENTS + i] =
get_string_in_brackets(element_info[i].class_name);
- sound_id_prefix[2 * MAX_NUM_ELEMENTS] = NULL;
+ for (i = 0; i < NUM_GLOBAL_ANIM_TOKENS; i++)
+ sound_id_prefix[2 * MAX_NUM_ELEMENTS + i] =
+ global_anim_info[i].token_name;
+ sound_id_prefix[2 * MAX_NUM_ELEMENTS + NUM_GLOBAL_ANIM_TOKENS] = NULL;
for (i = 0; i < NUM_MUSIC_PREFIXES; i++)
music_id_prefix[i] = music_prefix_info[i].prefix;
- music_id_prefix[NUM_MUSIC_PREFIXES] = NULL;
+ for (i = 0; i < NUM_GLOBAL_ANIM_TOKENS; i++)
+ music_id_prefix[NUM_MUSIC_PREFIXES + i] =
+ global_anim_info[i].token_name;
+ music_id_prefix[NUM_MUSIC_PREFIXES + NUM_GLOBAL_ANIM_TOKENS] = NULL;
for (i = 0; i < NUM_ACTIONS; i++)
action_id_suffix[i] = element_action_info[i].suffix;
sound_id_prefix, action_id_suffix, dummy,
special_id_suffix, ignore_sound_tokens);
InitMusicList(music_config, NUM_MUSIC_FILES, music_config_suffix,
- music_id_prefix, special_id_suffix, level_id_suffix,
- dummy, ignore_music_tokens);
+ music_id_prefix, action_id_suffix, special_id_suffix,
+ level_id_suffix, ignore_music_tokens);
}
-static void InitMixer()
+static void InitMixer(void)
{
OpenAudio();
+
StartMixer();
}
-void InitGfx()
+static void InitVideoOverlay(void)
{
+ // if virtual buttons are not loaded from setup file, repeat initializing
+ // virtual buttons grid with default values now that video is initialized
+ if (!setup.touch.grid_initialized)
+ InitSetup();
+
+ InitTileCursorInfo();
+ InitOverlayInfo();
+}
+
+void InitGfxBuffers(void)
+{
+ static int win_xsize_last = -1;
+ static int win_ysize_last = -1;
+
+ /* create additional image buffers for double-buffering and cross-fading */
+
+ if (WIN_XSIZE != win_xsize_last || WIN_YSIZE != win_ysize_last)
+ {
+ /* used to temporarily store the backbuffer -- only re-create if changed */
+ ReCreateBitmap(&bitmap_db_store_1, WIN_XSIZE, WIN_YSIZE);
+ ReCreateBitmap(&bitmap_db_store_2, WIN_XSIZE, WIN_YSIZE);
+
+ win_xsize_last = WIN_XSIZE;
+ win_ysize_last = WIN_YSIZE;
+ }
+
+ ReCreateBitmap(&bitmap_db_field, FXSIZE, FYSIZE);
+ ReCreateBitmap(&bitmap_db_panel, DXSIZE, DYSIZE);
+ ReCreateBitmap(&bitmap_db_door_1, 3 * DXSIZE, DYSIZE);
+ ReCreateBitmap(&bitmap_db_door_2, 3 * VXSIZE, VYSIZE);
+
+ /* initialize screen properties */
+ InitGfxFieldInfo(SX, SY, SXSIZE, SYSIZE,
+ REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE,
+ bitmap_db_field);
+ InitGfxDoor1Info(DX, DY, DXSIZE, DYSIZE);
+ InitGfxDoor2Info(VX, VY, VXSIZE, VYSIZE);
+ InitGfxDoor3Info(EX, EY, EXSIZE, EYSIZE);
+ InitGfxWindowInfo(WIN_XSIZE, WIN_YSIZE);
+ InitGfxScrollbufferInfo(FXSIZE, FYSIZE);
+ InitGfxClipRegion(FALSE, -1, -1, -1, -1);
+
+ /* required if door size definitions have changed */
+ InitGraphicCompatibilityInfo_Doors();
+
+ InitGfxBuffers_EM();
+ InitGfxBuffers_SP();
+}
+
+static void InitGfx(void)
+{
+ 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) */
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);
}
}
if (filename_font_initial == NULL) /* should not happen */
Error(ERR_EXIT, "cannot get filename for '%s'", CONFIG_TOKEN_FONT_INITIAL);
- /* create additional image buffers for double-buffering and cross-fading */
- bitmap_db_cross = CreateBitmap(WIN_XSIZE, WIN_YSIZE, DEFAULT_DEPTH);
- bitmap_db_field = CreateBitmap(FXSIZE, FYSIZE, DEFAULT_DEPTH);
- bitmap_db_panel = CreateBitmap(DXSIZE, DYSIZE, DEFAULT_DEPTH);
- bitmap_db_door = CreateBitmap(3 * DXSIZE, DYSIZE + VYSIZE, DEFAULT_DEPTH);
-
- /* initialize screen properties */
- InitGfxFieldInfo(SX, SY, SXSIZE, SYSIZE,
- REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE,
- bitmap_db_field);
- InitGfxDoor1Info(DX, DY, DXSIZE, DYSIZE);
- InitGfxDoor2Info(VX, VY, VXSIZE, VYSIZE);
- InitGfxScrollbufferInfo(FXSIZE, FYSIZE);
+ InitGfxBuffers();
+ InitGfxCustomArtworkInfo();
+ InitGfxOtherSettings();
bitmap_font_initial = LoadCustomImage(filename_font_initial);
InitFontGraphicInfo();
- font_height = getFontHeight(FC_RED);
-
-#if 1
- DrawInitText(getWindowTitleString(), 20, FC_YELLOW);
-#else
- DrawInitText(getProgramInitString(), 20, FC_YELLOW);
-#endif
- DrawInitText(PROGRAM_COPYRIGHT_STRING, 50, FC_RED);
- DrawInitText(PROGRAM_WEBSITE_STRING, WIN_YSIZE - 20 - font_height, FC_RED);
+ DrawProgramInfo();
DrawInitText("Loading graphics", 120, FC_GREEN);
-}
-void RedrawBackground()
-{
- BlitBitmap(graphic_info[IMG_GLOBAL_BORDER].bitmap, backbuffer,
- 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
+ /* initialize settings for busy animation with default values */
+ int parameter[NUM_GFX_ARGS];
+ for (i = 0; i < NUM_GFX_ARGS; i++)
+ parameter[i] = get_graphic_parameter_value(image_config_suffix[i].value,
+ image_config_suffix[i].token,
+ image_config_suffix[i].type);
- redraw_mask = REDRAW_ALL;
+ char *anim_token = CONFIG_TOKEN_GLOBAL_BUSY;
+ int len_anim_token = strlen(anim_token);
+
+ /* read settings for busy animation from default custom artwork config */
+ char *gfx_config_filename = getPath3(options.graphics_directory,
+ GFX_DEFAULT_SUBDIR,
+ GRAPHICSINFO_FILENAME);
+
+ if (fileExists(gfx_config_filename))
+ {
+ SetupFileHash *setup_file_hash = loadSetupFileHash(gfx_config_filename);
+
+ if (setup_file_hash)
+ {
+ char *filename = getHashEntry(setup_file_hash, anim_token);
+
+ if (filename)
+ {
+ filename_anim_initial = getStringCopy(filename);
+
+ for (j = 0; image_config_suffix[j].token != NULL; j++)
+ {
+ int type = image_config_suffix[j].type;
+ char *suffix = image_config_suffix[j].token;
+ char *token = getStringCat2(anim_token, suffix);
+ char *value = getHashEntry(setup_file_hash, token);
+
+ checked_free(token);
+
+ if (value)
+ parameter[j] = get_graphic_parameter_value(value, suffix, type);
+ }
+ }
+
+ freeSetupFileHash(setup_file_hash);
+ }
+ }
+
+ if (filename_anim_initial == NULL)
+ {
+ /* read settings for busy animation from static default artwork config */
+ for (i = 0; image_config[i].token != NULL; i++)
+ {
+ if (strEqual(image_config[i].token, anim_token))
+ filename_anim_initial = getStringCopy(image_config[i].value);
+ else if (strlen(image_config[i].token) > len_anim_token &&
+ strncmp(image_config[i].token, anim_token, len_anim_token) == 0)
+ {
+ 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);
+ }
+ }
+ }
+ }
+
+ if (filename_anim_initial == NULL) /* should not happen */
+ Error(ERR_EXIT, "cannot get filename for '%s'", CONFIG_TOKEN_GLOBAL_BUSY);
+
+ anim_initial.bitmaps =
+ checked_calloc(sizeof(Bitmap *) * NUM_IMG_BITMAP_POINTERS);
+
+ anim_initial.bitmaps[IMG_BITMAP_STANDARD] =
+ LoadCustomImage(filename_anim_initial);
+
+ checked_free(filename_anim_initial);
+
+ graphic_info = &anim_initial; /* graphic == 0 => anim_initial */
+
+ set_graphic_parameters_ext(0, parameter, anim_initial.bitmaps);
+
+ graphic_info = graphic_info_last;
+
+ init.busy.width = anim_initial.width;
+ init.busy.height = anim_initial.height;
+
+ InitMenuDesignSettings_Static();
+
+ InitGfxDrawBusyAnimFunction(DrawInitAnim);
+ InitGfxDrawGlobalAnimFunction(DrawGlobalAnimations);
+ InitGfxDrawGlobalBorderFunction(DrawMaskedBorderToTarget);
+ InitGfxDrawTileCursorFunction(DrawTileCursor);
+
+ gfx.fade_border_source_status = global.border_status;
+ gfx.fade_border_target_status = global.border_status;
+ gfx.masked_border_bitmap_ptr = backbuffer;
+
+ /* use copy of busy animation to prevent change while reloading artwork */
+ init_last = init;
}
-void InitGfxBackground()
+static void InitGfxBackground(void)
{
- int x, y;
-
fieldbuffer = bitmap_db_field;
- SetDrawtoField(DRAW_BACKBUFFER);
+ SetDrawtoField(DRAW_TO_BACKBUFFER);
-#if 1
ClearRectangle(backbuffer, 0, 0, WIN_XSIZE, WIN_YSIZE);
-#else
- RedrawBackground();
- ClearRectangle(backbuffer, REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE);
- ClearRectangle(bitmap_db_door, 0, 0, 3 * DXSIZE, DYSIZE + VYSIZE);
-#endif
-
- for (x = 0; x < MAX_BUF_XSIZE; x++)
- for (y = 0; y < MAX_BUF_YSIZE; y++)
- redraw[x][y] = 0;
- redraw_tiles = 0;
redraw_mask = REDRAW_ALL;
}
-static void InitLevelInfo()
+static void InitLevelInfo(void)
{
LoadLevelInfo(); /* global level info */
LoadLevelSetup_LastSeries(); /* last played series info */
LoadLevelSetup_SeriesInfo(); /* last played level info */
+
+ if (global.autoplay_leveldir &&
+ global.autoplay_mode != AUTOPLAY_MODE_TEST)
+ {
+ leveldir_current = getTreeInfoFromIdentifier(leveldir_first,
+ global.autoplay_leveldir);
+ if (leveldir_current == NULL)
+ leveldir_current = getFirstValidTreeInfoEntry(leveldir_first);
+ }
+
+ SetLevelSetInfo(leveldir_current->identifier, level_nr);
}
-void InitLevelArtworkInfo()
+static void InitLevelArtworkInfo(void)
{
LoadLevelArtworkInfo();
}
-static void InitImages()
+static void InitImages(void)
{
+ 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,
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");
+
+ LoadMenuDesignSettings_AfterGraphics();
+ print_timestamp_time("LoadMenuDesignSettings_AfterGraphics");
+
+ UPDATE_BUSY_STATE();
+
+ print_timestamp_done("InitImages");
}
static void InitSound(char *identifier)
{
+ print_timestamp_init("InitSound");
+
if (identifier == NULL)
identifier = artwork.snd_current->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;
setLevelArtworkDir(artwork.mus_first);
InitReloadCustomMusic(identifier);
+ print_timestamp_time("InitReloadCustomMusic");
+
ReinitializeMusic();
+ print_timestamp_time("ReinitializeMusic");
+
+ print_timestamp_done("InitMusic");
}
-void InitNetworkServer()
+static void InitArtworkDone(void)
{
-#if defined(NETWORK_AVALIABLE)
- int nr_wanted;
-#endif
+ if (program.headless)
+ return;
+
+ InitGlobalAnimations();
+}
+
+static void InitNetworkSettings(void)
+{
+ boolean network_enabled = (options.network || setup.network_mode);
+ char *network_server = (options.server_host != NULL ? options.server_host :
+ setup.network_server_hostname);
+
+ if (strEqual(network_server, STR_NETWORK_AUTO_DETECT))
+ network_server = NULL;
+
+ InitNetworkInfo(network_enabled,
+ FALSE,
+ options.serveronly,
+ network_server,
+ options.server_port);
+}
- if (!options.network)
+void InitNetworkServer(void)
+{
+ if (!network.enabled || network.connected)
return;
-#if defined(NETWORK_AVALIABLE)
- nr_wanted = Request("Choose player", REQ_PLAYER | REQ_STAY_CLOSED);
+ LimitScreenUpdates(FALSE);
+
+ if (game_status == GAME_MODE_LOADING)
+ DrawProgramInfo();
+
+ if (!ConnectToServer(network.server_host, network.server_port))
+ {
+ network.enabled = FALSE;
+
+ setup.network_mode = FALSE;
+ }
+ else
+ {
+ SendToServer_ProtocolVersion();
+ SendToServer_PlayerName(setup.player_name);
+ SendToServer_NrWanted(setup.network_player_nr + 1);
+
+ network.connected = TRUE;
+ }
+
+ /* short time to recognize result of network initialization */
+ if (game_status == GAME_MODE_LOADING)
+ Delay_WithScreenUpdates(1000);
+}
+
+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);
- if (!ConnectToServer(options.server_host, options.server_port))
- Error(ERR_EXIT, "cannot connect to network game server");
+ filename_local = getCustomArtworkConfigFilename(type);
- SendToServer_PlayerName(setup.player_name);
- SendToServer_ProtocolVersion();
+#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(void)
+{
+ 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 (nr_wanted)
- SendToServer_NrWanted(nr_wanted);
+#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 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);
- boolean setup_override_artwork = SETUP_OVERRIDE_ARTWORK(setup, type);
+ boolean setup_override_artwork = GFX_OVERRIDE_ARTWORK(type);
char *setup_artwork_set = SETUP_ARTWORK_SET(setup, type);
char *leveldir_identifier = leveldir_current->identifier;
-#if 1
/* !!! setLevelArtworkDir() should be moved to an earlier stage !!! */
char *leveldir_artwork_set = setLevelArtworkDir(artwork_first_node);
-#else
- char *leveldir_artwork_set = LEVELDIR_ARTWORK_SET(leveldir_current, type);
-#endif
boolean has_level_artwork_set = (leveldir_artwork_set != NULL);
char *artwork_current_identifier;
char *artwork_new_identifier = NULL; /* default: nothing has changed */
/* 2nd step: check if it is really needed to reload artwork set
------------------------------------------------------------ */
-#if 0
- if (type == ARTWORK_TYPE_GRAPHICS)
- printf("::: 0: '%s' ['%s', '%s'] ['%s' ('%s')]\n",
- artwork_new_identifier,
- ARTWORK_CURRENT_IDENTIFIER(artwork, type),
- artwork_current_identifier,
- leveldir_current->graphics_set,
- leveldir_current->identifier);
-#endif
-
/* ---------- reload if level set and also artwork set has changed ------- */
if (leveldir_current_identifier[type] != leveldir_identifier &&
(last_has_level_artwork_set[type] || has_level_artwork_set))
leveldir_current_identifier[type] = leveldir_identifier;
last_has_level_artwork_set[type] = has_level_artwork_set;
-#if 0
- if (type == ARTWORK_TYPE_GRAPHICS)
- printf("::: 1: '%s'\n", artwork_new_identifier);
-#endif
-
/* ---------- reload if "override artwork" setting has changed ----------- */
if (last_override_level_artwork[type] != setup_override_artwork)
artwork_new_identifier = artwork_current_identifier;
last_override_level_artwork[type] = setup_override_artwork;
-#if 0
- if (type == ARTWORK_TYPE_GRAPHICS)
- printf("::: 2: '%s'\n", artwork_new_identifier);
-#endif
-
/* ---------- reload if current artwork identifier has changed ----------- */
if (!strEqual(ARTWORK_CURRENT_IDENTIFIER(artwork, type),
artwork_current_identifier))
*(ARTWORK_CURRENT_IDENTIFIER_PTR(artwork, type))= artwork_current_identifier;
-#if 0
- if (type == ARTWORK_TYPE_GRAPHICS)
- printf("::: 3: '%s'\n", artwork_new_identifier);
-#endif
-
/* ---------- do not reload directly after starting ---------------------- */
if (!initialized[type])
artwork_new_identifier = NULL;
initialized[type] = TRUE;
-#if 0
- if (type == ARTWORK_TYPE_GRAPHICS)
- printf("::: 4: '%s'\n", artwork_new_identifier);
-#endif
-
-#if 0
- if (type == ARTWORK_TYPE_GRAPHICS)
- printf("CHECKING OLD/NEW GFX:\n- OLD: %s\n- NEW: %s ['%s', '%s'] ['%s']\n",
- artwork.gfx_current_identifier, artwork_current_identifier,
- artwork.gfx_current->identifier, leveldir_current->graphics_set,
- artwork_new_identifier);
-#endif
-
return artwork_new_identifier;
}
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();
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");
+
+ SetGameStatus(GAME_MODE_LOADING);
+
+ FadeOut(REDRAW_ALL);
+
+ ClearRectangle(drawto, 0, 0, WIN_XSIZE, WIN_YSIZE);
+ print_timestamp_time("ClearRectangle");
+
+ FadeIn(REDRAW_ALL);
+
if (gfx_new_identifier != NULL || force_reload_gfx)
{
#if 0
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();
+ InitArtworkDone();
- /* force redraw of (open or closed) door graphics */
- SetDoorState(DOOR_OPEN_ALL);
- CloseDoor(DOOR_CLOSE_ALL | DOOR_NO_DELAY);
+ SetGameStatus(last_game_status); /* restore current game status */
-#if 1
-#if 1
- FadeSetEnterScreen();
- // FadeSkipNextFadeOut();
- // FadeSetDisabled();
-#else
- FadeSkipNext();
-#endif
-#else
- fading = fading_none;
-#endif
- }
+ init_last = init; /* switch to new busy animation */
+
+ FadeOut(REDRAW_ALL);
+
+ RedrawGlobalBorder();
+
+ /* force redraw of (open or closed) door graphics */
+ SetDoorState(DOOR_OPEN_ALL);
+ CloseDoor(DOOR_CLOSE_ALL | DOOR_NO_DELAY);
+
+ FadeSetEnterScreen();
+ FadeSkipNextFadeOut();
+
+ print_timestamp_done("ReloadCustomArtwork");
+
+ LimitScreenUpdates(FALSE);
}
-void KeyboardAutoRepeatOffUnlessAutoplay()
+void KeyboardAutoRepeatOffUnlessAutoplay(void)
{
if (global.autoplay_leveldir == NULL)
KeyboardAutoRepeatOff();
}
+void DisplayExitMessage(char *format, va_list ap)
+{
+ // also check for initialized video (headless flag may be temporarily unset)
+ if (program.headless || !video.initialized)
+ return;
+
+ // check if draw buffer and fonts for exit message are already available
+ if (drawto == NULL || font_initial[NUM_INITIAL_FONTS - 1].bitmap == NULL)
+ return;
+
+ int font_1 = FC_RED;
+ int font_2 = FC_YELLOW;
+ int font_3 = FC_BLUE;
+ int font_width = getFontWidth(font_2);
+ int font_height = getFontHeight(font_2);
+ int sx = SX;
+ int sy = SY;
+ int sxsize = WIN_XSIZE - 2 * sx;
+ int sysize = WIN_YSIZE - 2 * sy;
+ int line_length = sxsize / font_width;
+ int max_lines = sysize / font_height;
+ int num_lines_printed;
+
+ gfx.sx = sx;
+ gfx.sy = sy;
+ gfx.sxsize = sxsize;
+ gfx.sysize = sysize;
+
+ sy = 20;
+
+ ClearRectangle(drawto, 0, 0, WIN_XSIZE, WIN_YSIZE);
+
+ DrawTextSCentered(sy, font_1, "Fatal error:");
+ sy += 3 * font_height;;
+
+ num_lines_printed =
+ DrawTextBufferVA(sx, sy, format, ap, font_2,
+ line_length, line_length, max_lines,
+ 0, BLIT_ON_BACKGROUND, TRUE, TRUE, FALSE);
+ sy += (num_lines_printed + 3) * font_height;
+
+ DrawTextSCentered(sy, font_1, "For details, see the following error file:");
+ sy += 3 * font_height;
+
+ num_lines_printed =
+ DrawTextBuffer(sx, sy, program.log_filename[LOG_ERR_ID], font_2,
+ line_length, line_length, max_lines,
+ 0, BLIT_ON_BACKGROUND, TRUE, TRUE, FALSE);
+
+ DrawTextSCentered(SYSIZE - 20, font_3, "Press any key or button to exit");
+
+ redraw_mask = REDRAW_ALL;
+
+ /* force drawing exit message even if screen updates are currently limited */
+ LimitScreenUpdates(FALSE);
+
+ BackToFront();
+
+ /* deactivate toons on error message screen */
+ setup.toons = FALSE;
+
+ WaitForEventToContinue();
+}
+
/* ========================================================================= */
/* OpenAll() */
/* ========================================================================= */
-void OpenAll()
+void OpenAll(void)
{
+ print_timestamp_init("OpenAll");
+
+ SetGameStatus(GAME_MODE_LOADING);
+
+ InitCounter();
+
InitGlobal(); /* initialize some global variables */
+ print_timestamp_time("[init global stuff]");
+
+ InitSetup();
+
+ print_timestamp_time("[init setup/config stuff (1)]");
+
+ InitScoresInfo();
+
if (options.execute_command)
Execute_Command(options.execute_command);
- if (options.serveronly)
+ InitNetworkSettings();
+
+ if (network.serveronly)
{
#if defined(PLATFORM_UNIX)
- NetworkServer(options.server_port, options.serveronly);
+ NetworkServer(network.server_port, TRUE);
#else
Error(ERR_WARN, "networking only supported in Unix version");
#endif
exit(0); /* never reached, server loops forever */
}
- InitSetup();
-
InitGameInfo();
+ print_timestamp_time("[init setup/config stuff (2)]");
InitPlayerInfo();
+ print_timestamp_time("[init setup/config stuff (3)]");
InitArtworkInfo(); /* needed before loading gfx, sound & music */
+ print_timestamp_time("[init setup/config stuff (4)]");
InitArtworkConfig(); /* needed before forking sound child process */
+ print_timestamp_time("[init setup/config stuff (5)]");
InitMixer();
-
- InitCounter();
+ print_timestamp_time("[init setup/config stuff (6)]");
InitRND(NEW_RANDOMIZE);
InitSimpleRandom(NEW_RANDOMIZE);
InitJoysticks();
+ print_timestamp_time("[init setup/config stuff]");
+
+ InitVideoDefaults();
InitVideoDisplay();
InitVideoBuffer(WIN_XSIZE, WIN_YSIZE, DEFAULT_DEPTH, setup.fullscreen);
+ InitVideoOverlay();
- InitEventFilter(FilterMouseMotionEvents);
+ print_timestamp_time("[init video stuff]");
InitElementPropertiesStatic();
InitElementPropertiesEngine(GAME_VERSION_ACTUAL);
+ InitElementPropertiesGfxElement();
+
+ print_timestamp_time("[init element properties stuff]");
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");
+
+ InitArtworkDone();
InitGfxBackground();
-#if 1
em_open_all();
-#endif
+ sp_open_all();
+ mm_open_all();
if (global.autoplay_leveldir)
{
ConvertLevels();
return;
}
+ else if (global.create_images_dir)
+ {
+ CreateLevelSketchImages();
+ return;
+ }
- game_status = GAME_MODE_MAIN;
+ InitNetworkServer();
+
+ SetGameStatus(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();
+#if 0
+ Error(ERR_DEBUG, "::: SDL_GetBasePath() == '%s'",
+ SDL_GetBasePath());
+ Error(ERR_DEBUG, "::: SDL_GetPrefPath() == '%s'",
+ SDL_GetPrefPath("artsoft", "rocksndiamonds"));
+#if defined(PLATFORM_ANDROID)
+ Error(ERR_DEBUG, "::: SDL_AndroidGetInternalStoragePath() == '%s'",
+ SDL_AndroidGetInternalStoragePath());
+ Error(ERR_DEBUG, "::: SDL_AndroidGetExternalStoragePath() == '%s'",
+ SDL_AndroidGetExternalStoragePath());
+ Error(ERR_DEBUG, "::: SDL_AndroidGetExternalStorageState() == '%s'",
+ (SDL_AndroidGetExternalStorageState() &
+ SDL_ANDROID_EXTERNAL_STORAGE_WRITE ? "writable" :
+ SDL_AndroidGetExternalStorageState() &
+ SDL_ANDROID_EXTERNAL_STORAGE_READ ? "readable" : "not available"));
+#endif
+#endif
}
void CloseAllAndExit(int exit_value)
FreeAllMusic();
CloseAudio(); /* called after freeing sounds (needed for SDL) */
-#if 1
em_close_all();
-#endif
+ sp_close_all();
FreeAllImages();
#if defined(TARGET_SDL)
+#if defined(TARGET_SDL2)
+ // !!! TODO !!!
+ // set a flag to tell the network server thread to quit and wait for it
+ // using SDL_WaitThread()
+#else
if (network_server) /* terminate network server */
SDL_KillThread(server_thread);
+#endif
#endif
CloseVideoDisplay();
ClosePlatformDependentStuff();
- if (exit_value != 0)
- NotifyUserAboutErrorFile();
+ if (exit_value != 0 && !options.execute_command)
+ {
+ /* fall back to default level set (current set may have caused an error) */
+ SaveLevelSetup_LastSeries_Deactivate();
+
+ /* tell user where to find error log file which may contain more details */
+ // (error notification now directly displayed on screen inside R'n'D
+ // NotifyUserAboutErrorFile(); /* currently only works for Windows */
+ }
exit(exit_value);
}