X-Git-Url: https://git.artsoft.org/?p=rocksndiamonds.git;a=blobdiff_plain;f=src%2Ffiles.c;h=65fb1bdc22b4ad158443ed7482b014aef6bfea63;hp=b5c92b98f5033e4b3fce32cc156f645d6b6bdf2a;hb=ca2d65072bf921ae4341eaa86ff7f674f3e3ba91;hpb=ffd8016e47406b66dbbb8d78eb85129ead34f0a7 diff --git a/src/files.c b/src/files.c index b5c92b98..65fb1bdc 100644 --- a/src/files.c +++ b/src/files.c @@ -4,7 +4,7 @@ // (c) 1995-2014 by Artsoft Entertainment // Holger Schemel // info@artsoft.org -// http://www.artsoft.org/ +// https://www.artsoft.org/ // ---------------------------------------------------------------------------- // files.c // ============================================================================ @@ -58,7 +58,8 @@ #define TAPE_CHUNK_VERS_SIZE 8 // size of file version chunk #define TAPE_CHUNK_HEAD_SIZE 20 // size of tape file header -#define TAPE_CHUNK_HEAD_UNUSED 2 // unused tape header bytes +#define TAPE_CHUNK_HEAD_UNUSED 1 // unused tape header bytes +#define TAPE_CHUNK_SCRN_SIZE 2 // size of screen size chunk #define LEVEL_CHUNK_CNT3_SIZE(x) (LEVEL_CHUNK_CNT3_HEADER + (x)) #define LEVEL_CHUNK_CUS3_SIZE(x) (2 + (x) * LEVEL_CPART_CUS3_SIZE) @@ -307,6 +308,11 @@ static struct LevelFileConfigInfo chunk_config_ELEM[] = TYPE_BOOLEAN, CONF_VALUE_8_BIT(15), &li.lazy_relocation, FALSE }, + { + EL_PLAYER_1, -1, + TYPE_BOOLEAN, CONF_VALUE_8_BIT(16), + &li.finish_dig_collect, TRUE + }, // (these values are different for each player) { @@ -768,9 +774,15 @@ static struct LevelFileConfigInfo chunk_config_ELEM[] = &li.android_clone_time, 10 }, { - EL_EMC_ANDROID, -1, + EL_EMC_ANDROID, SAVE_CONF_NEVER, TYPE_ELEMENT_LIST, CONF_VALUE_BYTES(1), &li.android_clone_element[0], EL_EMPTY, NULL, + &li.num_android_clone_elements, 1, MAX_ANDROID_ELEMENTS_OLD + }, + { + EL_EMC_ANDROID, -1, + TYPE_ELEMENT_LIST, CONF_VALUE_BYTES(2), + &li.android_clone_element[0], EL_EMPTY, NULL, &li.num_android_clone_elements, 1, MAX_ANDROID_ELEMENTS }, @@ -809,7 +821,7 @@ static struct LevelFileConfigInfo chunk_config_ELEM[] = { EL_EMC_MAGIC_BALL, -1, TYPE_BOOLEAN, CONF_VALUE_8_BIT(2), - &li.ball_state_initial, FALSE + &li.ball_active_initial, FALSE }, { EL_EMC_MAGIC_BALL, -1, @@ -2064,7 +2076,7 @@ static char *getPackedLevelBasename(int type) if ((dir = openDirectory(directory)) == NULL) { - Error(ERR_WARN, "cannot read current level directory '%s'", directory); + Warn("cannot read current level directory '%s'", directory); return basename; } @@ -2328,7 +2340,7 @@ static void copyLevelFileInfo(struct LevelFileInfo *lfi_from, // functions for loading R'n'D level // ---------------------------------------------------------------------------- -static int getMappedElement(int element) +int getMappedElement(int element) { // remap some (historic, now obsolete) elements @@ -2369,7 +2381,7 @@ static int getMappedElement(int element) default: if (element >= NUM_FILE_ELEMENTS) { - Error(ERR_WARN, "invalid level element %d", element); + Warn("invalid level element %d", element); element = EL_UNKNOWN; } @@ -2617,7 +2629,7 @@ static int LoadLevel_CNT2(File *file, int chunk_size, struct LevelInfo *level) } else { - Error(ERR_WARN, "cannot load content for element '%d'", element); + Warn("cannot load content for element '%d'", element); } return chunk_size; @@ -2677,7 +2689,7 @@ static int LoadLevel_CUS1(File *file, int chunk_size, struct LevelInfo *level) if (IS_CUSTOM_ELEMENT(element)) element_info[element].properties[EP_BITFIELD_BASE_NR] = properties; else - Error(ERR_WARN, "invalid custom element number %d", element); + Warn("invalid custom element number %d", element); // older game versions that wrote level files with CUS1 chunks used // different default push delay values (not yet stored in level file) @@ -2710,7 +2722,7 @@ static int LoadLevel_CUS2(File *file, int chunk_size, struct LevelInfo *level) if (IS_CUSTOM_ELEMENT(element)) element_info[element].change->target_element = custom_target_element; else - Error(ERR_WARN, "invalid custom element number %d", element); + Warn("invalid custom element number %d", element); } level->file_has_custom_elements = TRUE; @@ -2738,7 +2750,7 @@ static int LoadLevel_CUS3(File *file, int chunk_size, struct LevelInfo *level) if (!IS_CUSTOM_ELEMENT(element)) { - Error(ERR_WARN, "invalid custom element number %d", element); + Warn("invalid custom element number %d", element); element = EL_INTERNAL_DUMMY; } @@ -2824,9 +2836,10 @@ static int LoadLevel_CUS4(File *file, int chunk_size, struct LevelInfo *level) if (!IS_CUSTOM_ELEMENT(element)) { - Error(ERR_WARN, "invalid custom element number %d", element); + Warn("invalid custom element number %d", element); ReadUnusedBytesFromFile(file, chunk_size - 2); + return chunk_size; } @@ -2972,9 +2985,10 @@ static int LoadLevel_GRP1(File *file, int chunk_size, struct LevelInfo *level) if (!IS_GROUP_ELEMENT(element)) { - Error(ERR_WARN, "invalid group element number %d", element); + Warn("invalid group element number %d", element); ReadUnusedBytesFromFile(file, chunk_size - 2); + return chunk_size; } @@ -3036,9 +3050,8 @@ static int LoadLevel_MicroChunk(File *file, struct LevelFileConfigInfo *conf, 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); + Warn("truncating number of entities for element %d from %d to %d", + element, num_entities, max_num_entities); num_entities = max_num_entities; } @@ -3047,8 +3060,7 @@ static int LoadLevel_MicroChunk(File *file, struct LevelFileConfigInfo *conf, data_type == TYPE_CONTENT_LIST)) { // for element and content lists, zero entities are not allowed - Error(ERR_WARN, "found empty list of entities for element %d", - element); + Warn("found empty list of entities for element %d", element); // do not set "num_entities" here to prevent reading behind buffer @@ -3139,9 +3151,9 @@ static int LoadLevel_MicroChunk(File *file, struct LevelFileConfigInfo *conf, int error_conf_chunk_token = conf_type & CONF_MASK_TOKEN; int error_element = real_element; - Error(ERR_WARN, "cannot load micro chunk '%s(%d)' value for element %d ['%s']", - error_conf_chunk_bytes, error_conf_chunk_token, - error_element, EL_NAME(error_element)); + Warn("cannot load micro chunk '%s(%d)' value for element %d ['%s']", + error_conf_chunk_bytes, error_conf_chunk_token, + error_element, EL_NAME(error_element)); } return micro_chunk_size; @@ -3258,8 +3270,8 @@ static int LoadLevel_CUSX(File *file, int chunk_size, struct LevelInfo *level) if (ei->num_change_pages == -1) { - Error(ERR_WARN, "LoadLevel_CUSX(): missing 'num_change_pages' for '%s'", - EL_NAME(element)); + Warn("LoadLevel_CUSX(): missing 'num_change_pages' for '%s'", + EL_NAME(element)); ei->num_change_pages = 1; @@ -3346,7 +3358,7 @@ static void LoadLevelFromFileInfo_RND(struct LevelInfo *level, if (level_info_only) return; - Error(ERR_WARN, "cannot read level '%s' -- using empty level", filename); + Warn("cannot read level '%s' -- using empty level", filename); if (!setup.editor.use_template_for_new_levels) return; @@ -3373,7 +3385,7 @@ static void LoadLevelFromFileInfo_RND(struct LevelInfo *level, { level->no_valid_file = TRUE; - Error(ERR_WARN, "unknown format of level file '%s'", filename); + Warn("unknown format of level file '%s'", filename); closeFile(file); @@ -3392,7 +3404,7 @@ static void LoadLevelFromFileInfo_RND(struct LevelInfo *level, { level->no_valid_file = TRUE; - Error(ERR_WARN, "unknown format of level file '%s'", filename); + Warn("unknown format of level file '%s'", filename); closeFile(file); @@ -3403,7 +3415,7 @@ static void LoadLevelFromFileInfo_RND(struct LevelInfo *level, { level->no_valid_file = TRUE; - Error(ERR_WARN, "unsupported version of level file '%s'", filename); + Warn("unsupported version of level file '%s'", filename); closeFile(file); @@ -3464,15 +3476,17 @@ static void LoadLevelFromFileInfo_RND(struct LevelInfo *level, if (chunk_info[i].name == NULL) { - Error(ERR_WARN, "unknown chunk '%s' in level file '%s'", - chunk_name, filename); + Warn("unknown chunk '%s' in level file '%s'", + chunk_name, filename); + ReadUnusedBytesFromFile(file, chunk_size); } else if (chunk_info[i].size != -1 && chunk_info[i].size != chunk_size) { - Error(ERR_WARN, "wrong size (%d) of chunk '%s' in level file '%s'", - chunk_size, chunk_name, filename); + Warn("wrong size (%d) of chunk '%s' in level file '%s'", + chunk_size, chunk_name, filename); + ReadUnusedBytesFromFile(file, chunk_size); } else @@ -3486,8 +3500,8 @@ static void LoadLevelFromFileInfo_RND(struct LevelInfo *level, // information, so check them here if (chunk_size_expected != chunk_size) { - Error(ERR_WARN, "wrong size (%d) of chunk '%s' in level file '%s'", - chunk_size, chunk_name, filename); + Warn("wrong size (%d) of chunk '%s' in level file '%s'", + chunk_size, chunk_name, filename); } } } @@ -3515,118 +3529,98 @@ static void CopyNativeLevel_RND_to_EM(struct LevelInfo *level) { 2, 2 }, }; struct LevelInfo_EM *level_em = level->native_em_level; - struct LEVEL *lev = level_em->lev; - struct PLAYER **ply = level_em->ply; + struct CAVE *cav = level_em->cav; int i, j, x, y; - lev->width = MIN(level->fieldx, EM_MAX_CAVE_WIDTH); - lev->height = MIN(level->fieldy, EM_MAX_CAVE_HEIGHT); + cav->width = MIN(level->fieldx, MAX_PLAYFIELD_WIDTH); + cav->height = MIN(level->fieldy, MAX_PLAYFIELD_HEIGHT); - lev->time_seconds = level->time; - lev->required_initial = level->gems_needed; + cav->time_seconds = level->time; + cav->gems_needed = level->gems_needed; - lev->emerald_score = level->score[SC_EMERALD]; - lev->diamond_score = level->score[SC_DIAMOND]; - lev->alien_score = level->score[SC_ROBOT]; - lev->tank_score = level->score[SC_SPACESHIP]; - lev->bug_score = level->score[SC_BUG]; - lev->eater_score = level->score[SC_YAMYAM]; - lev->nut_score = level->score[SC_NUT]; - lev->dynamite_score = level->score[SC_DYNAMITE]; - lev->key_score = level->score[SC_KEY]; - lev->exit_score = level->score[SC_TIME_BONUS]; + cav->emerald_score = level->score[SC_EMERALD]; + cav->diamond_score = level->score[SC_DIAMOND]; + cav->alien_score = level->score[SC_ROBOT]; + cav->tank_score = level->score[SC_SPACESHIP]; + cav->bug_score = level->score[SC_BUG]; + cav->eater_score = level->score[SC_YAMYAM]; + cav->nut_score = level->score[SC_NUT]; + cav->dynamite_score = level->score[SC_DYNAMITE]; + cav->key_score = level->score[SC_KEY]; + cav->exit_score = level->score[SC_TIME_BONUS]; + + cav->num_eater_arrays = level->num_yamyam_contents; for (i = 0; i < MAX_ELEMENT_CONTENTS; i++) for (y = 0; y < 3; y++) for (x = 0; x < 3; x++) - lev->eater_array[i][y * 3 + x] = - map_element_RND_to_EM(level->yamyam_content[i].e[x][y]); + cav->eater_array[i][y * 3 + x] = + map_element_RND_to_EM_cave(level->yamyam_content[i].e[x][y]); - lev->amoeba_time = level->amoeba_speed; - lev->wonderwall_time_initial = level->time_magic_wall; - lev->wheel_time = level->time_wheel; + cav->amoeba_time = level->amoeba_speed; + cav->wonderwall_time = level->time_magic_wall; + cav->wheel_time = level->time_wheel; - lev->android_move_time = level->android_move_time; - lev->android_clone_time = level->android_clone_time; - 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; + cav->android_move_time = level->android_move_time; + cav->android_clone_time = level->android_clone_time; + cav->ball_random = level->ball_random; + cav->ball_active = level->ball_active_initial; + cav->ball_time = level->ball_time; + cav->num_ball_arrays = level->num_ball_contents; - lev->lenses_score = level->lenses_score; - lev->magnify_score = level->magnify_score; - lev->slurp_score = level->slurp_score; + cav->lenses_score = level->lenses_score; + cav->magnify_score = level->magnify_score; + cav->slurp_score = level->slurp_score; - lev->lenses_time = level->lenses_time; - lev->magnify_time = level->magnify_time; + cav->lenses_time = level->lenses_time; + cav->magnify_time = level->magnify_time; - lev->wind_direction_initial = + cav->wind_direction = 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++) - lev->ball_array[i][j] = - map_element_RND_to_EM(level-> - ball_content[i].e[ball_xy[j][0]][ball_xy[j][1]]); + cav->ball_array[i][j] = + map_element_RND_to_EM_cave(level->ball_content[i]. + e[ball_xy[j][0]][ball_xy[j][1]]); map_android_clone_elements_RND_to_EM(level); - // first fill the complete playfield with the default border element + // first fill the complete playfield with the empty space element for (y = 0; y < EM_MAX_CAVE_HEIGHT; y++) for (x = 0; x < EM_MAX_CAVE_WIDTH; x++) - level_em->cave[x][y] = ZBORDER; - - if (BorderElement == EL_STEELWALL) - { - for (y = 0; y < lev->height + 2; y++) - for (x = 0; x < lev->width + 2; x++) - level_em->cave[x + 1][y + 1] = map_element_RND_to_EM(EL_STEELWALL); - } + cav->cave[x][y] = Cblank; // then copy the real level contents from level file into the playfield - for (y = 0; y < lev->height; y++) for (x = 0; x < lev->width; x++) + for (y = 0; y < cav->height; y++) for (x = 0; x < cav->width; x++) { - int new_element = map_element_RND_to_EM(level->field[x][y]); - int offset = (BorderElement == EL_STEELWALL ? 1 : 0); - int xx = x + 1 + offset; - int yy = y + 1 + offset; + int new_element = map_element_RND_to_EM_cave(level->field[x][y]); if (level->field[x][y] == EL_AMOEBA_DEAD) - new_element = map_element_RND_to_EM(EL_AMOEBA_WET); + new_element = map_element_RND_to_EM_cave(EL_AMOEBA_WET); - level_em->cave[xx][yy] = new_element; + cav->cave[x][y] = new_element; } for (i = 0; i < MAX_PLAYERS; i++) { - ply[i]->x_initial = 0; - ply[i]->y_initial = 0; + cav->player_x[i] = -1; + cav->player_y[i] = -1; } // initialize player positions and delete players from the playfield - for (y = 0; y < lev->height; y++) for (x = 0; x < lev->width; x++) + for (y = 0; y < cav->height; y++) for (x = 0; x < cav->width; x++) { if (ELEM_IS_PLAYER(level->field[x][y])) { int player_nr = GET_PLAYER_NR(level->field[x][y]); - int offset = (BorderElement == EL_STEELWALL ? 1 : 0); - int xx = x + 1 + offset; - int yy = y + 1 + offset; - ply[player_nr]->x_initial = xx; - ply[player_nr]->y_initial = yy; + cav->player_x[player_nr] = x; + cav->player_y[player_nr] = y; - level_em->cave[xx][yy] = map_element_RND_to_EM(EL_EMPTY); + cav->cave[x][y] = map_element_RND_to_EM_cave(EL_EMPTY); } } - - if (BorderElement == EL_STEELWALL) - { - lev->width += 2; - lev->height += 2; - } } static void CopyNativeLevel_EM_to_RND(struct LevelInfo *level) @@ -3643,69 +3637,68 @@ static void CopyNativeLevel_EM_to_RND(struct LevelInfo *level) { 2, 2 }, }; struct LevelInfo_EM *level_em = level->native_em_level; - struct LEVEL *lev = level_em->lev; - struct PLAYER **ply = level_em->ply; + struct CAVE *cav = level_em->cav; int i, j, x, y; - level->fieldx = MIN(lev->width, MAX_LEV_FIELDX); - level->fieldy = MIN(lev->height, MAX_LEV_FIELDY); + level->fieldx = MIN(cav->width, MAX_LEV_FIELDX); + level->fieldy = MIN(cav->height, MAX_LEV_FIELDY); - level->time = lev->time_seconds; - level->gems_needed = lev->required_initial; + level->time = cav->time_seconds; + level->gems_needed = cav->gems_needed; sprintf(level->name, "Level %d", level->file_info.nr); - level->score[SC_EMERALD] = lev->emerald_score; - level->score[SC_DIAMOND] = lev->diamond_score; - level->score[SC_ROBOT] = lev->alien_score; - level->score[SC_SPACESHIP] = lev->tank_score; - level->score[SC_BUG] = lev->bug_score; - level->score[SC_YAMYAM] = lev->eater_score; - level->score[SC_NUT] = lev->nut_score; - level->score[SC_DYNAMITE] = lev->dynamite_score; - level->score[SC_KEY] = lev->key_score; - level->score[SC_TIME_BONUS] = lev->exit_score; + level->score[SC_EMERALD] = cav->emerald_score; + level->score[SC_DIAMOND] = cav->diamond_score; + level->score[SC_ROBOT] = cav->alien_score; + level->score[SC_SPACESHIP] = cav->tank_score; + level->score[SC_BUG] = cav->bug_score; + level->score[SC_YAMYAM] = cav->eater_score; + level->score[SC_NUT] = cav->nut_score; + level->score[SC_DYNAMITE] = cav->dynamite_score; + level->score[SC_KEY] = cav->key_score; + level->score[SC_TIME_BONUS] = cav->exit_score; - level->num_yamyam_contents = MAX_ELEMENT_CONTENTS; + level->num_yamyam_contents = cav->num_eater_arrays; - for (i = 0; i < level->num_yamyam_contents; i++) + for (i = 0; i < MAX_ELEMENT_CONTENTS; i++) for (y = 0; y < 3; y++) for (x = 0; x < 3; x++) level->yamyam_content[i].e[x][y] = - map_element_EM_to_RND(lev->eater_array[i][y * 3 + x]); + map_element_EM_to_RND_cave(cav->eater_array[i][y * 3 + x]); - level->amoeba_speed = lev->amoeba_time; - level->time_magic_wall = lev->wonderwall_time_initial; - level->time_wheel = lev->wheel_time; + level->amoeba_speed = cav->amoeba_time; + level->time_magic_wall = cav->wonderwall_time; + level->time_wheel = cav->wheel_time; - level->android_move_time = lev->android_move_time; - level->android_clone_time = lev->android_clone_time; - 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->android_move_time = cav->android_move_time; + level->android_clone_time = cav->android_clone_time; + level->ball_random = cav->ball_random; + level->ball_active_initial = cav->ball_active; + level->ball_time = cav->ball_time; + level->num_ball_contents = cav->num_ball_arrays; - level->lenses_score = lev->lenses_score; - level->magnify_score = lev->magnify_score; - level->slurp_score = lev->slurp_score; + level->lenses_score = cav->lenses_score; + level->magnify_score = cav->magnify_score; + level->slurp_score = cav->slurp_score; - level->lenses_time = lev->lenses_time; - level->magnify_time = lev->magnify_time; + level->lenses_time = cav->lenses_time; + level->magnify_time = cav->magnify_time; level->wind_direction_initial = - map_direction_EM_to_RND(lev->wind_direction_initial); + map_direction_EM_to_RND(cav->wind_direction); 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_element_EM_to_RND_cave(cav->ball_array[i][j]); map_android_clone_elements_EM_to_RND(level); // convert the playfield (some elements need special treatment) for (y = 0; y < level->fieldy; y++) for (x = 0; x < level->fieldx; x++) { - int new_element = map_element_EM_to_RND(level_em->cave[x + 1][y + 1]); + int new_element = map_element_EM_to_RND_cave(cav->cave[x][y]); if (new_element == EL_AMOEBA_WET && level->amoeba_speed == 0) new_element = EL_AMOEBA_DEAD; @@ -3717,8 +3710,8 @@ static void CopyNativeLevel_EM_to_RND(struct LevelInfo *level) { // in case of all players set to the same field, use the first player int nr = MAX_PLAYERS - i - 1; - int jx = ply[nr]->x_initial - 1; - int jy = ply[nr]->y_initial - 1; + int jx = cav->player_x[nr]; + int jy = cav->player_y[nr]; if (jx != -1 && jy != -1) level->field[jx][jy] = EL_PLAYER_1 + nr; @@ -3835,7 +3828,7 @@ static void CopyNativeLevel_SP_to_RND(struct LevelInfo *level) { num_invalid_elements++; - Error(ERR_DEBUG, "invalid element %d at position %d, %d", + Debug("level:native:SP", "invalid element %d at position %d, %d", element_old, x, y); } @@ -3844,8 +3837,8 @@ static void CopyNativeLevel_SP_to_RND(struct LevelInfo *level) } if (num_invalid_elements > 0) - Error(ERR_WARN, "found %d invalid elements%s", num_invalid_elements, - (!options.debug ? " (use '--debug' for more details)" : "")); + Warn("found %d invalid elements%s", num_invalid_elements, + (!options.debug ? " (use '--debug' for more details)" : "")); for (i = 0; i < MAX_PLAYERS; i++) level->initial_player_gravity[i] = @@ -3881,8 +3874,7 @@ static void CopyNativeLevel_SP_to_RND(struct LevelInfo *level) if (port_x < 0 || port_x >= level->fieldx || port_y < 0 || port_y >= level->fieldy) { - Error(ERR_WARN, "special port position (%d, %d) out of bounds", - port_x, port_y); + Warn("special port position (%d, %d) out of bounds", port_x, port_y); continue; } @@ -3892,7 +3884,7 @@ static void CopyNativeLevel_SP_to_RND(struct LevelInfo *level) if (port_element < EL_SP_GRAVITY_PORT_RIGHT || port_element > EL_SP_GRAVITY_PORT_UP) { - Error(ERR_WARN, "no special port at position (%d, %d)", port_x, port_y); + Warn("no special port at position (%d, %d)", port_x, port_y); continue; } @@ -3958,8 +3950,8 @@ static void CopyNativeTape_RND_to_SP(struct LevelInfo *level) if (demo->length + demo_entries >= SP_MAX_TAPE_LEN) { - Error(ERR_WARN, "tape truncated: size exceeds maximum SP demo size %d", - SP_MAX_TAPE_LEN); + Warn("tape truncated: size exceeds maximum SP demo size %d", + SP_MAX_TAPE_LEN); break; } @@ -4003,7 +3995,7 @@ static void CopyNativeTape_SP_to_RND(struct LevelInfo *level) int demo_repeat = (demo->data[i] & 0xf0) >> 4; int tape_action = map_key_SP_to_RND(demo_action); int tape_repeat = demo_repeat + 1; - byte action[MAX_PLAYERS] = { tape_action, 0, 0, 0 }; + byte action[MAX_TAPE_ACTIONS] = { tape_action }; boolean success = 0; int j; @@ -4012,8 +4004,8 @@ static void CopyNativeTape_SP_to_RND(struct LevelInfo *level) if (!success) { - Error(ERR_WARN, "SP demo truncated: size exceeds maximum tape size %d", - MAX_TAPE_LEN); + Warn("SP demo truncated: size exceeds maximum tape size %d", + MAX_TAPE_LEN); break; } @@ -4288,7 +4280,7 @@ static int getMappedElement_DC(int element) break; case 0x13f5: - element = EL_YAMYAM; + element = EL_YAMYAM_UP; break; case 0x1425: @@ -5314,7 +5306,7 @@ static int getMappedElement_DC(int element) break; case 0x1682: // secret gate (red) - element = EL_GATE_1_GRAY; + element = EL_EM_GATE_1_GRAY; break; case 0x1683: // gate (yellow) @@ -5322,7 +5314,7 @@ static int getMappedElement_DC(int element) break; case 0x1684: // secret gate (yellow) - element = EL_GATE_2_GRAY; + element = EL_EM_GATE_2_GRAY; break; case 0x1685: // gate (blue) @@ -5330,7 +5322,7 @@ static int getMappedElement_DC(int element) break; case 0x1686: // secret gate (blue) - element = EL_GATE_4_GRAY; + element = EL_EM_GATE_4_GRAY; break; case 0x1687: // gate (green) @@ -5338,7 +5330,7 @@ static int getMappedElement_DC(int element) break; case 0x1688: // secret gate (green) - element = EL_GATE_3_GRAY; + element = EL_EM_GATE_3_GRAY; break; case 0x1689: // gate (white) @@ -5569,7 +5561,8 @@ static int getMappedElement_DC(int element) element = EL_INVISIBLE_SAND; else { - Error(ERR_WARN, "unknown Diamond Caves element 0x%04x", element); + Warn("unknown Diamond Caves element 0x%04x", element); + element = EL_UNKNOWN; } break; @@ -5617,7 +5610,7 @@ static void LoadLevelFromFileStream_DC(File *file, struct LevelInfo *level, { level->no_valid_file = TRUE; - Error(ERR_WARN, "cannot decode level from stream -- using empty level"); + Warn("cannot decode level from stream -- using empty level"); return; } @@ -5730,6 +5723,13 @@ static void LoadLevelFromFileStream_DC(File *file, struct LevelInfo *level, level->extra_time = header[56] | (header[57] << 8); level->shield_normal_time = header[58] | (header[59] << 8); + // shield and extra time elements do not have a score + level->score[SC_SHIELD] = 0; + level->extra_time_score = 0; + + // set time for normal and deadly shields to the same value + level->shield_deadly_time = level->shield_normal_time; + // Diamond Caves has the same (strange) behaviour as Emerald Mine that gems // can slip down from flat walls, like normal walls and steel walls level->em_slippery_gems = TRUE; @@ -5750,7 +5750,7 @@ static void LoadLevelFromFileInfo_DC(struct LevelInfo *level, level->no_valid_file = TRUE; if (!level_info_only) - Error(ERR_WARN, "cannot read level '%s' -- using empty level", filename); + Warn("cannot read level '%s' -- using empty level", filename); return; } @@ -5768,8 +5768,7 @@ static void LoadLevelFromFileInfo_DC(struct LevelInfo *level, { level->no_valid_file = TRUE; - Error(ERR_WARN, "unknown DC level file '%s' -- using empty level", - filename); + Warn("unknown DC level file '%s' -- using empty level", filename); return; } @@ -5795,8 +5794,7 @@ static void LoadLevelFromFileInfo_DC(struct LevelInfo *level, { level->no_valid_file = TRUE; - Error(ERR_WARN, "cannot fseek in file '%s' -- using empty level", - filename); + Warn("cannot fseek in file '%s' -- using empty level", filename); return; } @@ -5814,8 +5812,7 @@ static void LoadLevelFromFileInfo_DC(struct LevelInfo *level, { level->no_valid_file = TRUE; - Error(ERR_WARN, "unknown DC2 level file '%s' -- using empty level", - filename); + Warn("unknown DC2 level file '%s' -- using empty level", filename); return; } @@ -5890,7 +5887,7 @@ static void LoadLevelFromFileInfo_SB(struct LevelInfo *level, level->no_valid_file = TRUE; if (!level_info_only) - Error(ERR_WARN, "cannot read level '%s' -- using empty level", filename); + Warn("cannot read level '%s' -- using empty level", filename); return; } @@ -6064,7 +6061,7 @@ static void LoadLevelFromFileInfo_SB(struct LevelInfo *level, { level->no_valid_file = TRUE; - Error(ERR_WARN, "cannot read level '%s' -- using empty level", filename); + Warn("cannot read level '%s' -- using empty level", filename); return; } @@ -6431,6 +6428,10 @@ static void LoadLevel_InitVersion(struct LevelInfo *level) // only Sokoban fields (but not objects) had to be solved before 4.1.1.1 if (level->game_version < VERSION_IDENT(4,1,1,1)) level->sb_objects_needed = FALSE; + + // CE actions were triggered by unfinished digging/collecting up to 4.2.2.0 + if (level->game_version <= VERSION_IDENT(4,2,2,0)) + level->finish_dig_collect = FALSE; } static void LoadLevel_InitStandardElements(struct LevelInfo *level) @@ -6611,7 +6612,7 @@ static void LoadLevel_InitPlayfield(struct LevelInfo *level) // copy elements to runtime playfield array for (x = 0; x < MAX_LEV_FIELDX; x++) for (y = 0; y < MAX_LEV_FIELDY; y++) - Feld[x][y] = level->field[x][y]; + Tile[x][y] = level->field[x][y]; // initialize level size variables for faster access lev_fieldx = level->fieldx; @@ -6646,7 +6647,7 @@ void LoadLevelTemplate(int nr) { if (!fileExists(getGlobalLevelTemplateFilename())) { - Error(ERR_WARN, "no level template found for this level"); + Warn("no level template found for this level"); return; } @@ -6809,8 +6810,8 @@ static int SaveLevel_BODY(FILE *file, struct LevelInfo *level) int chunk_size = 0; int x, y; - for (y = 0; y < level->fieldy; y++) - for (x = 0; x < level->fieldx; x++) + for (y = 0; y < level->fieldy; y++) + for (x = 0; x < level->fieldx; x++) if (level->encoding_16bit_field) chunk_size += putFile16BitBE(file, level->field[x][y]); else @@ -6887,7 +6888,8 @@ static void SaveLevel_CNT2(FILE *file, struct LevelInfo *level, int element) // chunk header already written -- write empty chunk data WriteUnusedBytesToFile(file, LEVEL_CHUNK_CNT2_SIZE); - Error(ERR_WARN, "cannot save content for element '%d'", element); + Warn("cannot save content for element '%d'", element); + return; } @@ -6955,7 +6957,7 @@ static void SaveLevel_CUS1(FILE *file, struct LevelInfo *level, } if (check != num_changed_custom_elements) // should not happen - Error(ERR_WARN, "inconsistent number of custom element properties"); + Warn("inconsistent number of custom element properties"); } #endif @@ -6984,7 +6986,7 @@ static void SaveLevel_CUS2(FILE *file, struct LevelInfo *level, } if (check != num_changed_custom_elements) // should not happen - Error(ERR_WARN, "inconsistent number of custom target elements"); + Warn("inconsistent number of custom target elements"); } #endif @@ -7067,7 +7069,7 @@ static void SaveLevel_CUS3(FILE *file, struct LevelInfo *level, } if (check != num_changed_custom_elements) // should not happen - Error(ERR_WARN, "inconsistent number of custom element properties"); + Warn("inconsistent number of custom element properties"); } #endif @@ -7445,7 +7447,8 @@ static void SaveLevelFromFilename(struct LevelInfo *level, char *filename, if (!(file = fopen(filename, MODE_WRITE))) { - Error(ERR_WARN, "cannot save level file '%s'", filename); + Warn("cannot save level file '%s'", filename); + return; } @@ -7570,7 +7573,7 @@ void DumpLevel(struct LevelInfo *level) { if (level->no_level_file || level->no_valid_file) { - Error(ERR_WARN, "cannot dump -- no valid level file found"); + Warn("cannot dump -- no valid level file found"); return; } @@ -7625,6 +7628,8 @@ static void setTapeInfoToDefaults(void) // at least one (default: the first) player participates in every tape tape.num_participating_players = 1; + tape.property_bits = TAPE_PROPERTY_NONE; + tape.level_nr = level_nr; tape.counter = 0; tape.changed = FALSE; @@ -7633,9 +7638,48 @@ static void setTapeInfoToDefaults(void) tape.playing = FALSE; tape.pausing = FALSE; + tape.scr_fieldx = SCR_FIELDX_DEFAULT; + tape.scr_fieldy = SCR_FIELDY_DEFAULT; + tape.no_valid_file = FALSE; } +static int getTapePosSize(struct TapeInfo *tape) +{ + int tape_pos_size = 0; + + if (tape->use_key_actions) + tape_pos_size += tape->num_participating_players; + + if (tape->use_mouse_actions) + tape_pos_size += 3; // x and y position and mouse button mask + + tape_pos_size += 1; // tape action delay value + + return tape_pos_size; +} + +static void setTapeActionFlags(struct TapeInfo *tape, int value) +{ + tape->use_key_actions = FALSE; + tape->use_mouse_actions = FALSE; + + if (value != TAPE_USE_MOUSE_ACTIONS_ONLY) + tape->use_key_actions = TRUE; + + if (value != TAPE_USE_KEY_ACTIONS_ONLY) + tape->use_mouse_actions = TRUE; +} + +static int getTapeActionValue(struct TapeInfo *tape) +{ + return (tape->use_key_actions && + tape->use_mouse_actions ? TAPE_USE_KEY_AND_MOUSE_ACTIONS : + tape->use_key_actions ? TAPE_USE_KEY_ACTIONS_ONLY : + tape->use_mouse_actions ? TAPE_USE_MOUSE_ACTIONS_ONLY : + TAPE_ACTIONS_DEFAULT); +} + static int LoadTape_VERS(File *file, int chunk_size, struct TapeInfo *tape) { tape->file_version = getFileVersion(file); @@ -7671,7 +7715,9 @@ static int LoadTape_HEAD(File *file, int chunk_size, struct TapeInfo *tape) } } - tape->use_mouse = (getFile8Bit(file) == 1 ? TRUE : FALSE); + setTapeActionFlags(tape, getFile8Bit(file)); + + tape->property_bits = getFile8Bit(file); ReadUnusedBytesFromFile(file, TAPE_CHUNK_HEAD_UNUSED); @@ -7685,6 +7731,14 @@ static int LoadTape_HEAD(File *file, int chunk_size, struct TapeInfo *tape) return chunk_size; } +static int LoadTape_SCRN(File *file, int chunk_size, struct TapeInfo *tape) +{ + tape->scr_fieldx = getFile8Bit(file); + tape->scr_fieldy = getFile8Bit(file); + + return chunk_size; +} + static int LoadTape_INFO(File *file, int chunk_size, struct TapeInfo *tape) { int level_identifier_size; @@ -7708,8 +7762,7 @@ static int LoadTape_INFO(File *file, int chunk_size, struct TapeInfo *tape) static int LoadTape_BODY(File *file, int chunk_size, struct TapeInfo *tape) { int i, j; - int tape_pos_size = - (tape->use_mouse ? 3 : tape->num_participating_players) + 1; + int tape_pos_size = getTapePosSize(tape); int chunk_size_expected = tape_pos_size * tape->length; if (chunk_size_expected != chunk_size) @@ -7722,25 +7775,17 @@ static int LoadTape_BODY(File *file, int chunk_size, struct TapeInfo *tape) { if (i >= MAX_TAPE_LEN) { - Error(ERR_WARN, "tape truncated -- size exceeds maximum tape size %d", + Warn("tape truncated -- size exceeds maximum tape size %d", MAX_TAPE_LEN); // tape too large; read and ignore remaining tape data from this chunk for (;i < tape->length; i++) - ReadUnusedBytesFromFile(file, tape->num_participating_players + 1); + ReadUnusedBytesFromFile(file, tape_pos_size); break; } - if (tape->use_mouse) - { - tape->pos[i].action[TAPE_ACTION_LX] = getFile8Bit(file); - tape->pos[i].action[TAPE_ACTION_LY] = getFile8Bit(file); - tape->pos[i].action[TAPE_ACTION_BUTTON] = getFile8Bit(file); - - tape->pos[i].action[TAPE_ACTION_UNUSED] = 0; - } - else + if (tape->use_key_actions) { for (j = 0; j < MAX_PLAYERS; j++) { @@ -7751,6 +7796,13 @@ static int LoadTape_BODY(File *file, int chunk_size, struct TapeInfo *tape) } } + if (tape->use_mouse_actions) + { + tape->pos[i].action[TAPE_ACTION_LX] = getFile8Bit(file); + tape->pos[i].action[TAPE_ACTION_LY] = getFile8Bit(file); + tape->pos[i].action[TAPE_ACTION_BUTTON] = getFile8Bit(file); + } + tape->pos[i].delay = getFile8Bit(file); if (tape->file_version == FILE_VERSION_1_0) @@ -7869,7 +7921,7 @@ static void LoadTape_SokobanSolution(char *filename) default: tape.no_valid_file = TRUE; - Error(ERR_WARN, "unsupported Sokoban solution file '%s' ['%d']", filename, c); + Warn("unsupported Sokoban solution file '%s' ['%d']", filename, c); break; } @@ -7918,7 +7970,7 @@ void LoadTapeFromFilename(char *filename) { tape.no_valid_file = TRUE; - Error(ERR_WARN, "unknown format of tape file '%s'", filename); + Warn("unknown format of tape file '%s'", filename); closeFile(file); @@ -7937,7 +7989,7 @@ void LoadTapeFromFilename(char *filename) { tape.no_valid_file = TRUE; - Error(ERR_WARN, "unknown format of tape file '%s'", filename); + Warn("unknown format of tape file '%s'", filename); closeFile(file); @@ -7948,7 +8000,7 @@ void LoadTapeFromFilename(char *filename) { tape.no_valid_file = TRUE; - Error(ERR_WARN, "unsupported version of tape file '%s'", filename); + Warn("unsupported version of tape file '%s'", filename); closeFile(file); @@ -7977,6 +8029,7 @@ void LoadTapeFromFilename(char *filename) { { "VERS", TAPE_CHUNK_VERS_SIZE, LoadTape_VERS }, { "HEAD", TAPE_CHUNK_HEAD_SIZE, LoadTape_HEAD }, + { "SCRN", TAPE_CHUNK_SCRN_SIZE, LoadTape_SCRN }, { "INFO", -1, LoadTape_INFO }, { "BODY", -1, LoadTape_BODY }, { NULL, 0, NULL } @@ -7992,15 +8045,17 @@ void LoadTapeFromFilename(char *filename) if (chunk_info[i].name == NULL) { - Error(ERR_WARN, "unknown chunk '%s' in tape file '%s'", + Warn("unknown chunk '%s' in tape file '%s'", chunk_name, filename); + ReadUnusedBytesFromFile(file, chunk_size); } else if (chunk_info[i].size != -1 && chunk_info[i].size != chunk_size) { - Error(ERR_WARN, "wrong size (%d) of chunk '%s' in tape file '%s'", + Warn("wrong size (%d) of chunk '%s' in tape file '%s'", chunk_size, chunk_name, filename); + ReadUnusedBytesFromFile(file, chunk_size); } else @@ -8014,7 +8069,7 @@ void LoadTapeFromFilename(char *filename) // information, so check them here if (chunk_size_expected != chunk_size) { - Error(ERR_WARN, "wrong size (%d) of chunk '%s' in tape file '%s'", + Warn("wrong size (%d) of chunk '%s' in tape file '%s'", chunk_size, chunk_name, filename); } } @@ -8027,9 +8082,12 @@ void LoadTapeFromFilename(char *filename) tape.length_seconds = GetTapeLengthSeconds(); #if 0 - printf("::: tape file version: %d\n", tape.file_version); - printf("::: tape game version: %d\n", tape.game_version); - printf("::: tape engine version: %d\n", tape.engine_version); + Debug("files:LoadTapeFromFilename", "tape file version: %d", + tape.file_version); + Debug("files:LoadTapeFromFilename", "tape game version: %d", + tape.game_version); + Debug("files:LoadTapeFromFilename", "tape engine version: %d", + tape.engine_version); #endif } @@ -8052,6 +8110,14 @@ void LoadSolutionTape(int nr) CopyNativeTape_SP_to_RND(&level); } +static boolean checkSaveTape_SCRN(struct TapeInfo *tape) +{ + // chunk required for team mode tapes with non-default screen size + return (tape->num_participating_players > 1 && + (tape->scr_fieldx != SCR_FIELDX_DEFAULT || + tape->scr_fieldy != SCR_FIELDY_DEFAULT)); +} + static void SaveTape_VERS(FILE *file, struct TapeInfo *tape) { putFileVersion(file, tape->file_version); @@ -8074,7 +8140,9 @@ static void SaveTape_HEAD(FILE *file, struct TapeInfo *tape) putFile8Bit(file, store_participating_players); - putFile8Bit(file, (tape->use_mouse ? 1 : 0)); + putFile8Bit(file, getTapeActionValue(tape)); + + putFile8Bit(file, tape->property_bits); // unused bytes not at the end here for 4-byte alignment of engine_version WriteUnusedBytesToFile(file, TAPE_CHUNK_HEAD_UNUSED); @@ -8082,6 +8150,12 @@ static void SaveTape_HEAD(FILE *file, struct TapeInfo *tape) putFileVersion(file, tape->engine_version); } +static void SaveTape_SCRN(FILE *file, struct TapeInfo *tape) +{ + putFile8Bit(file, tape->scr_fieldx); + putFile8Bit(file, tape->scr_fieldy); +} + static void SaveTape_INFO(FILE *file, struct TapeInfo *tape) { int level_identifier_size = strlen(tape->level_identifier) + 1; @@ -8101,50 +8175,39 @@ static void SaveTape_BODY(FILE *file, struct TapeInfo *tape) for (i = 0; i < tape->length; i++) { - if (tape->use_mouse) - { - putFile8Bit(file, tape->pos[i].action[TAPE_ACTION_LX]); - putFile8Bit(file, tape->pos[i].action[TAPE_ACTION_LY]); - putFile8Bit(file, tape->pos[i].action[TAPE_ACTION_BUTTON]); - } - else + if (tape->use_key_actions) { for (j = 0; j < MAX_PLAYERS; j++) if (tape->player_participates[j]) putFile8Bit(file, tape->pos[i].action[j]); } + if (tape->use_mouse_actions) + { + putFile8Bit(file, tape->pos[i].action[TAPE_ACTION_LX]); + putFile8Bit(file, tape->pos[i].action[TAPE_ACTION_LY]); + putFile8Bit(file, tape->pos[i].action[TAPE_ACTION_BUTTON]); + } + putFile8Bit(file, tape->pos[i].delay); } } -void SaveTape(int nr) +void SaveTapeToFilename(char *filename) { - char *filename = getTapeFilename(nr); FILE *file; - int num_participating_players = 0; int tape_pos_size; int info_chunk_size; int body_chunk_size; - int i; - - InitTapeDirectory(leveldir_current->subdir); if (!(file = fopen(filename, MODE_WRITE))) { - Error(ERR_WARN, "cannot save level recording file '%s'", filename); + Warn("cannot save level recording file '%s'", filename); + return; } - tape.file_version = FILE_VERSION_ACTUAL; - tape.game_version = GAME_VERSION_ACTUAL; - - // count number of participating players - for (i = 0; i < MAX_PLAYERS; i++) - if (tape.player_participates[i]) - num_participating_players++; - - tape_pos_size = (tape.use_mouse ? 3 : num_participating_players) + 1; + tape_pos_size = getTapePosSize(&tape); info_chunk_size = 2 + (strlen(tape.level_identifier) + 1) + 2; body_chunk_size = tape_pos_size * tape.length; @@ -8158,6 +8221,12 @@ void SaveTape(int nr) putFileChunkBE(file, "HEAD", TAPE_CHUNK_HEAD_SIZE); SaveTape_HEAD(file, &tape); + if (checkSaveTape_SCRN(&tape)) + { + putFileChunkBE(file, "SCRN", TAPE_CHUNK_SCRN_SIZE); + SaveTape_SCRN(file, &tape); + } + putFileChunkBE(file, "INFO", info_chunk_size); SaveTape_INFO(file, &tape); @@ -8167,22 +8236,43 @@ void SaveTape(int nr) fclose(file); SetFilePermissions(filename, PERMS_PRIVATE); +} + +void SaveTape(int nr) +{ + char *filename = getTapeFilename(nr); + int i; + + InitTapeDirectory(leveldir_current->subdir); + + tape.file_version = FILE_VERSION_ACTUAL; + tape.game_version = GAME_VERSION_ACTUAL; + + tape.num_participating_players = 0; + + // count number of participating players + for (i = 0; i < MAX_PLAYERS; i++) + if (tape.player_participates[i]) + tape.num_participating_players++; + + SaveTapeToFilename(filename); tape.changed = FALSE; } -static boolean SaveTapeCheckedExt(int nr, char *msg_replace, char *msg_saved) +static boolean SaveTapeCheckedExt(int nr, char *msg_replace, char *msg_saved, + unsigned int req_state_added) { char *filename = getTapeFilename(nr); boolean new_tape = !fileExists(filename); boolean tape_saved = FALSE; - if (new_tape || Request(msg_replace, REQ_ASK)) + if (new_tape || Request(msg_replace, REQ_ASK | req_state_added)) { SaveTape(nr); if (new_tape) - Request(msg_saved, REQ_CONFIRM); + Request(msg_saved, REQ_CONFIRM | req_state_added); tape_saved = TRUE; } @@ -8192,13 +8282,13 @@ static boolean SaveTapeCheckedExt(int nr, char *msg_replace, char *msg_saved) boolean SaveTapeChecked(int nr) { - return SaveTapeCheckedExt(nr, "Replace old tape?", "Tape saved!"); + return SaveTapeCheckedExt(nr, "Replace old tape?", "Tape saved!", 0); } boolean SaveTapeChecked_LevelSolved(int nr) { return SaveTapeCheckedExt(nr, "Level solved! Replace old tape?", - "Level solved! Tape saved!"); + "Level solved! Tape saved!", REQ_STAY_OPEN); } void DumpTape(struct TapeInfo *tape) @@ -8208,7 +8298,7 @@ void DumpTape(struct TapeInfo *tape) if (tape->no_valid_file) { - Error(ERR_WARN, "cannot dump -- no valid tape file found"); + Warn("cannot dump -- no valid tape file found"); return; } @@ -8288,15 +8378,18 @@ void LoadScore(int nr) if (!checkCookieString(cookie, SCORE_COOKIE)) { - Error(ERR_WARN, "unknown format of score file '%s'", filename); + Warn("unknown format of score file '%s'", filename); + fclose(file); + return; } for (i = 0; i < MAX_SCORE_ENTRIES; i++) { if (fscanf(file, "%d", &highscore[i].Score) == EOF) - Error(ERR_WARN, "fscanf() failed; %s", strerror(errno)); + Warn("fscanf() failed; %s", strerror(errno)); + if (fgets(line, MAX_LINE_LEN, file) == NULL) line[0] = '\0'; @@ -8329,7 +8422,8 @@ void SaveScore(int nr) if (!(file = fopen(filename, MODE_WRITE))) { - Error(ERR_WARN, "cannot save score for level %d", nr); + Warn("cannot save score for level %d", nr); + return; } @@ -8350,527 +8444,842 @@ void SaveScore(int nr) #define TOKEN_STR_PLAYER_PREFIX "player_" -// global setup -enum -{ - SETUP_TOKEN_PLAYER_NAME = 0, - SETUP_TOKEN_SOUND, - SETUP_TOKEN_SOUND_LOOPS, - SETUP_TOKEN_SOUND_MUSIC, - SETUP_TOKEN_SOUND_SIMPLE, - SETUP_TOKEN_TOONS, - SETUP_TOKEN_SCROLL_DELAY, - SETUP_TOKEN_SCROLL_DELAY_VALUE, - SETUP_TOKEN_ENGINE_SNAPSHOT_MODE, - SETUP_TOKEN_ENGINE_SNAPSHOT_MEMORY, - SETUP_TOKEN_FADE_SCREENS, - SETUP_TOKEN_AUTORECORD, - SETUP_TOKEN_SHOW_TITLESCREEN, - SETUP_TOKEN_QUICK_DOORS, - SETUP_TOKEN_TEAM_MODE, - SETUP_TOKEN_HANDICAP, - SETUP_TOKEN_SKIP_LEVELS, - SETUP_TOKEN_INCREMENT_LEVELS, - SETUP_TOKEN_AUTO_PLAY_NEXT_LEVEL, - SETUP_TOKEN_SKIP_SCORES_AFTER_GAME, - SETUP_TOKEN_TIME_LIMIT, - SETUP_TOKEN_FULLSCREEN, - SETUP_TOKEN_WINDOW_SCALING_PERCENT, - SETUP_TOKEN_WINDOW_SCALING_QUALITY, - SETUP_TOKEN_SCREEN_RENDERING_MODE, - SETUP_TOKEN_VSYNC_MODE, - SETUP_TOKEN_ASK_ON_ESCAPE, - SETUP_TOKEN_ASK_ON_ESCAPE_EDITOR, - SETUP_TOKEN_ASK_ON_GAME_OVER, - SETUP_TOKEN_QUICK_SWITCH, - SETUP_TOKEN_INPUT_ON_FOCUS, - SETUP_TOKEN_PREFER_AGA_GRAPHICS, - SETUP_TOKEN_GAME_SPEED_EXTENDED, - SETUP_TOKEN_GAME_FRAME_DELAY, - SETUP_TOKEN_SP_SHOW_BORDER_ELEMENTS, - SETUP_TOKEN_SMALL_GAME_GRAPHICS, - SETUP_TOKEN_SHOW_SNAPSHOT_BUTTONS, - SETUP_TOKEN_GRAPHICS_SET, - SETUP_TOKEN_SOUNDS_SET, - SETUP_TOKEN_MUSIC_SET, - SETUP_TOKEN_OVERRIDE_LEVEL_GRAPHICS, - SETUP_TOKEN_OVERRIDE_LEVEL_SOUNDS, - SETUP_TOKEN_OVERRIDE_LEVEL_MUSIC, - SETUP_TOKEN_VOLUME_SIMPLE, - SETUP_TOKEN_VOLUME_LOOPS, - SETUP_TOKEN_VOLUME_MUSIC, - SETUP_TOKEN_NETWORK_MODE, - SETUP_TOKEN_NETWORK_PLAYER_NR, - SETUP_TOKEN_NETWORK_SERVER_HOSTNAME, - SETUP_TOKEN_TOUCH_CONTROL_TYPE, - SETUP_TOKEN_TOUCH_MOVE_DISTANCE, - SETUP_TOKEN_TOUCH_DROP_DISTANCE, - SETUP_TOKEN_TOUCH_TRANSPARENCY, - SETUP_TOKEN_TOUCH_DRAW_OUTLINED, - SETUP_TOKEN_TOUCH_DRAW_PRESSED, - SETUP_TOKEN_TOUCH_GRID_XSIZE_0, - SETUP_TOKEN_TOUCH_GRID_YSIZE_0, - SETUP_TOKEN_TOUCH_GRID_XSIZE_1, - SETUP_TOKEN_TOUCH_GRID_YSIZE_1, - - NUM_GLOBAL_SETUP_TOKENS -}; - -// auto setup -enum -{ - SETUP_TOKEN_AUTO_EDITOR_ZOOM_TILESIZE = 0, - - NUM_AUTO_SETUP_TOKENS -}; - -// editor setup -enum -{ - SETUP_TOKEN_EDITOR_EL_CLASSIC = 0, - SETUP_TOKEN_EDITOR_EL_CUSTOM, - SETUP_TOKEN_EDITOR_EL_USER_DEFINED, - SETUP_TOKEN_EDITOR_EL_DYNAMIC, - SETUP_TOKEN_EDITOR_EL_HEADLINES, - SETUP_TOKEN_EDITOR_SHOW_ELEMENT_TOKEN, - - NUM_EDITOR_SETUP_TOKENS -}; - -// editor cascade setup -enum -{ - SETUP_TOKEN_EDITOR_CASCADE_BD = 0, - SETUP_TOKEN_EDITOR_CASCADE_EM, - SETUP_TOKEN_EDITOR_CASCADE_EMC, - SETUP_TOKEN_EDITOR_CASCADE_RND, - SETUP_TOKEN_EDITOR_CASCADE_SB, - SETUP_TOKEN_EDITOR_CASCADE_SP, - SETUP_TOKEN_EDITOR_CASCADE_DC, - SETUP_TOKEN_EDITOR_CASCADE_DX, - SETUP_TOKEN_EDITOR_CASCADE_TEXT, - SETUP_TOKEN_EDITOR_CASCADE_STEELTEXT, - SETUP_TOKEN_EDITOR_CASCADE_CE, - SETUP_TOKEN_EDITOR_CASCADE_GE, - SETUP_TOKEN_EDITOR_CASCADE_REF, - SETUP_TOKEN_EDITOR_CASCADE_USER, - SETUP_TOKEN_EDITOR_CASCADE_DYNAMIC, - - NUM_EDITOR_CASCADE_SETUP_TOKENS -}; - -// shortcut setup -enum -{ - SETUP_TOKEN_SHORTCUT_SAVE_GAME = 0, - SETUP_TOKEN_SHORTCUT_LOAD_GAME, - SETUP_TOKEN_SHORTCUT_TOGGLE_PAUSE, - SETUP_TOKEN_SHORTCUT_FOCUS_PLAYER_1, - SETUP_TOKEN_SHORTCUT_FOCUS_PLAYER_2, - SETUP_TOKEN_SHORTCUT_FOCUS_PLAYER_3, - SETUP_TOKEN_SHORTCUT_FOCUS_PLAYER_4, - SETUP_TOKEN_SHORTCUT_FOCUS_PLAYER_ALL, - SETUP_TOKEN_SHORTCUT_TAPE_EJECT, - SETUP_TOKEN_SHORTCUT_TAPE_EXTRA, - SETUP_TOKEN_SHORTCUT_TAPE_STOP, - SETUP_TOKEN_SHORTCUT_TAPE_PAUSE, - SETUP_TOKEN_SHORTCUT_TAPE_RECORD, - SETUP_TOKEN_SHORTCUT_TAPE_PLAY, - SETUP_TOKEN_SHORTCUT_SOUND_SIMPLE, - SETUP_TOKEN_SHORTCUT_SOUND_LOOPS, - SETUP_TOKEN_SHORTCUT_SOUND_MUSIC, - SETUP_TOKEN_SHORTCUT_SNAP_LEFT, - SETUP_TOKEN_SHORTCUT_SNAP_RIGHT, - SETUP_TOKEN_SHORTCUT_SNAP_UP, - SETUP_TOKEN_SHORTCUT_SNAP_DOWN, - - NUM_SHORTCUT_SETUP_TOKENS -}; - -// player setup -enum -{ - SETUP_TOKEN_PLAYER_USE_JOYSTICK = 0, - SETUP_TOKEN_PLAYER_JOY_DEVICE_NAME, - SETUP_TOKEN_PLAYER_JOY_XLEFT, - SETUP_TOKEN_PLAYER_JOY_XMIDDLE, - SETUP_TOKEN_PLAYER_JOY_XRIGHT, - SETUP_TOKEN_PLAYER_JOY_YUPPER, - SETUP_TOKEN_PLAYER_JOY_YMIDDLE, - SETUP_TOKEN_PLAYER_JOY_YLOWER, - SETUP_TOKEN_PLAYER_JOY_SNAP, - SETUP_TOKEN_PLAYER_JOY_DROP, - SETUP_TOKEN_PLAYER_KEY_LEFT, - SETUP_TOKEN_PLAYER_KEY_RIGHT, - SETUP_TOKEN_PLAYER_KEY_UP, - SETUP_TOKEN_PLAYER_KEY_DOWN, - SETUP_TOKEN_PLAYER_KEY_SNAP, - SETUP_TOKEN_PLAYER_KEY_DROP, - - NUM_PLAYER_SETUP_TOKENS -}; - -// system setup -enum -{ - SETUP_TOKEN_SYSTEM_SDL_VIDEODRIVER = 0, - SETUP_TOKEN_SYSTEM_SDL_AUDIODRIVER, - SETUP_TOKEN_SYSTEM_AUDIO_FRAGMENT_SIZE, - - NUM_SYSTEM_SETUP_TOKENS -}; - -// internal setup -enum -{ - SETUP_TOKEN_INT_PROGRAM_TITLE = 0, - SETUP_TOKEN_INT_PROGRAM_VERSION, - SETUP_TOKEN_INT_PROGRAM_AUTHOR, - SETUP_TOKEN_INT_PROGRAM_EMAIL, - SETUP_TOKEN_INT_PROGRAM_WEBSITE, - SETUP_TOKEN_INT_PROGRAM_COPYRIGHT, - SETUP_TOKEN_INT_PROGRAM_COMPANY, - SETUP_TOKEN_INT_PROGRAM_ICON_FILE, - SETUP_TOKEN_INT_DEFAULT_GRAPHICS_SET, - SETUP_TOKEN_INT_DEFAULT_SOUNDS_SET, - SETUP_TOKEN_INT_DEFAULT_MUSIC_SET, - SETUP_TOKEN_INT_FALLBACK_GRAPHICS_FILE, - SETUP_TOKEN_INT_FALLBACK_SOUNDS_FILE, - SETUP_TOKEN_INT_FALLBACK_MUSIC_FILE, - SETUP_TOKEN_INT_DEFAULT_LEVEL_SERIES, - SETUP_TOKEN_INT_CHOOSE_FROM_TOP_LEVELDIR, - SETUP_TOKEN_INT_SHOW_SCALING_IN_TITLE, - SETUP_TOKEN_INT_DEFAULT_WINDOW_WIDTH, - SETUP_TOKEN_INT_DEFAULT_WINDOW_HEIGHT, - - NUM_INTERNAL_SETUP_TOKENS -}; - -// debug setup -enum -{ - SETUP_TOKEN_DEBUG_FRAME_DELAY_0 = 0, - SETUP_TOKEN_DEBUG_FRAME_DELAY_1, - SETUP_TOKEN_DEBUG_FRAME_DELAY_2, - SETUP_TOKEN_DEBUG_FRAME_DELAY_3, - SETUP_TOKEN_DEBUG_FRAME_DELAY_4, - SETUP_TOKEN_DEBUG_FRAME_DELAY_5, - SETUP_TOKEN_DEBUG_FRAME_DELAY_6, - SETUP_TOKEN_DEBUG_FRAME_DELAY_7, - SETUP_TOKEN_DEBUG_FRAME_DELAY_8, - SETUP_TOKEN_DEBUG_FRAME_DELAY_9, - SETUP_TOKEN_DEBUG_FRAME_DELAY_KEY_0, - SETUP_TOKEN_DEBUG_FRAME_DELAY_KEY_1, - SETUP_TOKEN_DEBUG_FRAME_DELAY_KEY_2, - SETUP_TOKEN_DEBUG_FRAME_DELAY_KEY_3, - SETUP_TOKEN_DEBUG_FRAME_DELAY_KEY_4, - SETUP_TOKEN_DEBUG_FRAME_DELAY_KEY_5, - SETUP_TOKEN_DEBUG_FRAME_DELAY_KEY_6, - SETUP_TOKEN_DEBUG_FRAME_DELAY_KEY_7, - SETUP_TOKEN_DEBUG_FRAME_DELAY_KEY_8, - SETUP_TOKEN_DEBUG_FRAME_DELAY_KEY_9, - SETUP_TOKEN_DEBUG_FRAME_DELAY_USE_MOD_KEY, - SETUP_TOKEN_DEBUG_FRAME_DELAY_GAME_ONLY, - SETUP_TOKEN_DEBUG_SHOW_FRAMES_PER_SECOND, - - NUM_DEBUG_SETUP_TOKENS -}; - -// options setup -enum -{ - SETUP_TOKEN_OPTIONS_VERBOSE = 0, - - NUM_OPTIONS_SETUP_TOKENS -}; - - -static struct SetupInfo si; -static struct SetupAutoSetupInfo sasi; -static struct SetupEditorInfo sei; -static struct SetupEditorCascadeInfo seci; -static struct SetupShortcutInfo ssi; -static struct SetupInputInfo sii; -static struct SetupSystemInfo syi; -static struct SetupInternalInfo sxi; -static struct SetupDebugInfo sdi; -static struct OptionInfo soi; static struct TokenInfo global_setup_tokens[] = { - { TYPE_STRING, &si.player_name, "player_name" }, - { TYPE_SWITCH, &si.sound, "sound" }, - { TYPE_SWITCH, &si.sound_loops, "repeating_sound_loops" }, - { TYPE_SWITCH, &si.sound_music, "background_music" }, - { TYPE_SWITCH, &si.sound_simple, "simple_sound_effects" }, - { TYPE_SWITCH, &si.toons, "toons" }, - { TYPE_SWITCH, &si.scroll_delay, "scroll_delay" }, - { TYPE_INTEGER,&si.scroll_delay_value, "scroll_delay_value" }, - { TYPE_STRING, &si.engine_snapshot_mode, "engine_snapshot_mode" }, - { TYPE_INTEGER,&si.engine_snapshot_memory, "engine_snapshot_memory" }, - { TYPE_SWITCH, &si.fade_screens, "fade_screens" }, - { TYPE_SWITCH, &si.autorecord, "automatic_tape_recording"}, - { TYPE_SWITCH, &si.show_titlescreen, "show_titlescreen" }, - { TYPE_SWITCH, &si.quick_doors, "quick_doors" }, - { TYPE_SWITCH, &si.team_mode, "team_mode" }, - { TYPE_SWITCH, &si.handicap, "handicap" }, - { TYPE_SWITCH, &si.skip_levels, "skip_levels" }, - { TYPE_SWITCH, &si.increment_levels, "increment_levels" }, - { TYPE_SWITCH, &si.auto_play_next_level, "auto_play_next_level" }, - { TYPE_SWITCH, &si.skip_scores_after_game, "skip_scores_after_game" }, - { TYPE_SWITCH, &si.time_limit, "time_limit" }, - { TYPE_SWITCH, &si.fullscreen, "fullscreen" }, - { TYPE_INTEGER,&si.window_scaling_percent, "window_scaling_percent" }, - { TYPE_STRING, &si.window_scaling_quality, "window_scaling_quality" }, - { TYPE_STRING, &si.screen_rendering_mode, "screen_rendering_mode" }, - { TYPE_STRING, &si.vsync_mode, "vsync_mode" }, - { TYPE_SWITCH, &si.ask_on_escape, "ask_on_escape" }, - { TYPE_SWITCH, &si.ask_on_escape_editor, "ask_on_escape_editor" }, - { TYPE_SWITCH, &si.ask_on_game_over, "ask_on_game_over" }, - { TYPE_SWITCH, &si.quick_switch, "quick_player_switch" }, - { TYPE_SWITCH, &si.input_on_focus, "input_on_focus" }, - { TYPE_SWITCH, &si.prefer_aga_graphics, "prefer_aga_graphics" }, - { TYPE_SWITCH, &si.game_speed_extended, "game_speed_extended" }, - { TYPE_INTEGER,&si.game_frame_delay, "game_frame_delay" }, - { TYPE_SWITCH, &si.sp_show_border_elements, "sp_show_border_elements" }, - { TYPE_SWITCH, &si.small_game_graphics, "small_game_graphics" }, - { TYPE_SWITCH, &si.show_snapshot_buttons, "show_snapshot_buttons" }, - { TYPE_STRING, &si.graphics_set, "graphics_set" }, - { TYPE_STRING, &si.sounds_set, "sounds_set" }, - { TYPE_STRING, &si.music_set, "music_set" }, - { TYPE_SWITCH3,&si.override_level_graphics, "override_level_graphics" }, - { TYPE_SWITCH3,&si.override_level_sounds, "override_level_sounds" }, - { TYPE_SWITCH3,&si.override_level_music, "override_level_music" }, - { TYPE_INTEGER,&si.volume_simple, "volume_simple" }, - { TYPE_INTEGER,&si.volume_loops, "volume_loops" }, - { TYPE_INTEGER,&si.volume_music, "volume_music" }, - { TYPE_SWITCH, &si.network_mode, "network_mode" }, - { TYPE_PLAYER, &si.network_player_nr, "network_player" }, - { TYPE_STRING, &si.network_server_hostname, "network_server_hostname" }, - { TYPE_STRING, &si.touch.control_type, "touch.control_type" }, - { TYPE_INTEGER,&si.touch.move_distance, "touch.move_distance" }, - { TYPE_INTEGER,&si.touch.drop_distance, "touch.drop_distance" }, - { TYPE_INTEGER,&si.touch.transparency, "touch.transparency" }, - { TYPE_INTEGER,&si.touch.draw_outlined, "touch.draw_outlined" }, - { TYPE_INTEGER,&si.touch.draw_pressed, "touch.draw_pressed" }, - { TYPE_INTEGER,&si.touch.grid_xsize[0], "touch.virtual_buttons.0.xsize" }, - { TYPE_INTEGER,&si.touch.grid_ysize[0], "touch.virtual_buttons.0.ysize" }, - { TYPE_INTEGER,&si.touch.grid_xsize[1], "touch.virtual_buttons.1.xsize" }, - { TYPE_INTEGER,&si.touch.grid_ysize[1], "touch.virtual_buttons.1.ysize" }, -}; - -static struct TokenInfo auto_setup_tokens[] = -{ - { TYPE_INTEGER,&sasi.editor_zoom_tilesize, "editor.zoom_tilesize" }, -}; - -static struct TokenInfo editor_setup_tokens[] = -{ - { TYPE_SWITCH, &sei.el_classic, "editor.el_classic" }, - { TYPE_SWITCH, &sei.el_custom, "editor.el_custom" }, - { TYPE_SWITCH, &sei.el_user_defined, "editor.el_user_defined" }, - { TYPE_SWITCH, &sei.el_dynamic, "editor.el_dynamic" }, - { TYPE_SWITCH, &sei.el_headlines, "editor.el_headlines" }, - { TYPE_SWITCH, &sei.show_element_token,"editor.show_element_token" }, -}; - -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_mm, "editor.cascade.el_mm" }, - { TYPE_SWITCH, &seci.el_df, "editor.cascade.el_df" }, - { TYPE_SWITCH, &seci.el_chars, "editor.cascade.el_chars" }, - { TYPE_SWITCH, &seci.el_steel_chars, "editor.cascade.el_steel_chars" }, - { TYPE_SWITCH, &seci.el_ce, "editor.cascade.el_ce" }, - { TYPE_SWITCH, &seci.el_ge, "editor.cascade.el_ge" }, - { TYPE_SWITCH, &seci.el_ref, "editor.cascade.el_ref" }, - { TYPE_SWITCH, &seci.el_user, "editor.cascade.el_user" }, - { TYPE_SWITCH, &seci.el_dynamic, "editor.cascade.el_dynamic" }, -}; - -static struct TokenInfo shortcut_setup_tokens[] = -{ - { TYPE_KEY_X11, &ssi.save_game, "shortcut.save_game" }, - { TYPE_KEY_X11, &ssi.load_game, "shortcut.load_game" }, - { TYPE_KEY_X11, &ssi.toggle_pause, "shortcut.toggle_pause" }, - { TYPE_KEY_X11, &ssi.focus_player[0], "shortcut.focus_player_1" }, - { TYPE_KEY_X11, &ssi.focus_player[1], "shortcut.focus_player_2" }, - { TYPE_KEY_X11, &ssi.focus_player[2], "shortcut.focus_player_3" }, - { TYPE_KEY_X11, &ssi.focus_player[3], "shortcut.focus_player_4" }, - { TYPE_KEY_X11, &ssi.focus_player_all,"shortcut.focus_player_all" }, - { TYPE_KEY_X11, &ssi.tape_eject, "shortcut.tape_eject" }, - { TYPE_KEY_X11, &ssi.tape_extra, "shortcut.tape_extra" }, - { TYPE_KEY_X11, &ssi.tape_stop, "shortcut.tape_stop" }, - { TYPE_KEY_X11, &ssi.tape_pause, "shortcut.tape_pause" }, - { TYPE_KEY_X11, &ssi.tape_record, "shortcut.tape_record" }, - { TYPE_KEY_X11, &ssi.tape_play, "shortcut.tape_play" }, - { TYPE_KEY_X11, &ssi.sound_simple, "shortcut.sound_simple" }, - { TYPE_KEY_X11, &ssi.sound_loops, "shortcut.sound_loops" }, - { TYPE_KEY_X11, &ssi.sound_music, "shortcut.sound_music" }, - { TYPE_KEY_X11, &ssi.snap_left, "shortcut.snap_left" }, - { TYPE_KEY_X11, &ssi.snap_right, "shortcut.snap_right" }, - { TYPE_KEY_X11, &ssi.snap_up, "shortcut.snap_up" }, - { TYPE_KEY_X11, &ssi.snap_down, "shortcut.snap_down" }, -}; - -static struct TokenInfo player_setup_tokens[] = -{ - { TYPE_BOOLEAN, &sii.use_joystick, ".use_joystick" }, - { TYPE_STRING, &sii.joy.device_name, ".joy.device_name" }, - { TYPE_INTEGER, &sii.joy.xleft, ".joy.xleft" }, - { TYPE_INTEGER, &sii.joy.xmiddle, ".joy.xmiddle" }, - { TYPE_INTEGER, &sii.joy.xright, ".joy.xright" }, - { TYPE_INTEGER, &sii.joy.yupper, ".joy.yupper" }, - { TYPE_INTEGER, &sii.joy.ymiddle, ".joy.ymiddle" }, - { TYPE_INTEGER, &sii.joy.ylower, ".joy.ylower" }, - { TYPE_INTEGER, &sii.joy.snap, ".joy.snap_field" }, - { TYPE_INTEGER, &sii.joy.drop, ".joy.place_bomb" }, - { TYPE_KEY_X11, &sii.key.left, ".key.move_left" }, - { TYPE_KEY_X11, &sii.key.right, ".key.move_right" }, - { TYPE_KEY_X11, &sii.key.up, ".key.move_up" }, - { TYPE_KEY_X11, &sii.key.down, ".key.move_down" }, - { TYPE_KEY_X11, &sii.key.snap, ".key.snap_field" }, - { TYPE_KEY_X11, &sii.key.drop, ".key.place_bomb" }, -}; - -static struct TokenInfo system_setup_tokens[] = -{ - { TYPE_STRING, &syi.sdl_videodriver, "system.sdl_videodriver" }, - { TYPE_STRING, &syi.sdl_audiodriver, "system.sdl_audiodriver" }, - { TYPE_INTEGER, &syi.audio_fragment_size,"system.audio_fragment_size" }, -}; - -static struct TokenInfo internal_setup_tokens[] = -{ - { TYPE_STRING, &sxi.program_title, "program_title" }, - { TYPE_STRING, &sxi.program_version, "program_version" }, - { TYPE_STRING, &sxi.program_author, "program_author" }, - { TYPE_STRING, &sxi.program_email, "program_email" }, - { TYPE_STRING, &sxi.program_website, "program_website" }, - { TYPE_STRING, &sxi.program_copyright, "program_copyright" }, - { TYPE_STRING, &sxi.program_company, "program_company" }, - { TYPE_STRING, &sxi.program_icon_file, "program_icon_file" }, - { TYPE_STRING, &sxi.default_graphics_set, "default_graphics_set" }, - { TYPE_STRING, &sxi.default_sounds_set, "default_sounds_set" }, - { TYPE_STRING, &sxi.default_music_set, "default_music_set" }, - { TYPE_STRING, &sxi.fallback_graphics_file, "fallback_graphics_file"}, - { TYPE_STRING, &sxi.fallback_sounds_file, "fallback_sounds_file" }, - { TYPE_STRING, &sxi.fallback_music_file, "fallback_music_file" }, - { TYPE_STRING, &sxi.default_level_series, "default_level_series" }, - { TYPE_BOOLEAN,&sxi.choose_from_top_leveldir, "choose_from_top_leveldir" }, - { TYPE_BOOLEAN,&sxi.show_scaling_in_title, "show_scaling_in_title" }, - { TYPE_INTEGER,&sxi.default_window_width, "default_window_width" }, - { TYPE_INTEGER,&sxi.default_window_height, "default_window_height" }, -}; - -static struct TokenInfo debug_setup_tokens[] = -{ - { TYPE_INTEGER, &sdi.frame_delay[0], "debug.frame_delay_0" }, - { TYPE_INTEGER, &sdi.frame_delay[1], "debug.frame_delay_1" }, - { TYPE_INTEGER, &sdi.frame_delay[2], "debug.frame_delay_2" }, - { TYPE_INTEGER, &sdi.frame_delay[3], "debug.frame_delay_3" }, - { TYPE_INTEGER, &sdi.frame_delay[4], "debug.frame_delay_4" }, - { TYPE_INTEGER, &sdi.frame_delay[5], "debug.frame_delay_5" }, - { TYPE_INTEGER, &sdi.frame_delay[6], "debug.frame_delay_6" }, - { TYPE_INTEGER, &sdi.frame_delay[7], "debug.frame_delay_7" }, - { TYPE_INTEGER, &sdi.frame_delay[8], "debug.frame_delay_8" }, - { TYPE_INTEGER, &sdi.frame_delay[9], "debug.frame_delay_9" }, - { TYPE_KEY_X11, &sdi.frame_delay_key[0], "debug.key.frame_delay_0" }, - { TYPE_KEY_X11, &sdi.frame_delay_key[1], "debug.key.frame_delay_1" }, - { TYPE_KEY_X11, &sdi.frame_delay_key[2], "debug.key.frame_delay_2" }, - { TYPE_KEY_X11, &sdi.frame_delay_key[3], "debug.key.frame_delay_3" }, - { TYPE_KEY_X11, &sdi.frame_delay_key[4], "debug.key.frame_delay_4" }, - { TYPE_KEY_X11, &sdi.frame_delay_key[5], "debug.key.frame_delay_5" }, - { TYPE_KEY_X11, &sdi.frame_delay_key[6], "debug.key.frame_delay_6" }, - { TYPE_KEY_X11, &sdi.frame_delay_key[7], "debug.key.frame_delay_7" }, - { TYPE_KEY_X11, &sdi.frame_delay_key[8], "debug.key.frame_delay_8" }, - { TYPE_KEY_X11, &sdi.frame_delay_key[9], "debug.key.frame_delay_9" }, - { TYPE_BOOLEAN, &sdi.frame_delay_use_mod_key,"debug.frame_delay.use_mod_key"}, - { TYPE_BOOLEAN, &sdi.frame_delay_game_only, "debug.frame_delay.game_only" }, - { TYPE_BOOLEAN, &sdi.show_frames_per_second, "debug.show_frames_per_second" }, -}; - -static struct TokenInfo options_setup_tokens[] = -{ - { TYPE_BOOLEAN, &soi.verbose, "options.verbose" }, -}; - -static char *get_corrected_login_name(char *login_name) -{ - // needed because player name must be a fixed length string - char *login_name_new = checked_malloc(MAX_PLAYER_NAME_LEN + 1); - - strncpy(login_name_new, login_name, MAX_PLAYER_NAME_LEN); - login_name_new[MAX_PLAYER_NAME_LEN] = '\0'; - - if (strlen(login_name) > MAX_PLAYER_NAME_LEN) // name has been cut - if (strchr(login_name_new, ' ')) - *strchr(login_name_new, ' ') = '\0'; - - return login_name_new; -} - -static void setSetupInfoToDefaults(struct SetupInfo *si) -{ - int i; - - si->player_name = get_corrected_login_name(getLoginName()); - - si->sound = TRUE; - si->sound_loops = TRUE; - si->sound_music = TRUE; - si->sound_simple = TRUE; - si->toons = TRUE; - si->scroll_delay = TRUE; - si->scroll_delay_value = STD_SCROLL_DELAY; - si->engine_snapshot_mode = getStringCopy(STR_SNAPSHOT_MODE_DEFAULT); - si->engine_snapshot_memory = SNAPSHOT_MEMORY_DEFAULT; - si->fade_screens = TRUE; - si->autorecord = TRUE; - si->show_titlescreen = TRUE; - si->quick_doors = FALSE; - si->team_mode = FALSE; - si->handicap = TRUE; - si->skip_levels = TRUE; - si->increment_levels = TRUE; - si->auto_play_next_level = TRUE; - si->skip_scores_after_game = FALSE; - si->time_limit = TRUE; - si->fullscreen = FALSE; - si->window_scaling_percent = STD_WINDOW_SCALING_PERCENT; - si->window_scaling_quality = getStringCopy(SCALING_QUALITY_DEFAULT); - si->screen_rendering_mode = getStringCopy(STR_SPECIAL_RENDERING_DEFAULT); - si->vsync_mode = getStringCopy(STR_VSYNC_MODE_DEFAULT); - si->ask_on_escape = TRUE; - si->ask_on_escape_editor = TRUE; - si->ask_on_game_over = TRUE; - si->quick_switch = FALSE; - si->input_on_focus = FALSE; - si->prefer_aga_graphics = TRUE; - si->game_speed_extended = FALSE; - si->game_frame_delay = GAME_FRAME_DELAY; - si->sp_show_border_elements = FALSE; - si->small_game_graphics = FALSE; - si->show_snapshot_buttons = FALSE; - - si->graphics_set = getStringCopy(GFX_CLASSIC_SUBDIR); - si->sounds_set = getStringCopy(SND_CLASSIC_SUBDIR); - si->music_set = getStringCopy(MUS_CLASSIC_SUBDIR); - - si->override_level_graphics = FALSE; - si->override_level_sounds = FALSE; - si->override_level_music = FALSE; - - si->volume_simple = 100; // percent - si->volume_loops = 100; // percent - si->volume_music = 100; // percent + { + TYPE_STRING, + &setup.player_name, "player_name" + }, + { + TYPE_SWITCH, + &setup.multiple_users, "multiple_users" + }, + { + TYPE_SWITCH, + &setup.sound, "sound" + }, + { + TYPE_SWITCH, + &setup.sound_loops, "repeating_sound_loops" + }, + { + TYPE_SWITCH, + &setup.sound_music, "background_music" + }, + { + TYPE_SWITCH, + &setup.sound_simple, "simple_sound_effects" + }, + { + TYPE_SWITCH, + &setup.toons, "toons" + }, + { + TYPE_SWITCH, + &setup.scroll_delay, "scroll_delay" + }, + { + TYPE_SWITCH, + &setup.forced_scroll_delay, "forced_scroll_delay" + }, + { + TYPE_INTEGER, + &setup.scroll_delay_value, "scroll_delay_value" + }, + { + TYPE_STRING, + &setup.engine_snapshot_mode, "engine_snapshot_mode" + }, + { + TYPE_INTEGER, + &setup.engine_snapshot_memory, "engine_snapshot_memory" + }, + { + TYPE_SWITCH, + &setup.fade_screens, "fade_screens" + }, + { + TYPE_SWITCH, + &setup.autorecord, "automatic_tape_recording" + }, + { + TYPE_SWITCH, + &setup.show_titlescreen, "show_titlescreen" + }, + { + TYPE_SWITCH, + &setup.quick_doors, "quick_doors" + }, + { + TYPE_SWITCH, + &setup.team_mode, "team_mode" + }, + { + TYPE_SWITCH, + &setup.handicap, "handicap" + }, + { + TYPE_SWITCH, + &setup.skip_levels, "skip_levels" + }, + { + TYPE_SWITCH, + &setup.increment_levels, "increment_levels" + }, + { + TYPE_SWITCH, + &setup.auto_play_next_level, "auto_play_next_level" + }, + { + TYPE_SWITCH, + &setup.skip_scores_after_game, "skip_scores_after_game" + }, + { + TYPE_SWITCH, + &setup.time_limit, "time_limit" + }, + { + TYPE_SWITCH, + &setup.fullscreen, "fullscreen" + }, + { + TYPE_INTEGER, + &setup.window_scaling_percent, "window_scaling_percent" + }, + { + TYPE_STRING, + &setup.window_scaling_quality, "window_scaling_quality" + }, + { + TYPE_STRING, + &setup.screen_rendering_mode, "screen_rendering_mode" + }, + { + TYPE_STRING, + &setup.vsync_mode, "vsync_mode" + }, + { + TYPE_SWITCH, + &setup.ask_on_escape, "ask_on_escape" + }, + { + TYPE_SWITCH, + &setup.ask_on_escape_editor, "ask_on_escape_editor" + }, + { + TYPE_SWITCH, + &setup.ask_on_game_over, "ask_on_game_over" + }, + { + TYPE_SWITCH, + &setup.quick_switch, "quick_player_switch" + }, + { + TYPE_SWITCH, + &setup.input_on_focus, "input_on_focus" + }, + { + TYPE_SWITCH, + &setup.prefer_aga_graphics, "prefer_aga_graphics" + }, + { + TYPE_SWITCH, + &setup.prefer_lowpass_sounds, "prefer_lowpass_sounds" + }, + { + TYPE_SWITCH, + &setup.prefer_extra_panel_items, "prefer_extra_panel_items" + }, + { + TYPE_SWITCH, + &setup.game_speed_extended, "game_speed_extended" + }, + { + TYPE_INTEGER, + &setup.game_frame_delay, "game_frame_delay" + }, + { + TYPE_SWITCH, + &setup.sp_show_border_elements, "sp_show_border_elements" + }, + { + TYPE_SWITCH, + &setup.small_game_graphics, "small_game_graphics" + }, + { + TYPE_SWITCH, + &setup.show_snapshot_buttons, "show_snapshot_buttons" + }, + { + TYPE_STRING, + &setup.graphics_set, "graphics_set" + }, + { + TYPE_STRING, + &setup.sounds_set, "sounds_set" + }, + { + TYPE_STRING, + &setup.music_set, "music_set" + }, + { + TYPE_SWITCH3, + &setup.override_level_graphics, "override_level_graphics" + }, + { + TYPE_SWITCH3, + &setup.override_level_sounds, "override_level_sounds" + }, + { + TYPE_SWITCH3, + &setup.override_level_music, "override_level_music" + }, + { + TYPE_INTEGER, + &setup.volume_simple, "volume_simple" + }, + { + TYPE_INTEGER, + &setup.volume_loops, "volume_loops" + }, + { + TYPE_INTEGER, + &setup.volume_music, "volume_music" + }, + { + TYPE_SWITCH, + &setup.network_mode, "network_mode" + }, + { + TYPE_PLAYER, + &setup.network_player_nr, "network_player" + }, + { + TYPE_STRING, + &setup.network_server_hostname, "network_server_hostname" + }, + { + TYPE_STRING, + &setup.touch.control_type, "touch.control_type" + }, + { + TYPE_INTEGER, + &setup.touch.move_distance, "touch.move_distance" + }, + { + TYPE_INTEGER, + &setup.touch.drop_distance, "touch.drop_distance" + }, + { + TYPE_INTEGER, + &setup.touch.transparency, "touch.transparency" + }, + { + TYPE_INTEGER, + &setup.touch.draw_outlined, "touch.draw_outlined" + }, + { + TYPE_INTEGER, + &setup.touch.draw_pressed, "touch.draw_pressed" + }, + { + TYPE_INTEGER, + &setup.touch.grid_xsize[0], "touch.virtual_buttons.0.xsize" + }, + { + TYPE_INTEGER, + &setup.touch.grid_ysize[0], "touch.virtual_buttons.0.ysize" + }, + { + TYPE_INTEGER, + &setup.touch.grid_xsize[1], "touch.virtual_buttons.1.xsize" + }, + { + TYPE_INTEGER, + &setup.touch.grid_ysize[1], "touch.virtual_buttons.1.ysize" + }, +}; + +static struct TokenInfo auto_setup_tokens[] = +{ + { + TYPE_INTEGER, + &setup.auto_setup.editor_zoom_tilesize, "editor.zoom_tilesize" + }, +}; + +static struct TokenInfo editor_setup_tokens[] = +{ + { + TYPE_SWITCH, + &setup.editor.el_classic, "editor.el_classic" + }, + { + TYPE_SWITCH, + &setup.editor.el_custom, "editor.el_custom" + }, + { + TYPE_SWITCH, + &setup.editor.el_user_defined, "editor.el_user_defined" + }, + { + TYPE_SWITCH, + &setup.editor.el_dynamic, "editor.el_dynamic" + }, + { + TYPE_SWITCH, + &setup.editor.el_headlines, "editor.el_headlines" + }, + { + TYPE_SWITCH, + &setup.editor.show_element_token, "editor.show_element_token" + }, +}; + +static struct TokenInfo editor_cascade_setup_tokens[] = +{ + { + TYPE_SWITCH, + &setup.editor_cascade.el_bd, "editor.cascade.el_bd" + }, + { + TYPE_SWITCH, + &setup.editor_cascade.el_em, "editor.cascade.el_em" + }, + { + TYPE_SWITCH, + &setup.editor_cascade.el_emc, "editor.cascade.el_emc" + }, + { + TYPE_SWITCH, + &setup.editor_cascade.el_rnd, "editor.cascade.el_rnd" + }, + { + TYPE_SWITCH, + &setup.editor_cascade.el_sb, "editor.cascade.el_sb" + }, + { + TYPE_SWITCH, + &setup.editor_cascade.el_sp, "editor.cascade.el_sp" + }, + { + TYPE_SWITCH, + &setup.editor_cascade.el_dc, "editor.cascade.el_dc" + }, + { + TYPE_SWITCH, + &setup.editor_cascade.el_dx, "editor.cascade.el_dx" + }, + { + TYPE_SWITCH, + &setup.editor_cascade.el_mm, "editor.cascade.el_mm" + }, + { + TYPE_SWITCH, + &setup.editor_cascade.el_df, "editor.cascade.el_df" + }, + { + TYPE_SWITCH, + &setup.editor_cascade.el_chars, "editor.cascade.el_chars" + }, + { + TYPE_SWITCH, + &setup.editor_cascade.el_steel_chars, "editor.cascade.el_steel_chars" + }, + { + TYPE_SWITCH, + &setup.editor_cascade.el_ce, "editor.cascade.el_ce" + }, + { + TYPE_SWITCH, + &setup.editor_cascade.el_ge, "editor.cascade.el_ge" + }, + { + TYPE_SWITCH, + &setup.editor_cascade.el_ref, "editor.cascade.el_ref" + }, + { + TYPE_SWITCH, + &setup.editor_cascade.el_user, "editor.cascade.el_user" + }, + { + TYPE_SWITCH, + &setup.editor_cascade.el_dynamic, "editor.cascade.el_dynamic" + }, +}; + +static struct TokenInfo shortcut_setup_tokens[] = +{ + { + TYPE_KEY_X11, + &setup.shortcut.save_game, "shortcut.save_game" + }, + { + TYPE_KEY_X11, + &setup.shortcut.load_game, "shortcut.load_game" + }, + { + TYPE_KEY_X11, + &setup.shortcut.toggle_pause, "shortcut.toggle_pause" + }, + { + TYPE_KEY_X11, + &setup.shortcut.focus_player[0], "shortcut.focus_player_1" + }, + { + TYPE_KEY_X11, + &setup.shortcut.focus_player[1], "shortcut.focus_player_2" + }, + { + TYPE_KEY_X11, + &setup.shortcut.focus_player[2], "shortcut.focus_player_3" + }, + { + TYPE_KEY_X11, + &setup.shortcut.focus_player[3], "shortcut.focus_player_4" + }, + { + TYPE_KEY_X11, + &setup.shortcut.focus_player_all, "shortcut.focus_player_all" + }, + { + TYPE_KEY_X11, + &setup.shortcut.tape_eject, "shortcut.tape_eject" + }, + { + TYPE_KEY_X11, + &setup.shortcut.tape_extra, "shortcut.tape_extra" + }, + { + TYPE_KEY_X11, + &setup.shortcut.tape_stop, "shortcut.tape_stop" + }, + { + TYPE_KEY_X11, + &setup.shortcut.tape_pause, "shortcut.tape_pause" + }, + { + TYPE_KEY_X11, + &setup.shortcut.tape_record, "shortcut.tape_record" + }, + { + TYPE_KEY_X11, + &setup.shortcut.tape_play, "shortcut.tape_play" + }, + { + TYPE_KEY_X11, + &setup.shortcut.sound_simple, "shortcut.sound_simple" + }, + { + TYPE_KEY_X11, + &setup.shortcut.sound_loops, "shortcut.sound_loops" + }, + { + TYPE_KEY_X11, + &setup.shortcut.sound_music, "shortcut.sound_music" + }, + { + TYPE_KEY_X11, + &setup.shortcut.snap_left, "shortcut.snap_left" + }, + { + TYPE_KEY_X11, + &setup.shortcut.snap_right, "shortcut.snap_right" + }, + { + TYPE_KEY_X11, + &setup.shortcut.snap_up, "shortcut.snap_up" + }, + { + TYPE_KEY_X11, + &setup.shortcut.snap_down, "shortcut.snap_down" + }, +}; + +static struct SetupInputInfo setup_input; +static struct TokenInfo player_setup_tokens[] = +{ + { + TYPE_BOOLEAN, + &setup_input.use_joystick, ".use_joystick" + }, + { + TYPE_STRING, + &setup_input.joy.device_name, ".joy.device_name" + }, + { + TYPE_INTEGER, + &setup_input.joy.xleft, ".joy.xleft" + }, + { + TYPE_INTEGER, + &setup_input.joy.xmiddle, ".joy.xmiddle" + }, + { + TYPE_INTEGER, + &setup_input.joy.xright, ".joy.xright" + }, + { + TYPE_INTEGER, + &setup_input.joy.yupper, ".joy.yupper" + }, + { + TYPE_INTEGER, + &setup_input.joy.ymiddle, ".joy.ymiddle" + }, + { + TYPE_INTEGER, + &setup_input.joy.ylower, ".joy.ylower" + }, + { + TYPE_INTEGER, + &setup_input.joy.snap, ".joy.snap_field" + }, + { + TYPE_INTEGER, + &setup_input.joy.drop, ".joy.place_bomb" + }, + { + TYPE_KEY_X11, + &setup_input.key.left, ".key.move_left" + }, + { + TYPE_KEY_X11, + &setup_input.key.right, ".key.move_right" + }, + { + TYPE_KEY_X11, + &setup_input.key.up, ".key.move_up" + }, + { + TYPE_KEY_X11, + &setup_input.key.down, ".key.move_down" + }, + { + TYPE_KEY_X11, + &setup_input.key.snap, ".key.snap_field" + }, + { + TYPE_KEY_X11, + &setup_input.key.drop, ".key.place_bomb" + }, +}; + +static struct TokenInfo system_setup_tokens[] = +{ + { + TYPE_STRING, + &setup.system.sdl_renderdriver, "system.sdl_renderdriver" + }, + { + TYPE_STRING, + &setup.system.sdl_videodriver, "system.sdl_videodriver" + }, + { + TYPE_STRING, + &setup.system.sdl_audiodriver, "system.sdl_audiodriver" + }, + { + TYPE_INTEGER, + &setup.system.audio_fragment_size, "system.audio_fragment_size" + }, +}; + +static struct TokenInfo internal_setup_tokens[] = +{ + { + TYPE_STRING, + &setup.internal.program_title, "program_title" + }, + { + TYPE_STRING, + &setup.internal.program_version, "program_version" + }, + { + TYPE_STRING, + &setup.internal.program_author, "program_author" + }, + { + TYPE_STRING, + &setup.internal.program_email, "program_email" + }, + { + TYPE_STRING, + &setup.internal.program_website, "program_website" + }, + { + TYPE_STRING, + &setup.internal.program_copyright, "program_copyright" + }, + { + TYPE_STRING, + &setup.internal.program_company, "program_company" + }, + { + TYPE_STRING, + &setup.internal.program_icon_file, "program_icon_file" + }, + { + TYPE_STRING, + &setup.internal.default_graphics_set, "default_graphics_set" + }, + { + TYPE_STRING, + &setup.internal.default_sounds_set, "default_sounds_set" + }, + { + TYPE_STRING, + &setup.internal.default_music_set, "default_music_set" + }, + { + TYPE_STRING, + &setup.internal.fallback_graphics_file, "fallback_graphics_file" + }, + { + TYPE_STRING, + &setup.internal.fallback_sounds_file, "fallback_sounds_file" + }, + { + TYPE_STRING, + &setup.internal.fallback_music_file, "fallback_music_file" + }, + { + TYPE_STRING, + &setup.internal.default_level_series, "default_level_series" + }, + { + TYPE_INTEGER, + &setup.internal.default_window_width, "default_window_width" + }, + { + TYPE_INTEGER, + &setup.internal.default_window_height, "default_window_height" + }, + { + TYPE_BOOLEAN, + &setup.internal.choose_from_top_leveldir, "choose_from_top_leveldir" + }, + { + TYPE_BOOLEAN, + &setup.internal.show_scaling_in_title, "show_scaling_in_title" + }, + { + TYPE_BOOLEAN, + &setup.internal.create_user_levelset, "create_user_levelset" + }, + { + TYPE_BOOLEAN, + &setup.internal.menu_game, "menu_game" + }, + { + TYPE_BOOLEAN, + &setup.internal.menu_editor, "menu_editor" + }, + { + TYPE_BOOLEAN, + &setup.internal.menu_graphics, "menu_graphics" + }, + { + TYPE_BOOLEAN, + &setup.internal.menu_sound, "menu_sound" + }, + { + TYPE_BOOLEAN, + &setup.internal.menu_artwork, "menu_artwork" + }, + { + TYPE_BOOLEAN, + &setup.internal.menu_input, "menu_input" + }, + { + TYPE_BOOLEAN, + &setup.internal.menu_touch, "menu_touch" + }, + { + TYPE_BOOLEAN, + &setup.internal.menu_shortcuts, "menu_shortcuts" + }, + { + TYPE_BOOLEAN, + &setup.internal.menu_exit, "menu_exit" + }, + { + TYPE_BOOLEAN, + &setup.internal.menu_save_and_exit, "menu_save_and_exit" + }, +}; + +static struct TokenInfo debug_setup_tokens[] = +{ + { + TYPE_INTEGER, + &setup.debug.frame_delay[0], "debug.frame_delay_0" + }, + { + TYPE_INTEGER, + &setup.debug.frame_delay[1], "debug.frame_delay_1" + }, + { + TYPE_INTEGER, + &setup.debug.frame_delay[2], "debug.frame_delay_2" + }, + { + TYPE_INTEGER, + &setup.debug.frame_delay[3], "debug.frame_delay_3" + }, + { + TYPE_INTEGER, + &setup.debug.frame_delay[4], "debug.frame_delay_4" + }, + { + TYPE_INTEGER, + &setup.debug.frame_delay[5], "debug.frame_delay_5" + }, + { + TYPE_INTEGER, + &setup.debug.frame_delay[6], "debug.frame_delay_6" + }, + { + TYPE_INTEGER, + &setup.debug.frame_delay[7], "debug.frame_delay_7" + }, + { + TYPE_INTEGER, + &setup.debug.frame_delay[8], "debug.frame_delay_8" + }, + { + TYPE_INTEGER, + &setup.debug.frame_delay[9], "debug.frame_delay_9" + }, + { + TYPE_KEY_X11, + &setup.debug.frame_delay_key[0], "debug.key.frame_delay_0" + }, + { + TYPE_KEY_X11, + &setup.debug.frame_delay_key[1], "debug.key.frame_delay_1" + }, + { + TYPE_KEY_X11, + &setup.debug.frame_delay_key[2], "debug.key.frame_delay_2" + }, + { + TYPE_KEY_X11, + &setup.debug.frame_delay_key[3], "debug.key.frame_delay_3" + }, + { + TYPE_KEY_X11, + &setup.debug.frame_delay_key[4], "debug.key.frame_delay_4" + }, + { + TYPE_KEY_X11, + &setup.debug.frame_delay_key[5], "debug.key.frame_delay_5" + }, + { + TYPE_KEY_X11, + &setup.debug.frame_delay_key[6], "debug.key.frame_delay_6" + }, + { + TYPE_KEY_X11, + &setup.debug.frame_delay_key[7], "debug.key.frame_delay_7" + }, + { + TYPE_KEY_X11, + &setup.debug.frame_delay_key[8], "debug.key.frame_delay_8" + }, + { + TYPE_KEY_X11, + &setup.debug.frame_delay_key[9], "debug.key.frame_delay_9" + }, + { + TYPE_BOOLEAN, + &setup.debug.frame_delay_use_mod_key, "debug.frame_delay.use_mod_key"}, + { + TYPE_BOOLEAN, + &setup.debug.frame_delay_game_only, "debug.frame_delay.game_only" + }, + { + TYPE_BOOLEAN, + &setup.debug.show_frames_per_second, "debug.show_frames_per_second" + }, + { + TYPE_SWITCH3, + &setup.debug.xsn_mode, "debug.xsn_mode" + }, + { + TYPE_INTEGER, + &setup.debug.xsn_percent, "debug.xsn_percent" + }, +}; + +static struct TokenInfo options_setup_tokens[] = +{ + { + TYPE_BOOLEAN, + &setup.options.verbose, "options.verbose" + }, +}; + +static void setSetupInfoToDefaults(struct SetupInfo *si) +{ + int i; + + si->player_name = getStringCopy(getDefaultUserName(user.nr)); + + si->multiple_users = TRUE; + + si->sound = TRUE; + si->sound_loops = TRUE; + si->sound_music = TRUE; + si->sound_simple = TRUE; + si->toons = TRUE; + si->scroll_delay = TRUE; + si->forced_scroll_delay = FALSE; + si->scroll_delay_value = STD_SCROLL_DELAY; + si->engine_snapshot_mode = getStringCopy(STR_SNAPSHOT_MODE_DEFAULT); + si->engine_snapshot_memory = SNAPSHOT_MEMORY_DEFAULT; + si->fade_screens = TRUE; + si->autorecord = TRUE; + si->show_titlescreen = TRUE; + si->quick_doors = FALSE; + si->team_mode = FALSE; + si->handicap = TRUE; + si->skip_levels = TRUE; + si->increment_levels = TRUE; + si->auto_play_next_level = TRUE; + si->skip_scores_after_game = FALSE; + si->time_limit = TRUE; + si->fullscreen = FALSE; + si->window_scaling_percent = STD_WINDOW_SCALING_PERCENT; + si->window_scaling_quality = getStringCopy(SCALING_QUALITY_DEFAULT); + si->screen_rendering_mode = getStringCopy(STR_SPECIAL_RENDERING_DEFAULT); + si->vsync_mode = getStringCopy(STR_VSYNC_MODE_DEFAULT); + si->ask_on_escape = TRUE; + si->ask_on_escape_editor = TRUE; + si->ask_on_game_over = TRUE; + si->quick_switch = FALSE; + si->input_on_focus = FALSE; + si->prefer_aga_graphics = TRUE; + si->prefer_lowpass_sounds = FALSE; + si->prefer_extra_panel_items = TRUE; + si->game_speed_extended = FALSE; + si->game_frame_delay = GAME_FRAME_DELAY; + si->sp_show_border_elements = FALSE; + si->small_game_graphics = FALSE; + si->show_snapshot_buttons = FALSE; + + si->graphics_set = getStringCopy(GFX_CLASSIC_SUBDIR); + si->sounds_set = getStringCopy(SND_CLASSIC_SUBDIR); + si->music_set = getStringCopy(MUS_CLASSIC_SUBDIR); + + si->override_level_graphics = FALSE; + si->override_level_sounds = FALSE; + si->override_level_music = FALSE; + + si->volume_simple = 100; // percent + si->volume_loops = 100; // percent + si->volume_music = 100; // percent si->network_mode = FALSE; si->network_player_nr = 0; // first player @@ -9005,6 +9414,7 @@ static void setSetupInfoToDefaults(struct SetupInfo *si) si->input[i].key.drop = (i == 0 ? DEFAULT_KEY_DROP : KSYM_UNDEFINED); } + si->system.sdl_renderdriver = getStringCopy(ARG_DEFAULT); si->system.sdl_videodriver = getStringCopy(ARG_DEFAULT); si->system.sdl_audiodriver = getStringCopy(ARG_DEFAULT); si->system.audio_fragment_size = DEFAULT_AUDIO_FRAGMENT_SIZE; @@ -9030,6 +9440,7 @@ static void setSetupInfoToDefaults(struct SetupInfo *si) si->internal.default_level_series = getStringCopy(UNDEFINED_LEVELSET); si->internal.choose_from_top_leveldir = FALSE; si->internal.show_scaling_in_title = TRUE; + si->internal.create_user_levelset = TRUE; si->internal.default_window_width = WIN_XSIZE_DEFAULT; si->internal.default_window_height = WIN_YSIZE_DEFAULT; @@ -9061,11 +9472,16 @@ static void setSetupInfoToDefaults(struct SetupInfo *si) si->debug.show_frames_per_second = FALSE; + si->debug.xsn_mode = AUTO; + si->debug.xsn_percent = 0; + si->options.verbose = FALSE; #if defined(PLATFORM_ANDROID) si->fullscreen = TRUE; #endif + + setHideSetupEntry(&setup.debug.xsn_mode); } static void setSetupInfoToDefaults_AutoSetup(struct SetupInfo *si) @@ -9112,16 +9528,19 @@ void setHideSetupEntry(void *setup_value) { char *hide_setup_token = getHideSetupToken(setup_value); + if (hide_setup_hash == NULL) + hide_setup_hash = newSetupFileHash(); + if (setup_value != NULL) setHashEntry(hide_setup_hash, hide_setup_token, ""); } -static void setHideSetupEntryRaw(char *token_text, void *setup_value_raw) +void removeHideSetupEntry(void *setup_value) { - // !!! DIRTY WORKAROUND; TO BE FIXED AFTER THE MM ENGINE RELEASE !!! - void *setup_value = setup_value_raw - (void *)&si + (void *)&setup; + char *hide_setup_token = getHideSetupToken(setup_value); - setHideSetupEntry(setup_value); + if (setup_value != NULL) + removeHashEntry(hide_setup_hash, hide_setup_token); } boolean hideSetupEntry(void *setup_value) @@ -9144,7 +9563,9 @@ static void setSetupInfoFromTokenText(SetupFileHash *setup_file_hash, // check if this setup option should be hidden in the setup menu if (token_hide_value != NULL && get_boolean_from_string(token_hide_value)) - setHideSetupEntryRaw(token_text, token_info[token_nr].value); + setHideSetupEntry(token_info[token_nr].value); + + free(token_hide_text); } static void setSetupInfoFromTokenInfo(SetupFileHash *setup_file_hash, @@ -9162,16 +9583,9 @@ static void decodeSetupFileHash(SetupFileHash *setup_file_hash) if (!setup_file_hash) return; - if (hide_setup_hash == NULL) - hide_setup_hash = newSetupFileHash(); - - // global setup - si = setup; - for (i = 0; i < NUM_GLOBAL_SETUP_TOKENS; i++) + for (i = 0; i < ARRAY_SIZE(global_setup_tokens); i++) setSetupInfoFromTokenInfo(setup_file_hash, global_setup_tokens, i); - setup = si; - // virtual buttons setup setup.touch.grid_initialized = TRUE; for (i = 0; i < 2; i++) { @@ -9210,27 +9624,20 @@ static void decodeSetupFileHash(SetupFileHash *setup_file_hash) } } - // editor setup - sei = setup.editor; - for (i = 0; i < NUM_EDITOR_SETUP_TOKENS; i++) + for (i = 0; i < ARRAY_SIZE(editor_setup_tokens); i++) setSetupInfoFromTokenInfo(setup_file_hash, editor_setup_tokens, i); - setup.editor = sei; - // shortcut setup - ssi = setup.shortcut; - for (i = 0; i < NUM_SHORTCUT_SETUP_TOKENS; i++) + for (i = 0; i < ARRAY_SIZE(shortcut_setup_tokens); i++) setSetupInfoFromTokenInfo(setup_file_hash, shortcut_setup_tokens, i); - setup.shortcut = ssi; - // player setup for (pnr = 0; pnr < MAX_PLAYERS; pnr++) { char prefix[30]; sprintf(prefix, "%s%d", TOKEN_STR_PLAYER_PREFIX, pnr + 1); - sii = setup.input[pnr]; - for (i = 0; i < NUM_PLAYER_SETUP_TOKENS; i++) + setup_input = setup.input[pnr]; + for (i = 0; i < ARRAY_SIZE(player_setup_tokens); i++) { char full_token[100]; @@ -9238,32 +9645,20 @@ static void decodeSetupFileHash(SetupFileHash *setup_file_hash) setSetupInfoFromTokenText(setup_file_hash, player_setup_tokens, i, full_token); } - setup.input[pnr] = sii; + setup.input[pnr] = setup_input; } - // system setup - syi = setup.system; - for (i = 0; i < NUM_SYSTEM_SETUP_TOKENS; i++) + for (i = 0; i < ARRAY_SIZE(system_setup_tokens); i++) setSetupInfoFromTokenInfo(setup_file_hash, system_setup_tokens, i); - setup.system = syi; - // internal setup - sxi = setup.internal; - for (i = 0; i < NUM_INTERNAL_SETUP_TOKENS; i++) + for (i = 0; i < ARRAY_SIZE(internal_setup_tokens); i++) setSetupInfoFromTokenInfo(setup_file_hash, internal_setup_tokens, i); - setup.internal = sxi; - // debug setup - sdi = setup.debug; - for (i = 0; i < NUM_DEBUG_SETUP_TOKENS; i++) + for (i = 0; i < ARRAY_SIZE(debug_setup_tokens); i++) setSetupInfoFromTokenInfo(setup_file_hash, debug_setup_tokens, i); - setup.debug = sdi; - // options setup - soi = setup.options; - for (i = 0; i < NUM_OPTIONS_SETUP_TOKENS; i++) + for (i = 0; i < ARRAY_SIZE(options_setup_tokens); i++) setSetupInfoFromTokenInfo(setup_file_hash, options_setup_tokens, i); - setup.options = soi; setHideRelatedSetupEntries(); } @@ -9275,13 +9670,10 @@ static void decodeSetupFileHash_AutoSetup(SetupFileHash *setup_file_hash) if (!setup_file_hash) return; - // auto setup - sasi = setup.auto_setup; - for (i = 0; i < NUM_AUTO_SETUP_TOKENS; i++) + for (i = 0; i < ARRAY_SIZE(auto_setup_tokens); i++) setSetupInfo(auto_setup_tokens, i, getHashEntry(setup_file_hash, auto_setup_tokens[i].text)); - setup.auto_setup = sasi; } static void decodeSetupFileHash_EditorCascade(SetupFileHash *setup_file_hash) @@ -9291,13 +9683,47 @@ static void decodeSetupFileHash_EditorCascade(SetupFileHash *setup_file_hash) if (!setup_file_hash) return; - // editor cascade setup - seci = setup.editor_cascade; - for (i = 0; i < NUM_EDITOR_CASCADE_SETUP_TOKENS; i++) + for (i = 0; i < ARRAY_SIZE(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 LoadUserNames(void) +{ + int last_user_nr = user.nr; + int i; + + if (global.user_names != NULL) + { + for (i = 0; i < MAX_PLAYER_NAMES; i++) + checked_free(global.user_names[i]); + + checked_free(global.user_names); + } + + global.user_names = checked_calloc(MAX_PLAYER_NAMES * sizeof(char *)); + + for (i = 0; i < MAX_PLAYER_NAMES; i++) + { + user.nr = i; + + SetupFileHash *setup_file_hash = loadSetupFileHash(getSetupFilename()); + + if (setup_file_hash) + { + char *player_name = getHashEntry(setup_file_hash, "player_name"); + + global.user_names[i] = getFixedUserName(player_name); + + freeSetupFileHash(setup_file_hash); + } + + if (global.user_names[i] == NULL) + global.user_names[i] = getStringCopy(getDefaultUserName(i)); + } + + user.nr = last_user_nr; } void LoadSetupFromFilename(char *filename) @@ -9312,7 +9738,7 @@ void LoadSetupFromFilename(char *filename) } else { - Error(ERR_DEBUG, "using default setup values"); + Debug("setup", "using default setup values"); } } @@ -9321,7 +9747,7 @@ static void LoadSetup_SpecialPostProcessing(void) char *player_name_new; // needed to work around problems with fixed length strings - player_name_new = get_corrected_login_name(setup.player_name); + player_name_new = getFixedUserName(setup.player_name); free(setup.player_name); setup.player_name = player_name_new; @@ -9429,7 +9855,7 @@ static void LoadSetup_ReadGameControllerMappings(SetupFileHash *mappings_hash, if (!(file = fopen(filename, MODE_READ))) { - Error(ERR_WARN, "cannot read game controller mappings file '%s'", filename); + Warn("cannot read game controller mappings file '%s'", filename); return; } @@ -9457,30 +9883,29 @@ void SaveSetup(void) if (!(file = fopen(filename, MODE_WRITE))) { - Error(ERR_WARN, "cannot write setup file '%s'", filename); + Warn("cannot write setup file '%s'", filename); + return; } fprintFileHeader(file, SETUP_FILENAME); - // global setup - si = setup; - for (i = 0; i < NUM_GLOBAL_SETUP_TOKENS; i++) + for (i = 0; i < ARRAY_SIZE(global_setup_tokens); i++) { // just to make things nicer :) - if (i == SETUP_TOKEN_PLAYER_NAME + 1 || - i == SETUP_TOKEN_GRAPHICS_SET || - i == SETUP_TOKEN_VOLUME_SIMPLE || - i == SETUP_TOKEN_NETWORK_MODE || - i == SETUP_TOKEN_TOUCH_CONTROL_TYPE || - i == SETUP_TOKEN_TOUCH_GRID_XSIZE_0 || - i == SETUP_TOKEN_TOUCH_GRID_XSIZE_1) + if (global_setup_tokens[i].value == &setup.multiple_users || + global_setup_tokens[i].value == &setup.sound || + global_setup_tokens[i].value == &setup.graphics_set || + global_setup_tokens[i].value == &setup.volume_simple || + global_setup_tokens[i].value == &setup.network_mode || + global_setup_tokens[i].value == &setup.touch.control_type || + global_setup_tokens[i].value == &setup.touch.grid_xsize[0] || + global_setup_tokens[i].value == &setup.touch.grid_xsize[1]) fprintf(file, "\n"); fprintf(file, "%s\n", getSetupLine(global_setup_tokens, "", i)); } - // virtual buttons setup for (i = 0; i < 2; i++) { int grid_xsize = setup.touch.grid_xsize[i]; @@ -9509,19 +9934,14 @@ void SaveSetup(void) } } - // editor setup - sei = setup.editor; fprintf(file, "\n"); - for (i = 0; i < NUM_EDITOR_SETUP_TOKENS; i++) + for (i = 0; i < ARRAY_SIZE(editor_setup_tokens); i++) fprintf(file, "%s\n", getSetupLine(editor_setup_tokens, "", i)); - // shortcut setup - ssi = setup.shortcut; fprintf(file, "\n"); - for (i = 0; i < NUM_SHORTCUT_SETUP_TOKENS; i++) + for (i = 0; i < ARRAY_SIZE(shortcut_setup_tokens); i++) fprintf(file, "%s\n", getSetupLine(shortcut_setup_tokens, "", i)); - // player setup for (pnr = 0; pnr < MAX_PLAYERS; pnr++) { char prefix[30]; @@ -9529,30 +9949,25 @@ void SaveSetup(void) sprintf(prefix, "%s%d", TOKEN_STR_PLAYER_PREFIX, pnr + 1); fprintf(file, "\n"); - sii = setup.input[pnr]; - for (i = 0; i < NUM_PLAYER_SETUP_TOKENS; i++) + setup_input = setup.input[pnr]; + for (i = 0; i < ARRAY_SIZE(player_setup_tokens); i++) fprintf(file, "%s\n", getSetupLine(player_setup_tokens, prefix, i)); } - // system setup - syi = setup.system; fprintf(file, "\n"); - for (i = 0; i < NUM_SYSTEM_SETUP_TOKENS; i++) + for (i = 0; i < ARRAY_SIZE(system_setup_tokens); i++) fprintf(file, "%s\n", getSetupLine(system_setup_tokens, "", i)); - // internal setup // (internal setup values not saved to user setup file) - // debug setup - sdi = setup.debug; fprintf(file, "\n"); - for (i = 0; i < NUM_DEBUG_SETUP_TOKENS; i++) - fprintf(file, "%s\n", getSetupLine(debug_setup_tokens, "", i)); + for (i = 0; i < ARRAY_SIZE(debug_setup_tokens); i++) + if (!strPrefix(debug_setup_tokens[i].text, "debug.xsn_") || + setup.debug.xsn_mode != AUTO) + fprintf(file, "%s\n", getSetupLine(debug_setup_tokens, "", i)); - // options setup - soi = setup.options; fprintf(file, "\n"); - for (i = 0; i < NUM_OPTIONS_SETUP_TOKENS; i++) + for (i = 0; i < ARRAY_SIZE(options_setup_tokens); i++) fprintf(file, "%s\n", getSetupLine(options_setup_tokens, "", i)); fclose(file); @@ -9570,15 +9985,16 @@ void SaveSetup_AutoSetup(void) if (!(file = fopen(filename, MODE_WRITE))) { - Error(ERR_WARN, "cannot write auto setup file '%s'", filename); + Warn("cannot write auto setup file '%s'", filename); + free(filename); + return; } fprintFileHeader(file, AUTOSETUP_FILENAME); - sasi = setup.auto_setup; - for (i = 0; i < NUM_AUTO_SETUP_TOKENS; i++) + for (i = 0; i < ARRAY_SIZE(auto_setup_tokens); i++) fprintf(file, "%s\n", getSetupLine(auto_setup_tokens, "", i)); fclose(file); @@ -9598,107 +10014,531 @@ void SaveSetup_EditorCascade(void) if (!(file = fopen(filename, MODE_WRITE))) { - Error(ERR_WARN, "cannot write editor cascade state file '%s'", filename); + Warn("cannot write editor cascade state file '%s'", filename); + free(filename); + return; } fprintFileHeader(file, EDITORCASCADE_FILENAME); - seci = setup.editor_cascade; - for (i = 0; i < NUM_EDITOR_CASCADE_SETUP_TOKENS; i++) - fprintf(file, "%s\n", getSetupLine(editor_cascade_setup_tokens, "", i)); + for (i = 0; i < ARRAY_SIZE(editor_cascade_setup_tokens); i++) + fprintf(file, "%s\n", getSetupLine(editor_cascade_setup_tokens, "", i)); + + fclose(file); + + SetFilePermissions(filename, PERMS_PRIVATE); + + free(filename); +} + +static void SaveSetup_WriteGameControllerMappings(SetupFileHash *mappings_hash, + char *filename) +{ + FILE *file; + + if (!(file = fopen(filename, MODE_WRITE))) + { + Warn("cannot write game controller mappings file '%s'", filename); + + return; + } + + BEGIN_HASH_ITERATION(mappings_hash, itr) + { + fprintf(file, "%s\n", HASH_ITERATION_VALUE(itr)); + } + END_HASH_ITERATION(mappings_hash, itr) + + fclose(file); +} + +void SaveSetup_AddGameControllerMapping(char *mapping) +{ + char *filename = getPath2(getSetupDir(), GAMECONTROLLER_BASENAME); + SetupFileHash *mappings_hash = newSetupFileHash(); + + InitUserDataDirectory(); + + // load existing personal game controller mappings + LoadSetup_ReadGameControllerMappings(mappings_hash, filename); + + // add new mapping to personal game controller mappings + addGameControllerMappingToHash(mappings_hash, mapping); + + // save updated personal game controller mappings + SaveSetup_WriteGameControllerMappings(mappings_hash, filename); + + freeSetupFileHash(mappings_hash); + free(filename); +} + +void LoadCustomElementDescriptions(void) +{ + char *filename = getCustomArtworkConfigFilename(ARTWORK_TYPE_GRAPHICS); + SetupFileHash *setup_file_hash; + int i; + + for (i = 0; i < NUM_FILE_ELEMENTS; i++) + { + if (element_info[i].custom_description != NULL) + { + free(element_info[i].custom_description); + element_info[i].custom_description = NULL; + } + } + + if ((setup_file_hash = loadSetupFileHash(filename)) == NULL) + return; + + for (i = 0; i < NUM_FILE_ELEMENTS; i++) + { + char *token = getStringCat2(element_info[i].token_name, ".name"); + char *value = getHashEntry(setup_file_hash, token); + + if (value != NULL) + element_info[i].custom_description = getStringCopy(value); + + free(token); + } + + freeSetupFileHash(setup_file_hash); +} + +static int getElementFromToken(char *token) +{ + char *value = getHashEntry(element_token_hash, token); + + if (value != NULL) + return atoi(value); + + Warn("unknown element token '%s'", token); + + return EL_UNDEFINED; +} + +void FreeGlobalAnimEventInfo(void) +{ + struct GlobalAnimEventInfo *gaei = &global_anim_event_info; + + if (gaei->event_list == NULL) + return; + + int i; + + for (i = 0; i < gaei->num_event_lists; i++) + { + checked_free(gaei->event_list[i]->event_value); + checked_free(gaei->event_list[i]); + } + + checked_free(gaei->event_list); + + gaei->event_list = NULL; + gaei->num_event_lists = 0; +} + +static int AddGlobalAnimEventList(void) +{ + struct GlobalAnimEventInfo *gaei = &global_anim_event_info; + int list_pos = gaei->num_event_lists++; + + gaei->event_list = checked_realloc(gaei->event_list, gaei->num_event_lists * + sizeof(struct GlobalAnimEventListInfo *)); + + gaei->event_list[list_pos] = + checked_calloc(sizeof(struct GlobalAnimEventListInfo)); + + struct GlobalAnimEventListInfo *gaeli = gaei->event_list[list_pos]; + + gaeli->event_value = NULL; + gaeli->num_event_values = 0; + + return list_pos; +} + +static int AddGlobalAnimEventValue(int list_pos, int event_value) +{ + // do not add empty global animation events + if (event_value == ANIM_EVENT_NONE) + return list_pos; + + // if list position is undefined, create new list + if (list_pos == ANIM_EVENT_UNDEFINED) + list_pos = AddGlobalAnimEventList(); + + struct GlobalAnimEventInfo *gaei = &global_anim_event_info; + struct GlobalAnimEventListInfo *gaeli = gaei->event_list[list_pos]; + int value_pos = gaeli->num_event_values++; + + gaeli->event_value = checked_realloc(gaeli->event_value, + gaeli->num_event_values * sizeof(int *)); + + gaeli->event_value[value_pos] = event_value; + + return list_pos; +} + +int GetGlobalAnimEventValue(int list_pos, int value_pos) +{ + if (list_pos == ANIM_EVENT_UNDEFINED) + return ANIM_EVENT_NONE; + + struct GlobalAnimEventInfo *gaei = &global_anim_event_info; + struct GlobalAnimEventListInfo *gaeli = gaei->event_list[list_pos]; + + return gaeli->event_value[value_pos]; +} + +int GetGlobalAnimEventValueCount(int list_pos) +{ + if (list_pos == ANIM_EVENT_UNDEFINED) + return 0; + + struct GlobalAnimEventInfo *gaei = &global_anim_event_info; + struct GlobalAnimEventListInfo *gaeli = gaei->event_list[list_pos]; + + return gaeli->num_event_values; +} + +// This function checks if a string of the format "string1, string2, ..." +// exactly contains a string . + +static boolean string_has_parameter(char *s, char *s_contained) +{ + char *substring; + + if (s == NULL || s_contained == NULL) + return FALSE; + + if (strlen(s_contained) > strlen(s)) + return FALSE; + + if (strncmp(s, s_contained, strlen(s_contained)) == 0) + { + char next_char = s[strlen(s_contained)]; + + // check if next character is delimiter or whitespace + return (next_char == ',' || next_char == '\0' || + next_char == ' ' || next_char == '\t' ? TRUE : FALSE); + } + + // check if string contains another parameter string after a comma + substring = strchr(s, ','); + if (substring == NULL) // string does not contain a comma + return FALSE; + + // advance string pointer to next character after the comma + substring++; + + // skip potential whitespaces after the comma + while (*substring == ' ' || *substring == '\t') + substring++; + + return string_has_parameter(substring, s_contained); +} + +static int get_anim_parameter_value(char *s) +{ + int event_value[] = + { + ANIM_EVENT_CLICK, + ANIM_EVENT_INIT, + ANIM_EVENT_START, + ANIM_EVENT_END, + ANIM_EVENT_POST + }; + char *pattern_1[] = + { + "click:anim_", + "init:anim_", + "start:anim_", + "end:anim_", + "post:anim_" + }; + char *pattern_2 = ".part_"; + char *matching_char = NULL; + char *s_ptr = s; + int pattern_1_len = 0; + int result = ANIM_EVENT_NONE; + int i; + + for (i = 0; i < ARRAY_SIZE(event_value); i++) + { + matching_char = strstr(s_ptr, pattern_1[i]); + pattern_1_len = strlen(pattern_1[i]); + result = event_value[i]; + + if (matching_char != NULL) + break; + } + + if (matching_char == NULL) + return ANIM_EVENT_NONE; + + s_ptr = matching_char + pattern_1_len; + + // check for main animation number ("anim_X" or "anim_XX") + if (*s_ptr >= '0' && *s_ptr <= '9') + { + 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; + + 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') + { + int gic_part_nr = (*s_ptr++ - '0'); + + 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 + { + // invalid animation part number specified - fclose(file); + return ANIM_EVENT_NONE; + } + } - SetFilePermissions(filename, PERMS_PRIVATE); + // discard result if next character is neither delimiter nor whitespace + if (!(*s_ptr == ',' || *s_ptr == '\0' || + *s_ptr == ' ' || *s_ptr == '\t')) + return ANIM_EVENT_NONE; - free(filename); + return result; } -static void SaveSetup_WriteGameControllerMappings(SetupFileHash *mappings_hash, - char *filename) +static int get_anim_parameter_values(char *s) { - FILE *file; + int list_pos = ANIM_EVENT_UNDEFINED; + int event_value = ANIM_EVENT_DEFAULT; - if (!(file = fopen(filename, MODE_WRITE))) - { - Error(ERR_WARN, "cannot write game controller mappings file '%s'",filename); + if (string_has_parameter(s, "any")) + event_value |= ANIM_EVENT_ANY; - return; - } + if (string_has_parameter(s, "click:self") || + string_has_parameter(s, "click") || + string_has_parameter(s, "self")) + event_value |= ANIM_EVENT_SELF; - BEGIN_HASH_ITERATION(mappings_hash, itr) + if (string_has_parameter(s, "unclick:any")) + event_value |= ANIM_EVENT_UNCLICK_ANY; + + // if animation event found, add it to global animation event list + if (event_value != ANIM_EVENT_NONE) + list_pos = AddGlobalAnimEventValue(list_pos, event_value); + + while (s != NULL) { - fprintf(file, "%s\n", HASH_ITERATION_VALUE(itr)); + // add optional "click:anim_X" or "click:anim_X.part_X" parameter + event_value = get_anim_parameter_value(s); + + // if animation event found, add it to global animation event list + if (event_value != ANIM_EVENT_NONE) + list_pos = AddGlobalAnimEventValue(list_pos, event_value); + + // continue with next part of the string, starting with next comma + s = strchr(s + 1, ','); } - END_HASH_ITERATION(mappings_hash, itr) - fclose(file); + return list_pos; } -void SaveSetup_AddGameControllerMapping(char *mapping) +static int get_anim_action_parameter_value(char *token) { - char *filename = getPath2(getSetupDir(), GAMECONTROLLER_BASENAME); - SetupFileHash *mappings_hash = newSetupFileHash(); + // check most common default case first to massively speed things up + if (strEqual(token, ARG_UNDEFINED)) + return ANIM_EVENT_ACTION_NONE; - InitUserDataDirectory(); + int result = getImageIDFromToken(token); - // load existing personal game controller mappings - LoadSetup_ReadGameControllerMappings(mappings_hash, filename); + if (result == -1) + { + char *gfx_token = getStringCat2("gfx.", token); - // add new mapping to personal game controller mappings - addGameControllerMappingToHash(mappings_hash, mapping); + result = getImageIDFromToken(gfx_token); - // save updated personal game controller mappings - SaveSetup_WriteGameControllerMappings(mappings_hash, filename); + checked_free(gfx_token); + } - freeSetupFileHash(mappings_hash); - free(filename); + if (result == -1) + { + Key key = getKeyFromX11KeyName(token); + + if (key != KSYM_UNDEFINED) + result = -(int)key; + } + + if (result == -1) + result = ANIM_EVENT_ACTION_NONE; + + return result; } -void LoadCustomElementDescriptions(void) +int get_parameter_value(char *value_raw, char *suffix, int type) { - char *filename = getCustomArtworkConfigFilename(ARTWORK_TYPE_GRAPHICS); - SetupFileHash *setup_file_hash; - int i; + char *value = getStringToLower(value_raw); + int result = 0; // probably a save default value - for (i = 0; i < NUM_FILE_ELEMENTS; i++) + if (strEqual(suffix, ".direction")) { - if (element_info[i].custom_description != NULL) - { - free(element_info[i].custom_description); - element_info[i].custom_description = NULL; - } + result = (strEqual(value, "left") ? MV_LEFT : + strEqual(value, "right") ? MV_RIGHT : + strEqual(value, "up") ? MV_UP : + strEqual(value, "down") ? MV_DOWN : MV_NONE); + } + else if (strEqual(suffix, ".position")) + { + result = (strEqual(value, "left") ? POS_LEFT : + strEqual(value, "right") ? POS_RIGHT : + strEqual(value, "top") ? POS_TOP : + strEqual(value, "upper") ? POS_UPPER : + strEqual(value, "middle") ? POS_MIDDLE : + strEqual(value, "lower") ? POS_LOWER : + strEqual(value, "bottom") ? POS_BOTTOM : + strEqual(value, "any") ? POS_ANY : + strEqual(value, "last") ? POS_LAST : POS_UNDEFINED); + } + else if (strEqual(suffix, ".align")) + { + result = (strEqual(value, "left") ? ALIGN_LEFT : + strEqual(value, "right") ? ALIGN_RIGHT : + strEqual(value, "center") ? ALIGN_CENTER : + strEqual(value, "middle") ? ALIGN_CENTER : ALIGN_DEFAULT); + } + else if (strEqual(suffix, ".valign")) + { + result = (strEqual(value, "top") ? VALIGN_TOP : + strEqual(value, "bottom") ? VALIGN_BOTTOM : + strEqual(value, "middle") ? VALIGN_MIDDLE : + strEqual(value, "center") ? VALIGN_MIDDLE : VALIGN_DEFAULT); } + else if (strEqual(suffix, ".anim_mode")) + { + result = (string_has_parameter(value, "none") ? ANIM_NONE : + string_has_parameter(value, "loop") ? ANIM_LOOP : + string_has_parameter(value, "linear") ? ANIM_LINEAR : + string_has_parameter(value, "pingpong") ? ANIM_PINGPONG : + string_has_parameter(value, "pingpong2") ? ANIM_PINGPONG2 : + string_has_parameter(value, "random") ? ANIM_RANDOM : + string_has_parameter(value, "ce_value") ? ANIM_CE_VALUE : + string_has_parameter(value, "ce_score") ? ANIM_CE_SCORE : + string_has_parameter(value, "ce_delay") ? ANIM_CE_DELAY : + string_has_parameter(value, "horizontal") ? ANIM_HORIZONTAL : + string_has_parameter(value, "vertical") ? ANIM_VERTICAL : + string_has_parameter(value, "centered") ? ANIM_CENTERED : + string_has_parameter(value, "all") ? ANIM_ALL : + ANIM_DEFAULT); - if ((setup_file_hash = loadSetupFileHash(filename)) == NULL) - return; + if (string_has_parameter(value, "once")) + result |= ANIM_ONCE; - for (i = 0; i < NUM_FILE_ELEMENTS; i++) - { - char *token = getStringCat2(element_info[i].token_name, ".name"); - char *value = getHashEntry(setup_file_hash, token); + if (string_has_parameter(value, "reverse")) + result |= ANIM_REVERSE; - if (value != NULL) - element_info[i].custom_description = getStringCopy(value); + if (string_has_parameter(value, "opaque_player")) + result |= ANIM_OPAQUE_PLAYER; - free(token); + if (string_has_parameter(value, "static_panel")) + result |= ANIM_STATIC_PANEL; + } + else if (strEqual(suffix, ".init_event") || + strEqual(suffix, ".anim_event")) + { + result = get_anim_parameter_values(value); + } + else if (strEqual(suffix, ".init_delay_action") || + strEqual(suffix, ".anim_delay_action") || + strEqual(suffix, ".post_delay_action") || + strEqual(suffix, ".init_event_action") || + strEqual(suffix, ".anim_event_action")) + { + result = get_anim_action_parameter_value(value_raw); + } + else if (strEqual(suffix, ".class")) + { + result = (strEqual(value, ARG_UNDEFINED) ? ARG_UNDEFINED_VALUE : + get_hash_from_key(value)); } + else if (strEqual(suffix, ".style")) + { + result = STYLE_DEFAULT; - freeSetupFileHash(setup_file_hash); -} + if (string_has_parameter(value, "accurate_borders")) + result |= STYLE_ACCURATE_BORDERS; -static int getElementFromToken(char *token) -{ - char *value = getHashEntry(element_token_hash, token); + if (string_has_parameter(value, "inner_corners")) + result |= STYLE_INNER_CORNERS; - if (value != NULL) - return atoi(value); + if (string_has_parameter(value, "reverse")) + result |= STYLE_REVERSE; - Error(ERR_WARN, "unknown element token '%s'", token); + if (string_has_parameter(value, "leftmost_position")) + result |= STYLE_LEFTMOST_POSITION; - return EL_UNDEFINED; + if (string_has_parameter(value, "block_clicks")) + result |= STYLE_BLOCK; + + if (string_has_parameter(value, "passthrough_clicks")) + result |= STYLE_PASSTHROUGH; + + if (string_has_parameter(value, "multiple_actions")) + result |= STYLE_MULTIPLE_ACTIONS; + } + else if (strEqual(suffix, ".fade_mode")) + { + result = (string_has_parameter(value, "none") ? FADE_MODE_NONE : + string_has_parameter(value, "fade") ? FADE_MODE_FADE : + string_has_parameter(value, "crossfade") ? FADE_MODE_CROSSFADE : + string_has_parameter(value, "melt") ? FADE_MODE_MELT : + string_has_parameter(value, "curtain") ? FADE_MODE_CURTAIN : + FADE_MODE_DEFAULT); + } + else if (strEqual(suffix, ".auto_delay_unit")) + { + result = (string_has_parameter(value, "ms") ? AUTO_DELAY_UNIT_MS : + string_has_parameter(value, "frames") ? AUTO_DELAY_UNIT_FRAMES : + AUTO_DELAY_UNIT_DEFAULT); + } + else if (strPrefix(suffix, ".font")) // (may also be ".font_xyz") + { + result = gfx.get_font_from_token_function(value); + } + else // generic parameter of type integer or boolean + { + result = (strEqual(value, ARG_UNDEFINED) ? ARG_UNDEFINED_VALUE : + type == TYPE_INTEGER ? get_integer_from_string(value) : + type == TYPE_BOOLEAN ? get_boolean_from_string(value) : + ARG_UNDEFINED_VALUE); + } + + free(value); + + return result; } static int get_token_parameter_value(char *token, char *value_raw) @@ -9750,10 +10590,14 @@ static void InitMenuDesignSettings_SpecialPreProcessing(void) title_initial_first_default.post_delay; titlescreen_initial_first_default.auto_delay = title_initial_first_default.auto_delay; + titlescreen_initial_first_default.auto_delay_unit = + title_initial_first_default.auto_delay_unit; titlescreen_first_default.fade_mode = title_first_default.fade_mode; titlescreen_first_default.fade_delay = title_first_default.fade_delay; titlescreen_first_default.post_delay = title_first_default.post_delay; titlescreen_first_default.auto_delay = title_first_default.auto_delay; + titlescreen_first_default.auto_delay_unit = + title_first_default.auto_delay_unit; titlemessage_initial_first_default.fade_mode = title_initial_first_default.fade_mode; titlemessage_initial_first_default.fade_delay = @@ -9762,27 +10606,36 @@ static void InitMenuDesignSettings_SpecialPreProcessing(void) title_initial_first_default.post_delay; titlemessage_initial_first_default.auto_delay = title_initial_first_default.auto_delay; + titlemessage_initial_first_default.auto_delay_unit = + title_initial_first_default.auto_delay_unit; titlemessage_first_default.fade_mode = title_first_default.fade_mode; titlemessage_first_default.fade_delay = title_first_default.fade_delay; titlemessage_first_default.post_delay = title_first_default.post_delay; titlemessage_first_default.auto_delay = title_first_default.auto_delay; + titlemessage_first_default.auto_delay_unit = + title_first_default.auto_delay_unit; titlescreen_initial_default.fade_mode = title_initial_default.fade_mode; titlescreen_initial_default.fade_delay = title_initial_default.fade_delay; titlescreen_initial_default.post_delay = title_initial_default.post_delay; titlescreen_initial_default.auto_delay = title_initial_default.auto_delay; + titlescreen_initial_default.auto_delay_unit = + title_initial_default.auto_delay_unit; titlescreen_default.fade_mode = title_default.fade_mode; titlescreen_default.fade_delay = title_default.fade_delay; titlescreen_default.post_delay = title_default.post_delay; titlescreen_default.auto_delay = title_default.auto_delay; + titlescreen_default.auto_delay_unit = title_default.auto_delay_unit; titlemessage_initial_default.fade_mode = title_initial_default.fade_mode; titlemessage_initial_default.fade_delay = title_initial_default.fade_delay; titlemessage_initial_default.post_delay = title_initial_default.post_delay; - titlemessage_initial_default.auto_delay = title_initial_default.auto_delay; + titlemessage_initial_default.auto_delay_unit = + title_initial_default.auto_delay_unit; titlemessage_default.fade_mode = title_default.fade_mode; titlemessage_default.fade_delay = title_default.fade_delay; titlemessage_default.post_delay = title_default.post_delay; titlemessage_default.auto_delay = title_default.auto_delay; + titlemessage_default.auto_delay_unit = title_default.auto_delay_unit; // special case: initialize "ARG_DEFAULT" values in static default config // (e.g., init "titlemessage_1.fade_mode" from "[titlemessage].fade_mode") @@ -9842,7 +10695,7 @@ static void InitMenuDesignSettings_SpecialPostProcessing(void) { NULL, NULL } }; - int i; + int i, j; // special case: initialize later added SETUP list size from LEVELS value if (menu.list_size[GAME_MODE_SETUP] == -1) @@ -9853,6 +10706,237 @@ static void InitMenuDesignSettings_SpecialPostProcessing(void) if ((*game_buttons_xy[i].dst).x == -1 && (*game_buttons_xy[i].dst).y == -1) *game_buttons_xy[i].dst = *game_buttons_xy[i].src; + + // -------------------------------------------------------------------------- + // dynamic viewports (including playfield margins, borders and alignments) + // -------------------------------------------------------------------------- + + // dynamic viewports currently only supported for landscape mode + int display_width = MAX(video.display_width, video.display_height); + int display_height = MIN(video.display_width, video.display_height); + + for (i = 0; i < NUM_SPECIAL_GFX_ARGS; i++) + { + struct RectWithBorder *vp_window = &viewport.window[i]; + struct RectWithBorder *vp_playfield = &viewport.playfield[i]; + struct RectWithBorder *vp_door_1 = &viewport.door_1[i]; + struct RectWithBorder *vp_door_2 = &viewport.door_2[i]; + boolean dynamic_window_width = (vp_window->min_width != -1); + boolean dynamic_window_height = (vp_window->min_height != -1); + boolean dynamic_playfield_width = (vp_playfield->min_width != -1); + boolean dynamic_playfield_height = (vp_playfield->min_height != -1); + + // adjust window size if min/max width/height is specified + + if (vp_window->min_width != -1) + { + int window_width = display_width; + + // when using static window height, use aspect ratio of display + if (vp_window->min_height == -1) + window_width = vp_window->height * display_width / display_height; + + vp_window->width = MAX(vp_window->min_width, window_width); + } + + if (vp_window->min_height != -1) + { + int window_height = display_height; + + // when using static window width, use aspect ratio of display + if (vp_window->min_width == -1) + window_height = vp_window->width * display_height / display_width; + + vp_window->height = MAX(vp_window->min_height, window_height); + } + + if (vp_window->max_width != -1) + vp_window->width = MIN(vp_window->width, vp_window->max_width); + + if (vp_window->max_height != -1) + vp_window->height = MIN(vp_window->height, vp_window->max_height); + + int playfield_width = vp_window->width; + int playfield_height = vp_window->height; + + // adjust playfield size and position according to specified margins + + playfield_width -= vp_playfield->margin_left; + playfield_width -= vp_playfield->margin_right; + + playfield_height -= vp_playfield->margin_top; + playfield_height -= vp_playfield->margin_bottom; + + // adjust playfield size if min/max width/height is specified + + if (vp_playfield->min_width != -1) + vp_playfield->width = MAX(vp_playfield->min_width, playfield_width); + + if (vp_playfield->min_height != -1) + vp_playfield->height = MAX(vp_playfield->min_height, playfield_height); + + if (vp_playfield->max_width != -1) + vp_playfield->width = MIN(vp_playfield->width, vp_playfield->max_width); + + if (vp_playfield->max_height != -1) + vp_playfield->height = MIN(vp_playfield->height,vp_playfield->max_height); + + // adjust playfield position according to specified alignment + + if (vp_playfield->align == ALIGN_LEFT || vp_playfield->x > 0) + vp_playfield->x = ALIGNED_VP_XPOS(vp_playfield); + else if (vp_playfield->align == ALIGN_CENTER) + vp_playfield->x = playfield_width / 2 - vp_playfield->width / 2; + else if (vp_playfield->align == ALIGN_RIGHT) + vp_playfield->x += playfield_width - vp_playfield->width; + + if (vp_playfield->valign == VALIGN_TOP || vp_playfield->y > 0) + vp_playfield->y = ALIGNED_VP_YPOS(vp_playfield); + else if (vp_playfield->valign == VALIGN_MIDDLE) + vp_playfield->y = playfield_height / 2 - vp_playfield->height / 2; + else if (vp_playfield->valign == VALIGN_BOTTOM) + vp_playfield->y += playfield_height - vp_playfield->height; + + vp_playfield->x += vp_playfield->margin_left; + vp_playfield->y += vp_playfield->margin_top; + + // adjust individual playfield borders if only default border is specified + + if (vp_playfield->border_left == -1) + vp_playfield->border_left = vp_playfield->border_size; + if (vp_playfield->border_right == -1) + vp_playfield->border_right = vp_playfield->border_size; + if (vp_playfield->border_top == -1) + vp_playfield->border_top = vp_playfield->border_size; + if (vp_playfield->border_bottom == -1) + vp_playfield->border_bottom = vp_playfield->border_size; + + // set dynamic playfield borders if borders are specified as undefined + // (but only if window size was dynamic and playfield size was static) + + if (dynamic_window_width && !dynamic_playfield_width) + { + if (vp_playfield->border_left == -1) + { + vp_playfield->border_left = (vp_playfield->x - + vp_playfield->margin_left); + vp_playfield->x -= vp_playfield->border_left; + vp_playfield->width += vp_playfield->border_left; + } + + if (vp_playfield->border_right == -1) + { + vp_playfield->border_right = (vp_window->width - + vp_playfield->x - + vp_playfield->width - + vp_playfield->margin_right); + vp_playfield->width += vp_playfield->border_right; + } + } + + if (dynamic_window_height && !dynamic_playfield_height) + { + if (vp_playfield->border_top == -1) + { + vp_playfield->border_top = (vp_playfield->y - + vp_playfield->margin_top); + vp_playfield->y -= vp_playfield->border_top; + vp_playfield->height += vp_playfield->border_top; + } + + if (vp_playfield->border_bottom == -1) + { + vp_playfield->border_bottom = (vp_window->height - + vp_playfield->y - + vp_playfield->height - + vp_playfield->margin_bottom); + vp_playfield->height += vp_playfield->border_bottom; + } + } + + // adjust playfield size to be a multiple of a defined alignment tile size + + int align_size = vp_playfield->align_size; + int playfield_xtiles = vp_playfield->width / align_size; + int playfield_ytiles = vp_playfield->height / align_size; + int playfield_width_corrected = playfield_xtiles * align_size; + int playfield_height_corrected = playfield_ytiles * align_size; + boolean is_playfield_mode = (i == GFX_SPECIAL_ARG_PLAYING || + i == GFX_SPECIAL_ARG_EDITOR); + + if (is_playfield_mode && + dynamic_playfield_width && + vp_playfield->width != playfield_width_corrected) + { + int playfield_xdiff = vp_playfield->width - playfield_width_corrected; + + vp_playfield->width = playfield_width_corrected; + + if (vp_playfield->align == ALIGN_LEFT) + { + vp_playfield->border_left += playfield_xdiff; + } + else if (vp_playfield->align == ALIGN_RIGHT) + { + vp_playfield->border_right += playfield_xdiff; + } + else if (vp_playfield->align == ALIGN_CENTER) + { + int border_left_diff = playfield_xdiff / 2; + int border_right_diff = playfield_xdiff - border_left_diff; + + vp_playfield->border_left += border_left_diff; + vp_playfield->border_right += border_right_diff; + } + } + + if (is_playfield_mode && + dynamic_playfield_height && + vp_playfield->height != playfield_height_corrected) + { + int playfield_ydiff = vp_playfield->height - playfield_height_corrected; + + vp_playfield->height = playfield_height_corrected; + + if (vp_playfield->valign == VALIGN_TOP) + { + vp_playfield->border_top += playfield_ydiff; + } + else if (vp_playfield->align == VALIGN_BOTTOM) + { + vp_playfield->border_right += playfield_ydiff; + } + else if (vp_playfield->align == VALIGN_MIDDLE) + { + int border_top_diff = playfield_ydiff / 2; + int border_bottom_diff = playfield_ydiff - border_top_diff; + + vp_playfield->border_top += border_top_diff; + vp_playfield->border_bottom += border_bottom_diff; + } + } + + // adjust door positions according to specified alignment + + for (j = 0; j < 2; j++) + { + struct RectWithBorder *vp_door = (j == 0 ? vp_door_1 : vp_door_2); + + if (vp_door->align == ALIGN_LEFT || vp_door->x > 0) + vp_door->x = ALIGNED_VP_XPOS(vp_door); + else if (vp_door->align == ALIGN_CENTER) + vp_door->x = vp_window->width / 2 - vp_door->width / 2; + else if (vp_door->align == ALIGN_RIGHT) + vp_door->x += vp_window->width - vp_door->width; + + if (vp_door->valign == VALIGN_TOP || vp_door->y > 0) + vp_door->y = ALIGNED_VP_YPOS(vp_door); + else if (vp_door->valign == VALIGN_MIDDLE) + vp_door->y = vp_window->height / 2 - vp_door->height / 2; + else if (vp_door->valign == VALIGN_BOTTOM) + vp_door->y += vp_window->height - vp_door->height; + } + } } static void InitMenuDesignSettings_SpecialPostProcessing_AfterGraphics(void) @@ -9894,6 +10978,40 @@ static void InitMenuDesignSettings_SpecialPostProcessing_AfterGraphics(void) *editor_buttons_xy[i].dst = *editor_buttons_xy[i].src; } } + + // adjust editor palette rows and columns if specified to be dynamic + + if (editor.palette.cols == -1) + { + int vp_width = viewport.playfield[GFX_SPECIAL_ARG_EDITOR].width; + int bt_width = graphic_info[IMG_EDITOR_PALETTE_BUTTON].width; + int sc_width = graphic_info[IMG_EDITOR_PALETTE_SCROLLBAR].width; + + editor.palette.cols = (vp_width - sc_width) / bt_width; + + if (editor.palette.x == -1) + { + int palette_width = editor.palette.cols * bt_width + sc_width; + + editor.palette.x = (vp_width - palette_width) / 2; + } + } + + if (editor.palette.rows == -1) + { + int vp_height = viewport.playfield[GFX_SPECIAL_ARG_EDITOR].height; + int bt_height = graphic_info[IMG_EDITOR_PALETTE_BUTTON].height; + int tx_height = getFontHeight(FONT_TEXT_2); + + editor.palette.rows = (vp_height - tx_height) / bt_height; + + if (editor.palette.y == -1) + { + int palette_height = editor.palette.rows * bt_height + tx_height; + + editor.palette.y = (vp_height - palette_height) / 2; + } + } } static void LoadMenuDesignSettingsFromFilename(char *filename) @@ -9906,6 +11024,7 @@ static void LoadMenuDesignSettingsFromFilename(char *filename) { TYPE_INTEGER, &tfi.fade_delay, ".fade_delay" }, { TYPE_INTEGER, &tfi.post_delay, ".post_delay" }, { TYPE_INTEGER, &tfi.auto_delay, ".auto_delay" }, + { TYPE_INTEGER, &tfi.auto_delay_unit, ".auto_delay_unit" }, { -1, NULL, NULL } }; @@ -9928,6 +11047,7 @@ static void LoadMenuDesignSettingsFromFilename(char *filename) { TYPE_INTEGER, &tmi.fade_delay, ".fade_delay" }, { TYPE_INTEGER, &tmi.post_delay, ".post_delay" }, { TYPE_INTEGER, &tmi.auto_delay, ".auto_delay" }, + { TYPE_INTEGER, &tmi.auto_delay_unit, ".auto_delay_unit" }, { -1, NULL, NULL } }; @@ -10003,36 +11123,41 @@ static void LoadMenuDesignSettingsFromFilename(char *filename) // (e.g., init "menu.draw_xoffset.INFO" from "menu.draw_xoffset") for (i = 0; i < NUM_SPECIAL_GFX_ARGS; i++) { - char *value_1 = getHashEntry(setup_file_hash, "menu.draw_xoffset"); - char *value_2 = getHashEntry(setup_file_hash, "menu.draw_yoffset"); - char *value_3 = getHashEntry(setup_file_hash, "menu.list_size"); + struct TokenIntPtrInfo menu_config[] = + { + { "menu.draw_xoffset", &menu.draw_xoffset[i] }, + { "menu.draw_yoffset", &menu.draw_yoffset[i] }, + { "menu.list_size", &menu.list_size[i] } + }; + + for (j = 0; j < ARRAY_SIZE(menu_config); j++) + { + char *token = menu_config[j].token; + char *value = getHashEntry(setup_file_hash, token); - if (value_1 != NULL) - menu.draw_xoffset[i] = get_integer_from_string(value_1); - if (value_2 != NULL) - menu.draw_yoffset[i] = get_integer_from_string(value_2); - if (value_3 != NULL) - menu.list_size[i] = get_integer_from_string(value_3); + if (value != NULL) + *menu_config[j].value = get_integer_from_string(value); + } } // special case: initialize with default values that may be overwritten // (eg, init "menu.draw_xoffset.INFO[XXX]" from "menu.draw_xoffset.INFO") for (i = 0; i < NUM_SPECIAL_GFX_INFO_ARGS; i++) { - char *value_1 = getHashEntry(setup_file_hash, "menu.draw_xoffset.INFO"); - char *value_2 = getHashEntry(setup_file_hash, "menu.draw_yoffset.INFO"); - - if (value_1 != NULL) - menu.draw_xoffset_info[i] = get_integer_from_string(value_1); - if (value_2 != NULL) - menu.draw_yoffset_info[i] = get_integer_from_string(value_2); + struct TokenIntPtrInfo menu_config[] = + { + { "menu.draw_xoffset.INFO", &menu.draw_xoffset_info[i] }, + { "menu.draw_yoffset.INFO", &menu.draw_yoffset_info[i] }, + { "menu.list_size.INFO", &menu.list_size_info[i] } + }; - if (i == GFX_SPECIAL_ARG_INFO_ELEMENTS) + for (j = 0; j < ARRAY_SIZE(menu_config); j++) { - char *value_1 = getHashEntry(setup_file_hash, "menu.list_size.INFO"); + char *token = menu_config[j].token; + char *value = getHashEntry(setup_file_hash, token); - if (value_1 != NULL) - menu.list_size_info[i] = get_integer_from_string(value_1); + if (value != NULL) + *menu_config[j].value = get_integer_from_string(value); } } @@ -10040,179 +11165,131 @@ static void LoadMenuDesignSettingsFromFilename(char *filename) // (eg, init "menu.draw_xoffset.SETUP[XXX]" from "menu.draw_xoffset.SETUP") for (i = 0; i < NUM_SPECIAL_GFX_SETUP_ARGS; i++) { - char *value_1 = getHashEntry(setup_file_hash, "menu.draw_xoffset.SETUP"); - char *value_2 = getHashEntry(setup_file_hash, "menu.draw_yoffset.SETUP"); + struct TokenIntPtrInfo menu_config[] = + { + { "menu.draw_xoffset.SETUP", &menu.draw_xoffset_setup[i] }, + { "menu.draw_yoffset.SETUP", &menu.draw_yoffset_setup[i] } + }; + + for (j = 0; j < ARRAY_SIZE(menu_config); j++) + { + char *token = menu_config[j].token; + char *value = getHashEntry(setup_file_hash, token); - if (value_1 != NULL) - menu.draw_xoffset_setup[i] = get_integer_from_string(value_1); - if (value_2 != NULL) - menu.draw_yoffset_setup[i] = get_integer_from_string(value_2); + if (value != NULL) + *menu_config[j].value = get_integer_from_string(value); + } } // special case: initialize with default values that may be overwritten // (eg, init "menu.line_spacing.INFO[XXX]" from "menu.line_spacing.INFO") for (i = 0; i < NUM_SPECIAL_GFX_INFO_ARGS; i++) { - char *value_1 = getHashEntry(setup_file_hash,"menu.left_spacing.INFO"); - char *value_2 = getHashEntry(setup_file_hash,"menu.right_spacing.INFO"); - char *value_3 = getHashEntry(setup_file_hash,"menu.top_spacing.INFO"); - char *value_4 = getHashEntry(setup_file_hash,"menu.bottom_spacing.INFO"); - char *value_5 = getHashEntry(setup_file_hash,"menu.paragraph_spacing.INFO"); - char *value_6 = getHashEntry(setup_file_hash,"menu.headline1_spacing.INFO"); - char *value_7 = getHashEntry(setup_file_hash,"menu.headline2_spacing.INFO"); - char *value_8 = getHashEntry(setup_file_hash,"menu.line_spacing.INFO"); - char *value_9 = getHashEntry(setup_file_hash,"menu.extra_spacing.INFO"); - - if (value_1 != NULL) - menu.left_spacing_info[i] = get_integer_from_string(value_1); - if (value_2 != NULL) - menu.right_spacing_info[i] = get_integer_from_string(value_2); - if (value_3 != NULL) - menu.top_spacing_info[i] = get_integer_from_string(value_3); - if (value_4 != NULL) - menu.bottom_spacing_info[i] = get_integer_from_string(value_4); - if (value_5 != NULL) - menu.paragraph_spacing_info[i] = get_integer_from_string(value_5); - if (value_6 != NULL) - menu.headline1_spacing_info[i] = get_integer_from_string(value_6); - if (value_7 != NULL) - menu.headline2_spacing_info[i] = get_integer_from_string(value_7); - if (value_8 != NULL) - menu.line_spacing_info[i] = get_integer_from_string(value_8); - if (value_9 != NULL) - menu.extra_spacing_info[i] = get_integer_from_string(value_9); + struct TokenIntPtrInfo menu_config[] = + { + { "menu.left_spacing.INFO", &menu.left_spacing_info[i] }, + { "menu.right_spacing.INFO", &menu.right_spacing_info[i] }, + { "menu.top_spacing.INFO", &menu.top_spacing_info[i] }, + { "menu.bottom_spacing.INFO", &menu.bottom_spacing_info[i] }, + { "menu.paragraph_spacing.INFO", &menu.paragraph_spacing_info[i] }, + { "menu.headline1_spacing.INFO", &menu.headline1_spacing_info[i] }, + { "menu.headline2_spacing.INFO", &menu.headline2_spacing_info[i] }, + { "menu.line_spacing.INFO", &menu.line_spacing_info[i] }, + { "menu.extra_spacing.INFO", &menu.extra_spacing_info[i] }, + }; + + for (j = 0; j < ARRAY_SIZE(menu_config); j++) + { + char *token = menu_config[j].token; + char *value = getHashEntry(setup_file_hash, token); + + if (value != NULL) + *menu_config[j].value = get_integer_from_string(value); + } } // special case: initialize with default values that may be overwritten // (eg, init "menu.enter_screen.SCORES.xyz" from "menu.enter_screen.xyz") for (i = 0; i < NUM_SPECIAL_GFX_ARGS; i++) { - char *token_1 = "menu.enter_screen.fade_mode"; - char *token_2 = "menu.enter_screen.fade_delay"; - char *token_3 = "menu.enter_screen.post_delay"; - char *token_4 = "menu.leave_screen.fade_mode"; - char *token_5 = "menu.leave_screen.fade_delay"; - char *token_6 = "menu.leave_screen.post_delay"; - char *token_7 = "menu.next_screen.fade_mode"; - char *token_8 = "menu.next_screen.fade_delay"; - char *token_9 = "menu.next_screen.post_delay"; - char *value_1 = getHashEntry(setup_file_hash, token_1); - char *value_2 = getHashEntry(setup_file_hash, token_2); - char *value_3 = getHashEntry(setup_file_hash, token_3); - char *value_4 = getHashEntry(setup_file_hash, token_4); - char *value_5 = getHashEntry(setup_file_hash, token_5); - char *value_6 = getHashEntry(setup_file_hash, token_6); - char *value_7 = getHashEntry(setup_file_hash, token_7); - char *value_8 = getHashEntry(setup_file_hash, token_8); - char *value_9 = getHashEntry(setup_file_hash, token_9); - - if (value_1 != NULL) - menu.enter_screen[i].fade_mode = get_token_parameter_value(token_1, - value_1); - if (value_2 != NULL) - menu.enter_screen[i].fade_delay = get_token_parameter_value(token_2, - value_2); - if (value_3 != NULL) - menu.enter_screen[i].post_delay = get_token_parameter_value(token_3, - value_3); - if (value_4 != NULL) - menu.leave_screen[i].fade_mode = get_token_parameter_value(token_4, - value_4); - if (value_5 != NULL) - menu.leave_screen[i].fade_delay = get_token_parameter_value(token_5, - value_5); - if (value_6 != NULL) - menu.leave_screen[i].post_delay = get_token_parameter_value(token_6, - value_6); - if (value_7 != NULL) - menu.next_screen[i].fade_mode = get_token_parameter_value(token_7, - value_7); - if (value_8 != NULL) - menu.next_screen[i].fade_delay = get_token_parameter_value(token_8, - value_8); - if (value_9 != NULL) - menu.next_screen[i].post_delay = get_token_parameter_value(token_9, - value_9); + struct TokenIntPtrInfo menu_config[] = + { + { "menu.enter_screen.fade_mode", &menu.enter_screen[i].fade_mode }, + { "menu.enter_screen.fade_delay", &menu.enter_screen[i].fade_delay }, + { "menu.enter_screen.post_delay", &menu.enter_screen[i].post_delay }, + { "menu.leave_screen.fade_mode", &menu.leave_screen[i].fade_mode }, + { "menu.leave_screen.fade_delay", &menu.leave_screen[i].fade_delay }, + { "menu.leave_screen.post_delay", &menu.leave_screen[i].post_delay }, + { "menu.next_screen.fade_mode", &menu.next_screen[i].fade_mode }, + { "menu.next_screen.fade_delay", &menu.next_screen[i].fade_delay }, + { "menu.next_screen.post_delay", &menu.next_screen[i].post_delay } + }; + + for (j = 0; j < ARRAY_SIZE(menu_config); j++) + { + char *token = menu_config[j].token; + char *value = getHashEntry(setup_file_hash, token); + + if (value != NULL) + *menu_config[j].value = get_token_parameter_value(token, value); + } } // special case: initialize with default values that may be overwritten // (eg, init "viewport.door_1.MAIN.xyz" from "viewport.door_1.xyz") for (i = 0; i < NUM_SPECIAL_GFX_ARGS; i++) { - char *token_w1 = "viewport.window.width"; - char *token_w2 = "viewport.window.height"; - char *token_01 = "viewport.playfield.x"; - char *token_02 = "viewport.playfield.y"; - char *token_03 = "viewport.playfield.width"; - char *token_04 = "viewport.playfield.height"; - char *token_05 = "viewport.playfield.border_size"; - char *token_06 = "viewport.door_1.x"; - char *token_07 = "viewport.door_1.y"; - char *token_08 = "viewport.door_1.width"; - char *token_09 = "viewport.door_1.height"; - char *token_10 = "viewport.door_1.border_size"; - char *token_11 = "viewport.door_2.x"; - char *token_12 = "viewport.door_2.y"; - char *token_13 = "viewport.door_2.width"; - char *token_14 = "viewport.door_2.height"; - char *token_15 = "viewport.door_2.border_size"; - char *value_w1 = getHashEntry(setup_file_hash, token_w1); - char *value_w2 = getHashEntry(setup_file_hash, token_w2); - char *value_01 = getHashEntry(setup_file_hash, token_01); - char *value_02 = getHashEntry(setup_file_hash, token_02); - char *value_03 = getHashEntry(setup_file_hash, token_03); - char *value_04 = getHashEntry(setup_file_hash, token_04); - char *value_05 = getHashEntry(setup_file_hash, token_05); - char *value_06 = getHashEntry(setup_file_hash, token_06); - char *value_07 = getHashEntry(setup_file_hash, token_07); - char *value_08 = getHashEntry(setup_file_hash, token_08); - char *value_09 = getHashEntry(setup_file_hash, token_09); - char *value_10 = getHashEntry(setup_file_hash, token_10); - char *value_11 = getHashEntry(setup_file_hash, token_11); - char *value_12 = getHashEntry(setup_file_hash, token_12); - char *value_13 = getHashEntry(setup_file_hash, token_13); - char *value_14 = getHashEntry(setup_file_hash, token_14); - char *value_15 = getHashEntry(setup_file_hash, token_15); - - if (value_w1 != NULL) - viewport.window[i].width = get_token_parameter_value(token_w1, value_w1); - if (value_w2 != NULL) - viewport.window[i].height = get_token_parameter_value(token_w2, value_w2); - if (value_01 != NULL) - viewport.playfield[i].x = get_token_parameter_value(token_01, value_01); - if (value_02 != NULL) - viewport.playfield[i].y = get_token_parameter_value(token_02, value_02); - if (value_03 != NULL) - viewport.playfield[i].width = get_token_parameter_value(token_03, - value_03); - if (value_04 != NULL) - viewport.playfield[i].height = get_token_parameter_value(token_04, - value_04); - if (value_05 != NULL) - viewport.playfield[i].border_size = get_token_parameter_value(token_05, - value_05); - if (value_06 != NULL) - viewport.door_1[i].x = get_token_parameter_value(token_06, value_06); - if (value_07 != NULL) - viewport.door_1[i].y = get_token_parameter_value(token_07, value_07); - if (value_08 != NULL) - viewport.door_1[i].width = get_token_parameter_value(token_08, value_08); - if (value_09 != NULL) - viewport.door_1[i].height = get_token_parameter_value(token_09, value_09); - if (value_10 != NULL) - viewport.door_1[i].border_size = get_token_parameter_value(token_10, - value_10); - if (value_11 != NULL) - viewport.door_2[i].x = get_token_parameter_value(token_11, value_11); - if (value_12 != NULL) - viewport.door_2[i].y = get_token_parameter_value(token_12, value_12); - if (value_13 != NULL) - viewport.door_2[i].width = get_token_parameter_value(token_13, value_13); - if (value_14 != NULL) - viewport.door_2[i].height = get_token_parameter_value(token_14, value_14); - if (value_15 != NULL) - viewport.door_1[i].border_size = get_token_parameter_value(token_15, - value_15); + struct + { + char *token_prefix; + struct RectWithBorder *struct_ptr; + } + vp_struct[] = + { + { "viewport.window", &viewport.window[i] }, + { "viewport.playfield", &viewport.playfield[i] }, + { "viewport.door_1", &viewport.door_1[i] }, + { "viewport.door_2", &viewport.door_2[i] } + }; + + for (j = 0; j < ARRAY_SIZE(vp_struct); j++) + { + struct TokenIntPtrInfo vp_config[] = + { + { ".x", &vp_struct[j].struct_ptr->x }, + { ".y", &vp_struct[j].struct_ptr->y }, + { ".width", &vp_struct[j].struct_ptr->width }, + { ".height", &vp_struct[j].struct_ptr->height }, + { ".min_width", &vp_struct[j].struct_ptr->min_width }, + { ".min_height", &vp_struct[j].struct_ptr->min_height }, + { ".max_width", &vp_struct[j].struct_ptr->max_width }, + { ".max_height", &vp_struct[j].struct_ptr->max_height }, + { ".margin_left", &vp_struct[j].struct_ptr->margin_left }, + { ".margin_right", &vp_struct[j].struct_ptr->margin_right }, + { ".margin_top", &vp_struct[j].struct_ptr->margin_top }, + { ".margin_bottom", &vp_struct[j].struct_ptr->margin_bottom }, + { ".border_left", &vp_struct[j].struct_ptr->border_left }, + { ".border_right", &vp_struct[j].struct_ptr->border_right }, + { ".border_top", &vp_struct[j].struct_ptr->border_top }, + { ".border_bottom", &vp_struct[j].struct_ptr->border_bottom }, + { ".border_size", &vp_struct[j].struct_ptr->border_size }, + { ".align_size", &vp_struct[j].struct_ptr->align_size }, + { ".align", &vp_struct[j].struct_ptr->align }, + { ".valign", &vp_struct[j].struct_ptr->valign } + }; + + for (k = 0; k < ARRAY_SIZE(vp_config); k++) + { + char *token = getStringCat2(vp_struct[j].token_prefix, + vp_config[k].token); + char *value = getHashEntry(setup_file_hash, token); + + if (value != NULL) + *vp_config[k].value = get_token_parameter_value(token, value); + + free(token); + } + } } // special case: initialize with default values that may be overwritten @@ -10275,6 +11352,25 @@ static void LoadMenuDesignSettingsFromFilename(char *filename) } } + // special case: check if network and preview player positions are redefined, + // to compare this later against the main menu level preview being redefined + struct TokenIntPtrInfo menu_config_players[] = + { + { "main.network_players.x", &menu.main.network_players.redefined }, + { "main.network_players.y", &menu.main.network_players.redefined }, + { "main.preview_players.x", &menu.main.preview_players.redefined }, + { "main.preview_players.y", &menu.main.preview_players.redefined }, + { "preview.x", &preview.redefined }, + { "preview.y", &preview.redefined } + }; + + for (i = 0; i < ARRAY_SIZE(menu_config_players); i++) + *menu_config_players[i].value = FALSE; + + for (i = 0; i < ARRAY_SIZE(menu_config_players); i++) + if (getHashEntry(setup_file_hash, menu_config_players[i].token) != NULL) + *menu_config_players[i].value = TRUE; + // read (and overwrite with) values that may be specified in config file for (i = 0; image_config_vars[i].token != NULL; i++) { @@ -10373,19 +11469,19 @@ void LoadUserDefinedEditorElementList(int **elements, int *num_elements) { if (num_unknown_tokens == 0) { - Error(ERR_INFO_LINE, "-"); - Error(ERR_INFO, "warning: unknown token(s) found in config file:"); - Error(ERR_INFO, "- config file: '%s'", filename); + Warn("---"); + Warn("unknown token(s) found in config file:"); + Warn("- config file: '%s'", filename); num_unknown_tokens++; } - Error(ERR_INFO, "- token: '%s'", list->token); + Warn("- token: '%s'", list->token); } } if (num_unknown_tokens > 0) - Error(ERR_INFO_LINE, "-"); + Warn("---"); while (*num_elements % 4) // pad with empty elements, if needed (*elements)[(*num_elements)++] = EL_EMPTY; @@ -10395,8 +11491,8 @@ void LoadUserDefinedEditorElementList(int **elements, int *num_elements) #if 0 for (i = 0; i < *num_elements; i++) - printf("editor: element '%s' [%d]\n", - element_info[(*elements)[i]].token_name, (*elements)[i]); + Debug("editor", "element '%s' [%d]\n", + element_info[(*elements)[i]].token_name, (*elements)[i]); #endif } @@ -10575,7 +11671,8 @@ void LoadMusicInfo(void) if ((dir = openDirectory(music_directory)) == NULL) { - Error(ERR_WARN, "cannot read music directory '%s'", music_directory); + Warn("cannot read music directory '%s'", music_directory); + return; } @@ -10663,18 +11760,18 @@ static void print_unknown_token(char *filename, char *token, int token_nr) { if (token_nr == 0) { - Error(ERR_INFO_LINE, "-"); - Error(ERR_INFO, "warning: unknown token(s) found in config file:"); - Error(ERR_INFO, "- config file: '%s'", filename); + Warn("---"); + Warn("unknown token(s) found in config file:"); + Warn("- config file: '%s'", filename); } - Error(ERR_INFO, "- token: '%s'", token); + Warn("- token: '%s'", token); } static void print_unknown_token_end(int token_nr) { if (token_nr > 0) - Error(ERR_INFO_LINE, "-"); + Warn("---"); } void LoadHelpAnimInfo(void) @@ -10878,12 +11975,12 @@ void LoadHelpAnimInfo(void) #if 0 for (i = 0; i < num_list_entries; i++) - printf("::: '%s': %d, %d, %d => %d\n", - EL_NAME(helpanim_info[i].element), - helpanim_info[i].element, - helpanim_info[i].action, - helpanim_info[i].direction, - helpanim_info[i].delay); + Debug("files:LoadHelpAnimInfo", "'%s': %d, %d, %d => %d", + EL_NAME(helpanim_info[i].element), + helpanim_info[i].element, + helpanim_info[i].action, + helpanim_info[i].direction, + helpanim_info[i].delay); #endif } @@ -10915,8 +12012,8 @@ void LoadHelpTextInfo(void) #if 0 BEGIN_HASH_ITERATION(helptext_info, itr) { - printf("::: '%s' => '%s'\n", - HASH_ITERATION_TOKEN(itr), HASH_ITERATION_VALUE(itr)); + Debug("files:LoadHelpTextInfo", "'%s' => '%s'", + HASH_ITERATION_TOKEN(itr), HASH_ITERATION_VALUE(itr)); } END_HASH_ITERATION(hash, itr) #endif @@ -10942,8 +12039,7 @@ void ConvertLevels(void) global.convert_leveldir); if (convert_leveldir == NULL) - Error(ERR_EXIT, "no such level identifier: '%s'", - global.convert_leveldir); + Fail("no such level identifier: '%s'", global.convert_leveldir); leveldir_current = convert_leveldir; @@ -11043,7 +12139,6 @@ void ConvertLevels(void) void CreateLevelSketchImages(void) { -#if defined(TARGET_SDL) Bitmap *bitmap1; Bitmap *bitmap2; int i; @@ -11055,51 +12150,57 @@ void CreateLevelSketchImages(void) for (i = 0; i < NUM_FILE_ELEMENTS; i++) { - Bitmap *src_bitmap; - int src_x, src_y; int element = getMappedElement(i); - int graphic = el2edimg(element); char basename1[16]; char basename2[16]; char *filename1; char *filename2; - sprintf(basename1, "%03d.bmp", i); - sprintf(basename2, "%03ds.bmp", i); + sprintf(basename1, "%04d.bmp", i); + sprintf(basename2, "%04ds.bmp", i); filename1 = getPath2(global.create_images_dir, basename1); filename2 = getPath2(global.create_images_dir, basename2); - getFixedGraphicSource(graphic, 0, &src_bitmap, &src_x, &src_y); - BlitBitmap(src_bitmap, bitmap1, src_x, src_y, TILEX, TILEY, - 0, 0); + DrawSizedElement(0, 0, element, TILESIZE); + BlitBitmap(drawto, bitmap1, SX, SY, TILEX, TILEY, 0, 0); if (SDL_SaveBMP(bitmap1->surface, filename1) != 0) - Error(ERR_EXIT, "cannot save level sketch image file '%s'", filename1); + Fail("cannot save level sketch image file '%s'", filename1); - getMiniGraphicSource(graphic, &src_bitmap, &src_x, &src_y); - BlitBitmap(src_bitmap, bitmap2, src_x, src_y, MINI_TILEX, MINI_TILEY, 0, 0); + DrawSizedElement(0, 0, element, MINI_TILESIZE); + BlitBitmap(drawto, bitmap2, SX, SY, MINI_TILEX, MINI_TILEY, 0, 0); if (SDL_SaveBMP(bitmap2->surface, filename2) != 0) - Error(ERR_EXIT, "cannot save level sketch image file '%s'", filename2); + Fail("cannot save level sketch image file '%s'", filename2); free(filename1); free(filename2); + // create corresponding SQL statements (for normal and small images) + if (i < 1000) + { + printf("insert into phpbb_words values (NULL, '`%03d', '');\n", i, i); + printf("insert into phpbb_words values (NULL, '¸%03d', '');\n", i, i); + } + + printf("insert into phpbb_words values (NULL, '`%04d', '');\n", i, i); + printf("insert into phpbb_words values (NULL, '¸%04d', '');\n", i, i); + + // optional: create content for forum level sketch demonstration post if (options.debug) - printf("%03d `%03d%c", i, i, (i % 10 < 9 ? ' ' : '\n')); + fprintf(stderr, "%03d `%03d%c", i, i, (i % 10 < 9 ? ' ' : '\n')); } FreeBitmap(bitmap1); FreeBitmap(bitmap2); if (options.debug) - printf("\n"); + fprintf(stderr, "\n"); - Error(ERR_INFO, "%d normal and small images created", NUM_FILE_ELEMENTS); + Info("%d normal and small images created", NUM_FILE_ELEMENTS); CloseAllAndExit(0); -#endif } @@ -11109,7 +12210,6 @@ void CreateLevelSketchImages(void) void CreateCustomElementImages(char *directory) { -#if defined(TARGET_SDL) char *src_basename = "RocksCE-template.ilbm"; char *dst_basename = "RocksCE.bmp"; char *src_filename = getPath2(directory, src_basename); @@ -11120,7 +12220,7 @@ void CreateCustomElementImages(char *directory) int yoffset_ge = (TILEY * NUM_CUSTOM_ELEMENTS / 16); int i; - SDLInitVideoDisplay(); + InitVideoDefaults(); ReCreateBitmap(&backbuffer, video.width, video.height); @@ -11196,10 +12296,9 @@ void CreateCustomElementImages(char *directory) } if (SDL_SaveBMP(bitmap->surface, dst_filename) != 0) - Error(ERR_EXIT, "cannot save CE graphics file '%s'", dst_filename); + Fail("cannot save CE graphics file '%s'", dst_filename); FreeBitmap(bitmap); CloseAllAndExit(0); -#endif }