X-Git-Url: https://git.artsoft.org/?a=blobdiff_plain;f=src%2Ffiles.c;h=b11e7a9cfbfb957a8e2989b9cb87aefc4315f6fa;hb=1e5cae5e3ab889c3bcba80a065c6d7ba1e6d28a2;hp=d8695d7a6f64fef32245ed68b24f630430697ad2;hpb=4b38930413ff066d2aa7a6ea9b06763251454119;p=rocksndiamonds.git diff --git a/src/files.c b/src/files.c index d8695d7a..b11e7a9c 100644 --- a/src/files.c +++ b/src/files.c @@ -40,73 +40,104 @@ #define TAPE_HEADER_SIZE 20 /* size of tape file header */ #define TAPE_HEADER_UNUSED 3 /* unused tape header bytes */ -#define LEVEL_CHUNK_CNT3_SIZE(x) (LEVEL_CHUNK_CNT3_HEADER + (x)) -#define LEVEL_CHUNK_CUS3_SIZE(x) (2 + (x) * LEVEL_CPART_CUS3_SIZE) -#define LEVEL_CHUNK_CUS4_SIZE(x) (96 + (x) * 48) +#define LEVEL_CHUNK_CNT3_SIZE(x) (LEVEL_CHUNK_CNT3_HEADER + (x)) +#define LEVEL_CHUNK_CUS3_SIZE(x) (2 + (x) * LEVEL_CPART_CUS3_SIZE) +#define LEVEL_CHUNK_CUS4_SIZE(x) (96 + (x) * 48) /* file identifier strings */ -#define LEVEL_COOKIE_TMPL "ROCKSNDIAMONDS_LEVEL_FILE_VERSION_x.x" -#define TAPE_COOKIE_TMPL "ROCKSNDIAMONDS_TAPE_FILE_VERSION_x.x" -#define SCORE_COOKIE "ROCKSNDIAMONDS_SCORE_FILE_VERSION_1.2" +#define LEVEL_COOKIE_TMPL "ROCKSNDIAMONDS_LEVEL_FILE_VERSION_x.x" +#define TAPE_COOKIE_TMPL "ROCKSNDIAMONDS_TAPE_FILE_VERSION_x.x" +#define SCORE_COOKIE "ROCKSNDIAMONDS_SCORE_FILE_VERSION_1.2" /* values for "CONF" chunk */ -#define CONF_MASK_1_BYTE 0x00 -#define CONF_MASK_2_BYTE 0x40 -#define CONF_MASK_4_BYTE 0x80 -#define CONF_MASK_MULTI_BYTES 0xc0 - -#define CONF_MASK_BYTES 0xc0 -#define CONF_MASK_TOKEN 0x3f - -#define CONF_LAST_ENTRY (CONF_MASK_1_BYTE | 0) - -#define CONF_VALUE_INTEGER_1 (CONF_MASK_1_BYTE | 1) -#define CONF_VALUE_INTEGER_2 (CONF_MASK_1_BYTE | 2) -#define CONF_VALUE_INTEGER_3 (CONF_MASK_1_BYTE | 3) -#define CONF_VALUE_INTEGER_4 (CONF_MASK_1_BYTE | 4) -#define CONF_VALUE_BOOLEAN_1 (CONF_MASK_1_BYTE | 5) -#define CONF_VALUE_BOOLEAN_2 (CONF_MASK_1_BYTE | 6) -#define CONF_VALUE_BOOLEAN_3 (CONF_MASK_1_BYTE | 7) -#define CONF_VALUE_BOOLEAN_4 (CONF_MASK_1_BYTE | 8) - -#define CONF_VALUE_ELEMENT_1 (CONF_MASK_2_BYTE | 1) -#define CONF_VALUE_ELEMENT_2 (CONF_MASK_2_BYTE | 2) -#define CONF_VALUE_ELEMENT_3 (CONF_MASK_2_BYTE | 3) -#define CONF_VALUE_ELEMENT_4 (CONF_MASK_2_BYTE | 4) - -#define CONF_VALUE_CONTENT_1 (CONF_MASK_MULTI_BYTES | 1) -#define CONF_VALUE_CONTENT_8 (CONF_MASK_MULTI_BYTES | 2) - -#define CONF_VALUE_INTEGER(x) ((x) >= CONF_VALUE_INTEGER_1 && \ - (x) <= CONF_VALUE_INTEGER_4) - -#define CONF_VALUE_BOOLEAN(x) ((x) >= CONF_VALUE_BOOLEAN_1 && \ - (x) <= CONF_VALUE_BOOLEAN_4) - -#define CONF_VALUE_NUM_BYTES(x) ((x) == CONF_MASK_1_BYTE ? 1 : \ - (x) == CONF_MASK_2_BYTE ? 2 : \ - (x) == CONF_MASK_4_BYTE ? 4 : 0) +#define CONF_MASK_1_BYTE 0x00 +#define CONF_MASK_2_BYTE 0x40 +#define CONF_MASK_4_BYTE 0x80 +#define CONF_MASK_MULTI_BYTES 0xc0 + +#define CONF_MASK_BYTES 0xc0 +#define CONF_MASK_TOKEN 0x3f + +#define CONF_LAST_ENTRY (CONF_MASK_1_BYTE | 0) + +#define CONF_VALUE_INTEGER_1 (CONF_MASK_1_BYTE | 1) +#define CONF_VALUE_INTEGER_2 (CONF_MASK_1_BYTE | 2) +#define CONF_VALUE_INTEGER_3 (CONF_MASK_1_BYTE | 3) +#define CONF_VALUE_INTEGER_4 (CONF_MASK_1_BYTE | 4) +#define CONF_VALUE_INTEGER_5 (CONF_MASK_1_BYTE | 5) +#define CONF_VALUE_INTEGER_6 (CONF_MASK_1_BYTE | 6) +#define CONF_VALUE_INTEGER_7 (CONF_MASK_1_BYTE | 7) +#define CONF_VALUE_INTEGER_8 (CONF_MASK_1_BYTE | 8) +#define CONF_VALUE_BOOLEAN_1 (CONF_MASK_1_BYTE | 9) +#define CONF_VALUE_BOOLEAN_2 (CONF_MASK_1_BYTE | 10) +#define CONF_VALUE_BOOLEAN_3 (CONF_MASK_1_BYTE | 11) +#define CONF_VALUE_BOOLEAN_4 (CONF_MASK_1_BYTE | 12) +#define CONF_VALUE_BOOLEAN_5 (CONF_MASK_1_BYTE | 13) +#define CONF_VALUE_BOOLEAN_6 (CONF_MASK_1_BYTE | 14) +#define CONF_VALUE_BOOLEAN_7 (CONF_MASK_1_BYTE | 15) +#define CONF_VALUE_BOOLEAN_8 (CONF_MASK_1_BYTE | 16) + +#define CONF_VALUE_ELEMENT_1 (CONF_MASK_2_BYTE | 1) +#define CONF_VALUE_ELEMENT_2 (CONF_MASK_2_BYTE | 2) +#define CONF_VALUE_ELEMENT_3 (CONF_MASK_2_BYTE | 3) +#define CONF_VALUE_ELEMENT_4 (CONF_MASK_2_BYTE | 4) +#define CONF_VALUE_ELEMENT_5 (CONF_MASK_2_BYTE | 5) +#define CONF_VALUE_ELEMENT_6 (CONF_MASK_2_BYTE | 6) +#define CONF_VALUE_ELEMENT_7 (CONF_MASK_2_BYTE | 7) +#define CONF_VALUE_ELEMENT_8 (CONF_MASK_2_BYTE | 8) + +#define CONF_VALUE_ELEMENTS (CONF_MASK_MULTI_BYTES | 1) +#define CONF_VALUE_CONTENTS (CONF_MASK_MULTI_BYTES | 2) + +#define CONF_VALUE_INTEGER(x) ((x) >= CONF_VALUE_INTEGER_1 && \ + (x) <= CONF_VALUE_INTEGER_8) + +#define CONF_VALUE_BOOLEAN(x) ((x) >= CONF_VALUE_BOOLEAN_1 && \ + (x) <= CONF_VALUE_BOOLEAN_8) + +#define CONF_VALUE_NUM_BYTES(x) ((x) == CONF_MASK_1_BYTE ? 1 : \ + (x) == CONF_MASK_2_BYTE ? 2 : \ + (x) == CONF_MASK_4_BYTE ? 4 : 0) #define CONF_CONTENT_NUM_ELEMENTS (3 * 3) #define CONF_CONTENT_NUM_BYTES (CONF_CONTENT_NUM_ELEMENTS * 2) +#define CONF_ELEMENT_NUM_BYTES (2) + +#define CONF_ENTITY_NUM_BYTES(t) ((t) == CONF_VALUE_ELEMENTS ? \ + CONF_ELEMENT_NUM_BYTES : \ + (t) == CONF_VALUE_CONTENTS ? \ + CONF_CONTENT_NUM_BYTES : 1) + +#define CONF_ELEMENT_BYTE_POS(i) ((i) * CONF_ELEMENT_NUM_BYTES) +#define CONF_ELEMENTS_ELEMENT(b,i) ((b[CONF_ELEMENT_BYTE_POS(i)] << 8) | \ + (b[CONF_ELEMENT_BYTE_POS(i) + 1])) #define CONF_CONTENT_ELEMENT_POS(c,x,y) ((c) * CONF_CONTENT_NUM_ELEMENTS + \ (y) * 3 + (x)) -#define CONF_CONTENT_BYTE_POS(c,x,y) (CONF_CONTENT_ELEMENT_POS(c,x,y) * 2) -#define CONF_CONTENT_ELEMENT(b,c,x,y) ((b[CONF_CONTENT_BYTE_POS(c,x,y)] << 8)|\ - (b[CONF_CONTENT_BYTE_POS(c,x,y) + 1])) +#define CONF_CONTENT_BYTE_POS(c,x,y) (CONF_CONTENT_ELEMENT_POS(c,x,y) * \ + CONF_ELEMENT_NUM_BYTES) +#define CONF_CONTENTS_ELEMENT(b,c,x,y) ((b[CONF_CONTENT_BYTE_POS(c,x,y)]<< 8)|\ + (b[CONF_CONTENT_BYTE_POS(c,x,y) + 1])) static struct LevelInfo li; static struct { - int element; - int type; - void *value; - int default_value; + int element; /* element for which data is to be stored */ + int type; /* type of data to be stored */ + + /* (mandatory) */ + void *value; /* variable that holds the data to be stored */ + int default_value; /* initial default value for this variable */ + + /* (optional) */ + void *num_entities; /* number of entities for multi-byte data */ + int default_num_entities; /* default number of entities for this data */ + int max_num_entities; /* maximal number of entities for this data */ } element_conf[] = { /* ---------- 1-byte values ---------------------------------------------- */ + { EL_EMC_ANDROID, CONF_VALUE_INTEGER_1, &li.android_move_time, 10 @@ -115,10 +146,6 @@ static struct EL_EMC_ANDROID, CONF_VALUE_INTEGER_2, &li.android_clone_time, 10 }, - { - EL_EMC_MAGIC_BALL, CONF_VALUE_INTEGER_1, - &li.ball_time, 10 - }, { EL_EMC_LENSES, CONF_VALUE_INTEGER_1, &li.lenses_score, 10 @@ -227,8 +254,53 @@ static struct EL_PLAYER_4, CONF_VALUE_BOOLEAN_2, &li.use_start_element[3], FALSE }, + { + EL_PLAYER_1, CONF_VALUE_BOOLEAN_3, + &li.use_artwork_element[0], FALSE + }, + { + EL_PLAYER_2, CONF_VALUE_BOOLEAN_3, + &li.use_artwork_element[1], FALSE + }, + { + EL_PLAYER_3, CONF_VALUE_BOOLEAN_3, + &li.use_artwork_element[2], FALSE + }, + { + EL_PLAYER_4, CONF_VALUE_BOOLEAN_3, + &li.use_artwork_element[3], FALSE + }, + { + EL_PLAYER_1, CONF_VALUE_BOOLEAN_4, + &li.use_explosion_element[0], FALSE + }, + { + EL_PLAYER_2, CONF_VALUE_BOOLEAN_4, + &li.use_explosion_element[1], FALSE + }, + { + EL_PLAYER_3, CONF_VALUE_BOOLEAN_4, + &li.use_explosion_element[2], FALSE + }, + { + EL_PLAYER_4, CONF_VALUE_BOOLEAN_4, + &li.use_explosion_element[3], FALSE + }, + { + EL_EMC_MAGIC_BALL, CONF_VALUE_INTEGER_1, + &li.ball_time, 10 + }, + { + EL_EMC_MAGIC_BALL, CONF_VALUE_BOOLEAN_1, + &li.ball_random, FALSE + }, + { + EL_EMC_MAGIC_BALL, CONF_VALUE_BOOLEAN_2, + &li.ball_state_initial, FALSE + }, /* ---------- 2-byte values ---------------------------------------------- */ + { EL_PLAYER_1, CONF_VALUE_ELEMENT_1, &li.start_element[0], EL_PLAYER_1 @@ -245,16 +317,55 @@ static struct EL_PLAYER_4, CONF_VALUE_ELEMENT_1, &li.start_element[3], EL_PLAYER_4 }, + { + EL_PLAYER_1, CONF_VALUE_ELEMENT_2, + &li.artwork_element[0], EL_PLAYER_1 + }, + { + EL_PLAYER_2, CONF_VALUE_ELEMENT_2, + &li.artwork_element[1], EL_PLAYER_2 + }, + { + EL_PLAYER_3, CONF_VALUE_ELEMENT_2, + &li.artwork_element[2], EL_PLAYER_3 + }, + { + EL_PLAYER_4, CONF_VALUE_ELEMENT_2, + &li.artwork_element[3], EL_PLAYER_4 + }, + { + EL_PLAYER_1, CONF_VALUE_ELEMENT_3, + &li.explosion_element[0], EL_PLAYER_1 + }, + { + EL_PLAYER_2, CONF_VALUE_ELEMENT_3, + &li.explosion_element[1], EL_PLAYER_2 + }, + { + EL_PLAYER_3, CONF_VALUE_ELEMENT_3, + &li.explosion_element[2], EL_PLAYER_3 + }, + { + EL_PLAYER_4, CONF_VALUE_ELEMENT_3, + &li.explosion_element[3], EL_PLAYER_4 + }, /* ---------- multi-byte values ------------------------------------------ */ + { - EL_EMC_MAGIC_BALL, CONF_VALUE_CONTENT_8, - &li.ball_content, EL_EMPTY + EL_EMC_MAGIC_BALL, CONF_VALUE_CONTENTS, + &li.ball_content, EL_EMPTY, + &li.num_ball_contents, 4, MAX_ELEMENT_CONTENTS + }, + { + EL_EMC_ANDROID, CONF_VALUE_ELEMENTS, + &li.android_clone_element[0], EL_EMPTY, + &li.num_android_clone_elements, 1, MAX_ANDROID_ELEMENTS }, { -1, -1, - NULL, -1 + NULL, -1, }, }; @@ -292,23 +403,39 @@ static void setLevelInfoToDefaultsFromConfigList(struct LevelInfo *level) int type = element_conf[i].type; int bytes = type & CONF_MASK_BYTES; - if (bytes != CONF_MASK_MULTI_BYTES) + if (bytes == CONF_MASK_MULTI_BYTES) + { + int default_num_entities = element_conf[i].default_num_entities; + int max_num_entities = element_conf[i].max_num_entities; + + *(int *)(element_conf[i].num_entities) = default_num_entities; + + if (type == CONF_VALUE_ELEMENTS) + { + int *element_array = (int *)(element_conf[i].value); + int j; + + for (j = 0; j < max_num_entities; j++) + element_array[j] = default_value; + } + else if (type == CONF_VALUE_CONTENTS) + { + struct Content *content = (struct Content *)(element_conf[i].value); + int c, x, y; + + for (c = 0; c < max_num_entities; c++) + for (y = 0; y < 3; y++) + for (x = 0; x < 3; x++) + content[c].e[x][y] = default_value; + } + } + else /* constant size configuration data (1, 2 or 4 bytes) */ { if (CONF_VALUE_BOOLEAN(type)) *(boolean *)(element_conf[i].value) = default_value; else *(int *) (element_conf[i].value) = default_value; } - else if (type == CONF_VALUE_CONTENT_8) - { - struct Content *content = (struct Content *)(element_conf[i].value); - int c, x, y; - - for (c = 0; c < MAX_ELEMENT_CONTENTS; c++) - for (y = 0; y < 3; y++) - for (x = 0; x < 3; x++) - content[c].e[x][y] = default_value; - } } *level = li; /* copy temporary buffer back to level information */ @@ -379,6 +506,10 @@ static void setLevelInfoToDefaults(struct LevelInfo *level) static boolean clipboard_elements_initialized = FALSE; int i, j, x, y; +#if 1 + InitElementPropertiesStatic(); +#endif + setLevelInfoToDefaultsFromConfigList(level); setLevelInfoToDefaults_EM(); @@ -455,17 +586,17 @@ static void setLevelInfoToDefaults(struct LevelInfo *level) level->magnify_time = 10; level->slurp_score = 10; level->wind_direction_initial = MV_NONE; -#endif level->ball_random = FALSE; level->ball_state_initial = FALSE; -#if 0 for (i = 0; i < MAX_ELEMENT_CONTENTS; i++) for (x = 0; x < 3; x++) for (y = 0; y < 3; y++) level->ball_content[i].e[x][y] = EL_EMPTY; #endif +#if 0 for (i = 0; i < 16; i++) level->android_array[i] = FALSE; +#endif level->use_custom_template = FALSE; @@ -577,9 +708,13 @@ static void setLevelInfoToDefaults(struct LevelInfo *level) ei->current_change_page = 0; +#if 0 + /* !!! now done in InitElementPropertiesStatic() (see above) !!! */ + /* !!! (else properties set there will be overwritten here) !!! */ /* start with no properties at all */ for (j = 0; j < NUM_EP_BITFIELDS; j++) Properties[element][j] = EP_BITMASK_DEFAULT; +#endif /* now set default properties */ SET_PROPERTY(element, EP_CAN_MOVE_INTO_ACID, TRUE); @@ -1582,19 +1717,41 @@ static int LoadLevel_CONF(FILE *file, int chunk_size, struct LevelInfo *level) if (element_conf[i].element == element && element_conf[i].type == type) { + int num_entities = num_bytes / CONF_ENTITY_NUM_BYTES(type); + int max_num_entities = element_conf[i].max_num_entities; + + if (num_entities > max_num_entities) + { + Error(ERR_WARN, + "truncating number of entities for element %d from %d to %d", + element, num_entities, max_num_entities); + + num_entities = max_num_entities; + } + + *(int *)(element_conf[i].num_entities) = num_entities; + element_found = TRUE; - if (type == CONF_VALUE_CONTENT_8) + if (type == CONF_VALUE_ELEMENTS) + { + int *element_array = (int *)(element_conf[i].value); + int j; + + for (j = 0; j < num_entities; j++) + element_array[j] = + getMappedElement(CONF_ELEMENTS_ELEMENT(buffer, j)); + } + else if (type == CONF_VALUE_CONTENTS) { struct Content *content= (struct Content *)(element_conf[i].value); - int num_contents = num_bytes / CONF_CONTENT_NUM_BYTES; int c, x, y; - for (c = 0; c < num_contents; c++) + for (c = 0; c < num_entities; c++) for (y = 0; y < 3; y++) for (x = 0; x < 3; x++) content[c].e[x][y] = - getMappedElement(CONF_CONTENT_ELEMENT(buffer, c, x, y)); + getMappedElement(CONF_CONTENTS_ELEMENT(buffer, c, x, y)); } else element_found = FALSE; @@ -1607,7 +1764,7 @@ static int LoadLevel_CONF(FILE *file, int chunk_size, struct LevelInfo *level) real_chunk_size += 2 + num_bytes; } - else + else /* constant size configuration data (1, 2 or 4 bytes) */ { int value = (bytes == CONF_MASK_1_BYTE ? getFile8Bit (file) : bytes == CONF_MASK_2_BYTE ? getFile16BitBE(file) : @@ -2259,6 +2416,7 @@ void CopyNativeLevel_RND_to_EM(struct LevelInfo *level) lev->ball_random = level->ball_random; lev->ball_state_initial = level->ball_state_initial; lev->ball_time = level->ball_time; + lev->num_ball_arrays = level->num_ball_contents; lev->lenses_score = level->lenses_score; lev->magnify_score = level->magnify_score; @@ -2266,7 +2424,11 @@ void CopyNativeLevel_RND_to_EM(struct LevelInfo *level) lev->lenses_time = level->lenses_time; lev->magnify_time = level->magnify_time; - lev->wind_direction_initial = level->wind_direction_initial; + + lev->wind_direction_initial = + map_direction_RND_to_EM(level->wind_direction_initial); + lev->wind_cnt_initial = (level->wind_direction_initial != MV_NONE ? + lev->wind_time : 0); for (i = 0; i < MAX_ELEMENT_CONTENTS; i++) for (j = 0; j < 8; j++) @@ -2274,8 +2436,12 @@ void CopyNativeLevel_RND_to_EM(struct LevelInfo *level) map_element_RND_to_EM(level-> ball_content[i].e[ball_xy[j][0]][ball_xy[j][1]]); + map_android_clone_elements_RND_to_EM(level); + +#if 0 for (i = 0; i < 16; i++) lev->android_array[i] = FALSE; /* !!! YET TO COME !!! */ +#endif /* first fill the complete playfield with the default border element */ for (y = 0; y < EM_MAX_CAVE_HEIGHT; y++) @@ -2302,6 +2468,16 @@ void CopyNativeLevel_RND_to_EM(struct LevelInfo *level) /* initialize player positions and delete players from the playfield */ for (y = 0; y < lev->height; y++) for (x = 0; x < lev->width; x++) { +#if 1 + /* !!! CURRENTLY ONLY SUPPORT FOR ONE PLAYER !!! */ + if (ELEM_IS_PLAYER(level->field[x][y])) + { + ply1->x_initial = x + 1; + ply1->y_initial = y + 1; + level_em->cave[x + 1][y + 1] = map_element_RND_to_EM(EL_EMPTY); + } +#else + /* !!! ADD SUPPORT FOR MORE THAN ONE PLAYER !!! */ if (level->field[x][y] == EL_PLAYER_1) { ply1->x_initial = x + 1; @@ -2314,6 +2490,7 @@ void CopyNativeLevel_RND_to_EM(struct LevelInfo *level) ply2->y_initial = y + 1; level_em->cave[x + 1][y + 1] = map_element_RND_to_EM(EL_EMPTY); } +#endif } } @@ -2372,6 +2549,7 @@ void CopyNativeLevel_EM_to_RND(struct LevelInfo *level) level->ball_random = lev->ball_random; level->ball_state_initial = lev->ball_state_initial; level->ball_time = lev->ball_time; + level->num_ball_contents = lev->num_ball_arrays; level->lenses_score = lev->lenses_score; level->magnify_score = lev->magnify_score; @@ -2379,15 +2557,21 @@ void CopyNativeLevel_EM_to_RND(struct LevelInfo *level) level->lenses_time = lev->lenses_time; level->magnify_time = lev->magnify_time; - level->wind_direction_initial = lev->wind_direction_initial; + + level->wind_direction_initial = + map_direction_EM_to_RND(lev->wind_direction_initial); for (i = 0; i < MAX_ELEMENT_CONTENTS; i++) for (j = 0; j < 8; j++) level->ball_content[i].e[ball_xy[j][0]][ball_xy[j][1]] = map_element_EM_to_RND(lev->ball_array[i][j]); + map_android_clone_elements_EM_to_RND(level); + +#if 0 for (i = 0; i < 16; i++) level->android_array[i] = FALSE; /* !!! YET TO COME !!! */ +#endif /* convert the playfield (some elements need special treatment) */ for (y = 0; y < level->fieldy; y++) for (x = 0; x < level->fieldx; x++) @@ -3607,9 +3791,39 @@ static int SaveLevel_CONF_Value(FILE *file, int pos) return num_bytes; } -static int SaveLevel_CONF_Content(FILE *file, int pos, int num_contents) +static int SaveLevel_CONF_Elements(FILE *file, int pos) +{ + int *element_array = (int *)(element_conf[pos].value); + int num_elements = *(int *)element_conf[pos].num_entities; + int default_value = element_conf[pos].default_value; + int element = element_conf[pos].element; + int type = element_conf[pos].type; + int num_bytes = 0; + boolean modified = FALSE; + int i; + + /* check if any settings have been modified before saving them */ + for (i = 0; i < num_elements; i++) + if (element_array[i] != default_value) + modified = TRUE; + + if (!modified) /* do not save unmodified default settings */ + return 0; + + num_bytes += putFile16BitBE(file, element); + num_bytes += putFile8Bit(file, type); + num_bytes += putFile16BitBE(file, num_elements * CONF_ELEMENT_NUM_BYTES); + + for (i = 0; i < num_elements; i++) + num_bytes += putFile16BitBE(file, element_array[i]); + + return num_bytes; +} + +static int SaveLevel_CONF_Contents(FILE *file, int pos) { struct Content *content = (struct Content *)(element_conf[pos].value); + int num_contents = *(int *)element_conf[pos].num_entities; int default_value = element_conf[pos].default_value; int element = element_conf[pos].element; int type = element_conf[pos].type; @@ -3653,8 +3867,10 @@ static int SaveLevel_CONF(FILE *file, struct LevelInfo *level) if (bytes != CONF_MASK_MULTI_BYTES) chunk_size += SaveLevel_CONF_Value(file, i); - else if (type == CONF_VALUE_CONTENT_8) - chunk_size += SaveLevel_CONF_Content(file, i, MAX_ELEMENT_CONTENTS); + else if (type == CONF_VALUE_ELEMENTS) + chunk_size += SaveLevel_CONF_Elements(file, i); + else if (type == CONF_VALUE_CONTENTS) + chunk_size += SaveLevel_CONF_Contents(file, i); } return chunk_size; @@ -4461,12 +4677,30 @@ void SaveScore(int nr) #define SETUP_TOKEN_EDITOR_EL_DX_BOULDERDASH 7 #define SETUP_TOKEN_EDITOR_EL_CHARS 8 #define SETUP_TOKEN_EDITOR_EL_CUSTOM 9 -#define SETUP_TOKEN_EDITOR_EL_CUSTOM_MORE 10 -#define SETUP_TOKEN_EDITOR_EL_HEADLINES 11 -#define SETUP_TOKEN_EDITOR_EL_USER_DEFINED 12 +#define SETUP_TOKEN_EDITOR_EL_HEADLINES 10 +#define SETUP_TOKEN_EDITOR_EL_USER_DEFINED 11 +#define SETUP_TOKEN_EDITOR_EL_DYNAMIC 12 #define NUM_EDITOR_SETUP_TOKENS 13 +/* editor cascade setup */ +#define SETUP_TOKEN_EDITOR_CASCADE_BD 0 +#define SETUP_TOKEN_EDITOR_CASCADE_EM 1 +#define SETUP_TOKEN_EDITOR_CASCADE_EMC 2 +#define SETUP_TOKEN_EDITOR_CASCADE_RND 3 +#define SETUP_TOKEN_EDITOR_CASCADE_SB 4 +#define SETUP_TOKEN_EDITOR_CASCADE_SP 5 +#define SETUP_TOKEN_EDITOR_CASCADE_DC 6 +#define SETUP_TOKEN_EDITOR_CASCADE_DX 7 +#define SETUP_TOKEN_EDITOR_CASCADE_TEXT 8 +#define SETUP_TOKEN_EDITOR_CASCADE_CE 9 +#define SETUP_TOKEN_EDITOR_CASCADE_GE 10 +#define SETUP_TOKEN_EDITOR_CASCADE_USER 11 +#define SETUP_TOKEN_EDITOR_CASCADE_GENERIC 12 +#define SETUP_TOKEN_EDITOR_CASCADE_DYNAMIC 13 + +#define NUM_EDITOR_CASCADE_SETUP_TOKENS 14 + /* shortcut setup */ #define SETUP_TOKEN_SHORTCUT_SAVE_GAME 0 #define SETUP_TOKEN_SHORTCUT_LOAD_GAME 1 @@ -4508,6 +4742,7 @@ void SaveScore(int nr) static struct SetupInfo si; static struct SetupEditorInfo sei; +static struct SetupEditorCascadeInfo seci; static struct SetupShortcutInfo ssi; static struct SetupInputInfo sii; static struct SetupSystemInfo syi; @@ -4552,9 +4787,27 @@ static struct TokenInfo editor_setup_tokens[] = { TYPE_SWITCH, &sei.el_dx_boulderdash,"editor.el_dx_boulderdash" }, { TYPE_SWITCH, &sei.el_chars, "editor.el_chars" }, { TYPE_SWITCH, &sei.el_custom, "editor.el_custom" }, - { TYPE_SWITCH, &sei.el_custom_more, "editor.el_custom_more" }, { TYPE_SWITCH, &sei.el_headlines, "editor.el_headlines" }, { TYPE_SWITCH, &sei.el_user_defined, "editor.el_user_defined" }, + { TYPE_SWITCH, &sei.el_dynamic, "editor.el_dynamic" }, +}; + +static struct TokenInfo editor_cascade_setup_tokens[] = +{ + { TYPE_SWITCH, &seci.el_bd, "editor.cascade.el_bd" }, + { TYPE_SWITCH, &seci.el_em, "editor.cascade.el_em" }, + { TYPE_SWITCH, &seci.el_emc, "editor.cascade.el_emc" }, + { TYPE_SWITCH, &seci.el_rnd, "editor.cascade.el_rnd" }, + { TYPE_SWITCH, &seci.el_sb, "editor.cascade.el_sb" }, + { TYPE_SWITCH, &seci.el_sp, "editor.cascade.el_sp" }, + { TYPE_SWITCH, &seci.el_dc, "editor.cascade.el_dc" }, + { TYPE_SWITCH, &seci.el_dx, "editor.cascade.el_dx" }, + { TYPE_SWITCH, &seci.el_chars, "editor.cascade.el_chars" }, + { TYPE_SWITCH, &seci.el_ce, "editor.cascade.el_ce" }, + { TYPE_SWITCH, &seci.el_ge, "editor.cascade.el_ge" }, + { TYPE_SWITCH, &seci.el_user, "editor.cascade.el_user" }, + { TYPE_SWITCH, &seci.el_generic, "editor.cascade.el_generic" }, + { TYPE_SWITCH, &seci.el_dynamic, "editor.cascade.el_dynamic" }, }; static struct TokenInfo shortcut_setup_tokens[] = @@ -4652,10 +4905,10 @@ static void setSetupInfoToDefaults(struct SetupInfo *si) si->editor.el_dx_boulderdash = TRUE; si->editor.el_chars = TRUE; si->editor.el_custom = TRUE; - si->editor.el_custom_more = FALSE; si->editor.el_headlines = TRUE; si->editor.el_user_defined = FALSE; + si->editor.el_dynamic = TRUE; si->shortcut.save_game = DEFAULT_KEY_SAVE_GAME; si->shortcut.load_game = DEFAULT_KEY_LOAD_GAME; @@ -4687,6 +4940,25 @@ static void setSetupInfoToDefaults(struct SetupInfo *si) si->options.verbose = FALSE; } +static void setSetupInfoToDefaults_EditorCascade(struct SetupInfo *si) +{ + si->editor_cascade.el_bd = TRUE; + si->editor_cascade.el_em = TRUE; + si->editor_cascade.el_emc = TRUE; + si->editor_cascade.el_rnd = TRUE; + si->editor_cascade.el_sb = TRUE; + si->editor_cascade.el_sp = TRUE; + si->editor_cascade.el_dc = TRUE; + si->editor_cascade.el_dx = TRUE; + + si->editor_cascade.el_chars = FALSE; + si->editor_cascade.el_ce = FALSE; + si->editor_cascade.el_ge = FALSE; + si->editor_cascade.el_user = FALSE; + si->editor_cascade.el_generic = FALSE; + si->editor_cascade.el_dynamic = FALSE; +} + static void decodeSetupFileHash(SetupFileHash *setup_file_hash) { int i, pnr; @@ -4749,6 +5021,22 @@ static void decodeSetupFileHash(SetupFileHash *setup_file_hash) setup.options = soi; } +static void decodeSetupFileHash_EditorCascade(SetupFileHash *setup_file_hash) +{ + int i; + + if (!setup_file_hash) + return; + + /* editor cascade setup */ + seci = setup.editor_cascade; + for (i = 0; i < NUM_EDITOR_CASCADE_SETUP_TOKENS; i++) + setSetupInfo(editor_cascade_setup_tokens, i, + getHashEntry(setup_file_hash, + editor_cascade_setup_tokens[i].text)); + setup.editor_cascade = seci; +} + void LoadSetup() { char *filename = getSetupFilename(); @@ -4779,6 +5067,27 @@ void LoadSetup() Error(ERR_WARN, "using default setup values"); } +void LoadSetup_EditorCascade() +{ + char *filename = getPath2(getSetupDir(), EDITORCASCADE_FILENAME); + SetupFileHash *setup_file_hash = NULL; + + /* always start with reliable default values */ + setSetupInfoToDefaults_EditorCascade(&setup); + + setup_file_hash = loadSetupFileHash(filename); + + if (setup_file_hash) + { + checkSetupFileHashIdentifier(setup_file_hash, getCookie("SETUP")); + decodeSetupFileHash_EditorCascade(setup_file_hash); + + freeSetupFileHash(setup_file_hash); + } + + free(filename); +} + void SaveSetup() { char *filename = getSetupFilename(); @@ -4851,6 +5160,37 @@ void SaveSetup() SetFilePermissions(filename, PERMS_PRIVATE); } +void SaveSetup_EditorCascade() +{ + char *filename = getPath2(getSetupDir(), EDITORCASCADE_FILENAME); + FILE *file; + int i; + + InitUserDataDirectory(); + + if (!(file = fopen(filename, MODE_WRITE))) + { + Error(ERR_WARN, "cannot write editor cascade state file '%s'", filename); + free(filename); + return; + } + + fprintf(file, "%s\n", getFormattedSetupEntry(TOKEN_STR_FILE_IDENTIFIER, + getCookie("SETUP"))); + fprintf(file, "\n"); + + seci = setup.editor_cascade; + fprintf(file, "\n"); + for (i = 0; i < NUM_EDITOR_SETUP_TOKENS; i++) + fprintf(file, "%s\n", getSetupLine(editor_cascade_setup_tokens, "", i)); + + fclose(file); + + SetFilePermissions(filename, PERMS_PRIVATE); + + free(filename); +} + void LoadCustomElementDescriptions() { char *filename = getCustomArtworkConfigFilename(ARTWORK_TYPE_GRAPHICS); @@ -4952,6 +5292,10 @@ void LoadUserDefinedEditorElementList(int **elements, int *num_elements) /* add space for up to 3 more elements for padding that may be needed */ *num_elements += 3; + /* free memory for old list of elements, if needed */ + checked_free(*elements); + + /* allocate memory for new list of elements */ *elements = checked_malloc(*num_elements * sizeof(int)); *num_elements = 0;