StopGlobalAnimMusic(part);
}
-static boolean matchesAnimEventMask(int bits, int mask)
-{
- return (bits & (mask & ANIM_EVENT_CLICK_ANIM_ALL) &&
- bits & (mask & ANIM_EVENT_CLICK_PART_ALL));
-}
-
static boolean isClickablePart(struct GlobalAnimPartControlInfo *part, int mask)
{
struct GraphicInfo *c = &part->control_info;
-
- boolean clickable_any = FALSE;
- boolean clickable_self = FALSE;
- boolean clickable_triggered = FALSE;
-
- if (mask & ANIM_EVENT_CLICK_ANY)
- clickable_any = (c->init_event & ANIM_EVENT_CLICK_ANY ||
- c->anim_event & ANIM_EVENT_CLICK_ANY);
-
- if (mask & ANIM_EVENT_CLICK_SELF)
- clickable_self = (c->init_event & ANIM_EVENT_CLICK_SELF ||
- c->anim_event & ANIM_EVENT_CLICK_SELF);
-
- clickable_triggered = (matchesAnimEventMask(c->init_event, mask) ||
- matchesAnimEventMask(c->anim_event, mask));
-
- return (clickable_any || clickable_self || clickable_triggered);
+ int trigger_mask = ANIM_EVENT_ANIM_MASK | ANIM_EVENT_PART_MASK;
+ int mask_anim_only = mask & ANIM_EVENT_ANIM_MASK;
+
+ if (mask & ANIM_EVENT_ANY)
+ return (c->init_event & ANIM_EVENT_ANY ||
+ c->anim_event & ANIM_EVENT_ANY);
+ else if (mask & ANIM_EVENT_SELF)
+ return (c->init_event & ANIM_EVENT_SELF ||
+ c->anim_event & ANIM_EVENT_SELF);
+ else
+ return ((c->init_event & trigger_mask) == mask ||
+ (c->anim_event & trigger_mask) == mask ||
+ (c->init_event & trigger_mask) == mask_anim_only ||
+ (c->anim_event & trigger_mask) == mask_anim_only);
}
static boolean isClickedPart(struct GlobalAnimPartControlInfo *part,
if (!part->clickable)
continue;
- if (isClickablePart(part, ANIM_EVENT_CLICK_ANY))
+ if (isClickablePart(part, ANIM_EVENT_ANY))
any_part_clicked = part->clicked = TRUE;
if (isClickedPart(part, mx, my, clicked))
printf("::: %d.%d CLICKED\n", anim_nr, part_nr);
#endif
- if (isClickablePart(part, ANIM_EVENT_CLICK_SELF))
+ if (isClickablePart(part, ANIM_EVENT_SELF))
any_part_clicked = part->clicked = TRUE;
// check if this click is defined to trigger other animations
- int old_anim_nr = part->old_anim_nr;
- int old_part_nr = part->old_nr;
- int mask = ANIM_EVENT_CLICK_ANIM_1 << old_anim_nr;
-
- if (part->is_base)
- mask |= ANIM_EVENT_CLICK_PART_ALL;
- else
- mask |= ANIM_EVENT_CLICK_PART_1 << old_part_nr;
+ int gic_anim_nr = part->old_anim_nr + 1; // X as in "anim_X"
+ int gic_part_nr = part->old_nr + 1; // Y as in "part_Y"
+ int mask = gic_anim_nr << ANIM_EVENT_ANIM_BIT;
+
+ if (!part->is_base)
+ mask |= gic_part_nr << ANIM_EVENT_PART_BIT;
int anim2_nr;
{ "gfx.global.anim_6", UNDEFINED_FILENAME },
{ "gfx.global.anim_7", UNDEFINED_FILENAME },
{ "gfx.global.anim_8", UNDEFINED_FILENAME },
+ { "gfx.global.anim_9", UNDEFINED_FILENAME },
+ { "gfx.global.anim_10", UNDEFINED_FILENAME },
+ { "gfx.global.anim_11", UNDEFINED_FILENAME },
+ { "gfx.global.anim_12", UNDEFINED_FILENAME },
+ { "gfx.global.anim_13", UNDEFINED_FILENAME },
+ { "gfx.global.anim_14", UNDEFINED_FILENAME },
+ { "gfx.global.anim_15", UNDEFINED_FILENAME },
+ { "gfx.global.anim_16", UNDEFINED_FILENAME },
+ { "gfx.global.anim_17", UNDEFINED_FILENAME },
+ { "gfx.global.anim_18", UNDEFINED_FILENAME },
+ { "gfx.global.anim_19", UNDEFINED_FILENAME },
+ { "gfx.global.anim_20", UNDEFINED_FILENAME },
+ { "gfx.global.anim_21", UNDEFINED_FILENAME },
+ { "gfx.global.anim_22", UNDEFINED_FILENAME },
+ { "gfx.global.anim_23", UNDEFINED_FILENAME },
+ { "gfx.global.anim_24", UNDEFINED_FILENAME },
+ { "gfx.global.anim_25", UNDEFINED_FILENAME },
+ { "gfx.global.anim_26", UNDEFINED_FILENAME },
+ { "gfx.global.anim_27", UNDEFINED_FILENAME },
+ { "gfx.global.anim_28", UNDEFINED_FILENAME },
+ { "gfx.global.anim_29", UNDEFINED_FILENAME },
+ { "gfx.global.anim_30", UNDEFINED_FILENAME },
+ { "gfx.global.anim_31", UNDEFINED_FILENAME },
+ { "gfx.global.anim_32", UNDEFINED_FILENAME },
{ "global.anim_1", UNDEFINED_FILENAME },
{ "global.anim_2", UNDEFINED_FILENAME },
{ "global.anim_6", UNDEFINED_FILENAME },
{ "global.anim_7", UNDEFINED_FILENAME },
{ "global.anim_8", UNDEFINED_FILENAME },
+ { "global.anim_9", UNDEFINED_FILENAME },
+ { "global.anim_10", UNDEFINED_FILENAME },
+ { "global.anim_11", UNDEFINED_FILENAME },
+ { "global.anim_12", UNDEFINED_FILENAME },
+ { "global.anim_13", UNDEFINED_FILENAME },
+ { "global.anim_14", UNDEFINED_FILENAME },
+ { "global.anim_15", UNDEFINED_FILENAME },
+ { "global.anim_16", UNDEFINED_FILENAME },
+ { "global.anim_17", UNDEFINED_FILENAME },
+ { "global.anim_18", UNDEFINED_FILENAME },
+ { "global.anim_19", UNDEFINED_FILENAME },
+ { "global.anim_20", UNDEFINED_FILENAME },
+ { "global.anim_21", UNDEFINED_FILENAME },
+ { "global.anim_22", UNDEFINED_FILENAME },
+ { "global.anim_23", UNDEFINED_FILENAME },
+ { "global.anim_24", UNDEFINED_FILENAME },
+ { "global.anim_25", UNDEFINED_FILENAME },
+ { "global.anim_26", UNDEFINED_FILENAME },
+ { "global.anim_27", UNDEFINED_FILENAME },
+ { "global.anim_28", UNDEFINED_FILENAME },
+ { "global.anim_29", UNDEFINED_FILENAME },
+ { "global.anim_30", UNDEFINED_FILENAME },
+ { "global.anim_31", UNDEFINED_FILENAME },
+ { "global.anim_32", UNDEFINED_FILENAME },
{ "internal.global.toon_default", UNDEFINED_FILENAME },
{ "internal.global.toon_default.anim_mode", "random" },
element_info[i].editor_description= element_name_info[i].editor_description;
}
+ 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++)
{ "global.anim_6" },
{ "global.anim_7" },
{ "global.anim_8" },
+ { "global.anim_9" },
+ { "global.anim_10" },
+ { "global.anim_11" },
+ { "global.anim_12" },
+ { "global.anim_13" },
+ { "global.anim_14" },
+ { "global.anim_15" },
+ { "global.anim_16" },
+ { "global.anim_17" },
+ { "global.anim_18" },
+ { "global.anim_19" },
+ { "global.anim_20" },
+ { "global.anim_21" },
+ { "global.anim_22" },
+ { "global.anim_23" },
+ { "global.anim_24" },
+ { "global.anim_25" },
+ { "global.anim_26" },
+ { "global.anim_27" },
+ { "global.anim_28" },
+ { "global.anim_29" },
+ { "global.anim_30" },
+ { "global.anim_31" },
+ { "global.anim_32" },
{ NULL }
};
return string_has_parameter(substring, s_contained);
}
-static boolean string_has_anim_parameter(char *s, char *s_contained)
-{
- char *s_copy = getStringCopy(s);
- boolean has_parameter = FALSE;
- int len_s_copy = strlen(s_copy);
- int i;
-
- // replace all "anim" and "part" numbers with 'X'
- for (i = 0; i < len_s_copy; i++)
- if (s_copy[i] >= '1' && s_copy[i] <= '8')
- s_copy[i] = 'X';
-
- has_parameter = string_has_parameter(s_copy, s_contained);
-
- checked_free(s_copy);
-
- return has_parameter;
-}
-
int get_anim_parameter_value(char *s)
{
char *pattern_1 = "click:anim_";
matching_char = strstr(s_ptr, pattern_1);
if (matching_char == NULL)
- return result;
+ return ANIM_EVENT_NONE;
s_ptr = matching_char + strlen(pattern_1);
- if (*s_ptr == '\0')
- return result;
- // check for "click:anim_X"
- if (*s_ptr >= '1' && *s_ptr <= '8')
+ // check for main animation number ("anim_X" or "anim_XX")
+ if (*s_ptr >= '0' && *s_ptr <= '9')
{
- result |= ANIM_EVENT_CLICK_ANIM_1 << (*s_ptr - '1');
- s_ptr++;
+ int gic_anim_nr = (*s_ptr++ - '0');
+
+ if (*s_ptr >= '0' && *s_ptr <= '9')
+ gic_anim_nr = 10 * gic_anim_nr + (*s_ptr++ - '0');
+
+ if (gic_anim_nr < 1 || gic_anim_nr > MAX_GLOBAL_ANIMS)
+ return ANIM_EVENT_NONE;
- // check for "click:anim_X.part_X"
- if (strPrefix(s_ptr, pattern_2))
+ result |= gic_anim_nr << ANIM_EVENT_ANIM_BIT;
+ }
+ else
+ {
+ // invalid main animation number specified
+
+ return ANIM_EVENT_NONE;
+ }
+
+ // check for animation part number ("part_X" or "part_XX") (optional)
+ if (strPrefix(s_ptr, pattern_2))
+ {
+ s_ptr += strlen(pattern_2);
+
+ if (*s_ptr >= '0' && *s_ptr <= '9')
{
- s_ptr += strlen(pattern_2);
+ int gic_part_nr = (*s_ptr++ - '0');
- if (*s_ptr >= '1' && *s_ptr <= '8')
- {
- result |= ANIM_EVENT_CLICK_PART_1 << (*s_ptr - '1');
- s_ptr++;
- }
+ if (*s_ptr >= '0' && *s_ptr <= '9')
+ gic_part_nr = 10 * gic_part_nr + (*s_ptr++ - '0');
+
+ if (gic_part_nr < 1 || gic_part_nr > MAX_GLOBAL_ANIM_PARTS)
+ return ANIM_EVENT_NONE;
+
+ result |= gic_part_nr << ANIM_EVENT_PART_BIT;
}
else
{
- // no "part_X" specified -- trigger by click on any part
- result |= ANIM_EVENT_CLICK_PART_ALL;
+ // invalid animation part number specified
+
+ return ANIM_EVENT_NONE;
}
}
/* discard result if next character is neither delimiter nor whitespace */
if (!(*s_ptr == ',' || *s_ptr == '\0' ||
*s_ptr == ' ' || *s_ptr == '\t'))
- return get_anim_parameter_value(s_ptr);
+ return ANIM_EVENT_NONE;
- /* check if string contains another parameter string after a comma */
- s_ptr = strchr(s_ptr, ',');
- if (s_ptr == NULL) /* string does not contain a comma */
- return result;
-
- return result | get_anim_parameter_value(s_ptr);
+ return result;
}
int get_parameter_value(char *value_raw, char *suffix, int type)
result = ANIM_EVENT_DEFAULT;
if (string_has_parameter(value, "any"))
- result |= ANIM_EVENT_CLICK_ANY;
+ result |= ANIM_EVENT_ANY;
if (string_has_parameter(value, "click"))
- result |= ANIM_EVENT_CLICK_SELF;
+ result |= ANIM_EVENT_SELF;
- if (string_has_anim_parameter(value, "click:anim_X") ||
- string_has_anim_parameter(value, "click:anim_X.part_X"))
- result |= get_anim_parameter_value(value);
+ // add optional "click:anim_X" or "click:anim_X.part_X" parameter
+ result |= get_anim_parameter_value(value);
}
else if (strEqual(suffix, ".class"))
{
#define STYLE_DEFAULT STYLE_NONE
+/* values for special global animation events */
#define ANIM_EVENT_NONE 0
-#define ANIM_EVENT_CLICK_ANIM_1 (1 << 0)
-#define ANIM_EVENT_CLICK_ANIM_2 (1 << 1)
-#define ANIM_EVENT_CLICK_ANIM_3 (1 << 2)
-#define ANIM_EVENT_CLICK_ANIM_4 (1 << 3)
-#define ANIM_EVENT_CLICK_ANIM_5 (1 << 4)
-#define ANIM_EVENT_CLICK_ANIM_6 (1 << 5)
-#define ANIM_EVENT_CLICK_ANIM_7 (1 << 6)
-#define ANIM_EVENT_CLICK_ANIM_8 (1 << 7)
-#define ANIM_EVENT_CLICK_PART_1 (1 << 8)
-#define ANIM_EVENT_CLICK_PART_2 (1 << 9)
-#define ANIM_EVENT_CLICK_PART_3 (1 << 10)
-#define ANIM_EVENT_CLICK_PART_4 (1 << 11)
-#define ANIM_EVENT_CLICK_PART_5 (1 << 12)
-#define ANIM_EVENT_CLICK_PART_6 (1 << 13)
-#define ANIM_EVENT_CLICK_PART_7 (1 << 14)
-#define ANIM_EVENT_CLICK_PART_8 (1 << 15)
-#define ANIM_EVENT_CLICK_SELF (1 << 16)
-#define ANIM_EVENT_CLICK_ANY (1 << 17)
-
-#define ANIM_EVENT_CLICK_ANIM_ALL (ANIM_EVENT_CLICK_ANIM_1 | \
- ANIM_EVENT_CLICK_ANIM_2 | \
- ANIM_EVENT_CLICK_ANIM_3 | \
- ANIM_EVENT_CLICK_ANIM_4 | \
- ANIM_EVENT_CLICK_ANIM_5 | \
- ANIM_EVENT_CLICK_ANIM_6 | \
- ANIM_EVENT_CLICK_ANIM_7 | \
- ANIM_EVENT_CLICK_ANIM_8)
-
-#define ANIM_EVENT_CLICK_PART_ALL (ANIM_EVENT_CLICK_PART_1 | \
- ANIM_EVENT_CLICK_PART_2 | \
- ANIM_EVENT_CLICK_PART_3 | \
- ANIM_EVENT_CLICK_PART_4 | \
- ANIM_EVENT_CLICK_PART_5 | \
- ANIM_EVENT_CLICK_PART_6 | \
- ANIM_EVENT_CLICK_PART_7 | \
- ANIM_EVENT_CLICK_PART_8)
+#define ANIM_EVENT_SELF (1 << 16)
+#define ANIM_EVENT_ANY (1 << 17)
+
+#define ANIM_EVENT_ANIM_BIT 0
+#define ANIM_EVENT_PART_BIT 8
+
+#define ANIM_EVENT_ANIM_MASK (0xff << ANIM_EVENT_ANIM_BIT)
+#define ANIM_EVENT_PART_MASK (0xff << ANIM_EVENT_PART_BIT)
#define ANIM_EVENT_DEFAULT ANIM_EVENT_NONE
/* maximum number of levels in a level set */
#define MAX_LEVELS 1000
+/* maximum number of global animation and parts */
+#define MAX_GLOBAL_ANIMS 32
+#define MAX_GLOBAL_ANIM_PARTS 32
+
/* default name for empty highscore entry */
#define EMPTY_PLAYER_NAME "no name"
{ ".part_6", ACTION_PART_6, FALSE },
{ ".part_7", ACTION_PART_7, FALSE },
{ ".part_8", ACTION_PART_8, FALSE },
+ { ".part_9", ACTION_PART_9, FALSE },
+ { ".part_10", ACTION_PART_10, FALSE },
+ { ".part_11", ACTION_PART_11, FALSE },
+ { ".part_12", ACTION_PART_12, FALSE },
+ { ".part_13", ACTION_PART_13, FALSE },
+ { ".part_14", ACTION_PART_14, FALSE },
+ { ".part_15", ACTION_PART_15, FALSE },
+ { ".part_16", ACTION_PART_16, FALSE },
+ { ".part_17", ACTION_PART_17, FALSE },
+ { ".part_18", ACTION_PART_18, FALSE },
+ { ".part_19", ACTION_PART_19, FALSE },
+ { ".part_20", ACTION_PART_20, FALSE },
+ { ".part_21", ACTION_PART_21, FALSE },
+ { ".part_22", ACTION_PART_22, FALSE },
+ { ".part_23", ACTION_PART_23, FALSE },
+ { ".part_24", ACTION_PART_24, FALSE },
+ { ".part_25", ACTION_PART_25, FALSE },
+ { ".part_26", ACTION_PART_26, FALSE },
+ { ".part_27", ACTION_PART_27, FALSE },
+ { ".part_28", ACTION_PART_28, FALSE },
+ { ".part_29", ACTION_PART_29, FALSE },
+ { ".part_30", ACTION_PART_30, FALSE },
+ { ".part_31", ACTION_PART_31, FALSE },
+ { ".part_32", ACTION_PART_32, FALSE },
{ ".other", ACTION_OTHER, FALSE },
/* empty suffix always matches -- check as last entry in InitSoundInfo() */
{ NULL }
};
-struct GlobalAnimInfo global_anim_info[NUM_GLOBAL_ANIM_TOKENS + 1] =
+struct GlobalAnimInfo global_anim_info[NUM_GLOBAL_ANIM_TOKENS + 1];
+
+/* this contains predefined structure elements to init "global_anim_info" */
+struct GlobalAnimNameInfo global_anim_name_info[NUM_GLOBAL_ANIM_TOKENS + 1] =
{
/* (real) graphic definitions used to define animation graphics */
{ "gfx.global.anim_1", },
{ "gfx.global.anim_6", },
{ "gfx.global.anim_7", },
{ "gfx.global.anim_8", },
+ { "gfx.global.anim_9", },
+ { "gfx.global.anim_10", },
+ { "gfx.global.anim_11", },
+ { "gfx.global.anim_12", },
+ { "gfx.global.anim_13", },
+ { "gfx.global.anim_14", },
+ { "gfx.global.anim_15", },
+ { "gfx.global.anim_16", },
+ { "gfx.global.anim_17", },
+ { "gfx.global.anim_18", },
+ { "gfx.global.anim_19", },
+ { "gfx.global.anim_20", },
+ { "gfx.global.anim_21", },
+ { "gfx.global.anim_22", },
+ { "gfx.global.anim_23", },
+ { "gfx.global.anim_24", },
+ { "gfx.global.anim_25", },
+ { "gfx.global.anim_26", },
+ { "gfx.global.anim_27", },
+ { "gfx.global.anim_28", },
+ { "gfx.global.anim_29", },
+ { "gfx.global.anim_30", },
+ { "gfx.global.anim_31", },
+ { "gfx.global.anim_32", },
/* (dummy) graphic definitions used to define animation controls */
{ "global.anim_1", },
{ "global.anim_6", },
{ "global.anim_7", },
{ "global.anim_8", },
+ { "global.anim_9", },
+ { "global.anim_10", },
+ { "global.anim_11", },
+ { "global.anim_12", },
+ { "global.anim_13", },
+ { "global.anim_14", },
+ { "global.anim_15", },
+ { "global.anim_16", },
+ { "global.anim_17", },
+ { "global.anim_18", },
+ { "global.anim_19", },
+ { "global.anim_20", },
+ { "global.anim_21", },
+ { "global.anim_22", },
+ { "global.anim_23", },
+ { "global.anim_24", },
+ { "global.anim_25", },
+ { "global.anim_26", },
+ { "global.anim_27", },
+ { "global.anim_28", },
+ { "global.anim_29", },
+ { "global.anim_30", },
+ { "global.anim_31", },
+ { "global.anim_32", },
{ NULL }
};
#define ACTION_PART_6 89
#define ACTION_PART_7 90
#define ACTION_PART_8 91
-#define ACTION_OTHER 92
-
-#define NUM_ACTIONS 93
+#define ACTION_PART_9 92
+#define ACTION_PART_10 93
+#define ACTION_PART_11 94
+#define ACTION_PART_12 95
+#define ACTION_PART_13 96
+#define ACTION_PART_14 97
+#define ACTION_PART_15 98
+#define ACTION_PART_16 99
+#define ACTION_PART_17 100
+#define ACTION_PART_18 101
+#define ACTION_PART_19 102
+#define ACTION_PART_20 103
+#define ACTION_PART_21 104
+#define ACTION_PART_22 105
+#define ACTION_PART_23 106
+#define ACTION_PART_24 107
+#define ACTION_PART_25 108
+#define ACTION_PART_26 109
+#define ACTION_PART_27 110
+#define ACTION_PART_28 111
+#define ACTION_PART_29 112
+#define ACTION_PART_30 113
+#define ACTION_PART_31 114
+#define ACTION_PART_32 115
+#define ACTION_OTHER 116
+
+#define NUM_ACTIONS 117
#define ACTION_BORING_LAST ACTION_BORING_10
#define ACTION_SLEEPING_LAST ACTION_SLEEPING_3
#define MAX_NUM_TOONS 20
/* values for global animation configuration (must match those from main.c) */
-#define NUM_GLOBAL_ANIMS 8
-#define NUM_GLOBAL_ANIM_PARTS 8
+#define NUM_GLOBAL_ANIMS MAX_GLOBAL_ANIMS
+#define NUM_GLOBAL_ANIM_PARTS MAX_GLOBAL_ANIM_PARTS
#define NUM_GLOBAL_ANIM_PARTS_ALL (NUM_GLOBAL_ANIM_PARTS + 1)
#define NUM_GLOBAL_ANIM_TOKENS (2 * NUM_GLOBAL_ANIMS)
#define GLOBAL_ANIM_ID_GRAPHIC_FIRST 0
-#define GLOBAL_ANIM_ID_GRAPHIC_LAST 7
-#define GLOBAL_ANIM_ID_CONTROL_FIRST (NUM_GLOBAL_ANIMS + 0)
-#define GLOBAL_ANIM_ID_CONTROL_LAST (NUM_GLOBAL_ANIMS + 7)
+#define GLOBAL_ANIM_ID_GRAPHIC_LAST (NUM_GLOBAL_ANIMS - 1)
+#define GLOBAL_ANIM_ID_CONTROL_FIRST (NUM_GLOBAL_ANIMS)
+#define GLOBAL_ANIM_ID_CONTROL_LAST (2 * NUM_GLOBAL_ANIMS - 1)
#define GLOBAL_ANIM_ID_PART_FIRST 0
-#define GLOBAL_ANIM_ID_PART_LAST 7
-#define GLOBAL_ANIM_ID_PART_BASE 8
+#define GLOBAL_ANIM_ID_PART_LAST (NUM_GLOBAL_ANIM_PARTS - 1)
+#define GLOBAL_ANIM_ID_PART_BASE (NUM_GLOBAL_ANIM_PARTS)
/* values for global border graphics */
#define IMG_GLOBAL_BORDER_FIRST IMG_GLOBAL_BORDER
/* internal bitmap ID for special graphics */
};
+struct GlobalAnimNameInfo
+{
+ char *token_name; /* global animation token in config files */
+};
+
struct GlobalAnimInfo
{
char *token_name; /* global animation token in config files */
extern struct TokenIntPtrInfo image_config_vars[];
extern struct FontInfo font_info[];
extern struct GlobalAnimInfo global_anim_info[];
+extern struct GlobalAnimNameInfo global_anim_name_info[];
extern struct MusicPrefixInfo music_prefix_info[];
extern struct GraphicInfo *graphic_info;
extern struct SoundInfo *sound_info;